Skip to content

Haste Effects Overriding Improved Haste Fix (Previously Blackrazor Revision)

AbelAbel Member Posts: 785
edited February 2014 in BGII:EE Mods
Original post:
It has always saddened me that my preferred sword doesn't work well with Improved Haste, my preferred spell. So, I made two Blackrazor revised versions that you can use: link. Quick and plain edits with the fabulous DLTCEP! Just place the .itm file of your choice in your override folder (C:\Program Files (x86)\Baldur's Gate II Enhanced Edition\Data\00783\override).

- 1st version simply replaces the Haste effect by Improved Haste.
In my opinion, this is the most 'faithful' revision.
This effect overrides previous Haste effects on the character for the duration (20s). So, Hasted characters will benefit from Improved Haste and Improved Hasted character won't witness any change.

- 2nd version emulates the Haste effect by providing, as per spell description:
* x2 speed movement (not cumulative with boots of speed)
* -2 initiative (actually -2 to weapon speed factor which I guess is not the same but closest I could find)
* +1 attack per round
This revision I find more powerful because you can stack its effects with (Improved) Haste.

Maybe not ideal solutions but the most reasonable I could come up with. Feel free to report/suggest anything.

I did not expect that this little 'fix' would actually prove larger (though not much).
Now, it's not only WeiDU but it also potentially fix issues that are not directly related to Blackrazor.

However, it's not perfect! The features:
- Patches all spells (even in your override) that use the Improved Haste effect
- Adds an Immunity to Haste (all kinds) for the duration of the spell
Yes, it may seem little but it's a nightmare to code!

Now, the limit is since you're immune to all Haste effects, if you cast a spell with Improved Haste effect on a character that is immune, it obviously won't affect him/her. So you'd have to wait until the spell ends to renew the effect. Although I'm not sure if in the base game when you cast a spell over the same one it overrides its effect.

I tested it and it works! Unfortunately, it seems if you use an already written spell (like Improved Haste) on a current game, it doesn't (I used a scroll when I noticed that). So I guess you would have to erase the spell and scribe it again. Ugh!

Also, why didn't I patch Haste effect spells too? Well, the problem with the Haste effect is that it has two types. One for simple Haste, the other for Improved Haste. Unfortunately, when adding an Immunity to this effect, you can't choose to what type it applies. No, Bioware didn't think it could help to make a separate effect for Improved Haste. Ugh!

So, simply extract the files to your main folder (C:\Program Files (x86)\Baldur's Gate II Enhanced Edition\Data\00783) and run the setup. Patched files will be mentioned in the window.
On a side note, it seems my attached file are regularly disappearing?! So, just for history sake I will attach again the old mod.

And for those who are interested, the code below.
It's far from neat so I would welcome any comment.
I spent hours debugging it. Especially figuring out the feature block offsets that are inconveniently set at header level while index is set at extended header level. I don't get the logic... Fortunately, even when IESDP descriptions fail you, there's still Near Infinity and its ability to display offsets.
BACKUP ~abel_imphaste_fix/backup~ AUTHOR ~Abel, http://forum.baldursgate.com/messages/add/Abel~ BEGIN ~Haste Effects Overriding Improved Haste Fix~ REQUIRE_PREDICATE (GAME_IS ~tob bgee bg2ee~) ~Fine!~ //A variable we'll use later OUTER_SET incnum = 0 //Will check every spell even in the override folder COPY_EXISTING_REGEXP GLOB ~.*\.spl~ ~override~ //Spells must be 0x72 at least PATCH_IF (SOURCE_SIZE > 0x71) BEGIN //Get the value of the Extended Header offset READ_LONG 0x64 xheadoff //Get the value of the Extended Header count (number of Extended Header) READ_SHORT 0x68 xheadcnt //Warning! Offset for Feature Block is from Header, not from Extended Header //So, get the value of the Feature Block Table (spell effects of all Extended Headers) offset READ_LONG 0x6a fblocktaboff //As long as there's an header we haven't checked (0x28 or 40 per header) FOR (h = 0; h < xheadcnt; h = h + 1) BEGIN //Get the value of the Feature Block count (number of spell effects) of this Extended Header READ_SHORT (h * 0x28 + (xheadoff + 0x1e)) fblockcnt //Get the value of the Feature Block TABLE Index of this Extended Header READ_SHORT (h * 0x28 + (xheadoff + 0x20)) fblocktabin //Get the value of the Feature Block offset FOR this Extended Header //Warning! Each Feature Block is 0x30 long SET fblockoff = (fblocktabin * 0x30) + fblocktaboff //As long as there's a block we haven't checked (0x30 or 48 per block) //PATCH_PRINT ~xheadoff %xheadoff% - h %h% - fblocktabin %fblocktabin%~ FOR (b = fblockcnt; b > 0; b = b - 1) BEGIN //Get the value of the opcode and param2 of this Feature Block READ_SHORT ((b - 1) * 0x30 + fblockoff) opcode READ_LONG (fblockoff + 0x8) param2 //PATCH_PRINT ~b %b% - fblockoff %fblockoff% - fblockcnt %fblockcnt% - opcode %opcode% - param2 %param2%~ //If Improved Haste opcode is detected //Warning! Opcodes are in decimal value! WTF IESDP?! PATCH_IF ((opcode = 16) AND (param2 = 1)) BEGIN //Get all other offsets values of this Feature Block READ_BYTE (fblockoff + 0x2) target READ_BYTE (fblockoff + 0x3) power READ_LONG (fblockoff + 0x4) param1 READ_BYTE (fblockoff + 0xc) timing READ_BYTE (fblockoff + 0xd) resist READ_LONG (fblockoff + 0xe) duration READ_BYTE (fblockoff + 0x12) prob1 READ_BYTE (fblockoff + 0x13) prob2 READ_ASCII (fblockoff + 0x14) resource READ_LONG (fblockoff + 0x1c) dicenum READ_LONG (fblockoff + 0x20) dicetype READ_LONG (fblockoff + 0x24) savetype READ_LONG (fblockoff + 0x28) savebonus READ_LONG (fblockoff + 0x2c) unknown //Update the value of the Feature Block count offset of this Extended Header WRITE_SHORT (h * 0x28 + (xheadoff + 0x1e)) (fblockcnt + 1) //Increment the value of the Feature Block TABLE Index of the NEXT Extended Header //Warning! Use a variable to keep tracks of all incrementation SET incnum = incnum + 1 READ_SHORT ((h + 1) * 0x28 + (xheadoff + 0x20)) nextfblocktabin WRITE_SHORT ((h + 1) * 0x28 + (xheadoff + 0x20)) (nextfblocktabin + incnum) //Add a new Feature Block SET newfblockoff = fblockoff + fblockcnt * 0x30 INSERT_BYTES newfblockoff 0x30 //PATCH_PRINT ~newfblockoff %newfblockoff% - resource %resource% nextfblocktabin %nextfblocktabin% incnum %incnum%~ //Set its opcode to protect from Haste opcode WRITE_LONG newfblockoff 101 WRITE_LONG (newfblockoff + 0x8) 16 //Copy all offsets values we got except opcode and param2 WRITE_BYTE (newfblockoff + 0x2) target WRITE_BYTE (newfblockoff + 0x3) power WRITE_LONG (newfblockoff + 0x4) param1 WRITE_BYTE (newfblockoff + 0xc) timing WRITE_BYTE (newfblockoff + 0xd) resist WRITE_LONG (newfblockoff + 0xe) duration WRITE_BYTE (newfblockoff + 0x12) prob1 WRITE_BYTE (newfblockoff + 0x13) prob2 WRITE_EVALUATED_ASCII (newfblockoff + 0x14) ~%resource%~ WRITE_LONG (newfblockoff + 0x1c) dicenum WRITE_LONG (newfblockoff + 0x20) dicetype WRITE_LONG (newfblockoff + 0x24) savetype WRITE_LONG (newfblockoff + 0x28) savebonus WRITE_LONG (newfblockoff + 0x2c) unknown //Close the loop SET b = 0 //Print resource file patched PATCH_PRINT ~Patched %SOURCE_RES%~ END END END END BUT_ONLY_IF_IT_CHANGES
Post edited by Abel on

Comments

  • LathlaerLathlaer Member Posts: 475
    That's a nice revision and should keep this awesome blade useful till the end of ToB.

    One question: I want to make my Blackrazor completely black. Right now the flames are on the grey-ish scale. What is the gradient number for black? (Equipping Effect: change colour by palette)?
  • AbelAbel Member Posts: 785
    Hey @Lathlaer, thanks :) ! I was thinking about making a WeiDU. Easier to manage and uninstall!
    So about your question, I made a quick search on the IESDP and I found this. Hope it helps ;) !
  • LathlaerLathlaer Member Posts: 475
    @Abel Thanks for your help, it worked :) The blade itself is still white, but the flames are black. I don't suppose anything can be done with the white core, but that's still improvement :)
  • AbelAbel Member Posts: 785
    @Lathlaer Did you try changing the color of the other parts as well?
    I see there are two others in the item file.
    Don't know if that would work though. I never tried it myself!
    I've never given much attention to it, but if there's an actual item that comes close to what you want, maybe you should try to imitate its effects. Just guessing there :)
  • LathlaerLathlaer Member Posts: 475
    Unfortunately I don't know every blade in game from memory :D

    There is quillon and grip there only, I'm afraid. The core and the flames are both considered location 21 (major part of the blade).
  • DeeDee Member Posts: 10,447
    Set the color indexes to...I think it's 136 that's dark black? Either 136 or 135. The core of the flame is going to be the lightest part of the gradient, for reference.
  • LathlaerLathlaer Member Posts: 475
    @Dee Now we're talking! Thanks very much :)
  • bob_vengbob_veng Member Posts: 2,308
    edited January 2014
    The second version should be incorporated into vanilla.
  • AbelAbel Member Posts: 785
    @bob_veng Haha, you may be right ;) !
    Actually, since Lathlaer bumped this thread I had another idea that could be even closer to the original.

    The normal version uses the Haste opcode which leads to the various problems mentioned above.
    Another possibility would be to replace it by the opcode that casts a spell on specified target (like Foebane).
    In that case, it would be the Haste spell. I looked for an existing version that would cast it on the user only (not the party). I was able to find one that I guess is used by various items. Problem is the duration is 48 instead of 20 which means a slightly modified version would be needed.

    Thing is, I'm not really sure how Haste spells interact with other resources that use effects like free action, slow and really anything that affects movement. A new spell would need to take those into account.
    Finally, and it's also a bug, when you cast a Haste spell on a Whirlwinded character, it screws with the number of attacks.

    Another behavior I thing is unintended is that the level drain and the positive effects aren't simultaneous. My guess is that the game rolls a different random number for each target. I don't see how that could be modified.

    All in all, it's feasible but it would need some time and tinkering, especially with WeiDU that I'm only beginning to understand.
  • bob_vengbob_veng Member Posts: 2,308
    edited January 2014
    @Abel
    if i understand everything correctly, this is what happens when the blackrazor's special ability is activated - the wielder is hasted, but this haste effect overrides the already existing improved haste?
    i have used blackrazor moderately and i think i have noticed this but im not 100% sure (just 95%)

    if that's the case, this is a bug!
    haste must not override improved haste in any instance.

    any solution to that is welcome - both your versions are just fine and the third proposed version (spontaneously cast spell, like foebane) is the best one!
    the duration issue is microscopically minor.

    --- if i got everything right, you should make a bug report. if you don't, i'll do it :)

    in ee, free action disables subsequent haste/slow and removes previous haste/slow
    haste dispels slow (they nullify each other so neither persists)

    the haste effect coming from blacrazor should also obey these rules.
  • AbelAbel Member Posts: 785
    @bob_veng Yes, you're right! It's because it uses 'State: Haste', opcode #16 (see here for more information and DLTCEP to view the item).

    It's good you asked this question, because I actually think there could be an easier way to do this.
    Since as you well said it's a problem of one effect overriding others, why not just protect against it for the duration of the overridden effects?
    So, we could just add an effect to Improved Haste and Whirlwind abilities:
    #101 (0x101) Protection: from Opcode [101]
    Parameter #1: Irrelevant
    Parameter #2: opcode
    Description:
    Gives the targeted creature(s) protection from the opcode specified by the 'opcode' field.
    By setting it to protect from opcode #16, I think it would solve everything. It would need testing of course, but I think that could work.

    I believe I reported it already and you know it's a very ancient and known bug. Some have tried to fix it, but I've never found in a satisfactory manner...
  • bob_vengbob_veng Member Posts: 2,308
    @Abel
    it's been reported more recently and already registered
    http://forum.baldursgate.com/discussion/28624/7402-core-blackrazor-removes-extra-attacks-from-improved-haste-and-greater-whirlwind-hla

    your solution seems correct, you could post it to that thread, it might prove helpful :)
  • AbelAbel Member Posts: 785
    @Lathlaer, @bob_veng and @all
    The mod is done!
    I edited my original post and uploaded the files.
    Finally, you can increase your Strength and heal yourself while under Improved Haste :) !
  • bob_vengbob_veng Member Posts: 2,308
    awesome awesome!
Sign In or Register to comment.