Jump to content

Photo

Toss your semi-useful WeiDU macros here


88 replies to this topic

#61 c4_angel

c4_angel
  • Modders
  • 55 posts
  • Gender:Male
  • Location:Shanghai, China

Posted 27 November 2017 - 02:15 PM

I may toss one here, but flawed I think.
 
Since TobEx expands the use of STATS.IDS to support new hard-coded stats and custom stats, this function aims ease-to-use and work in EE engine as well.
It should be used along with script trigger:
CheckStat(O:Object*,I:Value*,I:StatNum*Stats) for vanilla games (so ToBEx must be installed to make this happen) and CheckSpellState(O:Object*,I:State*splstate) for EE games.    
 
If anyone already have a better function to do this job please let me know.
 
Codes are here: https://github.com/S...unique_mark.tpa

Borrowed the FJ_SPL_ITM_REINDEX function for file correction, thanks to authors.
 

Function name: C4_FIND_STAT_SLOT and C4_ADD_UNIQUE_MARK

 

C4_FIND_STAT_SLOT is an action function, checks all creature/item/spell files in game which have effect using opcode #318 (vanilla game) or opcode #328 (EE game), also values in STATS.IDS or SPLSTATE.IDS, find an unused one from 501 to 32767, and append a line with an user defined "identifier"(requred). Return "available_stat" for further usage.

Spoiler

 

C4_ADD_UNIQUE_MARK is a patch function, calls C4_FIND_STAT_SLOT, and uses function CLONE_EFFECT to add an effect to creature/item/spell file with an user defined "identifier"(also requred), other parameters of the "match_" part are same with CLONE_EFFECT.

Spoiler

 

Take mage spell Blur for example:

Spoiler

 

Note the I:Value* must be fixed to 1, since CheckSpellState has no value parameter.


Edited by c4_angel, 22 December 2017 - 09:08 AM.


#62 kjeron

kjeron
  • Members
  • 118 posts

Posted 27 November 2017 - 02:36 PM

 

C4_FIND_STAT_SLOT is an action function, checks all creature/item/spell files in game which have effect using opcode #318 (vanilla game) or opcode #328 (EE game), also values in STATS.IDS or SPLSTATE.IDS, find an unused one from 501 to 32767, and append a line with an user defined "identifier"(requred). Return "available_stat" for further usage.

SPLSTATE values 256+ are set by the engine for other purposes. (STATS, Bardsong, Backstab, New Opcodes, some pulled straight from the EXE).

Setting them manually has no effect(mostly), but checking them is not reliable.



#63 c4_angel

c4_angel
  • Modders
  • 55 posts
  • Gender:Male
  • Location:Shanghai, China

Posted 27 November 2017 - 02:47 PM

 

 

C4_FIND_STAT_SLOT is an action function, checks all creature/item/spell files in game which have effect using opcode #318 (vanilla game) or opcode #328 (EE game), also values in STATS.IDS or SPLSTATE.IDS, find an unused one from 501 to 32767, and append a line with an user defined "identifier"(requred). Return "available_stat" for further usage.

SPLSTATE values 256+ are set by the engine for other purposes. (STATS, Bardsong, Backstab, New Opcodes, some pulled straight from the EXE).

Setting them manually has no effect(mostly), but checking them is not reliable.

 

I did test in my mod at 500+, no bug found by now, is there any range already found? 32767 is top...

 

And are there any reliable way?


Edited by c4_angel, 27 November 2017 - 03:01 PM.


#64 kjeron

kjeron
  • Members
  • 118 posts

Posted 27 November 2017 - 03:42 PM

There are two gaps of 32 splstates that I haven't been able to map, one at 1664-1695 and one at 4224-4255, and then several semi-random gaps beyond 6240(where it starts pulling from the EXE).

 

SPLSTATE  500, for example, is set by BIT4 of the RESISTFIRE stat.

496 is set by BIT0 of RESISTFIRE, 497 of BIT1, 498 by BIT2, 499 by BIT3, 501 by BIT5 502 by BIT6, 503 by BIT7, 504 by BIT 8, 510 by BIT14, 511 by BIT15, then 512 is BIT0 of RESISTCOLD, and it continues on.

 

There are some usable SPLSTATE ranges within the stats, as some stats cannot carry values other than zero or one (BIT0), leaving the other 15 bits open, such as HELD (1409-1439), PLYMORPHED (1441-1471), ENTANGLE (1473-1503), SANCTUARY (1505-1535), MINORGLOBE (1537-1567), SHIELDGLOBE (1569-1599), GREASE (1601-1631), and WEB (1633-1663).

 

I made a table of all this here, excluding the values above 6240, as it varies depending on game version.



#65 c4_angel

c4_angel
  • Modders
  • 55 posts
  • Gender:Male
  • Location:Shanghai, China

Posted 27 November 2017 - 09:40 PM

 

I made a table of all this here, excluding the values above 6240, as it varies depending on game version.

 

That's a great table. Thank you very much!

 

And I still may need help in two issues:

1. You mentioned "Spellstates 6240+ are dependent on the game campaign/version, read directly from specific offsets of the EXE. Pattern is 32(set) - 160(emtpy) - 32(set), and repeats semi-consistently up to the max (32767)". If I skip 6240-6271, use 6272-6431, then skip 6432-6463 ...etc, will function as expected?

 

2. Can I use splprot.2da to check them in script ? And how?



#66 kjeron

kjeron
  • Members
  • 118 posts

Posted 28 November 2017 - 04:22 AM

 

 

I made a table of all this here, excluding the values above 6240, as it varies depending on game version.

 

That's a great table. Thank you very much!

 

And I still may need help in two issues:

1. You mentioned "Spellstates 6240+ are dependent on the game campaign/version, read directly from specific offsets of the EXE. Pattern is 32(set) - 160(emtpy) - 32(set), and repeats semi-consistently up to the max (32767)". If I skip 6240-6271, use 6272-6431, then skip 6432-6463 ...etc, will function as expected?

 

2. Can I use splprot.2da to check them in script ? And how?

The semi-consistent part is that it occasionally has an extra multiple of 160 empty SPLSTATES between sets.  For example, BGSOD v2.3.67.3, starting from 6240, has:

3x(32 - 160 - 32) - 160 - 7x(32 - 160 - 32) - 1600 - (32 - 160 - 32) - (32 - 160 - 32) etc...

But I don't know if every game version has the same pattern off extra space or not.  I didn't go very far with it, other than to check from the other end (32767) to see if it was still in effect.  The second 32 of each such set has always had the exact same value though, 0x0000000a, using only bits 1 and 3.

 

SPLPROT only works in spells/items/projectiles, and comes with an entry for checking SPLSTATES, entry 110, using Parameter1 to specifcy the spellstate.

Scripts still have to use CheckSpellState().


Edited by kjeron, 28 November 2017 - 04:23 AM.


#67 c4_angel

c4_angel
  • Modders
  • 55 posts
  • Gender:Male
  • Location:Shanghai, China

Posted 28 November 2017 - 04:55 AM

 

 

 

I made a table of all this here, excluding the values above 6240, as it varies depending on game version.

 

That's a great table. Thank you very much!

 

And I still may need help in two issues:

1. You mentioned "Spellstates 6240+ are dependent on the game campaign/version, read directly from specific offsets of the EXE. Pattern is 32(set) - 160(emtpy) - 32(set), and repeats semi-consistently up to the max (32767)". If I skip 6240-6271, use 6272-6431, then skip 6432-6463 ...etc, will function as expected?

 

2. Can I use splprot.2da to check them in script ? And how?

The semi-consistent part is that it occasionally has an extra multiple of 160 empty SPLSTATES between sets.  For example, BGSOD v2.3.67.3, starting from 6240, has:

3x(32 - 160 - 32) - 160 - 7x(32 - 160 - 32) - 1600 - (32 - 160 - 32) - (32 - 160 - 32) etc...

But I don't know if every game version has the same pattern off extra space or not.  I didn't go very far with it, other than to check from the other end (32767) to see if it was still in effect.  The second 32 of each such set has always had the exact same value though, 0x0000000a, using only bits 1 and 3.

 

SPLPROT only works in spells/items/projectiles, and comes with an entry for checking SPLSTATES, entry 110, using Parameter1 to specifcy the spellstate.

Scripts still have to use CheckSpellState().

 

 

a little confused with the pattern, but try start from 32767 will be a good idea, thank you.



#68 CamDawg

CamDawg

    ALL GLORY TO THE HYPNOTOAD

  • Gibberling Poobah
  • 9684 posts
  • Gender:Not Telling

Posted 02 January 2018 - 04:57 PM

Here are a couple of macros to take advantage of some new EE features.

 

Opcode 331 can be used to randomly summon monsters off a custom 2da table as defined in smtables.2da. cd_new_summon_table, an action function, will add a new reference for you and then return the value for use in your spells:

DEFINE_ACTION_FUNCTION cd_new_summon_table
  STR_VAR descript = "foo"
          2da_file = "foo"
  RET     table
  BEGIN

  COPY_EXISTING ~smtables.2da~ ~override~
    COUNT_2DA_ROWS 2 count
    READ_2DA_ENTRY (count - 1) 0 2 table
    INNER_PATCH_SAVE table ~%table%~ BEGIN
      REPLACE_TEXTUALLY ~^\([0-9]+\).+$~ ~\1~
    END
    SET table += 1

  APPEND ~smtables.2da~ ~%table%_%descript% %2da_file%~

END

Sample usage:

LAF cd_new_summon_table STR_VAR descript = "Giant_insect" 2da_file = cdiinsct RET table END

ADD_SPELL ~iwdification/spl/cdid418.spl~ 1 4 CLERIC_GIANT_INSECT
  LPF ALTER_EFFECT INT_VAR match_opcode = 331 parameter2 = table END

This appends "XX_Giant_insect cdiinsct" (where XX is the next entry available on the table) to smtables.2da, and then allows you to use the variable 'table' to patch it into your opcode 331 calls. Note that it only adds the reference to the 2da file (cdiinsct in this case) and that you will still need to copy over the file yourself.

 

EE also supports new portrait icons, as defined in statdesc.2da. cd_new_portrait_icon, another action function, will find the next available entry and add your strref and bam file to the list.

DEFINE_ACTION_FUNCTION cd_new_portrait_icon
  INT_VAR string = 0
  STR_VAR bam_file = "****"
  RET     icon
  BEGIN

  COPY_EXISTING ~statdesc.2da~ ~override~
    COUNT_2DA_ROWS 3 count
    READ_2DA_ENTRY (count - 1) 0 3 icon
    SET icon += 1

  APPEND ~statdesc.2da~ ~%icon% %string% %bam_file%~

END

And a sample use case:

LAF cd_new_portrait_icon INT_VAR string = RESOLVE_STR_REF(@3070) STR_VAR bam_file = cdia422d RET icon END

ADD_SPELL ~iwdification/spl/cdia422.spl~ 2 4 WIZARD_BELTYNS_BURNING_BLOOD
  LPF ALTER_EFFECT INT_VAR match_opcode = 142 match_parameter2 = 66 parameter2 = icon END

This will add "XX YY cdia422d" to statdesc.2da where XX is the next available entry and YY is the strref you've designated.

 

As above, it returns 'icon' with the value of the new entry for usage in your spells or items, and you still need to copy your BAM.


Why is this Hypnotoad video so popu... ALL GLORY TO THE HYPNOTOAD.


#69 argent77

argent77
  • Modders
  • 820 posts
  • Gender:Male

Posted 27 January 2018 - 04:49 AM

This macro can be used to sort arrays of numbers or strings in ascending or descending order.
Spoiler

I had to resort to macros, since WeiDU functions can't return array content yet.

Sample code for numeric arrays:
Spoiler

Edited by argent77, 27 January 2018 - 06:29 AM.


#70 subtledoctor

subtledoctor
  • Modders
  • 2641 posts
  • Gender:Male

Posted 02 March 2018 - 09:17 AM

Action macro that generates JOINABLE_NPC_ARRAY table which can be used to patch joinable NPC CRE files (more reliable method than checking CRE BIO offset)

https://github.com/K...e_npc_array.tpa
Example usage:

LAM JOINABLE_NPC_ARRAY
ACTION_PHP_EACH JOINABLE_NPC_ARRAY AS cre => dv BEGIN
    PRINT ~%cre% => %dv%~ 
    COPY_EXISTING ~%cre%~ ~override~
    //your patching code
END

 

This is excellent, by the way, I'm using it in almost all of my mods now.  And I've slightly extended the macro, so that it creates arrays of both joinable and non-joinable NPCs when the macro is run, so you can easily PHP_EACH through either exclusive set of .CRE files at a moment's notice:

DEFINE_ACTION_MACRO JOINABLE_NPC_ARRAYS BEGIN
    //PDIALOG.2DA exists in all games
    ACTION_DEFINE_ASSOCIATIVE_ARRAY JOINABLE_NPC_ARRAY_2da BEGIN ~PDIALOG~ => ~~ END
    //Check PDIALOG.2DA file variants referenced in CAMPAIGN.2DA
    ACTION_IF FILE_EXISTS_IN_GAME ~CAMPAIGN.2DA~ BEGIN
        COPY_EXISTING ~CAMPAIGN.2DA~ ~CAMPAIGN.2DA~
            COUNT_2DA_ROWS 32 "cntrow"
            FOR (i = 0; i < cntrow; i = i + 1) BEGIN
                READ_2DA_ENTRY i 11 32 file
                TO_UPPER file
                DEFINE_ASSOCIATIVE_ARRAY JOINABLE_NPC_ARRAY_2da BEGIN ~%file%~ => ~~ END
            END
        BUT_ONLY
    END
    //Generate array with joinable NPC DV
    ACTION_PHP_EACH JOINABLE_NPC_ARRAY_2da AS file => ~~ BEGIN
        ACTION_IF FILE_EXISTS_IN_GAME ~%file%.2da~ BEGIN
            COPY_EXISTING ~%file%.2da~ ~override~
                COUNT_2DA_ROWS 3 "cntrow"
                FOR (i = 1; i < cntrow; i = i + 1) BEGIN
                    READ_2DA_ENTRY i 0 3 "dv"
                    TO_UPPER dv
                    DEFINE_ASSOCIATIVE_ARRAY JOINABLE_NPC_ARRAY_dv BEGIN ~%dv%~ => ~~ END
                END
            BUT_ONLY
        END
    END
    //Generate array with joinable NPC cre files
    COPY_EXISTING_REGEXP GLOB ~.+\.CRE~ ~override~
        READ_ASCII DEATHVAR "dv" (32) NULL
        TO_UPPER dv
        PATCH_IF VARIABLE_IS_SET $JOINABLE_NPC_ARRAY_dv(~%dv%~) BEGIN
            DEFINE_ASSOCIATIVE_ARRAY JOINABLE_NPC_ARRAY BEGIN ~%SOURCE_FILE%~ => ~%dv%~ END
        END
        PATCH_IF NOT VARIABLE_IS_SET $JOINABLE_NPC_ARRAY_dv(~%dv%~) BEGIN
            DEFINE_ASSOCIATIVE_ARRAY NON_JOINABLE_NPC_ARRAY BEGIN ~%SOURCE_FILE%~ => ~%dv%~ END
        END
    BUT_ONLY
END

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


#71 subtledoctor

subtledoctor
  • Modders
  • 2641 posts
  • Gender:Male

Posted 02 March 2018 - 09:26 AM

Also:

 

WeiDU's CREATE can make spells.

 

Whaaaaaaaaat

 

I'm never using NI again.

 

 

 

(Well, okay, that's a lie.)


Edited by subtledoctor, 02 March 2018 - 09:35 AM.

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


#72 K4thos

K4thos
  • Modders
  • 1188 posts
  • Gender:Male

Posted 29 July 2018 - 03:18 AM

REPLACE_MULTILINE: Patch function that replaces set or all occurrences of the given regexp pattern in the file with the given string. Use EVAL to perform variable substitution on the string and/or the regexp pattern. Unlike REPLACE_TEXTUALLY the pattern can be multi-line text, even without using regexp. Just like REPLACE_BCS_BLOCK the function ignores pattern whitespace. The function can be also used as a COUNT_REGEXP_INSTANCES alternative with the above mentioned features. Optional PATCH_WARN message is printed if the task could not be performed (pattern not found or different amount of pattern matches than expected).

 

https://github.com/K...e_multiline.tpa

 

Mostly useful for UI.MENU patching because REPLACE_BCS_BLOCK  doesn't work with text files and we often need to replace multiple lines in this file, preferably ignoring whitespace differences (enters, spaces, tabs). Of course it works with any text file, so can be used on decompiled scripts and dialogs as well.


Edited by K4thos, 29 July 2018 - 04:03 AM.


#73 CamDawg

CamDawg

    ALL GLORY TO THE HYPNOTOAD

  • Gibberling Poobah
  • 9684 posts
  • Gender:Not Telling

Posted 29 August 2018 - 09:41 PM

Based on the discussion over yonder about cloning spells, I used a new function when updating Sword and Fist. This will clone a spell, updating any opcodes in both the original and clone that self-reference as appropriate. It can optionally also convert the newly cloned spell to an innate spell, finally ending the need for this very old, very outdated bit of code from the mists of time*.

 

Since it can potentially need to update the source spell, it's an action function, not a patch function. Usage is simple, just provide a source and destination string and (if desired) set the make_innate variable to 1 (default is zero), e.g. here's a whole mess of spells being converted to innates for the Hexblade kit:

LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi612 destination = ~a#hex91~ END // pw silence
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi815 destination = ~a#hex92~ END // pw blind
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi715 destination = ~a#hex93~ END // pw stun
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = sppr113 destination = ~a#hex03~ END // doom
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi104 destination = ~a#hex11~ END // charm person
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi116 destination = ~a#hex12~ END // sleep
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi412 destination = ~a#hex04~ END // greater malison
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi206 destination = ~a#hex21~ END // invisibility
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi212 destination = ~a#hex22~ END // mirror image
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi311 destination = ~a#hex31~ END // pfnm
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi314 destination = ~a#hex32~ END // vampiric touch
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi405 destination = ~a#hex41~ END // improved invisibility
LAF cd_clone_spell INT_VAR make_innate = 1 STR_VAR source = spwi415 destination = ~a#hex42~ END // polymorph other

The function itself:

Spoiler

* Yes, there was a time when READ/WRITE patching was so radical that we wrote tutorials for it.


Why is this Hypnotoad video so popu... ALL GLORY TO THE HYPNOTOAD.


#74 Luke

Luke
  • Members
  • 145 posts
  • Gender:Male

Posted 30 August 2018 - 05:41 AM

Thanks to @argent77's help:

 

ALTER_STORE_ITEM -----> Alters properties of all store items matching the resource name specified by "match_resref".

Spoiler

 

ALTER_CRE_ITEM -----> Alters properties of all inventory items matching the resource name specified by "match_resref".

Spoiler

 

ALTER_AREA_ITEM ----> Alters properties of all area items matching the resource name specified by "match_resref".

Spoiler

Edited by Luke, 30 August 2018 - 05:46 AM.


#75 kjeron

kjeron
  • Members
  • 118 posts

Posted 30 August 2018 - 10:53 AM

Based on the discussion over yonder about cloning spells, I used a new function when updating Sword and Fist. This will clone a spell, updating any opcodes in both the original and clone that self-reference as appropriate. It can optionally also convert the newly cloned spell to an innate spell, finally ending the need for this very old, very outdated bit of code from the mists of time*.
 
Since it can potentially need to update the source spell, it's an action function, not a patch function. Usage is simple, just provide a source and destination string and (if desired) set the make_innate variable to 1 (default is zero), e.g. here's a whole mess of spells being converted to innates for the Hexblade kit:
[code=auto:0]

There's one more issue that wasn't mentioned:
Every other spell/item needs opcodes 321/206/318 of the original spell cloned for the new spell.
i.e. Remove Fear applies opcode 321 for the horror spell. Any duplicates of the Horror spell would need removal duplicated on every type of Remove/Resist Fear spell.
It think it would be more efficient to store all such changes in an array for later, then patch them all at once in a single COPY_EXISTING_REGEXP.

Also, 7eyes should check every entry, not just the defaults for the Seven Eyes spell.


Edited by kjeron, 30 August 2018 - 10:55 AM.




Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users