Skip to content

General mod Questions thread

1171820222370

Comments

  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    Bubb said:

    A little complicated - but possible. If you want any help with the modification, just let me know.

    Yes, a little help would be really appreciated. Thanks!
  • BubbBubb Member Posts: 1,000
    @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.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    edited March 2018
    Bubb said:

    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......
  • lefreutlefreut Member Posts: 1,462
    I don't think the UI have enough information to detect these problems in all cases. I agree with @Bubb, it should be fixed in the engine.
  • semiticgoddesssemiticgoddess Member Posts: 14,903
    How do I change the destination for a door using Near Infinity?
  • GwendolyneGwendolyne Member Posts: 461
    Using NI, it is really easy. Let's have a look at the Copper Coronet entry:

    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. ;)
  • semiticgoddesssemiticgoddess Member Posts: 14,903
    Brilliant!

    Next, how do I separate WeiDu components to ask for each one?
  • GwendolyneGwendolyne Member Posts: 461
    edited March 2018
    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
    
    might help you.
    Post edited by Gwendolyne on
  • RaduzielRaduziel Member Posts: 4,714
    Hi,

    What is the 2da that controls which race can multiclass and which race can dual class?

    Thanks.
  • ArunsunArunsun Member Posts: 1,592
    edited March 2018
    Hi,

    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
    Raduziel said:

    Hi,

    What is the 2da that controls which race can multiclass and which race can dual class?

    Thanks.

    It's CLSRCREQ.2da
  • GwendolyneGwendolyne Member Posts: 461
    edited March 2018
    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).
  • RaduzielRaduziel Member Posts: 4,714
    Arunsun said:

    It's CLSRCREQ.2da

    Thanks :)
  • semiticgoddesssemiticgoddess Member Posts: 14,903
    edited April 2018
    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.
  • ArdanisArdanis Member Posts: 1,736
    edited April 2018
    This is from memory, but iirc REPLACE does what you want:
    // APPEND feats.2da ~WILDSHAPE_BOAR 72 9999990 9999991~
    
    COPY_EXISTING feats.2da override
      REPLACE 9999990 @184
      REPLACE 9999991 @185
    Otherwise set some var to RESOLVE_STR_REF (@184) and either REPLACE_TEXTUALLY 9999990 with evaluated var, or append with a var itself.
  • argent77argent77 Member Posts: 3,433

    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
  • semiticgoddesssemiticgoddess Member Posts: 14,903
    @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.
  • ArunsunArunsun Member Posts: 1,592
    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?
  • The user and all related content has been deleted.
  • RaduzielRaduziel Member Posts: 4,714
    Arunsun said:

    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?
  • semiticgoddesssemiticgoddess Member Posts: 14,903
    @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
  • ArunsunArunsun Member Posts: 1,592
    Raduziel said:

    Arunsun said:

    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 :smiley:
    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!
  • kjeronkjeron Member Posts: 2,367
    @Arunsun
    Regardless of effect order:
    Opcode 321: Resource(THIS)
    Opcode 146: Resource(OTHER)
    or
    Opcode 146: Resource(OTHER)
    Opcode 321: Resource(THIS)
    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.
  • argent77argent77 Member Posts: 3,433

    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).
  • semiticgoddesssemiticgoddess Member Posts: 14,903
    @argent77: Thank you! I've got it working on all the .2da entries I wanted, and now the mod is complete.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    edited April 2018
    1. 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 
    2. 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?
    3. 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?
    4. [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?
    Post edited by _Luke_ on
  • ArunsunArunsun Member Posts: 1,592
    edited April 2018
    Luke93 said:

    1. 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 
    2. 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?
    3. 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?
    4. [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.

    4. None, functionally.
  • The user and all related content has been deleted.
  • _Luke__Luke_ Member, Mobile Tester Posts: 1,535
    edited April 2018


    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:
    COPY_EXISTING ~CS_BLND.spl~ ~override~
    PATCH_IF (~%SOURCE_SIZE%~ > ~0x71~) BEGIN
    	READ_SHORT 0x1c spell_type
    PATCH_IF  (%spell_type% = 4) BEGIN
        READ_LONG 	0x64	ab_off			                             // Abilities Offset
    	READ_SHORT	0x68	ab_num			                             // Number of Abilities
    	READ_SHORT	0x6a	fx_off			                             // Effects Offset
    	READ_SHORT	0x70	glob_fx			                             // Number of Global Effects
    	SET	glob_add = 0
    
    
    
    INSERT_BYTES (fx_off) 0x30
    	WRITE_SHORT (fx_off) 171			                             // opcode 171 -> Give Innate Ability
    	WRITE_BYTE (fx_off + 0x2) 1			                             // Target (self)
    	// WRITE_BYTE (fx_off + 0x4) 1			                         // Level 1
    	// WRITE_LONG (fx_off + 0x8) 0			                         // Wizard
    	WRITE_LONG (fx_off + 0xc) 4			                             // timing 4 -> Delay/Permanent
        WRITE_LONG (fx_off + 0xe) 12                                     // duration
    	WRITE_BYTE (fx_off + 0x12) 100			                         // Probability 1
    	WRITE_ASCII (fx_off + 0x14) ~CS_BLND~                             // resource
    	++glob_add
    
    INSERT_BYTES (fx_off) 0x30
    	WRITE_SHORT (fx_off) 172			                             // opcode 172 -> Remove Spell
    	WRITE_BYTE (fx_off + 0x2) 1			                             // Target (self)
    	// WRITE_BYTE (fx_off + 0x4) 1			                         // Level 1
    	// WRITE_LONG (fx_off + 0x8) 0			                         // Wizard
    	WRITE_LONG (fx_off + 0xc) 9			                             // timing 9 -> Permanent
        // WRITE_LONG (fx_off + 0xe) 10                                  // duration
    	WRITE_BYTE (fx_off + 0x12) 100			                         // Probability 1
        WRITE_ASCII (fx_off + 0x14) ~CS_BLND~                             // resource
    	++glob_add
    	
    INSERT_BYTES (fx_off) 0x30
    	WRITE_SHORT (fx_off) 318			                             // opcode 318 -> Protection from spell
    	WRITE_BYTE (fx_off + 0x2) 2			                             // Preset Target
    	// WRITE_BYTE (fx_off + 0x4) 1			                         // Level 1
    	// WRITE_LONG (fx_off + 0x8) 0			                         // Wizard
    	WRITE_LONG (fx_off + 0x08)  1                                    // Parameter 2 = UNDEAD
    	WRITE_LONG (fx_off + 0xc) 1			                             // timing 1 -> Instant/Permanent until death
        // WRITE_LONG (fx_off + 0xe) 10                                  // duration
    	WRITE_BYTE (fx_off + 0x12) 100			                         // Probability 1
        WRITE_ASCII (fx_off + 0x14) ~CS_BLND~                            // resource
        SAY (fx_off + 0x2c)  ~Unaffected by Called Shot: Blind~          // warning message
    	++glob_add
    
    	
        glob_fx += glob_add
    	WRITE_SHORT 0x70 glob_fx			                             // Increment Number of Global Effects
    	FOR (i = 0; i < ab_num; ++i) BEGIN		                         // Offset Effect Index for all Abilities
    	  READ_SHORT (ab_off + i * 0x28 + 0x20) fx_idx
    	  WRITE_SHORT (ab_off + i * 0x28 + 0x20) (fx_idx + glob_add)
    	END
    END
    END

  • kjeronkjeron Member Posts: 2,367
    @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~

  • [Deleted User][Deleted User] Posts: 0
    edited April 2018
    The user and all related content has been deleted.
Sign In or Register to comment.