Jump to content

Spell Shield shimmery ground animation


Recommended Posts

If I'm remembering right, Opcode #291 can disable the hardcoded visuals, with the caveat that it disables them on the opcode level, (meaning all spells that use those opcodes, and rely on them for their graphics, will suddenly lose their visuals on the target creature).

Link to comment

Hmp.   I gave Haste and Slow opposing sectypes and give them each a 226 effect with a spell in the resource field that has a 321 effect to cancel them - just like SPWI519 in the vanilla game.

When I cast Slow on Imoen, she is slowed; when I then cast Haste on her, the Haste is blocked and the Slow is dispelled, for a net neutral result.  Exactly what I expect.

However, when I cast Haste on Imoen, and then cast Slow on her (suitably altered to target allies), the Slow is ineffective but the Haste remains, instead of being canceled. I cast Slow again and it is also blocked, and Haste still remains. 

I don't understand what the difference is.  Haste's 226 effect is only set to block 1 spell level of spells with the Slow sectype; getting hit with Slow twice should be dispelling it.  Why would one work and not the other??

Sigh.  The trials and tribulations of modding these games...

Edited by subtledoctor
Link to comment
18 minutes ago, subtledoctor said:

Hmp.   I gave Haste and Slow opposing sectypes and give them each a 226 effect with a spell in the resource field that has a 321 effect to cancel them - just like SPWI519 in the vanilla game.

When I cast Slow on Imoen, she is slowed; when I then cast Haste on her, the Haste is blocked and the Slow is dispelled, for a net neutral result.  Exactly what I expect.

However, when I cast Haste on Imoen, and then cast Slow on her (suitably altered to target allies), the Slow is ineffective but the Haste remains, instead of being canceled. I cast Slow again and it is also blocked, and Haste still remains. 

I don't understand what the difference is.  Haste's 226 effect is only set to block 1 spell level of spells with the Slow sectype; getting hit with Slow twice should be dispelling it.  Why would one work and not the other??

Sigh.  The trials and tribulations of modding these games...

I think you meant to put this in the SRR thread, not your Spell Shield thread, but my answer is the same regardless: it's probably somethin' inexplicable and/or stupid, just like it always is when something in these games isn't working like it seems like it obviously should.

Link to comment

No, I meant to post it here.  This is quite frustrating.  Looking at the spells, they seem the same; but one works and one doesn't.

Here's the code I used to test it btw:

COPY_EXISTING ~msectype.2da~ ~override~
	READ_2DA_ENTRIES_NOW rows 2
	FOR (row = 1; row < rows; ++row) BEGIN 
	  READ_2DA_ENTRY_FORMER rows row 0 ~sectype~ 
	  PATCH_IF (~%sectype%~ STRING_EQUAL_CASE ~k1#Haste~) BEGIN
	    SET k1haste_row = (%row% - 1)
	  END
	  PATCH_IF (~%sectype%~ STRING_EQUAL_CASE ~k1#Slow~) BEGIN
	    SET k1slow_row = (%row% - 1)
	  END
	END
BUT_ONLY

COPY_EXISTING_REGEXP GLOB ~^.+\.spl$~ ~override~
  PATCH_IF (%SOURCE_SIZE% > 0x71) BEGIN
	READ_BYTE 0x27 sec_type
	PATCH_IF (sec_type = %k1haste_row%) BEGIN
	  SPRINT $haste_list(~%SOURCE_RES%~) ~haste~
	  LPF CLONE_EFFECT INT_VAR silent = 1 match_opcode = 176 opcode = 226 parameter1 = 1 parameter2 = %k1slow_row% STR_VAR resource = ~d5xw305~ END
	END
	PATCH_IF (sec_type = %k1slow_row%) BEGIN
	  SPRINT $slow_list(~%SOURCE_RES%~) ~slow~
	  LPF CLONE_EFFECT INT_VAR silent = 1 match_opcode = 40 opcode = 226 parameter1 = 1 parameter2 = %k1haste_row% STR_VAR resource = ~d5xw312~ END
	END
  END
BUT_ONLY

COPY_EXISTING ~spwi312.spl~ ~override/d5xw305.spl~
  WRITE_BYTE 0x27 0
  LPF ALTER_SPELL_HEADER INT_VAR target = 5 projectile = 1 END
  LPF DELETE_EFFECT END
  PHP_EACH haste_list AS haste_res => type BEGIN
	PATCH_IF (~%type%~ STRING_EQUAL_CASE ~haste~) BEGIN
	  LPF ADD_SPELL_EFFECT INT_VAR opcode = 321 target = 2 timing = 1 STR_VAR resource = EVAL ~%haste_res%~ END
	END
  END

COPY_EXISTING ~spwi312.spl~ ~override/d5xw312.spl~
  WRITE_BYTE 0x27 0
  LPF ALTER_SPELL_HEADER INT_VAR target = 5 projectile = 1 END
  LPF DELETE_EFFECT END
  PHP_EACH slow_list AS slow_res => type BEGIN
	PATCH_IF (~%type%~ STRING_EQUAL_CASE ~slow~) BEGIN
	  LPF ADD_SPELL_EFFECT INT_VAR opcode = 321 target = 2 timing = 1 STR_VAR resource = EVAL ~%slow_res%~ END
	END
  END

COPY_EXISTING ~spwi305.spl~ ~override~
			  ~spwi312.spl~ ~override~
	LPF ALTER_SPELL_HEADER INT_VAR target = 1 projectile = 0 END
	LPF ALTER_EFFECT INT_VAR savingthrow = 0 END
BUT_ONLY

(Must be installed after SR or SRR.  And is EE-only.)

Edited by subtledoctor
Link to comment
21 minutes ago, subtledoctor said:

No, I meant to post it here.  This is quite frustrating.  Looking at the spells, they seem the same; but one works and one doesn't.

Here's the code I used to test it btw:


COPY_EXISTING ~msectype.2da~ ~override~
	READ_2DA_ENTRIES_NOW rows 2
	FOR (row = 1; row < rows; ++row) BEGIN 
	  READ_2DA_ENTRY_FORMER rows row 0 ~sectype~ 
	  PATCH_IF (~%sectype%~ STRING_EQUAL_CASE ~k1#Haste~) BEGIN
	    SET k1haste_row = (%row% - 1)
	  END
	  PATCH_IF (~%sectype%~ STRING_EQUAL_CASE ~k1#Slow~) BEGIN
	    SET k1slow_row = (%row% - 1)
	  END
	END
BUT_ONLY

COPY_EXISTING_REGEXP GLOB ~^.+\.spl$~ ~override~
  PATCH_IF (%SOURCE_SIZE% > 0x71) BEGIN
	READ_BYTE 0x27 sec_type
	PATCH_IF (sec_type = %k1haste_row%) BEGIN
	  SPRINT $haste_list(~%SOURCE_RES%~) ~haste~
	  LPF CLONE_EFFECT INT_VAR silent = 1 match_opcode = 176 opcode = 226 parameter1 = 1 parameter2 = %k1slow_row% STR_VAR resource = ~d5xw305~ END
	END
	PATCH_IF (sec_type = %k1slow_row%) BEGIN
	  SPRINT $slow_list(~%SOURCE_RES%~) ~slow~
	  LPF CLONE_EFFECT INT_VAR silent = 1 match_opcode = 40 opcode = 226 parameter1 = 1 parameter2 = %k1haste_row% STR_VAR resource = ~d5xw312~ END
	END
  END
BUT_ONLY

COPY_EXISTING ~spwi312.spl~ ~override/d5xw305.spl~
  WRITE_BYTE 0x27 0
  LPF ALTER_SPELL_HEADER INT_VAR target = 5 projectile = 1 END
  LPF DELETE_EFFECT END
  PHP_EACH haste_list AS haste_res => type BEGIN
	PATCH_IF (~%type%~ STRING_EQUAL_CASE ~haste~) BEGIN
	  LPF ADD_SPELL_EFFECT INT_VAR opcode = 321 target = 2 timing = 1 STR_VAR resource = EVAL ~%haste_res%~ END
	END
  END

COPY_EXISTING ~spwi312.spl~ ~override/d5xw312.spl~
  WRITE_BYTE 0x27 0
  LPF ALTER_SPELL_HEADER INT_VAR target = 5 projectile = 1 END
  LPF DELETE_EFFECT END
  PHP_EACH slow_list AS slow_res => type BEGIN
	PATCH_IF (~%type%~ STRING_EQUAL_CASE ~slow~) BEGIN
	  LPF ADD_SPELL_EFFECT INT_VAR opcode = 321 target = 2 timing = 1 STR_VAR resource = EVAL ~%slow_res%~ END
	END
  END

COPY_EXISTING ~spwi305.spl~ ~override~
			  ~spwi312.spl~ ~override~
	LPF ALTER_SPELL_HEADER INT_VAR target = 1 projectile = 0 END
	LPF ALTER_EFFECT INT_VAR savingthrow = 0 END
BUT_ONLY

(Must be installed after SR or SRR.  And is EE-only.)

Should look like this, right? (There are weird delays and fraudulent "spell ineffective" messages for the sectype removals, but it does seem to work.)

https://dl.dropboxusercontent.com/s/emxj527wuablqjz/tHq0SmCvl6.mp4

Edited by Bartimaeus
Link to comment

Well poop, does it actually work?? Wonder why it doesn’t work for me...

EDIT - technically, while a Slow spell might successfully cancel a Haste effect, if it doesn't manage to apply its own Slow effects then it is, in a sense, "ineffective."  So I don't think the messages are totally spurious. I would like there to be fewer messages in general, and using subspells would give that result.  But I think that's a pretty successful patch job given the relatively small amount of code and that it works seamlessly with Kreso's haste/slow code. 

The most reasonable way to do it with subspells would be to modify kreso's code itself, rather than come in later and muck about with it.  But for now at least, I want to keep this as a separate "install after SR" kind of thing.

Edited by subtledoctor
Link to comment
6 hours ago, Bubb said:

If I'm remembering right, Opcode #291 can disable the hardcoded visuals, with the caveat that it disables them on the opcode level,

Okay, I'm not really seeing how this works.  The IESDP uses typically opaque language:

Quote

Blocks the hardcoded animations applied by the following opcodes: 201, 204, 205, 223, 226, 259, 197, 198, 199, 200, 202, 203, 207, 227, 228, 299.

The effect modifies STAT #174 to 'param2'.

Uh, I think that first sentence is missing a conjunction or ten.  Does it block all of those?  One of them?  Can you specify which?

I think @DavidW coded the new "Remove Visual Effect from the Cloak of Mirroring" component of CDTweaks, and it looks like this:

COPY_EXISTING "clck26.itm" override
  LPF ADD_ITEM_EQEFFECT INT_VAR opcode=291 timing=2 target=1 parameter2=1 insert_point=0 END

How does that know to block the "mirroring" visual effect, and not any other visual effects?

Color me confused.

Link to comment
10 hours ago, subtledoctor said:

Well poop, does it actually work?? Wonder why it doesn’t work for me...

Didn't see anything wrong with your patching (not that, uh, I'm a weidu expert or nothing, but I didn't see any inconsistencies), so I decided the only thing to do was actually run it and look at what it created. A cursory glance at both spells showed that your 221 and 226 opcodes weren't being added in the same order or places on both spells, and that Slow had a 324 opcode at the very beginning of the spell (which Hsate doesn't), which I just moved to being after your 221 and 226 opcodes and it magically started working.

Edited by Bartimaeus
Link to comment
12 hours ago, lynx said:

I think it disables all, but we don't understand it well in GemRB. My suspicion is that the stat works like a mask, so potentially you could disable specific hardcoded overlays.

Most of the spell protection opcodes add an entry to an immunity list in the stats of a creature. Every time the effects list is evaluated on a creature the engine checks if one of these lists is populated, and if it is it adds a corresponding graphic to the creature. Pseudocode:

Spoiler

if (!m_bPreventSpellProtectionEffects && m_generalState & 0x800 == 0 && CGameObject::InControl(this))
{
    if (m_cBounceProjectile.m_nCount == 0 && m_cBounceEffect.m_nCount == 0)
    {
        for (CSpellLevelDecrementing level : m_cBounceProjectileLevelDec)
        {
            if (level.m_bImmune != 0) goto SPTURNI2
        }

        if (   (m_cBounceSchool.m_nCount != 0) || (m_cBounceSecondaryType.m_nCount != 0) || (m_cBounceSpell.m_nCount != 0)
            || (m_cBounceSchoolLevelDec.m_nCount != 0) || (m_cBounceSecondaryTypeLevelDec.m_nCount != 0) 
            || (m_cImmunitiesSecondaryTypeLevelDec.m_nCount != 0) || (0 < m_nChaosShield) )
        {
            goto SPTURNI2
        }
    }
    else
    {
        SPTURNI2:
        // Apply spturni2
    }


    for (CSpellLevelDecrementing level : m_cImmunitiesProjectileLevelDec)
    {
        if (level.m_bImmune != 0) goto SPMAGGLO
    }

    if (   (m_cImmunitiesSchool.m_nCount != 0) || (m_cImmunitiesSecondaryType.m_nCount != 0)
        || (m_cImmunitiesSchoolLevelDec.m_nCount != 0) )
    {
        SPMAGGLO:
        // Apply spmagglo
    }


    for (CSpellLevelDecrementing level : m_cSpellTrapLevelDec)
    {
        if (level.m_bImmune != 0)
        {
            // Apply spmagglo
            break
        }
    }
}

 

Opcode #291 sets m_bPreventSpellProtectionEffects to Param2, (so it's an all-or-nothing deal). The list of Opcode graphics it blocks is as follows:

// Blocks the below graphics
m_bPreventSpellProtectionEffects -> Opcode #291 Param2

// Applies SPTURNI2
m_cBounceProjectile                -> Opcode #197
m_cBounceEffect                    -> Opcode #198
m_cBounceProjectileLevelDec        -> Opcode #200
m_cBounceSchool                    -> Opcode #202
m_cBounceSecondaryType             -> Opcode #203
m_cBounceSpell                     -> Opcode #207
m_cImmunitiesSecondaryTypeLevelDec -> Opcode #226
m_cBounceSchoolLevelDec            -> Opcode #227
m_cBounceSecondaryTypeLevelDec     -> Opcode #228
m_nChaosShield                     -> Opcode #299 Param1

// Applies SPMAGGLO
m_cImmunitiesProjectileLevelDec -> Opcode #201
m_cImmunitiesSchool             -> Opcode #204
m_cImmunitiesSecondaryType      -> Opcode #205
m_cImmunitiesSchoolLevelDec     -> Opcode #223
m_cSpellTrapLevelDec            -> Opcode #259

The IESDP description lists Opcode #199 as one of the opcodes with blocked graphics - but this is false, (that opcode has no associated graphics).

So this is all to say, Opcode #291 doesn't discriminate which visuals it blocks; if you apply it to a creature with Param2 = 1, all the above opcodes will have their graphics suppressed for as long as the Opcode #291 stays in effect.

If you put a permanent Opcode #291 on every creature, and manually add-back the graphics to all the affected spells, in theory you could customize how you want new spells to display without borking the vanilla ones.

Link to comment

Well that is SUPER annoying. 

So to adding sectype-opposition to Haste and Slow effects, they automatically get the Spell Shield “glowing disc at your feet” visual. Seems like the options are:

- Keep that (but sorry, it’s weird)

- Keep it, but modify SPTURNI2.bam to be less aggravating

- Replace SPTURNI2.bam with a blank animation and add a clone of the original, and set Spell Shield and Spell Turning etc. spells to apply the new clone. (I gather this is something like what CDTweaks used to do for the Cloak of Mirroring.)

- Use opcode 291 but... I don’t see any advantage to it. It suppresses multiple animations, not just one, so would take more work to deal with the consequences. 

Modifying or replacing SPTURNI2 seems fine... this goes with SR, so there are no Spell Turning spells. Something else is using that animation - maybe Dispelling Screen? But it should be okay to change it. 

Link to comment

Solution as of now - and btw how nice is it to target this only for installs that have both Spell Revisions and are on the EE 2.5 patch? - is to copy SPTURNI2.bam, the overwrite the original with a blank animation, and manually set SR's Dispelling Screen to apply the copied animation. That works because in the 2.5 patch spell protections can cancel all of their timed effects when the protection is removed, which means we can freely add all sorts of things to them now.

Of course, it looks like opcode 226 is hardcoded to automatically apply a portrait icon as well.  :rant:  :wallbash:

Sigh.  I guess a similar solution will work.

Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...