From 91e2acaadad87934be42f69957974e66a1d42f41 Mon Sep 17 00:00:00 2001 From: DudeMcDude Date: Fri, 6 May 2016 17:07:21 +0300 Subject: [PATCH] Fixed vanilla bug for Dwarves moving despite web/entangle effects --- TemplePlus/bonus.cpp | 40 +++---------------- TemplePlus/common.cpp | 46 +++++++++++++++++++--- TemplePlus/common.h | 22 +++++------ TemplePlus/d20.cpp | 14 ++++--- TemplePlus/dispatcher.cpp | 65 +++++++++++++++++++++++++++++-- TemplePlus/dispatcher.h | 11 +++++- TemplePlus/fixes/generalfixes.cpp | 27 ++++++++++--- TemplePlus/spell_condition.cpp | 16 ++++++++ 8 files changed, 172 insertions(+), 69 deletions(-) diff --git a/TemplePlus/bonus.cpp b/TemplePlus/bonus.cpp index d8163d132..cd9ae946a 100644 --- a/TemplePlus/bonus.cpp +++ b/TemplePlus/bonus.cpp @@ -125,8 +125,7 @@ uint32_t BonusSystem::bonusCapAddWithDescr(BonusList* bonList, int capType, int return 0; } -uint32_t BonusSystem::isBonusCapped(BonusList* bonList, int bonIdx, int* capperIdx) -{ +uint32_t BonusSystem::isBonusCapped(BonusList* bonList, int bonIdx, int* capperIdx){ bool bonTypeMatch = 0; int32_t capValueLowest = 255; int32_t bonValue = bonList->bonusEntries[bonIdx].bonValue; @@ -150,13 +149,12 @@ uint32_t BonusSystem::isBonusCapped(BonusList* bonList, int bonIdx, int* capperI return bonTypeMatch; } -void BonusSystem::initBonusList(BonusList* bonusList) -{ +void BonusSystem::initBonusList(BonusList* bonusList){ bonusList ->bonCount=0 ; bonusList ->bonCapperCount=0; bonusList ->zeroBonusCount=0; - bonusList ->overallCapLow = 0x80000001; - bonusList ->overallCapHigh = 0x7fffFFFF; + bonusList ->overallCapLow.bonValue = 0x80000001; + bonusList ->overallCapHigh.bonValue = 0x7fffFFFF; bonusList ->bonFlags = 0; } @@ -184,34 +182,8 @@ uint32_t BonusSystem::zeroBonusSetMeslineNum(BonusList* bonList, uint32_t zeroBo return 1; } -uint32_t BonusSystem::bonusSetOverallCap(uint32_t bonFlags, BonusList* bonList, int32_t newCap, int a4, uint32_t bonMesLineNum, char* capDescr) -{ - MesLine mesLine; - if (!bonFlags) return 0; - mesLine.key = bonMesLineNum; - - if (bonMesLineNum >= 335) - mesFuncs.GetLine_Safe(bonusMesNew, &mesLine); - else - mesFuncs.GetLine_Safe(*bonusMesHandle, &mesLine); - - char * bonMesString = (char*)mesLine.value; - if (bonFlags & 1 && (bonList->overallCapHigh > newCap || bonFlags & 4)) - { - bonList->overallCapHigh = newCap; - bonList->field358 = a4; - bonList->overallCapHighBonusMesString = bonMesString; - bonList->overallCapHighDescr = capDescr; - } - if (bonFlags & 2 && (bonList->overallCapHigh < newCap || bonFlags & 4)) - { - bonList->overallCapLow = newCap; - bonList->field368 = a4; - bonList->overallCapLowBonusMesString = bonMesString; - bonList->overallCapLowDescr = capDescr; - } - bonList->bonFlags |= bonFlags; - return 1; +uint32_t BonusSystem::bonusSetOverallCap(uint32_t bonFlags, BonusList* bonList, int32_t newCap, int newCapType, uint32_t bonMesLineNum, char* capDescr){ + return bonList->SetOverallCap(bonFlags, newCap, newCapType, bonMesLineNum, capDescr); } BonusSystem::BonusSystem() diff --git a/TemplePlus/common.cpp b/TemplePlus/common.cpp index 3580740ef..c088f3429 100644 --- a/TemplePlus/common.cpp +++ b/TemplePlus/common.cpp @@ -46,11 +46,11 @@ int BonusList::GetEffectiveBonusSum() const { } } - if (bonFlags & 1 && result > overallCapHigh) { - result = overallCapHigh; + if (bonFlags & 1 && result > overallCapHigh.bonValue) { + result = overallCapHigh.bonValue; } - if (bonFlags & 2 && result < overallCapLow) { - result = overallCapLow; + if (bonFlags & 2 && result < overallCapLow.bonValue) { + result = overallCapLow.bonValue; } return result; @@ -189,6 +189,29 @@ int BonusList::AddCapWithDescr(int capType, int capValue, uint32_t bonMesLineNum return 0; } +BOOL BonusList::SetOverallCap(int newBonFlags, int newCap, int newCapType, int newCapMesLineNum, char *capDescr) { + if (!newBonFlags) + return FALSE; + + auto bonMesString = GetBonusMesLine(newCapMesLineNum); + + if (newBonFlags & 1 && (overallCapHigh.bonValue > newCap || newBonFlags & 4)) { + overallCapHigh.bonValue = newCap; + overallCapHigh.bonType = newCapType; + overallCapHigh.bonusMesString = bonMesString; + overallCapHigh.bonusDescr = capDescr; + } + if (newBonFlags & 2 && (overallCapLow.bonValue < newCap || newBonFlags & 4)) { + overallCapLow.bonValue = newCap; + overallCapLow.bonType = newCapType; + overallCapLow.bonusMesString = bonMesString; + overallCapLow.bonusDescr = capDescr; + } + + bonFlags |= newBonFlags; + return TRUE; +} + objHndl AttackPacket::GetWeaponUsed() const { if ( !(flags& D20CAF_TOUCH_ATTACK) || (flags & D20CAF_THROWN_GRENADE) ) @@ -232,7 +255,18 @@ PointNode::PointNode(float x, float y, float z){ absY = y; } -int BonusList::AddBonus(int value, int bonType, int mesline) -{ +int BonusList::AddBonus(int value, int bonType, int mesline){ return bonusSys.bonusAddToBonusList(this, value, bonType, mesline); } + + +const char* BonusList::GetBonusMesLine(int lineNum) { + MesLine mesLine(lineNum); + + if (lineNum >= 335) + mesFuncs.GetLine_Safe(bonusSys.bonusMesNew, &mesLine); + else + mesFuncs.GetLine_Safe(*bonusSys.bonusMesHandle, &mesLine); + + return mesLine.value; +} \ No newline at end of file diff --git a/TemplePlus/common.h b/TemplePlus/common.h index 1ed8219cc..1a2a1932f 100644 --- a/TemplePlus/common.h +++ b/TemplePlus/common.h @@ -95,7 +95,7 @@ struct BonusEntry { int32_t bonValue; uint32_t bonType; // gets comapred with 0, 8 and 21 in 100E6490; I think these types allow bonuses to stack - char * bonusMesString; // parsable string for the help system e.g. "~Item~[TAG_ITEM]" + const char * bonusMesString; // parsable string for the help system e.g. "~Item~[TAG_ITEM]" char * bonusDescr; // e.g. "Magic Full Plate +1" }; @@ -115,24 +115,17 @@ struct BonusList uint32_t bonCapperCount; uint32_t zeroBonusReasonMesLine[10]; // a line from the bonus.mes that is auto assigned a 0 value (I think it will print ---). Probably for overrides like racial immunity and stuff. uint32_t zeroBonusCount; - int32_t overallCapHigh; // init to largest positive int; controlls what the sum of all the modifiers of various types cannot exceed - uint32_t field358; // looks unused - char * overallCapHighBonusMesString; - char * overallCapHighDescr; - int32_t overallCapLow; //init to most negative int - uint32_t field368; // looks unused - char * overallCapLowBonusMesString; - char * overallCapLowDescr; + BonusEntry overallCapHigh; // init to largest positive int; controlls what the sum of all the modifiers of various types cannot exceed + BonusEntry overallCapLow; //init to most negative int uint32_t bonFlags; // init 0; 0x1 - overallCapHigh set; 0x2 - overallCapLow set; 0x4 - force cap override (otherwise it can only impose restrictions i.e. it will only change the cap if it's lower than the current one) - BonusList() - { + BonusList() { this->bonCount = 0; this->bonCapperCount = 0; this->zeroBonusCount = 0; this->bonFlags = 0; - this->overallCapHigh = 0x7fffFFFF; - this->overallCapLow = 0x80000001; + this->overallCapHigh.bonValue = 0x7fffFFFF; + this->overallCapLow.bonValue = 0x80000001; } int GetEffectiveBonusSum() const; @@ -160,6 +153,9 @@ struct BonusList int AddCap(int capType, int capValue, uint32_t bonMesLineNum); int AddCapWithDescr(int capType, int capValue, uint32_t bonMesLineNum, char* capDescr); + + BOOL SetOverallCap(int BonFlags, int newCap, int newCapType, int newCapMesLineNum, char *capDescr = nullptr); + static const char* GetBonusMesLine(int lineNum); }; const int TestSizeOfBonusList = sizeof(BonusList); // should be 888 (0x378) diff --git a/TemplePlus/d20.cpp b/TemplePlus/d20.cpp index 9fcfc285d..0f772e0b0 100644 --- a/TemplePlus/d20.cpp +++ b/TemplePlus/d20.cpp @@ -702,15 +702,15 @@ objHndl LegacyD20System::GetAttackWeapon(objHndl obj, int attackCode, D20CAF fla } if (flags & D20CAF_SECONDARY_WEAPON) - return inventory.ItemWornAt(obj, 4); + return inventory.ItemWornAt(obj, EquipSlot::WeaponSecondary); if (UsingSecondaryWeapon(obj, attackCode)) - return inventory.ItemWornAt(obj, 4); + return inventory.ItemWornAt(obj, EquipSlot::WeaponSecondary); if (attackCode > ATTACK_CODE_NATURAL_ATTACK) return 0i64; - return inventory.ItemWornAt(obj, 3); + return inventory.ItemWornAt(obj, EquipSlot::WeaponPrimary); } ActionErrorCode D20ActionCallbacks::PerformStandardAttack(D20Actn* d20a) @@ -753,11 +753,15 @@ ActionErrorCode D20ActionCallbacks::PerformTripAttack(D20Actn* d20a) if (!d20a->d20ATarget) return AEC_TARGET_INVALID; + auto performer = d20a->d20APerformer; + + objHndl weaponUsed = d20Sys.GetAttackWeapon(performer, d20a->data1, (D20CAF)d20a->d20Caf); + + d20a->d20Caf |= D20CAF_TOUCH_ATTACK; combatSys.ToHitProcessing(*d20a); //d20Sys.ToHitProc(d20a); - if (animationGoals.PushAttemptAttack(d20a->d20APerformer, d20a->d20ATarget)) - { + if (animationGoals.PushAttemptAttack(d20a->d20APerformer, d20a->d20ATarget)){ d20a->animID = animationGoals.GetAnimIdSthgSub_1001ABB0(d20a->d20APerformer); d20a->d20Caf |= D20CAF_NEED_ANIM_COMPLETED; } diff --git a/TemplePlus/dispatcher.cpp b/TemplePlus/dispatcher.cpp index 77743c42c..17cc338e0 100644 --- a/TemplePlus/dispatcher.cpp +++ b/TemplePlus/dispatcher.cpp @@ -126,10 +126,37 @@ int32_t DispatcherSystem::dispatch1ESkillLevel(objHndl objHnd, SkillEnum skill, } -float DispatcherSystem::Dispatch29hGetMoveSpeed(objHndl objHnd, void* iO) // including modifiers like armor restirction +float DispatcherSystem::Dispatch29hGetMoveSpeed(objHndl objHnd, DispIoMoveSpeed *dispIoIn) // including modifiers like armor restirction { float result = 30.0; - uint32_t objHndLo = (uint32_t)(objHnd & 0xffffFFFF); + + auto dispatcher = gameSystems->GetObj().GetObject(objHnd)->GetDispatcher(); + if (!dispatcher->IsValid()) + return result; + + + DispIoMoveSpeed dispIo; + BonusList bonlist; + if (dispIoIn) { + dispIo.bonlist = dispIoIn->bonlist; + } + else { + dispIo.bonlist = &bonlist; + } + + dispatch.Dispatch40GetBaseMoveSpeed(objHnd, &dispIo); + dispatch.DispatcherProcessor(dispatcher, dispTypeGetMoveSpeed, DK_NONE, &dispIo); + auto moveTot = dispIo.bonlist->GetEffectiveBonusSum(); + + if (dispIo.factor < 0) + dispIo.factor = 0; + if (moveTot < 0) + moveTot = 0; + + result = moveTot * dispIo.factor; + + + /*uint32_t objHndLo = (uint32_t)(objHnd & 0xffffFFFF); uint32_t objHndHi = (uint32_t)((objHnd >>32) & 0xffffFFFF); macAsmProl; __asm{ @@ -145,10 +172,42 @@ float DispatcherSystem::Dispatch29hGetMoveSpeed(objHndl objHnd, void* iO) // inc add esp, 12; fstp result; } - macAsmEpil + macAsmEpil*/ return result; } +float DispatcherSystem::Dispatch40GetBaseMoveSpeed(objHndl objHnd, DispIoMoveSpeed *dispIoIn) +{ + float result = 30.0; + + auto dispatcher = gameSystems->GetObj().GetObject(objHnd)->GetDispatcher(); + if (!dispatcher->IsValid()) + return result; + + + DispIoMoveSpeed dispIo; + BonusList bonlist; + if (dispIoIn) { + dispIo.bonlist = dispIoIn->bonlist; + } + else { + dispIo.bonlist = &bonlist; + } + + dispatch.DispatcherProcessor(dispatcher, dispTypeGetMoveSpeedBase, DK_NONE, &dispIo); + auto bonResult = dispIo.bonlist->GetEffectiveBonusSum(); + + if (dispIoIn) { + dispIoIn->factor = dispIo.factor; + } + + result = bonResult * dispIo.factor; + + return result; +} + + + void DispatcherSystem::dispIOTurnBasedStatusInit(DispIOTurnBasedStatus* dispIOtbStat) { dispIOtbStat->dispIOType = dispIOTypeTurnBasedStatus; diff --git a/TemplePlus/dispatcher.h b/TemplePlus/dispatcher.h index 77dcb6df2..fa8e4de56 100644 --- a/TemplePlus/dispatcher.h +++ b/TemplePlus/dispatcher.h @@ -56,7 +56,8 @@ struct DispatcherSystem : temple::AddressTable void DispatcherClearConds(Dispatcher *dispatcher); int32_t dispatch1ESkillLevel(objHndl objHnd, SkillEnum skill, BonusList * bonOut, objHndl objHnd2, int32_t flag); - float Dispatch29hGetMoveSpeed(objHndl objHnd, void *); + float Dispatch29hGetMoveSpeed(objHndl objHnd, DispIoMoveSpeed * dispIo = nullptr); + float Dispatch40GetBaseMoveSpeed(objHndl objHnd, DispIoMoveSpeed * dispIo = nullptr); void dispIOTurnBasedStatusInit(DispIOTurnBasedStatus* dispIOtbStat); void dispatchTurnBasedStatusInit(objHndl objHnd, DispIOTurnBasedStatus* dispIOtB); @@ -347,7 +348,13 @@ struct DispIoD20ActionTurnBased : DispIO { // dispIoType = 12; matches dispTypes struct DispIoMoveSpeed : DispIO // dispIoType = 13, matches dispTypes 40,41 { BonusList* bonlist; - float moveSpeed; + float factor; + DispIoMoveSpeed() { + dispIOType = dispIOTypeMoveSpeed; + factor = 1.0; + bonlist = nullptr; + } + }; diff --git a/TemplePlus/fixes/generalfixes.cpp b/TemplePlus/fixes/generalfixes.cpp index 1c1201c16..136be7608 100644 --- a/TemplePlus/fixes/generalfixes.cpp +++ b/TemplePlus/fixes/generalfixes.cpp @@ -64,30 +64,32 @@ class DwarfEncumbranceFix: public TempleFix { public: static int EncumberedMoveSpeedCallback(DispatcherCallbackArgs args); + static int DwarfGetMoveSpeed(DispatcherCallbackArgs args); void apply() override { + replaceFunction(0x100EFEC0, DwarfGetMoveSpeed); // recreates Spellslinger fix replaceFunction(0x100EBAA0, EncumberedMoveSpeedCallback); } } dwarfEncumbranceFix; -int DwarfEncumbranceFix::EncumberedMoveSpeedCallback(DispatcherCallbackArgs args) -{ +int DwarfEncumbranceFix::EncumberedMoveSpeedCallback(DispatcherCallbackArgs args){ auto dispIo = dispatch.DispIOCheckIoType13(args.dispIO); if ( dispIo->bonlist->bonFlags == 3) // in case the cap has already been set (e.g. by web/entangle) - recreating the spellslinger fix return 0; if (args.subDispNode->subDispDef->data2 == 324) // overburdened { - bonusSys.bonusSetOverallCap(5, dispIo->bonlist, 5, 0, 324, 0); - bonusSys.bonusSetOverallCap(6, dispIo->bonlist, 5, 0, 324, 0); + dispIo->bonlist->SetOverallCap(5, 5, 0, 324); + dispIo->bonlist->SetOverallCap(6, 5, 0, 324); return 0; } - if (critterSys.GetRace(args.objHndCaller) == Race::race_dwarf) // dwarves do not suffer movement penalty for meidum/heavy encumbrance + if (critterSys.GetRace(args.objHndCaller) == Race::race_dwarf) // dwarves do not suffer movement penalty for medium/heavy encumbrance return 0; if (dispIo->bonlist->bonusEntries[0].bonValue <= 20) // this is probably the explicit form for base speed... { bonusSys.bonusAddToBonusList(dispIo->bonlist, -5, 0, args.subDispNode->subDispDef->data2); - } else + } + else { bonusSys.bonusAddToBonusList(dispIo->bonlist, -10, 0, args.subDispNode->subDispDef->data2); } @@ -95,6 +97,19 @@ int DwarfEncumbranceFix::EncumberedMoveSpeedCallback(DispatcherCallbackArgs args return 0; } +int DwarfEncumbranceFix::DwarfGetMoveSpeed(DispatcherCallbackArgs args){ + + args.dispIO->AssertType(dispIOTypeMoveSpeed); + auto dispIo = static_cast(args.dispIO); + + if (dispIo->bonlist->bonFlags & 2) // in case the cap has already been set (e.g. by web/entangle) - recreating the spellslinger fix + return 0; + + dispIo->bonlist->SetOverallCap(2, args.GetData1(), 0, args.GetData2()); + + return 0; +} + // Putting SpellSlinger's small fixes concentrated here :) class SpellSlingerGeneralFixes : public TempleFix { diff --git a/TemplePlus/spell_condition.cpp b/TemplePlus/spell_condition.cpp index 807e4f54c..56634ac24 100644 --- a/TemplePlus/spell_condition.cpp +++ b/TemplePlus/spell_condition.cpp @@ -40,11 +40,16 @@ class SpellConditionFixes : public TempleFix { static int BootsOfSpeedBonusAttack(DispatcherCallbackArgs args); static int BlinkDefenderMissChance(DispatcherCallbackArgs args); + static int WebOnMoveSpeed(DispatcherCallbackArgs args); + void apply() override { VampiricTouchFix(); enlargePersonModelScaleFix(); + // Replaces sp-WebOn movement speed hook + replaceFunction(0x100CB700, WebOnMoveSpeed); + // Fix for Blink defender miss chance (the conditions for true seeing reducing the chance to 20% was flipped) replaceFunction(0x100C62D0, BlinkDefenderMissChance); @@ -445,3 +450,14 @@ int SpellConditionFixes::BlinkDefenderMissChance(DispatcherCallbackArgs args){ } return 0; } + +int SpellConditionFixes::WebOnMoveSpeed(DispatcherCallbackArgs args){ + args.dispIO->AssertType(dispIOTypeMoveSpeed); + auto dispIo = static_cast(args.dispIO); + if (!d20Sys.d20Query(args.objHndCaller, DK_QUE_Critter_Has_Freedom_of_Movement)) { + dispIo->bonlist->SetOverallCap(1, 0, 0, args.GetData2()); + dispIo->bonlist->SetOverallCap(2, 0, 0, args.GetData2()); + } + + return 0; +}