The_Real_Al Posted September 28, 2013 Share Posted September 28, 2013 How could i execute a second chunk a set amount of time after the first one.As in: execute 1st chunk --> wait five seconds --> continue with 2nd chunk. Me thinks one way to go is to set a counter for an 'OnTick' or 'OnPlayerUpdate' event but both are a drag on performance. Link to comment Share on other sites More sharing options...
Stormy Posted September 28, 2013 Share Posted September 28, 2013 Just to be clear: when you add your function to OnTick it causes a drag in performance or you are worried that it will cause a drag in performance? I'm not an expert but I've been under the impression that all games operate in a continual loop; doing the draw each 'tick', doing the logic, checking for button presses etc. If this is the case, presumably using an if control statement minimises the overhead, and whatever you are doing is presumably negligible next to LoS, AI, world drawing. I assumed the onTick was a way of hooking into the natural loop of the game. My question would be after I've added something to the OnTick, can I remove it (like removing listeners or observers). Link to comment Share on other sites More sharing options...
Stormy Posted September 29, 2013 Share Posted September 29, 2013 EDIT: Answered my own question. Add a function to OnTick that executes functions in a table and checks first if the table is empty and doesn't do anything if it is. Add your desired function to that table and have it remove itself from the table once executed. Here is a short program that shows it working:print('Start')timesExecuted = 0onTickTable = {}local newFunction = function() print(timesExecuted) if(timesExecuted > 5) then return timesExecuted else return nil end endonTickTable[1] = newFunctionlocal checkTickTable = function() local removeIndex = 1 local functionToRemove = {} for i,method in ipairs(onTickTable) do if method ~= nil then local temp = method() if temp == nil then print('fail') else print('success') functionToRemove[removeIndex] = i removeIndex = removeIndex + 1 endend end for i=1, removeIndex-1 do onTickTable[functionToRemove[i]] = nil endend-- Mock OnTick functionwhile(timesExecuted < 10) do local temp = checkTickTable() -- Add this to OnTick timesExecuted = timesExecuted + 1endprint('Finish')Output: Start0fail1fail2fail3fail4fail5fail6successFinish After 6 is printed, the function is removed from the table and never executes again. Therefore no fear of overhead. The only overhead you have now comes from the checkTicksTable which effectively does nothing because the table is empty. Because of the way Lua uses nil to determine whether the end of an array has been met I'm not sure if this works if onTickTable look like {function1, function2, nil, function3}. But still, with only one function, you should be fine. In your function you'd be checking that the current ticks value is greater than 5secs + the ticks value at the time the function was created. This may take a little more work passing value around but I'm fairly sure it's all possible. The_Real_Al 1 Link to comment Share on other sites More sharing options...
Ontogenesis Posted September 29, 2013 Share Posted September 29, 2013 Lua has no wait function.Although, question about the above - if you're using ticks isn't that depend on the speed of the computer, rather than real time? Or would that actually be an advantage? Link to comment Share on other sites More sharing options...
RoboMat Posted September 29, 2013 Share Posted September 29, 2013 Is Khalua capable of coroutines? http://www.lua.org/pil/9.html I have no clue. Stormy's suggestion looks nice and that's how I probably would try to handle it. Lua has no wait function.Although, question about the above - if you're using ticks isn't that depend on the speed of the computer, rather than real time? Or would that actually be an advantage? I asked myself the same question a few days / weeks ago and found that this thread explains it pretty well:http://www.java-gaming.org/index.php?topic=25361.0and linked from the above, this one:http://www.java-gaming.org/topics/game-loops/24220/view.html Link to comment Share on other sites More sharing options...
The_Real_Al Posted September 29, 2013 Author Share Posted September 29, 2013 What does that mean: 'lua has no wait function'?. Punk! Lua, that is.Loss of performance is a mere hunch. I had two or three 'OnTick' Events firing and some stutter when moving. Something i don't seem to have with vanilla but nothing i can definitely pin on the events. Here is a short program that shows it workingThanks a lot. That will take time for me to compute. Self-delete doesn't sound like it's fit for re-occuring functions, right? and linked from the above, this oneLol, the first example looks strangely familiar to something i tried. The one he calls 'Bad Bad Bad'. Link to comment Share on other sites More sharing options...
Stormy Posted September 30, 2013 Share Posted September 30, 2013 Thanks a lot. That will take time for me to compute. Self-delete doesn't sound like it's fit for re-occuring functions, right? Depends what you mean by reoccurring. The method I proposed would be best suited to a strength potion for example. After x amount of time stop performing the function. But you could drink potions again. Adding the function to the table again and then removing it after x has passed. If you mean that the function always needs to keep doing something provided a condition is metthen adding something to OnTick where you check a condition first should be sufficient to avoid the overhead. For example, reloading is in the OnTick method. It constantly checks for r being pressed If r is pressed then it checks for ammo. That check for ammo involves looping through every item in the inventory (for semi-auto weapons anyway). I've never noticed a performance loss on it. The one thing I implemented that caused a massive overhead was a very nasty recursive loop when I did explosions a while back. Link to comment Share on other sites More sharing options...
RoboMat Posted September 30, 2013 Share Posted September 30, 2013 You could also use OnPlayerUpdate if you fear the OnTick event. I think it fires not as often as the OnTick event. Link to comment Share on other sites More sharing options...
The_Real_Al Posted September 30, 2013 Author Share Posted September 30, 2013 The method I proposed would be best suited to a strength potion for example. After x amount of time stop performing the function. But you could drink potions again. Adding the function to the table again and then removing it after x has passed. Forgive my ignorance but this hellish program of yours could also be written in mayan for all that i understand of it.But i believe that should do. To give this some context:I want to simulate a dialog between two zombies. Right now it will fire both 'Say()' at the same time.I'd like it to be 1st 'zombie:Say("Text")' --> wait until the line has faded out --> 2nd 'zombie:Say("Text"). So basically as you said, measure the ticks it takes for the 'Say()'-texture to fade and then insert a loop into your program that counts them down before executing the second 'Say()' command. Come to think about it, it should be possible to set the non-existence of this texture as an object as the condition for the loop to stop. Link to comment Share on other sites More sharing options...
EnigmaGrey Posted September 30, 2013 Share Posted September 30, 2013 Probably want to avoid a while loop, particularly if you're calling the function OnTick, as it might cause hang ups until that function is complete. Link to comment Share on other sites More sharing options...
Stormy Posted October 1, 2013 Share Posted October 1, 2013 Yeah loops won't work... For what we're talking about here we could do some sort of scheduler... The original program could be adapted. EDIT: See below. Link to comment Share on other sites More sharing options...
Stormy Posted October 1, 2013 Share Posted October 1, 2013 Okay so here's a little program I've tested in zomboid: http://www.mediafire.com/download/lk48iyy5e178fhg/Scheduler.zip Essentially, the effects can largely be summed up from the temp.lua and you don't really need to pay much attention to the other two classes. The code there is as follows:local checkFunction = function(ticksAtCreation, ticks) print("ticksAtCreation"..ticksAtCreation) print("ticks"..ticks) return ticks - ticksAtCreation> 5endlocal performFunction = function() print("Action performed")endlocal postFunction = function() return nilendlocal newEvent = ScheduledEvent:new(ticks, checkFunction, performFunction, postFunction)EventManager.onTickTable[1] = newEventI create three local variables that each hold a function. The check function should return a boolean. It checks the conditions at any given moment and returns true or false. For example, in the above example it checks if 5 ticks have passed (this is a very short amount of time). The ScheduledEventManager is forced to pass those exact parameters to that function. However, if you could access a global variable (like the in-game date, or the player) you could have any type of condition here (e.g. the player has an item in their inventory or a certain date has been reached). The performFunction is the action that is performed when the condition is met. In this case, it just prints out to the console. The postFunction should return the next ScheduledEvent that you want to execute. After the performFunction executes, the postFunction is called and the value it returns replaces the 1 index in the onTickTable. A ScheduledEvent takes those functions in its constructor. So if you want a new function to execute after the current one you'd write three more functions, add them to a ScheduledEvent, have the postFunction of the first one return that object. If you don't want any more to execute, do as I do and return nil. The last step is adding the ScheduledEvent we wish to execute first to the EventManager's onTickTable. I've left some debug statements in there for assistance. RegularX 1 Link to comment Share on other sites More sharing options...
Stormy Posted October 2, 2013 Share Posted October 2, 2013 I should point out that there is one major thing missing from this implementation. I haven't been bothered to look into this properly but the table in Lua is not an ideal collection. When a table is looped over the nil element identifies the end of the table. With a table consisting of {1, 2, nil, 3, 4} the loop ends when it hits the nil and doesn't go to elements 3, 4. Ideally the implementation above needs two things: 1. The ability to append an item to the end of the collection. Instead of calling EventManager.onTickTable[1] = newEvent, I should be calling an EventManager.addEvent(newEvent) which adds it on to the end of a table. A table resembling {event1, event2} before calling the method should look like {event1, event2, newEvent} afterwards. 2. To be able to remove items from the table and shuffle everything to the left when it happens. So when event2 executes, it is removed from the table and the table looks like: {event1, newEvent} rather than {event1, nil, newEvent}. I would have tried to do it but for some reason I couldn't define a function properly... I tried adding something like this: function ScheduledEventManager:append(newEvent) self.onTickTable[nextAvailableIndex]end but I was getting an error to do with the reference to self. I think I've dome something wrong with meta table. Maybe RJ or RoboMat can see it. Its probably really obvious. Essentially, because of these limitations, you can only have 1 series of scheduled events operating at a time. Oh well. Link to comment Share on other sites More sharing options...
The_Real_Al Posted October 4, 2013 Author Share Posted October 4, 2013 That ...is ...magnificent. When a table is looped over the nil element identifies the end of the table The program already loops over the events in the metatable, couldn't a 'table.remove' for all nil entries just do the trick? Like this:for i,event in ipairs(o.onTickTable) do if event == nil then table.remove(o.onTickTable[i]) else if event.condition(event.ticksAtCreation, ticks) then event.performAction() o.onTickTable[1] = event.postAction() end end end Oh and the boys would like to have a word: benw 1 Link to comment Share on other sites More sharing options...
Stormy Posted October 4, 2013 Share Posted October 4, 2013 I'm going to bundle this up into an object, but this will do nicely: local size = 0local table = {}function add(value) if(value ~= nil) then table[size+1] = value size = size + 1 endendfunction remove(index) if((index ~= nil) and (index < size) and (index > 0)) then for i=index, size do if(i+1 > size) then table[i] = nil else table[i] = table[i+1] end end size = size - 1 elseif(index == size) then table[index] = nil size = size - 1 endend Link to comment Share on other sites More sharing options...
Stormy Posted October 4, 2013 Share Posted October 4, 2013 Oh and the boys would like to have a word: Tell them they're welcome. Link to comment Share on other sites More sharing options...
Cl0nec0mmand0 Posted October 4, 2013 Share Posted October 4, 2013 Oh and the boys would like to have a word: thats funny is there a way you can make that as mod with a lot of conversations? Link to comment Share on other sites More sharing options...
The_Real_Al Posted October 6, 2013 Author Share Posted October 6, 2013 That's a definite possibility. Right now i'm wrestling with some issues on how to pick them talkers. Doesn't make sense to have one zombie answering to another across the screen. Link to comment 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