mirror of
https://github.com/brues-code/nampower.git
synced 2026-09-21 23:26:54 +00:00
add events for environmental dmg, damage shield, dispels
This commit is contained in:
@@ -43,6 +43,9 @@ For custom Lua functions, see [SCRIPTS.md](SCRIPTS.md). For general usage inform
|
||||
- [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)
|
||||
- [SPELL_MISS_SELF and SPELL_MISS_OTHER](#spell_miss_self-and-spell_miss_other)
|
||||
- [UNIT_DIED](#unit_died)
|
||||
- [ENVIRONMENTAL_DMG_SELF and ENVIRONMENTAL_DMG_OTHER](#environmental_dmg_self-and-environmental_dmg_other)
|
||||
- [DAMAGE_SHIELD_SELF and DAMAGE_SHIELD_OTHER](#damage_shield_self-and-damage_shield_other)
|
||||
- [SPELL_DISPEL_BY_SELF and SPELL_DISPEL_BY_OTHER](#spell_dispel_by_self-and-spell_dispel_by_other)
|
||||
- [Unit GUID Events](#unit-guid-events)
|
||||
- [KEY_DOWN and KEY_UP](#key_down-and-key_up)
|
||||
|
||||
@@ -576,6 +579,105 @@ frame:RegisterEvent("UNIT_DIED", function(guid)
|
||||
end)
|
||||
```
|
||||
|
||||
### ENVIRONMENTAL_DMG_SELF and ENVIRONMENTAL_DMG_OTHER
|
||||
Fire when environmental damage is taken. "Self" fires when the active player is the victim, "Other" fires for any other unit.
|
||||
|
||||
Parameters:
|
||||
1. string unitGuid - guid of the unit that took damage like "0xF5300000000000A5"
|
||||
2. int dmgType - type of environmental damage (see below)
|
||||
3. int damage - amount of damage taken
|
||||
4. int absorb - amount of damage absorbed
|
||||
5. int resist - amount of damage resisted
|
||||
|
||||
#### EnvironmentalDamageType
|
||||
```
|
||||
DAMAGE_EXHAUSTED = 0 -- Fatigue
|
||||
DAMAGE_DROWNING = 1 -- Drowning
|
||||
DAMAGE_FALL = 2 -- Falling
|
||||
DAMAGE_LAVA = 3 -- Lava
|
||||
DAMAGE_SLIME = 4 -- Slime
|
||||
DAMAGE_FIRE = 5 -- Fire
|
||||
DAMAGE_FALL_TO_VOID = 6 -- Fall without durability loss (unused, server seems to convert this to DAMAGE_FALL)
|
||||
```
|
||||
|
||||
Example:
|
||||
```lua
|
||||
local ENV_DMG_NAMES = {
|
||||
[0] = "Exhausted", [1] = "Drowning", [2] = "Fall",
|
||||
[3] = "Lava", [4] = "Slime", [5] = "Fire", [6] = "FallToVoid",
|
||||
}
|
||||
|
||||
local function onEnvDmg(unitGuid, dmgType, damage, absorb, resist)
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
||||
"%s took %d %s damage (absorbed: %d, resisted: %d)",
|
||||
unitGuid, damage, ENV_DMG_NAMES[dmgType] or "Unknown", absorb, resist
|
||||
))
|
||||
end
|
||||
|
||||
frame:RegisterEvent("ENVIRONMENTAL_DMG_SELF", onEnvDmg)
|
||||
frame:RegisterEvent("ENVIRONMENTAL_DMG_OTHER", onEnvDmg)
|
||||
```
|
||||
|
||||
### DAMAGE_SHIELD_SELF and DAMAGE_SHIELD_OTHER
|
||||
Fire when a damage shield (e.g. Thorns, Fire Shield) deals damage to an attacker. "Self" fires when the active player is the shield owner, "Other" fires for any other unit.
|
||||
|
||||
Parameters:
|
||||
1. string unitGuid - guid of the unit whose shield dealt the damage like "0xF5300000000000A5"
|
||||
2. string targetGuid - guid of the attacker who took the shield damage like "0xF5300000000000A5"
|
||||
3. int damage - amount of shield damage dealt
|
||||
4. int spellSchool - school of the shield damage (see below)
|
||||
|
||||
#### Spell School
|
||||
```
|
||||
SPELL_SCHOOL_PHYSICAL = 0
|
||||
SPELL_SCHOOL_HOLY = 1
|
||||
SPELL_SCHOOL_FIRE = 2
|
||||
SPELL_SCHOOL_NATURE = 3
|
||||
SPELL_SCHOOL_FROST = 4
|
||||
SPELL_SCHOOL_SHADOW = 5
|
||||
SPELL_SCHOOL_ARCANE = 6
|
||||
```
|
||||
|
||||
Example:
|
||||
```lua
|
||||
local SCHOOL_NAMES = {
|
||||
[0] = "Physical", [1] = "Holy", [2] = "Fire",
|
||||
[3] = "Nature", [4] = "Frost", [5] = "Shadow", [6] = "Arcane",
|
||||
}
|
||||
|
||||
local function onDamageShield(unitGuid, targetGuid, damage, spellSchool)
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
||||
"%s shield dealt %d %s damage to %s",
|
||||
unitGuid, damage, SCHOOL_NAMES[spellSchool] or "Unknown", targetGuid
|
||||
))
|
||||
end
|
||||
|
||||
frame:RegisterEvent("DAMAGE_SHIELD_SELF", onDamageShield)
|
||||
frame:RegisterEvent("DAMAGE_SHIELD_OTHER", onDamageShield)
|
||||
```
|
||||
|
||||
### SPELL_DISPEL_BY_SELF and SPELL_DISPEL_BY_OTHER
|
||||
Fire when a spell dispel is processed. "Self" fires when the active player performed the dispel, "Other" fires when someone else did.
|
||||
|
||||
Parameters:
|
||||
1. string casterGuid - guid of the unit that performed the dispel like "0xF5300000000000A5"
|
||||
2. string targetGuid - guid of the unit that was dispelled like "0xF5300000000000A5"
|
||||
3. int spellId - spell ID of the spell that was dispelled
|
||||
|
||||
Example:
|
||||
```lua
|
||||
local function onDispel(casterGuid, targetGuid, spellId)
|
||||
local spellName = GetSpellInfo(spellId) or tostring(spellId)
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
||||
"%s dispelled %s from %s",
|
||||
casterGuid, spellName, targetGuid
|
||||
))
|
||||
end
|
||||
|
||||
frame:RegisterEvent("SPELL_DISPEL_BY_SELF", onDispel)
|
||||
frame:RegisterEvent("SPELL_DISPEL_BY_OTHER", onDispel)
|
||||
```
|
||||
|
||||
### KEY_DOWN and KEY_UP
|
||||
Fire when keyboard input is processed by `CSimpleTop::OnKeyDown` / `CSimpleTop::OnKeyUp`. You could accomplish similar already
|
||||
by calling EnableKeyBoard and using 'OnKeyDown' / 'OnKeyUp' scripts but that blocks all keyboard input to the game. You could also poll for IsShiftKeyDown, IsAltKeyDown, in OnUpdate but that was also limiting.
|
||||
|
||||
+14557
-14127
File diff suppressed because it is too large
Load Diff
+21
-1
@@ -1660,7 +1660,27 @@ namespace game {
|
||||
KEY_DOWN = 598,
|
||||
KEY_UP = 599,
|
||||
|
||||
UNIT_CASTEVENT = 600 // superwow
|
||||
UNIT_CASTEVENT = 600, // superwow
|
||||
|
||||
ENVIRONMENTAL_DMG_SELF = 650, // nampower
|
||||
ENVIRONMENTAL_DMG_OTHER = 651, // nampower
|
||||
|
||||
DAMAGE_SHIELD_SELF = 652, // nampower
|
||||
DAMAGE_SHIELD_OTHER = 653, // nampower
|
||||
|
||||
SPELL_DISPEL_BY_SELF = 654, // nampower
|
||||
SPELL_DISPEL_BY_OTHER = 655, // nampower
|
||||
};
|
||||
|
||||
/// Type of environmental damages
|
||||
enum EnvironmentalDamageType {
|
||||
DAMAGE_EXHAUSTED = 0,
|
||||
DAMAGE_DROWNING = 1,
|
||||
DAMAGE_FALL = 2,
|
||||
DAMAGE_LAVA = 3,
|
||||
DAMAGE_SLIME = 4,
|
||||
DAMAGE_FIRE = 5,
|
||||
DAMAGE_FALL_TO_VOID = 6 // seems to be unused, server converts to DAMAGE_FALL
|
||||
};
|
||||
|
||||
typedef enum CHAT_COMMAND_ID {
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace Nampower {
|
||||
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gProcResistHandlerDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gSpellLogMissHandlerDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<PacketHandlerT> > gSpellOrDamageImmuneHandlerDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<UnitCombatLogDispelledT> > gUnitCombatLogDispelledDetour;
|
||||
|
||||
std::unique_ptr<hadesmem::PatchDetour<FastCallPacketHandlerT> > gSpellStartHandlerDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<FastCallPacketHandlerT> > gPeriodicAuraLogHandlerDetour;
|
||||
@@ -171,6 +172,8 @@ namespace Nampower {
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGPetInfo_GetPetSpellActionT> > gCGPetInfo_GetPetSpellActionDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGPetInfo_SendPetActionT> > gCGPetInfo_SendPetActionDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGGameUI_ShowCombatFeedbackT> > gCGGameUI_ShowCombatFeedbackDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<CGUnit_C_HandleEnvironmentDamageT> > gCGUnit_C_HandleEnvironmentDamageDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<UnitCombatLogDamageShieldT> > gUnitCombatLogDamageShieldDetour;
|
||||
std::unique_ptr<hadesmem::PatchDetour<LoadScriptFunctionsT> > gGlueLoadScriptFunctionsDetour;
|
||||
|
||||
// Flags for one-time initialization
|
||||
@@ -1528,6 +1531,8 @@ namespace Nampower {
|
||||
&SpellLogMissHandlerHook);
|
||||
gSpellOrDamageImmuneHandlerDetour = createHook<PacketHandlerT>(process, Offsets::SpellOrDamageImmuneHandler,
|
||||
&SpellOrDamageImmuneHandlerHook);
|
||||
gUnitCombatLogDispelledDetour = createHook<UnitCombatLogDispelledT>(process, Offsets::UnitCombatLogDispelled,
|
||||
&UnitCombatLogDispelledHook);
|
||||
gSpellFailedOtherHandlerDetour = createHook<PacketHandlerT>(process, Offsets::SpellFailedOtherHandler,
|
||||
&SpellFailedOtherHandlerHook);
|
||||
gSpellFailedDetour = createHook<Spell_C_SpellFailedT>(process, Offsets::Spell_C_SpellFailed,
|
||||
@@ -1590,6 +1595,10 @@ namespace Nampower {
|
||||
process, Offsets::CGPetInfo_SendPetAction, &CGPetInfo_SendPetActionHook);
|
||||
gCGGameUI_ShowCombatFeedbackDetour = createHook<CGGameUI_ShowCombatFeedbackT>(
|
||||
process, Offsets::CGGameUI_ShowCombatFeedback, &CGGameUI_ShowCombatFeedbackHook);
|
||||
gCGUnit_C_HandleEnvironmentDamageDetour = createHook<CGUnit_C_HandleEnvironmentDamageT>(
|
||||
process, Offsets::CGUnit_C_HandleEnvironmentDamage, &CGUnit_C_HandleEnvironmentDamageHook);
|
||||
gUnitCombatLogDamageShieldDetour = createHook<UnitCombatLogDamageShieldT>(
|
||||
process, Offsets::UnitCombatLogDamageShield, &UnitCombatLogDamageShieldHook);
|
||||
gLoadScriptFunctionsDetour = createHook<LoadScriptFunctionsT>(process, Offsets::Player_LoadScriptFunctions,
|
||||
&Player_LoadScriptFunctionsHook);
|
||||
gGlueLoadScriptFunctionsDetour = createHook<LoadScriptFunctionsT>(process, Offsets::Glue_LoadScriptFunctions,
|
||||
@@ -1781,6 +1790,24 @@ namespace Nampower {
|
||||
|
||||
char KEY_UP[] = "KEY_UP";
|
||||
addCustomEvent(game::KEY_UP, KEY_UP);
|
||||
|
||||
char ENVIRONMENTAL_DMG_SELF[] = "ENVIRONMENTAL_DMG_SELF";
|
||||
addCustomEvent(game::ENVIRONMENTAL_DMG_SELF, ENVIRONMENTAL_DMG_SELF);
|
||||
|
||||
char ENVIRONMENTAL_DMG_OTHER[] = "ENVIRONMENTAL_DMG_OTHER";
|
||||
addCustomEvent(game::ENVIRONMENTAL_DMG_OTHER, ENVIRONMENTAL_DMG_OTHER);
|
||||
|
||||
char DAMAGE_SHIELD_SELF[] = "DAMAGE_SHIELD_SELF";
|
||||
addCustomEvent(game::DAMAGE_SHIELD_SELF, DAMAGE_SHIELD_SELF);
|
||||
|
||||
char DAMAGE_SHIELD_OTHER[] = "DAMAGE_SHIELD_OTHER";
|
||||
addCustomEvent(game::DAMAGE_SHIELD_OTHER, DAMAGE_SHIELD_OTHER);
|
||||
|
||||
char SPELL_DISPEL_BY_SELF[] = "SPELL_DISPEL_BY_SELF";
|
||||
addCustomEvent(game::SPELL_DISPEL_BY_SELF, SPELL_DISPEL_BY_SELF);
|
||||
|
||||
char SPELL_DISPEL_BY_OTHER[] = "SPELL_DISPEL_BY_OTHER";
|
||||
addCustomEvent(game::SPELL_DISPEL_BY_OTHER, SPELL_DISPEL_BY_OTHER);
|
||||
}
|
||||
|
||||
void FrameScript_CreateEventsHook(hadesmem::PatchDetourBase *detour, int param_1, uint32_t maxEventId) {
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ namespace Nampower {
|
||||
constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic
|
||||
|
||||
constexpr uint32_t MAJOR_VERSION = 3;
|
||||
constexpr uint32_t MINOR_VERSION = 3;
|
||||
constexpr uint32_t PATCH_VERSION = 1;
|
||||
constexpr uint32_t MINOR_VERSION = 4;
|
||||
constexpr uint32_t PATCH_VERSION = 0;
|
||||
|
||||
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
||||
constexpr int32_t LUA_GLOBALSINDEX = -10001;
|
||||
|
||||
@@ -94,6 +94,8 @@ enum class Offsets : std::uint32_t {
|
||||
CGGameUI_HandleObjectTrackChange = 0x00492890,
|
||||
CGGameUI_Target = 0X00493540,
|
||||
CGGameUI_ShowCombatFeedback = 0x00494600,
|
||||
CGUnit_C_HandleEnvironmentDamage = 0x00624f30,
|
||||
UnitCombatLogDamageShield = 0x0062ca20,
|
||||
ScriptTargetUnit = 0X00489A40,
|
||||
|
||||
MouseoverGuidLow = 0x00B4E2C8,
|
||||
@@ -124,6 +126,7 @@ enum class Offsets : std::uint32_t {
|
||||
ProcResistHandler = 0x006289A0,
|
||||
SpellLogMissHandler = 0x005E7E00,
|
||||
SpellOrDamageImmuneHandler = 0x005E8CA0,
|
||||
UnitCombatLogDispelled = 0x0062d480,
|
||||
|
||||
Spell_C_GetCastTime = 0X006E3340,
|
||||
Spell_C_CastSpell = 0x6E4B60,
|
||||
|
||||
@@ -1529,4 +1529,30 @@ namespace Nampower {
|
||||
|
||||
return spellOrDamageImmuneHandler(opCode, packet);
|
||||
}
|
||||
|
||||
void UnitCombatLogDispelledHook(hadesmem::PatchDetourBase *detour, uint64_t *casterGuid, uint64_t *targetGuid,
|
||||
uint32_t spellId) {
|
||||
auto const original = detour->GetTrampolineT<UnitCombatLogDispelledT>();
|
||||
original(casterGuid, targetGuid, spellId);
|
||||
|
||||
if (!casterGuid || *casterGuid == 0) return;
|
||||
|
||||
static char format[] = "%s%s%d";
|
||||
char *casterGuidStr = ConvertGuidToString(*casterGuid);
|
||||
char *targetGuidStr = targetGuid ? ConvertGuidToString(*targetGuid) : nullptr;
|
||||
|
||||
auto event = game::SPELL_DISPEL_BY_OTHER;
|
||||
if (*casterGuid == game::ClntObjMgrGetActivePlayerGuid())
|
||||
event = game::SPELL_DISPEL_BY_SELF;
|
||||
|
||||
((int (__cdecl *)(int, char *, char *, char *, uint32_t)) Offsets::SignalEventParam)(
|
||||
event,
|
||||
format,
|
||||
casterGuidStr,
|
||||
targetGuidStr,
|
||||
spellId);
|
||||
|
||||
FreeGuidString(casterGuidStr);
|
||||
FreeGuidString(targetGuidStr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "main.hpp"
|
||||
|
||||
namespace Nampower {
|
||||
using UnitCombatLogDispelledT = void (__fastcall *)(uint64_t *casterGuid, uint64_t *targetGuid, uint32_t spellId);
|
||||
|
||||
void SignalEventHook(hadesmem::PatchDetourBase *detour, game::Events eventId);
|
||||
|
||||
int SpellDelayedHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet);
|
||||
@@ -45,4 +47,6 @@ namespace Nampower {
|
||||
int SpellLogMissHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet);
|
||||
|
||||
int SpellOrDamageImmuneHandlerHook(hadesmem::PatchDetourBase *detour, uint32_t *opCode, CDataStore *packet);
|
||||
|
||||
void UnitCombatLogDispelledHook(hadesmem::PatchDetourBase *detour, uint64_t *casterGuid, uint64_t *targetGuid, uint32_t spellId);
|
||||
}
|
||||
@@ -269,4 +269,58 @@ namespace Nampower {
|
||||
FreeGuidString(guidStr);
|
||||
}
|
||||
}
|
||||
|
||||
void CGUnit_C_HandleEnvironmentDamageHook(hadesmem::PatchDetourBase *detour, uintptr_t *unit, void *dummy_edx,
|
||||
int dmgType, int damage, int absorb, int resist) {
|
||||
auto const original = detour->GetTrampolineT<CGUnit_C_HandleEnvironmentDamageT>();
|
||||
original(unit, dummy_edx, dmgType, damage, absorb, resist);
|
||||
|
||||
auto unitGuid = game::UnitGetGuid(unit);
|
||||
if (unitGuid == 0) return;
|
||||
|
||||
static char format[] = "%s%d%d%d%d";
|
||||
char *unitGuidStr = ConvertGuidToString(unitGuid);
|
||||
|
||||
auto event = game::ENVIRONMENTAL_DMG_OTHER;
|
||||
if (unitGuid == game::ClntObjMgrGetActivePlayerGuid())
|
||||
event = game::ENVIRONMENTAL_DMG_SELF;
|
||||
|
||||
((int (__cdecl *)(int, char *, char *, int, int, int, int)) Offsets::SignalEventParam)(
|
||||
event,
|
||||
format,
|
||||
unitGuidStr,
|
||||
dmgType,
|
||||
damage,
|
||||
absorb,
|
||||
resist);
|
||||
|
||||
FreeGuidString(unitGuidStr);
|
||||
}
|
||||
|
||||
void UnitCombatLogDamageShieldHook(hadesmem::PatchDetourBase *detour, uint64_t *unitGuid, uint64_t *targetGuid,
|
||||
uint32_t damage, uint32_t spellSchool) {
|
||||
auto const original = detour->GetTrampolineT<UnitCombatLogDamageShieldT>();
|
||||
original(unitGuid, targetGuid, damage, spellSchool);
|
||||
|
||||
if (!unitGuid || *unitGuid == 0) return;
|
||||
|
||||
static char format[] = "%s%s%d%d";
|
||||
char *targetGuidString = targetGuid ? ConvertGuidToString(*targetGuid) : nullptr;
|
||||
char *unitGuidStr = ConvertGuidToString(*unitGuid);
|
||||
|
||||
auto event = game::DAMAGE_SHIELD_OTHER;
|
||||
if (*unitGuid == game::ClntObjMgrGetActivePlayerGuid())
|
||||
event = game::DAMAGE_SHIELD_SELF;
|
||||
|
||||
((int (__cdecl *)(int, char *, char *, char *, uint32_t, uint32_t)) Offsets::SignalEventParam)(
|
||||
event,
|
||||
format,
|
||||
unitGuidStr,
|
||||
targetGuidString,
|
||||
damage,
|
||||
spellSchool);
|
||||
|
||||
FreeGuidString(unitGuidStr);
|
||||
FreeGuidString(targetGuidString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,9 @@ namespace Nampower {
|
||||
using CGGameUI_GetRaidMemberT = uint64_t (__fastcall *)(uint32_t index);
|
||||
using CGGameUI_GetRaidMemberPetT = uint64_t (__fastcall *)(uint32_t index);
|
||||
|
||||
using CGUnit_C_HandleEnvironmentDamageT = void (__fastcall *)(uintptr_t *unit, void *dummy_edx, int dmgType, int damage, int absorb, int resist);
|
||||
using UnitCombatLogDamageShieldT = void (__fastcall *)(uint64_t *victimGuid, uint64_t *unitGuid, uint32_t damage, uint32_t spellSchool);
|
||||
|
||||
using CGGameUI_ShowCombatFeedbackT = void (__fastcall *)(uint64_t *guid, const char *action, int damage, int school, int hitInfo);
|
||||
using SignalEventParamUnitCombatT = int (__cdecl *)(uint32_t eventCode, const char *format, const char *unit, const char *action, const char *critIndicator, int damage, int school);
|
||||
using SignalEventParamGuidT = int (__cdecl *)(uint32_t eventCode, const char *format, const char *guid, int isPlayer, int isTarget, int isMouseover, int isPet, int partyIndex, int raidIndex);
|
||||
@@ -75,4 +78,6 @@ namespace Nampower {
|
||||
|
||||
void SendUnitSignalHook(hadesmem::PatchDetourBase *detour, uint64_t *guid, uint32_t eventCode);
|
||||
void CGGameUI_ShowCombatFeedbackHook(hadesmem::PatchDetourBase *detour, uint64_t *guid, const char *action, int damage, int school, int hitInfo);
|
||||
void CGUnit_C_HandleEnvironmentDamageHook(hadesmem::PatchDetourBase *detour, uintptr_t *unit, void *dummy_edx, int dmgType, int damage, int absorb, int resist);
|
||||
void UnitCombatLogDamageShieldHook(hadesmem::PatchDetourBase *detour, uint64_t *targetGuid, uint64_t *unitGuid, uint32_t damage, uint32_t spellSchool);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user