@Luke93 Sorry for the delayed response - I haven't been near a computer for a while. I attempted to come up with a fix for that problem, and I kept running up against edge-case after edge-case. For example, if the bonus from the weapon and the bonus from the proficiency cancel out to 0, the weapon entry is completely omitted from the list, and thus is not fixable. I've tried my best, but I just can't get something reliable to work. If you are good at LUA, you could try yourself. Here is my starter code if you want a head start:
function getMainHandWeaponName()
local details = characters[id].damage.details
local firstNewline = string.find(details, "\n", 1, true)
for i = firstNewline - 1, 1, -1 do
local character = string.sub(details, i, i)
if character == ":" then
return string.sub(details, 1, i - 1)
end
end
end
function getMainHandWeaponBonus()
local details = characters[id].THAC0.details
local mainHandWeaponName = getMainHandWeaponName()
local weaponNameIndex = string.find(details, mainHandWeaponName, 1, true)
if weaponNameIndex ~= nil then
local startSubstringIndex = weaponNameIndex + #mainHandWeaponName + 2
local endSubstringIndex
local nextNewline = string.find(details, "\n", weaponNameIndex, 1, true)
if nextNewline ~= nil then endSubstringIndex = nextNewline else endSubstringIndex = #details end
local bonusString = string.sub(details, startSubstringIndex, endSubstringIndex)
return tonumber(bonusString)
end
end
function getSingleWeaponStyleBonus()
local singleWeaponStyleString = Infinity_FetchString(31137)
local details = characters[id].THAC0.details
local singleWeaponStyleIndex = string.find(details, singleWeaponStyleString, 1, true)
if singleWeaponStyleIndex ~= nil then
local startSubstringIndex = singleWeaponStyleIndex + #singleWeaponStyleString + 2
local endSubstringIndex
local nextNewline = string.find(details, "\n", singleWeaponStyleIndex, 1, true)
if nextNewline ~= nil then endSubstringIndex = nextNewline else endSubstringIndex = #details end
local bonusString = string.sub(details, startSubstringIndex, endSubstringIndex)
return tonumber(bonusString)
end
end
function correctTHAC0Details()
local mainHandWeaponBonus = getMainHandWeaponBonus()
local singleWeaponStyleBonus = getSingleWeaponStyleBonus()
if singleWeaponStyleBonus ~= nil and mainHandWeaponBonus ~= nil then
local difference = mainHandWeaponBonus - singleWeaponStyleBonus
if difference ~= 0 then
Infinity_DisplayString("Needs to be corrected!")
--Do whatever is needed here to correct the current weapon's bonus
else
Infinity_DisplayString("Needs to be deleted!")
--Do whatever is needed here to delete the current weapon's bonus
end
else
Infinity_DisplayString("Nothing needs to be done!")
--Do nothing
end
end
I really do believe the issue needs to be fixed in the engine, and is out of our control. Sorry I couldn't be of much help.
Maybe you could create a thread in the UI Modding section and see if anyone else has some insight. I think you would get more exposure there, based on the nature of your question.
Maybe you could create a thread in the UI Modding section and see if anyone else has some insight. I think you would get more exposure there, based on the nature of your question.
I've already asked @lefreut to have a look at this issue, hopefully he can let me know something in the near future..... Well, at this point I think it can be useful to also summon @Pecca , @AncientCowboy and @kjeron In the meantime I opened a Redmine ticket......
COPY_EXISTING myarea.are
LPF ALTER_AREA_REGION STR_VAR region_name = "name of the region to be patched" destination_area = "resref of the new destination area" END
Is there a way, in a script or a dialog, to check if the party has a certain item, a certain amount of time? Or can you only check if the party has an item at least once? I would like to make a dialog with an option that only appears if the party has at least 5 copies of an item.
NumItemsPartyGT(S:ResRef*,I:Num*) Returns true only if the party has a total number of items of the type specified greater than the 2nd parameter.
==> IF ~NumItemsPartyGT("youritem",2)~ THEN ... to check if the party has at least 3 instances of youritem. Often more efficient than NumItemsParty("youritem",3).
How do I replace an existing string in WeiDu? Or, how do I set a new string for a .2da file?
I'm working with the FEATS.2da in Icewind Dale 2. I know which values I want to change; I just don't know how to get WeiDu to grab them. Here's the top of the .2da, where it looks like the first three columns are the ID, the string reference for the name, and the string reference for the description:
The values I want are down at the bottom:
I've already got the .tra references prepared. I want to turn 41519 into @184, 41533 into @185, 41520 into @186, 41534 into @187, 41521 into @188, and 41535 into @189.
How do I replace an existing string in WeiDu? Or, how do I set a new string for a .2da file?
I'm working with the FEATS.2da in Icewind Dale 2. I know which values I want to change; I just don't know how to get WeiDu to grab them.
WeiDU's 2DA-specific functions allow you to directly control which table value to update. Example: COPY_EXISTING ~feats.2da~ ~override~
COUNT_2DA_COLS num_cols
READ_2DA_ENTRIES_NOW rows num_cols
FOR (row = 0; row < rows; ++row) BEGIN
READ_2DA_ENTRY_FORMER rows row 0 label
PATCH_MATCH ~%label%~ WITH
~WILDSHAPE_BOAR~ BEGIN
SET strref = RESOLVE_STR_REF(@184)
SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~
END
~WILDSHAPE_PANTHER~ BEGIN
SET strref = RESOLVE_STR_REF(@185)
SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~
END
~WILDSHAPE_SHAMBLER~ BEGIN
SET strref = RESOLVE_STR_REF(@186)
SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~
END
DEFAULT
END
END
SET_2DA_ENTRIES_NOW rows_out num_cols
BUT_ONLY
@Ardanis: I tacked it on without the // part (when I had that first line commented out, it replaced the lines with a blank string) and replaced the 9999990 and 9999991 with the entries in the .2da, and it put in the .tra references I wanted.
How would I replace it if I did not know the current entry for that part of the .2da file? The vanilla, unmodded file would have a defined value, but there's another mod, IWD2 Tweaks, that edits the same files. If someone installs that mod before mine (my mod is designed to overwrite that specific component), the current code will result in a null string.
When using OPcode 321 (Remove effects by resource), what, exactly is removed? If I use this OPcode to remove the effects of spell A, and among the effects of spell A is a cast spell B effect, will the effects from spell B be removed too?
When using OPcode 321 (Remove effects by resource), what, exactly is removed? If I use this OPcode to remove the effects of spell A, and among the effects of spell A is a cast spell B effect, will the effects from spell B be removed too?
I would use two Op321 just in case, one for spell A, other for spell B.
@argent77: Your code worked! Thank you! I now have the correct strings for those three feats.
I'm trying to use the same code for a different .2da file, but I can't tell which parts I need to tweak. Right now I'm dealing with help02.2da, focusing on the first three rows.
Let's say I want to change that 37 to a @525, the 9562 to a @527, and the 9559 to a @529. This the code I've been using to make that happen, but it just gives me the vanilla, unmodded string references for those entries. COPY_EXISTING ~help02.2da~ ~override~
COUNT_2DA_COLS num_cols
READ_2DA_ENTRIES_NOW rows num_cols
FOR (row = 0; row < rows; ++row) BEGIN
READ_2DA_ENTRY_FORMER rows row 0 label
PATCH_MATCH ~%label%~ WITH
~1~ BEGIN
SET strref = RESOLVE_STR_REF(@525)
SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~
END
~2~ BEGIN
SET strref = RESOLVE_STR_REF(@527)
SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~
END
~3~ BEGIN
SET strref = RESOLVE_STR_REF(@529)
SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~
END
DEFAULT
END
END
SET_2DA_ENTRIES_NOW rows_out num_cols
BUT_ONLY
When using OPcode 321 (Remove effects by resource), what, exactly is removed? If I use this OPcode to remove the effects of spell A, and among the effects of spell A is a cast spell B effect, will the effects from spell B be removed too?
I would use two Op321 just in case, one for spell A, other for spell B.
-------
How do I add a recipe to Cespenar/Cromwell?
Actually my issue is the other way around... I've made ~70 spells always using the same architecture, which involves a spell A that I want to cancel in certain situations using OP321, and a spell B that is cast at the same time as spell A but isn't canceled by OP321. And currently what I've done is that I made B to be cast by A, and wouldn't want to spend another 2 hours changing that if it's useless, hence the question It's not that I can't think of a workaround, more that I don't want to inflict 2 hours of tediousness on myself for no reason!
opcode 146 will still process, casting the other spell, and its effects will not be removed, UNLESS opcode 146 is on a non-zero-duration delayed timing mode, then the latter will remove the opcode 146 effect before it processes and casts the other spell. You will get similar results with other casting opcodes (148/258/260/326).
The effects of every subspell use that subspell as the parent resource, not whatever spell/item it's spell was cast from.
I'm trying to use the same code for a different .2da file, but I can't tell which parts I need to tweak. Right now I'm dealing with help02.2da, focusing on the first three rows. Let's say I want to change that 37 to a @525, the 9562 to a @527, and the 9559 to a @529. This the code I've been using to make that happen, but it just gives me the vanilla, unmodded string references for those entries.
You have to change the argument "3" from SET_2DA_ENTRY_LATER into "2", since you now want to update values in the 2nd column (counting from 0).
Is it possible to create a Ranger kit that cannot Fall? The game ignores
LAF fl#add_kit_ee
INT_VAR
fallen = 0 // This kit cannot Fall
The game ignores my HP*.2DA (see the attached screenshot). At level 8 I should have 64 HP (with "Max HP on level up" enabled and 14 CON): instead, I have 57 HP. Why?
How can I make Golems, Undead and Elementals immune to my Ranged hit effects? Is it enough to add 3 Protection From Spell (318) effects (Preset Target (2), RACE = ELEMENTAL || RACE = GOLEM || GENERAL = UNDEAD, Istant/Limited, Natural/Nonmagical, Duration 12, Probability1 100, Resource [spell name], special = RESOLVE_STR_REF ~~) to the spell header of my innate ability?
[Dispel/Resistance] What's the difference between Natural/Nonmagical and Not dispel/Bypass resistance? I mean, if Resource of my Ranged hit effect is set to Natural/Nonmagical instead of Not dispel/Bypass resistance, then it won't be blocked by the Magic Resistance of the Target, neither it'll be dispelled (since I put Natural). I think the same applies to passive abilities. Is it correct?
Is it possible to create a Ranger kit that cannot Fall? The game ignores
LAF fl#add_kit_ee
INT_VAR
fallen = 0 // This kit cannot Fall
The game ignores my HP*.2DA (see the attached screenshot). At level 8 I should have 64 HP (with "Max HP on level up" enabled and 14 CON): instead, I have 57 HP. Why?
How can I make Golems, Undead and Elementals immune to my Ranged hit effects? Is it enough to add 3 Protection From Spell (318) effects (Preset Target (2), RACE = ELEMENTAL || RACE = GOLEM || GENERAL = UNDEAD, Istant/Limited, Natural/Nonmagical, Duration 12, Probability1 100, Resource [spell name], special = RESOLVE_STR_REF ~~) to the spell header of my innate ability?
[Dispel/Resistance] What's the difference between Natural/Nonmagical and Not dispel/Bypass resistance? I mean, if Resource of my Ranged hit effect is set to Natural/Nonmagical instead of Not dispel/Bypass resistance, then it won't be blocked by the Magic Resistance of the Target, neither it'll be dispelled (since I put Natural). Is it correct?
1. Check clastext.2da after installing your kit. Normally, under the fallen column, there should be a 0 for your kit. If there is, but your kit still falls, then no it's not possible. In the original game all ranger and paladin kits could fall. Beamdog introduced only a Paladin kit that cannot fall (Blackguard), so maybe they only de-hardcode the Paladin part...
2. Well obviously it does take something that isn't the normal table into account, because a vanilla ranger rolls d10 and should have 80 hp at level 8 with 14 CON. This time, please check HPCLASS.2da after installing your kit. Second column should be HPARC in your case. Make sure you copy the HPARC.2da file to the override folder before you use the add_kit function. Otherwise, try using an already existing table. HPMONK and HPPRS are literal copies of your table.
3. What I would do would be making my on-hit cast a spell that has 4 effects. The first three ones (and it must be the first three in the order of effects) will be OP318 ( Preset Target (2), RACE = ELEMENTAL || RACE = GOLEM || GENERAL = UNDEAD, Instant/Limited, Natural/Nonmagical, Duration 1, Probability1 100, Resource "SPELLB", special = RESOLVE_STR_REF ~~), and the 4th one will be cast spell(146) with the actual on-hit spell (called SPELLB). This way, the first on-hit spell will protect elementals, golems and undeads, then it will cast the second spell, to which the appropriate targets will be immune.
3. 318 or 324, and make sure they are the first effects in each header. The can refer to the spell containing them - no need for subspells in this case.
It's not working (First effect index is 0 and Effect 0 is opcode 318...) This is the piece of code that adds opcode 318:
@Luke93 Melee/Ranged hit effects do not have a parent resource unless directly specified in their EFF files. In those EFF's, fill in the parent resource field with something similar, but not exactly matching the spell, so it doesn't interfere with a mirror match. Then add another Ranged Hit Effect (preceding the others Ranged Hit Effects in effect order), put opcode 318 in it's EFF, and use as its resource the parent resource specified in the other EFF files.
COPY_EXISTING ~(EFF'S).eff~ override // the EFF's for the hit effects
WRITE_ASCII 0x94 ~CS_BLNDX~
COPY_EXISTING ~CS_BLND.spl~ ~override~
LPF ADD_SPELLL_CFEFFECT INT_VAR opcode = 171 target = 1 END
LPF ADD_SPELLL_CFEFFECT INT_VAR opcode = 172 target = 1 END
LPF CLONE_EFFECT INT_VAR match_opcode = 249 STR_VAR resource = ~NEWEFF~ END
CREATE EFF ~NEWEFF~
WRITE_SHORT 0x10 318
WRITE_LONG 0x20 2
WRITE_BYTE 0x2c 100
WRITE_ASCII 0x30 ~CS_BLNDX~
Comments
Sorry for the delayed response - I haven't been near a computer for a while. I attempted to come up with a fix for that problem, and I kept running up against edge-case after edge-case. For example, if the bonus from the weapon and the bonus from the proficiency cancel out to 0, the weapon entry is completely omitted from the list, and thus is not fixable. I've tried my best, but I just can't get something reliable to work. If you are good at LUA, you could try yourself. Here is my starter code if you want a head start:
function getMainHandWeaponName() local details = characters[id].damage.details local firstNewline = string.find(details, "\n", 1, true) for i = firstNewline - 1, 1, -1 do local character = string.sub(details, i, i) if character == ":" then return string.sub(details, 1, i - 1) end end end function getMainHandWeaponBonus() local details = characters[id].THAC0.details local mainHandWeaponName = getMainHandWeaponName() local weaponNameIndex = string.find(details, mainHandWeaponName, 1, true) if weaponNameIndex ~= nil then local startSubstringIndex = weaponNameIndex + #mainHandWeaponName + 2 local endSubstringIndex local nextNewline = string.find(details, "\n", weaponNameIndex, 1, true) if nextNewline ~= nil then endSubstringIndex = nextNewline else endSubstringIndex = #details end local bonusString = string.sub(details, startSubstringIndex, endSubstringIndex) return tonumber(bonusString) end end function getSingleWeaponStyleBonus() local singleWeaponStyleString = Infinity_FetchString(31137) local details = characters[id].THAC0.details local singleWeaponStyleIndex = string.find(details, singleWeaponStyleString, 1, true) if singleWeaponStyleIndex ~= nil then local startSubstringIndex = singleWeaponStyleIndex + #singleWeaponStyleString + 2 local endSubstringIndex local nextNewline = string.find(details, "\n", singleWeaponStyleIndex, 1, true) if nextNewline ~= nil then endSubstringIndex = nextNewline else endSubstringIndex = #details end local bonusString = string.sub(details, startSubstringIndex, endSubstringIndex) return tonumber(bonusString) end end function correctTHAC0Details() local mainHandWeaponBonus = getMainHandWeaponBonus() local singleWeaponStyleBonus = getSingleWeaponStyleBonus() if singleWeaponStyleBonus ~= nil and mainHandWeaponBonus ~= nil then local difference = mainHandWeaponBonus - singleWeaponStyleBonus if difference ~= 0 then Infinity_DisplayString("Needs to be corrected!") --Do whatever is needed here to correct the current weapon's bonus else Infinity_DisplayString("Needs to be deleted!") --Do whatever is needed here to delete the current weapon's bonus end else Infinity_DisplayString("Nothing needs to be done!") --Do nothing end end
I really do believe the issue needs to be fixed in the engine, and is out of our control. Sorry I couldn't be of much help.
Maybe you could create a thread in the UI Modding section and see if anyone else has some insight. I think you would get more exposure there, based on the nature of your question.
In the meantime I opened a Redmine ticket......
The door is door0406b
The destination area is defined in the Travel trigger name
where you find it:
You can easily change it with WeiDU.
Next, how do I separate WeiDu components to ask for each one?
What is the 2da that controls which race can multiclass and which race can dual class?
Thanks.
Is there a way, in a script or a dialog, to check if the party has a certain item, a certain amount of time? Or can you only check if the party has an item at least once?
I would like to make a dialog with an option that only appears if the party has at least 5 copies of an item.
Thanks It's CLSRCREQ.2da
Returns true only if the party has a total number of items of the type specified greater than the 2nd parameter.
==> IF ~NumItemsPartyGT("youritem",2)~ THEN ... to check if the party has at least 3 instances of youritem. Often more efficient than NumItemsParty("youritem",3).
I'm working with the FEATS.2da in Icewind Dale 2. I know which values I want to change; I just don't know how to get WeiDu to grab them. Here's the top of the .2da, where it looks like the first three columns are the ID, the string reference for the name, and the string reference for the description:
The values I want are down at the bottom:
I've already got the .tra references prepared. I want to turn 41519 into @184, 41533 into @185, 41520 into @186, 41534 into @187, 41521 into @188, and 41535 into @189.
COPY_EXISTING ~feats.2da~ ~override~ COUNT_2DA_COLS num_cols READ_2DA_ENTRIES_NOW rows num_cols FOR (row = 0; row < rows; ++row) BEGIN READ_2DA_ENTRY_FORMER rows row 0 label PATCH_MATCH ~%label%~ WITH ~WILDSHAPE_BOAR~ BEGIN SET strref = RESOLVE_STR_REF(@184) SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~ END ~WILDSHAPE_PANTHER~ BEGIN SET strref = RESOLVE_STR_REF(@185) SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~ END ~WILDSHAPE_SHAMBLER~ BEGIN SET strref = RESOLVE_STR_REF(@186) SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~ END DEFAULT END END SET_2DA_ENTRIES_NOW rows_out num_cols BUT_ONLY
How would I replace it if I did not know the current entry for that part of the .2da file? The vanilla, unmodded file would have a defined value, but there's another mod, IWD2 Tweaks, that edits the same files. If someone installs that mod before mine (my mod is designed to overwrite that specific component), the current code will result in a null string.
If I use this OPcode to remove the effects of spell A, and among the effects of spell A is a cast spell B effect, will the effects from spell B be removed too?
-------
How do I add a recipe to Cespenar/Cromwell?
I'm trying to use the same code for a different .2da file, but I can't tell which parts I need to tweak. Right now I'm dealing with help02.2da, focusing on the first three rows.
Let's say I want to change that 37 to a @525, the 9562 to a @527, and the 9559 to a @529. This the code I've been using to make that happen, but it just gives me the vanilla, unmodded string references for those entries.
COPY_EXISTING ~help02.2da~ ~override~ COUNT_2DA_COLS num_cols READ_2DA_ENTRIES_NOW rows num_cols FOR (row = 0; row < rows; ++row) BEGIN READ_2DA_ENTRY_FORMER rows row 0 label PATCH_MATCH ~%label%~ WITH ~1~ BEGIN SET strref = RESOLVE_STR_REF(@525) SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~ END ~2~ BEGIN SET strref = RESOLVE_STR_REF(@527) SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~ END ~3~ BEGIN SET strref = RESOLVE_STR_REF(@529) SET_2DA_ENTRY_LATER rows_out row 3 ~%strref%~ END DEFAULT END END SET_2DA_ENTRIES_NOW rows_out num_cols BUT_ONLY
It's not that I can't think of a workaround, more that I don't want to inflict 2 hours of tediousness on myself for no reason!
Regardless of effect order: or opcode 146 will still process, casting the other spell, and its effects will not be removed, UNLESS opcode 146 is on a non-zero-duration delayed timing mode, then the latter will remove the opcode 146 effect before it processes and casts the other spell. You will get similar results with other casting opcodes (148/258/260/326).
The effects of every subspell use that subspell as the parent resource, not whatever spell/item it's spell was cast from.
2. Well obviously it does take something that isn't the normal table into account, because a vanilla ranger rolls d10 and should have 80 hp at level 8 with 14 CON. This time, please check HPCLASS.2da after installing your kit. Second column should be HPARC in your case. Make sure you copy the HPARC.2da file to the override folder before you use the add_kit function. Otherwise, try using an already existing table. HPMONK and HPPRS are literal copies of your table.
3. What I would do would be making my on-hit cast a spell that has 4 effects. The first three ones (and it must be the first three in the order of effects) will be OP318 ( Preset Target (2), RACE = ELEMENTAL || RACE = GOLEM || GENERAL = UNDEAD, Instant/Limited, Natural/Nonmagical, Duration 1, Probability1 100, Resource "SPELLB", special = RESOLVE_STR_REF ~~), and the 4th one will be cast spell(146) with the actual on-hit spell (called SPELLB). This way, the first on-hit spell will protect elementals, golems and undeads, then it will cast the second spell, to which the appropriate targets will be immune.
4. None, functionally.
Melee/Ranged hit effects do not have a parent resource unless directly specified in their EFF files. In those EFF's, fill in the parent resource field with something similar, but not exactly matching the spell, so it doesn't interfere with a mirror match.
Then add another Ranged Hit Effect (preceding the others Ranged Hit Effects in effect order), put opcode 318 in it's EFF, and use as its resource the parent resource specified in the other EFF files.