mirror of
https://github.com/brues-code/nampower.git
synced 2026-10-05 21:20:01 +00:00
add duration+spellType args to SPELL_START events to make it easier to handle channeling spells for other players
add GetSpellDuration
This commit is contained in:
@@ -123,7 +123,7 @@ end);
|
||||
```
|
||||
|
||||
### SPELL_START_SELF and SPELL_START_OTHER
|
||||
Fire when a spell start packet is received. "Self" fires when the active player is the caster, "Other" fires for any other caster. Triggered by the server to notify that a spell with a cast time has begun.
|
||||
Fire when a spell start packet is received. "Self" fires when the active player is the caster, "Other" fires for any other caster. Triggered by the server to notify that a spell with a cast time has begun. Note: SPELL_START_OTHER also fires for channeling spells cast by other players, as there is no separate SPELL_CHANNEL_START packet for other players — channeling and cast time spells are both bundled into SPELL_START. Use the `spellType` parameter to distinguish channeling spells.
|
||||
|
||||
These events are gated behind the `NP_EnableSpellStartEvents` CVar (default 0). Set it to `1` to enable.
|
||||
|
||||
@@ -134,6 +134,8 @@ Parameters:
|
||||
4. string targetGuid - target guid like "0xF5300000000000A5" or "0x0000000000000000" if none
|
||||
5. int castFlags
|
||||
6. int castTime - cast time in milliseconds
|
||||
7. int duration - channel duration in milliseconds (only set for channeling spells, 0 otherwise. See GetSpellDuration if you want it for other spell types)
|
||||
8. int spellType - 0 = Normal, 1 = Channeling, 2 = Autorepeating
|
||||
|
||||
### SPELL_GO_SELF and SPELL_GO_OTHER
|
||||
Fire when a spell go packet is received. "Self" fires when the active player is the caster, "Other" fires for any other caster. Triggered by the server to indicate a spell completed casting.
|
||||
|
||||
@@ -153,6 +153,7 @@ This includes functions for:
|
||||
- Cooldown tracking (GetSpellIdCooldown, GetItemIdCooldown), including item metadata on cooldown detail tables
|
||||
- Inventory helpers (GetTrinketCooldown, GetTrinkets, GetAmmo)
|
||||
- Aura duration tracking and cancel helpers (GetPlayerAuraDuration, CancelPlayerAuraSlot, CancelPlayerAuraSpellId)
|
||||
- Spell duration lookup (GetSpellDuration) - returns channel duration for channeling spells and the first aura effect duration for non-channeling spells
|
||||
- Player movement state queries (PlayerIsMoving, PlayerIsRooted, PlayerIsSwimming)
|
||||
- Talent helpers (LearnTalentRank)
|
||||
- Spell lookups and utilities
|
||||
|
||||
+21
@@ -21,6 +21,7 @@ For custom events, see [EVENTS.md](EVENTS.md). For installation, configuration,
|
||||
- [GetSpellRecField](#getspellrecfieldspellid-fieldname-copy)
|
||||
- [GetSpellModifiers](#getspellmodifiersspellid-modifiertype)
|
||||
- [GetSpellPower](#getspellpowermode)
|
||||
- [GetSpellDuration](#getspelldurationspellid-ignoremodifiers)
|
||||
- [GetUnitData](#getunitdataunittoken-copy)
|
||||
- [GetUnitField](#getunitfieldunittoken-fieldname-copy)
|
||||
- [GetSpellIdForName](#getspellidfornamenspellname)
|
||||
@@ -620,6 +621,26 @@ local physical, holy, fire, nature, frost, shadow, arcane = GetSpellPower("posit
|
||||
local physical, holy, fire, nature, frost, shadow, arcane = GetSpellPower("negative")
|
||||
```
|
||||
|
||||
#### GetSpellDuration(spellId, [ignoreModifiers])
|
||||
Returns the duration of a spell in milliseconds. For channeling spells this is the channel duration, and for non-channeling spells I think this is always the duration of the first aura effect. By default, the active player's spell modifiers (e.g. talents that extend duration) are applied.
|
||||
|
||||
**Parameters:**
|
||||
- `spellId` (number): The spell ID to look up.
|
||||
- `ignoreModifiers` (number, optional): Pass `1` to ignore your spell modifiers (talents, etc.) and return the base duration. Defaults to `0` (apply modifiers).
|
||||
|
||||
**Returns:**
|
||||
- `number` - Duration in milliseconds, or `0` if the spell has no duration.
|
||||
- `nil` - If the spell ID is invalid.
|
||||
|
||||
**Examples:**
|
||||
```lua
|
||||
-- Get modified duration of a spell
|
||||
local duration = GetSpellDuration(spellId)
|
||||
|
||||
-- Get base duration ignoring talent modifiers
|
||||
local baseDuration = GetSpellDuration(spellId, 1)
|
||||
```
|
||||
|
||||
#### GetUnitData(unitToken, [copy])
|
||||
Returns a Lua table reference containing all unit fields for the specified unit. This provides access to low-level unit data like health, mana, stats, auras, resistances, and more.
|
||||
|
||||
|
||||
+9933
-9935
File diff suppressed because it is too large
Load Diff
@@ -1702,6 +1702,9 @@ namespace Nampower {
|
||||
char getSpellPower[] = "GetSpellPower";
|
||||
RegisterLuaFunction(getSpellPower, reinterpret_cast<uintptr_t *>(Script_GetSpellPower));
|
||||
|
||||
char getSpellDuration[] = "GetSpellDuration";
|
||||
RegisterLuaFunction(getSpellDuration, reinterpret_cast<uintptr_t *>(Script_GetSpellDuration));
|
||||
|
||||
char learnTalentRank[] = "LearnTalentRank";
|
||||
RegisterLuaFunction(learnTalentRank, reinterpret_cast<uintptr_t *>(Script_LearnTalentRank));
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ namespace Nampower {
|
||||
constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic
|
||||
|
||||
constexpr uint32_t MAJOR_VERSION = 2;
|
||||
constexpr uint32_t MINOR_VERSION = 37;
|
||||
constexpr uint32_t MINOR_VERSION = 38;
|
||||
constexpr uint32_t PATCH_VERSION = 0;
|
||||
|
||||
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
||||
|
||||
@@ -650,4 +650,35 @@ namespace Nampower {
|
||||
return 7;
|
||||
}
|
||||
|
||||
uint32_t Script_GetSpellDuration(uintptr_t *luaState) {
|
||||
luaState = GetLuaStatePtr();
|
||||
|
||||
if (!lua_isnumber(luaState, 1)) {
|
||||
lua_error(luaState, "Usage: GetSpellDuration(spellId [, ignoreModifiers])");
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto const spellId = uint32_t(lua_tonumber(luaState, 1));
|
||||
auto const spellRec = game::GetSpellInfo(spellId);
|
||||
|
||||
if (!spellRec) {
|
||||
lua_pushnil(luaState);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ignoreModifiers = false;
|
||||
if (lua_isnumber(luaState, 2)) {
|
||||
ignoreModifiers = lua_tonumber(luaState, 2) != 0;
|
||||
}
|
||||
|
||||
auto dur = game::GetSpellDuration(spellRec, ignoreModifiers);
|
||||
if (dur > 0) {
|
||||
lua_pushnumber(luaState, static_cast<uint32_t>(dur));
|
||||
} else {
|
||||
lua_pushnumber(luaState, 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,5 +34,7 @@ namespace Nampower {
|
||||
|
||||
uint32_t Script_GetSpellPower(uintptr_t *luaState);
|
||||
|
||||
uint32_t Script_GetSpellDuration(uintptr_t *luaState);
|
||||
|
||||
uint32_t GetSpellSlotFromLuaHook(hadesmem::PatchDetourBase *detour, int param_1, uint32_t *slot, uint32_t *type);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,12 @@ namespace Nampower {
|
||||
uint32_t lastCastResultTimeMs;
|
||||
constexpr int MAX_ALLOWED_SPELL_TARGETS = 100;
|
||||
|
||||
enum SpellType : uint32_t {
|
||||
SPELL_TYPE_NORMAL = 0,
|
||||
SPELL_TYPE_CHANNELING = 1,
|
||||
SPELL_TYPE_AUTOREPEATING = 2,
|
||||
};
|
||||
|
||||
|
||||
void SignalEventHook(hadesmem::PatchDetourBase *detour, game::Events eventId) {
|
||||
auto const signalEvent = detour->GetTrampolineT<SignalEventT>();
|
||||
@@ -772,11 +778,26 @@ namespace Nampower {
|
||||
uint64_t targetGuid,
|
||||
uint16_t castFlags,
|
||||
uint32_t castTime) {
|
||||
static char format[] = "%d%d%s%s%d%d";
|
||||
static char format[] = "%d%d%s%s%d%d%d%d";
|
||||
|
||||
char *casterGuidStr = ConvertGuidToString(casterGuid);
|
||||
char *targetGuidStr = ConvertGuidToString(targetGuid);
|
||||
|
||||
uint32_t duration = 0;
|
||||
SpellType spellType = SPELL_TYPE_NORMAL;
|
||||
auto spellRec = game::GetSpellInfo(spellId);
|
||||
if (spellRec) {
|
||||
if (spellRec->AttributesEx2 & game::SpellAttributesEx2::SPELL_ATTR_EX2_AUTO_REPEAT) {
|
||||
spellType = SPELL_TYPE_AUTOREPEATING;
|
||||
} else if (spellRec->AttributesEx & (game::SpellAttributesEx::SPELL_ATTR_EX_IS_CHANNELED | game::SpellAttributesEx::SPELL_ATTR_EX_IS_SELF_CHANNELED)) {
|
||||
spellType = SPELL_TYPE_CHANNELING;
|
||||
auto dur = game::GetSpellDuration(spellRec, casterGuid != game::ClntObjMgrGetActivePlayerGuid());
|
||||
if (dur > 0) {
|
||||
duration = static_cast<uint32_t>(dur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto event = game::SPELL_START_OTHER;
|
||||
if (casterGuid == game::ClntObjMgrGetActivePlayerGuid()) {
|
||||
event = game::SPELL_START_SELF;
|
||||
@@ -789,7 +810,9 @@ namespace Nampower {
|
||||
char *casterGuidParam,
|
||||
char *targetGuidParam,
|
||||
uint32_t castFlagsParam,
|
||||
uint32_t castTimeParam)) Offsets::SignalEventParam)(
|
||||
uint32_t castTimeParam,
|
||||
uint32_t durationParam,
|
||||
uint32_t spellTypeParam)) Offsets::SignalEventParam)(
|
||||
event,
|
||||
format,
|
||||
itemId,
|
||||
@@ -797,7 +820,9 @@ namespace Nampower {
|
||||
casterGuidStr,
|
||||
targetGuidStr,
|
||||
castFlags,
|
||||
castTime);
|
||||
castTime,
|
||||
duration,
|
||||
spellType);
|
||||
|
||||
delete[] casterGuidStr;
|
||||
delete[] targetGuidStr;
|
||||
|
||||
Reference in New Issue
Block a user