Jump to content

[Solved] REPLACE_ACTION_TEXT as a Timer Solver?


cmorgan

Recommended Posts

Hello, oh fellow Weidu-ites - I am having a little trouble messing about with R_A_T.

Problem:

I have timers as variables set by ACTION_READLN. I want to move that to individual SUBCOMPONENT to make it easier for unattended installs.

 

Currently, I use OUTER_SET ARAN_LTT = 3600 to build the "default install values".  The timers I need to adjust later are set almost exclusively through dialogue:

IF ~Global("c-aranbg2rom","GLOBAL",7)~ THEN BEGIN a111
  SAY @3864
  ++ @3865 DO ~SetGlobal("c-aranbg2rom","GLOBAL",8) RealSetGlobalTimer("c-aranromtimer","GLOBAL",%ARAN_LTT%)~ + a112

I compile the file with E_B and things go fine: resulting file in NI shows a valid action RealSetGlobalTimer("c-aranromtimer","GLOBAL",3600)

So everything is fine for creating the default! Now comes the part where oddity ensues...

To test changing the timer values through patching the default settings, I create a second component that compiles a file timertest.d with only the following contents:

REPLACE_ACTION_TEXT C-ARANJ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",3600)~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",4000)~

It installs fine... unfortunately, there is no change to C-ARANJ.  NI shows the original timer unchanged.

Checked the usual: NI is not running on install,  no typos, DLTCEP is not running, I am in the correct directory - .debug says the dialog file was loaded, but saved untouched.

Perhaps I misunderstand how R_A_T is supposed to be formed? Doesn't it pick up all instances of that text in the .d and replace it with the second value?

 

 

 

Link to comment

One thing that usually helps in cases like this is to just decompile the dialogue directly with WeiDU. Sometimes it'll pull a slightly different action or sub in symbols for the values; so looking at a direct decompile can help identify these issues.

Given that 3600 is TWELVE_HOURS in gtimes, I suspect that's being decompiled as RealSetGlobalTimer("c-aranromtimer","GLOBAL",TWELVE_HOURS) in which case you'd need something like

 REPLACE_ACTION_TEXT C-ARANJ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",\(3600\|TWELVE_HOURS\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",4000)~ 

 

Link to comment

Cool - that definitely worked! 😀

And, Dammit, that definitely worked. 😒

I will retest, but this brings up a rather awkward problem. If I am installing BG2 Fixpack, I am working with a clean GTIMES.IDS and can do R_A_T without fear of other entries in the .ids.

If, on the other hand, I am an NPC mod that has other folks going first, I am not sure what values match the same entries. Since we have had mods in the field for years that use the .ids entries as shortcuts for timers. 3600 = a bunch of entries. And I can't account for what would be on a mega install...

unless I parse the gtimes.ids for the value that the local install is going to use as the decompiled label?

So which is more stable, using the "heck just slap MYNPC_TIMER in there and then edit the .ids to the new value", or "do it right by setting a static value, then try to account for what weidu is going to see when it decompiles my dialog?"

 

I am looking carefully at what you do in Tweaks, here:

ACTION_PHP_EACH cd_romances_timers AS script => variable BEGIN

  ACTION_IF FILE_EXISTS_IN_GAME ~%script%.bcs~ THEN BEGIN
  
    COPY_EXISTING ~%script%.bcs~ ~override~
	  DECOMPILE_AND_PATCH BEGIN
	    REPLACE_EVALUATE ~RealSetGlobalTimer("%variable%","GLOBAL",\([^)]+\))~ BEGIN
          PATCH_IF IS_AN_INT MATCH1 BEGIN
		    SET time = MATCH1
		  END ELSE BEGIN
            SET time = IDS_OF_SYMBOL (~GTIMES~ ~%MATCH1%~) // should convert stuff like EIGHT_HOURS to numeric value
          END
          SET time = ((time * romance_speed_factor) / 100) 
        END ~RealSetGlobalTimer("%variable%","GLOBAL",%time%)~	
	  END
	  BUT_ONLY
	  
  END

END

Just not sure of some stuff. Like, can that array have multiple passes at the same dialog file, such that


C-ARANJ => c-aranBG2romtimer
C-ARANJ => c-aranBG2friendtimer
C-ARANJ => choseninitialflirt
C-ARANJ => anothervalue
C-ARN25J => etc. etc. etc.

It looks promising, so I will go play about - unless someone comes along and fixes it all up for me.

 

 

 

 

Link to comment

Heh. So, leave it to me to try to reverse engineer a nuclear weapon to swat a fly...

1. that array won't work as the first column needs to have unique entries - the simplest answer would be to process each file once for each variable.

2. since the timers are setting in the dialog using the same value, I don't need to be careful about only replacing a very specific set without touching others

3. the wicked cool code above has the simplest answer - a regexp for "find all the flies and eat them".

So using

REPLACE_ACTION_TEXT C-ARANJ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",4000)~

does the job, bypassing the problem of parsing the .ids

.bcs is another matter, but there are only two script blocks to manipulate, and they (hopefully) will not have the same problem. If they do, then I can always false() and rebuild.

 

Thank you for getting me on the right track, @CamDawg

Link to comment
10 hours ago, cmorgan said:

I will retest, but this brings up a rather awkward problem. If I am installing BG2 Fixpack, I am working with a clean GTIMES.IDS and can do R_A_T without fear of other entries in the .ids.

If, on the other hand, I am an NPC mod that has other folks going first, I am not sure what values match the same entries. Since we have had mods in the field for years that use the .ids entries as shortcuts for timers. 3600 = a bunch of entries. And I can't account for what would be on a mega install...

And to answer my own question in another way - devSin and Smoketest spent some time really explaining all this symbolic referent to me, but it has taken over a decade for the lesson to sink in.

In a nutshell, if you want to make sure that an .ids or something doesn't accidentally interfere on compilation/decompilation, then...

get this...

use a nonstandard value. 🙄

So final .d for me is a series of files with different values, and set my initial .bcs as a non-standard value so that it can be easily picked up and sorted.

file c-arantimer1h30min.d

/* Change the installed timers in .dlg to values that are a minimum of 1 hour 30 minutes real time before the next talk can trigger */
/* all timers (after initial .bcs) in the project are set through dialog, and they all are the same length - the initial .bcs block staggers the start out to try to make it less likely that multiple events align */

REPLACE_ACTION_TEXT C-ARANJ ~RealSetGlobalTimer("c-aranfriendtimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",5405)~
REPLACE_ACTION_TEXT C-ARANJ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",5405)~
REPLACE_ACTION_TEXT C-ARANJ ~RealSetGlobalTimer("c-aranflirttimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",5405)~
REPLACE_ACTION_TEXT C-ARN25J ~RealSetGlobalTimer("c-aranfriendtimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",5405)~
REPLACE_ACTION_TEXT C-ARN25J ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",5405)~
REPLACE_ACTION_TEXT C-ARN25J ~RealSetGlobalTimer("c-aranromtimer","GLOBAL",\([^)]+\))~ ~RealSetGlobalTimer("c-aranflirttimer","GLOBAL",5405)~

 

 

Link to comment

Behold, as your code decreases.

REPLACE_ACTION_TEXT_REGEXP C-ARAN\(25\)?J ~RealSetGlobalTimer("c-aran\(friend\|rom\|flirt\)timer","GLOBAL",[^)]+)~ ~RealSetGlobalTimer("c-aran\1timer","GLOBAL",5405)~

FWIW, the regexp [^)]+ means to match anything except a closing parenthesis, so it doesn't matter if the timer gets decompiled with a numeric or symbolic value--it'll get matched and replaced.

Link to comment
2 hours ago, cmorgan said:

RealSetGlobalTimer("c-aranromtimer","GLOBAL",5405)

What CamDawg said and why do you not want the ids to interfere with the new timer value - isn't it unimportant what it looks like once you replaced it? Even if there is a mod that adds a lot of new entries to the ids and the player deinstalls it midgame, Aran would be reinstalled after it so the timer should be ok, again?

Thanks for the discussion and also the short version from @CamDawg as I will need this, too.

Link to comment

Why replace anything in the dialogue at all? What about putting the dialogue processing/the whole mod into a .tpa file and do something like (warning, pseudocode):

BEGIN ~twelve hour timer~
	SUBCOMPONENT ~how long is the timer?~
	OUTER_SET ARAN_LTT = 3600
	INCLUDE ~mod/rest_of_mod.tpa~
	 
	BEGIN ~six hour timer~
	SUBCOMPONENT ~how long is the timer?~
	OUTER_SET ARAN_LTT = 1800
	INCLUDE ~mod/rest_of_mod.tpa~
	 
	Etc.

Then you don't need to mess with the dialogue at all, just leave it coded with the %ARAN_LTT% variable. 

 

EDIT - not loving this new forum posting interface... :(

Edited by subtledoctor
Link to comment

Dang, @CamDawg - I need to go refresh my (very limited) regexp knowledge - that is sweeeeeet - I will implement that on the next pass!

 

Wow, @subtledoctor -  mind... blown.  So flip the traditional mod structure on its head. Instead of installing a base mod and then editing it, create a workflow that makes a decision up front and then adds the rest of the mod down the chain.

It would even work with Alien's mod install tool.

For me, though, there is way too much player choice to work it out without my brain going nuts. I would have to think backwards - and the initial subcomponents to establish the workflow would be

BEGIN ~Twelve Hour Timers, Aran to Dual Class to Cleric, Portrait #9, Poor Equipment, Scale Armor, Long Sword, Shield, Long Bow~
	SUBCOMPONENT ~How many Torm-Kissed Choices Do You Want Me To Go Through You Silly Modder?~
	OUTER_SET ARAN_LTT = 3600
    INCLUDE ~mod/outer_set_choice_pattern_176_or_a_zillion.tpa~
	INCLUDE ~mod/rest_of_mod.tpa~

BEGIN ~Twelve Hour Timers, Aran to Dual Class to Cleric, Portrait #9, Poor Equipment, Scale Armor, Long Sword, Shield, Crossbow~
	SUBCOMPONENT ~How many Torm-Kissed Choices Do You Want Me To Go Through You Silly Modder?~
    INCLUDE ~mod/outer_set_choice_pattern_177_or_a_zillion.tpa~
	INCLUDE ~mod/rest_of_mod.tpa~

although come to think of it that might be a cool way to handle it after all. I would just need to pare down the choices I am allowing.

 @jastey I know setting the values to 'non-standard" ones takes care of the problem but is overkill after using regexp to blow away the original value  (I am not adding values to gtimes.ids the way we were, just trying to patch the darned stuff :)  )  - I am just going to make very sure I can see the changes, and that the changes were made by my mod not something else. Or did I not understand you?

Link to comment
36 minutes ago, Ardanis said:

Just offer 2-3 choices you think best balanced, and add external settings.ini with variables for power users to edit.

To how many questions ? As the dialog setting is NOT the only question. There's things like NPCs class, kit, portrait, proficiencies ... plah plah plah. So, setting a default, is always the best. And then altering that with another component is "easy".

Unless you are Level1NPCs mod, but that's a special case, as there the default is already set.

And externalizing settings is only useful if you can also install the "same components" without the externalizing the settings. Just like with the games own settings, they can be changed after the first run. And there is no need to even go and edit a thing with text-editor.

Or how much do you thing you would play the game if it was set to play on 640x480 resolution ? 

Edited by Jarno Mikkola
Link to comment
2 hours ago, cmorgan said:

.Wow, @subtledoctor -  mind... blown.  So flip the traditional mod structure on its head. Instead of installing a base mod and then editing it, create a workflow that makes a decision up front and then adds the rest of the mod down the chain.

For me, though, there is way too much player choice to work it out without my brain going nuts

You could make a component with subcomponents for each choice

How many days in your week?
	OUTER_SET days = 6
	OUTER_SET days = 7
	OUTER_SET days = 8
	How many weeks in your month?
	OUTER_SET weeks = 3
	OUTER_SET weeks = 4
	OUTER_SET weeks = 5
	How many months in your year?
	OUTER_SET months = 11 
	OUTER_SET months = 12
	OUTER_SET months = 13

Then have a separate component that actually does what needs doing, plugging in the variables set earlier. This last component would be automatically installed, by default, with no user input. I forget the Weidu parameter for this but there is one. 

In that last component you would want to start it with

ACTION_IF NOT VARIABLE IS SET %days% BEGIN
	OUTER_SET days = 7
	Etc. 

...to set default values in case the user chooses "[N]o" in the variable-setting subcomponents. 

This way the player would just face a series of sequential choices, and after the last one the mod would plug all the choices in, in whatever combination, and then do its magic. 

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...