AvA Posted August 26 Share Posted August 26 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? Quote Link to comment
lynx Posted August 26 Share Posted August 26 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. Quote Link to comment
guyudennis Posted August 26 Share Posted August 26 (edited) 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 August 26 by guyudennis Quote Link to comment
AvA Posted August 26 Author Share Posted August 26 @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 Quote Link to comment
Jarno Mikkola Posted August 27 Share Posted August 27 (edited) 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 August 27 by Jarno Mikkola Quote Link to comment
guyudennis Posted August 27 Share Posted August 27 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. Quote Link to comment
AvA Posted August 27 Author Share Posted August 27 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 Quote Link to comment
lynx Posted August 27 Share Posted August 27 If you insist, you can look at how the GTU (text update) component did it. 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.