pickleplayer Posted October 19, 2015 Share Posted October 19, 2015 So I've been messing around with stategraphs a lot, and in the Stategraph States, the timeline has TimeEvents that link code to frames in an animation Heres a quick example of a simple state with timeline events. This one is for the "Give" action, like when you give food or armor to a pigState{ name = "give", onenter = function(inst) inst.components.locomotor:Stop() inst.AnimState:PlayAnimation("give") end, timeline = { TimeEvent(13*FRAMES, function(inst) inst:PerformBufferedAction() end), }, events= { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ), }, }, And the timeline is pretty useful because it's like a DoTaskInTime that cancels itself if the animation is interrupted before that frame (frame 13 in the above example).And same with the "animover" event, except that's a hassle to change. So I've been using "inst.AnimState:Pause()" and "inst.AnimState:Resume()" to temporarily pause animations, and I assumed that it would also pause the TimeEvents. But it turns out that it doesn't pause the TimeEvents at all. They still happen during the frozen animation. Only the "animover" events are paused and resumed correctly. So I'm pretty aweful when it comes to timed events. I can't even figure out how to cancel a DoPeriodicTask. But is there anything I can do to pause and resume these stategraph timeevents on command? Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/ Share on other sites More sharing options...
Blueberrys Posted October 20, 2015 Share Posted October 20, 2015 (edited) So I'm pretty aweful when it comes to timed events. I can't even figure out how to cancel a DoPeriodicTask.I believe it's just:-- task is the instance of the periodic tasktask:Cancel() You can get the task instance when creating it:task = doer:DoPeriodicTask(...) Edited October 20, 2015 by Blueberrys Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-681547 Share on other sites More sharing options...
Mobbstar Posted October 20, 2015 Share Posted October 20, 2015 To add to what BB said, you can definitely get the TimeEvent in question by navigating through the stategraph (if you don't make a new state, in which case you should just assign a variable). By the way, the TimeEvent doesn't stop because it's essentially a TaskInTime, and FRAMES is 1/30 of a second (hardcoded I think, which would be bad practise). Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-681578 Share on other sites More sharing options...
pickleplayer Posted October 20, 2015 Author Share Posted October 20, 2015 I believe it's just:-- task is the instance of the periodic tasktask:Cancel() You can get the task instance when creating it:task = doer:DoPeriodicTask(...) Hm, I can't get it to work.. I think I'm understanding it wrong though, Am I doing it right?Is it supposed to look like this? (assuming I'm using it in a stategraph)TimeEvent(10*FRAMES, function(inst) inst.task = inst:DoPeriodicTask(0.1, function() if inst:HasTag("rolling") then --DO THE THING inst:DoTaskInTime(3, function(inst) inst.task:Cancel() end) end end)end),--ALSO CAN IT BE CANCELED FROM ANOTHER THREAD LIKE THIS IF I WANTED TO?TimeEvent(20*FRAMES, function(inst) --inst.task:Cancel()end),I've tried a bunch of other things too but couldn't get it to work.I'm probably setting it up wrong. I once got "inst:CancelAllPendingTasks()" to work. But it also canceled the task that resumes the animation, so that didn't help Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-681684 Share on other sites More sharing options...
pickleplayer Posted October 20, 2015 Author Share Posted October 20, 2015 To add to what BB said, you can definitely get the TimeEvent in question by navigating through the stategraph (if you don't make a new state, in which case you should just assign a variable). By the way, the TimeEvent doesn't stop because it's essentially a TaskInTime, and FRAMES is 1/30 of a second (hardcoded I think, which would be bad practise). They're all custom states. What do you mean I could assign it a variable? What is this? How is do things I can't.I wish there was more documentation on time events. Does anyone know any game files with a lot of time tasks that I could study? Theres a whole bunch of stuff in stategraphs.lua that I would love to try out, but have no idea how to apply them. This code looks like it might be able to freeze the current stategraphs, but I have no idea how to use itfunction StateGraphWrangler:Hibernate(inst) if self.instances[inst] then self:SendToList(inst, self.hibernaters) endendfunction StateGraphWrangler:Wake(inst) if self.instances[inst] then self:SendToList(inst, self.updaters) endendfunction StateGraphWrangler:Sleep(inst, time_to_wait) if self.instances[inst] then local sleep_ticks = time_to_wait/GetTickTime() if sleep_ticks == 0 then sleep_ticks = 1 end local target_tick = math.floor(GetTick() + sleep_ticks) + 1 local waiters = self.tickwaiters[target_tick] if not waiters then waiters = {} self.tickwaiters[target_tick] = waiters end self:SendToList(inst, waiters) endend Is there a way to pause all tasks at once?I know how to kill all tasks, but I want to be able to resume them later Wait, no I guess I wouldnt want all tasks paused, because the function the resumes the tasks is also a TaskInTime. um. Also, I think FRAMES is actually 1/60. For the longest time, I thought it was all 24 fps, until just recently I tested something out in stategraphs to see how many frames it prints out in 1 second and now I'm pretty sure it's 60 Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-681685 Share on other sites More sharing options...
Blueberrys Posted October 21, 2015 Share Posted October 21, 2015 (edited) @pickleplayer I think the problem is with your references.TimeEvent(10*FRAMES, function(inst) -- Let's call this "inst" variable here "inst_1" inst.task = inst:DoPeriodicTask(0.1, function() if inst:HasTag("rolling") then --DO THE THING -- Inside the function below, a *new* inst variable is received as a -- parameter, lets call it "inst_2" inst:DoTaskInTime(3, function(inst) -- If "inst_2" is not the SAME instance as "inst_1" -- (or at least has the same data), -- you won't have the task stored at inst_2.task inst.task:Cancel() end) end end) end), TimeEvent(20*FRAMES, function(inst) -- If the "inst" here is the same instance as "inst_1", then yes. -- But this function also has "inst" as a parameter. --inst.task:Cancel()end),To fix that, you could just change the name of the parameters so they don't interfere.inst:DoTaskInTime(3, function(inst_2)-- ...end)- Edit: Also, check out scheduler.lua Edited October 21, 2015 by Blueberrys Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-681721 Share on other sites More sharing options...
pickleplayer Posted October 21, 2015 Author Share Posted October 21, 2015 @pickleplayer I think the problem is with your references.To fix that, you could just change the name of the parameters so they don't interfere.inst:DoTaskInTime(3, function(inst_2)-- ...end)- Edit: Also, check out scheduler.lua oh, just typed up a whole response before realizing the previous code actually DID work, and I had forgotten to disable the workaround I was using, so I didn't realize the task had been canceled. woops. Anyways, Thanks! so now I know how to cancel time tasks, but is there a way to pause them? I've already combed through scheduler.lua, but I don't see anything that looks like it will work. There is a Sleep() function, but it's marked under "These are to be called from within a thread", And I was hoping to be able to pause them from elsewhere Can the Stategraph time events even be paused? I tried to do something similar with them like the dopriodictask, but it just crashes. Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-681796 Share on other sites More sharing options...
pickleplayer Posted October 25, 2015 Author Share Posted October 25, 2015 Aww, well I am very dissapointed. I finally managed to apply the stategraph wrangler functions from stategraph.lua in my code, only to find out they don't work the way I was hoping they would.I added this to the modmain (because I was having problems editing the file directly)AddGlobalClassPostConstruct("entityscript", "EntityScript", function(self) function self:FreezeStateGraph() if self.sg then GLOBAL.SGManager:Sleep(self.sg, 8*(1/30)) end end function self:PauseStateGraph() if self.sg then GLOBAL.SGManager:Hibernate(self.sg) end end function self:UnPauseStateGraph() if self.sg then GLOBAL.SGManager:Wake(self.sg) end endend)I tried two methods, the "sleep" method, and the "hibernate/wake" method. (Although they both worked exactly the same way) Upon hibernating the stategraphs, it succesfully stopped the TimeEvents from happening while in hibernation. But as soon as it came out of hibernation, all of the time events that would have gone off during its hibernation just all went off at once, and it resumed as if no pause ever happened. Guess I'll have to try something else. I'm looking at update.lua next because theres this important looking code snippet in the main update functionfor i = last_tick_seen + 1, tick do TheSim:ProfilerPush("LuaSG") SGManager:Update(i) TheSim:ProfilerPop() TheSim:ProfilerPush("LuaBrain") BrainManager:Update(i) TheSim:ProfilerPop() endlines 2 and 3 specifically are what I want to mess with, IF I can figure out how to actually edit it. also, where is the source of this "TheSim" class?? I can't actually find it in the game files, and it's not simutil.lua (also, oops, it is in 30 fps, my bad mobbsar) Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-682456 Share on other sites More sharing options...
Mobbstar Posted October 25, 2015 Share Posted October 25, 2015 TheSim is constructed in C++, I think, just like AnimState, Transform, etc. Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-682458 Share on other sites More sharing options...
pickleplayer Posted October 25, 2015 Author Share Posted October 25, 2015 TheSim is constructed in C++, I think, just like AnimState, Transform, etc. Does that mean it isn't in the game files at all? Is there maybe some documentation of the content of those classes? Like the global functions on pastebin? http://pastebin.com/D4c4SRaD Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-682540 Share on other sites More sharing options...
pickleplayer Posted December 22, 2015 Author Share Posted December 22, 2015 I DID IToh my god. I actually fixed hitlag. Even though I doubt anyone else will ever need to know how to do this, I'm going to leave this here anyways because you never know if anyone down the road will want to know how to pause a stategraph time event for their mod. Okay so my old broken method was some rediculously over-complicated system changing how update.lua worked so that stategraphs were updated on a seperate timeline from the rest of the game that was x frames slower, where x was the number of hitlag frames, and once a state was over, it would catch up to the real game time to prevent future state events from happening x frames slower than they should.And it actually kind of worked at first. Except that SGmanager applies to ALL states, and for BOTH players, so if one player changed states after being hit while the other was still in their attack animation, it would mess up their timeline and they would be frozen in that state permanently. SO I cut all that out finally figured out a way to freeze individual stategraphs from anywhere. at the end of hitlag, I made this function that adjusts the state's current time so that it's exactly where it left off when the hitlag started.if self.inst.sg then --PROJECTILES DON'T HAVE STATEGRAPHS SO THINGS GET WEIRD IF YOU TRY TO UPDATE THEM self.inst.sg.timeinstate = self.inst.sg.timeinstate - ((self.hitlag-3)*FRAMES) -- -3 FOR THE 3 FRAME STARTUP DELAYend(it's strange how some stategraph variables are measured in frames and some are measured in seconds) and then to prevent any TimeEvents from going off during the duration of hitlag before the timeinstate was reset, I added these two entityscript functionsAddGlobalClassPostConstruct("entityscript", "EntityScript", function(self) function self:PauseStateGraph() if self.sg then GLOBAL.SGManager:Hibernate(self.sg) end end function self:UnPauseStateGraph() if self.sg then GLOBAL.SGManager:Wake(self.sg) end endend)Which are called at the beginning and end of hitlag respectively.self.inst:PauseStateGraph()--AND THEN LATER ONself.inst:UnPauseStateGraph() They were added through the modmain because for some reason, any changes applied to major game files like entityscript.lua don't take effect at all. So there you go. And it only took me a few months. Link to comment https://forums.kleientertainment.com/forums/topic/58597-pausing-a-stategraph-time-event/#findComment-700828 Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now