Jump to content

Larloch's MD, Vamp Touch, other draining spells

Recommended Posts

Vampiric Touch and Larloch's Minor Drain will both apply their HP bonuses to caster regardless of whether the spell fails due to target MR. Galactygon suggested a fix and I can confrim that it works. The idea is that LMD or VT would actually just be a shell spell (which checks MR) that casts another spell which does all the actual work.


In a practical example, it means that spin104 (the innate LMD) would be renamed to spin104a and spin104 would be replaced with the shell spell that casts spin104a. Because we're making some major changes that could cause incompatibilities, is this worth it? Would it break any scripts? Is there anything else that it could affect?

Link to comment

And this is coded:


// vampiric touch, larloch minor drain fixes
COPY_EXISTING ~spin104.spl~ ~override/spin104a.spl~ // innate LMD
             ~spin106.spl~ ~override/spin106a.spl~ // innate vamp touch
             ~spin997.spl~ ~override/spin997a.spl~ // innate vamp touch
             ~spwi119.spl~ ~override/spwi119a.spl~ // mage LMD
             ~spwi314.spl~ ~override/spwi314a.spl~ // mage vamp touch
 READ_LONG  0x64 "abil_off"
 READ_SHORT 0x68 "abil_num"
 READ_LONG  0x6a "fx_off"
 READ_SHORT ("%abil_off%" + 0x1e + (0x28 * ("%abil_num%" - 1))) "abil_fx_num"
 READ_SHORT ("%abil_off%" + 0x20 + (0x28 * ("%abil_num%" - 1))) "abil_fx_idx"
 SET "total_fx" = ("%abil_fx_idx%" + "%abil_fx_num%")
 WHILE ("%abil_num%" > 0) BEGIN
   SET "abil_num" = ("%abil_num%" - 1)
   WRITE_SHORT ("%abil_off%" + 0x26 + (0x28 * "%abil_num%")) 1 // removes projectile
 WHILE ("%total_fx%" > 0) BEGIN
   SET "total_fx" = ("%total_fx%" - 1)
   READ_BYTE ("%fx_off%" + 0x0d + (0x30 * "%total_fx%")) "dispel"
   PATCH_IF ("%dispel%" = 1) BEGIN // if dispel/not bypass
     WRITE_BYTE ("%fx_off%" + 0x0d + (0x30 * "%total_fx%")) 3 // make dispel/bypass
   PATCH_IF ("%dispel%" = 2) BEGIN // if not dispel/not bypass
     WRITE_BYTE ("%fx_off%" + 0x0d + (0x30 * "%total_fx%")) 0 // make not dispel/bypass

COPY_EXISTING ~spin104.spl~ ~override~ // innate LMD
             ~spin106.spl~ ~override~ // innate vamp touch
             ~spin997.spl~ ~override~ // innate vamp touch
             ~spwi119.spl~ ~override~ // mage LMD
             ~spwi314.spl~ ~override~ // mage vamp touch
 READ_LONG  0x64 "abil_off"
 READ_SHORT 0x68 "abil_num"
 READ_LONG  0x6a "fx_off"
 READ_SHORT 0x70 "fx_num"
 WHILE ("%abil_num%" > 0) BEGIN
   SET "abil_num" = ("%abil_num%" - 1)
   READ_SHORT  ("%abil_off%" + 0x10 + (0x28 * "%abil_num%")) "level"
   READ_SHORT  ("%abil_off%" + 0x1e + (0x28 * "%abil_num%")) "abil_fx_num"
   WRITE_SHORT ("%abil_off%" + 0x1e + (0x28 * "%abil_num%")) 1
   READ_SHORT  ("%abil_off%" + 0x20 + (0x28 * "%abil_num%")) "abil_fx_idx"
   WRITE_SHORT ("%abil_off%" + 0x20 + (0x28 * "%abil_num%")) "%abil_num%"
   DELETE_BYTES  ("%fx_off%" +        (0x30 * "%abil_fx_idx%")) (0x30 * "%abil_fx_num%") // deletes all effects
   INSERT_BYTES  ("%fx_off%" +        (0x30 * "%abil_fx_idx%")) 0x30                     // new, sole effect
     WRITE_SHORT ("%fx_off%" +        (0x30 * "%abil_fx_idx%")) 146                      // cast spell
     WRITE_BYTE  ("%fx_off%" + 0x02 + (0x30 * "%abil_fx_idx%")) 2                        // target:preset target
     WRITE_BYTE  ("%fx_off%" + 0x03 + (0x30 * "%abil_fx_idx%")) 1                        // power
     WRITE_LONG  ("%fx_off%" + 0x04 + (0x30 * "%abil_fx_idx%")) "%level%"                // cast at level
     WRITE_LONG  ("%fx_off%" + 0x08 + (0x30 * "%abil_fx_idx%")) 1                        // cast instantly
     WRITE_BYTE  ("%fx_off%" + 0x0c + (0x30 * "%abil_fx_idx%")) 1                        // instant/permanent
     WRITE_BYTE  ("%fx_off%" + 0x0d + (0x30 * "%abil_fx_idx%")) 1                        // dispel/not bypass
     WRITE_BYTE  ("%fx_off%" + 0x12 + (0x30 * "%abil_fx_idx%")) 100                      // probability
     WRITE_EVALUATED_ASCII ("%fx_off%" + 0x14 + (0x30 * "%abil_fx_idx%")) ~%SOURCE_RES%~ // spell
     WRITE_ASCII ("%fx_off%" + 0x1b + (0x30 * "%abil_fx_idx%")) ~a~                      // plus the letter a
 PATCH_IF ("%fx_num%" > 0) BEGIN // eliminates global fx
   DELETE_BYTES "%fx_off%" (0x30 * "%fx_num%")
   WRITE_SHORT 0x70 0

Link to comment
If you go with F/M/T don't forget the cheese where larloch's minor drain and vampiric touch will raise your HP, and heal you if you cast them on yourself.
Does this fix that?
Link to comment

On core rules and above, this can't be exploited. The problem is that the game will scale fixed points of damage--on normal, LMD only does three on self-cast, so you net a 1 hp gain. The damage gets altered to 2, 3, 4, 6, or 8 depending on difficulty. Vamp Touch suffers a similar problem.


We could solve this by adding a one-second spell immunity to the caster but it seems hackish.

Link to comment
I recall Galc mentioning that a duration of 0 caused the immunity effect to apply to that particular spell's effects but nothing else, in which case it shifts from hackish to functional. Can anybody confirm?

Using instant/limited timing with zero duration, the 206 immunity opcode worked. In this case we can't use it directly since it would block legit uses--however, adding the immunity to the 'shell' spell prevents self-casting but allows it to work on others.


On core rules and above, this can't be exploited.

No, but the fact that you gain hit points from casting the same spells on a door, or on an item lying on the ground, can be exploited on any difficulty setting.

With target MR now being properly checked I don't think this is the case anymore. Can you think of anything previously exploitable on which we could test?

Link to comment


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

  • Create New...