Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Dark Dreams of Furiae - a new module for NWN:EE! Buy now
Attention, new and old users! Please read the new rules of conduct for the forums, and we hope you enjoy your stay!

[(BGEE, BG2) Bug] Self-stacking spells

CamDawgCamDawg Member, Developer Posts: 3,420
edited August 2012 in Fixed
The effects of several spells will 'stack' with themselves, when they logically should not--i.e. casting multiple armor of faith spells on a creature should ultimately result in one armor of faith.

The problem is that the engine really doesn't have a good way to deal with this, so in Fixpack we simply made a creature that was under the effect of one of these spells immune to subsequent castings until the spell ran out.

NB this will also add a new string to dialog.tlk: "You cannot cast this spell until the current casting has run out."
// many spells stack with themselves and should not
COPY_EXISTING ~spcl423.spl~ ~override~ // assassin poison weapon ability
~spin943.spl~ ~override~ // blur (air mephit)
~sppr111.spl~ ~override~ // armor of faith (priest)
~sppr113.spl~ ~override~ // doom
~sppr210.spl~ ~override~ // resist fire/cold
~sppr306.spl~ ~override~ // protection from fire (priest)
~sppr406.spl~ ~override~ // defensive harmony
~sppr412.spl~ ~override~ // holy power
~sppr513.spl~ ~override~ // righteous magic (priest)
~spwi107.spl~ ~override~ // friends: special case, handled directly in its own patch // not anymore
~spwi201.spl~ ~override~ // blur (wizard)
~spwi214.spl~ ~override~ // strength
~spwi319.spl~ ~override~ // protection from fire (wizard)
~spwi320.spl~ ~override~ // protection from cold
~spwi603.spl~ ~override~ // tenser's transformation
~spwi702.spl~ ~override~ // protection from the elements
~spwi703.spl~ ~override~ // projected image
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"
READ_LONG 0x34 "level"
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"
READ_BYTE ("%fx_off%" + 0x0c + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "timing"
READ_LONG ("%fx_off%" + 0x0e + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "duration"
PATCH_IF (("%timing%" = 0) AND ("%duration%" > 5) AND // instant/limited and duration greater than a round
(("%opcode%" = 33) OR ("%opcode%" = 86) OR ("%opcode%" = 142))) BEGIN
READ_BYTE ("%fx_off%" + 0x02 + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "target"
READ_BYTE ("%fx_off%" + 0x03 + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "power"
READ_BYTE ("%fx_off%" + 0x0d + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "bypass"
SET "index2" = "%abil_fx_num%" // kills WHILE loop
INSERT_BYTES ("%fx_off%" + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 0x30
WRITE_SHORT ("%fx_off%" + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 206 // spell immunity
WRITE_BYTE ("%fx_off%" + 0x02 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) "%target%" // inherits target
WRITE_BYTE ("%fx_off%" + 0x03 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) "%power%" // power
SAY ("%fx_off%" + 0x04 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) ~You cannot cast this spell until the current casting has run out.~
WRITE_BYTE ("%fx_off%" + 0x0c + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 0 // instant/limited
WRITE_BYTE ("%fx_off%" + 0x0d + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) "%bypass%" // inherits dispel/MR
WRITE_LONG ("%fx_off%" + 0x0e + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) "%duration%" // inherits duration
WRITE_BYTE ("%fx_off%" + 0x12 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) 100 // probability
WRITE_EVALUATED_ASCII ("%fx_off%" + 0x14 + (0x30 * ("%abil_fx_num%" + "%abil_fx_idx%"))) ~%SOURCE_RES%~ // spell: self
SET "delta1" = 1
SET "delta" = ("%delta%" + "%delta1%")
WRITE_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) ("%abil_fx_num%" + "%delta1%")

Post edited by Bhryaen on


  • CuvCuv Member, Developer Posts: 2,535
    Question @CamDawg How will that affect custom scripts if the spell is dispelled? Will the spell be available to be recast at that point? Just concerned about the duration properties... and reading WeiDU code hurts my eyes. Sorry if this question may seem silly, just looking at that new string.

  • CamDawgCamDawg Member, Developer Posts: 3,420
    edited July 2012
    The re-casting protection is cloned from existing effects so that duration, power, magic resistance, etc. are the same, meaning it should get dispelled/expire with the rest of the effects.

    @Galactygon has proposed an alternative way to handle this that would make this moot, but I suspect it's going to require a lot of recoding and may not be worth it for the BGEE team.

    Post edited by CamDawg on
  • SethDavisSethDavis Member Posts: 1,812
    edited July 2012
    Checking this one now

    Potentially fixed - @CamDawg 's fix has been applied, though I'm not sure that I like that it tells you you cannot cast it, but takes the memorized spell away regardless.

    I think that the modding support that is planned might eventually be able to handle @Galactygon 's solution.

  • Avenger_teambgAvenger_teambg Member, Developer Posts: 5,862
    Yes, his solution is so much better.

  • CamDawgCamDawg Member, Developer Posts: 3,420
    Agreed. The patch above is the best we could do without access to the engine.

  • TanthalasTanthalas Member Posts: 6,738
    Confirmed fixed for:

    spcl423.spl assassin poison weapon ability
    sppr111.spl armor of faith (priest)
    sppr113.spl doom
    sppr210.spl resist fire/cold
    sppr306.spl protection from fire (priest)
    sppr406.spl defensive harmony
    sppr412.spl holy power
    sppr513.spl righteous magic (priest)
    spwi107.spl friends
    spwi201.spl blur (wizard)
    spwi214.spl strength
    spwi319.spl protection from fire (wizard)
    spwi320.spl protection from cold
    spwi702.spl protection from the elements

    Not sure about:

    spwi703.spl projected image -> The copy can't cast the spell, but no message appears in the battle log. But, the copy has some other problems too (it gets a spell with a the Call Lightning icon that transforms it into a Loup Garou o.O). But since this is a level 7 spell, it will only be an issue in BG2EE

    Couldn't test:

    spin943.spl blur (air mephit) -> Are air Mephit's even in the game?

    spwi603.spl tenser's transformation -> Not sure how to test this one since Tenser's Transformation can't be cast on other people and the effect disables wizard spells.

  • TanthalasTanthalas Member Posts: 6,738
    Well, the doubts I have are BG2 spells, so I don't think this is an issue.

Sign In or Register to comment.