mirror of
https://github.com/brues-code/nampower.git
synced 2026-10-03 04:00:01 +00:00
fix bugs with new quickcast mode
This commit is contained in:
@@ -271,4 +271,10 @@ namespace Nampower {
|
||||
void SetNameplateDistance(float distance) {
|
||||
*reinterpret_cast<float *>(Offsets::NameplateDistance) = distance * distance;
|
||||
}
|
||||
|
||||
bool IsTargetingTerrainSpell() {
|
||||
const auto s_needTargets = *reinterpret_cast<uint32_t *>(Offsets::SpellNeedsTargets);
|
||||
return (s_needTargets & game::SpellCastTargetFlags::TARGET_FLAG_SOURCE_LOCATION) ||
|
||||
(s_needTargets & game::SpellCastTargetFlags::TARGET_FLAG_DEST_LOCATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Nampower {
|
||||
|
||||
bool SpellIsAttackTradeskillOrEnchant(const game::SpellRec *spell);
|
||||
|
||||
bool IsTargetingTerrainSpell();
|
||||
|
||||
uint32_t GetGcdOrCooldownForSpell(uint32_t spellId);
|
||||
|
||||
uint32_t GetRemainingGcdOrCooldownForSpell(uint32_t spellId);
|
||||
|
||||
@@ -124,6 +124,7 @@ namespace Nampower {
|
||||
std::unique_ptr<hadesmem::PatchDetour<FastCallPacketHandlerT>> gSpellNonMeleeDmgLogHandlerDetour;
|
||||
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGPlayer_C_OnAttackIconPressedT>> gCGPlayer_C_OnAttackIconPressedDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGActionBar_UseActionT>> gCGActionBar_UseActionDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGUnit_C_OnAuraRemovedT>> gCGUnit_C_OnAuraRemovedDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGUnit_C_OnAuraAddedT>> gCGUnit_C_OnAuraAddedDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGUnit_C_OnAuraAddedStackT>> gCGUnit_C_OnAuraAddedStackDetour;
|
||||
@@ -1060,6 +1061,7 @@ namespace Nampower {
|
||||
|
||||
loadUserVar("NP_RetryServerRejectedSpells");
|
||||
loadUserVar("NP_QuickcastTargetingSpells");
|
||||
loadUserVar("NP_QuickcastOnDoubleCast");
|
||||
loadUserVar("NP_ReplaceMatchingNonGcdCategory");
|
||||
loadUserVar("NP_OptimizeBufferUsingPacketTimings");
|
||||
|
||||
@@ -1103,6 +1105,7 @@ namespace Nampower {
|
||||
|
||||
gSetCVarDetour = createHook<SetCVarT>(process, Offsets::Script_SetCVar, &Script_SetCVarHook);
|
||||
gCGSpellBook_CastSpellDetour = createHook<CGSpellBook_CastSpellT>(process, Offsets::CGSpellBook_CastSpell, &CGSpellBook_CastSpellHook);
|
||||
gCGActionBar_UseActionDetour = createHook<CGActionBar_UseActionT>(process, Offsets::CGActionBar_UseAction, &CGActionBar_UseActionHook);
|
||||
gCastDetour = createHook<CastSpellT>(process, Offsets::Spell_C_CastSpell, &Spell_C_CastSpellHook);
|
||||
gSendCastDetour = createHook<SendCastT>(process, Offsets::SendCast, &SendCastHook);
|
||||
gCancelSpellDetour = createHook<CancelSpellT>(process, Offsets::CancelSpell, &CancelSpellHook);
|
||||
|
||||
+2
-1
@@ -31,7 +31,7 @@ namespace Nampower {
|
||||
|
||||
constexpr uint32_t MAJOR_VERSION = 2;
|
||||
constexpr uint32_t MINOR_VERSION = 15;
|
||||
constexpr uint32_t PATCH_VERSION = 0;
|
||||
constexpr uint32_t PATCH_VERSION = 1;
|
||||
|
||||
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
||||
constexpr int32_t LUA_GLOBALSINDEX = -10001;
|
||||
@@ -100,6 +100,7 @@ namespace Nampower {
|
||||
using Spell_C_GetSpellModifiersT = void (__fastcall *)(const game::SpellRec *spellRec, int *returnVal, game::SpellModOp modOp);
|
||||
|
||||
using CGPlayer_C_OnAttackIconPressedT = int (__fastcall *)(uintptr_t *this_ptr, void *dummy_edx, uint64_t guid);
|
||||
using CGActionBar_UseActionT = void (__fastcall *)(uint32_t param_1, int param_2, int param_3);
|
||||
|
||||
using GetSpellSlotAndTypeT = uint32_t (__fastcall *)(const char *, uint32_t *);
|
||||
using GetSpellSlotFromLuaT = uint32_t (__fastcall *)(int param_1, uint32_t *slot, uint32_t *type);
|
||||
|
||||
@@ -64,6 +64,10 @@ enum class Offsets : std::uint32_t {
|
||||
CGSpellBook_mKnownPetSpells = 0XB6F098,
|
||||
CGSpellBook_CastSpell = 0x004b3300,
|
||||
|
||||
CGActionBar_UseAction = 0x004E5EE0,
|
||||
CGActionBar_mSlotActions = 0X004E5F52,
|
||||
GetSpellIdFromAction = 0x004E5A50,
|
||||
|
||||
IsSpellInRangeOfUnit = 0X004E56F0,
|
||||
CancelSpell = 0x6E4940,
|
||||
CancelAutoRepeatSpell = 0X006EA080,
|
||||
|
||||
+70
-26
@@ -359,42 +359,86 @@ namespace Nampower {
|
||||
|
||||
// check for double cast to trigger quickcast on targeting spells
|
||||
if (gUserSettings.quickcastOnDoubleCast) {
|
||||
// check if needs_targets set
|
||||
auto s_needTargets = *reinterpret_cast<uint32_t *>(Offsets::SpellNeedsTargets);
|
||||
if (s_needTargets & game::SpellCastTargetFlags::TARGET_FLAG_SOURCE_LOCATION ||
|
||||
s_needTargets & game::SpellCastTargetFlags::TARGET_FLAG_DEST_LOCATION) {
|
||||
auto currentTime = GetTime();
|
||||
|
||||
uint32_t spellId = 0;
|
||||
if (bookType == 0) {
|
||||
spellId = *reinterpret_cast<uint32_t *>(
|
||||
static_cast<uint32_t>(Offsets::CGSpellBook_mKnownSpells) + spellSlot * 4);
|
||||
} else if (bookType == 1) {
|
||||
spellId = *reinterpret_cast<uint32_t *>(
|
||||
static_cast<uint32_t>(Offsets::CGSpellBook_mKnownPetSpells) + spellSlot * 4);
|
||||
} else {
|
||||
// call original
|
||||
cgSpellBookCastSpell(spellSlot, bookType, target);
|
||||
uint32_t spellId = 0;
|
||||
if (bookType == 0) {
|
||||
spellId = *reinterpret_cast<uint32_t *>(
|
||||
static_cast<uint32_t>(Offsets::CGSpellBook_mKnownSpells) + spellSlot * 4);
|
||||
} else if (bookType == 1) {
|
||||
spellId = *reinterpret_cast<uint32_t *>(
|
||||
static_cast<uint32_t>(Offsets::CGSpellBook_mKnownPetSpells) + spellSlot * 4);
|
||||
} else {
|
||||
// call original
|
||||
cgSpellBookCastSpell(spellSlot, bookType, target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsTargetingTerrainSpell() && spellId > 0) {
|
||||
if (gCastData.channeling || EffectiveCastEndMs() >= currentTime) {
|
||||
// if we are already casting block action as that will interrupt
|
||||
return;
|
||||
}
|
||||
|
||||
if (spellId > 0) {
|
||||
// check if aoe spell targeting is active
|
||||
if (gLastCastData.attemptSpellId == spellId){
|
||||
auto spell = game::GetSpellInfo(spellId);
|
||||
auto spellName = game::GetSpellName(spellId);
|
||||
// check if aoe spell targeting is active
|
||||
if (gLastCastData.attemptSpellId == spellId) {
|
||||
auto spell = game::GetSpellInfo(spellId);
|
||||
auto spellName = game::GetSpellName(spellId);
|
||||
|
||||
// don't mess with summon guardian
|
||||
if (spell->Effect[0] != game::SPELL_EFFECT_SUMMON_GUARDIAN) {
|
||||
DEBUG_LOG("Double cast detected for targeting spell " << spellName << ", triggering quickcast");
|
||||
TriggerQuickcast();
|
||||
return; // don't cast again
|
||||
// don't mess with summon guardian
|
||||
if (spell->Effect[0] != game::SPELL_EFFECT_SUMMON_GUARDIAN) {
|
||||
DEBUG_LOG(
|
||||
"CastSpell double cast detected for targeting spell " << spellName <<
|
||||
", triggering quickcast");
|
||||
TriggerQuickcast();
|
||||
return; // don't cast again
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cgSpellBookCastSpell(spellSlot, bookType, target);
|
||||
}
|
||||
|
||||
void CGActionBar_UseActionHook(hadesmem::PatchDetourBase *detour, uint32_t actionSlot, int param_2, int param_3) {
|
||||
if (-1 > actionSlot && actionSlot < 120) {
|
||||
uint32_t refValue = 0;
|
||||
|
||||
typedef uint32_t (__fastcall *GetSpellIdFromActionT)(uint32_t actionSlot, uint32_t *refParam);
|
||||
auto getSpellIdFromAction = reinterpret_cast<GetSpellIdFromActionT>(Offsets::GetSpellIdFromAction);
|
||||
|
||||
uint32_t spellId = getSpellIdFromAction(actionSlot, &refValue);
|
||||
if (spellId > 0) {
|
||||
// check for double cast to trigger quickcast on targeting spells
|
||||
if (gUserSettings.quickcastOnDoubleCast) {
|
||||
auto currentTime = GetTime();
|
||||
|
||||
if (IsTargetingTerrainSpell() && spellId > 0) {
|
||||
if (gCastData.channeling || EffectiveCastEndMs() >= currentTime) {
|
||||
// if we are already casting block action as that will interrupt
|
||||
return;
|
||||
}
|
||||
|
||||
// check if aoe spell targeting is active
|
||||
if (gLastCastData.attemptSpellId == spellId) {
|
||||
auto spell = game::GetSpellInfo(spellId);
|
||||
auto spellName = game::GetSpellName(spellId);
|
||||
|
||||
// don't mess with summon guardian
|
||||
if (spell->Effect[0] != game::SPELL_EFFECT_SUMMON_GUARDIAN) {
|
||||
DEBUG_LOG(
|
||||
"Use action double cast detected for targeting spell " << spellName <<
|
||||
", triggering quickcast");
|
||||
TriggerQuickcast();
|
||||
return; // don't cast again
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cgSpellBookCastSpell(spellSlot, bookType, target);
|
||||
}
|
||||
|
||||
auto const useAction = detour->GetTrampolineT<CGActionBar_UseActionT>();
|
||||
return useAction(actionSlot, param_2, param_3);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Nampower {
|
||||
|
||||
void CGSpellBook_CastSpellHook(hadesmem::PatchDetourBase *detour, uint32_t spellSlot, int bookType, uint64_t target);
|
||||
|
||||
void CGActionBar_UseActionHook(hadesmem::PatchDetourBase *detour, uint32_t actionSlot, int param_2, int param_3);
|
||||
|
||||
bool Spell_C_CastSpellHook(hadesmem::PatchDetourBase *detour, uint32_t *casterUnit, uint32_t spellId, uintptr_t *item,
|
||||
std::uint64_t guid);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user