Jump to content

Predicting Giant Attack

Recommended Posts

So in combination with my characters ability to predict hound attacks, I want to have him also capable of predicting the attack of Deerclops and brethren.


However, the basehassler.lua doesn't have a public function I can use to get the _timetoattack that I would need.


I know there's still a way I can get this information cleanly without having to edit basehassler, but I can't put my finger on what I need to do.


I usually test script in Console before I add it to scripts, but I'm not sure how I could check here.


At an rate, I'm essentially trying to get access to the private member variables of basehassler to use in a giant prediction perk for my character.

Link to comment
Share on other sites

I thought that they did hear the Deerclops coming, emoting something like "That sounds big." 

Is that not currently happening in RoG test? Or am I even remembering it right that it happened at all?

OH WELL, if it doesn't happen, it certainly should be able to.

Link to comment
Share on other sites

I thought that they did hear the Deerclops coming, emoting something like "That sounds big."

It does.


And I remember Wigfrid saying "A worthy foe approaches" with the Dragonfly too. So there should be something for the other giants. Maybe one of the pro modders can come here and give some help....

Link to comment
Share on other sites

If you really, really, REALLY, REALLY, AND SUPER REALLY.

And really, really, I say really.

Want to use that.


AddComponentPostInit("basehassler", function(self)	local old = self.OnUpdate	local _counter = 120	function self:OnUpdate(dt)		old(self, dt)		_counter = _counter - dt		if _counter < 0 then			dont, seriously = GLOBAL.debug.getupvalue(old, 1)			for k, v in pairs(GLOBAL.AllPlayers) do				if seriously then					v:PushEvent("plsno", {timeleft = seriously})				end			end			_counter = 120		end	endend)AddPlayerPostInit(function(inst)	inst:ListenForEvent("plsno", function(inst, data)		local daysleft = data.timeleft / 480		inst.components.talker:Say("Please, dont do this, but Clops comes in "..daysleft.." days")	end)end)


Here I give an example. An abomination.


When the dormant state stops, the timetoattack clock will tick and basehassler will update.

When timetoattack reaches 0, the deerclops growls will start.


Use with caution.

Link to comment
Share on other sites


Well that's fine, it's not really high priority and I could gladly wait for it to become more moddable, I mostly want to figure out what resource and methods I have available.  But I have once particular question.


Are you trying to portray some kind of message to me?  As if I'm about to open a pandora's box?


Either way, I can't help but laugh when looking at the names of things.




Yep, debug.getupvalue will get you to a local. As @DarkXero stated, It's inadvisable - its very likely to break and would be highly incompatible with other mods if they chose to override things that are properly exposed.


Mostly interested in the learning experience here, are you saying that I shouldn't CHANGE any of the local values here?  or is it just dangerous to DO ANYTHING with the local values here?  Because I essentially only want VIEW the information without making adjustments.


I'll tear something apart all the way to binary if I have too, I want to know as much as I can with the tools I'm using.  Especially so I can know WHY something would prove problematic.


Edit: I think I managed to figure out the issue's that would come up (Albeit I opened pandora's box and destroyed an entire dimension, nothing major obviously), I'll probably just end up waiting until it becomes more moddable, such as when it gets a function similar to hounded:GetTimeToAttack() which simply hands me the variable I'm looking for, as opposed to a method that's almost as unsafe as directly changing basehassler.lua itself.



Edit 2: My curiousity has peaked, what exactly is GLOBAL.debug.getupvalue doing?  Because through my test code I have a theory, so let me know if I got this right.


I decided based off of your example to make a different change.

AddComponentPostInit("basehassler", function(self)    local old = self.GetDebugString    function self:GetDebugString(debugstr)		if debugstr == "test1" then			return GLOBAL.debug.getupvalue(old, 1)		end		if debugstr == "test2" then			return GLOBAL.debug.getupvalue(old, 2)		end		if debugstr == "test3" then			return GLOBAL.debug.getupvalue(old, 3)		end		if debugstr == "test4" then			return GLOBAL.debug.getupvalue(old, 4)		end		if debugstr == "test5" then			return GLOBAL.debug.getupvalue(old, 5)		end		if debugstr == "test6" then			return GLOBAL.debug.getupvalue(old, 6)		end		if debugstr == "test7" then			return GLOBAL.debug.getupvalue(old, 7)		end		return old() --This didn't work, oh well no ones using it.    endend)

Using this I could test out your example in console by doing


And I would get 

_timetoattack        1589.959435... blah blah the number I need


I could also do test 2-4, with those I got




Then test5 came up nil.


SO to make sense of things I looked at the function self:GetDebugString() that I made changes to

I noticed that the local variables that got used in that function, were used in the order


1.  _timetoattack

2. _warning

3. _activehassler

4. _storedhassler


So I theorize that GLOBAL.debug.getupvalue(old, #) gives me the #th variable that was used in that function, I went back to OnUpdate and noticed that the first variable that ever gets used is



Which I bet that if I were to have changed GLOBAL.debug.getupvalue(old, 1) to GLOBAL.debug.getupvalue(old, 2) in your example DarkXero, I would get _activehassler instead since that is the second used variable in that function, with 3 being _warning and etc...

Am I on the right track teach?


So basically your warnings are basically trying to inform me that if I use code utilizing this method, if these functions ever get changed and move the order of their variables around, then my code will break immediately.  Which makes absolute sense in this whole regard of how debug.getupvalue() appears to work.



Now theories aside, what is debug.getupvalue doing?  and furthermore, what type of variable is my print() showing me?  and lastly, what am I capable of doing with what I'm getting?


Edit 3: Also as a side question, the old basehassler:GetDebugString() normally returns a string after giving it no arguements so I wanted to see if I could make GetDebugString do what it normally does if I don't put in a string, but it gives me an error saying self is nil.  What did I do wrong at the end there, how could I fix it?  Again, learning experience so I can understand how to use AddComponentPostInit better.


Edit 4: This thing where we store the old function before we replace it with a new one that references the old one so that it still functions like the old one on top of the new one.  Is there a name for it?  A terminology?  

Cause calling it a "That thing where we store the old function before we replace it with a new one that references the old one so that it still functions like the old one while also doing what we want in the new one but done in a way so that other mods don't conflict because they can all do this exact thing infinitely because the new one then BECOMES the old one which then newer ones do the same thing treating this one like the old one but it's actually a modified version of the old one which might have also been modded by other ones as well" is a bit of a mouthful.


If it doesn't have a name, then I shall abbreviate it to Ttwwstofbwriwanotrtoostisfltoowadwwwitnobdiawstomdcbtcadtetibtnotbtoowtnodtstttoltoobiaamvotoowmhabmbooaw for short.


Edit 5: Wait did I post this in general discussion?  I thought I posted this in Mods and Tools?  What is this madness?

Edited by Zackreaver
Link to comment
Share on other sites

You can combat the movement of upvalues inside a function.

debug = GLOBAL.debuglocal t = debug.getinfo(func)local name, value = 0, 0for i = 1, t.nups, 1 do   name, value = debug.getupvalue(func, i)   if name == "_timetoattack" then      break   end   value = nilendif value == nil then   -- nothing foundelse   -- _timetoattack upvalueend

But you shouldn't be combatting a function: debugging is for what the name says, debugging.


Upvalues: http://www.lua.org/pil/27.3.3.html


Lua 5.1 library (debug): http://www.lua.org/manual/5.1/manual.html#5.9

This is the one for Klei. You can print this one if in modmain you do:

for k, v in pairs(GLOBAL.debug) do   print(k, v)end


Lua versions here: http://www.lua.org/versions.html



-- Your old didn't work because you havefunction self:GetDebugString()-- that equates intofunction self.GetDebugString(self)-- so, the correct way isreturn old(self)

Link to comment
Share on other sites

@DarkXero,let me just say that I envy your ability to break everything down so nice and tidy.


As you can clearly see I have a major issue with trying to keep things short and sweet.




But you shouldn't be combatting a function: debugging is for what the name says, debugging.

I get what your saying, I don't intend to have my code running with a paper mache foundation.  I'll just use whatever I can with caution comments to erase sections that go out of date and correct it later when better code becomes available.


But if I can manage to get something working and little damage is caused to everything else, then I'll do it for as long as it's possible.


Edit: Okay I finally have it all figured out, the funny thing is I'm not even gonna use this code yet anyway since it's for a separate item I'm gonna make down the line so by the time I actually finish it hassler might get an update.


However, the knowledge of things I'm capable of doing is always the most valuable thing here.  I feel I understand LUA a little bit better everytime you two come to help me.

Edited by Zackreaver
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Create New...