[(BGEE, BG2) Bug] Cone of Cold
Internet went out Friday evening and just got restored, so I'm back to spamming spell fixes.
Cone of Cold has a bevy of minor errors. The range is incorrect at level 9, there's no level 10 header (so when cast at level 10, it does damage as if cast at 9) and the save vs. half damage is wonky. Normally for spells with save for half damage, the damage is split into two separate damage opcodes, and on odd damages (i.e. 11d4) it was split 5d4 and 6d4. Sometimes the extra 1d4 would be saveable, sometimes not, so this patch also makes the split consistent throughout all levels of the spell.
Cone of Cold has a bevy of minor errors. The range is incorrect at level 9, there's no level 10 header (so when cast at level 10, it does damage as if cast at 9) and the save vs. half damage is wonky. Normally for spells with save for half damage, the damage is split into two separate damage opcodes, and on odd damages (i.e. 11d4) it was split 5d4 and 6d4. Sometimes the extra 1d4 would be saveable, sometimes not, so this patch also makes the split consistent throughout all levels of the spell.
// cone of cold missing level 10 ability header, wrong range at level 9, inconsistent save v non-save damage split
COPY_EXISTING ~spwi503.spl~ ~override~
READ_LONG 0x64 "abil_off"
READ_SHORT 0x68 "abil_num"
READ_LONG 0x6a "fx_off"
READ_SHORT 0x70 "fx_num"
SET "lev10_exist" = 0
SET "new_abil" = 0
FOR (index = 0 ; index < abil_num ; index = index + 1) BEGIN
READ_SHORT ("%abil_off%" + 0x10 + (0x28 * "%index%")) "min_lev"
READ_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) "abil_fx_num"
READ_SHORT ("%abil_off%" + 0x20 + (0x28 * "%index%")) "abil_fx_idx"
PATCH_IF ("%min_lev%" = 1) BEGIN
SET "min_lev" = 9
END
FOR (index2 = 0 ; index2 < abil_fx_num ; index2 = index2 + 1) BEGIN
READ_SHORT ("%fx_off%" + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "opcode"
PATCH_IF ("%opcode%" = 12) BEGIN // damage
READ_LONG ("%fx_off%" + 0x24 + (0x30 * ("%abil_fx_idx%" + "%index2%"))) "save"
PATCH_IF ("%save%" = 0) BEGIN
WRITE_BYTE ("%fx_off%" + 0x04 + (0x30 * ("%abil_fx_idx%" + "%index2%"))) (("%min_lev%" + 1) / 2) // damage
WRITE_BYTE ("%fx_off%" + 0x1c + (0x30 * ("%abil_fx_idx%" + "%index2%"))) ("%min_lev%" / 2) // damage
END ELSE BEGIN
WRITE_BYTE ("%fx_off%" + 0x04 + (0x30 * ("%abil_fx_idx%" + "%index2%"))) ("%min_lev%" / 2) // damage
WRITE_BYTE ("%fx_off%" + 0x1c + (0x30 * ("%abil_fx_idx%" + "%index2%"))) (("%min_lev%" + 1) / 2) // damage
END
END
END
PATCH_IF ("%min_lev%" = 9) BEGIN // if first header
WRITE_SHORT ("%abil_off%" + 0x0e + (0x28 * "%index%")) 12 // corrects range
READ_ASCII ("%abil_off%" + (0x28 * "%index%")) "abil_clone" (0x28)
READ_ASCII ("%fx_off%" + (0x30 * ("%abil_fx_idx%"))) "fx_clone" (0x30 * "%abil_fx_num%")
SET "new_fx" = "%abil_fx_num%"
SET "start_fx" = ("%abil_fx_idx%" + "%abil_fx_num%")
SET "insert" = ("%abil_off%" + (0x28 * ("%index%" + 1)))
END ELSE
PATCH_IF ("%min_lev%" = 10) BEGIN
SET "lev10_exist" = 1
END
END
PATCH_IF ("%lev10_exist%" = 0) BEGIN
SET "level" = 10
INSERT_BYTES (("%fx_off%" + (0x28 * "%new_abil%")) + (0x30 * ("%start_fx%" * ("%new_abil%" + 1)))) (0x30 * "%new_fx%")
WRITE_EVALUATED_ASCII (("%fx_off%" + (0x28 * "%new_abil%")) + (0x30 * ("%start_fx%" * ("%new_abil%" + 1)))) "%fx_clone%"
FOR (index2 = 0 ; index2 < new_fx ; index2 = index2 + 1) BEGIN
READ_SHORT (("%fx_off%" + (0x28 * "%new_abil%")) + (0x30 * ("%index2%" + "%start_fx%" + ("%new_abil%" * "%new_fx%")))) "opcode"
PATCH_IF ("%opcode%" = 12) BEGIN // damage
READ_LONG (("%fx_off%" + (0x28 * "%new_abil%")) + 0x24 + (0x30 * ("%index2%" + "%start_fx%" + ("%new_abil%" * "%new_fx%")))) "save"
PATCH_IF ("%save%" = 0) BEGIN
WRITE_BYTE (("%fx_off%" + (0x28 * "%new_abil%")) + 0x04 + (0x30 * ("%index2%" + "%start_fx%" + ("%new_abil%" * "%new_fx%")))) (("%level%" + 1) / 2) // damage
WRITE_BYTE (("%fx_off%" + (0x28 * "%new_abil%")) + 0x1c + (0x30 * ("%index2%" + "%start_fx%" + ("%new_abil%" * "%new_fx%")))) ("%level%" / 2) // damage
END ELSE BEGIN
WRITE_BYTE (("%fx_off%" + (0x28 * "%new_abil%")) + 0x04 + (0x30 * ("%index2%" + "%start_fx%" + ("%new_abil%" * "%new_fx%")))) ("%level%" / 2) // damage
WRITE_BYTE (("%fx_off%" + (0x28 * "%new_abil%")) + 0x1c + (0x30 * ("%index2%" + "%start_fx%" + ("%new_abil%" * "%new_fx%")))) (("%level%" + 1) / 2) // damage
END
END
END
INSERT_BYTES ("%insert%" + (0x28 * "%new_abil%")) 0x28
WRITE_EVALUATED_ASCII ("%insert%" + (0x28 * "%new_abil%")) "%abil_clone%"
WRITE_SHORT (("%insert%" + (0x28 * "%new_abil%")) + 0x10) "%level%"
WRITE_SHORT (("%insert%" + (0x28 * "%new_abil%")) + 0x1e) "%new_fx%"
SET "new_abil" = "%new_abil%" + 1
END
PATCH_IF ("%new_abil%" > 0) BEGIN
SET "abil_num" = ("%abil_num%" + "%new_abil%")
WRITE_SHORT 0x68 "abil_num"
WRITE_LONG 0x6a ("%fx_off%" + (0x28 * "%new_abil%"))
// re-index everything
FOR (index = 0 ; index < abil_num ; index = index + 1) BEGIN
WRITE_SHORT ("%abil_off%" + 0x20 + (0x28 * "%index%")) "%fx_num%"
READ_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) "abil_fx_num"
SET "fx_num" = "%fx_num%" + "%abil_fx_num%"
END
END
BUT_ONLY_IF_IT_CHANGES
Post edited by Bhryaen on
1
Comments
Desired fix:
The cone would have an angle of roughly 12 degrees, with an area of effect that changes with the caster level. Either do this with multiple .pro files or add a flag in the area effect header of the .pro file format to enable the caster level to be used as a multiple with the radius.
Note that narrow area effect projectiles are tricky to target becuse they have to hit the exact coordinate the target is standing on, it is not enough if the projectile area effect overlaps with the foot circle of the creature. Suggestions to this fix:
a. make the projectile angle a bit wider
b. change the engine so that area effects overlapping the foot circle is enough (or give some other tolerance)
c. set the spell to single target rather than area
-Galactygon
I think we should be able to do this; I'll see what I can bodge together and test. Mods, go ahead and leave the thread here for now, I'll create a new one when I get to it.
Thanks!
-G
There is already a flag for repeating explosions by caster level (separate for priest and wizard).
So another level based flag(s) would fit in. There are also enough flags in the AOE flags bitfield. So this is a "piece of cake".
-Galactygon
SPWI503-
1. Range for Spell Ability #0 changed from 8 (BG2) to 12, though the "Minimum level" is set to 1- even in BG2, not 9. Not sure if this bodes ill or no.
2. A 10th level Spell ability has been added to roster.
3. All Spell Ability levels have consistently two sections for damage, one automatic, the other that can be Saved against (vs Spells). The extra 1d4 dam for uneven splits has been allotted to the Savable portion.
I'll take your word for it. :-) Explains why you wanted a Lvl10 version since the minimum level mage to get the 5th lvl spell is actually 9. So a scroll of this actually casts at the equivalent of Lvl9- i.e. rather than the usual 6th?