Jump to content

String editing


Recommended Posts

Hi all,

this question seems so simple, it is driving me crazy that I can't find any guide or even mention of it. And trying to circumvent the problem is just sending me into the next road block.

So: how to manipulate a string in WeiDu the right way? Use case is that I make a small change to a kit and wish to update the kit description. All examples I found just brute force their new description into the TKL. I wish to be more elegant and add or replace part of a line. My idea is to pull the current description with ACTION_GET_STRREF. Do a bit of REGEXP magic and paste the new stuff with STRING_SET. Because all REGEXP funtions only target files I paste the text into a dummy, do my manipulation, and read it back. It seems unnecessarily complicated... But it works, expect the translation part. I can't seem to be able to resolve my tra identifiers. Any way I try to push my @100 into a string to use in the REGEXP it fails. I could use RESOLVE_STR_REF and read that back but that is again messing with the TKL creating useless bloat. All in all what is the commonly approved approch for this?

Link to comment

Everybody appends new strings since that's both the sane and polite thing to do. If this is for something that will see the public eye, you should do the same, if not, why are translations an issue?

I'm not sure you can fully restore the TLK by uninstalling a mod.

Link to comment

I believe OUTER_PATCH_SAVE/INNER_PATCH_SAVE can help you.

With these, you save your talk/tra references as a string variable which you can abuse anyway you like; don't forget to "write it back" again afterwards. Here's an example where I edited vanilla Avenger description based on an ini setting at install time:

Spoiler
ACTION_GET_STRREF %kit_strref% help_avenger // default avenger description

ACTION_IF (avenger_no_shapeshifting = 1) BEGIN
  OUTER_PATCH_SAVE help_avenger ~%help_avenger%~ BEGIN
    SPRINT string1 @91 // 7th level: May Shapeshift
    SPRINT string2 @90 // 19th level: Gains an additional use of Shapeshift
    REPLACE_TEXTUALLY ~– %string1%.*%LNL%~ ~~
    REPLACE_TEXTUALLY ~– %string2%.*%LNL%~ ~~
  END
END ELSE ACTION_IF (MOD_IS_INSTALLED ~yys_tweaks.tp2~ (ID_OF_LABEL ~yys_tweaks.tp2~ ~yys_tweaks_druid_revisions~)) BEGIN
  OUTER_PATCH_SAVE help_avenger ~%help_avenger%~ BEGIN
    SPRINT string1 @81 // 7th level
    SPRINT string2 @90 // 19th level: Gains an additional use of Shapeshift
    SPRINT string3 @80 // 8th level
    REPLACE_TEXTUALLY ~- %string1%~ ~- %string3%~
    REPLACE_TEXTUALLY ~- %string2%.*%LNL%~ ~~
  END
END

LAF SET_KIT_STRREF_EX STR_VAR kit_name = ~AVENGER~ kit_desc = ~%help_avenger%~ END // new avenger description

Good thing is as long as you're still in the same installation process, this variable can be called up and manipulated again by a later component. Here's an example where said Avenger description is further modified dynamically by user's choice of the Avenger's additional spells, wrapped inside a PATCH process:

Spoiler
INNER_PATCH_SAVE help_avenger ~%help_avenger%~ BEGIN // we still do this inside the COPY_EXISTING here to make sure the current READ_2DA_ENTRIES_NOW rows is not yet overwritten
    SPRINT string1 @87 // 1st level
    SPRINT string2 @86 // 2nd level
    SPRINT string3 @85 // 3rd level
    SPRINT string4 @84 // 4th level
    SPRINT string5 @83 // 5th level
    SPRINT string6 @82 // 6th level
    SPRINT string7 @81 // 7th level
    SPRINT string8 @89 // Six arcane spells are added to <PRO_HISHER> repertoire, all the way up to the 6th level
    SPRINT string9 @88 // Thirteen spells are added to <PRO_HISHER> repertoire, all the way up to the 7th level
    FOR (row = 0; row < (7 * 2 - 1); ++row) BEGIN // 7 levels, with 2 spells from lv1 to lv6 plus 1 spell from lv7, and we start with row 0, so we need to substract 1 at the end
      SPRINT ~idx~ $rows(~%row%~ ~0~) // get the avenger spell filename from avenger_spl.2da
      SPRINT ~value%row%~ $avg_spl_names(~%idx%~) // get the avenger spell spellname from array:avg_spl_names
    END
    REPLACE_TEXTUALLY ~%string1%: .*~ ~%string1%: %value0%, %value1%.~
    REPLACE_TEXTUALLY ~%string2%: .*~ ~%string2%: %value2%, %value3%.~
    REPLACE_TEXTUALLY ~%string3%: .*~ ~%string3%: %value4%, %value5%.~
    REPLACE_TEXTUALLY ~%string4%: .*~ ~%string4%: %value6%, %value7%.~
    REPLACE_TEXTUALLY ~%string5%: .*~ ~%string5%: %value8%, %value9%.~
    REPLACE_TEXTUALLY ~%string6%: .*~ ~%string6%: %value10%, %value11%.%LNL%  %string7%: %value12%.~
    REPLACE_TEXTUALLY ~%string8%~ ~%string9%~
  END
  INNER_ACTION BEGIN // because there is no patch-context version of SET_KIT_STRREF_EX
    LAF SET_KIT_STRREF_EX STR_VAR kit_name = ~AVENGER~ kit_desc = ~%help_avenger%~ END // new avenger description
  END

This way you bloat your tra file (because my REGEXP-foo sucks so I rely on a lot of "helper" text to find the positions to modify) but not your tlk.

However, all this does is creating a "pseudo" sense of translation-friendly, I believe. All it takes is a grammar that for example has different translations for the word "take" when it's spoken in the context of a sentence than when it's uttered alone. Then if I used English tra file containing just the word "take" as my REGEXP helper, it might work for English but end up screwed for some other language if said language's tra produces the wrong word for "take". Therefore, the most translation-friendly way probably is still just brute forcing the entire text string into the tlk...

---- Edited for clarity ----

Edited by guyudennis
Link to comment

@lynx

I had stumbled about the same claim with contradicting responses: https://www.reddit.com/r/baldursgate/comments/172wo1f/to_modders_string_set_does_not_get_rolled_back/

My testing so far shows that changes roll back to the vanilla state. If this can be considered fully or not is beyond my knowledge. The alternative is to append the changed description and change the corresponding links in the 2DA. I believe this can create much worse incompatibilities with any mod that is using static references.

@guyudennis

This is exactly what I was looking for! It may not be the most elegant code wise, but I hardly care as long as it keeps the game files clean. The memory effect seems tempting, as indeed my next component will give the user the option to modify it just a bit more. But I think the premise of a single install could lead to some really frustrating issues down the road I better avoid.

I totally agree about the overall limitations. Adding or replacing single lines is probably about as fancy as we can get. Less and we run into the language problem, more and we can forget cross-mod compatibility and get back to good old brute forcing😅

Link to comment
5 hours ago, AvA said:

I had stumbled about the same claim with contradicting responses:

This might be due to the strings still being stored in the games .dlg/.tlk file(s, don't remember which, don't care to go look), even if you uninstall a mod that added it into it, as the strings won't get removed ... at least in weidu mods. The roll back is due to the files being rolled back so they keep the original string references, not the appended ones that the mod added later.

Also, the weidu tries to find if there's the exact same string already exists in the games .-files before it appends the new string to the files, so when you uninstall then reinstall you only move to the already made reference in reinstalls.

Yes, a little Weidu magic.

16 hours ago, lynx said:

I'm not sure you can fully restore the TLK by uninstalling a mod.

The only way to do that is to restore a backup, from before the mod was installed.

Edited by Jarno Mikkola
Link to comment
6 hours ago, AvA said:

The memory effect seems tempting, as indeed my next component will give the user the option to modify it just a bit more. But I think the premise of a single install could lead to some really frustrating issues down the road I better avoid.

In your later component, first do a check with VARIABLE_IS_SET, then on FALSE condition ACTION_GET_STRREF (the same ref position as with an earlier component) + OUTER_PATCH_SAVE (the same variable as with an earlier component), and your worries go away. This way, you can safely code your later component without having to worry about it being in the same installation process or not, because you would have saved your previous modifications from an earlier component to the original string ref position anyways in a previous install instance.

Link to comment
Quote
16 hours ago, Jarno Mikkola said:

Yes, a little Weidu magic.

The only way to do that is to restore a backup, from before the mod was installed.

That kind-of makes sense. The effort to handle empty offsets is probably not worth it. With collapsing out of the question it prevents duplication. That should protect against the worst, unless, someone is running a decade old install over and over...

This means the risk is overall quite limited. Even more so with direct replacements were the roll back can always reach a defined state. At least that is what I see when reading the same offset before, after install and uninstalling the mod. Not to mention that un- and reinstalling through SCS sitting on top of the stack is so painful that I consider working with clean checkpoints way better advise.

15 hours ago, guyudennis said:

In your later component, first do a check with VARIABLE_IS_SET, then on FALSE condition ACTION_GET_STRREF

I think I will go with the fail-safe branch all the time. With that code already in place I better not make a bad habit only to save some split milliseconds of install time 🙃

 

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