Page 1 of 1

Localized message repeats itself [Solved]

Posted: Sat Nov 15, 2014 1:54 am
by jedimoose32
Hi everyone.

I'm trying to have a message/notification appear in the top-left of the screen when a certain event happens. The first time the event happens, it works fine and the text appears. All subsequent times after that, the message shows up between three and ten times in a row. I can't figure out what's causing it. Any idea what I've done wrong in my lua? Pictures and code below.

How it looks the first time (no problems here):
Image
How it looks each subsequent time (problem):
Image
Here's the code that runs this:
Hidden/Spoiler:
[code]
function GoForBombing()
if GetObjectTeam("cp6") == DEF or GetObjectTeam("cp7") == DEF then
--BOMB THEM!!

RewindAnimation("flyby"); --Here we want the bomber to go back to the beginning of its run if not there already...
PlayAnimation("flyby"); --...and come for another flyby
--SetProperty("bomber1", "SoundProperty", "vwingflying")
DestroyTimer(bombingreset) --Get rid of the timer that caused us to come back to this point
strafecoord = CreateTimer("strafecoord") --Create a timer that will let us know when the bombing animation is finished
SetTimerValue(strafecoord, (17))
StartTimer(strafecoord)
ShowMessageText("level.dda.objectives.bombwarn1",1) --Let the clones know that the cavalry has arrived
ShowMessageText("level.dda.objectives.bombwarn2",2) --Let the droids know of their impending doom
OnTimerElapse(function(BombingResetTime) --Once the animation timer is done we'll...
DestroyTimer(strafecoord) --...get rid of the timer...
bombingreset = CreateTimer("bombingreset") --...make a new timer that will determine when another bombing run will occur...
SetTimerValue(bombingreset, (math.random(45,105))) --...which will be somewhere between 0:45 and 1:45 later.
StartTimer(bombingreset)
OnTimerElapse(GoForBombing, bombingreset) --Once this random timer has finished I want this whole GoForBombing function to run itself again
end
,strafecoord)
end

end
[/code]
That whole function "GoForBombing" gets called the first time when a particular object is destroyed, using OnObjectKillName, and as you can see by my comments in the code, from then on as long as either CP6 or CP7 belongs to team 2 then the bomber should keep coming back. That part works fine. I'm just trying to make it look a bit nicer by not having the message absolutely spammed on the player's screen. Thanks!

Re: Localized message repeats itself

Posted: Sat Nov 15, 2014 2:57 am
by Maveritchell
Your if statement ("GetObjectTeam("cp6") == DEF..etc.) isn't a one-time condition. That should fire multiple times, because the condition is (theoretically) continually met.

Re: Localized message repeats itself

Posted: Sat Nov 15, 2014 2:59 am
by jedimoose32
Right but isn't it just being checked once each time I call the function GoForBombing?

Re: Localized message repeats itself

Posted: Sat Nov 15, 2014 3:55 am
by Maveritchell
Right, duh, I'm an idiot. I'll take a look back once I've slept.

Re: Localized message repeats itself

Posted: Sat Nov 15, 2014 5:41 pm
by jedimoose32
Thanks. I've looked through that code any number of times and can't figure it out.

Re: Localized message repeats itself

Posted: Sat Nov 15, 2014 6:23 pm
by Locutus
I assume you are calling GoForBombing() more than one time during the match, right?
Now, each time you call this function you will register a new OnTimerElapse() event, thus for each time you call the function it will be executed i+1 time.
So just enclose the elapse function with an if-statement and you should be good: (Destroying a timer will not release the OnTimerElapse function)

timer_elapse_initialized = false

function GoForBombing()
[...]
if not timer_elapse_initialized then
OnTimerElapse(...)
timer_elapse_initialized = true
end
[...]
end

Re: Localized message repeats itself

Posted: Sat Nov 15, 2014 9:26 pm
by jedimoose32
It kind of works...

The message now displays 1x the first run, 1x the second run, then 2x the third, 3x the fourth, 4x the fifth, etc. I'll show you how I put it into my code:
Hidden/Spoiler:
[code]
function ScriptPostLoad()
...
timer_elapse_initialized = false --Locutus
end

function GoForBombing()
if GetObjectTeam("cp6") == DEF or GetObjectTeam("cp7") == DEF then
--BOMB THEM!!

RewindAnimation("flyby"); --Here we want the bomber to go back to the beginning of its run if not there already...
PlayAnimation("flyby"); --...and come for another flyby
--SetProperty("bomber1", "SoundProperty", "vwingflying")
DestroyTimer(bombingreset) --Get rid of the timer that caused us to come back to this point
strafecoord = CreateTimer("strafecoord") --Create a timer that will let us know when the bombing animation is finished
SetTimerValue(strafecoord, (17))
StartTimer(strafecoord)
ShowMessageText("level.dda.objectives.bombwarn1",1) --Let the clones know that the cavalry has arrived
ShowMessageText("level.dda.objectives.bombwarn2",2) --Let the droids know of their impending doom
if not timer_elapse_initialized then --Locutus
OnTimerElapse(function(BombingResetTime) --Once the animation timer is done we'll...
DestroyTimer(strafecoord) --...get rid of the timer...
bombingreset = CreateTimer("bombingreset") --...make a new timer that will determine when another bombing run will occur...
SetTimerValue(bombingreset, (math.random(5,15))) --...which will be somewhere between 0:45 and 1:45 later.
StartTimer(bombingreset)
OnTimerElapse(GoForBombing, bombingreset) --Once this random timer has finished I want this whole GoForBombing function to run itself again
end
,strafecoord)
timer_elapse_initialized = true --Locutus
end
end

end
[/code]
I have tried putting that first "timer_elapse_initialized = false" bit above PostLoad, in PostLoad, and in GoForBombing, and they all yield the same result.
I suppose it works the first two times because timer_elapse_initialized is a boolean, and only has two states? What do you think?

Re: Localized message repeats itself

Posted: Sun Nov 16, 2014 12:36 am
by Maveritchell
So why are you destroying your timers at all? If you're going to reuse them under the same name, just recycle them by resetting their start values (which you're doing already) and don't destroy them. Initialize them first (CreateTimer) outside the function.

Also, could you describe your desired logic in plaintext? I.e. when your events occur and under what conditions.

Re: Localized message repeats itself

Posted: Sun Nov 16, 2014 3:10 am
by jedimoose32
I must have misinterpreted the tutorial on timers. It seemed to imply that the DestroyTimer bit was an important part of it. I've gone ahead and removed those lines now.

Essentially what I'm trying to accomplish is this:
1. Gate gets destroyed.
2. Message displays advising that V-Wing is about to fly by.
3. V-Wing flies past.
4. V-Wing reaches end of its animation path.
5. Game starts Invisible-Random-Timer to determine when the V-Wing should fly past again.
6. Invisible-Random-Timer elapses.
7. Steps 2 through 6 repeat ad infinitum.

Here's my current code. I tried using Locutus's idea in a few different variations but it ended up stopping everything after the second bombing run.
Hidden/Spoiler:
[code]
function GoForBombing()
if GetObjectTeam("cp6") == DEF or GetObjectTeam("cp7") == DEF then

StopTimer(bombingreset)

--BOMB THEM!!
ShowMessageText("level.dda.objectives.bombwarn1",1) --Let the clones know that the cavalry has arrived
ShowMessageText("level.dda.objectives.bombwarn2",2) --Let the droids know of their impending doom

RewindAnimation("flyby"); --Here we want the bomber to go back to the beginning of its run if not there already...
PlayAnimation("flyby"); --...and come for another flyby

SetTimerValue(strafecoord, (17))

StartTimer(strafecoord) --Start the timer so we know when the anim is done playing
OnTimerElapse(BombingResetTime,strafecoord)
end
end

function BombingResetTime() --Once the animation timer is done we'll...

StopTimer(strafecoord)

--SetTimerValue(bombingreset, (math.random(5,15))) --...which will be somewhere between 0:45 and 1:45 later.
SetTimerValue(bombingreset, (math.random(5,15)))

StartTimer(bombingreset)
OnTimerElapse(GoForBombing, bombingreset) --Once this random timer has finished I want this whole GoForBombing function to run itself again

end
[/code]

Re: Localized message repeats itself

Posted: Sun Nov 16, 2014 7:58 am
by Locutus
Since you are using two OnTimerElapse functions you should encapsulate both with an if-clause.

if not timer_1_elapse_initialized then
OnTimerElapse(BombingResetTime,strafecoord)
end

if not timer_2_elapse_initialized then
OnTimerElapse(GoForBombing, bombingreset)
end

Set timer_X_elapse_initialized to true at the end of each function.

Another note:
Because math.random can cause trouble in multiplayer I'd recommend to replace it with this: (ScriptCB_random() * 10) + 5
ScriptCB_random() returns a random value between 0 and 1 and works perfectly in MP.

Re: Localized message repeats itself

Posted: Sun Nov 16, 2014 5:28 pm
by jedimoose32
This worked. Thanks so much for your help!

For anyone viewing this later on, my code:
Hidden/Spoiler:
[code]
function ScriptPostLoad()
...
--Create a timer that will let us know when the bombing animation is finished
strafecoord = CreateTimer("strafecoord")
bombingreset = CreateTimer("bombingreset") --...make a new timer that will determine when another bombing run will occur...

timer1_elapse_initialized = false
timer2_elapse_initialized = false
...
OnObjectKillName(GoForBombing, "thegate");
end

function GoForBombing()
if GetObjectTeam("cp6") == DEF or GetObjectTeam("cp7") == DEF then

StopTimer(bombingreset)

--BOMB THEM!!
ShowMessageText("level.dda.objectives.bombwarn1",1) --Let the clones know that the cavalry has arrived
ShowMessageText("level.dda.objectives.bombwarn2",2) --Let the droids know of their impending doom

RewindAnimation("flyby");
PlayAnimation("flyby");

SetTimerValue(strafecoord, (17))

StartTimer(strafecoord)
if not timer1_elapse_initialized then
OnTimerElapse(BombingResetTime,strafecoord)
end
end
timer1_elapse_initialized = true
end

function BombingResetTime()

StopTimer(strafecoord)

SetTimerValue(bombingreset, (math.random(5,15)))

StartTimer(bombingreset)
if not timer2_elapse_initialized then
OnTimerElapse(GoForBombing, bombingreset)
end
timer2_elapse_initialized = true
end
[/code]