From 226a7d28807c6b6348532c5e1639b50be7fbd2b1 Mon Sep 17 00:00:00 2001 From: DudeMcDude Date: Mon, 11 Apr 2016 22:08:55 +0300 Subject: [PATCH] Finished quivering palm and fixed Craft Wand second crash (grrr) --- TemplePlus/combat.cpp | 7 +++++ TemplePlus/combat.h | 3 +- TemplePlus/condition.cpp | 59 ++++++++++++++++++++++++++++++++++---- TemplePlus/d20.cpp | 20 ++++++++----- TemplePlus/dispatcher.cpp | 8 ++++++ TemplePlus/dispatcher.h | 1 + TemplePlus/tig/tig_mes.cpp | 16 +++++++++++ TemplePlus/tig/tig_mes.h | 3 ++ 8 files changed, 104 insertions(+), 13 deletions(-) diff --git a/TemplePlus/combat.cpp b/TemplePlus/combat.cpp index 654d18833..c558c0ab5 100644 --- a/TemplePlus/combat.cpp +++ b/TemplePlus/combat.cpp @@ -25,6 +25,7 @@ #include "maps.h" #include "tutorial.h" #include "objlist.h" +#include "ui/ui_dialog.h" struct CombatSystemAddresses : temple::AddressTable @@ -219,6 +220,12 @@ void LegacyCombatSystem::FloatCombatLine(objHndl obj, int line, FloatLineColor f floatSys.floatMesLine(obj, 1, static_cast(floatColor), combatLineText); } +void LegacyCombatSystem::FloatTextBubble(objHndl handle, int combatMesLine) +{ + auto combatLineText = GetCombatMesLine(combatMesLine); + uiDialog.ShowTextBubble(handle, handle, combatLineText); +} + int LegacyCombatSystem::IsWithinReach(objHndl attacker, objHndl target) { float reach = critterSys.GetReach(attacker, D20A_UNSPECIFIED_ATTACK); diff --git a/TemplePlus/combat.h b/TemplePlus/combat.h index 9366da218..38f96813d 100644 --- a/TemplePlus/combat.h +++ b/TemplePlus/combat.h @@ -25,6 +25,8 @@ struct LegacyCombatSystem : temple::AddressTable { char * GetCombatMesLine(int line) const; void FloatCombatLine(objHndl obj, int line); void FloatCombatLine(objHndl obj, int line, FloatLineColor floatColor); + void FloatTextBubble(objHndl handle, int combatMesLine); + int IsWithinReach(objHndl attacker, objHndl target); BOOL CanMeleeTargetAtLoc(objHndl obj, objHndl target, LocAndOffsets* loc); // checks if obj is able to hit target if the TARGET is at loc @@ -48,7 +50,6 @@ struct LegacyCombatSystem : temple::AddressTable { void TurnStart2( int initiativeIdx); void CombatAdvanceTurn(objHndl obj); BOOL IsBrawlInProgress(); - uint32_t* combatModeActive; bool isCombatActive(); uint32_t IsCloseToParty(objHndl objHnd); diff --git a/TemplePlus/condition.cpp b/TemplePlus/condition.cpp index cc4e7c738..0aa314087 100644 --- a/TemplePlus/condition.cpp +++ b/TemplePlus/condition.cpp @@ -183,6 +183,7 @@ class ItemCallbacks class ClassAbilityCallbacks { +#define FeatFunc(fname) static int __cdecl Feat ## fname ## (DispatcherCallbackArgs args) public: // note: conditions obtained from feats always arg0 set to the feat enum (automatically) static int __cdecl FeatDamageReduction(DispatcherCallbackArgs args); @@ -196,16 +197,20 @@ class ClassAbilityCallbacks static int __cdecl FeatQuiveringPalmAvailable(DispatcherCallbackArgs args); + // Timed effect callbacks; assumption: num of rounds remaining is at arg[2] static int __cdecl GetNumRoundsRemaining(DispatcherCallbackArgs args); static int __cdecl TimedEffectCountdown(DispatcherCallbackArgs args); - + // Diamond Soul + static int __cdecl FeatDiamondSoulInit(DispatcherCallbackArgs args); + static int __cdecl FeatDiamondSoulSpellResistanceMod(DispatcherCallbackArgs args); } classAbilityCallbacks; class GenericCallbacks { +#define CBFunc(fname) static int __cdecl fname ## (DispatcherCallbackArgs args) public: static int QuerySetReturnVal1(DispatcherCallbackArgs args); static int QuerySetReturnVal0(DispatcherCallbackArgs); @@ -220,7 +225,8 @@ class GenericCallbacks static int EtherealDamageDealingNull(DispatcherCallbackArgs); static int EtherealOnRemove(DispatcherCallbackArgs); - + static int __cdecl SpellResistanceQuery(DispatcherCallbackArgs args); + static int __cdecl SpellResistanceTooltip(DispatcherCallbackArgs args); } genericCallbacks; @@ -598,6 +604,25 @@ int GenericCallbacks::EtherealOnRemove(DispatcherCallbackArgs args) return 0; } +int GenericCallbacks::SpellResistanceQuery(DispatcherCallbackArgs args){ + auto srMod = args.GetCondArg(1); + auto dispIo = dispatch.DispIoCheckIoType7(args.dispIO); + dispIo->data1 = srMod; + dispIo->return_val = 1; + dispIo->data2 = 0; + return 0; +} + +int GenericCallbacks::SpellResistanceTooltip(DispatcherCallbackArgs args){ + + auto dispIo = dispatch.DispIoCheckIoType9(args.dispIO); + auto srMod = args.GetCondArg(1); + string text( fmt::format("{} [{}]" ,combatSys.GetCombatMesLine(args.GetData1()), srMod) ); + + dispIo->Append(text); + + return 0; +} int GenericCallbacks::EffectTooltip(DispatcherCallbackArgs args) { @@ -1579,9 +1604,10 @@ void ConditionSystem::RegisterNewConditions() #pragma endregion - mCondCraftWandLevelSet = CondStructNew("Craft Wand Level Set", 2); - mCondCraftWandLevelSet.AddHook(dispTypeD20Query, DK_QUE_Craft_Wand_Spell_Level, QueryRetrun1GetArgs, (uint32_t)&mCondCraftWandLevelSet, 0); - mCondCraftWandLevelSet.AddHook(dispTypeRadialMenuEntry, DK_NONE, CraftWandRadialMenu); + //mCondCraftWandLevelSet = + static CondStructNew craftWandSetLev("Craft Wand Level Set", 2); + craftWandSetLev.AddHook(dispTypeD20Query, DK_QUE_Craft_Wand_Spell_Level, QueryRetrun1GetArgs, (uint32_t)&mCondCraftWandLevelSet, 0); + craftWandSetLev.AddHook(dispTypeRadialMenuEntry, DK_NONE, CraftWandRadialMenu); // Aid Another mCondAidAnother = new CondStructNew(); @@ -2791,6 +2817,22 @@ int ClassAbilityCallbacks::TimedEffectCountdown(DispatcherCallbackArgs args){ args.SetCondArg(2, numRoundsRem - 1); return 0; } + +int ClassAbilityCallbacks::FeatDiamondSoulInit(DispatcherCallbackArgs args){ + + auto monkLvl = objects.StatLevelGet(args.objHndCaller, stat_level_monk); + args.SetCondArg(1, monkLvl + 10); + + return 0; +} + +int ClassAbilityCallbacks::FeatDiamondSoulSpellResistanceMod(DispatcherCallbackArgs args) +{ + auto srMod = args.GetCondArg(1); + auto dispIo = dispatch.DispIOCheckIoType14(static_cast(args.dispIO)); + dispIo->bonList->AddBonus(srMod, 36, 203); + return 0; +} #pragma endregion int CaptivatingSongOnConditionAdd(DispatcherCallbackArgs args) @@ -2819,6 +2861,13 @@ void Conditions::AddConditionsToTable(){ static CondStructNew itemSkillBonus("Special Equipment Skill Bonus", 3, false); itemSkillBonus.AddHook(dispTypeSkillLevel, DK_SKILL_APPRAISE, itemCallbacks.SkillBonus, 99, 0); + static CondStructNew diamondSoul("Diamond Soul", 3); + diamondSoul.AddHook(dispTypeConditionAdd, DK_NONE, classAbilityCallbacks.FeatDiamondSoulInit); + diamondSoul.AddHook(dispTypeSpellResistanceMod, DK_NONE, classAbilityCallbacks.FeatDiamondSoulSpellResistanceMod); + diamondSoul.AddHook(dispTypeD20Query, DK_QUE_Critter_Has_Spell_Resistance, genericCallbacks.SpellResistanceQuery); + diamondSoul.AddHook(dispTypeTooltip, DK_NONE, genericCallbacks.SpellResistanceTooltip, 5048, 0); + diamondSoul.AddToFeatDictionary(FEAT_MONK_DIAMOND_SOUL); + static CondStructNew perfectSelf("Perfect Self", 3); perfectSelf.AddHook(dispTypeTakingDamage2, DK_NONE, classAbilityCallbacks.FeatDamageReduction, 0x4, 0); // 0x4 denotes Magical attacks perfectSelf.AddToFeatDictionary(FEAT_MONK_PERFECT_SELF, FEAT_INVALID, 10); diff --git a/TemplePlus/d20.cpp b/TemplePlus/d20.cpp index d5b4a8721..dd584f62a 100644 --- a/TemplePlus/d20.cpp +++ b/TemplePlus/d20.cpp @@ -26,6 +26,8 @@ #include "d20_obj_registry.h" #include "gamesystems/gamesystems.h" #include "gamesystems/objects/objsystem.h" +#include "damage.h" +#include "history.h" static_assert(sizeof(D20SpellData) == (8U), "D20SpellData structure has the wrong size!"); //shut up compiler, this is ok @@ -277,11 +279,10 @@ void LegacyD20System::NewD20ActionsInit() d20Defs[d20Type].turnBasedStatusCheck = d20Callbacks.StdAttackTurnBasedStatusCheck; d20Defs[d20Type].actionCheckFunc = d20Callbacks.ActionCheckQuiveringPalm; d20Defs[d20Type].locCheckFunc = addresses.LocationCheckStdAttack; - d20Defs[d20Type].performFunc = d20Callbacks.PerformQuiveringPalm; d20Defs[d20Type].actionFrameFunc = d20Callbacks.ActionFrameQuiveringPalm; d20Defs[d20Type].actionCost = d20Callbacks.ActionCostStandardAttack; - d20Defs[d20Type].seqRenderFunc = nullptr; + d20Defs[d20Type].seqRenderFunc = addresses._PickerFuncTooltipToHitChance; d20Defs[d20Type].flags = (D20ADF)(D20ADF_TargetSingleExcSelf | D20ADF_TriggersCombat | D20ADF_UseCursorForPicking); @@ -1210,13 +1211,18 @@ ActionErrorCode D20ActionCallbacks::ActionFrameQuiveringPalm(D20Actn* d20a){ objHndl performer = d20a->d20APerformer; d20Sys.d20Defs[D20A_STANDARD_ATTACK].actionFrameFunc(d20a); + if (!(d20a->d20Caf & D20CAF_HIT)) + return AEC_OK; - /*if (combatSys.DisarmCheck(performer, d20a->d20ATarget, d20a)){ - objects.floats->FloatCombatLine(d20a->d20ATarget, 211); - }*/ - - // TODO + auto monkLvl = objects.StatLevelGet(performer, stat_level_monk); + auto wisScore = objects.StatLevelGet(performer, stat_wisdom); + auto dc = 10 + monkLvl / 2 + (wisScore-10)/2; + if (!damage.SavingThrow(performer, d20a->d20ATarget, dc, SavingThrowType::Fortitude, D20STD_F_NONE)){ + critterSys.KillByEffect(d20a->d20ATarget, performer); + histSys.CreateFromFreeText(fmt::format("{} killed by Quivering Palm!", description.getDisplayName(d20a->d20ATarget)).c_str() ); + combatSys.FloatTextBubble(performer, 215); + } return AEC_OK; } diff --git a/TemplePlus/dispatcher.cpp b/TemplePlus/dispatcher.cpp index 8046fb984..6b0d7a579 100644 --- a/TemplePlus/dispatcher.cpp +++ b/TemplePlus/dispatcher.cpp @@ -1050,6 +1050,14 @@ DispIoAttackBonus::DispIoAttackBonus() this->attackPacket.flags = (D20CAF) 0; } +void DispIoTooltip::Append(string& cs) +{ + if (numStrings < 10) + { + strncpy(strings[numStrings++], &cs[0], 0x100); + } +} + DispIoBonusAndObj::DispIoBonusAndObj() { dispIOType = dispIOTypeSkillLevel; diff --git a/TemplePlus/dispatcher.h b/TemplePlus/dispatcher.h index b990c08b9..9a96af34b 100644 --- a/TemplePlus/dispatcher.h +++ b/TemplePlus/dispatcher.h @@ -307,6 +307,7 @@ struct DispIoTooltip : DispIO // DispIoType 9 ; tooltip additional text when hov { char strings[10][256]; uint32_t numStrings; + void Append(std::string& cs); }; const auto TestSizeOfDispIoTooltip = sizeof(DispIoTooltip); // should be 2568 (0xA08) diff --git a/TemplePlus/tig/tig_mes.cpp b/TemplePlus/tig/tig_mes.cpp index 34cf9dd95..cb3a4433c 100644 --- a/TemplePlus/tig/tig_mes.cpp +++ b/TemplePlus/tig/tig_mes.cpp @@ -3,3 +3,19 @@ #include "tig_mes.h" MesFuncs mesFuncs; + +MesLine::MesLine() +{ + key = 0; + value = nullptr; +} + +MesLine::MesLine(uint32_t Key){ + key = Key; + value = nullptr; +} + +MesLine::MesLine(uint32_t Key, const char* Line){ + key = Key; + value = Line; +} diff --git a/TemplePlus/tig/tig_mes.h b/TemplePlus/tig/tig_mes.h index 763654bc2..9f5867fb4 100644 --- a/TemplePlus/tig/tig_mes.h +++ b/TemplePlus/tig/tig_mes.h @@ -8,6 +8,9 @@ typedef uint32_t MesHandle; struct MesLine { uint32_t key; const char *value; + MesLine(); + MesLine(uint32_t key); + MesLine(uint32_t key, const char* line); }; struct MesFuncs : temple::AddressTable {