IWD Tweak pack:
There are some issues with component 'wear multiple protection items' (missing/wrong items, wrong offsets...).
One problem might be, that obviously the code got copied over from another tweak pack and needed to be adapted in a couple of places to account for the different items in
IWD.
I took a different approach, read all items in itemexcl.2da (missing items will be added infront), search for amuletts, rings and cloaks, that grant
AC boni (ignore 'Set
AC base' items, which might be arguable), copy (used a different file name scheme than the original code) and patch them, as needed.
IMHO an advantage is, that all items added by mods to itemexcl.2da (when installed before tweak pack) will be automatically accounted for.
Whats missing in the code for now are modifications to item descriptions reflecting the removed
ac boni. Instead of this, I was thinking more of just popping up a string ('
AC boni disabled'), when equipped (if that's possible).
Warning:
This code has only been tested in so far, that all intended patches got applied, looking at the items using
NI.
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
///// \\\\\
///// wear multiple protection items \\\\\
///// \\\\\
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
///// \\\\\
///// PnP restrictions \\\\\
///// \\\\\
BEGIN @206001 DESIGNATED 2060 // PnP restrictions
GROUP @9
SUBCOMPONENT @206000 // wear multiple protection items
// this file does nothing, it just allows other mods to detect this component
COPY_EXISTING ~sw1h01.itm~ ~override/cdi02060.g3~
//Add items to itemexcl.2da, if missing
ACTION_FOR_EACH item IN
~amul14~
~bwtalis~
~clck01~
~clck02~
~clck03~
~cloakmi~
~glimglm~
~mantlecs~
~virgin~
~ring06~
~ring07~
~ring25~
~shldrng~
~uring2a~
~uring4b~
~uring5a~
~mirror2~ //Totlm
~cdwuff~ //IWD Item Upgrade
~amfaith~ //auril's bane
~amulcm03~ //auril's bane
BEGIN
ACTION_IF FILE_EXISTS_IN_GAME ~%item%.itm~ THEN
BEGIN
APPEND ~itemexcl.2da~ ~%item%%TAB%1~ UNLESS ~%item%~
BUT_ONLY_IF_IT_CHANGES
END
END
//Search for fitting items in itemexcl.2da
OUTER_SET fnd=0
COPY_EXISTING ~itemexcl.2da~ ~override~
COUNT_2DA_COLS rcol
COUNT_2DA_ROWS %rcol% row
FOR (i=1; i<%row%; %i%+=1)
BEGIN
READ_2DA_ENTRY ~%i%~ ~0~ ~%rcol%~ sres
TO_LOWER sres
PATCH_IF FILE_EXISTS_IN_GAME ~%sres%.itm~ THEN
BEGIN
INNER_ACTION
BEGIN
COPY_EXISTING ~%sres%.itm~ ~override~
//PATCH_PRINT ~File: %SOURCE_FILE%~
PATCH_IF (SOURCE_SIZE>0x71) THEN
BEGIN
READ_SHORT 0x1c cat //Read item categorie
PATCH_IF (cat= 1) OR //Amul./Neckl.
(cat=10) OR //Ring
(cat=32) THEN //Cloak/Robe
BEGIN
READ_LONG 0x64 ab_off //Read file offset of abilities
READ_SHORT 0x68 ab_num //Read # of existing abilities
READ_LONG 0x6a fx_off //Read file offset of effects
READ_SHORT 0x70 fx_num //Read # of existing effects
FOR (ii=0; ii<%fx_num%; %ii%+=1)
BEGIN
READ_SHORT %fx_off%+%ii%*0x30 fx_type //Read effect type
READ_LONG %fx_off%+%ii%*0x30+0x08 ac_to //Read Bonus to
PATCH_IF %fx_type%=0 AND
%ac_to%<0x10 THEN
BEGIN
//PATCH_PRINT ~Item found: %sres%.itm~
SPRINT $item("%fnd%") ~%sres%~
SET %fnd%+=1
SET ii=%fx_num%
END
END
END
END
BUT_ONLY_IF_IT_CHANGES
END
END
END
BUT_ONLY_IF_IT_CHANGES
//Adapt found items
OUTER_FOR (i=0; i<%fnd%; %i%+=1)
BEGIN
OUTER_SPRINT ires $item("%i%")
ACTION_IF FILE_EXISTS_IN_GAME ~%ires%.itm~ THEN
BEGIN
//Create file names for copies
//Scheme: -Add 'c' as first char for copies
// -Replace first char of source file name by '1' or '2'
//Example:
//Source: bwtalis.itm
//1. copy: c1wtalis.itm
//2. copy: c2wtalis.itm
OUTER_PATCH ~c%ires% ~
BEGIN
WRITE_ASCII 0x01 ~1~
SPRINT c1ires ~~
FOR (ii=0; ii<8; %ii%+=1)
BEGIN
READ_ASCII %ii% chr (1)
PATCH_IF (~%chr%~ STRING_EQUAL ~ ~ =0) BEGIN SPRINT c1ires ~%c1ires%%chr%~ END ELSE
BEGIN SET ii=8 END
END
WRITE_ASCII 0x01 ~2~
SPRINT c2ires ~~
FOR (ii=0; ii<8; ii+=1)
BEGIN
READ_ASCII %ii% chr (1)
PATCH_IF (~%chr%~ STRING_EQUAL ~ ~ =0) BEGIN SPRINT c2ires ~%c2ires%%chr%~ END ELSE
BEGIN SET ii=8 END
END
END
//Create copies, patch
COPY_EXISTING ~%ires%.itm~ ~override/%ires%.itm~
~%ires%.itm~ ~override/%c1ires%.itm~
~%ires%.itm~ ~override/%c2ires%.itm~
PATCH_IF (SOURCE_SIZE>0x71) THEN
BEGIN
//Insert ability 'Magical' with effect 'Create inventory item'
//Only source file
PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~%SOURCE_RES%~ =0) THEN
BEGIN
READ_LONG 0x64 ab_off //Read file offset of abilities
READ_SHORT 0x68 ab_num //Read # of existing abilities
READ_LONG 0x6a fx_off //Read file offset of global effects
READ_SHORT 0x68 fx_idx //Read first global effects idx
READ_SHORT 0x70 fx_num //Read # of existing global effects
READ_ASCII 0x3a icon (<img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> //Read name of icon resource
PATCH_IF %ab_num%=0 THEN
BEGIN
SET ab_off=0x72
WRITE_LONG 0x64 %ab_off% //Write file offset of abilities
END
PATCH_IF %fx_num%=0 THEN
BEGIN
SET fx_off=%ab_off%+%ab_num%*0x38
WRITE_LONG 0x6a %fx_off% //Write file offset of global effects
END
SET fx_num_max=%fx_idx%+%fx_num%
//Find last effect index for insertion
FOR (ii=0; ii<%ab_num%; %ii%+=1)
BEGIN
READ_SHORT %ab_off%+%ii%*0x38+0x20 ab_fx_idx //Read ability effect index
READ_SHORT %ab_off%+%ii%*0x38+0x1e ab_fx_num //Read # of ability effects
PATCH_IF (%ab_fx_idx%+%ab_fx_num%)>%fx_num_max% BEGIN fx_num_max=%ab_fx_idx%+%ab_fx_num% END
END
//Insert new effect
SET fx_off_add=%fx_off%+%fx_num_max%*0x30
INSERT_BYTES %fx_off_add% 0x30 // New effect
WRITE_SHORT %fx_off_add% 122 // Type: Create inventory item
WRITE_BYTE %fx_off_add%+0x02 1 // Target: Self
WRITE_BYTE %fx_off_add%+0x0c 1 // Timing mode: Instant/Permanent until death
WRITE_BYTE %fx_off_add%+0x12 100 // Probability 1: 100
WRITE_EVALUATED_ASCII %fx_off_add%+0x14 ~%c1ires%~ (<img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> // Resource
PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~^[Cc]1.+$~ =0) THEN
BEGIN
WRITE_EVALUATED_ASCII %fx_off_add%+0x14 ~%c2ires%~ (<img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> // Resource
END
PATCH_IF %ab_off%>%fx_off% THEN //Unlikely, but possible?
BEGIN
SET %ab_off%+=0x30 //Add file offset of global effects
WRITE_LONG 0x64 %ab_off% //Write file offset of global effects
END
//Insert new ability
SET ab_off_add=%ab_off%+%ab_num%*0x38
INSERT_BYTES %ab_off_add% 0x38 // New ability
WRITE_BYTE %ab_off_add% 3 // Type: Magical
WRITE_BYTE %ab_off_add%+ 0x01 1 // ID to use?: Yes
WRITE_SHORT %ab_off_add%+ 0x02 3 // Location: Item slots
WRITE_EVALUATED_ASCII %ab_off_add%+ 0x04 ~%icon%~ (<img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> // Icon
WRITE_SHORT %ab_off_add%+ 0x0c 5 // Target: Caster
WRITE_SHORT %ab_off_add%+ 0x0e 1 // Range: 1
WRITE_SHORT %ab_off_add%+ 0x1e 1 // # effects: 1
WRITE_SHORT %ab_off_add%+ 0x20 %fx_num_max% // First effect index
WRITE_SHORT %ab_off_add%+ 0x22 1 // # charges: 1
WRITE_BYTE %ab_off_add%+ 0x24 1 // When drained: Item vanishes
WRITE_SHORT %ab_off_add%+ 0x2a 1 // Projectile: None
SET %ab_num%+=1 //Increment # of existing abilities
WRITE_SHORT 0x68 %ab_num% //Write # of existing abilities
PATCH_IF %fx_off%>=%ab_off% THEN
BEGIN
SET %fx_off%+=0x38 //Add file offset of global effects
WRITE_LONG 0x6a %fx_off% //Write file offset of global effects
END
//Set # of charges to items found on creatures or areas
//No idea, why this needs to be done...
INNER_ACTION
BEGIN
COPY_EXISTING_REGEXP GLOB ~^.+\.cre$~ ~override~
~^.+\.are$~ ~override~
PATCH_IF (~%SOURCE_FILE%~ STRING_MATCHES_REGEXP ~^.+\.cre$~ =0)
BEGIN
READ_LONG 0x324 "itm_off" ELSE 0
READ_LONG 0x328 "itm_num" ELSE 0
END ELSE
BEGIN
READ_LONG 0x78 "itm_off" ELSE 0
READ_SHORT 0x76 "itm_num" ELSE 0
END
FOR (ii=0; ii<%itm_num%; %ii%+=1)
BEGIN
READ_ASCII %itm_off%+%ii%*0x14 item //Read item resource
PATCH_IF (~%item%~ STRING_MATCHES_REGEXP ~%ires%~ =0) THEN
BEGIN
READ_SHORT %itm_off%+%ii%*0x14+0x0a+(%ab_num%-1)*2 chrgs //Read # of charges
PATCH_IF %chrgs%=0 THEN
BEGIN
WRITE_SHORT %itm_off%+%ii%*0x14+0x0a+(%ab_num%-1)*2 1 //Write # of charges
END
END
END
BUT_ONLY_IF_IT_CHANGES
END
END
//Set 'Lore'=0
//Only copies
PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~^[Cc][12].+$~ =0) THEN
BEGIN
WRITE_SHORT 0x42 0 //Set 'Lore'
END
//Remove armor class bonus
//Only copies c1*.*
PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~^[Cc]1.+$~ =0) THEN
BEGIN
FOR (ii=0; ii<%fx_num%; %ii%+=1)
BEGIN
READ_SHORT %fx_off%+%ii%*0x30 fx_type
PATCH_IF %fx_type%=0 THEN
BEGIN
READ_LONG %fx_off%+%ii%*0x30+0x08 ac_to //Read Bonus to
PATCH_IF %ac_to%<0x10 THEN
BEGIN
DELETE_BYTES %fx_off%+%ii%*0x30 0x30 //Delete global effect
SET %ii%-=1 //Decrement loop counter
SET %fx_num%-=1 //Decrement # of effects
WRITE_SHORT 0x70 %fx_num% //Set # of effects
FOR (iii=0; iii<%ab_num%; %iii%+=1)
BEGIN
READ_SHORT %ab_off%+%iii%*0x38+0x20 ab_fx_idx //Read ability effect index
SET %ab_fx_idx%-=1 //Decrement ability effect index
WRITE_SHORT %ab_off%+%iii%*0x38+0x20 %ab_fx_idx% //Write ability effect index
END
PATCH_IF %ab_off%>%fx_off% THEN
BEGIN
SET %ab_off%-=0x30
WRITE_LONG 0x64 %ab_off% //Write new file offset of abilities
END
END
END
END
END
//Add item to itemexcl.2da
//Only copies c2*.*
PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~^[Cc]2.+$~ =0) THEN
BEGIN
INNER_ACTION
BEGIN
APPEND ~itemexcl.2da~ ~%DEST_RES%%TAB%1~ UNLESS ~%DEST_RES%~
BUT_ONLY_IF_IT_CHANGES
END
END
END
BUT_ONLY_IF_IT_CHANGES
END
END
///// \\\\\
///// no restrictions \\\\\
///// \\\\\
BEGIN @206100 DESIGNATED 2061 // no restrictions
GROUP @9
SUBCOMPONENT @206000 // wear multiple protection items
// this file does nothing, it just allows other mods to detect this component
COPY_EXISTING ~sw1h01.itm~ ~override/cdi02061.g3~
//Remove rings, amuletts, cloaks from itemexcl.2da
COPY_EXISTING ~itemexcl.2da~ ~override~
COUNT_2DA_COLS rcol
COUNT_2DA_ROWS %rcol% row
FOR (i=%row%-1; i>0; i=%i%-1)
BEGIN
READ_2DA_ENTRY ~%i%~ ~0~ ~%rcol%~ sres
TO_LOWER sres
PATCH_IF FILE_EXISTS_IN_GAME ~%sres%.itm~ THEN
BEGIN
SET det=0 //Reset detection count
INNER_ACTION
BEGIN
COPY_EXISTING ~%sres%.itm~ ~override~
PATCH_IF (SOURCE_SIZE>0x71) THEN
BEGIN
READ_SHORT 0x1c cat
PATCH_IF (cat= 1) OR
(cat=10) OR
(cat=32) THEN
BEGIN
READ_LONG 0x6a fx_off //Read file offset of effects
READ_SHORT 0x70 fx_num //Read # of existing effects
FOR (ii=0; ii<%fx_num%; %ii%+=1)
BEGIN
READ_SHORT %fx_off%+%ii%*0x30 fx_type //Read effect type
PATCH_IF %fx_type%=0 THEN
BEGIN
READ_LONG %fx_off%+%ii%*0x30+0x8 ac_type //Read AC bonus type
PATCH_IF %ac_type%!=0x10 THEN //AC bonus type != Set base AC
BEGIN
SET det=det+1
END
END
END
END
END
END
PATCH_IF %det%>0 THEN
BEGIN
REMOVE_2DA_ROW ~%i%~ ~%rcol%~
END
END
END
BUT_ONLY_IF_IT_CHANGES