Jump to content

Fix for improved ivisibilities is bugged


Recommended Posts

As Nythrun beat around the bush, this is also a slight problem with slow. We make the spell non-cumulative because of the THAC0 penalty, but the haste effect cancels the slow effect in ugly hardcoded ways; the target would then appear to be moving at normal speeds, but you wouldn't be able to cast another slow on them until the whole spell was dispelled or expired.

 

Also, is inability to refresh any non-cumulative spell an effect introduced by the fixpack?
I don't understand what you're asking.
Link to comment

In any case where a spell effect is made non-cumulative by the fixpack, it's done by granting immunity to spell, so yes.

 

There are a few opcodes that are inherantly non-cumulative and can be refreshed freely. But by and large Bioware had to do the same thing (vide Simulacrum, Chaos Shield, Improved Haste, Wizard Eye, et alis).

Link to comment

And after all this, we still have nasty choices here. I think the save bonuses are intended for the improved invisibility spells, and the stacking prevention is causing a lot of problems for legit players. I think the least worse solution at this point is to farm out the save bonuses to secondary spells and prevent those from stacking--you'll still be able to toss a shadow door on top of mass invisibility, but you should only be getting the save bonuses once.

 

Very ugly, but I think it's the best we can do.

Link to comment

A new tidbit for the IESDP: it appears that opcodes 146 and 148 are parsed and/or executed after other effects. Trying to cast the shell spell and then provide protection against it (opcode 206) in the same ability caused it to fail every time. The solution was to make it even more hacky with not one but two shell spells. (Cue devSin gnashing teeth. ;) )

 

At any rate this should hopefully make the improved invisibilities suck less.

 

// improved invisibility and its %$^%&$# save bonuses
// first make shell spells containing just the saves
COPY_EXISTING ~balth10.spl~ ~override/balth10a.spl~ // Shadow Stance!
		  ~spdr401.spl~ ~override/spdr401a.spl~ // Invisible Stalker Improved Invisibility
		  ~spin544.spl~ ~override/spin544a.spl~ // PSIONIC _SUPERIOR_INVISIBILITY
		  ~spin687.spl~ ~override/spin687a.spl~ // Create Shadows
		  ~spin698.spl~ ~override/spin698a.spl~ // Cerebus Improved Invisibility
		  ~spwi405.spl~ ~override/spwi405a.spl~ // improved invis (mage)
		  ~spwi505.spl~ ~override/spwi505a.spl~ // shadow door (mage)
		  ~spwi607.spl~ ~override/spwi607a.spl~ // Mislead
		  ~spwi721.spl~ ~override/spwi721a.spl~ // mass invisibility
 PATCH_IF (SOURCE_SIZE > 0x71) THEN BEGIN // protects against invalid files
WRITE_LONG  0x08 0xffffffff // blanks spell name
WRITE_ASCII 0x10 ~~ #8	  // blanks casting sound
READ_LONG   0x64 "abil_off"
READ_SHORT  0x68 "abil_num"
READ_LONG   0x6a "fx_off"
FOR (index = (abil_num - 1); index >= 0; index = index - 1) BEGIN
  READ_SHORT  ("%abil_off%" + 0x1e + (0x28 * "%index%")) "abil_fx_num"
  READ_SHORT  ("%abil_off%" + 0x20 + (0x28 * "%index%")) "abil_fx_idx"
  WRITE_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) 5
  WRITE_SHORT ("%abil_off%" + 0x20 + (0x28 * "%index%")) (5 * "%index%")
  WRITE_SHORT ("%abil_off%" + 0x26 + (0x28 * "%index%")) 1 // remove projectile, if any
  FOR (index2 = (abil_fx_num - 1); index2 >= 0; index2 = index2 - 1) BEGIN
	READ_SHORT ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) "opcode"
	PATCH_IF ("%opcode%" = 20) BEGIN
	  READ_ASCII ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) "clone" (0x30)
	END
	DELETE_BYTES ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) 0x30
  END
  FOR (index3 = 33; index3 < 38; index3 = index3 + 1) BEGIN
	INSERT_BYTES   ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) 0x30
	  WRITE_ASCIIE ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) "%clone%"
	  WRITE_SHORT  ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) "%index3%" // save v X
	  WRITE_LONG   ("%fx_off%" + 0x04 + (0x30 * "%abil_fx_idx%")) 4 // save bonus
	  WRITE_LONG   ("%fx_off%" + 0x08 + (0x30 * "%abil_fx_idx%")) 0 // increase/decrease
  END
END
 END
 BUT_ONLY_IF_IT_CHANGES

// next make shell spells containing just protection spells
COPY_EXISTING ~balth10.spl~ ~override/balth10b.spl~ // Shadow Stance!
		  ~spdr401.spl~ ~override/spdr401b.spl~ // Invisible Stalker Improved Invisibility
		  ~spin544.spl~ ~override/spin544b.spl~ // PSIONIC _SUPERIOR_INVISIBILITY
		  ~spin687.spl~ ~override/spin687b.spl~ // Create Shadows
		  ~spin698.spl~ ~override/spin698b.spl~ // Cerebus Improved Invisibility
		  ~spwi405.spl~ ~override/spwi405b.spl~ // improved invis (mage)
		  ~spwi505.spl~ ~override/spwi505b.spl~ // shadow door (mage)
		  ~spwi607.spl~ ~override/spwi607b.spl~ // Mislead
		  ~spwi721.spl~ ~override/spwi721b.spl~ // mass invisibility
 PATCH_IF (SOURCE_SIZE > 0x71) THEN BEGIN // protects against invalid files
WRITE_LONG  0x08 0xffffffff // blanks spell name
WRITE_ASCII 0x10 ~~ #8	  // blanks casting sound
READ_LONG   0x64 "abil_off"
READ_SHORT  0x68 "abil_num"
READ_LONG   0x6a "fx_off"
FOR (index = (abil_num - 1); index >= 0; index = index - 1) BEGIN
  READ_SHORT  ("%abil_off%" + 0x1e + (0x28 * "%index%")) "abil_fx_num"
  READ_SHORT  ("%abil_off%" + 0x20 + (0x28 * "%index%")) "abil_fx_idx"
  WRITE_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) 9
  WRITE_SHORT ("%abil_off%" + 0x20 + (0x28 * "%index%")) (9 * "%index%")
  WRITE_SHORT ("%abil_off%" + 0x26 + (0x28 * "%index%")) 1 // remove projectile, if any
  FOR (index2 = (abil_fx_num - 1); index2 >= 0; index2 = index2 - 1) BEGIN
	READ_SHORT ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) "opcode"
	PATCH_IF ("%opcode%" = 20) BEGIN
	  READ_ASCII ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) "clone" (0x30)
	END
	DELETE_BYTES ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) 0x30
  END
  FOR (index4 = 0; index4 < 9; index4 = index4 + 1) BEGIN
	INSERT_BYTES   ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) 0x30
	  WRITE_ASCIIE ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) "%clone%"
	  WRITE_SHORT  ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) 206	   // spell immunity
	  WRITE_LONG   ("%fx_off%" + 0x04 + (0x30 * "%abil_fx_idx%")) 0xffffffff // no string (silent fail)
//		  SAY   ("%fx_off%" + 0x04 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) @114 // no string (silent fail)
  END
  // resrefs for immunity spells
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%"	))) ~balth10a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 1))) ~spdr401a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 2))) ~spin544a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 3))) ~spin687a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 4))) ~spin698a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 5))) ~spwi405a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 6))) ~spwi505a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 7))) ~spwi607a~ #8 // resref
  WRITE_ASCII	  ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_idx%" + 8))) ~spwi721a~ #8 // resref
END
 END
 BUT_ONLY_IF_IT_CHANGES

// improved invisibility needs to cast both shell spells to get save bonuses properly applied
COPY_EXISTING ~balth10.spl~ ~override~ // Shadow Stance!
		  ~spdr401.spl~ ~override~ // Invisible Stalker Improved Invisibility
		  ~spin544.spl~ ~override~ // PSIONIC _SUPERIOR_INVISIBILITY
		  ~spin687.spl~ ~override~ // Create Shadows
		  ~spin698.spl~ ~override~ // Cerebus Improved Invisibility
		  ~spwi405.spl~ ~override~ // improved invis (mage)
		  ~spwi505.spl~ ~override~ // shadow door (mage)
		  ~spwi607.spl~ ~override~ // Mislead
		  ~spwi721.spl~ ~override~ // mass invisibility
 PATCH_IF (SOURCE_SIZE > 0x71) THEN BEGIN // protects against invalid files
READ_LONG  0x64 "abil_off"
READ_SHORT 0x68 "abil_num"
READ_LONG  0x6a "fx_off"
SET "delta" = 0
FOR (index = 0; index < abil_num; index = index + 1) BEGIN
  READ_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) "abil_fx_num"
  READ_SHORT ("%abil_off%" + 0x20 + (0x28 * "%index%")) "abil_fx_idx"
  SET "abil_fx_idx" = ("%abil_fx_idx%" + "%delta%")
  WRITE_SHORT ("%abil_off%" + 0x20 + (0x28 * "%index%")) "%abil_fx_idx%"
  FOR (index2 = 0; index2 < abil_fx_num; index2 = index2 + 1) BEGIN
	READ_SHORT ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) "opcode"
	PATCH_IF ("%opcode%" = 20) BEGIN
	  READ_ASCII ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) "clone" (0x30)
	END ELSE
	PATCH_IF (("%opcode%" > 32) AND ("%opcode%" < 38)) BEGIN // if save bonuses present, remove them
	  DELETE_BYTES ("%fx_off%" +		(0x30 * ("%abil_fx_idx%" + "%index2%"))) 0x30
	  SET "index2" = "%index2%" - 1
	  SET "abil_fx_num" = "%abil_fx_num%" - 1
	  SET "delta" = "%delta%" - 1
	END
  END
  INSERT_BYTES   ("%fx_off%" +		(0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 0x30
	WRITE_ASCIIE ("%fx_off%" +		(0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) "%clone%"
	WRITE_SHORT  ("%fx_off%" +		(0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 146	   // cast spell
	WRITE_LONG   ("%fx_off%" + 0x04 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 0 // no string (silent fail)
	WRITE_LONG   ("%fx_off%" + 0x08 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 1 // no string (silent fail)
	WRITE_ASCIIE ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) ~%SOURCE_RES%b~ #8 // resref
  INSERT_BYTES   ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) 0x30
	WRITE_ASCIIE ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) "%clone%"
	WRITE_SHORT  ("%fx_off%" +		(0x30 * "%abil_fx_idx%")) 146			   // cast spell
	WRITE_LONG   ("%fx_off%" + 0x04 + (0x30 * "%abil_fx_idx%")) 0				 // use caster level
	WRITE_LONG   ("%fx_off%" + 0x08 + (0x30 * "%abil_fx_idx%")) 1				 // cast instantly
	WRITE_ASCIIE ("%fx_off%" + 0x14 + (0x30 * "%abil_fx_idx%")) ~%SOURCE_RES%a~   // resref
  SET "abil_fx_num" = "%abil_fx_num%" + 2
  SET "delta" = "%delta%" + 2
  WRITE_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) "%abil_fx_num%"
END
 END
 BUT_ONLY_IF_IT_CHANGES

Link to comment
Guest Grocer

Casting a fresh Bless or the like doesn't regenerate duration, correct? You have to wait for it to expire or it doesn't have any effect. This is my understanding, at least.

 

If that's so, I don't see why Improved Invisibility should act any differently. Even if you violate your (normal) invisibility voluntarily while under the effect of the spell, the rest of it (immunity to spells etc.) is still in effect. I don't see why you should be able to recast it while it is still in effect. I mean, I understand why people would want to and I don't think there's anything wrong with casting (normal) Invisibility if you've voluntarily violated yours. I just don't think there's any compelling reason for Improved Invisibility to act differently from other spells. The fact that it has multiple effects which can be 'disspelled' seperately doesn't seem to lead strongly to a conclusion that multiple castings would be cumulative, it is still a single spell.

Link to comment
Guest Grocer
The fact that it has multiple effects which can be 'disspelled' seperately doesn't seem to lead strongly to a conclusion that multiple castings would be cumulative, it is still a single spell.

 

Eh, I'm an idiot. It doesn't actually say that it's non-cumulative, does it? Nevermind then.

 

However, I'd say that the two types, regular and improved, are not the same thing at all. Regular makes you disappear. If you do something, you re-appear. Improved makes you not there, in some fundamental way. If you do something, you reappear, but you still aren't completely there. The fundamental effects of the spell are still working (inability to target with spells, enemies get a -4 to hit, and you get a +4 to save). So if you don't want it to stack, then you shouldn't be able to recast improved until it runs its course or is disspelled. As there are several other ways to disappear again, I highly doubt this is a serious problem for anyone except sorcerers who failed to take regular as a spell.

 

But that probably accounts for a lot of people, and several people who do infinitely more than me for all of us seem to think it needs fixing, so I'm not going to lose a lot of sleep if I don't sway you.

Link to comment

I'm pretty sure the effects list is always parsed in the intuitive order, it's just that the effects from a separate spell file aren't queued until the first spell has fully resolved - and in this case, immunity granted (will .effs, you can usually squeak by unless the effects list is particularly large).

 

As long as the shell spell is what's granting immunity to the shell spell, I don't see why two spells are necessary?

Link to comment
As long as the shell spell is what's granting immunity to the shell spell, I don't see why two spells are necessary?
Yeah, I also thought about that (but neglected to post it, it seems). Why can't SPELLA.SPL just provide immunity against SPELLA (and SPELLB.SPL just not exist)?
Link to comment

An odd thought crossed my mind: Is it possible to make these spells work so than when cast on someone who already has the effect on them, the new casting dispels the old casting and re-applies an all-new spell on the target? Or has this already been discussed long ago.

Link to comment

The only remotely sane way to do what you're suggesting is to invent a new primary or secondary type and shunt the Improved Invisibility stuff into this new cubbyhole, and then update all of the illusion removal effects blocks to also remove the new type.

 

It's something the fixpack has thus far eschewed; it'll break some mods for sure.

Link to comment
Xyx is correct to note that Improved Invisibility does not provide an AC bonus. That doesn't contradict what I said about it giving enemies a -4 malus to hit. Mathematically they're the same (strictly speaking, enemy penalty is better because of base AC capping at -20) and it's totally hardcoded, so we can't swap the enemy penalty for a bonus anyway.
Sorry guys to resurrect such an old thread...can someone confirm that what Nythrun said is effectively true in-game? I mean, has someone tested it? :fish:
Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...