Kulyok Posted November 13, 2006 Share Posted November 13, 2006 As per the title: I've installed BG2 Fixpack V1, and my sorceress can only cast Melf's Minute Meteors once per round. Got the savegame ready, too. No Beta fixes installed. When used with Melf's Minute Meteors, a blade's Offensive Spin could cause the attacks per round to drop to 0.5 due to an overflow issue in the engine. As a workaround, blades can no longer cast Offensive Spin when wielding Minute Meteors. Might it be this one? Btw, I see that Skull Traps can now be cast right across the screen, just like Fireballs. Is it intentional? Link to comment
CamDawg Posted November 13, 2006 Share Posted November 13, 2006 As per the title: I've installed BG2 Fixpack V1, and my sorceress can only cast Melf's Minute Meteors once per round. Got the savegame ready, too. No Beta fixes installed. Will check it out. It should be setting them to 5 and not allowing anything else to modify that. Btw, I see that Skull Traps can now be cast right across the screen, just like Fireballs. Is it intentional? As part of the Spell Range Fixes, yes--Skull Trap's listed range is 20 yards. By way of comparison, visual range is ~30 feet, so it's now effectively the same range as Fireball (which is visual range). Link to comment
Kulyok Posted November 14, 2006 Author Share Posted November 14, 2006 Yes, this is strange indeed. (Your character is a sorcerer, right? Not a mage?) Besides Fixpack, I have Unfinished Business, Quest Pack, last Tweaks(but they never provoked such behavior before), DBG, Banter Pack, Xan and Kivan installed. I guess it's neither of these... Link to comment
Kulyok Posted November 14, 2006 Author Share Posted November 14, 2006 Update: Thankfully, it passed. Sorry for this false alarm. It was there, though, and I still don't know what caused it: perhaps a slow effect of a shadow attack... Anyway, not guilty as charged. Link to comment
Nythrun Posted November 16, 2006 Share Posted November 16, 2006 Please mention it if this happens again. If the engine can't handle this sort of effect stacking, that's important to know Link to comment
CamDawg Posted November 17, 2006 Share Posted November 17, 2006 Based on John's report here, it looks like we've discovered a new method of engine flakiness. I've recoded this fix slightly to only block the ApR modifications of Boon of Lathander and Offensive Spin with a shell spell hack: // Melf's Minute Meteors causing an attack per round overflow bug with certain spells; see spcl521.spl and spcl741 COPY_EXISTING ~melfmet.itm~ ~override~ // Melf's Minute Meteor 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_SHORT 0x70 "glb_fx_num" FOR ("i"="%abil_num%"; "%i%">0; "i"-=1) BEGIN READ_SHORT ("%abil_off%"+(0x38*"%i%")+0x20) "abil_fx_idx" WRITE_SHORT ("%abil_off%"+(0x38*"%i%")+0x20) ("%abil_fx_idx%"+0x02) END // FOR i, repairing extended header effect indices PATCH_IF ("%abil_off%">"%fx_off%") BEGIN WRITE_LONG 0x64 ("%abil_off%"+0x60) SET "abil_off"=("%abil_off%"+0x60) END // PATCH_IF offset re-ordering WRITE_SHORT 0x70 ("%glb_fx_num%"+0x02) INSERT_BYTES ("%fx_off%"+(0x30*"%glb_fx_num%")+0x00) 0x30 // new while equipped effect WRITE_SHORT ("%fx_off%"+(0x30*"%glb_fx_num%")+0x00) 206 // protection from spell WRITE_BYTE ("%fx_off%"+(0x30*"%glb_fx_num%")+0x02) 1 // target: self WRITE_LONG ("%fx_off%"+(0x30*"%glb_fx_num%")+0x04) 0xffffffff // no string WRITE_BYTE ("%fx_off%"+(0x30*"%glb_fx_num%")+0x0c) 2 // timing mode: while equipped WRITE_BYTE ("%fx_off%"+(0x30*"%glb_fx_num%")+0x12) 100 // min probability 100% WRITE_ASCII ("%fx_off%"+(0x30*"%glb_fx_num%")+0x14) ~spcl521a~ // spell INSERT_BYTES ("%fx_off%"+(0x30*"%glb_fx_num%")+0x00) 0x30 // new while equipped effect WRITE_SHORT ("%fx_off%"+(0x30*"%glb_fx_num%")+0x00) 206 // protection from spell WRITE_BYTE ("%fx_off%"+(0x30*"%glb_fx_num%")+0x02) 1 // target: self WRITE_LONG ("%fx_off%"+(0x30*"%glb_fx_num%")+0x04) 0xffffffff // no string WRITE_BYTE ("%fx_off%"+(0x30*"%glb_fx_num%")+0x0c) 2 // timing mode: while equipped WRITE_BYTE ("%fx_off%"+(0x30*"%glb_fx_num%")+0x12) 100 // min probability 100% WRITE_ASCII ("%fx_off%"+(0x30*"%glb_fx_num%")+0x14) ~spcl741a~ // spell END // PATCH_IF filesize sanity check BUT_ONLY_IF_IT_CHANGES // COPY_EXISTING ~melfmet.itm~ closed // use shell spells for ApR modification to avoid issues with MMM; see melfmet.itm COPY_EXISTING ~spcl521.spl~ ~override/spcl521a.spl~ // offensive spin ~spcl741.spl~ ~override/spcl741a.spl~ // boon of lathander WRITE_LONG NAME1 0xffffffff WRITE_LONG NAME2 0xffffffff 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%" WRITE_SHORT ("%abil_off%" + 0x26 + (0x28 * "%index%")) 1 // removes projectile FOR (index2 = 0; index2 < abil_fx_num; index2 = index2 + 1) BEGIN READ_SHORT ("%fx_off%" + (0x30 * "%index2%")) "opcode" PATCH_IF("%opcode%" != 1) BEGIN DELETE_BYTES ("%fx_off%" + (0x30 * "%index2%")) 0x30 // delete effect SET "index2" = ("%index2%" - 1) SET "abil_fx_num" = ("%abil_fx_num%" - 1) END END WRITE_SHORT ("%abil_off%" + 0x1e + (0x28 * "%index%")) "%abil_fx_num%" END BUT_ONLY_IF_IT_CHANGES // use shell spells for ApR modification to avoid issues with MMM; see melfmet.itm COPY_EXISTING ~spcl521.spl~ ~override~ // offensive spin ~spcl741.spl~ ~override~ // boon of lathander READ_LONG 0x64 "abil_off" READ_SHORT 0x68 "abil_num" READ_LONG 0x6a "fx_off" 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" FOR (index2 = 0; index2 < abil_fx_num; index2 = index2 + 1) BEGIN READ_SHORT ("%fx_off%" + (0x30 * "%index2%")) "opcode" PATCH_IF("%opcode%" = 1) BEGIN WRITE_SHORT ("%fx_off%" + (0x30 * "%index2%")) 146 // cast spell WRITE_LONG ("%fx_off%" + 0x08 + (0x30 * "%index2%")) 1 // cast instantly WRITE_ASCIIE ("%fx_off%" + 0x14 + (0x30 * "%index2%")) ~%SOURCE_RES%a~ #8 //resref END END END BUT_ONLY_IF_IT_CHANGES Not nearly as pretty, but should hopefully feature less wonk. Link to comment
Nythrun Posted November 17, 2006 Share Posted November 17, 2006 There's also the casting sequence where you do Offensive Spin first and then cast Melf's, which can also overflow // Melf's Minute Meteors causing an attack per round overflow bug with certain spells COPY_EXISTING ~melfmet.itm~ ~override~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN READ_LONG 0x64 "ho" READ_SHORT 0x68 "hc" READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i" = 0x00; "i" < ("hc" * 0x38); "i" += 0x38) BEGIN READ_SHORT ("ho" + "i" + 0x20) "ei" WRITE_SHORT ("ho" + "i" + 0x20) ("ei" + 0x02) END INSERT_BYTES ("eo" + ("gc" * 0x30) + 0x00) (0x30 * 0x02) FOR ("j" = ("gc" * 0x30); "j" < (("gc" + 0x02) * 0x30); "j" += 0x30) BEGIN WRITE_SHORT ("eo" + "j" + 0x00) 0xce // opcode: protection from spell WRITE_BYTE ("eo" + "j" + 0x02) 0x01 // target: self WRITE_LONG ("eo" + "j" + 0x04) `0x0 // string displayed WRITE_BYTE ("eo" + "j" + 0x0c) 0x02 // timing mode: while equipped WRITE_BYTE ("eo" + "j" + 0x12) 0x64 // minimum probability 100% END WRITE_ASCII ("eo" + ("gc" * 0x30) + 0x14) ~spcl521d~ // resource reference WRITE_ASCII ("eo" + ("gc" * 0x30) + 0x44) ~spcl741d~ // resource reference WRITE_SHORT 0x70 ("gc" + 0x02) END BUT_ONLY_IF_IT_CHANGES COPY_EXISTING ~spcl521.spl~ ~override/spcl521d.spl~ ~spcl741.spl~ ~override/spcl741d.spl~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN WRITE_ASCIIT 0x10 ~~ // completion sound WRITE_SHORT 0x22 0x00 // casting graphics READ_LONG 0x64 "ho" READ_SHORT 0x68 "hc" READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i" = "hc"; "i" > 0x00; "i" -= 0x01) BEGIN WRITE_LONG ("ho" + (("i" - 0x01) * 0x28) + 0x12) 0x00 // casting time READ_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x1e) "ec" WRITE_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x1e) 0x02 //number of effects WRITE_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x20) ("gc" + (("i" - 0x01) * 0x02)) DELETE_BYTES ("eo" + ("ei" * 0x30) + 0x00) (("ec" - 0x02) * 0x30) WRITE_SHORT ("eo" + ("ei" * 0x30) + 0x00) 0x01 // opcode: apr mod WRITE_BYTE ("eo" + ("ei" * 0x30) + 0x02) 0x01 // target: self WRITE_LONG ("eo" + ("ei" * 0x30) + 0x04) 0x01 // modifier WRITE_LONG ("eo" + ("ei" * 0x30) + 0x08) 0x00 // type: cumulative WRITE_ASCIIT ("eo" + ("ei" * 0x30) + 0x14) ~~ // nulling resref WRITE_SHORT ("eo" + ("ei" * 0x30) + 0x30) 0xce // opcode: protection from spell WRITE_BYTE ("eo" + ("ei" * 0x30) + 0x32) 0x01 // target: self WRITE_LONG ("eo" + ("ei" * 0x30) + 0x34) `0x0 // string displayed WRITE_ASCIIT ("eo" + ("ei" * 0x30) + 0x44) ~spwi325~ // melf's meteors END END BUT_ONLY_IF_IT_CHANGES COPY_EXISTING ~spcl521.spl~ ~override/spcl521.spl~ ~spcl741.spl~ ~override/spcl741.spl~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN READ_LONG 0x64 "ho" READ_SHORT 0x68 "hc" READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i" = 0x00; "i" < ("hc" * 0x28); "i" += 0x28) BEGIN READ_SHORT ("ho" + "i" + 0x1e) "ec" READ_SHORT ("ho" + "i" + 0x20) "ei" FOR ("j" = ("ei" * 0x30); "j" < (("ei" + "ec") * 0x30); "j" += 0x30) BEGIN READ_SHORT ("eo" + "j" + 0x00) "op" PATCH_IF (("op" = 0x10) OR ("op" = 0x01)) THEN BEGIN WRITE_SHORT ("eo" + "j" + 0x00) 0x92 // opcode: cast spell WRITE_LONG ("eo" + "j" + 0x04) 0x00 // cast at level WRITE_LONG ("eo" + "j" + 0x08) 0x00 // cast normally WRITE_BYTE ("eo" + "j" + 0x0c) 0x01 // timing mode: instant/permanent WRITE_LONG ("eo" + "j" + 0x0e) 0x00 // duration PATCH_IF (NOT "%SOURCE_RES%" STRING_COMPARE_CASE "spcl521") THEN BEGIN WRITE_ASCII ("eo" + "j" + 0x14) ~spcl521d~ // resref END ELSE PATCH_IF (NOT "%SOURCE_RES%" STRING_COMPARE_CASE "spcl741") THEN BEGIN WRITE_ASCII ("eo" + "j" + 0x14) ~spcl741d~ // resref END END END END END BUT_ONLY_IF_IT_CHANGES I'd be very interested to see if Whirlwind Attack/Greater Whirlwind attack also bug out in these games. // Melf's Minute Meteors causing an attack per round overflow bug with certain spells COPY_EXISTING ~melfmet.itm~ ~override~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN READ_LONG 0x64 "ho" READ_SHORT 0x68 "hc" READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i" = 0x00; "i" < ("hc" * 0x38); "i" += 0x38) BEGIN READ_SHORT ("ho" + "i" + 0x20) "ei" WRITE_SHORT ("ho" + "i" + 0x20) ("ei" + 0x02) END INSERT_BYTES ("eo" + ("gc" * 0x30) + 0x00) (0x30 * 0x02) FOR ("j" = ("gc" * 0x30); "j" < (("gc" + 0x02) * 0x30); "j" += 0x30) BEGIN WRITE_SHORT ("eo" + "j" + 0x00) 0xce // opcode: protection from spell WRITE_BYTE ("eo" + "j" + 0x02) 0x01 // target: self WRITE_LONG ("eo" + "j" + 0x04) `0x0 // string displayed WRITE_BYTE ("eo" + "j" + 0x0c) 0x02 // timing mode: while equipped WRITE_BYTE ("eo" + "j" + 0x12) 0x64 // minimum probability 100% END WRITE_ASCII ("eo" + ("gc" * 0x30) + 0x14) ~spcl521d~ // resource reference WRITE_ASCII ("eo" + ("gc" * 0x30) + 0x44) ~spcl741d~ // resource reference WRITE_SHORT 0x70 ("gc" + 0x02) END BUT_ONLY_IF_IT_CHANGES COPY_EXISTING ~spcl521.spl~ ~override/spcl521d.spl~ ~spcl741.spl~ ~override/spcl741d.spl~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN WRITE_ASCIIT 0x10 ~~ // completion sound WRITE_SHORT 0x22 0x00 // casting graphics READ_LONG 0x64 "ho" READ_SHORT 0x68 "hc" READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i" = "hc"; "i" > 0x00; "i" -= 0x01) BEGIN WRITE_LONG ("ho" + (("i" - 0x01) * 0x28) + 0x12) 0x00 // casting time READ_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x1e) "ec" WRITE_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x1e) 0x02 //number of effects READ_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x20) "ei" WRITE_SHORT ("ho" + (("i" - 0x01) * 0x28) + 0x20) ("gc" + (("i" - 0x01) * 0x02)) DELETE_BYTES ("eo" + ("ei" * 0x30) + 0x00) (("ec" - 0x02) * 0x30) WRITE_SHORT ("eo" + ("ei" * 0x30) + 0x00) 0x01 // opcode: apr mod WRITE_BYTE ("eo" + ("ei" * 0x30) + 0x02) 0x01 // target: self WRITE_LONG ("eo" + ("ei" * 0x30) + 0x04) 0x01 // modifier WRITE_LONG ("eo" + ("ei" * 0x30) + 0x08) 0x00 // type: cumulative WRITE_ASCIIT ("eo" + ("ei" * 0x30) + 0x14) ~~ // nulling resref WRITE_SHORT ("eo" + ("ei" * 0x30) + 0x30) 0xce // opcode: protection from spell WRITE_BYTE ("eo" + ("ei" * 0x30) + 0x32) 0x01 // target: self WRITE_LONG ("eo" + ("ei" * 0x30) + 0x34) `0x0 // string displayed WRITE_ASCIIT ("eo" + ("ei" * 0x30) + 0x44) ~spwi325~ // melf's meteors END END BUT_ONLY_IF_IT_CHANGES COPY_EXISTING ~spcl521.spl~ ~override/spcl521.spl~ ~spcl741.spl~ ~override/spcl741.spl~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN READ_LONG 0x64 "ho" READ_SHORT 0x68 "hc" READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i" = 0x00; "i" < ("hc" * 0x28); "i" += 0x28) BEGIN READ_SHORT ("ho" + "i" + 0x1e) "ec" READ_SHORT ("ho" + "i" + 0x20) "ei" FOR ("j" = ("ei" * 0x30); "j" < (("ei" + "ec") * 0x30); "j" += 0x30) BEGIN READ_SHORT ("eo" + "j" + 0x00) "op" PATCH_IF (("op" = 0x10) OR ("op" = 0x01)) THEN BEGIN WRITE_SHORT ("eo" + "j" + 0x00) 0x92 // opcode: cast spell WRITE_LONG ("eo" + "j" + 0x04) 0x00 // cast at level WRITE_LONG ("eo" + "j" + 0x08) 0x00 // cast normally WRITE_BYTE ("eo" + "j" + 0x0c) 0x01 // timing mode: instant/permanent WRITE_LONG ("eo" + "j" + 0x0e) 0x00 // duration PATCH_IF (NOT "%SOURCE_RES%" STRING_COMPARE_CASE "spcl521") THEN BEGIN WRITE_ASCII ("eo" + "j" + 0x14) ~spcl521d~ // resref END ELSE PATCH_IF (NOT "%SOURCE_RES%" STRING_COMPARE_CASE "spcl741") THEN BEGIN WRITE_ASCII ("eo" + "j" + 0x14) ~spcl741d~ // resref END END END END END BUT_ONLY_IF_IT_CHANGES Link to comment
CamDawg Posted November 25, 2006 Share Posted November 25, 2006 Added, moving to archives. Link to comment
pro5 Posted November 27, 2006 Share Posted November 27, 2006 This last patch doesn't compile. Link to comment
Nythrun Posted November 27, 2006 Share Posted November 27, 2006 The one CamDawg posted, or the one I did? Both should work fine. (I didn't know codeboxes kill the formatting, so it's reposted for easy reading) I just use this locally: COPY_EXISTING ~melfmet.itm~ ~override~ ~eneblade.itm~ ~override~ PATCH_IF (%SOURCE_SIZE% > 0x71) THEN BEGIN READ_LONG 0x6a "eo" READ_SHORT 0x70 "gc" FOR ("i1" = 0x00; "i1" < ("gc" * 0x30); "i1" += 0x30) BEGIN READ_SHORT ("eo" + "i1" + 0x00) "op" PATCH_IF ("op" = 0x01) THEN BEGIN WRITE_LONG ("eo" + "i1" + 0x04) 0x0a WRITE_LONG ("eo" + "i1" + 0x08) 0x00 END END END BUT_ONLY_IF_IT_CHANGES as either one of the previous will still not solve the longstanding bug with other APR granting items. Link to comment
pro5 Posted November 27, 2006 Share Posted November 27, 2006 It was reporting "illegal write" error when I copied it from the codebox (I had to to hit "reply" to be able to copy the whole code, maybe that had something to do with it). Link to comment
Nythrun Posted November 28, 2006 Share Posted November 28, 2006 Well, thanks for checking up By the way, in an unreleased mod I've been twiddling with there's an item that grants +100% cold resistance and displays the cold resistance portrait icon. I thought it would be nice to add an immunity to the cold resistance portrait icon so there wouldn't be duplicates cluttering up the attractive NPCs <CHARNAME> travels with. The cold resistance icon sporadically disappears Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.