mirror of
https://github.com/brues-code/nampower.git
synced 2026-10-10 15:40:02 +00:00
add new heal and energize events
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user