mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 15:50:20 +00:00
300 lines
12 KiB
C++
300 lines
12 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <ctime>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace wowee {
|
|
namespace game {
|
|
|
|
/**
|
|
* Aura slot data for buff/debuff tracking
|
|
*/
|
|
struct AuraSlot {
|
|
uint32_t spellId = 0;
|
|
uint8_t flags = 0; // Active, positive/negative, etc.
|
|
uint8_t level = 0;
|
|
uint8_t charges = 0;
|
|
int32_t durationMs = -1;
|
|
int32_t maxDurationMs = -1;
|
|
uint64_t casterGuid = 0;
|
|
uint64_t receivedAtMs = 0; // Client timestamp (ms) when durationMs was set
|
|
|
|
bool isEmpty() const { return spellId == 0; }
|
|
// Remaining duration in ms, counting down from when the packet was received
|
|
int32_t getRemainingMs(uint64_t nowMs) const {
|
|
if (durationMs < 0) return -1;
|
|
uint64_t elapsed = (nowMs > receivedAtMs) ? (nowMs - receivedAtMs) : 0;
|
|
int32_t remaining = durationMs - static_cast<int32_t>(elapsed);
|
|
return (remaining > 0) ? remaining : 0;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Action bar slot
|
|
*/
|
|
struct ActionBarSlot {
|
|
enum Type : uint8_t { EMPTY = 0, SPELL = 1, ITEM = 2, MACRO = 3 };
|
|
Type type = EMPTY;
|
|
uint32_t id = 0; // spellId, itemId, or macroId
|
|
float cooldownRemaining = 0.0f;
|
|
float cooldownTotal = 0.0f;
|
|
|
|
bool isReady() const { return cooldownRemaining <= 0.0f; }
|
|
bool isEmpty() const { return type == EMPTY; }
|
|
};
|
|
|
|
/**
|
|
* Floating combat text entry
|
|
*/
|
|
struct CombatTextEntry {
|
|
enum Type : uint8_t {
|
|
MELEE_DAMAGE, SPELL_DAMAGE, HEAL, MISS, DODGE, PARRY, BLOCK,
|
|
CRIT_DAMAGE, CRIT_HEAL, PERIODIC_DAMAGE, PERIODIC_HEAL, ENVIRONMENTAL,
|
|
ENERGIZE, XP_GAIN, IMMUNE, ABSORB, RESIST, PROC_TRIGGER,
|
|
DISPEL, STEAL, INTERRUPT, INSTAKILL
|
|
};
|
|
Type type;
|
|
int32_t amount = 0;
|
|
uint32_t spellId = 0;
|
|
float age = 0.0f; // Seconds since creation (for fadeout)
|
|
bool isPlayerSource = false; // True if player dealt this
|
|
uint8_t powerType = 0; // For ENERGIZE: 0=mana,1=rage,2=focus,3=energy,6=runicpower
|
|
|
|
static constexpr float LIFETIME = 2.5f;
|
|
bool isExpired() const { return age >= LIFETIME; }
|
|
};
|
|
|
|
/**
|
|
* Persistent combat log entry (stored in a rolling deque, survives beyond floating-text lifetime)
|
|
*/
|
|
struct CombatLogEntry {
|
|
CombatTextEntry::Type type = CombatTextEntry::MELEE_DAMAGE;
|
|
int32_t amount = 0;
|
|
uint32_t spellId = 0;
|
|
bool isPlayerSource = false;
|
|
time_t timestamp = 0; // Wall-clock time (std::time(nullptr))
|
|
std::string sourceName; // Resolved display name of attacker/caster
|
|
std::string targetName; // Resolved display name of victim/target
|
|
};
|
|
|
|
/**
|
|
* Spell cooldown entry received from server
|
|
*/
|
|
struct SpellCooldownEntry {
|
|
uint32_t spellId;
|
|
uint16_t itemId;
|
|
uint16_t categoryId;
|
|
uint32_t cooldownMs;
|
|
uint32_t categoryCooldownMs;
|
|
};
|
|
|
|
/**
|
|
* Get human-readable spell cast failure reason (WoW 3.3.5a SpellCastResult)
|
|
*/
|
|
inline const char* getSpellCastResultString(uint8_t result, int powerType = -1) {
|
|
// AzerothCore 3.3.5a SpellCastResult enum (SharedDefines.h)
|
|
switch (result) {
|
|
case 0: return nullptr; // SUCCESS — not a failure
|
|
case 1: return "Affecting combat";
|
|
case 2: return "Already at full health";
|
|
case 3: return "Already at full mana";
|
|
case 4: return "Already at full power";
|
|
case 5: return "Already being tamed";
|
|
case 6: return "Already have charm";
|
|
case 7: return "Already have summon";
|
|
case 8: return "Already open";
|
|
case 9: return "Aura bounced";
|
|
case 10: return "Autotrack interrupted";
|
|
case 11: return "Bad implicit targets";
|
|
case 12: return "Invalid target";
|
|
case 13: return "Can't be charmed";
|
|
case 14: return "Can't be disenchanted";
|
|
case 15: return "Can't be disenchanted (skill)";
|
|
case 16: return "Can't be milled";
|
|
case 17: return "Can't be prospected";
|
|
case 18: return "Can't cast on tapped";
|
|
case 19: return "Can't duel while invisible";
|
|
case 20: return "Can't duel while stealthed";
|
|
case 21: return "Can't stealth";
|
|
case 22: return "Caster aurastate";
|
|
case 23: return "Caster dead";
|
|
case 24: return "Charmed";
|
|
case 25: return "Chest in use";
|
|
case 26: return "Confused";
|
|
case 27: return nullptr; // DONT_REPORT — suppress message
|
|
case 28: return "Equipped item required";
|
|
case 29: return "Equipped item class (mainhand)";
|
|
case 30: return "Equipped item class (mainhand)";
|
|
case 31: return "Equipped item class (offhand)";
|
|
case 32: return "Error";
|
|
case 33: return "Fizzle";
|
|
case 34: return "Fleeing";
|
|
case 35: return "Food too low level";
|
|
case 36: return "Target too high level";
|
|
case 37: return "Hunger satiated";
|
|
case 38: return "Immune";
|
|
case 39: return "Incorrect area";
|
|
case 40: return "Interrupted";
|
|
case 41: return "Interrupted (combat)";
|
|
case 42: return "Item already enchanted";
|
|
case 43: return "Item gone";
|
|
case 44: return "Item not found";
|
|
case 45: return "Item not ready";
|
|
case 46: return "Level requirement";
|
|
case 47: return "Target not in line of sight";
|
|
case 48: return "Target too low level";
|
|
case 49: return "Low cast level";
|
|
case 50: return "Mainhand empty";
|
|
case 51: return "Can't do that while moving";
|
|
case 52: return "Need ammo";
|
|
case 53: return "Need ammo pouch";
|
|
case 54: return "Need exotic ammo";
|
|
case 55: return "Need more items";
|
|
case 56: return "No path";
|
|
case 57: return "Not behind";
|
|
case 58: return "Not fishable";
|
|
case 59: return "Not flying";
|
|
case 60: return "Not here";
|
|
case 61: return "Target needs to be in front of you";
|
|
case 62: return "Not in control";
|
|
case 63: return "Not known";
|
|
case 64: return "Not mounted";
|
|
case 65: return "Not on taxi";
|
|
case 66: return "Not on transport";
|
|
case 67: return "Not ready";
|
|
case 68: return "Not in shapeshift form";
|
|
case 69: return "Not standing";
|
|
case 70: return "Not tradeable";
|
|
case 71: return "Not while trading";
|
|
case 72: return "Not unsheathed";
|
|
case 73: return "Not while ghost";
|
|
case 74: return "Not while looting";
|
|
case 75: return "No ammo";
|
|
case 76: return "No charges remain";
|
|
case 77: return "No champion";
|
|
case 78: return "Not enough combo points";
|
|
case 79: return "No dueling";
|
|
case 80: return "No endurance";
|
|
case 81: return "No fish";
|
|
case 82: return "No items while shapeshifted";
|
|
case 83: return "No mounts allowed here";
|
|
case 84: return "No pet";
|
|
case 85:
|
|
switch (powerType) {
|
|
case 1: return "Not enough rage";
|
|
case 2: return "Not enough focus";
|
|
case 3: return "Not enough energy";
|
|
case 6: return "Not enough runic power";
|
|
default: return "Not enough mana";
|
|
}
|
|
case 86: return "Nothing to dispel";
|
|
case 87: return "Nothing to steal";
|
|
case 88: return "Only above water";
|
|
case 89: return "Only daytime";
|
|
case 90: return "Only indoors";
|
|
case 91: return "Only mounted";
|
|
case 92: return "Only nighttime";
|
|
case 93: return "Only outdoors";
|
|
case 94: return "Requires correct stance/form";
|
|
case 95: return "Only stealthed";
|
|
case 96: return "Only underwater";
|
|
case 97: return "Out of range";
|
|
case 98: return "Pacified";
|
|
case 99: return "Possessed";
|
|
case 100: return "Reagents required";
|
|
case 101: return "Requires area";
|
|
case 102: return "Requires spell focus";
|
|
case 103: return "Can't do that while rooted";
|
|
case 104: return "Can't do that while silenced";
|
|
case 105: return "Spell in progress";
|
|
case 106: return "Spell learned";
|
|
case 107: return "Spell unavailable";
|
|
case 108: return "Stunned";
|
|
case 109: return "Targets dead";
|
|
case 110: return "Target affecting combat";
|
|
case 111: return "Target aurastate";
|
|
case 112: return "Target dueling";
|
|
case 113: return "Target is enemy";
|
|
case 114: return "Target enraged";
|
|
case 115: return "Target friendly";
|
|
case 116: return "Target in combat";
|
|
case 117: return "Target is player";
|
|
case 118: return "Target is player controlled";
|
|
case 119: return "Target not dead";
|
|
case 120: return "Target not in party";
|
|
case 121: return "Target not looted";
|
|
case 122: return "Target not player";
|
|
case 123: return "Target no pockets";
|
|
case 124: return "Target no weapons";
|
|
case 125: return "Target no ranged weapons";
|
|
case 126: return "Target unskinnable";
|
|
case 127: return "Thirst satiated";
|
|
case 128: return "Too close";
|
|
case 129: return "Too many of item";
|
|
case 130: return "Totem category";
|
|
case 131: return "Totems";
|
|
case 132: return "Try again";
|
|
case 133: return "Unit not behind";
|
|
case 134: return "Unit not in front";
|
|
case 135: return "Wrong pet food";
|
|
case 136: return "Not while fatigued";
|
|
case 137: return "Target not in instance";
|
|
case 138: return "Not while trading";
|
|
case 139: return "Target not in raid";
|
|
case 140: return "Target free for all";
|
|
case 141: return "No edible corpses";
|
|
case 142: return "Only battlegrounds";
|
|
case 143: return "Target not ghost";
|
|
case 144: return "Transform unusable";
|
|
case 145: return "Wrong weather";
|
|
case 146: return "Damage immune";
|
|
case 147: return "Prevented by mechanic";
|
|
case 148: return "Play time restriction";
|
|
case 149: return "Reputation required";
|
|
case 150: return "Min skill required";
|
|
case 151: return "Not in arena";
|
|
case 152: return "Not on shapeshift";
|
|
case 153: return "Not on stealthed";
|
|
case 154: return "Not on damage immune";
|
|
case 155: return "Not on mounted";
|
|
case 156: return "Too shallow";
|
|
case 157: return "Target not in sanctuary";
|
|
case 158: return "Target is trivial";
|
|
case 159: return "BM or invis god";
|
|
case 160: return "Expert riding required";
|
|
case 161: return "Artisan riding required";
|
|
case 162: return "Not idle";
|
|
case 163: return "Not inactive";
|
|
case 164: return "Partial playtime";
|
|
case 165: return "No playtime";
|
|
case 166: return "Not in battleground";
|
|
case 167: return "Not in raid instance";
|
|
case 168: return "Only in arena";
|
|
case 169: return "Target locked to raid instance";
|
|
case 170: return "On use enchant";
|
|
case 171: return "Not on ground";
|
|
case 172: return "Custom error";
|
|
case 173: return "Can't do that right now";
|
|
case 174: return "Too many sockets";
|
|
case 175: return "Invalid glyph";
|
|
case 176: return "Unique glyph";
|
|
case 177: return "Glyph socket locked";
|
|
case 178: return "No valid targets";
|
|
case 179: return "Item at max charges";
|
|
case 180: return "Not in barbershop";
|
|
case 181: return "Fishing too low";
|
|
case 182: return "Item enchant trade window";
|
|
case 183: return "Summon pending";
|
|
case 184: return "Max sockets";
|
|
case 185: return "Pet can rename";
|
|
case 186: return "Target cannot be resurrected";
|
|
case 187: return "Unknown error";
|
|
case 255: return nullptr; // SPELL_CAST_OK
|
|
default: return nullptr;
|
|
}
|
|
}
|
|
|
|
} // namespace game
|
|
} // namespace wowee
|