add new heal and energize events

This commit is contained in:
avitasia
2026-01-20 17:58:51 -08:00
parent a4963e01dc
commit 701b0a3c98
10 changed files with 11534 additions and 11143 deletions
+95 -1
View File
@@ -16,6 +16,8 @@ For custom Lua functions, see [SCRIPTS.md](SCRIPTS.md). For general usage inform
- [Buff/Debuff Events](#buffdebuff-events)
- [AURA_CAST_ON_SELF and AURA_CAST_ON_OTHER](#aura_cast_on_self-and-aura_cast_on_other)
- [AUTO_ATTACK_SELF and AUTO_ATTACK_OTHER](#auto_attack_self-and-auto_attack_other)
- [SPELL_HEAL_BY_SELF, SPELL_HEAL_BY_OTHER, and SPELL_HEAL_ON_SELF](#spell_heal_by_self-spell_heal_by_other-and-spell_heal_on_self)
- [SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_OTHER, and SPELL_ENERGIZE_ON_SELF](#spell_energize_by_self-spell_energize_by_other-and-spell_energize_on_self)
- [UNIT_DIED](#unit_died)
---
@@ -150,7 +152,9 @@ Parameters for `SPELL_FAILED_OTHER`:
2. int spellId
### SPELL_DELAYED_SELF and SPELL_DELAYED_OTHER
Fire when a spell is delayed, generally due to taking damage. "Self" fires when the active player is affected, "Other" for other players.
Fire when a spell is delayed, generally due to taking damage. "Self" fires when the active player is affected, "Other" fires for other players.
**Note:** `SPELL_DELAYED_OTHER` currently does not work because the server only sends the spell delayed packet to the affected player. This means you will only ever receive `SPELL_DELAYED_SELF` events for your own spell pushbacks. Leaving `SPELL_DELAYED_OTHER` in case this changes in the future.
Parameters:
1. string casterGuid - caster guid like "0xF5300000000000A5"
@@ -355,6 +359,96 @@ frame:RegisterEvent("AUTO_ATTACK_SELF", onAutoAttack)
frame:RegisterEvent("AUTO_ATTACK_OTHER", onAutoAttack)
```
### SPELL_HEAL_BY_SELF, SPELL_HEAL_BY_OTHER, and SPELL_HEAL_ON_SELF
Fire when a spell healing log is received from the server. These events let you track heals in real-time.
- `SPELL_HEAL_BY_SELF` - Fires when the active player is the caster (you healed someone)
- `SPELL_HEAL_BY_OTHER` - Fires when someone other than the active player is the caster (someone else healed someone)
- `SPELL_HEAL_ON_SELF` - Fires when the active player is the target (you received a heal)
Note that `SPELL_HEAL_BY_SELF` and `SPELL_HEAL_ON_SELF` can both fire for the same heal if you heal yourself.
These events are gated behind the `NP_EnableSpellHealEvents` CVar (default 0). Set it to `1` to enable.
Parameters (same for all three events):
1. string targetGuid - guid of the heal target like "0xF5300000000000A5"
2. string casterGuid - guid of the healer like "0xF5300000000000A5"
3. int spellId - the spell ID that caused the heal
4. int amount - the amount healed
5. int critical - 1 if the heal was a critical, 0 otherwise
6. int periodic - 1 if the heal came from a periodic aura, 0 otherwise
Example:
```lua
local function onHeal(targetGuid, casterGuid, spellId, amount, critical, periodic)
local critText = critical == 1 and " (CRIT)" or ""
local periodicText = periodic == 1 and " (PERIODIC)" or ""
local spellName = GetSpellInfo(spellId) or "Unknown"
DEFAULT_CHAT_FRAME:AddMessage(string.format(
"%s healed %s for %d with %s%s%s",
casterGuid, targetGuid, amount, spellName, critText, periodicText
))
end
frame:RegisterEvent("SPELL_HEAL_BY_SELF", onHeal) -- Heals you cast
frame:RegisterEvent("SPELL_HEAL_BY_OTHER", onHeal) -- Heals others cast
frame:RegisterEvent("SPELL_HEAL_ON_SELF", onHeal) -- Heals you receive
```
### SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_OTHER, and SPELL_ENERGIZE_ON_SELF
Fire when a spell energize log is received from the server (power restoration like mana, rage, energy gains).
- `SPELL_ENERGIZE_BY_SELF` - Fires when the active player is the caster (you restored power to someone)
- `SPELL_ENERGIZE_BY_OTHER` - Fires when someone other than the active player is the caster (someone else restored power)
- `SPELL_ENERGIZE_ON_SELF` - Fires when the active player is the target (you received power)
Note that `SPELL_ENERGIZE_BY_SELF` and `SPELL_ENERGIZE_ON_SELF` can both fire for the same energize if you restore power to yourself.
These events are gated behind the `NP_EnableSpellEnergizeEvents` CVar (default 0). Set it to `1` to enable.
Parameters (same for all three events):
1. string targetGuid - guid of the power recipient like "0xF5300000000000A5"
2. string casterGuid - guid of the caster like "0xF5300000000000A5"
3. int spellId - the spell ID that caused the energize
4. int powerType - the type of power restored (see below)
5. int amount - the amount of power restored
6. int periodic - 1 if the energize came from a periodic aura, 0 otherwise
#### Power Types
```
POWER_MANA = 0 -- Mana
POWER_RAGE = 1 -- Rage
POWER_FOCUS = 2 -- Focus (hunter pets)
POWER_ENERGY = 3 -- Energy
POWER_HAPPINESS = 4 -- Happiness (hunter pets)
POWER_HEALTH = -2 -- Health (0xFFFFFFFE as unsigned)
```
Example:
```lua
local POWER_NAMES = {
[0] = "Mana",
[1] = "Rage",
[2] = "Focus",
[3] = "Energy",
[4] = "Happiness",
}
local function onEnergize(targetGuid, casterGuid, spellId, powerType, amount, periodic)
local powerName = POWER_NAMES[powerType] or "Unknown"
local spellName = GetSpellInfo(spellId) or "Unknown"
local periodicText = periodic == 1 and " (PERIODIC)" or ""
DEFAULT_CHAT_FRAME:AddMessage(string.format(
"%s restored %d %s to %s with %s%s",
casterGuid, amount, powerName, targetGuid, spellName, periodicText
))
end
frame:RegisterEvent("SPELL_ENERGIZE_BY_SELF", onEnergize) -- Power you restore
frame:RegisterEvent("SPELL_ENERGIZE_BY_OTHER", onEnergize) -- Power others restore
frame:RegisterEvent("SPELL_ENERGIZE_ON_SELF", onEnergize) -- Power you receive
```
### UNIT_DIED
Fires when a unit death is recorded in the combat log.
+6
View File
@@ -103,6 +103,10 @@ SET NP_TargetingQueueWindowMs "1000"
- `NP_EnableSpellGoEvents` - Whether to enable SPELL_GO_SELF and SPELL_GO_OTHER events. 0 to disable, 1 to enable. Default is 0.
- `NP_EnableSpellHealEvents` - Whether to enable SPELL_HEAL_BY_SELF, SPELL_HEAL_BY_OTHER, and SPELL_HEAL_ON_SELF events. 0 to disable, 1 to enable. Default is 0.
- `NP_EnableSpellEnergizeEvents` - Whether to enable SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_OTHER, and SPELL_ENERGIZE_ON_SELF events. 0 to disable, 1 to enable. Default is 0.
- `NP_ChannelLatencyReductionPercentage` - The percentage of your latency to subtract from the end of a channel duration to optimize cast time while hopefully not losing any ticks (more explanation below). Default is 75.
- `NP_NameplateDistance` - The distance in yards to display nameplates. Defaults to whatever was set by the game or vanilla tweaks.
@@ -156,6 +160,8 @@ Available events:
- Buff/Debuff Events (BUFF_ADDED_SELF, BUFF_REMOVED_SELF, etc.)
- AURA_CAST_ON_SELF and AURA_CAST_ON_OTHER - Aura application events (fires once per aura effect per target; "Self" fires when the aura lands on the active player, including self-cast with no explicit target; includes aura metadata + amplitude/misc + aura cap bitfield for buff/debuff slots). Handles single-target and multi-target (AOE) spells. Some auras don't have spell effects and won't trigger this; use BUFF/DEBUFF gains for those. Set `NP_EnableAuraCastEvents=1` to enable. See EVENTS.md for details on multi-target behavior and known limitations.
- AUTO_ATTACK_SELF and AUTO_ATTACK_OTHER - Auto attack round events (fires when auto attack hits are processed; includes damage, hit info, victim state, absorb/resist/block amounts). Set `NP_EnableAutoAttackEvents=1` to enable. See EVENTS.md for details.
- SPELL_HEAL_BY_SELF, SPELL_HEAL_BY_OTHER, and SPELL_HEAL_ON_SELF - Spell healing events (fires when spell heals are processed; includes target, caster, spell ID, amount, critical flag, and periodic flag). Set `NP_EnableSpellHealEvents=1` to enable. See EVENTS.md for details.
- SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_OTHER, and SPELL_ENERGIZE_ON_SELF - Spell energize events (fires when power is restored via spells; includes target, caster, spell ID, power type, amount, and periodic flag). Set `NP_EnableSpellEnergizeEvents=1` to enable. See EVENTS.md for details.
- UNIT_DIED - Fires when a unit dies
## Bug Reporting
+11161 -11136
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -1548,6 +1548,14 @@ namespace game {
SPELL_CHANNEL_START = 572,
SPELL_CHANNEL_UPDATE = 573,
SPELL_HEAL_BY_SELF = 574,
SPELL_HEAL_BY_OTHER = 575,
SPELL_HEAL_ON_SELF = 576,
SPELL_ENERGIZE_BY_SELF = 577,
SPELL_ENERGIZE_BY_OTHER = 578,
SPELL_ENERGIZE_ON_SELF = 579,
};
enum TypeMask {
+68 -3
View File
@@ -131,6 +131,8 @@ namespace Nampower {
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gSpellChannelStartHandlerDetour;
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gSpellChannelUpdateHandlerDetour;
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gPlaySpellVisualHandlerDetour;
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gSpellHealingLogHandlerDetour;
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gSpellEnergizeLogHandlerDetour;
std::unique_ptr<hadesmem::PatchDetour<FastCallPacketHandlerT> > gSpellStartHandlerDetour;
std::unique_ptr<hadesmem::PatchDetour<FastCallPacketHandlerT> > gPeriodicAuraLogHandlerDetour;
@@ -683,6 +685,12 @@ namespace Nampower {
} else if (strcmp(cvar, "NP_EnableSpellGoEvents") == 0) {
gUserSettings.enableSpellGoEvents = atoi(value) != 0;
DEBUG_LOG("Set NP_EnableSpellGoEvents to " << gUserSettings.enableSpellGoEvents);
} else if (strcmp(cvar, "NP_EnableSpellHealEvents") == 0) {
gUserSettings.enableSpellHealEvents = atoi(value) != 0;
DEBUG_LOG("Set NP_EnableSpellHealEvents to " << gUserSettings.enableSpellHealEvents);
} else if (strcmp(cvar, "NP_EnableSpellEnergizeEvents") == 0) {
gUserSettings.enableSpellEnergizeEvents = atoi(value) != 0;
DEBUG_LOG("Set NP_EnableSpellEnergizeEvents to " << gUserSettings.enableSpellEnergizeEvents);
} else if (strcmp(cvar, "NP_PreventMountingWhenBuffCapped") == 0) {
gUserSettings.preventMountingWhenBuffCapped = atoi(value) != 0;
DEBUG_LOG("Set NP_PreventMountingWhenBuffCapped to " << gUserSettings.preventMountingWhenBuffCapped);
@@ -775,10 +783,23 @@ namespace Nampower {
}
bool safeRemove(const char *filename) {
if (isFileInUse(filename)) {
return false;
// If file doesn't exist, consider it successfully removed
if (GetFileAttributesA(filename) == INVALID_FILE_ATTRIBUTES) {
return true;
}
return remove(filename) == 0;
// Clear read-only attribute if set
SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL);
// Try to delete with retries
for (int i = 0; i < 3; i++) {
if (DeleteFileA(filename)) {
return true;
}
Sleep(10);
}
return false;
}
bool safeRename(const char *oldname, const char *newname) {
@@ -1027,6 +1048,26 @@ namespace Nampower {
0, // unk2
0); // unk3
char NP_EnableSpellHealEvents[] = "NP_EnableSpellHealEvents";
CVarRegister(NP_EnableSpellHealEvents, // name
nullptr, // help
0, // unk1
gUserSettings.enableSpellHealEvents ? defaultTrue : defaultFalse, // default value address
nullptr, // callback
1, // category
0, // unk2
0); // unk3
char NP_EnableSpellEnergizeEvents[] = "NP_EnableSpellEnergizeEvents";
CVarRegister(NP_EnableSpellEnergizeEvents, // name
nullptr, // help
0, // unk1
gUserSettings.enableSpellEnergizeEvents ? defaultTrue : defaultFalse, // default value address
nullptr, // callback
1, // category
0, // unk2
0); // unk3
char NP_PreventMountingWhenBuffCapped[] = "NP_PreventMountingWhenBuffCapped";
CVarRegister(NP_PreventMountingWhenBuffCapped, // name
nullptr, // help
@@ -1166,6 +1207,8 @@ namespace Nampower {
loadUserVar("NP_EnableAutoAttackEvents");
loadUserVar("NP_EnableSpellStartEvents");
loadUserVar("NP_EnableSpellGoEvents");
loadUserVar("NP_EnableSpellHealEvents");
loadUserVar("NP_EnableSpellEnergizeEvents");
loadUserVar("NP_PreventMountingWhenBuffCapped");
loadUserVar("NP_MinBufferTimeMs");
@@ -1302,6 +1345,10 @@ namespace Nampower {
&SpellChannelStartHandlerHook);
gSpellChannelUpdateHandlerDetour = createHook<PacketHandlerT>(process, Offsets::SpellChannelUpdateHandler,
&SpellChannelUpdateHandlerHook);
gSpellHealingLogHandlerDetour = createHook<PacketHandlerT>(process, Offsets::SpellHealingLogHandler,
&SpellHealingLogHandlerHook);
gSpellEnergizeLogHandlerDetour = createHook<PacketHandlerT>(process, Offsets::SpellEnergizeLogHandler,
&SpellEnergizeLogHandlerHook);
gSpellFailedDetour = createHook<Spell_C_SpellFailedT>(process, Offsets::Spell_C_SpellFailed,
&Spell_C_SpellFailedHook);
gSpellGoDetour = createHook<SpellGoT>(process, Offsets::SpellGo, &SpellGoHook);
@@ -1446,6 +1493,24 @@ namespace Nampower {
char SPELL_CHANNEL_UPDATE[] = "SPELL_CHANNEL_UPDATE";
addCustomEvent(game::SPELL_CHANNEL_UPDATE, SPELL_CHANNEL_UPDATE);
char SPELL_HEAL_BY_SELF[] = "SPELL_HEAL_BY_SELF";
addCustomEvent(game::SPELL_HEAL_BY_SELF, SPELL_HEAL_BY_SELF);
char SPELL_HEAL_BY_OTHER[] = "SPELL_HEAL_BY_OTHER";
addCustomEvent(game::SPELL_HEAL_BY_OTHER, SPELL_HEAL_BY_OTHER);
char SPELL_HEAL_ON_SELF[] = "SPELL_HEAL_ON_SELF";
addCustomEvent(game::SPELL_HEAL_ON_SELF, SPELL_HEAL_ON_SELF);
char SPELL_ENERGIZE_BY_SELF[] = "SPELL_ENERGIZE_BY_SELF";
addCustomEvent(game::SPELL_ENERGIZE_BY_SELF, SPELL_ENERGIZE_BY_SELF);
char SPELL_ENERGIZE_BY_OTHER[] = "SPELL_ENERGIZE_BY_OTHER";
addCustomEvent(game::SPELL_ENERGIZE_BY_OTHER, SPELL_ENERGIZE_BY_OTHER);
char SPELL_ENERGIZE_ON_SELF[] = "SPELL_ENERGIZE_ON_SELF";
addCustomEvent(game::SPELL_ENERGIZE_ON_SELF, SPELL_ENERGIZE_ON_SELF);
}
void FrameScript_CreateEventsHook(hadesmem::PatchDetourBase *detour, int param_1, uint32_t maxEventId) {
+1 -1
View File
@@ -35,7 +35,7 @@ namespace Nampower {
constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic
constexpr uint32_t MAJOR_VERSION = 2;
constexpr uint32_t MINOR_VERSION = 25;
constexpr uint32_t MINOR_VERSION = 26;
constexpr uint32_t PATCH_VERSION = 0;
constexpr int32_t LUA_REGISTRYINDEX = -10000;
+2
View File
@@ -103,6 +103,8 @@ enum class Offsets : std::uint32_t {
SpellCooldownHandler = 0X006E9460,
PeriodicAuraLogHandler = 0X00626DD0,
SpellNonMeleeDmgLogHandler = 0X005E85E0,
SpellHealingLogHandler = 0x005E89C0,
SpellEnergizeLogHandler = 0x005E8A90,
Spell_C_GetCastTime = 0X006E3340,
Spell_C_CastSpell = 0x6E4B60,
+187 -2
View File
@@ -13,6 +13,7 @@ namespace Nampower {
uint32_t lastCastResultTimeMs;
constexpr int MAX_ALLOWED_SPELL_TARGETS = 100;
void SignalEventHook(hadesmem::PatchDetourBase *detour, game::Events eventId) {
auto const signalEvent = detour->GetTrampolineT<SignalEventT>();
signalEvent(eventId);
@@ -80,6 +81,128 @@ namespace Nampower {
delete[] casterGuidStr;
}
void TriggerSpellHealEvent(uint64_t targetGuid,
uint64_t casterGuid,
uint32_t spellId,
uint32_t amount,
uint8_t critical,
uint8_t periodic) {
static char format[] = "%s%s%d%d%d%d";
char *targetGuidStr = ConvertGuidToString(targetGuid);
char *casterGuidStr = ConvertGuidToString(casterGuid);
auto const activePlayerGuid = game::ClntObjMgrGetActivePlayerGuid();
// SPELL_HEAL_BY_SELF/SPELL_HEAL_BY_OTHER based on caster
auto casterEvent = game::SPELL_HEAL_BY_OTHER;
if (casterGuid == activePlayerGuid) {
casterEvent = game::SPELL_HEAL_BY_SELF;
}
((int (__cdecl *)(int eventCode,
char *format,
char *targetGuid,
char *casterGuid,
uint32_t spellId,
uint32_t amount,
uint32_t critical,
uint32_t periodic)) Offsets::SignalEventParam)(
casterEvent,
format,
targetGuidStr,
casterGuidStr,
spellId,
amount,
critical,
periodic);
// SPELL_HEAL_ON_SELF based on target
if (targetGuid == activePlayerGuid) {
((int (__cdecl *)(int eventCode,
char *format,
char *targetGuid,
char *casterGuid,
uint32_t spellId,
uint32_t amount,
uint32_t critical,
uint32_t periodic)) Offsets::SignalEventParam)(
game::SPELL_HEAL_ON_SELF,
format,
targetGuidStr,
casterGuidStr,
spellId,
amount,
critical,
periodic);
}
delete[] targetGuidStr;
delete[] casterGuidStr;
}
void TriggerSpellEnergizeEvent(uint64_t targetGuid,
uint64_t casterGuid,
uint32_t spellId,
uint32_t powerType,
uint32_t amount,
uint8_t periodic) {
static char format[] = "%s%s%d%d%d%d";
char *targetGuidStr = ConvertGuidToString(targetGuid);
char *casterGuidStr = ConvertGuidToString(casterGuid);
auto const activePlayerGuid = game::ClntObjMgrGetActivePlayerGuid();
// SPELL_ENERGIZE_BY_SELF/SPELL_ENERGIZE_BY_OTHER based on caster
auto casterEvent = game::SPELL_ENERGIZE_BY_OTHER;
if (casterGuid == activePlayerGuid) {
casterEvent = game::SPELL_ENERGIZE_BY_SELF;
}
((int (__cdecl *)(int eventCode,
char *format,
char *targetGuid,
char *casterGuid,
uint32_t spellId,
uint32_t powerType,
uint32_t amount,
uint32_t periodic)) Offsets::SignalEventParam)(
casterEvent,
format,
targetGuidStr,
casterGuidStr,
spellId,
powerType,
amount,
periodic);
// SPELL_ENERGIZE_ON_SELF based on target
if (targetGuid == activePlayerGuid) {
((int (__cdecl *)(int eventCode,
char *format,
char *targetGuid,
char *casterGuid,
uint32_t spellId,
uint32_t powerType,
uint32_t amount,
uint32_t periodic)) Offsets::SignalEventParam)(
game::SPELL_ENERGIZE_ON_SELF,
format,
targetGuidStr,
casterGuidStr,
spellId,
powerType,
amount,
periodic);
}
delete[] targetGuidStr;
delete[] casterGuidStr;
}
void Spell_C_SpellFailedHook(hadesmem::PatchDetourBase *detour, uint32_t spellId,
game::SpellCastResult spellResult, int unk1, int unk2, bool failedByServer) {
auto const spellFailed = detour->GetTrampolineT<Spell_C_SpellFailedT>();
@@ -1067,7 +1190,9 @@ namespace Nampower {
case 20: // SPELL_AURA_OBS_MOD_HEALTH
packet->Get(amount); // heal amount
// No custom event for these for now
if (gUserSettings.enableSpellHealEvents) {
TriggerSpellHealEvent(targetGuid, casterGuid, spellId, amount, 0, 1);
}
break;
case 21: // SPELL_AURA_OBS_MOD_MANA
case 24: // SPELL_AURA_PERIODIC_ENERGIZE
@@ -1075,7 +1200,9 @@ namespace Nampower {
packet->Get(amount); // power type amount
// No custom event for these for now
if (gUserSettings.enableSpellEnergizeEvents) {
TriggerSpellEnergizeEvent(targetGuid, casterGuid, spellId, powerType, amount, 1);
}
break;
case 64: // SPELL_AURA_PERIODIC_MANA_LEECH
packet->Get(powerType);
@@ -1163,4 +1290,62 @@ namespace Nampower {
return 1;
}
int SpellHealingLogHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet) {
auto const spellHealingLogHandler = detour->GetTrampolineT<PacketHandlerT>();
auto const rpos = packet->m_read;
uint64_t targetGuid;
packet->GetPackedGuid(targetGuid);
uint64_t casterGuid;
packet->GetPackedGuid(casterGuid);
uint32_t spellId;
packet->Get(spellId);
uint32_t amount;
packet->Get(amount);
uint8_t critical;
packet->Get(critical);
packet->m_read = rpos;
if (gUserSettings.enableSpellHealEvents) {
TriggerSpellHealEvent(targetGuid, casterGuid, spellId, amount, critical, 0);
}
return spellHealingLogHandler(opCode, packet);
}
int SpellEnergizeLogHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet) {
auto const spellEnergizeLogHandler = detour->GetTrampolineT<PacketHandlerT>();
auto const rpos = packet->m_read;
uint64_t targetGuid;
packet->GetPackedGuid(targetGuid);
uint64_t casterGuid;
packet->GetPackedGuid(casterGuid);
uint32_t spellId;
packet->Get(spellId);
uint32_t powerType;
packet->Get(powerType);
uint32_t amount;
packet->Get(amount);
packet->m_read = rpos;
if (gUserSettings.enableSpellEnergizeEvents) {
TriggerSpellEnergizeEvent(targetGuid, casterGuid, spellId, powerType, amount, 0);
}
return spellEnergizeLogHandler(opCode, packet);
}
}
+4
View File
@@ -35,4 +35,8 @@ namespace Nampower {
CDataStore *packet);
int PlaySpellVisualHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet);
int SpellHealingLogHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet);
int SpellEnergizeLogHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet);
}
+2
View File
@@ -32,6 +32,8 @@ struct UserSettings {
bool enableAutoAttackEvents = false;
bool enableSpellStartEvents = false;
bool enableSpellGoEvents = false;
bool enableSpellHealEvents = false;
bool enableSpellEnergizeEvents = false;
bool preventMountingWhenBuffCapped = true;
uint32_t spellQueueWindowMs = 500;