@Raduziel
Are you talking about swapping the palette of the actual animation or is this solely about the inventory bam? If it's the later, you could also simply extract it as graphics and then edit those with a tool like gimp or photoshop and rebuild the bam. It's very straight forward and will probably yield better results.
Only the inventory. The game already gives the animation per se. The inventory is given for the black bear and the brown bear, but not for the polar bear (even if in IWD a druid can shapeshif into a polar bear).
I've tried editing it using a image editor and NI - both result were ugly as punching a kid (you can see it a few posts above).
@argent77 I'll give it a try and will report to you (through PM or at NI's thread to keep this one clean). Thanks!
To remove its availability at CharGen, just append it to hidespl.2da. (And note, that file has a different number of columns in different games.) To remove scrolls you can patch stores and containers (there are macros, I think), or just overwrite the scroll with another, valid one (my incredibly lazy alternate method )
The problem with it, I think, is that a store that sells "Spell A and Spell B", both to be replaced, would display two entries of the same item "Spell C". Or am I wrong?
That's why I was thinking about removing the old ones and adding the new one.
Do you know if I can do something like the following:
ACTION_FOR_EACH scroll IN ((SCROLLS LIST)) BEGIN
ACTION_IF FILE_CONTAINS scroll BEGIN
COPY_EXISTING_REGEXP ~.*\.sto~ ~override~
ADD_STORE_ITEM ~newscroll~ BEFORE ~%scroll%~ #0 #0 #0 ~IDENTIFIED~ #2
REMOVE_STORE_ITEM ~%scroll%~
BUT_ONLY IF_CHANGES
END
END
@Raduziel: p1 = 50, p2 = 2 is correct, I've tested it by modifying some boots of haste. How are you applying the opcode and to what creature are you doing so?
I also have some problems with
p2 = Set % of
In particular, (opcode #73 - Attack damage modifier) if I set p1 = 50 and p2 = 2, the damage output of my targeted creature doesn't seem to be reduced by 50% ...... (even if I put p1 = "-50".....) Am I missing something?
On the other hand, everything seems to work fine if I use opcode #332 (Stat: Specific Damage Modifier), p1 = "-50"..... But I'd like to alter the base damage so that "X damage resisted" doesn't get displayed in the combat log.....
In particular, (opcode #73 - Attack damage modifier) if I set p1 = 50 and p2 = 2, the damage output of my targeted creature doesn't seem to be reduced by 50% ...... (even if I put p1 = "-50".....) Am I missing something?
On the other hand, everything seems to work fine if I use opcode #332 (Stat: Specific Damage Modifier), p1 = "-50"..... But I'd like to alter the base damage so that "X damage resisted" doesn't get displayed in the combat log.....
Opcode 73 modifies that specific stat (#50 DAMAGEBONUS), the stats final value is added to weapon damage. You can use it to apply a negative increment value to reduce the damage dealt (min:1), but not by a percentage.
Opcode 332 meanwhile does modify total damage.
Does anyone know how to make Weidu recognize zero-length strings? I'm looking for a way to find creatures who don't have anything in their Override script field (0x248).
And is there an example of a mod that puts items in stores of such-and-such type? For example, custom swords should only appear in stores that don't have stealing and do both buy and sell and so on. I would have a look at the code there.
READ_ASCII 0x248 ~script~ (8) NULL
PATCH_IF (~%script%~ STR_EQ ~~) OR (~%script%~ STR_EQ ~NONE~) BEGIN
//do your patching
END
Thank you. It works, but I also need to phase out (remove) the script in the override slot.
COPY_EXISTING_REGEXP GLOB ~.*\.CRE~ ~override~
READ_BYTE 0x272 race /// gnolls
READ_ASCII 0x248 override (8) NULL /// have a useless override script
READ_ASCII 0x250 class (8) NULL /// and usually nothing on the class level
PATCH_IF race = 110 & (~%override%~ STRING_EQUAL_CASE ~GNOLLF~) & ((~%class%~ STRING_EQUAL_CASE ~~) OR (~%class%~ STRING_EQUAL_CASE ~NONE~)) /// so if that's the case...
THEN BEGIN
WRITE_ASCII 0x248 ~~ /// empty the override level
WRITE_ASCII 0x250 ~GNOLLF~ /// move the script to the class level
END
BUT_ONLY
That's the gist of it. How do I fill override with nothing? Writing ~~ doesn't change anything.
Ok, I have a scroll that I want to turn into another scroll. To do it I'm doing the following:
LAF RES_NUM_OF_SPELL_NAME STR_VAR spell_name = ~WIZARD_RADUZIEL_FIRESHIELD~ RET spell_1 = spell_res END
LAF RES_NUM_OF_SPELL_NAME STR_VAR spell_name = ~WIZARD_RADUZIEL_EMOTION~ RET spell_2 = spell_res END
LAF RES_NUM_OF_SPELL_NAME STR_VAR spell_name = ~WIZARD_RADUZIEL_SYMBOL~ RET spell_3 = spell_res END
COPY_EXISTING ~SCRL1W.itm~ ~override/SCRLFSD.itm~
SAY NAME1 @9999275 SAY NAME2 @9999275 SAY UNIDENTIFIED_DESC @9999277 SAY DESC @9999277
LPF ALTER_ITEM_EFFECT INT_VAR match_opcode = ~-1~ STR_VAR resource = EVAL ~%spell_1%~ END
LPF ALTER_ITEM_EFFECT STR_VAR icon = EVAL ~%spell_1%A~ END
COPY_EXISTING ~SCRL1W.itm~ ~override/SCRLEMO.itm~
SAY NAME1 @9999278 SAY NAME2 @9999278 SAY UNIDENTIFIED_DESC @9999280 SAY DESC @9999280
LPF ALTER_ITEM_EFFECT INT_VAR match_opcode = ~-1~ STR_VAR resource = EVAL ~%spell_2%~ END
LPF ALTER_ITEM_EFFECT STR_VAR icon = EVAL ~%spell_2%A~ END
COPY_EXISTING ~SCRL9F.itm~ ~override/SCRLSYM.itm~
SAY NAME1 @9999281 SAY NAME2 @9999281 SAY UNIDENTIFIED_DESC @9999283 SAY DESC @9999283
LPF ALTER_ITEM_EFFECT INT_VAR match_opcode = ~-1~ STR_VAR resource = EVAL ~%spell_3%~ END
LPF ALTER_ITEM_EFFECT STR_VAR icon = EVAL ~%spell_3%A~ END
CLEAR_ARRAYS
But nothing is happening. The new scroll has the correct name and description, but the Cast Spell/Learn Spell keeps referring themselves to the old spell, and I've changed the wrong icon (the icon was a long shot, but I could swear that at least the opcode would be altered properly).
The results are attached so you can see and laugh.
Moreover, instead of writing 0b0001000001101111 you can use BIT0 | BIT1 | BIT2 | BIT3 and so forth ("|" stands for Bitwise OR, also known as BOR........)
That's the gist of it. How do I fill override with nothing? Writing ~~ doesn't change anything.
I believe you need to specify a size for WeiDU to pad the field with NULLs. Try this:
WRITE_ASCII 0x248 ~~ #8
Also note that in most cases, the engine simply sets a script slot to "None" when it wants to clear it. Actually, I think certain opcodes are specifically rigged to not allow you to make script references NULL, so take caution. It will probably work just fine, but there might be a small chance that the engine doesn't account for this possibility somewhere...
@Raduziel
ALTER_ITEM_EFFECT defaults both 'check_headers' and 'check_globals' to 0 (ignore).
ALTER_EFFECT defaults both to 1 (check).
Either use ALTER_ITEM_EFFECT with "INT_VAR check_headers = 1",
or use ALTER_EFFECT with "INT_VAR check_globals = 0".
Moreover, instead of writing 0b0001000001101111 you can use BIT0 | BIT1 | BIT2 | BIT3 and so forth ("|" stands for Bitwise OR, also known as BOR........)
So how would that look?
type = 0 & ((kind BIT0 | BIT1 | BIT2 | BIT3 | BIT5 | BIT 6))... What?
Also, the 4 byte length means 32 bits, but I'm using READ_SHORT to get the first 16 bits. They are the only ones that matter for me - Fence is bit 12, I think, and all the rest can be what they like. From what I understand, reading just the beginning of a field omits the remainder, and it's less confusing this way.
Edit: okay, it worked. But the scope may be a little too broad. The item currently appears in all store-stores that buy, sell, identify, don't buy stolen goods and where there is no stealing option. A lot do. I would like to narrow the scope to stores that buy wands. Any idea how to read that? Do I have to go with an OR through every "Store purchases" offset looking for number 35 for wands? But then, I don't know how many offsets there will be.
And another question I'd like to broadcast here, just to be on the safe side. Probabilities of effects. I've heard that 100 is never rolled. So, then, if I wanted 1% chance, I would write 100-99? Or 0-0? Is there a difference?
And another question I'd like to broadcast here, just to be on the safe side. Probabilities of effects. I've heard that 100 is never rolled. So, then, if I wanted 1% chance, I would write 100-99? Or 0-0? Is there a difference?
Opcode 73 modifies that specific stat (#50 DAMAGEBONUS), the stats final value is added to weapon damage. You can use it to apply a negative increment value to reduce the damage dealt (min:1), but not by a percentage.
How can I prevent that DAMAGEBONUS drops below a certain threshold? I successfully added stat #50 to SLPPROT.2da and the following spell effects to my SPL:
The first row is: Greater than 4294967288 (-8).
The second row is: Less than or equal to 2147483648 (-2147483648, highest negative value), in hex because its value easier to remember.
The third row is: Not (first row or second row) - this is the one you would use in op318.
The end result is: True if current value is between:
(-2117483648 and -8) == (2147483648 and 4294967288).
/**
* Converts any decimal number into a hexadecimal number
*/
DEFINE_ACTION_FUNCTION TO_HEX_NUMBER
INT_VAR
value = 0 // the decimal number
minDigits = 1 // min. number of digits in return value (not counting sign)
prefix = 0 // whether to return number with "0x" prefix
RET
hexNumber // returned as string without prefix
BEGIN
ACTION_IF (minDigits < 1) BEGIN OUTER_SET minDigits = 1 END
ACTION_IF (minDigits > 8) BEGIN OUTER_SET minDigits = 8 END
OUTER_TEXT_SPRINT hexNumber ~~
ACTION_DEFINE_ARRAY digit BEGIN ~0~ ~1~ ~2~ ~3~ ~4~ ~5~ ~6~ ~7~ ~8~ ~9~ ~a~ ~b~ ~c~ ~d~ ~e~ ~f~ END
ACTION_IF (value < 0) BEGIN
OUTER_SET signed = 1
OUTER_SET value = 0 - value
END ELSE BEGIN
OUTER_SET signed = 0
END
OUTER_WHILE (value != 0) BEGIN
OUTER_SET curDigit = value BAND 0xf
OUTER_SET value = value BLSR 4
OUTER_TEXT_SPRINT hexDigit $EVAL digit(~%curDigit%~)
OUTER_TEXT_SPRINT hexNumber ~%hexDigit%%hexNumber%~
END
OUTER_WHILE (STRING_LENGTH ~%hexNumber%~ < minDigits) BEGIN
OUTER_TEXT_SPRINT hexNumber ~0%hexNumber%~
END
ACTION_IF (prefix) BEGIN
OUTER_TEXT_SPRINT hexNumber ~0x%hexNumber%~
END
ACTION_IF (signed) BEGIN
OUTER_TEXT_SPRINT hexNumber ~-%hexNumber%~
END
END
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/**
* Adds a new entry to SPLPROT.2DA and returns its index. If an identical entry already exists it will return
* the index of that entry instead.
* INT_VAR stat A code from STATS.IDS or an extended stat code starting at 0x100 (256).
* STR_VAR value Either a numeric value that is evaluated by "stat", or a default value "*" for specific stats.
* (Note: "-1" indicates a user-defined value.)
* STR_VAR relation Specifies how to evaluate the value.
* (Note: Not all extended stats require a relation code. Use "*" in this case.)
* RET index Entry number that can be used to refer to this operation in various effect opcodes.
* Returns -1 on error.
*/
DEFINE_ACTION_FUNCTION ADD_SPLPROT_ENTRY
INT_VAR
stat = "-1"
STR_VAR
value = "*"
relation = "*"
RET
index
BEGIN
OUTER_SET index = "-1"
ACTION_IF (stat >= 0) BEGIN
LAF TO_HEX_NUMBER INT_VAR value = stat RET hexNumber END
OUTER_TEXT_SPRINT valueHex ~0x%hexNumber%~
ACTION_IF (~%value%~ STRING_EQUAL ~~) BEGIN
OUTER_TEXT_SPRINT value ~*~
END
ACTION_IF (~%relation%~ STRING_EQUAL ~~) BEGIN
OUTER_TEXT_SPRINT relation ~*~
END
ACTION_IF (FILE_EXISTS_IN_GAME ~splprot.2da~) BEGIN
COPY_EXISTING ~splprot.2da~ ~override~
READ_2DA_ENTRIES_NOW table 4
// Search for identical entries
FOR (idx = 0; idx < table; idx += 1) BEGIN
READ_2DA_ENTRY_FORMER table idx 1 curStat
PATCH_IF (~%stat%~ STRING_EQUAL ~%curStat%~ OR ~%valueHex%~ STRING_EQUAL_CASE ~%curStat%~) BEGIN
READ_2DA_ENTRY_FORMER table idx 2 curValue
PATCH_IF (~%value%~ STRING_EQUAL ~%curValue%~) BEGIN
READ_2DA_ENTRY_FORMER table idx 3 curRelation
PATCH_IF (~%relation%~ STRING_EQUAL ~%curRelation%~) BEGIN
SET index = idx
SET idx = table
END
END
END
END
PATCH_IF (index < 0) BEGIN
// Add new entry
PATCH_IF (stat >= 0x100) BEGIN
TEXT_SPRINT line ~%table% %valueHex% %value% %relation%~
END ELSE BEGIN
TEXT_SPRINT line ~%table% %stat% %value% %relation%~
END
INSERT_2DA_ROW table 4 ~%line%~
SET index = table
END
BUT_ONLY
END
END
END
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
LAF ADD_SPLPROT_ENTRY
INT_VAR
stat = 50 // STAT DAMAGEBONUS
STR_VAR
value = ~-8~ // User-defined value
relation = ~3~ // Greater
RET
index
END
OUTER_SET index1 = index
LAF ADD_SPLPROT_ENTRY
INT_VAR
stat = 50 // STAT DAMAGEBONUS
STR_VAR
value = ~0x80000000~ // Highest negative value - 2147483648
relation = ~0~ // Less than or equal
RET
index
END
OUTER_SET index2 = index
LAF ADD_SPLPROT_ENTRY
INT_VAR
stat = 0x104 // negate 0x103 (where 0x103 - use two rows of splprot.2da)
STR_VAR
value = ~index1~ //
relation = ~index2~ //
RET
index
END
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
LPF ADD_SPELL_EFFECT
INT_VAR
opcode = 318 // Protection from spell
target = 2
parameter2 = index // Not match entries
STR_VAR
resource = EVAL ~%SOURCE_RES%~
END
I guess there are 2 problems:
row#B is 'Less than or equal specified value' (but param1 is unused, so this is probably fine...)
Comments
@Ulb
Only the inventory. The game already gives the animation per se. The inventory is given for the black bear and the brown bear, but not for the polar bear (even if in IWD a druid can shapeshif into a polar bear).
I've tried editing it using a image editor and NI - both result were ugly as punching a kid (you can see it a few posts above).
@argent77 I'll give it a try and will report to you (through PM or at NI's thread to keep this one clean). Thanks!
I'm combining several spells into one, so I don't want those spells to-be-combined to be available at chargen and for Sorcerer/Shamans at level up.
I also want to search every store and container to remove the scrolls from those spells and replace with the new spell I'm creating.
Thanks!
@subtledoctor
That's what I meant, lol.
Can you teach me to do the lazy-overwrite way?
The problem with it, I think, is that a store that sells "Spell A and Spell B", both to be replaced, would display two entries of the same item "Spell C". Or am I wrong?
That's why I was thinking about removing the old ones and adding the new one.
I'll take a look soon, at the moment I'm building the new spells per se.
Probably the macros can be found at G3's forum, right? I'll take a look there.
Again, thanks!
Edit:
@subtledoctor
Do you know if I can do something like the following:
WeiDU functions save a lot of coding lines.
But don't I need the name of the store and item to use this code?
Wait
Do you mean like that?
Don't it also create the issue of double entries of the same item at the stores?
Fixed, thanks for noticing!
I also have some problems with
In particular, (opcode #73 - Attack damage modifier) if I set p1 = 50 and p2 = 2, the damage output of my targeted creature doesn't seem to be reduced by 50% ...... (even if I put p1 = "-50".....) Am I missing something?
On the other hand, everything seems to work fine if I use opcode #332 (Stat: Specific Damage Modifier), p1 = "-50"..... But I'd like to alter the base damage so that "X damage resisted" doesn't get displayed in the combat log.....
Opcode 332 meanwhile does modify total damage.
And is there an example of a mod that puts items in stores of such-and-such type? For example, custom swords should only appear in stores that don't have stealing and do both buy and sell and so on. I would have a look at the code there.
Thank you. It works, but I also need to phase out (remove) the script in the override slot.
COPY_EXISTING_REGEXP GLOB ~.*\.CRE~ ~override~
READ_BYTE 0x272 race /// gnolls
READ_ASCII 0x248 override (8) NULL /// have a useless override script
READ_ASCII 0x250 class (8) NULL /// and usually nothing on the class level
PATCH_IF race = 110 & (~%override%~ STRING_EQUAL_CASE ~GNOLLF~) & ((~%class%~ STRING_EQUAL_CASE ~~) OR (~%class%~ STRING_EQUAL_CASE ~NONE~)) /// so if that's the case...
THEN BEGIN
WRITE_ASCII 0x248 ~~ /// empty the override level
WRITE_ASCII 0x250 ~GNOLLF~ /// move the script to the class level
END
BUT_ONLY
That's the gist of it. How do I fill override with nothing? Writing ~~ doesn't change anything.
Is the syntax mistaken or am I using selection criteria no store satisfies?
Ok, I have a scroll that I want to turn into another scroll. To do it I'm doing the following:
But nothing is happening. The new scroll has the correct name and description, but the Cast Spell/Learn Spell keeps referring themselves to the old spell, and I've changed the wrong icon (the icon was a long shot, but I could swear that at least the opcode would be altered properly).
The results are attached so you can see and laugh.
What am I doing wrong?
Thanks.
Offsets 0x8 and 0x10 are 4-byte long ---> https://gibberlings3.github.io/iesdp/file_formats/ie_formats/sto_v1.htm#storv1_0_Header
Moreover, instead of writing 0b0001000001101111 you can use BIT0 | BIT1 | BIT2 | BIT3 and so forth ("|" stands for Bitwise OR, also known as BOR........)
I believe you need to specify a size for WeiDU to pad the field with NULLs. Try this:
Also note that in most cases, the engine simply sets a script slot to "None" when it wants to clear it. Actually, I think certain opcodes are specifically rigged to not allow you to make script references NULL, so take caution. It will probably work just fine, but there might be a small chance that the engine doesn't account for this possibility somewhere...
ALTER_ITEM_EFFECT defaults both 'check_headers' and 'check_globals' to 0 (ignore).
ALTER_EFFECT defaults both to 1 (check).
Either use ALTER_ITEM_EFFECT with "INT_VAR check_headers = 1",
or use ALTER_EFFECT with "INT_VAR check_globals = 0".
Try this;
or
Oops. Ninja-ed by @kjeron
Thanks! You're all invited to Aurora's birthday party.
So how would that look?
type = 0 & ((kind BIT0 | BIT1 | BIT2 | BIT3 | BIT5 | BIT 6))... What?
Also, the 4 byte length means 32 bits, but I'm using READ_SHORT to get the first 16 bits. They are the only ones that matter for me - Fence is bit 12, I think, and all the rest can be what they like. From what I understand, reading just the beginning of a field omits the remainder, and it's less confusing this way.
Yeah, I kind of figured this on my own. Writing "None" there with #8 is the ticket. Empty script slots show as "None" in Near Infinity. Thanks.
If you want to patch all STO that can buy fenced goods, then:
Edit: okay, it worked. But the scope may be a little too broad. The item currently appears in all store-stores that buy, sell, identify, don't buy stolen goods and where there is no stealing option. A lot do. I would like to narrow the scope to stores that buy wands. Any idea how to read that? Do I have to go with an OR through every "Store purchases" offset looking for number 35 for wands? But then, I don't know how many offsets there will be.
And another question I'd like to broadcast here, just to be on the safe side. Probabilities of effects. I've heard that 100 is never rolled. So, then, if I wanted 1% chance, I would write 100-99? Or 0-0? Is there a difference?
Have a look at this.....
How can I prevent that DAMAGEBONUS drops below a certain threshold? I successfully added stat #50 to SLPPROT.2da and the following spell effects to my SPL:
However, this isn't working (i.e., the target is always immune to opcode #73.....)
-8 = 4294967288
It takes 3 rows to work:
The first row is: Greater than 4294967288 (-8).
The second row is: Less than or equal to 2147483648 (-2147483648, highest negative value), in hex because its value easier to remember.
The third row is: Not (first row or second row) - this is the one you would use in op318.
The end result is: True if current value is between:
(-2117483648 and -8) == (2147483648 and 4294967288).
OK, here's my code:
I guess there are 2 problems: