Jump to content

Toss your semi-useful WeiDU macros here


Recommended Posts

The majority of my own functions and macros are too specific to be of (general) use. But there is a small number of functions that might be helpful.

 

TO_HEX_NUMBER:

A decimal to hexadecimal number converter. May be useful when dealing with IDS or INI files.

 

 

/**
 * Patch function. Converts any decimal number into a hexadecimal number.
 * INT_VAR value      The decimal number to convert.
 * INT_VAR minDigits  Minimum number of digits for the returned hex value. (default: 1)
 * INT_VAR prefix     A flag that indicates whether the returned number will be prefixed with "0x". (default: 0)
 * RET hexNumber      The converted hexadecimal number as string.
 */
DEFINE_PATCH_FUNCTION TO_HEX_NUMBER
INT_VAR
  value     = 0
  minDigits = 1
  prefix    = 0
RET
  hexNumber
BEGIN
  SET minDigits = (minDigits < 1) ? 1 : minDigits
  SET minDigits = (minDigits > 8) ? 8 : minDigits
  TEXT_SPRINT hexNumber ~~
  PATCH_DEFINE_ARRAY digit BEGIN ~0~ ~1~ ~2~ ~3~ ~4~ ~5~ ~6~ ~7~ ~8~ ~9~ ~a~ ~b~ ~c~ ~d~ ~e~ ~f~ END

  PATCH_IF (value < 0) BEGIN
    SET signed = 1
    SET value = 0 - value
  END ELSE BEGIN
    SET signed = 0
  END

  WHILE (value != 0) BEGIN
    SET curDigit = value BAND 0xf
    SET value = value BLSR 4
    TEXT_SPRINT hexDigit $EVAL digit(~%curDigit%~)
    TEXT_SPRINT hexNumber ~%hexDigit%%hexNumber%~
  END

  WHILE (STRING_LENGTH ~%hexNumber%~ < minDigits) BEGIN
    TEXT_SPRINT hexNumber ~0%hexNumber%~
  END

  PATCH_IF (prefix) BEGIN
    TEXT_SPRINT hexNumber ~0x%hexNumber%~
  END

  PATCH_IF (signed) BEGIN
    TEXT_SPRINT hexNumber ~-%hexNumber%~
  END
END

// Action version of TO_HEX_NUMBER
DEFINE_ACTION_FUNCTION TO_HEX_NUMBER
INT_VAR
  value     = 0
  minDigits = 1
  prefix    = 0
RET
  hexNumber
BEGIN
  OUTER_PATCH ~~ BEGIN
    LPF TO_HEX_NUMBER INT_VAR value = value minDigits = minDigits prefix = prefix RET hexNumber END
  END
END

 

FIND_FREE_ANIM_SLOT:

This function attempts to find a free creature animation slot in a given range, so that it can be used to install custom creature animations. I'm using it quite extensively in my Golem Construction mod (example code). This function requires EE games patched to v1.4 or higher. It also makes use of the function TO_HEX_NUMBER mentioned above.

 

 

// Internally used: Animation slots reserved by vanilla or mod-added game creatures (in hexadecimal format)
// Mods with fixed animation slots that are currently considered:
// - Bearwalker + extended Werebear animation
// - Pack Mule
OUTER_TEXT_SPRINT animationSlots ~"0410" "1000" "1003" "1004" "1100" "1101" "1102" "1103" "1104" "1105" "1200" "1201" "1202" "1203" "1204" "1205" "1206" "1207" "1208" "1300" "2000" "2100" "2200" "2300" "3000" "3001" "4000" "4001" "4002" "4010" "4012" "4100" "4101" "4102" "4110" "4112" "4200" "4300" "4400" "4410" "4500" "4600" "4700" "4710" "4800" "5000" "5001" "5002" "5003" "5010" "5011" "5012" "5013" "5100" "5101" "5102" "5103" "5110" "5111" "5112" "5113" "5200" "5201" "5202" "5210" "5211" "5212" "5300" "5301" "5302" "5303" "5310" "5311" "5312" "5313" "6000" "6001" "6002" "6003" "6004" "6005" "6010" "6011" "6012" "6013" "6014" "6015" "6100" "6101" "6102" "6103" "6104" "6105" "6110" "6111" "6112" "6113" "6114" "6115" "6200" "6201" "6202" "6204" "6205" "6210" "6211" "6212" "6214" "6215" "6300" "6301" "6302" "6303" "6304" "6305" "6310" "6311" "6312" "6313" "6314" "6315" "6400" "6401" "6402" "6403" "6404" "6405" "6406" "6500" "6510" "6621" "7000" "7001" "7100" "7101" "7200" "7201" "7202" "7203" "7300" "7301" "7302" "7310" "7311" "7312" "7313" "7314" "7320" "7321" "7400" "7401" "7402" "7500" "7501" "7600" "7601" "7602" "7603" "7604" "7700" "7701" "7702" "7703" "7800" "7801" "7802" "7900" "7901" "7902" "7903" "7904" "7a00" "7a01" "7a02" "7a03" "7a04" "7b00" "7b01" "7b02" "7b03" "7b04" "7b05" "7b06" "7c00" "7c01" "7d00" "7d01" "7d02" "7d03" "7d04" "7d05" "7d06" "7d07" "7d08" "7e00" "7e01" "7f00" "7f01" "7f02" "7f03" "7f04" "7f05" "7f06" "7f07" "7f08" "7f09" "7f0a" "7f0b" "7f0c" "7f0d" "7f0e" "7f0f" "7f10" "7f11" "7f12" "7f13" "7f14" "7f15" "7f16" "7f17" "7f18" "7f19" "7f20" "7f21" "7f22" "7f23" "7f24" "7f27" "7f28" "7f29" "7f2a" "7f2b" "7f2c" "7f2d" "7f2e" "7f2f" "7f30" "7f31" "7f32" "7f33" "7f34" "7f35" "7f36" "7f37" "7f38" "7f39" "7f3a" "7f3b" "7f3c" "7f3d" "7f3e" "7f3f" "7f40" "7f41" "7f42" "7f43" "7f44" "7f45" "7f46" "7f47" "7f48" "7f49" "7f4a" "7f4b" "7f4c" "7f4d" "7f4e" "7f4f" "7f50" "7f51" "7f52" "7f53" "7f54" "7f55" "7f56" "7f57" "7f58" "7f59" "7f5a" "7f5b" "7f5c" "7f5d" "7f5e" "7f5f" "7f60" "7f61" "7f62" "8000" "8100" "8200" "9000" "a000" "a100" "a200" "a201" "a202" "b000" "b100" "b200" "b210" "b300" "b310" "b400" "b410" "b500" "b510" "b600" "b610" "b700" "c000" "c100" "c200" "c300" "c400" "c500" "c600" "c610" "c700" "c710" "c800" "c810" "c900" "c910" "ca00" "ca10" "cb00" "cc00" "cc01" "cc02" "cc04" "d000" "d100" "d200" "d300" "d400" "e000" "e010" "e020" "e040" "e050" "e060" "e070" "e080" "e090" "e0a0" "e0b0" "e0c0" "e0d0" "e0e0" "e0f0" "e0f1" "e0f2" "e200" "e210" "e220" "e230" "e240" "e241" "e242" "e243" "e244" "e245" "e246" "e247" "e248" "e249" "e24a" "e24b" "e24c" "e24d" "e24e" "e24f" "e250" "e251" "e252" "e253" "e254" "e255" "e256" "e257" "e258" "e259" "e25a" "e25b" "e25c" "e25d" "e25e" "e25f" "e260" "e261" "e262" "e263" "e264" "e265" "e266" "e267" "e26a" "e26b" "e26d" "e26e" "e26f" "e270" "e271" "e272" "e273" "e274" "e276" "e279" "e27d" "e27e" "e27f" "e280" "e281" "e282" "e283" "e288" "e289" "e28a" "e28b" "e28c" "e28d" "e28e" "e28f" "e290" "e291" "e292" "e293" "e294" "e300" "e310" "e320" "e330" "e400" "e410" "e420" "e430" "e440" "e441" "e442" "e443" "e444" "e500" "e510" "e520" "e600" "e610" "e6fe" "e700" "e710" "e720" "e800" "e810" "e820" "e830" "e840" "e900" "e910" "ea00" "ea10" "ea20" "eb00" "eb10" "eb20" "ec00" "ec10" "ec20" "ed00" "ed10" "ed20" "ee00" "ee10" "ef10" "f000" "f001" "f002" "f003" "f004" "f005" "f006" "f007" "f008" "f009" "f00a" "f00b" "f00c" "f00d" "f00e" "f00f" "f010" "f011" "f012" "f013" "f014" "f015" "f016" "f017" "f018" "f019" "f01a" "f01b" "f01c" "f01d" "f01e" "f01f" "f020" "f021" "f022" "f023" "f024" "f025" "f026" "f027" "f028" "f029" "f02a" "f02b" "f02c" "f02d" "f02e" "f02f" "f030" "f031" "f032" "f033" "f034" "f035" "f036" "f037" "f038" "f039" "f03a" "f03b" "f03c" "f03d" "f03e" "f03f" "f040" "f041" "f042" "f043" "f044" "f045" "f046" "f047" "f048" "f049" "f04a" "f04b" "f04c" "f04d" "f04e" "f04f" "f050" "f051" "f052" "f053" "f054" "f055" "f056" "f057" "f058" "f059" "f05a" "f05b" "f05c" "f05d" "f05e" "f05f" "f060" "f061" "f062" "f100" "f101" "f22e" "f80e"~

/**
 * Patch function. Returns the first free creature animation slot in the range defined by slotMin and slotMax.
 * INT_VAR slotMin    Lowest available creature animation slot for the animation, inclusive. (Default: 0)
 * INT_VAR slotMax    Highest available creature animation slot for the animation, exclusive.
 *                    (Default: highest value for slot type indicated by "slotMin")
 * INT_VAR slotSteps  How many slots to skip after each iteration, starting from slotMin.
 *                    Setting this parameter is useful if compatible animation slots are always 
 *                    a fixed distance apart (e.g. at a distance of 0x10 each). (Default: 1)
 * RET slot           A free animation slot. Returns -1 if none are found in the given range.
 */
DEFINE_PATCH_FUNCTION FIND_FREE_ANIM_SLOT
INT_VAR
  slotMin   = 0
  slotMax   = (slotMin BAND 0xf000) + 0x1000
  slotSteps = 1
RET
  slot
BEGIN
  SET slot = "-1"
  SET slotSteps = (slotSteps < 1) ? 1 : slotSteps
  SET slotMin = (slotMin < 0) ? 0 : slotMin
  SET slotMax = (slotMax < 0) ? 0 : slotMax
  PATCH_IF (slotMax < slotMin) BEGIN
    SET tmp = slotMin
    SET slotMin = slotMax
    SET slotMax = tmp
  END

  INNER_PATCH ~%animationSlots%~ BEGIN
    FOR (idx = slotMin; idx < slotMax; idx += slotSteps) BEGIN
      LOOKUP_IDS_SYMBOL_OF_INT name ~animate~ idx
      PATCH_IF (~%name%~ STR_EQ ~%idx%~) BEGIN
        LPF TO_HEX_NUMBER INT_VAR value = idx minDigits = 4 RET hexNumber END
        PATCH_IF (NOT FILE_EXISTS_IN_GAME ~%hexNumber%.ini~ AND 
                  ~%slotList%~ STRING_CONTAINS_REGEXP ~"%hexNumber%"~ != 0) BEGIN
          SET slot = idx
          SET idx = slotMax
        END
      END
    END
  END
END

// Action version of FIND_FREE_ANIM_SLOT
DEFINE_ACTION_FUNCTION FIND_FREE_ANIM_SLOT
INT_VAR
  slotMin   = 0
  slotMax   = (slotMin BAND 0xf000) + 0x1000
  slotSteps = 1
RET
  slot
BEGIN
  OUTER_PATCH ~~ BEGIN
    LPF FIND_FREE_ANIM_SLOT
    INT_VAR
      slotMin = slotMin
      slotMax = slotMax
      slotSteps = slotSteps
    RET
      slot
    END
  END
END

 

Link to comment
TO_HEX_NUMBER:

A decimal to hexadecimal number converter. May be useful when dealing with IDS or INI files.

there is actually a hidden SPRINTF command in weidu that can do it. Example:

SET dec_value = 3
SPRINTF hex_value ~%x~ (dec_value)
PATCH_PRINT ~%hex_value%~
Edited by K4thos
Link to comment

You're right. There is a (patch-only) SPRINTF command available which supports %s, %d and %x format specifiers. However, the command doesn't properly convert negative values into hexadecimal format, always prefixes the result with "0x" and you can't specify minimum number of digits, which forces me to do a lot of editing either way for my purposes.

Link to comment
FIND_FREE_ANIM_SLOT:

This function attempts to find a free creature animation slot in a given range, so that it can be used to install custom creature animations. I'm using it quite extensively in my Golem Construction mod (example code). This function requires EE games patched to v1.4 or higher. It also makes use of the function TO_HEX_NUMBER mentioned above.

Ah, if only I knew how to create new animations and add them to the game. It's been a long-time wish of mine to add griffins, (black) unicorns and nightmares, to name but a few. :-)
Link to comment

 

FIND_FREE_ANIM_SLOT:

This function attempts to find a free creature animation slot in a given range, so that it can be used to install custom creature animations. I'm using it quite extensively in my Golem Construction mod (example code). This function requires EE games patched to v1.4 or higher. It also makes use of the function TO_HEX_NUMBER mentioned above.

Ah, if only I knew how to create new animations and add them to the game. It's been a long-time wish of mine to add griffins, (black) unicorns and nightmares, to name but a few. :-)

 

 

Sorry for the off-topic, but you won't have to wait too long, at least for unicorns (regular and black ones) and nightmares. ;)

Edited by Gwendolyne
Link to comment

 

 

FIND_FREE_ANIM_SLOT:

This function attempts to find a free creature animation slot in a given range, so that it can be used to install custom creature animations. I'm using it quite extensively in my Golem Construction mod (example code). This function requires EE games patched to v1.4 or higher. It also makes use of the function TO_HEX_NUMBER mentioned above.

Ah, if only I knew how to create new animations and add them to the game. It's been a long-time wish of mine to add griffins, (black) unicorns and nightmares, to name but a few. :-)

 

 

Sorry for the off-topic, but you won't have to wait too long, at least for unicorns (regular and black ones) and nightmares. ;)

 

 

Interesting, I will certainly keep an eye on that. Please tell me they will work with non-EE games as well! And I'd pay you to make a griffin animation. (Seriously, I would.)

Link to comment

End of the off-topic : my mod is written for BG2 and BGT and will be EE compatible. ;)

The ironic point is that I can use huge tarasque animations (640x640 px) with IA but not in BG2:EE because the enhanced dragon animation format seems to be buggy and does not allow to add new effective slots to ANIMATE.IDS.

Link to comment

argent77 just posted a WeiDU function to to fetch a journal strref here. Thinking about all the instances where original game journal entries need to be erased by a mod which only works for exact matching strings but BGT / EET not having them at specified reference numbers, this is very cool to use especially across game platforms.

Edited by jastey
Link to comment
but BGT / EET not having them at specified reference numbers

 

actually EET handles BG1 strrefs in a static way. SAY is not used at all during installation. You can reference correct journal number by simply adding 200000 to the original strrefs. For example BG1 strrefs 27091 is 227091 in EET and that's always true regardless of mods you install before/after it.

Link to comment

the function is extremely useful, indeed. Even BG2 Fixpack 'Game Text Update' can brake journal erasing in mods that use exact match approach (and there are 2 versions of this component if I remember correctly). Then there is a problem with translation of strings (I remember tons of issues with erasing journal in Polish version of some older mods - most likely because translator didn't even know that the text was meant to be copied directly from TLK file rather than translated from scratch).

 

Now I feel silly since I never thought about looking what IESDP has to say about DLG format (which turns out can be looped through like any other BG file format). For some reason I always considered it as a text file while decompiled and unreadable gibberlish after compiling :p

Edited by K4thos
Link to comment

Now I feel silly since I never thought about looking what IESDP has to say about DLG format (which turns out can be looped through like any other BG file format). For some reason I always considered it as a text file while decompiled and unreadable gibberlish after compiling :p

 

 

You can loop through states and transitions. Here is a homemade function used to extend existing dlg:

 

 

 

DEFINE_PATCH_FUNCTION ~GW_FIND_DLG_RESPONSE_STRING~
    INT_VAR GW_string_dlg = 0    // string we are looking for
    RET     GW_transition_found  // Y = strref found
            GW_state_number
            GW_transition_number
BEGIN

    SET GW_transition_number = "-99"
    SET GW_state_number = "-99"
    SPRINT GW_transition_found "N"
    READ_LONG 0x08 GW_numstates              // Number of states
    READ_LONG 0x0c GW_offstates              // Offset of state table from start of file
    READ_LONG 0x10 GW_numresponse            // Number of transitions
    READ_LONG 0x14 GW_offresponse            // Offset of transition table from start of file
    FOR (state = 0 ; state < GW_numstates ; ++state) BEGIN
        PATCH_IF ("%GW_transition_found%" STRING_COMPARE_CASE "Y") BEGIN
            READ_LONG ("%GW_offstates%" +       (state * 0x10)) GW_state_string          // Actor response text (i.e. what the non-player character says to the party)
            READ_LONG ("%GW_offstates%" + 0x4 + (state * 0x10)) GW_index_first_response  // Index of the first transition corresponding to this state (i.e. the index in the transition table of the first potential response the party can make in this state).
            READ_LONG ("%GW_offstates%" + 0x8 + (state * 0x10)) GW_state_num_response    // Number of transitions corresponding to this state (i.e. how many possible responses are there to this state). A consecutive range of transitions in the transition table are assigned to this state, starting from 'first', as given by the previous field, ranging up to (but not including) 'first'+'count'.
            FOR (response = 0 ; response < GW_state_num_response ; ++response) BEGIN
                READ_LONG ("%GW_offresponse%" + 0x4 + ("%GW_index_first_response%" * 0x20) + (response * 0x20)) GW_response_string
                PATCH_IF (GW_response_string = GW_string_dlg) BEGIN
                    SET GW_transition_number = response
                    SET GW_state_number = state
                    SPRINT GW_transition_found "Y"
                END
            END    // of Looping through responses
        END        // PATCH_IF ("%GW_transition_found%" STRING_COMPARE_CASE "Y")
    END            // of Looping through states

END                // of DEFINE_PATCH_FUNCTION

 

 

 

Then:

COPY_EXISTING - ~UHOGRE01.dlg~ ~override~
    PATCH_IF (SOURCE_SIZE > 0x2f) THEN BEGIN    // protects against invalid files

    // #33324 ~J'ai surtout décidé de mettre un terme à ton ignoble existence, sale monstre !~
    // EN = ~I've actually decided to end your monstrous existence, creature!~
        LPF ~GW_FIND_DLG_RESPONSE_STRING~ INT_VAR GW_string_dlg = 33324 RET GW_transition_found GW_state_number GW_transition_number END
        PATCH_IF ("%GW_transition_found%" STRING_EQUAL "Y") AND (GW_transition_number != "-99") BEGIN
            SET UHOGRE01_Transition16 = GW_transition_number
            SET UHOGRE01_State16 = GW_state_number
        END

    END    // of PATCH_IF (SOURCE_SIZE > 0x2f)
BUT_ONLY

And actually in the d file:

EXTEND_TOP UHOGRE01 %UHOGRE01_State16% #%UHOGRE01_Transition16%
    + ~Global("GWChevaucheuseKit","GLOBAL",2) Global("GWLyrielUmar","LOCALS",0)~ + @11100501 GOTO UhOgre01_Question    // ~D'abord, j'aimerais que tu répondes à une question, Madulf.~
END

 

 

 

 

 

Link to comment

Off topic, but have to ask, what's the difference ?

PATCH_IF plah THEN BEGIN

...

PATCH_IF plah BEGIN

Edit: thanks for the conformation ... I write it too... but most of he time it's there cause of a copy-paste had it.

Edited by Jarno Mikkola
Link to comment

In WeiDU it seems: none!

 

But as I am far away from being a programmer, I learned the IF THEN condition way of codding at my beginnings, a long time ago. After many years of modding, I know that THEN is not mandatory in WeiDU code but... the force of habit: sometimes I write it, sometimes not... ;)

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