on_nth_tick but with an offset, and "on_tick_n"

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
Post Reply
Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

on_nth_tick but with an offset, and "on_tick_n"

Post by Honktown »

On nth tick is kinda useful for me, but I was hoping for a "modulo+offset" effect. For certain cases, I would like to run a function every n ticks from now. Edit: (bootstrap vs event, still relevant)

There's also not an event I see which specifies a function be ran once on a certain tick. It would be some syntactic sugar for defining an event to run every n ticks, the function being ran on the first tick recognized, and then de-registering the event. To be particular, the tick on which I'd like to plan a future event is unknown, and I may not need to at all, so I can't do anything in advance.
I have mods! I guess!
Link

PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: on_nth_tick but with an offset, and "on_tick_n"

Post by PyroFire »

Honktown wrote:
Wed Dec 11, 2019 12:40 am
On nth tick is kinda useful for me, but I was hoping for a "modulo+offset" effect. For certain cases, I would like to run a function every n ticks from now. Edit: (bootstrap vs event, still relevant)
on_tick(tick) if(tick%n==offset)then ... end end
Honktown wrote:
Wed Dec 11, 2019 12:40 am
There's also not an event I see which specifies a function be ran once on a certain tick. It would be some syntactic sugar for defining an event to run every n ticks, the function being ran on the first tick recognized, and then de-registering the event. To be particular, the tick on which I'd like to plan a future event is unknown, and I may not need to at all, so I can't do anything in advance.
With enough math you can almost calculate anything in advance.

on_nth_tick(tick+5) dostuff() script.on_nth_tick(tick+5) end (so recreate an on_nth_tick inside your nth_tick)


I don't really understand what the issue you're describing is -- there is no issue here, you just need more math ?

Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: on_nth_tick but with an offset, and "on_tick_n"

Post by Honktown »

PyroFire wrote:
Wed Dec 11, 2019 1:41 am
Honktown wrote:
Wed Dec 11, 2019 12:40 am
On nth tick is kinda useful for me, but I was hoping for a "modulo+offset" effect. For certain cases, I would like to run a function every n ticks from now. Edit: (bootstrap vs event, still relevant)
on_tick(tick) if(tick%n==offset)then ... end end
Honktown wrote:
Wed Dec 11, 2019 12:40 am
There's also not an event I see which specifies a function be ran once on a certain tick. It would be some syntactic sugar for defining an event to run every n ticks, the function being ran on the first tick recognized, and then de-registering the event. To be particular, the tick on which I'd like to plan a future event is unknown, and I may not need to at all, so I can't do anything in advance.
With enough math you can almost calculate anything in advance.

on_nth_tick(tick+5) dostuff() script.on_nth_tick(tick+5) end (so recreate an on_nth_tick inside your nth_tick)


I don't really understand what the issue you're describing is -- there is no issue here, you just need more math ?
Hey it's you! It's related to Delayed Regeneration. I can't know in advance if an enemy took damage. If I had an on_nth_tick that could be offset, I could register every enemy that took damage, and each registration could manage taking care of itself and removing the enemy at the end of regeneration. It'd allow every enemy to heal on its own schedule, and each healing event to be individualized completely (excepting some minor data storage on the Lua side).

If I want to absolutely minimize the Lua overhead, I should be able to schedule things in a general way. Factorio currently does not have a "full" tick-oriented scheduler on the C++ side.
I have mods! I guess!
Link

Solinya
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sun Mar 17, 2019 10:39 pm
Contact:

Re: on_nth_tick but with an offset, and "on_tick_n"

Post by Solinya »

You could, but I don't know if you need to. I have a regeneration feature in one of my mods and if you just batch them all every 5-15 ticks (for aggressive regen) or 30-60 (for slower regen), it should be "good enough". I don't think most players will notice biters individually regenerating a handful of ticks apart.

I could still see a use for "on_nth_tick after this preset offset" - especially for time triggered events. I currently work around this by just looking at game.ticks_played and using a global to track the desired start tick every tick or nth tick. It would save me from making that check, but I don't know if the perf difference is enough for it to matter.

on_tick_n would be useful for timer based events. Again, could work around it by checking against game.ticks_played, but then you're making that check every tick (or every n ticks) for the rest of the game for what's intended as a one-off time-based event trigger. (Unless there's a way for us to subscribe/unsubscribe our event handlers at runtime?)

Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: on_nth_tick but with an offset, and "on_tick_n"

Post by Honktown »

Solinya wrote:
Wed Dec 11, 2019 3:54 am
You could, but I don't know if you need to. I have a regeneration feature in one of my mods and if you just batch them all every 5-15 ticks (for aggressive regen) or 30-60 (for slower regen), it should be "good enough". I don't think most players will notice biters individually regenerating a handful of ticks apart.

I could still see a use for "on_nth_tick after this preset offset" - especially for time triggered events. I currently work around this by just looking at game.ticks_played and using a global to track the desired start tick every tick or nth tick. It would save me from making that check, but I don't know if the perf difference is enough for it to matter.

on_tick_n would be useful for timer based events. Again, could work around it by checking against game.ticks_played, but then you're making that check every tick (or every n ticks) for the rest of the game for what's intended as a one-off time-based event trigger. (Unless there's a way for us to subscribe/unsubscribe our event handlers at runtime?)
I agree there's not much of a difference in performance per-se, but part of my reasoning is the conceptual model I'm working with and other people may expect. As a general programming rule, the more 1:1 you can make your conceptual model with the behavior, the easier it is to deal with (behavior, bugs, extension, refactoring). A way to reduce checking every tick is to use a decreasing-intensity like sleeping/busy-waiting: use a slow checker until you get near the time required, then use the checker that's worse performance wise. I did mention for a one-off timer, you can do on_nth_tick. Unlike on_init and on_load, testing suggests you can have multiple on_nth_tick functions in a single mod. May be a bug.

Edit: the bootstrap API page hints that on_nth_tick can have multiple functions, but it's not explicit:

Code: Select all

on_nth_tick(tick, f)
Register a handler to run every nth tick(s). When the game is on tick 0 it will trigger all registered handlers.

Parameters
tick :: uint or array of uint: The nth-tick(s) to invoke the handler on. Passing nil as the only parameter will unregister all nth-tick handlers.
f :: function(NthTickEvent): The handler to run. Passing nil will unregister the handler for the provided ticks.
"all registered handlers" could mean for all mods, all functions, etc. Apparent if you assume they're doing if tick % nth_tick {}.

"Passing nil will unregister the handler for the provided ticks." Does each nth-tick have it's own single function? This is a reasonable assumption to make, given that the call doesn't say it returns an ID you can use to de-register the handle later.
I have mods! I guess!
Link

Post Reply

Return to “Modding interface requests”