subtledoctor Posted April 19, 2016 Author Share Posted April 19, 2016 This ACTION_TO_UPPER and ACTION_TO_LOWER stuff is really annoying. I need to extract nice mixed-case versions of the spheres, because they get plugged into the kit descriptions.Is there an ACTION_TO_MIXED?EDIT - and the .tp2 entries for sphere access in the ~define_kit_info~ function have to be entered in the same case as they appear in the ~sphere_access~ array in compat.tpa, or they are ignored. I want to be able to ignore case, but I can't. Even if I comment out the FAIL check (which I'm guessing is a bad idea), even when I write ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && STRING_EQUAL_CASE ~major~) BEGIN ...STRING_EQUAL_CASE should mean the match check doesn't care about case. But here, it fails if it's not a perfect match.Very confused and annoyed right now. I don't understand the whole "validate spheres" section of compat.tpa. EDIT 2 - figured that part out. Now to see if I can change the case of the spheres to stay mixed. Link to comment
lynx Posted April 19, 2016 Share Posted April 19, 2016 just judging by the name, STRING_EQUAL_CASE does exactly what I'd expect — case must be equal. However the docs do suggest you are right and it's more like STRING_EQUAL_ANY_CASE. You did forget an argument there though. Write a trivial test case. Doesn't work? Tell Wisp, otherwise the problem is elsewhere. Link to comment
subtledoctor Posted April 19, 2016 Author Share Posted April 19, 2016 No, the problem is that I'm trying to implement code written by someone else and I don't fully understand how it works. I figured out the 2nd part. Link to comment
Mike1072 Posted April 20, 2016 Share Posted April 20, 2016 I used TO_UPPER and TO_LOWER a lot because variable names are case sensitive. If this array is defined: ACTION_DEFINE_ASSOCIATIVE_ARRAY d5_fnp_spheres BEGIN LIFE => 0 DEATH => 0 BENEDICTION => 0 DESTRUCTION => 0 PROTECTION => 0 WAR => 0 KNOWLEDGE => 0 DECEPTION => 0 THOUGHT => 0 DREAD => 0 VIGOR => 0 AFFLICTION => 0 ANIMAL => 0 PLANT => 0 EARTH => 0 WATER => 0 AIR => 0 FIRE => 0 LIGHT => 0 SHADOW => 0 MAGIC => 0 END Then VARIABLE_IS_SET $d5_fnp_spheres(~KNOWLEDGE~) would return true, while VARIABLE_IS_SET $d5_fnp_spheres(~knowLEDGE~) would return false. You should leave the case of these arrays alone. If you want to access a prettified version of their values, then you have a few options. 1) Define an associative array that maps the unpretty version to the pretty version. (This is a good choice if the unpretty versions don't have an easy automated mapping to the pretty version.) 2) Write some code to prettify the value. If you have an all uppercase string and you want to lowercase every letter except the first, you could do something like this: INNER_PATCH_SAVE mixed_sphere ~%sphere%~ BEGIN SET len = STRING_LENGTH ~%sphere%~ READ_ASCII 1 end (len - 1) TO_LOWER end WRITE_ASCIIE 1 ~%end%~ END I don't understand the whole "validate spheres" section of compat.tpa. // validate spheres ACTION_PHP_EACH d5_fnp_spheres AS sphere => val BEGIN ACTION_TO_LOWER sphere OUTER_TEXT_SPRINT sphere ~s_%sphere%~ OUTER_TEXT_SPRINT access EVAL ~%%sphere%%~ ACTION_TO_UPPER access ACTION_IF (NOT VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~)) BEGIN FAIL ~DEFINE_FNP_KIT_INFO: The access value (%access%) for the sphere %sphere% does not match one of the valid options: NONE, MAJOR, MINOR, FOCUS, PALADIN, or RANGER.~ END END Here's what it's doing in pseudocode: - For each entry in the d5_fnp_spheres array, get the key and value as the variables sphere and val. (e.g. sphere = ~KNOWLEDGE~ and val = 0) - Lowercase the value of the sphere variable. (sphere = ~knowledge~) - Prepend the sphere variable with ~s_~. (sphere = ~s_knowledge~) - Set the access variable to the value of the variable named by the sphere variable. (access = ~%s_knowledge%~, e.g. access = ~MAJOR~) - Uppercase the value of the access variable. (access = ~MAJOR~) - Check if the d5_fnp_sphere_access associative array contains a key matching the value of the access variable. - If it does not, the caller of the function specified an invalid value for one of the spheres (e.g. s_knowledge = ~MAJR~) and the installation should FAIL. Link to comment
subtledoctor Posted April 20, 2016 Author Share Posted April 20, 2016 I think I've wrapped my head around it. I was seeing it backwards - or something. I mostly get it now. You should leave the case of these arrays alone. Ha ha, too late. I managed to set them all to be mixed-case. The trick is to make sure they are mixed-case in the array, and in the "s_xyz" variables in the function, and in the variables the modder sets when launching the function, and in the base .2da file. Once I changed everything to match, as long as they continue to match, they all use mixed case and it gives me pretty output to append to kit descriptions. I also figured out how to make the sphere access - "major," minor" etc. - case-insensitive. This is good; the "s_xyz" variables will just be copied and pasted by modders from a form we provide, so I can reasonably rely on the case matching what's in the function. But modders will have to fill in the sphere access themselves, risking typos. Making this part case-insensitive will help the code to avoid stumbling over user error. I've very nearly got this going. These new functions are all plugged in, I just need need to do the grunt-work of entering in sphere access and class access for all of the Divine Remix and Frosty Journey kits. (Anyone know of any other popular priest kit mods for which I should include compatibility?) Then, I need to add some code to the item usability section: have it detect whether the kit identifies itself as an acolyte and if so, edit the kit's usability flag entry in kitlist.2da. Basically, it will - run through kits, identifying cleric kits - check whether each cleric kit is in our d5_class.2da file - check whether "c_acolyte = 1" - find the row of the kit in kitlist.2da* (this is pretty much the only part I'm still iffy on) - SET_2DA_ENTRY the usability flag Then, I need to cover any kits not already known. Probably add a default sphere access entry to the *base* .2da files, and have the kits use that access. Should be okay with HLAs, because the HLAs are dependent on sphere access, and these kits will all have identical (default) sphere access. Ergo, they can use the same HLA table. And then, this puppy is done! And I will hand it off to people with more free time and creativity to make priest kits galore. Link to comment
subtledoctor Posted April 21, 2016 Author Share Posted April 21, 2016 Dammit... so close! I need someone with eagle eyes to spot what I'm doing wrong. In the following code (which is to be used in conjunction with the .tpa file Mike uploaded a page back)... LAM ~READ_FNP_KIT_INFO~ COPY_EXISTING ~kitlist.2da~ ~override~ COUNT_2DA_ROWS ~9~ "rows" FOR ( index = 2 ; index < rows ; index = index + 1 ) BEGIN READ_2DA_ENTRY %index% 5 9 kit_clab READ_2DA_ENTRY %index% 8 9 class DEFINE_ASSOCIATIVE_ARRAY d5_deity_kits BEGIN "%kit_clab%" => "%class%" END END BUT_ONLY ACTION_PHP_EACH d5_deity_kits AS sam => iam BEGIN ACTION_IF (%iam% = 3) BEGIN //.................................................clerics ACTION_PHP_EACH d5_fnp_kits AS ind => kit BEGIN ACTION_IF (~%kit%~ STRING_EQUAL_CASE ~%sam%~) BEGIN ACTION_PHP_EACH d5_fnp_classes AS class => val BEGIN ACTION_IF (VARIABLE_IS_SET $d5_fnp_kit_class_access(~%class%~ ~%kit%~)) BEGIN OUTER_TEXT_SPRINT access $d5_fnp_kit_class_access(~%class%~ ~%kit%~) ACTION_IF (IS_AN_INT access && access == 1) BEGIN ACTION_IF (~%class%~ STRING_EQUAL_CASE ~acolyte~) BEGIN COPY_EXISTING - ~kitlist.2da~ ~override~ COUNT_2DA_COLS num_cols READ_2DA_ENTRIES_NOW ~r2en_kitlist~ 9 FOR (row = 1; row < r2en_kitlist; row += 1) BEGIN READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 kitclab PATCH_IF (~%kitclab%~ STRING_EQUAL_CASE ~%sam%~) BEGIN SET_2DA_ENTRY %row% 7 9 ~0x04000000~ PATCH_PRINT ~%kit% %row%~ END END BUT_ONLY END END END END END END END END The PATCH_PRINT line successfully prints the name of each kit identified as an Acolyte, and the correct row of that kit in kitlist.2da. Since that row is obtainable, the "SET_2DA_ENTRY %row% 7 9 ~0x04000000~" patch should work, right? But it doesn't. After an hour of fiddling I turned to Google, and found this issue: http://gibberlings3.net/forums/index.php?showtopic=27287&page=3 So I changed the line to this: TEXT_SPRINT acolyte_use ~04000000~ SET_2DA_ENTRY row 7 9 ~0x%acolyte_use%~ ...but that doesn't work either. Tearing my hair out here... EDIT - since we're using the priest of Lathander usability flag, I decided to READ_2DA_ENTRY it so that I would have the value in the same format. So: ACTION_IF (~%class%~ STRING_EQUAL_CASE ~acolyte~) BEGIN COPY_EXISTING - ~kitlist.2da~ ~override~ READ_2DA_ENTRY 22 7 9 ~usability~ READ_2DA_ENTRIES_NOW ~r2en_kitlist~ 9 FOR (row = 1; row < r2en_kitlist; row += 1) BEGIN READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 kitclab PATCH_IF (~%kitclab%~ STRING_EQUAL_CASE ~%sam%~) BEGIN SET_2DA_ENTRY %row% 7 9 ~%usability%~ PATCH_PRINT ~%kitclab% %row% %usability%~ END END BUT_ONLY END Here again, the PATCH_PRINT displays the correct usability code, but the SET_2DA_ENTRY fails to change the file. To quote a wise man: what gives??? Link to comment
Mike1072 Posted April 21, 2016 Share Posted April 21, 2016 COPY_EXISTING - That minus sign means the file changes will only be made in memory and won't affect the actual file on disk. Link to comment
subtledoctor Posted April 21, 2016 Author Share Posted April 21, 2016 OMG I didn't even see that minus sign there! Good eagle eyes. Link to comment
Mike1072 Posted April 21, 2016 Share Posted April 21, 2016 My eagle eyes missed this typo in fnp_compat.tpa on line 136: ACTION_IF (NOT FILE_EXISTS ~%clab_name%.2da~) BEGIN It should be: ACTION_IF (NOT FILE_EXISTS_IN_GAME ~%clab_name%.2da~) BEGIN I also wanted to point out that the code above has a lot of indenting, some of it unnecessary (looping through all kits but then checking if the kit matches a specific value) and it could be simplified: COPY_EXISTING ~kitlist.2da~ ~override~ COUNT_2DA_COLS num_cols READ_2DA_ENTRIES_NOW ~r2en_kitlist~ 9 FOR (row = 1; row < r2en_kitlist; row += 1) BEGIN READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 kit_clab READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 8 class_num PATCH_IF (class_num == 3) BEGIN // cleric PATCH_IF (VARIABLE_IS_SET $d5_fnp_kit_class_access(~ACOLYTE~ ~%kit_clab%~)) BEGIN TEXT_SPRINT access $d5_fnp_kit_class_access(~ACOLYTE~ ~%kit_clab%~) PATCH_IF (IS_AN_INT access && access == 1) BEGIN TEXT_SPRINT hex ~04000000~ SET_2DA_ENTRY_LATER ~s2el_kitlist~ row 7 ~0x%hex%~ // usability PATCH_PRINT ~%row% %kit_clab% 0x%hex%~ END END END SET_2DA_ENTRIES_NOW ~s2el_kitlist~ 9 END BUT_ONLY I understand you probably need to do more than this for each kit, but that could be accomplished with some functions thrown in there. By the way, I'd recommend that if you need to do things repeatedly, like "checking if class A has access to kit B", you could create a function that does that, hiding all of the VARIABLE_IS_SET and related array lookups. Link to comment
subtledoctor Posted April 21, 2016 Author Share Posted April 21, 2016 My eagle eyes missed this typo in fnp_compat.tpa on line 136: Erm, I didn't notice because I currently have that warning commented out (It was popping up for almost every kit, I think because I have most of my clab files in lower-case, and that warning fires if it doesn't find them in upper-case, so I was getting tons of false positives.) That is indeed nicer code, and will probably save some processor cycles. Should work fine for the item usability (I think I'd have to add an INNER_ACTION to append stuff to acolyte clab tables). But for the spheres and deity-choice sections, I'm not sure - they do a lot of text handling and some other stuff. The deity choice system, especially, relies on moving through an array and SETting block_num = (%block_num% + 1) in each iteration, building a dialogue with a bunch of unique GOTO commands. But, now I understand a bit better how it all works, I'll take a look at streamlining. But apart from streamlining, I think the only thing left to do is figure out the best to give default sphere access to mod kits that have not opted in to our system. That, and integrate Aquadrizzt's code for Shaman spell choice dialogues. After that, assuming it doesn't all fall apart at the seams when people play it, it will be ready to go! Link to comment
Mike1072 Posted April 21, 2016 Share Posted April 21, 2016 That typo is why the warning would pop up all the time. My test mod was only adding fake kits that didn't have an actual CLAB file in the game, so I didn't notice it wasn't working properly until I tried adding info for the vanilla cleric kits. The warning is there in case the CLAB file is misspelled. It provides a warning instead of failing the installation because if someone wanted to run the function before running ADD_KIT, that would be fine, but the CLAB wouldn't have been copied yet. Link to comment
subtledoctor Posted August 2, 2016 Author Share Posted August 2, 2016 More eagle eyes needed! Many moons later, I've discovered created a bug. This is the code in beta 41 of the mod, which patches sphere spells into cleric clab tables perfectly: LAM ~READ_FNP_KIT_INFO~ COPY_EXISTING ~kitlist.2da~ ~override~ COUNT_2DA_ROWS ~9~ "rows" FOR ( index = 2 ; index < rows ; index = index + 1 ) BEGIN READ_2DA_ENTRY %index% 5 9 clab READ_2DA_ENTRY %index% 8 9 class DEFINE_ASSOCIATIVE_ARRAY d5_sphere_kits BEGIN "%clab%" => "%class%" END END BUT_ONLY ACTION_PHP_EACH d5_sphere_kits AS fox => sox BEGIN ACTION_IF (%sox% = 3) BEGIN //...................................................clerics OUTER_INNER_PATCH ~~ BEGIN SNPRINT 6 ~lufox~ ~%fox%~ END COPY ~faiths_and_powers/spheres/hlas/luclxyz.2da~ ~override/lu%lufox%.2da~ ACTION_PHP_EACH d5_fnp_spheres AS sphere => val BEGIN ACTION_IF (VARIABLE_IS_SET $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~)) BEGIN OUTER_TEXT_SPRINT access $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~) ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~FOCUS~) BEGIN COPY_EXISTING ~%fox%.2da~ ~override~ LPM remove_blank_lines APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_focus.txt~ BUT_ONLY OUTER_TEXT_SPRINT focus_sphere_list ~%focus_sphere_list% %sphere%~ COPY_EXISTING ~lu%lufox%.2da~ ~override~ APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~ BUT_ONLY END ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MAJOR~) BEGIN COPY_EXISTING ~%fox%.2da~ ~override~ LPM remove_blank_lines APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_major.txt~ BUT_ONLY OUTER_TEXT_SPRINT major_sphere_list ~%major_sphere_list% %sphere%,~ COPY_EXISTING ~lu%lufox%.2da~ ~override~ APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~ BUT_ONLY END ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MINOR~) BEGIN COPY_EXISTING ~%fox%.2da~ ~override~ LPM remove_blank_lines APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_minor.txt~ BUT_ONLY OUTER_TEXT_SPRINT minor_sphere_list ~%minor_sphere_list% %sphere%,~ END END END END Meanwhile, after making a few additions to add support for multiclass kits in beta 51, this new code adds sphere spells twice to every kit. Basically the three APPEND_FILE commands are being applied twice and I can't figure out why. It's not actually much of a problem in-game - adding the same spell twice to a priest spellbook has no effect - but I want to know why it's wrong. LAM ~READ_FNP_KIT_INFO~ COPY_EXISTING ~kitlist.2da~ ~override~ COUNT_2DA_ROWS ~9~ "rows" FOR ( index = 3 ; index < rows ; index = index + 1 ) BEGIN READ_2DA_ENTRY %index% 5 9 clab READ_2DA_ENTRY %index% 1 9 name READ_2DA_ENTRY %index% 4 9 desc READ_2DA_ENTRY %index% 9 9 code READ_2DA_ENTRY %index% 8 9 class DEFINE_ASSOCIATIVE_ARRAY d5_sphere_kits BEGIN "%clab%" , "%name%" , "%desc%" , "%code%" => "%class%" END END BUT_ONLY ACTION_PHP_EACH d5_sphere_kits AS fox => sox BEGIN ACTION_IF (%sox% = 3 || %sox% = 11 || %sox% = 8 || %sox% = 14 || %sox% = 15 || %sox% = 18) BEGIN //.......clerics OUTER_INNER_PATCH ~~ BEGIN SNPRINT 6 ~lufox~ ~%fox%~ END COPY ~faiths_and_powers/spheres/hlas/luclxyz.2da~ ~override/lu%lufox%.2da~ ACTION_IF (%sox% = 11) BEGIN COPY ~faiths_and_powers/spheres/hlas/ludrxyz.2da~ ~override/lu%lufox%.2da~ END ACTION_PHP_EACH d5_fnp_spheres AS sphere => val BEGIN ACTION_IF (VARIABLE_IS_SET $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~)) BEGIN OUTER_TEXT_SPRINT access $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~) ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~FOCUS~) BEGIN COPY_EXISTING ~lu%lufox%.2da~ ~override~ APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~ BUT_ONLY COPY_EXISTING ~%fox%.2da~ ~override~ LPM remove_blank_lines APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_focus.txt~ BUT_ONLY OUTER_TEXT_SPRINT focus_sphere_list ~%focus_sphere_list% %sphere%~ END ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MAJOR~) BEGIN COPY_EXISTING ~lu%lufox%.2da~ ~override~ APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~ BUT_ONLY COPY_EXISTING ~%fox%.2da~ ~override~ LPM remove_blank_lines APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_major.txt~ BUT_ONLY OUTER_TEXT_SPRINT major_sphere_list ~%major_sphere_list% %sphere%,~ END ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MINOR~) BEGIN COPY_EXISTING ~%fox%.2da~ ~override~ LPM remove_blank_lines APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_minor.txt~ BUT_ONLY OUTER_TEXT_SPRINT minor_sphere_list ~%minor_sphere_list% %sphere%,~ END END END END And Mike I have a version of this using a straight R2EN and patching of kitlist, but it's not quite working right and it involves craziness like this: COPY PATCH_IF INNER_ACTION COPY PATCH_IF INNER_ACTION ... I want to set it aside for now and figure out why my current code doesn't work. Link to comment
Jarno Mikkola Posted August 2, 2016 Share Posted August 2, 2016 You might want to provide a link to the archive that has the bug present(at least in your install/game)... as it could provide a wider perspective of the problem. Link to comment
subtledoctor Posted August 2, 2016 Author Share Posted August 2, 2016 a link to the archive that has the bug present You mean the mod? I don't have beta 51 uploaded anywhere - it's just on my computer, as I work on it. But, what I posted above is the entire difference in to the code patch spheres into clab spells. Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.