Jump to content

Question about the OnCreation() trigger


argent77

Recommended Posts

I have two script blocks for the BALDUR.BCS script. The first one should be triggered immediately whenever the game starts or a savegame is loaded to initialize nonpersistent data. The second block should be triggered in timed intervals to track changes.

IF
  OnCreation()
THEN
  RESPONSE #100
    SetGlobalTimer("MY_TIMER","GLOBAL",FIVE_ROUNDS)
    // more actions...
    Continue()
END

IF
  !OnCreation()
  !ActuallyInCombat()
  !GlobalTimerNotExpired("MY_TIMER","GLOBAL")
THEN
  RESPONSE #100
    SetGlobalTimer("MY_TIMER","GLOBAL",FIVE_ROUNDS)
    // more actions...
    Continue()
END

With these blocks the OnCreation() block is triggered correctly whenever a game is loaded. However, it never fires the second block unless I remove the negated OnCreation() check. Is there something I have missed?

Link to comment

The second block should not be triggered in the same script round as the first block because it wouldn't make sense. This is probably a corner case and can be solved in different ways, but the current implementation would be the most convenient option for me.

I'm more interested why the OnCreation() trigger doesn't behave like other triggers.

Link to comment
1 minute ago, argent77 said:

The second block should not be triggered in the same script round as the first block because it wouldn't make sense. This is probably a corner case and can be solved in different ways, but the current implementation would be the most convenient option for me.

 

But doesn't the timer already take care of that? Game loads, first block is executed, second block is executed for the first time 5 rounds later, is that not the intended behaviour?

 

On the why I only had that guess, probably wrong

Link to comment

The second block runs immediately if the timer hasn't been set yet. Setting the timer in the same script round by another block doesn't work because changes to globals aren't registered until the next pass. I could change !GlobalTimerNotExpired() to GlobalTimerExpired(), but that isn't as robust either.

Link to comment
1 hour ago, argent77 said:

changes to globals aren't registered until the next pass.

 

Oh, I didn't know that. Thanks for explaining. 

So then if the first block sets a global and the second block checks for it, the condition wouldn't return true until the next scripting round, correct? Would that work for you?

 

I.E.:
 

IF
  OnCreation()
THEN
  RESPONSE #100
    SetGlobalTimer("MY_TIMER","GLOBAL",FIVE_ROUNDS)
    SetGlobal("MY_GLOBAL","GLOBAL",1)
    // more actions...
    Continue()
END

IF
  Global("MY_GLOBAL","GLOBAL",1)
  !ActuallyInCombat()
  !GlobalTimerNotExpired("MY_TIMER","GLOBAL")
THEN
  RESPONSE #100
    SetGlobalTimer("MY_TIMER","GLOBAL",FIVE_ROUNDS)
    // more actions...
    Continue()
END
Edited by Allbrother
Link to comment

Yes, that works but can be solved more elegantly. I could instead replace !GlobalTimerNotExpired() by GlobalTimerExpired() to ensure that unset timers fail the check as well, which is functionally equivalent to using an extra variable.

But then the script would be more vulnerable to outside influences, for instance, to other mods which install their own script blocks to the baldur.bcs and prevent the OnCreation() block from triggering. In that case the second block would never be triggered which basically disables the whole mod. Imo it's still the better option to work around the strange OnCreation() behavior since the probability of that scenario is quite low.

The main reason for this topic is still to find out how a negated OnCreation() trigger can fail to evaluate at the same time as a non-negated OnCreation() trigger. It doesn't make sense to me.

Link to comment

I think the question to ask should be, just how does the engine interpret !OnCreation()? Have you tried this trigger in different code, in a creature script, where the results may be different? Because in BALDUR it never returns true. But you shouldn't worry about other mods putting blocks that don't end in Continue() on top of yours. You have no control over that, if a modder screws up in this very basic way. Also, as an experimental solution, you could try putting your must-run OnCreation() stuff into a script for the override level and target Player1 with it. The main character has no special override script like companions, so it's safe - unless again someone beats you to that idea. But this is like the prisoner's dilemma, there is just no knowing what others will do. 

Link to comment

Triggers with IDS values < 0x4000 use an alternate event-driven system, which is buggy even for IE standards. A negated event trigger returns true if there are pending events that have yet to be processed, and if any of these pending events fails to satisfy the unnegated trigger.

You can see this effect by putting !OnCreation() on a creature. The block will fire every time the creature receives an event other than the one that is defined, such as taking damage.

Link to comment
2 hours ago, Bubb said:

Triggers with IDS values < 0x4000 use an alternate event-driven system, which is buggy even for IE standards. A negated event trigger returns true if there are pending events that have yet to be processed, and if any of these pending events fails to satisfy the unnegated trigger.

Very insightful. In that case I'll have to be careful when using event-based triggers.

The workaround of using GlobalTimerExpired() in place of !GlobalTimerNotExpired() should work well enough in my case. For PSTEE I had to come up with yet another solution involving the Delay() trigger, because apparently not even timer checks work correctly in that game when used in a global script.

Edited by argent77
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...