I’ll start with the TL;DR version: I have a loop in which a tracker device increments itself, while keeping count of incrementations; when the tracker completes I want the loop to break. However, the only way I know to detect a tracker is completed is to subscribe to its CompleteEvent. This means that the loop increments well past it’s intended bounds (within one timestamp) while the tracker device doesn’t respond until a bit later; so, instead of incrementing 5 times, it will increment many many times and can cause an infinite loop if you’re not careful. Is there a way to build in a slight delay to each iteration so that the script has time each loop iteration to await the CompleteEvent callback?
A bit more detail: the script I’m writing implements an ammo “overstock” system. If the player’s ammo–in this case, rockets–exceeds a certain amount, one rocket is taken away and “placed in” the overstock by incrementing the tracker device. If the player’s ammo goes below a threshold, the tracker is decremented and the player is granted a rocket. The tracker device is used because of it’s Save/Load functionality, which will be necessary.
The problem is: the tracker device currently has no way to get the current tracked value. You can increment or decrement, and get the max value, but not the current value. So when loading in to the level, I’m having the script “detect” the current value as above: each incrementation is kept track of in an integer variable, the tracker is reset at the end, the incrementations are subtracted from the tracker’s max value, and that gives us the current value in the tracker.
The problem is that if I use loops (if loops or the loop function) I have the stated problem above. I can get it to work by replacing the loops and having it iterate using a timer device, but that’s slow: the minimum timestep for a timer is one second (as far as I know) and if the player has a maximum overflow of, say, a hundred rockets, they have to stand there waiting for the counter for over a minute and a half before they can play, which isn’t ideal.
So, can I put delays in the loop, or does anyone have some other tips I could use?
# Called once at load in, to initialize the player's ammo overstock count from the tracker
GetCurrentTrackerLevel(InPlayer:?agent) : int =
var OverstockEmptyCounter : int = 0
set OverstockEmptyCounter = 0
# 12 iterations is sufficient for testing rockets
for (X := 0 .. 12):
# When the tracker completes, "set MaxOverstockReached = true"
OverstockTracker.CompleteEvent.Subscribe(AmmoIsFull)
Print("Looping:")
# Routine called when the counter (or loop) completes
if (MaxOverstockReached = true):
Print("Running AmmoFull Routine...")
if (MyAgent := InPlayer?):
# This loop doesn't actually work right, but is demonstrative.
for (I := 1..OverstockEmptyCounter):
Print("Decrementing {OverstockEmptyCounter} times...")
OverstockTracker.Decrement(MyAgent)
if (OverstockEmptyCounter > 0):
set MaxOverstockReached = false
# Routine called when counting
else if (MaxOverstockReached = false):
# HERE IS THE PROBLEM. It increments through the loop until it reads that the tracker device has
# detected completion, at which point the function is called that flags "MaxOverstockReached = true".
# The problem is, this loop is too fast. If I set it to (X := 0 .. 100), for example, it counts up to like
# 47 all in the same timestep, whereas the callback function from the tracker device isn't actually called until
# a bit later. So, can I program in some sort of delay, or asynchronicity?
if (MyAgent := InPlayer?):
Print("Incrementing from {OverstockEmptyCounter}")
OverstockTracker.Increment(MyAgent)
set OverstockEmptyCounter += 1
if (OverstockEmptyCounter >= 10):
# Self-diagnostic tool. Ignore this.
Print("Something's gone wrong.")
return {MaxRockets-OverstockEmptyCounter}