Luke
-
Posts
879 -
Joined
Content Type
Forums
Events
Downloads
Gallery
Mods
News
Store
Posts posted by Luke
-
-
I noted the following fact: if a SPL file is cast via op326, then it does not trigger SpellCastOnMe(). This is certainly something to take into account in order to avoid false positives...
-
1 minute ago, DavidW said:
I don't see any evidence that the effect is only supposed to work on wizard and priest spells, and not on all magic effects. The Sun Soul and Blackguard powers here are clearly magical.
There are a (very) few effects that get cast through .spl that clearly aren't magical, but it seems to me way overkill to patch every spell in the game just to block those edge cases.
Yeah, guess you are right... My concern was about mod-added content, such as a single-target fighter kit ability, which should not probably cure such creatures... Guess such kit abilities should probably use op248/249 (see Called Shot) in order to avoid curing these creatures...
-
So, I'm not sure if this is fixpack material or not, but just in case...
As modders know, there are several undroppable items in these games that are supposed to act as "creature skins", i.e.: they provide all sort of immunities (passive traits) a creature should have (well, to be precise, sometimes such immunities are directly attached to the CRE file, but ok...).
My question is: are they correct? That is to say: do they provide the intended immunities or too much / too few immunities...?
As confirmed by other forumites who know the lore (much) better than me, AD&D 2nd edition is not very informative about that... As a result, such things are up to individual Dungeon Master interpretations and campaign settings... which in turn means that such undroppable items are probably correct... which in turn means there is not a template for each creature type to stick with...
However, there is certainly something odd... I mean, letting aside special cases such as boss creatures and plot-armored creatures (that are normally immune to everything), let us start with the following:
-
Elementals, Salamanders and Genies are vulnerable to everything (Backstab, Entangle, Web, Grease, Petrification, Panic, Deafness, Berserk, Silence, Feeblemind, Stun, Charm, Confusion, Sleep, Blindness, Hold, Paralysis, Polymorph, Poison, Disease ...) Intended...? Probably not...?
- In IWD:EE, they are at least immune to cure/cause wounds spells and Disease spells, which makes sense me thinks... But I suspect they should get something more...? For instance at least Salamanders should get Sleep, Charm and Hold immunity...
-
Dragons ("dragring.itm") are basically immune to everything except Polymorph and Feeblemind. Intended...? Guess so, since they are boss / very high level creatures, though I'm not 100% sure...
- Let us say that the immunity to Slow seems out of place, unless that is part of them being boss creatures...?
- The Monstrous Manual (at least the one I found on the net) only speaks about immunity to normal missiles... I know the games are not meant to be 100% faithful to the source material, but just to point it out
-
Plants are generally are vulnerable to everything (Backstab, Entangle, Web, Grease, Petrification, Panic, Deafness, Berserk, Silence, Feeblemind, Stun, Charm, Confusion, Sleep, Blindness, Hold, Paralysis, Polymorph, Poison, Disease ...) Intended...?
- Probably not intended since when SoD was released, they added a new undroppable skin ("bdplant.itm") which provides immunity to Backstab, Stun, Petrification, Sleep, Hold, Paralysis, Polymorph, Poison, Disease ...
-
Demonic creatures vary between games. Intended...? Which is the correct variant...?
-
We have "ringdemn.itm" that provides the following immunities:
- Poison, Charm, Feeblemindedness, Confusion, Polymorph, normal weapons, Panic (BG2:EE and IWD:EE only)
-
We have "bddtrai.itm" (SoD) that provides the following immunities:
- Panic, Stun, Poison, Charm, Sleep, Confusion, normal weapons
-
We have "ringdemn.itm" that provides the following immunities:
-
Wyverns ("ring97.itm") are immune to (Entangle, Web, Grease, Hold, Paralysis, Slow)
- I think we can all agree that immunity to Paralysis is a relic from the past when op157 (Web) was a cosmetic-only opcode, thus it should be removed...
- As far as Hold and Slow are concerned, they seem to be out of place...?
-
Elementals, Salamanders and Genies are vulnerable to everything (Backstab, Entangle, Web, Grease, Petrification, Panic, Deafness, Berserk, Silence, Feeblemind, Stun, Charm, Confusion, Sleep, Blindness, Hold, Paralysis, Polymorph, Poison, Disease ...) Intended...? Probably not...?
-
Now that I think of it, there is probably another issue with these creatures...
"The hakeashar is completely immune to magic, and magic will actually heal it."
As of now, this block
SpoilerIF SpellCastOnMe([ANYONE],0) THEN RESPONSE #100 ApplySpell(Myself,CLERIC_CURE_LIGHT_WOUNDS) // SPPR103.SPL (Cure Light Wounds) END
returns true for all spells, including innate and spell-like abilities such as 'BLACKGUARD_ABSORB_HEALTH' and 'SUN_SOUL_SUN_SOULRAY'... Intended...?
Fixing this would require a bit of spell restructuring (i.e. something like patching all SPPR and SPWI files by adding an op326 effect as first effect casting 'CLERIC_CURE_LIGHT_WOUNDS'...?)
Is this out of scope...?
-
56 minutes ago, Galactygon said:
Good change. Due to the auto-pause bug,
Are you saying the auto-pause bug also affects casting from opcode...? I thought it only triggered when the player casts a spell...
-
6 minutes ago, argent77 said:
The script that was responsible for the falling-down mechanism in oIWD is still in place but doesn't contain any code. Instead it's realized by REG1HP2.ITM
The only odd thing is that not all trolls are equipped with REG1HP2... Some of them still rely upon scripts (see f.i. CDTROLL1.CRE and CDTROLL1.BCS...) Intended...? They probably forgot to update them... Also because such scripts are partially broken (cdtroll2.cre does not exist as a game resource...)
-
On 10/11/2023 at 5:55 PM, argent77 said:
That's handled slightly differently where the trigger delay isn't as noticeable, but the patch should work basically the same.
Yes, the trigger condition is slightly different (i.e. HPPercentLT 25)... However, it is still checked once per round (once per 2 rounds if slowed), so you might want to patch it as well...
On 10/11/2023 at 3:11 PM, argent77 said:which had been initially improved in EE games by moving it from script to spell effect
Unless I'm missing something, in IWD:EE the falling-down mechanism still relies upon scripts...?
-
15 hours ago, CamDawg said:
... for what's essentially an edge-case bug.
Besides wild surge, I think it's also relevant for level drain...?
-
14 minutes ago, argent77 said:
Slow doesn't appear to delay the falling-down trigger. Maybe it's delayed from one tick to two ticks, but that isn't noticeable by the player.
Fine. Guess another possible solution would be that of replacing op232 with op272 (p1=1, p2=3, i.e. once per second / once per 2 seconds if slowed)... In any case, I think this tweak is suitable for inclusion in the fixpack...
Before I forget: in SoD there are certain wolves that also have this falling-down mechanics. As a result, you might want to patch them as well...
-
1 hour ago, argent77 said:
My change includes a second opcode 232 (Cast spell on condition) to the trolls' TROLLREG items which triggers an intermediate spell on "TookDamage()/instant" that executes the original falling-down spell (TROLLREG.SPL, etc.) when the current hit points fall below a certain threshold.
Just out of curiosity: does "TookDamage()" still trigger immediately if the troll in question is slowed...?
1 hour ago, argent77 said:... without being invulnerable for another full round (in the worst case).
As I said before, the worst case scenario is when the troll in question is slowed (i.e. two rounds)
-
Here is a more sophisticated version of spell_to_innate. It makes sure all nested subspells (if any) are of type "innate" and can make the specified innate ability uninterruptible (while casting).
Spoiler// Example usage WITH_SCOPE BEGIN LAF "GET_UNIQUE_FILE_NAME" STR_VAR "extension" = "spl" RET "filename" END // LAF "MAKE_SPELL-LIKE_ABILITY" STR_VAR "source_spell" = "sppr450" // spell to clone "dest_spell" = EVAL "%filename%" // resource name of the cloned spell END END // Function definition DEFINE_ACTION_FUNCTION "MAKE_SPELL-LIKE_ABILITY" INT_VAR "level" = 0 // default: keep levels (in case "%source_spell%" scales with level), otherwise specify a level "location" = 2 // default: "Cast spell" button (F7) "uninterruptible" = 0 // boolean STR_VAR "source_spell" = "" // spell to clone "dest_spell" = "" // resource name of the cloned spell RET_ARRAY "make_spell-like_ability_reserved_hash" // this is only needed when the function calls itself (i.e., you can safely ignore it) BEGIN // Initialize OUTER_SET "last_valid_level" = "-1" OUTER_SET "last_valid_target" = 1 // COPY_EXISTING - "%source_spell%.spl" "override" PATCH_IF "%uninterruptible%" BEGIN READ_SLONG NAME1 "name" READ_LONG 0x18 "flags" END GET_OFFSET_ARRAY "abilityArray" SPL_V10_HEADERS PHP_EACH "abilityArray" AS "abilityIndex" => "abilityOffset" BEGIN PATCH_IF "%uninterruptible%" BEGIN SET "last_valid_target" = BYTE_AT ("%abilityOffset%" + 0xC) END // Return the last header whose "min_level" @ 0x10 is smaller or equal than "%level%" PATCH_IF (SHORT_AT ("%abilityOffset%" + 0x10) <= "%level%") BEGIN SET "last_valid_level" = SHORT_AT ("%abilityOffset%" + 0x10) END END BUT_ONLY_IF_IT_CHANGES // Clone the original spell ACTION_IF "%uninterruptible%" BEGIN LAF "GET_UNIQUE_FILE_NAME" STR_VAR "extension" = "spl" RET "shell_spell" = "filename" END END ELSE BEGIN OUTER_TEXT_SPRINT "shell_spell" "%dest_spell%" END COPY_EXISTING "%source_spell%.spl" "override/%shell_spell%.spl" // Header PATCH_IF "%uninterruptible%" BEGIN WRITE_LONG NAME1 "-1" WRITE_LONG 0x18 0 // flags END WRITE_SHORT 0x1C 4 // innate WRITE_LONG 0x1E 0 // exclusion flags // Extended header(s) PATCH_WITH_SCOPE BEGIN GET_OFFSET_ARRAY "abilityArray" SPL_V10_HEADERS PHP_EACH "abilityArray" AS "abilityIndex" => "abilityOffset" BEGIN PATCH_IF ("%last_valid_level%" != "-1") AND (SHORT_AT ("%abilityOffset%" + 0x10) != "%last_valid_level%") BEGIN WRITE_BYTE "%abilityOffset%" 0xFF // mark it for later deletion END ELSE BEGIN WRITE_SHORT ("%abilityOffset%" + 0x2) "%location%" WRITE_SHORT ("%abilityOffset%" + 0x10) ("%last_valid_level%" == "-1" ? THIS : 1) END END // Actual deletion LPF "DELETE_SPELL_HEADER" INT_VAR "header_type" = 0xFF END END // Feature block(s) -- make sure all op206/318/321/324/333 protect from / remove / cast the new resref LPF ~ALTER_EFFECT~ INT_VAR ~silent~ = 1 ~match_opcode~ = 206 STR_VAR ~match_resource~ = EVAL ~%SOURCE_RES%~ ~resource~ = EVAL ~%DEST_RES%~ END LPF ~ALTER_EFFECT~ INT_VAR ~silent~ = 1 ~match_opcode~ = 318 STR_VAR ~match_resource~ = EVAL ~%SOURCE_RES%~ ~resource~ = EVAL ~%DEST_RES%~ END LPF ~ALTER_EFFECT~ INT_VAR ~silent~ = 1 ~match_opcode~ = 321 STR_VAR ~match_resource~ = EVAL ~%SOURCE_RES%~ ~resource~ = EVAL ~%DEST_RES%~ END LPF ~ALTER_EFFECT~ INT_VAR ~silent~ = 1 ~match_opcode~ = 324 STR_VAR ~match_resource~ = EVAL ~%SOURCE_RES%~ ~resource~ = EVAL ~%DEST_RES%~ END LPF ~ALTER_EFFECT~ INT_VAR ~silent~ = 1 ~match_opcode~ = 333 STR_VAR ~match_resource~ = EVAL ~%SOURCE_RES%~ ~resource~ = EVAL ~%DEST_RES%~ END // Make sure any op146/148/326/333 cast an "innate" spell (if any) GET_OFFSET_ARRAY "abilityArray" SPL_V10_HEADERS PHP_EACH "abilityArray" AS "abilityIndex" => "abilityOffset" BEGIN GET_OFFSET_ARRAY2 "effectArray" "%abilityOffset%" SPL_V10_HEAD_EFFECTS PHP_EACH "effectArray" AS "effectIndex" => "effectOffset" BEGIN READ_ASCII ("%effectOffset%" + 0x14) "res" PATCH_MATCH SHORT_AT "%effectOffset%" WITH 146 148 326 333 WHEN ("%res%" STRING_COMPARE_CASE "%DEST_RES%") BEGIN PATCH_IF !(VARIABLE_IS_SET $"make_spell-like_ability_reserved_hash"("%res%")) BEGIN LPF "GET_UNIQUE_FILE_NAME" STR_VAR "extension" = "spl" RET "filename" END WRITE_ASCIIE ("%effectOffset%" + 0x14) "%filename%" #8 TEXT_SPRINT $"make_spell-like_ability_reserved_hash"("%res%") "%filename%" INNER_ACTION BEGIN LAF "MAKE_SPELL-LIKE_ABILITY" INT_VAR "level" "location" STR_VAR "source_spell" = EVAL "%res%" "dest_spell" = EVAL "%filename%" RET_ARRAY "make_spell-like_ability_reserved_hash" END END END ELSE BEGIN WRITE_ASCIIE ("%effectOffset%" + 0x14) $"make_spell-like_ability_reserved_hash"("%res%") #8 END END DEFAULT END END END BUT_ONLY_IF_IT_CHANGES // Make a dummy SPL file casting the real SPL file if "%uninterruptible%" ACTION_IF "%uninterruptible%" BEGIN ACTION_MATCH "%last_valid_target%" WITH 1 BEGIN // living actor OUTER_SET "opcode" = 146 // cast spell OUTER_SET "target" = 2 // projectile target END 4 BEGIN // any point within range OUTER_SET "opcode" = 148 // cast spell at point OUTER_SET "target" = 1 // self END 5 7 BEGIN // caster OUTER_SET "opcode" = 146 // cast spell OUTER_SET "target" = 1 // self END DEFAULT FAIL "MAKE_SPELL-LIKE_ABILITY: Should not happen" END COPY_EXISTING "%shell_spell%.spl" "override/%dest_spell%.spl" // Header WRITE_LONG NAME1 "%name%" WRITE_LONG 0x18 "%flags%" WRITE_SHORT 0x22 0 // casting animation WRITE_ASCII 0x10 "" #8 // casting sound // Extended header(s) PATCH_WITH_SCOPE BEGIN GET_OFFSET_ARRAY "abilityArray" SPL_V10_HEADERS PHP_EACH "abilityArray" AS "abilityIndex" => "abilityOffset" BEGIN PATCH_IF (SHORT_AT ("%abilityOffset%" + 0x10) != 1) BEGIN WRITE_BYTE "%abilityOffset%" 0xFF // mark it for later deletion END ELSE BEGIN WRITE_SHORT ("%abilityOffset%" + 0x12) 0 // casting speed WRITE_SHORT ("%abilityOffset%" + 0x26) IDS_OF_SYMBOL ("MISSILE" "None") // projectile END END // Actual deletion LPF "DELETE_SPELL_HEADER" INT_VAR "header_type" = 0xFF END END // Casting feature effects LPF ~ADD_SPELL_CFEFFECT~ INT_VAR "opcode" = 101 "target" = 1 "parameter2" = 12 END // Immunity to effect => Effect: Damage (`casting_speed=0` might not be enough, hence a 0-duration immunity to damage...) // Feature block(s) LPF ~DELETE_SPELL_EFFECT~ INT_VAR ~opcode_to_delete~ = ~-1~ END // delete everything LPF ~ADD_SPELL_EFFECT~ INT_VAR "opcode" "target" "timing" = 1 STR_VAR "resource" = EVAL "%SOURCE_RES%" END // Cast spell / Cast spell at point BUT_ONLY_IF_IT_CHANGES END END
-
On 9/20/2023 at 12:25 PM, Galactygon said:
It would be an extra nifty feature if the opcode could discriminate based on where the explosion point occoured relative to the creature being protected so it can block effects if the explosion occoured beyond a certain distance (unused param2 can be used). i.e. if you cast a fireball centered onto yourself but param2 is nonzero then it affects you.
What do you mean exactly here...?
-
On 7/25/2023 at 5:58 PM, Galactygon said:
(Really)(Force)SpellPointCreature(NoDec)(RES)() or (Really)(Force)SpellPointCreatureOffset(NoDec)(RES)() would make sense, yes.
Done.
-
14 minutes ago, subtledoctor said:
But, as I mentioned, on the EEs I assume we can use opcode 337 to make that distinction. Unless my assumption is mistaken.
Yes, op337 should work fine... It just cannot remove permanent (timing=9) effects...
-
14 minutes ago, CamDawg said:
Yes, still no on C_E_Rs. We're first in stack on a known platform, the patch list is known. I generally write a REGEXP to look for issues, then pare it down to a file list for a normal C_E.
Fine, I'll rewrite my code then...
-
Are you still against the idea of using COPY_EXISTING_REGEXP...?
If that is the case, then I need to recode my pending pull requests...
-
On 8/18/2023 at 7:27 PM, subtledoctor said:
Can’t you already achieve this with opcode 337?
Nevermind, it does not really matter... As Polytope said, op162 is meant to remove both op109 and op175 (as per spell description...)
-
On 8/4/2023 at 12:14 AM, Galactygon said:
For the sake of consistency, it might be a good idea to have Hold Undead use 175 and change Hold Monster to affect everything but Undead as well as remove protection from 175 from undead immunities (i.e. RING95.itm). This way, they are affected by Free Action as well.
Follow-up question: as you surely know (and as stated earlier in this thread), if something provides immunity to op109, then it also provides immunity to op175 (and viceversa).
If that is indeed incorrect, then why does op162 (Cure Paralysis) remove both op109 and op175? That is to say: should we have two separate removal opcodes, one specifically for op109 and another one specifically for op175...? Now that I think of it, it would be better to edit the special field of op162 so that it can remove op109 if, say, BIT0 is set, and op175 if BIT1 is set...
-
On 6/27/2023 at 9:10 PM, Galactygon said:
Though it might still be a good idea to use splstates for the sake of scripting.
As far as scripting is concerned, EEex has a new script trigger that can return true if the specified object is immune to a certain opcode (namely "EEex_IsImmuneToOpcode()").
Such a trigger should at least partially mitigate the need of using splstates... However, splstates might still be useful to provide feedback for the player (the so called "Uneffected by effects from" string...)
-
1 hour ago, Galactygon said:
Does your implementation work if the flag is set inside an external .eff?
Yes, it should (asking @Bubb for confirmation...)
-
4 hours ago, Luke said:
Also, Hold Monsters and the like (which use op175) do seem to belong to the so called mind-affecting sphere, so I think it is correct for Undead (among others) to be immune to op175...
Actually, this might be incorrect...
I asked ChatGPT (lol) about that, and it depicted hold monsters as "a spell that affects a creature's physical movements by magically paralyzing them. It doesn't directly target the mind, but rather the body."
- OK, nevermind, ChatGPT also states that the "Hold Monsters" spell is considered a mind-affecting spell. Mind-affecting spells are spells that target a creature's mind, influencing their thoughts, emotions, or mental faculties. "Hold Monsters" falls under this category because it affects the physical actions and movements of creatures by magically paralyzing them.
The fact that it is an Enchantment spell is kinda misleading...
-
11 hours ago, Galactygon said:
Web effects need to be changed to only rely on the Web opcode.
Yes, I think we can all agree on that.
11 hours ago, Galactygon said:For the sake of consistency, it might be a good idea to have Hold Undead use 175 and change Hold Monster to affect everything but Undead as well as remove protection from 175 from undead immunities (i.e. RING95.itm)
Yes, I (partially) agree.
Let's say that if you decide to implement this feature, then there's no need to strip the immunity to 175 from RING95.itm and the like...
Also, Hold Monsters and the like (which use op175) do seem to belong to the so called mind-affecting sphere, so I think it is correct for Undead (among others) to be immune to op175...
-
As far as this topic is concerned, is it correct that
1) opcode #109 should only be used by creatures/items that can naturally cause paralysis (f.i. liches, ghasts, carrion crawlers, etc...)?
2) opcode #175 should only be used by spells/items that are supposed to impose a mental control (f.i. all spells/items flagged as primary_type=4|ENCHANTER)?
3) opcode #185 should only be used for special cases such as Otiluke, Bigby, Hold Undead, ... ?
-
4 hours ago, argent77 said:
It looks like you stumbled upon another bug. The item from the first call of CreateItemGlobal() is created in the magical weapon slot, and only subsequent calls to CreateItemGlobal() will create the item in accessible inventory slots (starting in the last inventory slot).
Indeed.
Well, It can be worked around with GiveItemCreate() and multiple response blocks... The only issue is that it is a bit inelegant...
Will add it to my to-fix list...
Hakeashar / Nishruu
in EE Fixpack
Posted
Yeah, probably ( @subtledoctor do your ambient helper effects start with op146...? Asking because in my tests op326 does not trigger SpellCastOnMe()... Easy repro case: edit the Magic Missile scroll so that it makes use of op326 in place of op146 and use it against a Hakeashar. You will notice the creature does not get healed...)