Jump to content

Photo

Help: Some Coding Questions and Problems

Question Code Weidu Patching

14 replies to this topic

#1 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 24 February 2018 - 05:07 PM

While working on a recent mod attempt I’ve come to some impasses due to my rather poor skills at using weidu; in fact, that would be a rather kind appraisal, as I find myself near illiterate when it comes to weidu, doing most of my work by repurposing others’ code for what I need to accomplish, otherwise the actual coding process is rather opaque to me.

 

Let me get to what I’m stuck upon: firstly, I’m trying to create a code that will patch all quarterstaves to remove the backstab feature by toggling the “EE/Ex: Toggle critical hits (25)” feature in the itm files.  So far based on previous reference, I’ve managed to bang out this code:

 

COPY_EXISTING_REGEXP "^.+\.itm" override

  PATCH_IF (SOURCE_SIZE > 0x71) THEN BEGIN

    READ_SHORT 0x31 weaprof

              PATCH_IF (weaprof = 102) BEGIN

                WRITE_[Bor or Byte?] 0x1b (THIS [Bor or Byte?] 0b[?])

    END

  END

  BUT_ONLY_IF_IT_CHANGES

 

But in reading the Bor/Byte tutorial I’ve found myself over my head.  I can’t seem to figure out whether the [bracketed] parts should be a Bor or Byte (I think it’s Bor), and I know I need a binary to accomplish the task, but I can’t seem to grasp how I translate what I want into the proper 1s and 0s.  Could anyone help me with the missing pieces?

 

The second problem is a bit more vague.  What I need to accomplish is to create a weidu code that patches the WEAPPROF file so that all 3’s within the “2Weapon” row are turned into 2’s.  This is what, with some help, I’ve put together:

 

COPY_EXISTING ~WEAPPROF.2DA~ override

COUNT_2DA_COLS cols

FOR (col = 3; col < cols; ++col) BEGIN

  READ_2DA_ENTRY 34 cols col val

  PATCH_IF %val% = 3 BEGIN

    SET_2DA_ENTRY 34 cols col 2

  END

END

 

For obvious reasons (though not to me) this code does not work, and, being a poor hand at weidu, I imagine I’ve made a bunch of syntactical errors in this code that prevent it from working.  Could correct the code or tell me what I did wrong?

 

I’m immensely thankful for any help I can receive, in advance, and I hope you can be patience with me, given I lack a great deal of the Programmer’s savvy.

 



#2 Mike1072

Mike1072
  • Gibberling Poobah
  • 2487 posts
  • Gender:Male
  • Location:Canada

Posted 24 February 2018 - 06:45 PM

1)

 

I assume you're talking about this tutorial.  This code should work for setting the flag to toggle critical hit aversion.

COPY_EXISTING_REGEXP GLOB ~^.+\.itm$~ ~override~ // copy all item files
  PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
    READ_BYTE 0x31 proficiency // read the byte containing weapon proficiency type
    PATCH_IF (proficiency == 102) BEGIN // quarterstaff
      WRITE_BYTE 0x1b (THIS BOR 0b00000010) // set flag for toggle critical hit aversion
    END
  END
  BUT_ONLY_IF_IT_CHANGES

However, as far as I'm aware, that flag doesn't have anything to do with backstabs.  It has to do with changing whether helmets and other items prevent critical hits or not. You can probably achieve what you want by adding an effect to the items (opcode #263) that sets the wielder's backstab multiplier to x1.

 

 

2)

 

For the weapprof.2da patching, it's mostly a matter of keeping track of how you count the rows and columns and the effect of the required column count parameter.

 

We will be using a required column count of 0, which has the effect of starting counting from the first row of the file ("2DA V1.0").  If you wanted to start counting from the first row of data ("LARGE_SWORD..."), you would use a required column count equal to the number of columns in the largest row (determined by performing COUNT_COLS).

 

Here is your code with just the values fixed.

COPY_EXISTING ~weapprof.2da~ override
  COUNT_2DA_COLS cols
  FOR (col = 4; col < cols; ++col) BEGIN
    READ_2DA_ENTRY 34 col 0 val
    PATCH_IF (val == 3) BEGIN
      SET_2DA_ENTRY 34 col 0 2
    END
  END

This method can be slow if you are performing a large number of operations dealing with a large file, since each call to READ_2DA_ENTRY and SET_2DA_ENTRY involves parsing the text.

 

To avoid this, you can instead use READ_2DA_ENTRIES_NOW and SET_2DA_ENTRIES_LATER, which perform all the reads at once and all the sets at once.

COPY_EXISTING ~weapprof.2da~ override
  COUNT_2DA_COLS cols
  READ_2DA_ENTRIES_NOW r2en_weapprof 0
  FOR (col = 4; col < cols; ++col) BEGIN
    READ_2DA_ENTRY_FORMER r2en_weapprof 34 col val
    PATCH_IF (val == 3) BEGIN
      SET_2DA_ENTRY_LATER s2el_weapprof 34 col 2
    END
  END
  SET_2DA_ENTRIES_NOW s2el_weapprof 0


#3 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 24 February 2018 - 07:41 PM

 

1)

 

I assume you're talking about this tutorial.  This code should work for setting the flag to toggle critical hit aversion.

COPY_EXISTING_REGEXP GLOB ~^.+\.itm$~ ~override~ // copy all item files
  PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
    READ_BYTE 0x31 proficiency // read the byte containing weapon proficiency type
    PATCH_IF (proficiency == 102) BEGIN // quarterstaff
      WRITE_BYTE 0x1b (THIS BOR 0b00000010) // set flag for toggle critical hit aversion
    END
  END
  BUT_ONLY_IF_IT_CHANGES

However, as far as I'm aware, that flag doesn't have anything to do with backstabs.  It has to do with changing whether helmets and other items prevent critical hits or not. You can probably achieve what you want by adding an effect to the items (opcode #263) that sets the wielder's backstab multiplier to x1.

 

Thanks, greatly.  Although this opens a new can of worms.  How do I add that Item Effect (I know how how to create the proper opcode and effect, manually) via weidu patching? I assume a good deal of the code would be the same:

 

COPY_EXISTING_REGEXP "^.+\.itm" override

  PATCH_IF (SOURCE_SIZE > 0x71) THEN BEGIN

    READ_SHORT 0x31 weaprof

              PATCH_IF (weaprof = 102) BEGIN

                [???]

    END

  END

  BUT_ONLY_IF_IT_CHANGES

 

But what would the code in [???] be to blanket patch something that isn't a binary toggle?



#4 Mike1072

Mike1072
  • Gibberling Poobah
  • 2487 posts
  • Gender:Male
  • Location:Canada

Posted 24 February 2018 - 11:38 PM

There are functions that can handle that.

LPF ~ADD_ITEM_EQEFFECT~
  INT_VAR 
    opcode = 263
    target = 1
    timing = 2
    parameter1 = 1
    parameter2 = 1
END


#5 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 26 February 2018 - 02:00 PM

The last thing I need to do at the moment is finish coding a function that will append an ability to all Ranger Clab files, and do so for any kits added.

 

At the moment I use this to account for the base class

 

ACTION_FOR_EACH ~file~ IN
              ~clabrn01~
BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%file%.2da~ BEGIN
    APPEND ~%file%.2da~ ~ABILITYXT AP_XTRNGOF~ UNLESS ~ABILITYXT~
  END
END
 
But I can't manage to figure out how to put together the code that will read the ranger kitlist and then "Append" to all the relevant Clab files.
 
Examining a few other mods, I imagine part of it (the read part) could function like:
 
COPY_EXISTING ~kitlist.2da~ ~override~
  COUNT_2DA_COLS cols
  READ_2DA_ENTRIES_NOW ~r2en_kitlist~ cols
  FOR (row = 2; row < r2en_kitlist; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 [?]
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 8 class_num
    PATCH_IF (class_num == 12) OR (class_num == 18) BEGIN // rangers
      DEFINE_ASSOCIATIVE_ARRAY d5_rangers_array BEGIN "%[?]%" => "%class_num%" END
    END
    END
  END
BUT_ONLY
 
But the [?] parts I'm unsure about, nor do I know how to make the proper "connections" between the read function and the Append code.


#6 subtledoctor

subtledoctor
  • Modders
  • 2775 posts
  • Gender:Male

Posted 27 February 2018 - 04:49 AM

[?] should just be another variable, which stores the .2da clab filename of each kit. So, you could call it "2da_name" or something. Then,

DEFINE_ASSOCIATIVE_ARRAY rangers_array BEGIN "%2da_name%" => 1 END

Now you have an array containing the clab table of every ranger kit, except CLABRN01. (All arrays have associated vslues, but in this case you don't need it, sonyou can set it to 1 and ignore it.) Then:
ACTION_PHP_EACH ranger_kit AS clab => blah BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%clab%.2da~ BEGIN
    APPEND ~%clab%.2da~ ~stuff~
  END
END
Also you don't need the ACTION_FOR_EACH for CLABRN01 since there's only one.

Faiths & Powers: Spell spheres and kit pack for priests and paladins
Might & Guile: Tweaks and kits for warriors and rogues
Scales of Balance: Game tweaks and rule overhauls
NPC_EE: More options for NPCs in BGEE, SoD, & BG2EE


#7 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 27 February 2018 - 10:45 AM

[?] should just be another variable, which stores the .2da clab filename of each kit. So, you could call it "2da_name" or something. Then,

DEFINE_ASSOCIATIVE_ARRAY rangers_array BEGIN "%2da_name%" => 1 END

Now you have an array containing the clab table of every ranger kit, except CLABRN01. (All arrays have associated vslues, but in this case you don't need it, sonyou can set it to 1 and ignore it.) Then:

ACTION_PHP_EACH ranger_kit AS clab => blah BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%clab%.2da~ BEGIN
    APPEND ~%clab%.2da~ ~stuff~
  END
END
Also you don't need the ACTION_FOR_EACH for CLABRN01 since there's only one.

 

 

I can't get anything following this:

 

COPY_EXISTING ~kitlist.2da~ ~override~
  COUNT_2DA_COLS cols
  READ_2DA_ENTRIES_NOW ~r2en_kitlist~ cols
  FOR (row = 2; row < r2en_kitlist; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 class_ab
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 8 class_num
    PATCH_IF (class_num == 12) OR (class_num == 18) BEGIN // rangers
      DEFINE_ASSOCIATIVE_ARRAY d5_rangers_array BEGIN "%class_ab%" => "%class_num%" END
    END
  END
BUT_ONLY
 
. . .to work. Perhaps I'm mistaken about "blah".
 
I used this following it:
 
ACTION_PHP_EACH ranger_kit AS clab => %class_num% BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%clab%.2da~ BEGIN
    APPEND ~%clab%.2da~ ~ABILITYXT AP_XTRNGOF~ UNLESS ~ABILITYXT~
  END
END
 
But nothing was patched.

Edited by Reddbane, 27 February 2018 - 10:46 AM.


#8 subtledoctor

subtledoctor
  • Modders
  • 2775 posts
  • Gender:Male

Posted 27 February 2018 - 02:10 PM

Change " %class_num% " to " blah " - or literally any word. But not a variable.

A few things are going on here:

1) You iterate through the rows of kitlist.2da, reading the values in comumns 5 & 8 into variables (%class_ab% and %class_num%).

2) Those variables are used over and over for each row; before they take a new value from the next row, their content is deposited into an array. So you end up with an array that, if you print it, would look a lot like kitlist.2da, if every column except 5 & 8 were removed.

Now, forget those variables completely. They have served their purpose.

3) Now we want to iterate through the array. The ACTION_PHP_EACH command takes two strings ("clab => blah") that operate like variables to represent the values in each "column" of the array. You go through a process similar to the above: as you iterate through each row of the array, the contents of that row populate those variables, and you can do something with them. Then the content is discarded and the variables are filled by the content of the next row, etc.

Faiths & Powers: Spell spheres and kit pack for priests and paladins
Might & Guile: Tweaks and kits for warriors and rogues
Scales of Balance: Game tweaks and rule overhauls
NPC_EE: More options for NPCs in BGEE, SoD, & BG2EE


#9 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 27 February 2018 - 03:37 PM

A new problem arose, unrelated to weidu, involving using the opcode 233 (Modify proficiencies) on an item as a effect.

 

I tried adding this item effect to Montolio's Cloak:
 
Type: Modify proficiencies (233)
Target: Self (1)
Power: 0
# stars: Active class: 4, Original class: 0
Proficiency: PROFICIENCY2WEAPON - 114
Behavior: Set if higher (0)
Timing mode: Instant/While equipped - 2
Dispel/Resistance: Natural/Nonmagical (0)
Duration: 0
Probability 1: 100
Probability 2: 0
Unused: 00 00 00 00 00 00 00 00 h
# dice thrown/maximum level: 0
Dice size/minimum level: 0
Save type: ( No save )
Save bonus: 0
Special: 0
 
What it should do is raise "Two weapon Style" to 4 pips (for reference, I added a functional 4th level to 2 Weapon style), while the item is equipped. But for some reason this does not seem to work. The code itself is based on some of Wiemar's items which increase proficiency values with weapons.
Does anyone know why this is not working?
To clear out some obvious answers, the 4th level of "Two weapon Style" works properly if given to a character via EEkeeper, and opcode (233) does apparently work with "Two weapon Style", as applying it as an effect in EEkeeper to a character does produce the desired effect (4 pips in Two Weapon style).
 
Anyone?


#10 Jarno Mikkola

Jarno Mikkola

    The Imp

  • Modders
  • 6792 posts
  • Gender:Male
  • Location:The town where the dead haven't keeled over, yet. In Finland.

Posted 27 February 2018 - 04:35 PM

You are trying to apply the above to EE game ? Asking cause the weapon styles won't be editablein the non-EE  game. And have you tried to use a different timing mode, cause ... the while equipped might not work on opcode 233.


Welcome to the sanity, you are free to search for the limit, it's out there, we drew it in the sand.
Here's how to install all the ... mods you ever really could want to Infinity Engine games. I removed the stable word from there as Roxanne began to add BS mods that are likely to break compatibility from the BWS.

#11 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 27 February 2018 - 06:08 PM

You are trying to apply the above to EE game ? Asking cause the weapon styles won't be editablein the non-EE  game. And have you tried to use a different timing mode, cause ... the while equipped might not work on opcode 233.

 

Yes it is EE and the code does work when equipped, sometimes.  The code itself is based off of one of Weimar's clubs that changes club proficiency to 5.  Interestingly when it is set to Clubs, it works.



#12 subtledoctor

subtledoctor
  • Modders
  • 2775 posts
  • Gender:Male

Posted 27 February 2018 - 07:02 PM

One last note before moving on: the kit clab thing can be done in any number of ways, not all of which require the two-step process of creating an array and then doing actions based on the contents of that array.  With INNER_ACTION you can do the work from right inside the kitlist COPY operation:

COPY_EXISTING ~kitlist.2da~ ~override~
  COUNT_2DA_COLS cols
  READ_2DA_ENTRIES_NOW ~r2en_kitlist~ cols
  FOR (row = 2; row < r2en_kitlist; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 class_ab
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 8 class_num
    PATCH_IF (class_num == 12) OR (class_num == 18) BEGIN  // rangers
      INNER_ACTION BEGIN
        APPEND ~%class_ab%.2da~ ~ABILITYXT AP_XTRNGOF~ UNLESS ~ABILITYXT~
      END
    END
  END
BUT_ONLY

(I think you also had too any ENDs in your earlier code, which might have been screwing it up.)  So you ask, why deal with those arrays?  The answer is simply that I figured out how to do it, and implemented those arrays, before I knew about INNER_ACTION.  :p  And now I'm operating according to the principle of "if it ain't broke, don't fix it."

 

As for opcode 233: I use it with 'while equipped' timing extensively, including using it to increment proficiencies unrelated to the one used by the weapon with the equipping effect.  So the opcode definitely works. 

 

This might sounds weird, but how do you know it doesn't work?  Are you testing it in some way?  Maybe apply a 326 effect that requires 4 stars in dual-wielding, and seeing if it fires?  Or are you just looking at the character record screen?  If the latter, it could just be a proficiency-display quirk.  The game only expects you to have 3 stars, so it might not bother displaying anything higher than that.  Meaning, the effect may be working perfectly well.


Faiths & Powers: Spell spheres and kit pack for priests and paladins
Might & Guile: Tweaks and kits for warriors and rogues
Scales of Balance: Game tweaks and rule overhauls
NPC_EE: More options for NPCs in BGEE, SoD, & BG2EE


#13 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 28 February 2018 - 09:23 AM

One last note before moving on: the kit clab thing can be done in any number of ways, not all of which require the two-step process of creating an array and then doing actions based on the contents of that array.  With INNER_ACTION you can do the work from right inside the kitlist COPY operation:

COPY_EXISTING ~kitlist.2da~ ~override~
  COUNT_2DA_COLS cols
  READ_2DA_ENTRIES_NOW ~r2en_kitlist~ cols
  FOR (row = 2; row < r2en_kitlist; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 class_ab
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 8 class_num
    PATCH_IF (class_num == 12) OR (class_num == 18) BEGIN  // rangers
      INNER_ACTION BEGIN
        APPEND ~%class_ab%.2da~ ~ABILITYXT AP_XTRNGOF~ UNLESS ~ABILITYXT~
      END
    END
  END
BUT_ONLY

(I think you also had too any ENDs in your earlier code, which might have been screwing it up.)  So you ask, why deal with those arrays?  The answer is simply that I figured out how to do it, and implemented those arrays, before I knew about INNER_ACTION.  :p  And now I'm operating according to the principle of "if it ain't broke, don't fix it."

 

As for opcode 233: I use it with 'while equipped' timing extensively, including using it to increment proficiencies unrelated to the one used by the weapon with the equipping effect.  So the opcode definitely works. 

 

This might sounds weird, but how do you know it doesn't work?  Are you testing it in some way?  Maybe apply a 326 effect that requires 4 stars in dual-wielding, and seeing if it fires?  Or are you just looking at the character record screen?  If the latter, it could just be a proficiency-display quirk.  The game only expects you to have 3 stars, so it might not bother displaying anything higher than that.  Meaning, the effect may be working perfectly well.

 

I know it is not working because I made "Two weapon Style" 1-3 pips have a -2 damage penalty to the offhand, while 4 pips has none.  If I add the 4 pips manually (via eekeeper) it works, that is the offhand damage penalty disappears.  For some reason, however, If I try to apply the 4 pips via opcode 233 (via an item) it does not work.  The item effect code seems to properly function, however, if I change the "Proficiency:" line to a weapon (like clubs) the item applies the pips. ???



#14 subtledoctor

subtledoctor
  • Modders
  • 2775 posts
  • Gender:Male

Posted 28 February 2018 - 10:21 AM

Wild speculation: perhaps STYLBONU.2da looks for any effects on your character that match the number of stars in one of its rows. If you have two stars in DW and the cloak sets it at 4 stars, that permanent effect setting you to 2 stars is still there. Maybe the engine checks for that and it returns "true", and then it applies the bonus/penalty on that row of the .2da file.

You can't reduce proficiencies (either permanently or temporarily) and you can't cancel ones chosen at level-up (either permanently or temporarily), so if my wild speculation is true, there's no workaround that I can see :(

Of course you could simply give the cloak equipping effects that offset the penalties; that would be a simpler way to do it.

Faiths & Powers: Spell spheres and kit pack for priests and paladins
Might & Guile: Tweaks and kits for warriors and rogues
Scales of Balance: Game tweaks and rule overhauls
NPC_EE: More options for NPCs in BGEE, SoD, & BG2EE


#15 Reddbane

Reddbane
  • Members
  • 40 posts

Posted 28 February 2018 - 12:47 PM

I changed behavior to increment, (+2) which sets the wearer to 4, which works for my purposes.

So now the item effect works.





Reply to this topic



  



Also tagged with one or more of these keywords: Question, Code, Weidu, Patching

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users