CamDawg Posted March 4, 2006 Share Posted March 4, 2006 Trying to tackle a few issues from the Outstanding Bugs thread. Specifically, if you hit a troll with a spell like Finger of Death you get XP for killing the troll and then you can kill it again for more XP once it falls down. The other issue was that poison would kill downed trolls. First a bit of background into how trolls are supposed to work, for those who care. Trolls have monhp1 equipped, designed to keep them from reaching 0 hit points. They have a script that kicks in when they're down below a fixed number of HP (10 or 12) that replaces them with a different troll; i.e. troll01 gets swapped out for troll02 at low HPs. troll02 has one hit point, is immune to everything save fire and acid, and has a script that makes them play dead for a while before turning back into the original troll. In theory this works. Well, they forget poison immunity for the dead trolls, so fire/acid/poison will all permanently kill a troll. Also, the script to check for transforming into the dead troll is a straight HPLT check, so that if you kill the troll with Finger of Death, it still subs the dead troll. Both of these issues are fairly straightforward to fix. The problem is that the creature file substitution is hacky at best, and Bioware apparently didn't want to bother with normal/dead versions of all trolls, especially the main ones. For example, Tor'Gal just dies--no need to drop fire or acid on him. Pretty much any troll that has either a non-standard item or has a DV that needs checking by other scripts simply dies instead of requiring fire/acid to finish. I found a number of other discrepancies: kptrol01 - kptrol04 (Trolls from de'Arnise Keep) Killing with FoD vs melee yields different XP. Listed as 2400 XP, but they use troll02 as their dead form, which is only 1400 XP. kptrol03 is also missing its monhp1.itm, making it unlikely you need to use fire/acid on it at all. The other three have minhp1.itm instead, making them much more powerful. obsice01.cre (Snow Troll from Planar Sphere) Missing monhp1.itm. rogtro01.cre (Sea Troll from Roger's quest) Dead version has 1400 XP while the normal is only 650 XP. trolgi01.cre (Giant Troll, generic) Has minhp1.itm instead of monhp1.itm. The former provides a helluva lot of immunities and other goodies lacking from the latter. As noted above, several 'special' trolls do not require fire/acid to kill: daspitor.cre, datroll.cre (Spirit Troll and Troll from Ust Natha) Trolls locked in Ust Natha cages. No changes needed here. drshnl01.cre (Nilthiri, Druid Grove) From one of the druid stronghold quests, Nilthiri is the troll shaman you must kill to preserve balance. There is a dead version of her, but it is unused. eletro01.cre (Troll, Asylum maze) From one of the asylum test areas, this troll has the Giant Troll head item. His partner, eletro02, still requires fire/acid. grae.cre (Grae, Druid Grove) From the limited wish quest, Grae gives you info on how to find Drush and the gong. Once reaching 1hp, Grae will initiate dialogue, and all of the options lead to EscapeArea() or Kill(Myself). No changes needed. pptroll1.cre (Spirit Troll. Asylum maze) Bogstandard trolls. shtroll.cre (Giant Troll) Creature file used by Shapechange spell. No changes needed. sutroll.cre (Troll, Suldenessellar) Two trolls used in one of the Suldenessellar scenes showing the elves fighting. These two are standard trolls, but their DVs are used by the elf scripts. torgal.cre (Tor'gal, de'Arnise Keep) Tor'gal, from the conclusion of the de'Arnise Keep quest. Should also require fire/acid. trollens.cre (Giant Troll, Druid Grove) A troll from the discarded Rynn Lanthorn lens quest that was supposed to drop a lens. No reason it can't require fire/acid. Fixes on the way. Link to comment
CamDawg Posted March 4, 2006 Author Share Posted March 4, 2006 Oh, I forgot my favorite one. Freshwater trolls turn into giant trolls when they die. Link to comment
CamDawg Posted March 4, 2006 Author Share Posted March 4, 2006 Found a few other errors along the way. // poison immnity for 'dead' trolls COPY_EXISTING ~trolldie.itm~ ~override~ READ_LONG 0x64 "abil_off" READ_SHORT 0x68 "abil_num" READ_LONG 0x6a "fx_off" READ_SHORT 0x70 "fx_num" SET "new_fx" = 1 FOR (index = 0; index < abil_num; index = index + 1) BEGIN READ_SHORT (0x20 + "%abil_off%" + ("%index%" * 0x38)) "abil_fx_idx" WRITE_SHORT (0x20 + "%abil_off%" + ("%index%" * 0x38)) ("%abil_fx_idx%" + "%new_fx%") END WRITE_SHORT 0x70 ("%fx_num%" + "%new_fx%") INSERT_BYTES ("%fx_off%" + ("%fx_num%" * 0x30)) 0x30 WRITE_SHORT ("%fx_off%" + ("%fx_num%" * 0x30)) 101 // immunity to effect WRITE_BYTE ("%fx_off%" + 0x02 + ("%fx_num%" * 0x30)) 1 // target self WRITE_BYTE ("%fx_off%" + 0x08 + ("%fx_num%" * 0x30)) 25 // poison WRITE_BYTE ("%fx_off%" + 0x0c + ("%fx_num%" * 0x30)) 2 // instant/while equipped WRITE_BYTE ("%fx_off%" + 0x12 + ("%fx_num%" * 0x30)) 100 // probability 1 BUT_ONLY_IF_IT_CHANGES // trolls giving double XP if slain by spell or other goodies COPY_EXISTING ~chaltrol.bcs~ ~override~ // giant troll, challenge ~dgtrol01.bcs~ ~override~ // troll, druid grove ~firamb03.bcs~ ~override~ // fire troll ~hgtrl01.bcs~ ~override~ // fire troll ~rogtro01.bcs~ ~override~ // roger's sea troll ~trolde01.bcs~ ~override~ // desert troll ~trolfr01.bcs~ ~override~ // freshwater troll ~trolgi01.bcs~ ~override~ // giant troll ~trolic01.bcs~ ~override~ // ice troll ~trolic03.bcs~ ~override~ // blizzard troll ~troll01.bcs~ ~override~ // generic troll ~trolsi01.bcs~ ~override~ // spirit troll ~trollsm2.bcs~ ~override~ // small troll - lacking timers and such ~trolsn01.bcs~ ~override~ // snow troll ~trolsp01.bcs~ ~override~ // spectral troll DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~HPLT(Myself,\([0-9]+\))~ ~!StateCheck(Myself,STATE_REALLY_DEAD) HPLT(Myself,\1)~ PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "trolfr01" = 0) BEGIN // extra fix for freshwater troll REPLACE_TEXTUALLY ~"TROLGI02"~ ~"trolfr02"~ // freshwater trolls becoming giant trolls when knocked down END COMPILE_BAF_TO_BCS BUT_ONLY_IF_IT_CHANGES // restore Nith's attack script, pt 2: assign script COPY_EXISTING ~drshnl01.cre~ ~override~ WRITE_ASCII 0x258 ~drshnl01~ // race script BUT_ONLY_IF_IT_CHANGES // restore Nith's attack script, pt 1: false() out stuff that'll break COPY_EXISTING ~drshnl01.bcs~ ~override~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~HPLT(Myself,10)~ ~False()~ COMPILE_BAF_TO_BCS BUT_ONLY_IF_IT_CHANGES // trollens should require fire/acid to be killed COPY_EXISTING ~trollens.cre~ ~override~ WRITE_ASCII 0x258 ~troll01~ #8 // transform to fire/acid dead form BUT_ONLY_IF_IT_CHANGES // if killed directly via spell, fire trolls should do groovy death animations EXTEND_TOP ~hgtrl01.bcs~ ~bg2fixpack/baf/hgtrl01.baf~ // trolls lacking the correct 1hp items COPY_EXISTING ~hgtrl01.cre~ ~override~ // fire troll ~kptrol01.cre~ ~override~ // kptrol0[1-4] are trolls from de'Arnise keep ~kptrol02.cre~ ~override~ ~kptrol03.cre~ ~override~ ~kptrol04.cre~ ~override~ ~obsice01.cre~ ~override~ // snow troll from planar sphere ~trolgi01.cre~ ~override~ // generic giant troll ~trollens.cre~ ~override~ // giant troll ADD_CRE_ITEM ~monhp1~ #0 #0 #0 ~NONE~ ~AMULET~ // either adds it new, or forces minhp1 into inventory (and unequipped) BUT_ONLY_IF_IT_CHANGES // XP fixes COPY_EXISTING ~kptrol01.cre~ ~override~ ~kptrol02.cre~ ~override~ ~kptrol03.cre~ ~override~ ~kptrol04.cre~ ~override~ ~rogtro01.cre~ ~override~ WRITE_LONG 0x14 1400 BUT_ONLY_IF_IT_CHANGES // trolls should be knocked down and require fire/acid to destroy; everything from here down is to fix that // create 'dead' or 'knocked down' versions COPY_EXISTING ~drshnl01.cre~ ~override/drshnl02.cre~ ~eletro01.cre~ ~override/eletro03.cre~ ~pptroll1.cre~ ~override/pptroll2.cre~ ~sutroll.cre~ ~override/sutroll2.cre~ ~torgal.cre~ ~override/torgal2.cre~ WRITE_SHORT 0x24 1 // current HP WRITE_SHORT 0x46 10 // natural AC WRITE_SHORT 0x48 10 // effective AC WRITE_BYTE 0x5a 100 // resist cold WRITE_BYTE 0x5b 100 // resist electricity WRITE_BYTE 0x5f 100 // resist magic cold WRITE_BYTE 0x60 100 // resist slashing WRITE_BYTE 0x61 100 // resist crushing WRITE_BYTE 0x62 100 // resist piercing WRITE_BYTE 0x63 100 // resist missile WRITE_BYTE 0x23c 9 // dexterity WRITE_BYTE 0x270 255 // enemy PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "drshnl01" = 0) BEGIN WRITE_ASCII 0x248 ~drshnl03~ END ELSE PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "torgal" = 0) BEGIN WRITE_ASCII 0x248 ~torgal3~ #8 // race script END ELSE BEGIN WRITE_EVALUATED_ASCII 0x248 ~%SOURCE_RES%~ // new script END WRITE_ASCII 0x250 ~~ #32 // blanks all other script references // item changes READ_LONG 0x2bc "itm_off" READ_LONG 0x2c0 "itm_num" FOR (index = 0; index < itm_num; index = index + 1) BEGIN READ_ASCII ("%itm_off%" + (0x14 * "%index%")) "item" PATCH_IF ( ("%item%" STRING_COMPARE_CASE "monhp1" = 0) OR // so they can die ("%item%" STRING_COMPARE_CASE "trollreg" = 0) OR // can't regenerate ("%item%" STRING_COMPARE_CASE "trollspi" = 0) // makes dead spirit troll invisible ) BEGIN WRITE_ASCII ("%itm_off%" + (0x14 * "%index%")) ~trolldie~ END END // spells to transform back from dead to alive COPY_EXISTING ~spin955.spl~ ~override/drshnl03.spl~ ~spin955.spl~ ~override/eletro01.spl~ ~spin955.spl~ ~override/pptroll1.spl~ ~spin955.spl~ ~override/sutroll.spl~ ~spin955.spl~ ~override/torgal3.spl~ 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%" + (("%abil_fx_idx%" + "%index2%") * 0x30)) "opcode" READ_ASCII ("%fx_off%" + 0x14 + (("%abil_fx_idx%" + "%index2%") * 0x30)) "eff_file" PATCH_IF (("%opcode%" = 151) AND ("%eff_file%" STRING_COMPARE_CASE "troll01" = 0)) BEGIN WRITE_EVALUATED_ASCII ("%fx_off%" + 0x14 + (("%abil_fx_idx%" + "%index2%") * 0x30)) "%DEST_RES%" #8 END END END BUT_ONLY_IF_IT_CHANGES // add monhp1 item to prevent death and assign script to force transformation to dead form at low HP COPY_EXISTING ~drshnl01.cre~ ~override~ ~eletro01.cre~ ~override~ ~pptroll1.cre~ ~override~ ~sutroll.cre~ ~override~ ~torgal.cre~ ~override~ ADD_CRE_ITEM ~monhp1~ #0 #0 #0 ~NONE~ ~AMULET~ PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "drshnl01" = 0) BEGIN WRITE_ASCII 0x248 ~drshnl02~ END ELSE PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "eletro01" = 0) BEGIN WRITE_ASCII 0x248 ~eletro03~ END ELSE PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "pptroll1" = 0) BEGIN WRITE_ASCII 0x248 ~pptroll2~ END ELSE PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "sutroll" = 0) BEGIN WRITE_ASCII 0x248 ~sutroll2~ END ELSE PATCH_IF ("%SOURCE_RES%" STRING_COMPARE_CASE "torgal" = 0) BEGIN WRITE_ASCII 0x258 ~torgal2~ #8 // race script END // one-off change for Nilthiri to prevent repeating dialogue COPY_EXISTING ~drshnl01.cre~ ~override/drshnl03.cre~ WRITE_ASCII 0x250 ~~ #8 // no approach and speak script WRITE_BYTE 0x270 255 // enemy WRITE_ASCII 0x2cc ~~ #8 // no dialogue file // one-off change for Tor'gal to prevent repeating dialogue COPY_EXISTING ~torgal.cre~ ~override/torgal3.cre~ WRITE_ASCII 0x248 ~~ #8 // no approach and speak script WRITE_BYTE 0x270 255 // enemy WRITE_ASCII 0x2cc ~~ #8 // no dialogue file // new scripts to transform to dead versions at low HP COPY_EXISTING ~troll01.bcs~ ~override/drshnl02.bcs~ ~troll01.bcs~ ~override/eletro03.bcs~ ~troll01.bcs~ ~override/pptroll2.bcs~ ~troll01.bcs~ ~override/sutroll2.bcs~ ~troll01.bcs~ ~override/torgal2.bcs~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~ChangeAnimationNoEffect("TROLL02")~ ~ChangeAnimationNoEffect("%DEST_RES%")~ COMPILE_BAF_TO_BCS // new scripts to transform from dead to alive after time expires COPY_EXISTING ~troll02.bcs~ ~override/drshnl03.bcs~ ~troll02.bcs~ ~override/eletro01.bcs~ ~troll02.bcs~ ~override/pptroll1.bcs~ ~troll02.bcs~ ~override/sutroll.bcs~ ~troll02.bcs~ ~override/torgal3.bcs~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~ReallyForceSpell(Myself,TROLL_CHANGE)~ ~ReallyForceSpellRES("%DEST_RES%",Myself)~ COMPILE_BAF_TO_BCS edit: fixed a bug in the code Link to comment
CamDawg Posted March 4, 2006 Author Share Posted March 4, 2006 I should note in passing that I am utterly unable to stop poison damage (a la Wyvern's Tail, not the poison effect) from killing downed trolls. Link to comment
cirerrek Posted March 4, 2006 Share Posted March 4, 2006 I should note in passing that I am utterly unable to stop poison damage (a la Wyvern's Tail, not the poison effect) from killing downed trolls. <{POST_SNAPBACK}> Yey! I like to go get Valygar for the Keep Quest and the the Druid Grove quest. Verrrry Niccce! Link to comment
CamDawg Posted March 4, 2006 Author Share Posted March 4, 2006 I should note in passing that I am utterly unable to stop poison damage (a la Wyvern's Tail, not the poison effect) from killing downed trolls. Yey! I like to go get Valygar for the Keep Quest and the the Druid Grove quest. Verrrry Niccce! Valygar's katana uses the poison effect, so it's now blocked. Forgot the contents of hgtrl01.baf: IF Die() THEN RESPONSE #100 CreateVisualEffectObject("ICMAGICH",Myself) CreateVisualEffectObject("SPFIREPI",Myself) DestroySelf() END Link to comment
devSin Posted March 4, 2006 Share Posted March 4, 2006 Did you add reduced damage from poison? For immunity, they're always paired (reduced damage/immunity to poison). Link to comment
cirerrek Posted March 5, 2006 Share Posted March 5, 2006 Valygar's katana uses the poison effect, so it's now blocked. Spoil sport Link to comment
Kish Posted March 5, 2006 Share Posted March 5, 2006 grae.cre (Grae, Druid Grove) From the limited wish quest, Grae gives you info on how to find Drush and the gong. Once reaching 1hp, Grae will initiate dialogue, and all of the options lead to EscapeArea() or Kill(Myself). No changes needed. <{POST_SNAPBACK}> Actually, I can think of a change that would be good here. Would it be possible to have the party stop attacking her when she initiates dialogue? It can be tricky to make sure she survives. Link to comment
cirerrek Posted March 5, 2006 Share Posted March 5, 2006 grae.cre (Grae, Druid Grove) From the limited wish quest, Grae gives you info on how to find Drush and the gong. Once reaching 1hp, Grae will initiate dialogue, and all of the options lead to EscapeArea() or Kill(Myself). No changes needed. <{POST_SNAPBACK}> Actually, I can think of a change that would be good here. Would it be possible to have the party stop attacking her when she initiates dialogue? It can be tricky to make sure she survives. <{POST_SNAPBACK}> I agree with Kish. I've accidentally killed Grae a couple of times when I didn't intend to do so. Although, can you do anything about missiles already in the air? Thinking about what the eSeries does as soon as it sees red circled Grae. Link to comment
CamDawg Posted March 5, 2006 Author Share Posted March 5, 2006 Did you add reduced damage from poison? For immunity, they're always paired (reduced damage/immunity to poison). Ah, there we go. I was looking at the Periapt of Proof Against Poison, which doesn't have this. Adding this makes Wyvern's Tail ineffective. Incidentally... // periapt of proof against poison not preventing poison damage COPY_EXISTING ~amul22.itm~ ~override~ READ_LONG 0x64 "abil_off" READ_SHORT 0x68 "abil_num" READ_LONG 0x6a "fx_off" READ_SHORT 0x70 "fx_num" SET "new_fx" = 1 FOR (index = 0; index < abil_num; index = index + 1) BEGIN READ_SHORT (0x20 + "%abil_off%" + ("%index%" * 0x38)) "abil_fx_idx" WRITE_SHORT (0x20 + "%abil_off%" + ("%index%" * 0x38)) ("%abil_fx_idx%" + "%new_fx%") END WRITE_SHORT 0x70 ("%fx_num%" + "%new_fx%") INSERT_BYTES ("%fx_off%" + ("%fx_num%" * 0x30)) 0x30 WRITE_SHORT ("%fx_off%" + ("%fx_num%" * 0x30)) 173 // reduced damage from poison WRITE_BYTE ("%fx_off%" + 0x02 + ("%fx_num%" * 0x30)) 1 // target self WRITE_LONG ("%fx_off%" + 0x04 + ("%fx_num%" * 0x30)) 100 // damage WRITE_BYTE ("%fx_off%" + 0x0c + ("%fx_num%" * 0x30)) 2 // instant/while equipped WRITE_BYTE ("%fx_off%" + 0x12 + ("%fx_num%" * 0x30)) 100 // probability 1 BUT_ONLY_IF_IT_CHANGES grae.cre (Grae, Druid Grove) From the limited wish quest, Grae gives you info on how to find Drush and the gong. Once reaching 1hp, Grae will initiate dialogue, and all of the options lead to EscapeArea() or Kill(Myself). No changes needed. Actually, I can think of a change that would be good here. Would it be possible to have the party stop attacking her when she initiates dialogue? It can be tricky to make sure she survives. Sure--Grae destroys her minhp1 item in her script before initiating dialogue at low hp. If we delayed it until her Kill(Myself) block, she would keep her minhp1 item on the sole EscapeArea() option in the dialogue. Verified as working: // move grae's minhp1 destruction to dialogue options where she dies; see soa-dlg.d for rest of changes COPY_EXISTING ~grae.bcs~ ~override~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~DestroyItem("minhp1")~ ~~ COMPILE_BAF_TO_BCS BUT_ONLY_IF_IT_CHANGES .d code: REPLACE_ACTION_TEXT ~grae~ ~Kill(Myself)~ ~DestroyItem("minhp1") Kill(Myself)~ REPLACE_ACTION_TEXT ~grae~ ~EscapeArea()~ ~SetInterrupt(FALSE) EscapeArea()~ Link to comment
devSin Posted March 5, 2006 Share Posted March 5, 2006 Make sure you add that to the Resilient Sphere patch. We could just comment out Grae's DestroyItem() entirely (since it doesn't look like it was ever intended for the player to be able to kill her), and not have to touch the dlg at all... Link to comment
devSin Posted March 5, 2006 Share Posted March 5, 2006 There was a discussion somewhere that reduced damage from poison would horribly overpower the cheap SoA items (this includes the periapt, Kangaxx's ring, and some unused sword, IIRC), or at least that there was no evidence it was ever intended to be granted. In unmodded BG2, the only way for the player to get it was class abilities (monk, HL druid), or the ToB hood or anti-venom ring. Link to comment
CamDawg Posted March 5, 2006 Author Share Posted March 5, 2006 Make sure you add that to the Resilient Sphere patch. Got it. We had reduced damage from poison, but not the immunity to poison. We could just comment out Grae's DestroyItem() entirely (since it doesn't look like it was ever intended for the player to be able to kill her), and not have to touch the dlg at all... Does Kill(Myself) override minhp1 items? If so, sweet. There was a discussion somewhere that reduced damage from poison would horribly overpower the cheap SoA items (this includes the periapt, Kangaxx's ring, and some unused sword, IIRC), or at least that there was no evidence it was ever intended to be granted. In unmodded BG2, the only way for the player to get it was class abilities (monk, HL druid), or the ToB hood or anti-venom ring. Meh. I don't see how a description of 'Immune to poison' would preclude poison damage. Are there really enough items/spells that do direct poison damage for this to be a concern? Most poison benefits come from damage over time and disruption of spellcasters, for which the periapt already provides protection. Link to comment
devSin Posted March 5, 2006 Share Posted March 5, 2006 There is nothing that can stop Kill(). I've tested in the past with IMOENHP1 and MINHP1, which run the gamut of immunities. Meh. I don't see how a description of 'Immune to poison' would preclude poison damage. Are there really enough items/spells that do direct poison damage for this to be a concern? Most poison benefits come from damage over time and disruption of spellcasters, for which the periapt already provides protection.Kish might object; otherwise, it doesn't concern me either. If you like it, make sure to hit the ring and the sword (Albruin?), as well as the Protection from Poison scroll. (Actually, I'd whip up an effect iterator to find all items/spells that don't have both.) Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.