argent77 Posted August 5, 2021 Share Posted August 5, 2021 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? Quote Link to comment
Allbrother Posted August 5, 2021 Share Posted August 5, 2021 This might be a silly question, but what's the purpose of the !OnCreation() trigger? As for why it's breaking it, this is just a guess but could that condition not be read as "if this block hasn't been processed before, don't process it" meaning it always gets skipped? Quote Link to comment
argent77 Posted August 5, 2021 Author Share Posted August 5, 2021 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. Quote Link to comment
Allbrother Posted August 5, 2021 Share Posted August 5, 2021 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 Quote Link to comment
argent77 Posted August 5, 2021 Author Share Posted August 5, 2021 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. Quote Link to comment
Allbrother Posted August 5, 2021 Share Posted August 5, 2021 (edited) 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 August 5, 2021 by Allbrother Quote Link to comment
argent77 Posted August 5, 2021 Author Share Posted August 5, 2021 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. Quote Link to comment
temnix Posted August 5, 2021 Share Posted August 5, 2021 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. Quote Link to comment
Bubb Posted August 5, 2021 Share Posted August 5, 2021 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. Quote Link to comment
argent77 Posted August 5, 2021 Author Share Posted August 5, 2021 (edited) 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 August 5, 2021 by argent77 Quote Link to comment
Recommended Posts
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.