Jump to content

ROMANCE_TIMERS and Gtimes.ids


Kulyok

Recommended Posts

I encountered a problem with UB, and I think it concerns our romance timers.

 

In short: I believe that our romance timers, like XAROM_TIMER, get inserted where they shouldn't be inserted(for example, UB's Bodhi Hunt game-time timers, not real-time timers), and we're getting a stutter as a result. I think it's a bad thing.

 

(More on the topic here:

http://forums.gibberlings3.net/index.php?showtopic=25696

http://forums.pocketplane.net/index.php/topic,28632.msg332830.html#msg332830 )

 

There will be other mods with SetGlobalTimer command, and more potential compatibility issues. I would suggest getting rid of Gtimes.ids add-on entirely, and just set a variable for each romance's timer(like BGT/Tutu dialogue names), and compile all related files via an EVALUATE_BUFFER. Under no circumstances should our mod replace other mods' timers(and cause serious issues), I believe.

 

 

If other mods are using this scheme with Gtimes.ids, too: please, reconsider.

Link to comment

(Mike and Kaeloree pointed out that it can be reasonable compiler behavior and my problem can be elsewhere. I'd still say %VARIABLES% are safer than NEW_TIMERS). Will update if I find the solution to my problem elsewhere.

 

If only I had a working save game to check it out! Sigh.

Link to comment

I'm punting this back to Cam. Recoding the project from (for example) XAROM_TIMER to %XAROM_TIMER% and using EVALUATE_BUFFER is certainly another option; but since he came up with the shortcut, I'd appreciate his input. We use them within dialog files. I will go look and see if we also use them in script files, and compile a list.

Link to comment

This is going to be the post that contains the long explanation of how symbolic lookups work. If your eyes glaze over, you can skip ahead to the next post where I'll post an actual solution.

 

So, BG2 has a bunch of IDS files that contain various symbolic lookups--racial entries are in race.ids, times in gimes.ids, spell names in spell.ids, etc. If you look at these files, they're lists of paired numbers and text like 1106 CLERIC_MAGIC_STONE (spell.ids) or 104 CARRIONCRAWLER (race.ids) or 7200 ONE_DAY (gtimes.ids). CARRIONCRAWLER is a symbol that can be used in place of the number 104--though it adds a layer of complexity, it makes triggers and actions human-readable. Look at a non-symbolized AI block:

 

IF
   See(NearestEnemyOf(Myself))
   HaveSpell(2302)
   !Range(NearestEnemyOf(Myself),12)
   See([2.0.0.1])
THEN
   RESPONSE #100
       Spell([2.0.0.1],2302)
END

You'd never guess that it's casting dispel magic at PC mages. This is, however, how the engine understands it, which is why we have all of these IDS tables to facilitate human-readable code being compiled into engine-usable code. Let's look at a typical action from action.ids:

 

115 SetGlobalTimer(S:Name*,S:Area*,I:Time*GTimes)

 

So, SetGlobalTimer takes three parameters. Each parameter begins with a letter to signify the type of input--s for string, i for integer (number), p for point, or o for object--then the name of the parameter, and then an asterisk followed by a lookup table, if appropriate. In this particular case, the parameter provided for the time is designated as I:Time*GTimes--this means the parameter must be an integer, and you can provide a number directly or get the engine to go look up a value from gtimes.ids.

 

When you use an action like SetGlobalTimer("Mytimer","GLOBAL",ONE_DAY) it means nothing to the game sine ONE_DAY is not an integer--this is why when you compile any script with IDS references like this, WeiDU (or whatever you're using to compile) will go to gtimes.ids, look for ONE_DAY, and substitute the numerical value (in this case 7200) instead. If WeiDU can't find the symbol ONE_DAY in gtimes.ids, it will simply insert 0 as a default. These substitutions occur at compile time--if I compile my scripts and then go through and delete the ONE_DAY entry from gtimes.ids, it does not affect my compiled script since it's already using the numerical value. Hold on to this thought.

 

Dialogues, however, never actually compile their actions and triggers. When the engine encounters SetGlobalTimer("Mytimer","GLOBAL",ONE_DAY) during a game dialogue, it looks up the values right then and there. So if I add a dialogue with this trigger and then later delete the ONE_DAY entry from gtimes.ids, it will affect my dialogue.

 

WeiDU will also do its best when de-compiling scripts to substitute symbols to make your uncompiled scripts readable (same when you view a script in NI). So if I decompile a script that has a timer, and the value of the timer is 7200, WeiDU will substitute ONE_DAY instead of 7200 in the baf file.

 

With all this in mind, there are a couple of potential pitfalls.

 

The most common would be depending on an IDS entry that's not necessarily part of the core game. A lot of mods expect shoutids.ids entries, which is not necessarily present in SoA, or even the handful of Fixpack-added entries such as STATE_REALLY_DEAD in state.ids or even the new ETTIN racial entry. It's always handy to have a patched but unmodded install (preferable SoA and ToB) lying around to double-check symbols.

 

If you happen to decompile a script on a game with a custom IDS entries, a potential problem arises--WeiDU will substitute those custom entries as appropriate in your uncompiled script. However, you have no way to guarantee that your players will have those custom entries short of adding them in your mod otherwise they'll get a value of zero instead of your intended value.

Link to comment

OK, so my previous wall of text aside, the practical problem and its solution.

 

We got a little clever with the romance timer, mainly because I don't think we had EVALUATE_BUFFER when we encountered this problem (or I was just lazy). What we do is add a custom gtimes.ids entry based on the player's seclection of romance timer, e.g. XAROM_TIMER will be added to gtimes.ids with a value of 900 to 5400 depending on the player's choice. The scripts just use the XAROM_TIMER symbol and we compile them directly, so the player's choice gets substituted as the actual timer when WeiDU compiles them.

 

What we should be doing is setting a variable to the selected time, and then using the variable name instead of a XAROM_TIMER in the scripts. (Since the scripts are already being compile against EVALUATE_BUFFER we don't need to add the step. For Xan's stuff we'd replace

 

 	  ACTION_IF ("xantimer" = 1) THEN BEGIN
    APPEND ~gtimes.ids~ ~3600 XAROM_TIMER~
    PRINT @1109
    END
    ACTION_IF ("xantimer" = 2) THEN BEGIN
    APPEND ~gtimes.ids~ ~2700 XAROM_TIMER~
    PRINT @1110
    END
    ACTION_IF ("xantimer" = 3) THEN BEGIN
    APPEND ~gtimes.ids~ ~1800 XAROM_TIMER~
    PRINT @1111
    END
    ACTION_IF ("xantimer" = 4) THEN BEGIN
    APPEND ~gtimes.ids~ ~900 XAROM_TIMER~
    PRINT @1112
    END
    ACTION_IF ("xantimer" = 5) THEN BEGIN
    APPEND ~gtimes.ids~ ~5400 XAROM_TIMER~
    PRINT @1113
    END

 

with

 

	  ACTION_IF ("xantimer" = 1) THEN BEGIN
    OUTER_SET XAROM_TIMER = 3600
    PRINT @1109
    END
    ACTION_IF ("xantimer" = 2) THEN BEGIN
    OUTER_SET XAROM_TIMER = 2700
    PRINT @1110
    END
    ACTION_IF ("xantimer" = 3) THEN BEGIN
    OUTER_SET XAROM_TIMER = 1800
    PRINT @1111
    END
    ACTION_IF ("xantimer" = 4) THEN BEGIN
    OUTER_SET XAROM_TIMER = 900
    PRINT @1112
    END
    ACTION_IF ("xantimer" = 5) THEN BEGIN
    OUTER_SET XAROM_TIMER = 5400
    PRINT @1113
    END

 

Next, we just need to track down anything like

 

RealSetGlobalTimer("X#XaFlirtsTalkTime","GLOBAL",XAROM_TIMER)

 

in the scripts and replace that symbol with the variable:

 

RealSetGlobalTimer("X#XaFlirtsTalkTime","GLOBAL",%XAROM_TIMER%)

Link to comment

That matches my knowledge (since you taught it to me); the original idea was to take advantage of the dialog "just look up the ids" loophole, but then we were talking about an environment where there were relatively few mods that were messing about with this. SmokeTest and DevSin both pushed at my learning curve early on suggesting use of the numbers rather than the IDS entries, too. And the solution is relatively easy to deal with. The key understanding for me is that while the dialog actions/triggers are not messed with, the script ones are - and in each case, someone messing with the .ids entries themselves can throw things off.

 

So if I add a dialogue with this trigger and then later delete the ONE_DAY entry from gtimes.ids, it will affect my dialogue.

 

With the number of folks actually using relatively advanced patching these days, it sounds like the safest bet is to completely dispense with this in dialog files, too. That way even if (when) an install's .ids files get FUBAR'd by some other mod or routine, the numbers are in place.

 

For BG1NPC, I am pretty sure everything gets run through the E_B routine already, but I will check.

Link to comment

Thanks for that explanation, Cam. I hadn't realized scripts and dialogues were treated differently in this regard. (Any idea why?)

 

So if I add a dialogue with this trigger and then later delete the ONE_DAY entry from gtimes.ids, it will affect my dialogue.

 

With the number of folks actually using relatively advanced patching these days, it sounds like the safest bet is to completely dispense with this in dialog files, too. That way even if (when) an install's .ids files get FUBAR'd by some other mod or routine, the numbers are in place.

 

There's a point where you have to trust that nobody is going to do something that stupid intentionally. You need to weigh the effort to prevent a problem against the reasonable likelihood of that problem occurring.

 

ONE_DAY is used extensively in BG2 and even a bit in BG1, so if some mod intentionally deletes it, they would also need to clean up the mess. If some mod unintentionally deletes it, well, someone will find the bug soon enough. Chances are nobody would ever bother changing or deleting this identifier because there's not much to gain and a lot to lose.

Link to comment

I agree, Mike1072 :) I am weighing the value of leaving dialog states that trigger on (in a dialog file) like this:

 

++ ~[PC] Why yes, I am using the .ids and creating an entry which works fine in dialog but adds to gtimes.ids and therefore may be subject to screwups because I have added a custom "C-ARANROM" that weidu may try to use or someone could delete and end up with everything running as if the timer is expired.~ DO ~RealSetGlobalTimer("c-aranbg2rom","GLOBAL",C-ARANROM)~ EXIT

 

The reason I am still on the fence is that this is the first report we have had of this in any mod using the .ids entries in this fashion as far as I know, and the materials have been in the field for years now, working in several mods. But safer=better, so It seems smart to change the script ones at the very least.

 

It probably is worth just plain setting aside the time and changing the behavior to match everything, thinking about it. Mass replace could do the job relatively quickly, and we already do this for the area checks for cross platform stuff.

Link to comment

Thanks for that explanation, Cam. I hadn't realized scripts and dialogues were treated differently in this regard. (Any idea why?)

No idea. This was something I discovered for the More Interjections tweak--I could simply re-define IVFPD's value in trigger.ids to InParty's value and all of the dialogues would just work without being touched. Scripts had to be decompiled, patched, and recompiled.

 

And yeah, like Mike1072 said--if another mod wipes one of the expected values from an IDS file (like ONE_DAY) then that's on them. And I don't think BG1 NPC is to blame for the person reporting bugs to Kulyok either. However, it's a good idea in general to eschew the custom IDS entries for straight variables/values; though I'd make it a low priority since the odds of it causing a real-world problem are pretty long.

Link to comment
Dialogues, however, never actually compile their actions and triggers. When the engine encounters SetGlobalTimer("Mytimer","GLOBAL",ONE_DAY) during a game dialogue, it looks up the values right then and there. So if I add a dialogue with this trigger and then later delete the ONE_DAY entry from gtimes.ids, it will affect my dialogue.
Sounds like a bug to me.
Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...