diff --git a/source/WorldServer/EffectFlags.h b/source/WorldServer/EffectFlags.h
new file mode 100644
index 0000000..d890372
--- /dev/null
+++ b/source/WorldServer/EffectFlags.h
@@ -0,0 +1,442 @@
+/*
+ EQ2Emulator: Everquest II Server Emulator
+ Copyright (C) 2005 - 2026 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
+
+ This file is part of EQ2Emulator.
+
+ EQ2Emulator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ EQ2Emulator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with EQ2Emulator. If not, see .
+*/
+
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+class LuaSpell;
+
+// ----------------------------- Core bitflags --------------------------------
+template
+class BitFlags {
+public:
+ static constexpr std::size_t kWordBits = 64;
+ static constexpr std::size_t kWords = (NBits + kWordBits - 1) / kWordBits;
+
+ constexpr BitFlags() noexcept : words_{} {}
+
+ // Single-bit ops
+ inline void set(std::size_t bit) noexcept { words_[word_index(bit)] |= word_mask(bit); }
+ inline void reset(std::size_t bit) noexcept { words_[word_index(bit)] &= ~word_mask(bit); }
+ inline void toggle(std::size_t bit) noexcept { words_[word_index(bit)] ^= word_mask(bit); }
+ inline bool test(std::size_t bit) const noexcept { return (words_[word_index(bit)] & word_mask(bit)) != 0ULL; }
+
+ // Bulk ops
+ inline void clear() noexcept {
+ for (std::size_t i = 0; i < kWords; ++i) words_[i] = 0ULL;
+ }
+ inline bool any() const noexcept {
+ for (std::size_t i = 0; i < kWords; ++i) if (words_[i]) return true;
+ return false;
+ }
+ inline bool none() const noexcept { return !any(); }
+
+ inline void import_u32(std::uint32_t legacy) noexcept {
+ if (!legacy) return;
+ const std::size_t lim = (NBits < 32 ? NBits : 32);
+ for (std::size_t i = 0; i < lim; ++i)
+ if ((legacy >> i) & 1u) set(i);
+ }
+ inline std::uint32_t export_u32() const noexcept {
+ std::uint32_t out = 0;
+ const std::size_t lim = (NBits < 32 ? NBits : 32);
+ for (std::size_t i = 0; i < lim; ++i)
+ if (test(i)) out |= (1u << i);
+ return out;
+ }
+
+ // Import a 64-bit legacy mask (low 64 bits only)
+inline void import_u64(std::uint64_t legacy) noexcept {
+ if (!legacy) return;
+ const std::size_t lim = (NBits < 64 ? NBits : 64);
+ for (std::size_t i = 0; i < lim; ++i)
+ if ((legacy >> i) & 1ULL) set(i);
+}
+
+// Export low 64 bits into a uint64_t
+inline std::uint64_t export_u64() const noexcept {
+ std::uint64_t out = 0;
+ const std::size_t lim = (NBits < 64 ? NBits : 64);
+ for (std::size_t i = 0; i < lim; ++i)
+ if (test(i)) out |= (1ULL << i);
+ return out;
+}
+
+
+ // Set by legacy power-of-two value (find index of the single set bit)
+ inline void set_legacy_flag_value(std::uint64_t pow2) noexcept {
+ if (!pow2) return;
+#if defined(__GNUC__) || defined(__clang__)
+ std::size_t bit = static_cast(__builtin_ctzll(pow2));
+#else
+ std::size_t bit = 0; while (bit < 64 && ((pow2 >> bit) & 1ULL) == 0ULL) ++bit;
+#endif
+ if (bit < NBits) set(bit);
+ }
+
+ // Direct word access (used by TS wrapper)
+ static constexpr std::size_t words_count() noexcept { return kWords; }
+ inline std::uint64_t& word_ref(std::size_t i) noexcept { return words_[i]; }
+ inline const std::uint64_t& word_ref(std::size_t i) const noexcept { return words_[i]; }
+
+private:
+ static constexpr std::size_t word_index(std::size_t bit) noexcept { return bit / kWordBits; }
+ static constexpr std::uint64_t word_mask (std::size_t bit) noexcept { return 1ULL << (bit % kWordBits); }
+
+ std::array words_;
+};
+
+// --------------------------- Thread-safe wrapper ----------------------------
+template
+class TSBitFlags {
+public:
+ using Snapshot = BitFlags;
+
+ // Single-bit ops
+ inline void set(std::size_t bit) { std::unique_lock lk(m_); bits_.set(bit); }
+ inline void reset(std::size_t bit) { std::unique_lock lk(m_); bits_.reset(bit); }
+ inline void toggle(std::size_t bit) { std::unique_lock lk(m_); bits_.toggle(bit); }
+ inline bool test(std::size_t bit) const { std::shared_lock lk(m_); return bits_.test(bit); }
+
+ // Convenience
+ inline void add(std::size_t bit) { set(bit); }
+ inline void remove(std::size_t bit) { reset(bit); }
+ inline bool has(std::size_t bit) const { return test(bit); }
+
+ // Batch ops
+ inline void set_many(std::initializer_list bits) {
+ std::unique_lock lk(m_); for (auto b : bits) bits_.set(b);
+ }
+ inline void reset_many(std::initializer_list bits) {
+ std::unique_lock lk(m_); for (auto b : bits) bits_.reset(b);
+ }
+
+ // Clear / any / none
+ inline void clear() { std::unique_lock lk(m_); bits_.clear(); }
+ inline bool any() const { std::shared_lock lk(m_); return bits_.any(); }
+ inline bool none() const { std::shared_lock lk(m_); return bits_.none(); }
+
+ // Legacy helpers
+ inline void import_u32(std::uint32_t legacy) { std::unique_lock lk(m_); bits_.import_u32(legacy); }
+ inline std::uint32_t export_u32() const { std::shared_lock lk(m_); return bits_.export_u32(); }
+ inline void import_u64(std::uint64_t legacy) { std::unique_lock lk(m_); bits_.import_u64(legacy); }
+ inline std::uint64_t export_u64() const { std::shared_lock lk(m_); return bits_.export_u64(); }
+ inline void set_legacy_flag_value(std::uint64_t v){ std::unique_lock lk(m_); bits_.set_legacy_flag_value(v); }
+
+ // Snapshots (copy out/in without exposing lock)
+ inline Snapshot snapshot() const { std::shared_lock lk(m_); return bits_; }
+ inline void assign_from(const Snapshot& snap) {
+ std::unique_lock lk(m_);
+ for (std::size_t i = 0; i < Snapshot::words_count(); ++i)
+ bits_.word_ref(i) = snap.word_ref(i);
+ }
+
+private:
+ mutable std::shared_mutex m_;
+ Snapshot bits_{};
+};
+
+// ------------------------- Project-specific typedefs ------------------------
+inline constexpr std::size_t kEffectBits = 64; // limited due to DB restrictions at this time
+using EffectFlags = TSBitFlags;
+
+enum : std::size_t {
+ EFFECT_IDX_STUN = 0,
+ EFFECT_IDX_ROOT = 1,
+ EFFECT_IDX_MEZ = 2,
+ EFFECT_IDX_STIFLE = 3,
+ EFFECT_IDX_DAZE = 4,
+ EFFECT_IDX_FEAR = 5,
+ EFFECT_IDX_SPELLBONUS = 6,
+ EFFECT_IDX_SKILLBONUS = 7,
+ EFFECT_IDX_STEALTH = 8,
+ EFFECT_IDX_INVIS = 9,
+ EFFECT_IDX_SNARE = 10,
+ EFFECT_IDX_WATERWALK = 11,
+ EFFECT_IDX_WATERJUMP = 12,
+ EFFECT_IDX_FLIGHT = 13,
+ EFFECT_IDX_GLIDE = 14,
+ EFFECT_IDX_AOE_IMMUNE = 15,
+ EFFECT_IDX_STUN_IMMUNE = 16,
+ EFFECT_IDX_MEZ_IMMUNE = 17,
+ EFFECT_IDX_DAZE_IMMUNE = 18,
+ EFFECT_IDX_ROOT_IMMUNE = 19,
+ EFFECT_IDX_STIFLE_IMMUNE = 20,
+ EFFECT_IDX_FEAR_IMMUNE = 21,
+ EFFECT_IDX_SAFEFALL = 22,
+ EFFECT_IDX_ILLUSION = 23,
+};
+
+
+
+class EffectRegistryPerSpell {
+public:
+ using Code = uint8_t; // your int8 codes
+ using Value = std::variant;
+
+ explicit EffectRegistryPerSpell(Code max_code_inclusive)
+ : max_code_(max_code_inclusive),
+ slots_(static_cast(max_code_inclusive) + 1) {}
+
+ // --- Membership (writers) -------------------------------------------------
+
+ // Add a spell to a type. Returns true if inserted (false if already present).
+ bool Add(Code code, LuaSpell* spell) {
+ if (!in_range(code) || !spell) return false;
+ auto& s = slots_[code];
+ std::unique_lock lk(s.mtx);
+ return s.members.emplace(spell, Entry{spell, std::monostate{}}).second;
+ }
+
+ // Add or update (set/replace the per-spell value atomically).
+ // Returns true if inserted new, false if updated existing.
+ template
+ bool AddOrUpdate(Code code, LuaSpell* spell, T v) {
+ if (!in_range(code) || !spell) return false;
+ auto& s = slots_[code];
+ std::unique_lock lk(s.mtx);
+ auto [it, inserted] = s.members.emplace(spell, Entry{spell, std::monostate{}});
+ it->second.val = to_variant(std::move(v));
+ return inserted;
+ }
+
+ // Remove a spell from a type. Returns true if erased.
+ bool Remove(Code code, LuaSpell* spell) {
+ if (!in_range(code) || !spell) return false;
+ auto& s = slots_[code];
+ std::unique_lock lk(s.mtx);
+ return s.members.erase(spell) > 0;
+ }
+
+ // Clear all spells at a type
+ void Clear(Code code) {
+ if (!in_range(code)) return;
+ auto& s = slots_[code];
+ std::unique_lock lk(s.mtx);
+ s.members.clear();
+ }
+
+ // --- Queries (readers) ----------------------------------------------------
+
+ // Is there any spell registered at this type?
+ bool Has(Code code) const {
+ if (!in_range(code)) return false;
+ auto& s = slots_[code];
+ std::shared_lock lk(s.mtx);
+ return !s.members.empty();
+ }
+
+ // Is this specific spell present under this type?
+ bool Contains(Code code, const LuaSpell* spell) const {
+ if (!in_range(code) || !spell) return false;
+ auto& s = slots_[code];
+ std::shared_lock lk(s.mtx);
+ return s.members.find(const_cast(spell)) != s.members.end();
+ }
+
+ // How many spells are registered at this type?
+ size_t Count(Code code) const {
+ if (!in_range(code)) return 0;
+ auto& s = slots_[code];
+ std::shared_lock lk(s.mtx);
+ return s.members.size();
+ }
+
+ // Snapshot list of spells under a type (copy out while holding a shared lock).
+ std::vector Snapshot(Code code) const {
+ std::vector out;
+ if (!in_range(code)) return out;
+ auto& s = slots_[code];
+ std::shared_lock lk(s.mtx);
+ out.reserve(s.members.size());
+ for (auto& kv : s.members) out.push_back(kv.first);
+ return out;
+ }
+
+ // Snapshot of (spell, value) pairs under a type.
+ struct SpellWithValue {
+ LuaSpell* spell{};
+ Value value{};
+ };
+ std::vector SnapshotWithValues(Code code) const {
+ std::vector out;
+ if (!in_range(code)) return out;
+ auto& s = slots_[code];
+ std::shared_lock lk(s.mtx);
+ out.reserve(s.members.size());
+ for (auto& kv : s.members) out.push_back({kv.second.ptr, kv.second.val});
+ return out;
+ }
+
+ // --- Per-spell value API --------------------------------------------------
+
+ // Set/replace the value for a specific spell under a type.
+ template
+ bool SetValue(Code code, LuaSpell* spell, T v) {
+ if (!in_range(code) || !spell) return false;
+ auto& s = slots_[code];
+ std::unique_lock lk(s.mtx);
+ auto it = s.members.find(spell);
+ if (it == s.members.end()) return false;
+ it->second.val = to_variant(std::move(v));
+ return true;
+ }
+
+ // Clear value for a specific spell under a type (keeps membership).
+ bool ClearValue(Code code, LuaSpell* spell) {
+ if (!in_range(code) || !spell) return false;
+ auto& s = slots_[code];
+ std::unique_lock lk(s.mtx);
+ auto it = s.members.find(spell);
+ if (it == s.members.end()) return false;
+ it->second.val = std::monostate{};
+ return true;
+ }
+
+ // Read value as requested type. nullopt if not set or wrong type.
+ template
+ std::optional GetValue(Code code, const LuaSpell* spell) const {
+ if (!in_range(code) || !spell) return std::nullopt;
+ auto& s = slots_[code];
+ std::shared_lock lk(s.mtx);
+ auto it = s.members.find(const_cast(spell));
+ if (it == s.members.end()) return std::nullopt;
+ if (auto p = std::get_if(&it->second.val)) return *p;
+ return std::nullopt;
+ }
+
+ // Convenience typed getters
+ std::optional GetInt (Code code, const LuaSpell* s) const { return GetValue(code, s); }
+ std::optional GetFloat (Code code, const LuaSpell* s) const { return GetValue (code, s); }
+ std::optional GetString(Code code, const LuaSpell* s) const { return GetValue(code, s); }
+
+ Code MaxCode() const { return max_code_; }
+
+private:
+ struct Entry {
+ LuaSpell* ptr{};
+ Value val{};
+ };
+ struct Slot {
+ mutable std::shared_mutex mtx;
+ std::unordered_map members; // key = spell*, value = (spell*, variant)
+ };
+
+ bool in_range(Code code) const { return code <= max_code_; }
+
+ // normalize to variant
+ static Value to_variant(int64_t v) { return Value{v}; }
+ static Value to_variant(int v) { return Value{static_cast(v)}; }
+ static Value to_variant(uint32_t v) { return Value{static_cast(v)}; }
+ static Value to_variant(float v) { return Value{static_cast(v)}; }
+ static Value to_variant(double v) { return Value{v}; }
+ static Value to_variant(const char* s) { return Value{std::string(s ? s : "")}; }
+ static Value to_variant(std::string s) { return Value{std::move(s)}; }
+
+ Code max_code_;
+ std::vector slots_;
+};
+
+#define CONTROL_EFFECT_TYPE_MEZ 1
+#define CONTROL_EFFECT_TYPE_STIFLE 2
+#define CONTROL_EFFECT_TYPE_DAZE 3
+#define CONTROL_EFFECT_TYPE_STUN 4
+#define CONTROL_EFFECT_TYPE_ROOT 5
+#define CONTROL_EFFECT_TYPE_FEAR 6
+#define CONTROL_EFFECT_TYPE_WALKUNDERWATER 7
+#define CONTROL_EFFECT_TYPE_JUMPUNDERWATER 8
+#define CONTROL_EFFECT_TYPE_INVIS 9
+#define CONTROL_EFFECT_TYPE_STEALTH 10
+#define CONTROL_EFFECT_TYPE_SNARE 11
+#define CONTROL_EFFECT_TYPE_FLIGHT 12
+#define CONTROL_EFFECT_TYPE_GLIDE 13
+#define CONTROL_EFFECT_TYPE_SAFEFALL 14
+#define CONTROL_EFFECT_TYPE_ILLUSION 15
+#define CONTROL_MAX_EFFECTS 16
+
+#define IMMUNITY_TYPE_MEZ 1
+#define IMMUNITY_TYPE_STIFLE 2
+#define IMMUNITY_TYPE_DAZE 3
+#define IMMUNITY_TYPE_STUN 4
+#define IMMUNITY_TYPE_ROOT 5
+#define IMMUNITY_TYPE_FEAR 6
+#define IMMUNITY_TYPE_AOE 7
+#define IMMUNITY_TYPE_TAUNT 8
+#define IMMUNITY_TYPE_RIPOSTE 9
+#define IMMUNITY_TYPE_STRIKETHROUGH 10
+#define IMMUNITY_MAX_TYPES 11
+
+class ControlEffects {
+public:
+ ControlEffects() : reg_(CONTROL_MAX_EFFECTS - 1) {} // max code = 14
+
+ bool Add(uint8_t type, LuaSpell* s) { return reg_.Add(type, s); }
+ template bool AddOrUpdate(uint8_t t, LuaSpell* s, T v){ return reg_.AddOrUpdate(t, s, std::move(v)); }
+ bool Remove(uint8_t type, LuaSpell* s) { return reg_.Remove(type, s); }
+ void Clear(uint8_t type) { reg_.Clear(type); }
+
+ bool Has(uint8_t type) const { return reg_.Has(type); }
+ bool Contains(uint8_t type, const LuaSpell* s) const { return reg_.Contains(type, s); }
+ size_t Count(uint8_t type) const { return reg_.Count(type); }
+ std::vector Snapshot(uint8_t type) const { return reg_.Snapshot(type); }
+ auto SnapshotWithValues(uint8_t type) const { return reg_.SnapshotWithValues(type); }
+
+ template bool SetValue(uint8_t t, LuaSpell* s, T v) { return reg_.SetValue(t, s, std::move(v)); }
+ bool ClearValue(uint8_t t, LuaSpell* s) { return reg_.ClearValue(t, s); }
+
+ template std::optional GetValue(uint8_t t, const LuaSpell* s) const { return reg_.GetValue(t, s); }
+
+private:
+ EffectRegistryPerSpell reg_;
+};
+
+class Immunities {
+public:
+ Immunities() : reg_(IMMUNITY_MAX_TYPES) {} // max code = 10
+
+ bool Add(uint8_t type, LuaSpell* s) { return reg_.Add(type, s); }
+ template bool AddOrUpdate(uint8_t t, LuaSpell* s, T v){ return reg_.AddOrUpdate(t, s, std::move(v)); }
+ bool Remove(uint8_t type, LuaSpell* s) { return reg_.Remove(type, s); }
+ void Clear(uint8_t type) { reg_.Clear(type); }
+
+ bool Has(uint8_t type) const { return reg_.Has(type); }
+ bool Contains(uint8_t type, const LuaSpell* s) const { return reg_.Contains(type, s); }
+ size_t Count(uint8_t type) const { return reg_.Count(type); }
+ std::vector Snapshot(uint8_t type) const { return reg_.Snapshot(type); }
+ auto SnapshotWithValues(uint8_t type) const { return reg_.SnapshotWithValues(type); }
+
+ template bool SetValue(uint8_t t, LuaSpell* s, T v) { return reg_.SetValue(t, s, std::move(v)); }
+ bool ClearValue(uint8_t t, LuaSpell* s) { return reg_.ClearValue(t, s); }
+
+ template std::optional GetValue(uint8_t t, const LuaSpell* s) const { return reg_.GetValue(t, s); }
+
+private:
+ EffectRegistryPerSpell reg_;
+};
\ No newline at end of file
diff --git a/source/WorldServer/Entity.cpp b/source/WorldServer/Entity.cpp
index 6838ee1..0fc3799 100644
--- a/source/WorldServer/Entity.cpp
+++ b/source/WorldServer/Entity.cpp
@@ -73,11 +73,6 @@ Entity::Entity(){
MMaintainedSpells.SetName("Entity::MMaintainedSpells");
MSpellEffects.SetName("Entity::MSpellEffects");
m_procList.clear();
- control_effects.clear();
- for (int i = 0; i < CONTROL_MAX_EFFECTS; i++)
- control_effects[i] = NULL;
-
- immunities.clear();
info_struct.ResetEffects(this);
@@ -101,15 +96,6 @@ Entity::~Entity(){
safe_delete(itr2.value);
ClearProcs();
safe_delete(m_threatTransfer);
- map*>::iterator itr3;
- for (itr3 = control_effects.begin(); itr3 != control_effects.end(); itr3++)
- safe_delete(itr3->second);
- control_effects.clear();
- map*>::iterator itr4;
- for (itr4 = immunities.begin(); itr4 != immunities.end(); itr4++)
- safe_delete(itr4->second);
- immunities.clear();
- safe_delete(m_threatTransfer);
}
void Entity::DeleteSpellEffects(bool removeClient)
@@ -2067,15 +2053,10 @@ void Entity::CalculateSpellBonuses(ItemStatsValues* stats){
}
void Entity::AddMezSpell(LuaSpell* spell) {
- if (!spell)
+ if (!spell || IsMezImmune())
return;
-
- if (!control_effects[CONTROL_EFFECT_TYPE_MEZ])
- control_effects[CONTROL_EFFECT_TYPE_MEZ] = new MutexList;
-
- MutexList* mez_spells = control_effects[CONTROL_EFFECT_TYPE_MEZ];
-
- if (IsPlayer() && !IsStunned() && !IsMezImmune() && mez_spells->size(true) == 0){
+
+ if (IsPlayer() && !IsStunned() && !control_effects.Has(CONTROL_EFFECT_TYPE_MEZ)){
((Player*)this)->SetPlayerControlFlag(1, 16, true);
if (!IsRooted())
((Player*)this)->SetPlayerControlFlag(1, 8, true);
@@ -2083,22 +2064,18 @@ void Entity::AddMezSpell(LuaSpell* spell) {
GetZone()->LockAllSpells((Player*)this);
}
- if (IsNPC() && !IsMezImmune())
+ if (IsNPC())
{
HaltMovement();
}
- mez_spells->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_MEZ, spell);
}
void Entity::RemoveMezSpell(LuaSpell* spell) {
- MutexList* mez_spells = control_effects[CONTROL_EFFECT_TYPE_MEZ];
- if (!mez_spells || mez_spells->size(true) == 0)
- return;
-
- mez_spells->Remove(spell);
- if (mez_spells->size(true) == 0){
- if (IsPlayer() && !IsMezImmune() && !IsStunned()){
+ control_effects.Remove(CONTROL_EFFECT_TYPE_MEZ, spell);
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_MEZ)){
+ if (IsPlayer() && !IsStunned()){
if (!IsStifled() && !IsFeared())
GetZone()->UnlockAllSpells((Player*)this);
((Player*)this)->SetPlayerControlFlag(1, 16, false);
@@ -2114,13 +2091,7 @@ void Entity::RemoveMezSpell(LuaSpell* spell) {
}
void Entity::RemoveAllMezSpells() {
- MutexList* mez_spells = control_effects[CONTROL_EFFECT_TYPE_MEZ];
- if (!mez_spells)
- return;
-
- MutexList::iterator itr = mez_spells->begin();
- while (itr.Next()){
- LuaSpell* spell = itr.value;
+ for (LuaSpell* spell : control_effects.Snapshot(CONTROL_EFFECT_TYPE_MEZ)) {
if (!spell)
continue;
GetZone()->RemoveTargetFromSpell(spell, this);
@@ -2129,9 +2100,8 @@ void Entity::RemoveAllMezSpells() {
if (IsPlayer())
((Player*)this)->RemoveSkillBonus(spell->spell->GetSpellID());
}
-
- mez_spells->clear();
- if (IsPlayer() && !IsMezImmune() && !IsStunned()){
+ control_effects.Clear(CONTROL_EFFECT_TYPE_MEZ);
+ if (IsPlayer() && !IsStunned()){
if (!IsStifled() && !IsFeared())
GetZone()->UnlockAllSpells((Player*)this);
((Player*)this)->SetPlayerControlFlag(1, 16, false);
@@ -2141,55 +2111,37 @@ void Entity::RemoveAllMezSpells() {
}
void Entity::AddStifleSpell(LuaSpell* spell) {
- if (!spell)
+ if (!spell || IsStifleImmune() || IsMezzedOrStunned())
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_STIFLE])
- control_effects[CONTROL_EFFECT_TYPE_STIFLE] = new MutexList;
-
- if (IsPlayer() && control_effects[CONTROL_EFFECT_TYPE_STIFLE]->size(true) == 0 && !IsStifleImmune() && !IsMezzedOrStunned())
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_STIFLE))
GetZone()->LockAllSpells((Player*)this);
- control_effects[CONTROL_EFFECT_TYPE_STIFLE]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_STIFLE, spell);
}
void Entity::RemoveStifleSpell(LuaSpell* spell) {
- MutexList* stifle_list = control_effects[CONTROL_EFFECT_TYPE_STIFLE];
- if (!stifle_list || stifle_list->size(true) == 0)
- return;
-
- stifle_list->Remove(spell);
-
- if (IsPlayer() && stifle_list->size(true) == 0 && !IsStifleImmune() && !IsMezzedOrStunned())
+ control_effects.Remove(CONTROL_EFFECT_TYPE_STIFLE, spell);
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_STIFLE))
GetZone()->UnlockAllSpells((Player*)this);
}
void Entity::AddDazeSpell(LuaSpell* spell) {
if (!spell)
return;
-
- if (!control_effects[CONTROL_EFFECT_TYPE_DAZE])
- control_effects[CONTROL_EFFECT_TYPE_DAZE] = new MutexList;
-
- control_effects[CONTROL_EFFECT_TYPE_DAZE]->Add(spell);
+
+ control_effects.Add(CONTROL_EFFECT_TYPE_DAZE, spell);
}
void Entity::RemoveDazeSpell(LuaSpell* spell) {
- MutexList* daze_list = control_effects[CONTROL_EFFECT_TYPE_DAZE];
- if (!daze_list || daze_list->size(true) == 0)
- return;
-
- daze_list->Remove(spell);
+ control_effects.Remove(CONTROL_EFFECT_TYPE_DAZE, spell);
}
void Entity::AddStunSpell(LuaSpell* spell) {
- if (!spell)
+ if (!spell || IsStunImmune())
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_STUN])
- control_effects[CONTROL_EFFECT_TYPE_STUN] = new MutexList;
-
- if (IsPlayer() && control_effects[CONTROL_EFFECT_TYPE_STUN]->size(true) == 0 && !IsStunImmune()){
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_STUN)){
if (!IsMezzed()){
((Player*)this)->SetPlayerControlFlag(1, 16, true);
if (!IsRooted())
@@ -2199,17 +2151,13 @@ void Entity::AddStunSpell(LuaSpell* spell) {
}
}
- control_effects[CONTROL_EFFECT_TYPE_STUN]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_STUN, spell);
}
void Entity::RemoveStunSpell(LuaSpell* spell) {
- MutexList* stun_list = control_effects[CONTROL_EFFECT_TYPE_STUN];
- if (!stun_list || stun_list->size(true) == 0)
- return;
-
- stun_list->Remove(spell);
- if (stun_list->size(true) == 0){
- if (IsPlayer() && !IsMezzed() && !IsStunImmune()){
+ control_effects.Remove(CONTROL_EFFECT_TYPE_STUN, spell);
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_STUN)){
+ if (IsPlayer() && !IsMezzed()){
((Player*)this)->SetPlayerControlFlag(1, 16, false);
if (!IsRooted())
((Player*)this)->SetPlayerControlFlag(1, 8, false);
@@ -2555,6 +2503,8 @@ int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
for (auto it = tmp_deletes.begin(); it != tmp_deletes.end(); ++it) {
GetZone()->GetSpellProcess()->DeleteCasterSpell(*it, "purged");
+ // maybe this instead:
+ //GetZone()->GetSpellProcess()->DeleteCasterSpell(*it, "purged", false, this);
}
return damage;
}
@@ -2881,34 +2831,35 @@ DetrimentalEffects* Entity::GetDetrimentalEffect(int32 spell_id, Entity* caster)
void Entity::CancelAllStealth() {
bool did_change = false;
- MutexList* stealth_list = control_effects[CONTROL_EFFECT_TYPE_STEALTH];
- if (stealth_list){
- MutexList::iterator itr = stealth_list->begin();
- while (itr.Next()){
- if (itr.value->caster == this)
- GetZone()->GetSpellProcess()->AddSpellCancel(itr.value);
- else{
- GetZone()->RemoveTargetFromSpell(itr.value, this);
- RemoveSpellEffect(itr.value);
- }
- did_change = true;
+
+ for (LuaSpell* spell : control_effects.Snapshot(CONTROL_EFFECT_TYPE_STEALTH)) {
+ if (!spell)
+ continue;
+
+ if (spell->caster == this)
+ GetZone()->GetSpellProcess()->AddSpellCancel(spell);
+ else{
+ GetZone()->RemoveTargetFromSpell(spell, this);
+ RemoveSpellEffect(spell);
}
- stealth_list->clear();
+ did_change = true;
}
- MutexList* invis_list = control_effects[CONTROL_EFFECT_TYPE_INVIS];
- if (invis_list){
- MutexList::iterator invis_itr = invis_list->begin();
- while (invis_itr.Next()){
- if (invis_itr.value->caster == this)
- GetZone()->GetSpellProcess()->AddSpellCancel(invis_itr.value);
- else{
- GetZone()->RemoveTargetFromSpell(invis_itr.value, this);
- RemoveSpellEffect(invis_itr.value);
- }
- did_change = true;
+ control_effects.Clear(CONTROL_EFFECT_TYPE_STEALTH);
+
+
+ for (LuaSpell* spell : control_effects.Snapshot(CONTROL_EFFECT_TYPE_INVIS)) {
+ if (!spell)
+ continue;
+
+ if (spell->caster == this)
+ GetZone()->GetSpellProcess()->AddSpellCancel(spell);
+ else{
+ GetZone()->RemoveTargetFromSpell(spell, this);
+ RemoveSpellEffect(spell);
}
- invis_list->clear();
+ did_change = true;
}
+ control_effects.Clear(CONTROL_EFFECT_TYPE_INVIS);
if (did_change){
info_changed = true;
@@ -2922,8 +2873,7 @@ void Entity::CancelAllStealth() {
}
bool Entity::IsStealthed(){
- MutexList* stealth_list = control_effects[CONTROL_EFFECT_TYPE_STEALTH];
- return (!stealth_list || stealth_list->size(true) == 0) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_STEALTH);
}
bool Entity::CanSeeInvis(Entity* target) {
@@ -2941,19 +2891,14 @@ bool Entity::CanSeeInvis(Entity* target) {
}
bool Entity::IsInvis(){
- MutexList* invis_list = control_effects[CONTROL_EFFECT_TYPE_INVIS];
- return (!invis_list || invis_list->size(true) == 0) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_INVIS);
}
void Entity::AddStealthSpell(LuaSpell* spell) {
if (!spell)
return;
-
- if (!control_effects[CONTROL_EFFECT_TYPE_STEALTH])
- control_effects[CONTROL_EFFECT_TYPE_STEALTH] = new MutexList;
-
- control_effects[CONTROL_EFFECT_TYPE_STEALTH]->Add(spell);
- if (control_effects[CONTROL_EFFECT_TYPE_STEALTH]->size(true) == 1){
+ control_effects.Add(CONTROL_EFFECT_TYPE_STEALTH, spell);
+ if (control_effects.Has(CONTROL_EFFECT_TYPE_STEALTH)){
info_changed = true;
changed = true;
AddChangedZoneSpawn();
@@ -2969,11 +2914,8 @@ void Entity::AddInvisSpell(LuaSpell* spell) {
if (!spell)
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_INVIS])
- control_effects[CONTROL_EFFECT_TYPE_INVIS] = new MutexList;
-
- control_effects[CONTROL_EFFECT_TYPE_INVIS]->Add(spell);
- if (control_effects[CONTROL_EFFECT_TYPE_INVIS]->size(true) == 1){
+ control_effects.Add(CONTROL_EFFECT_TYPE_INVIS, spell);
+ if (control_effects.Has(CONTROL_EFFECT_TYPE_INVIS)){
info_changed = true;
changed = true;
AddChangedZoneSpawn();
@@ -2986,13 +2928,9 @@ void Entity::AddInvisSpell(LuaSpell* spell) {
}
void Entity::RemoveInvisSpell(LuaSpell* spell) {
- MutexList* invis_list = control_effects[CONTROL_EFFECT_TYPE_INVIS];
- if (!invis_list || invis_list->size(true) == 0)
- return;
-
- invis_list->Remove(spell);
+ control_effects.Remove(CONTROL_EFFECT_TYPE_INVIS, spell);
RemoveSpellEffect(spell);
- if (invis_list->size(true) == 0){
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_INVIS)){
info_changed = true;
changed = true;
AddChangedZoneSpawn();
@@ -3005,13 +2943,9 @@ void Entity::RemoveInvisSpell(LuaSpell* spell) {
}
void Entity::RemoveStealthSpell(LuaSpell* spell) {
- MutexList* stealth_list = control_effects[CONTROL_EFFECT_TYPE_STEALTH];
- if (!stealth_list || stealth_list->size(true) == 0)
- return;
-
- stealth_list->Remove(spell);
+ control_effects.Remove(CONTROL_EFFECT_TYPE_STEALTH, spell);
RemoveSpellEffect(spell);
- if (stealth_list->size() == 0){
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_STEALTH)){
info_changed = true;
changed = true;
AddChangedZoneSpawn();
@@ -3024,13 +2958,10 @@ void Entity::RemoveStealthSpell(LuaSpell* spell) {
}
void Entity::AddRootSpell(LuaSpell* spell) {
- if (!spell)
+ if (!spell || IsRootImmune())
return;
-
- if (!control_effects[CONTROL_EFFECT_TYPE_ROOT])
- control_effects[CONTROL_EFFECT_TYPE_ROOT] = new MutexList;
-
- if (control_effects[CONTROL_EFFECT_TYPE_ROOT]->size(true) == 0 && !IsRootImmune()) {
+
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_ROOT)) {
if (IsPlayer()){
if (!IsMezzedOrStunned())
((Player*)this)->SetPlayerControlFlag(1, 8, true); // heading movement only
@@ -3039,16 +2970,12 @@ void Entity::AddRootSpell(LuaSpell* spell) {
SetSpeedMultiplier(0.0f);
}
- control_effects[CONTROL_EFFECT_TYPE_ROOT]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_ROOT, spell);
}
void Entity::RemoveRootSpell(LuaSpell* spell) {
- MutexList* root_list = control_effects[CONTROL_EFFECT_TYPE_ROOT];
- if (!root_list || root_list->size(true) == 0)
- return;
-
- root_list->Remove(spell);
- if (root_list->size(true) == 0 && !IsRootImmune()) {
+ control_effects.Remove(CONTROL_EFFECT_TYPE_ROOT, spell);
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_ROOT)) {
if (IsPlayer()){
if (!IsMezzedOrStunned())
((Player*)this)->SetPlayerControlFlag(1, 8, false); // heading movement only
@@ -3066,34 +2993,26 @@ void Entity::RemoveRootSpell(LuaSpell* spell) {
}
void Entity::AddFearSpell(LuaSpell* spell){
- if (!spell)
+ if (!spell || IsFearImmune())
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_FEAR])
- control_effects[CONTROL_EFFECT_TYPE_FEAR] = new MutexList;
-
- if (IsPlayer() && control_effects[CONTROL_EFFECT_TYPE_FEAR]->size(true) == 0 && !IsFearImmune()){
+ if (IsPlayer() && control_effects.Has(CONTROL_EFFECT_TYPE_FEAR)){
((Player*)this)->SetPlayerControlFlag(4, 4, true); // feared
if (!IsMezzedOrStunned() && !IsStifled())
GetZone()->LockAllSpells((Player*)this);
}
- if (!IsFearImmune() && IsNPC())
+ if (IsNPC())
{
HaltMovement();
}
- control_effects[CONTROL_EFFECT_TYPE_FEAR]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_FEAR, spell);
}
void Entity::RemoveFearSpell(LuaSpell* spell){
- MutexList* fear_list = control_effects[CONTROL_EFFECT_TYPE_FEAR];
- if (!fear_list || fear_list->size(true) == 0)
- return;
-
- fear_list->Remove(spell);
-
- if (IsPlayer() && fear_list->size(true) == 0 && !IsFearImmune()){
+ control_effects.Remove(CONTROL_EFFECT_TYPE_FEAR, spell);
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_FEAR)){
((Player*)this)->SetPlayerControlFlag(4, 4, false); // feared disabled
if (!IsMezzedOrStunned() && !IsStifled())
GetZone()->LockAllSpells((Player*)this);
@@ -3106,35 +3025,23 @@ void Entity::RemoveFearSpell(LuaSpell* spell){
}
void Entity::AddSnareSpell(LuaSpell* spell) {
- if (!spell)
- return;
+ control_effects.Add(CONTROL_EFFECT_TYPE_SNARE, spell);
- if (!control_effects[CONTROL_EFFECT_TYPE_SNARE])
- control_effects[CONTROL_EFFECT_TYPE_SNARE] = new MutexList;
-
- control_effects[CONTROL_EFFECT_TYPE_SNARE]->Add(spell);
-
- // Don't set speed multiplier if there is a root or no snare values
- MutexList* roots = control_effects[CONTROL_EFFECT_TYPE_ROOT];
- if ((!roots || roots->size(true) == 0) && snare_values.size() > 0)
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_ROOT) && control_effects.Has(CONTROL_EFFECT_TYPE_SNARE))
SetSpeedMultiplier(GetHighestSnare());
}
void Entity::RemoveSnareSpell(LuaSpell* spell) {
- MutexList* snare_list = control_effects[CONTROL_EFFECT_TYPE_SNARE];
- if (!snare_list || snare_list->size(true) == 0)
- return;
-
- snare_list->Remove(spell);
- snare_values.erase(spell);
-
- //LogWrite(PLAYER__ERROR, 0, "Debug", "snare_values.size() = %u", snare_values.size());
-
- // only change speeds if there are no roots
- MutexList* roots = control_effects[CONTROL_EFFECT_TYPE_ROOT];
- if (!roots || roots->size(true) == 0) {
+ control_effects.Remove(CONTROL_EFFECT_TYPE_SNARE, spell);
+ {
+ std::unique_lock lock(MSnareValues);
+ snare_values.erase(spell);
+ }
+ if (control_effects.Has(CONTROL_EFFECT_TYPE_SNARE)) {
+ SetSpeedMultiplier(GetHighestSnare());
+ }
+ else if (!control_effects.Has(CONTROL_EFFECT_TYPE_ROOT)) {
float multiplier = GetHighestSnare();
- //LogWrite(PLAYER__ERROR, 0, "Debug", "GetHighestSnare() = %f", multiplier);
SetSpeedMultiplier(multiplier);
}
}
@@ -3143,7 +3050,10 @@ void Entity::SetSnareValue(LuaSpell* spell, float snare_val) {
if (!spell)
return;
- snare_values[spell] = snare_val;
+ {
+ std::unique_lock lock(MSnareValues);
+ snare_values[spell] = snare_val;
+ }
}
float Entity::GetHighestSnare() {
@@ -3168,115 +3078,75 @@ float Entity::GetHighestSnare() {
weight_diff = weight_pct_cap; // cap weight impact rule
}
}
- if (snare_values.size() == 0)
- return ((ret - weight_diff) < 0.0f ) ? 0.0f : (ret - weight_diff);
+
+ {
+ std::shared_lock rlock(MSnareValues);
+ if (snare_values.size() == 0)
+ return ((ret - weight_diff) < 0.0f ) ? 0.0f : (ret - weight_diff);
- map::iterator itr;
- for (itr = snare_values.begin(); itr != snare_values.end(); itr++) {
- if (itr->second < ret)
- ret = itr->second;
+ map::iterator itr;
+ for (itr = snare_values.begin(); itr != snare_values.end(); itr++) {
+ if (itr->second < ret)
+ ret = itr->second;
+ }
}
return ((ret - weight_diff) < 0.0f ) ? 0.0f : (ret - weight_diff);
}
bool Entity::IsSnared() {
- if (control_effects.size() < 1 || !control_effects[CONTROL_EFFECT_TYPE_SNARE])
- return false;
-
- MutexList* snare_list = control_effects[CONTROL_EFFECT_TYPE_SNARE];
- return (!snare_list || snare_list->size(true) == 0) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_SNARE);
}
bool Entity::IsMezzed(){
- if (control_effects.size() < 1 || !control_effects[CONTROL_EFFECT_TYPE_MEZ])
- return false;
-
- MutexList* mez_spells = control_effects[CONTROL_EFFECT_TYPE_MEZ];
- return (!mez_spells || mez_spells->size(true) == 0 || IsMezImmune()) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_MEZ);
}
bool Entity::IsStifled(){
- if (!control_effects[CONTROL_EFFECT_TYPE_STIFLE])
- return false;
-
- MutexList* stifle_list = control_effects[CONTROL_EFFECT_TYPE_STIFLE];
- return (!stifle_list || stifle_list->size(true) == 0 || IsStifleImmune()) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_STIFLE);
}
bool Entity::IsDazed(){
- if (control_effects.size() < 1 || !control_effects[CONTROL_EFFECT_TYPE_DAZE])
- return false;
-
- MutexList* daze_list = control_effects[CONTROL_EFFECT_TYPE_DAZE];
- return (!daze_list || daze_list->size(true) == 0 || IsDazeImmune()) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_DAZE);
}
bool Entity::IsStunned(){
- if (!control_effects[CONTROL_EFFECT_TYPE_STUN])
- return false;
-
- MutexList* stun_list = control_effects[CONTROL_EFFECT_TYPE_STUN];
- return (!stun_list || stun_list->size(true) == 0 || IsStunImmune()) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_STUN);
}
bool Entity::IsRooted(){
- if (control_effects.size() < 1 || !control_effects[CONTROL_EFFECT_TYPE_ROOT])
- return false;
-
- MutexList* root_list = control_effects[CONTROL_EFFECT_TYPE_ROOT];
- return (!root_list || root_list->size(true) == 0 || IsRootImmune()) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_ROOT);
}
bool Entity::IsFeared(){
- if (control_effects.size() < 1 || !control_effects[CONTROL_EFFECT_TYPE_FEAR])
- return false;
-
- MutexList* fear_list = control_effects[CONTROL_EFFECT_TYPE_FEAR];
- return (!fear_list || fear_list->size(true) == 0 || IsFearImmune()) == false;
+ return control_effects.Has(CONTROL_EFFECT_TYPE_FEAR);
}
void Entity::AddWaterwalkSpell(LuaSpell* spell){
if (!spell)
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_WALKUNDERWATER])
- control_effects[CONTROL_EFFECT_TYPE_WALKUNDERWATER] = new MutexList;
-
- control_effects[CONTROL_EFFECT_TYPE_WALKUNDERWATER]->Add(spell);
- if (control_effects[CONTROL_EFFECT_TYPE_WALKUNDERWATER]->size(true) == 1 && IsPlayer())
+ control_effects.Add(CONTROL_EFFECT_TYPE_WALKUNDERWATER, spell);
+ if (control_effects.Has(CONTROL_EFFECT_TYPE_WALKUNDERWATER) && IsPlayer())
((Player*)this)->SetPlayerControlFlag(3, 128, true); // enable walking underwater
}
void Entity::RemoveWaterwalkSpell(LuaSpell* spell){
- MutexList* waterwalk_list = control_effects[CONTROL_EFFECT_TYPE_WALKUNDERWATER];
- if (!waterwalk_list || waterwalk_list->size(true) == 0)
- return;
-
- waterwalk_list->Remove(spell);
- if (waterwalk_list->size(true) == 0 && IsPlayer())
+ control_effects.Remove(CONTROL_EFFECT_TYPE_WALKUNDERWATER, spell);
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_WALKUNDERWATER) && IsPlayer()){
((Player*)this)->SetPlayerControlFlag(3, 128, false); // disable walking underwater
+ }
}
void Entity::AddWaterjumpSpell(LuaSpell* spell){
- if (!spell)
- return;
-
- if (!control_effects[CONTROL_EFFECT_TYPE_JUMPUNDERWATER])
- control_effects[CONTROL_EFFECT_TYPE_JUMPUNDERWATER] = new MutexList;
-
- control_effects[CONTROL_EFFECT_TYPE_JUMPUNDERWATER]->Add(spell);
- if (control_effects[CONTROL_EFFECT_TYPE_JUMPUNDERWATER]->size(true) == 1 && IsPlayer())
+ control_effects.Add(CONTROL_EFFECT_TYPE_JUMPUNDERWATER, spell);
+ if (control_effects.Has(CONTROL_EFFECT_TYPE_JUMPUNDERWATER) && IsPlayer())
((Player*)this)->SetPlayerControlFlag(4, 1, true); // enable moonjumps underwater
}
void Entity::RemoveWaterjumpSpell(LuaSpell* spell){
- MutexList* waterjump_list = control_effects[CONTROL_EFFECT_TYPE_JUMPUNDERWATER];
- if (!waterjump_list || waterjump_list->size(true) == 0)
- return;
-
- waterjump_list->Remove(spell);
- if (waterjump_list->size(true) == 0 && IsPlayer())
+ control_effects.Remove(CONTROL_EFFECT_TYPE_JUMPUNDERWATER, spell);
+ if (!control_effects.Has(CONTROL_EFFECT_TYPE_JUMPUNDERWATER) && IsPlayer())
((Player*)this)->SetPlayerControlFlag(4, 1, false); // disable moonjumps underwater
}
@@ -3284,45 +3154,32 @@ void Entity::AddAOEImmunity(LuaSpell* spell){
if (!spell)
return;
- if (!immunities[IMMUNITY_TYPE_AOE])
- immunities[IMMUNITY_TYPE_AOE] = new MutexList;
-
- immunities[IMMUNITY_TYPE_AOE]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_AOE, spell);
}
void Entity::RemoveAOEImmunity(LuaSpell* spell){
- MutexList* aoe_list = immunities[IMMUNITY_TYPE_AOE];
- if (!aoe_list || aoe_list->size(true) == 0)
- return;
- aoe_list->Remove(spell);
+ immunities.Remove(IMMUNITY_TYPE_AOE, spell);
}
bool Entity::IsAOEImmune(){
- return (immunities[IMMUNITY_TYPE_AOE] && immunities[IMMUNITY_TYPE_AOE]->size(true));
+ return immunities.Has(IMMUNITY_TYPE_AOE);
}
void Entity::AddStunImmunity(LuaSpell* spell){
if (!spell)
return;
-
- if (!immunities[IMMUNITY_TYPE_STUN])
- immunities[IMMUNITY_TYPE_STUN] = new MutexList;
-
+
if (IsPlayer() && IsStunned() && !IsMezzed()){
((Player*)this)->SetPlayerControlFlag(4, 64, false);
if (!IsFeared() && !IsStifled())
((Player*)this)->UnlockAllSpells();
}
- immunities[IMMUNITY_TYPE_STUN]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_STUN, spell);
}
void Entity::RemoveStunImmunity(LuaSpell* spell){
- MutexList* stun_list = immunities[IMMUNITY_TYPE_STUN];
- if (!stun_list || stun_list->size(true) == 0)
- return;
-
- stun_list->Remove(spell);
+ immunities.Remove(IMMUNITY_TYPE_STUN, spell);
if (IsPlayer() && IsStunned() && !IsMezzed()){
((Player*)this)->SetPlayerControlFlag(4, 64, true);
@@ -3332,61 +3189,47 @@ void Entity::RemoveStunImmunity(LuaSpell* spell){
}
bool Entity::IsStunImmune(){
- return (immunities[IMMUNITY_TYPE_STUN] && immunities[IMMUNITY_TYPE_STUN]->size(true) > 0);
+ return immunities.Has(IMMUNITY_TYPE_STUN);
}
void Entity::AddStifleImmunity(LuaSpell* spell){
if (!spell)
return;
-
- if (!immunities[IMMUNITY_TYPE_STIFLE])
- immunities[IMMUNITY_TYPE_STIFLE] = new MutexList;
-
- if (IsPlayer() && immunities[IMMUNITY_TYPE_STIFLE]->size(true) == 0){
+
+ if (IsPlayer() && !immunities.Has(IMMUNITY_TYPE_STIFLE)){
if (IsStifled() && !IsMezzedOrStunned() && !IsFeared())
((Player*)this)->UnlockAllSpells();
}
- immunities[IMMUNITY_TYPE_STIFLE]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_STIFLE, spell);
}
void Entity::RemoveStifleImmunity(LuaSpell* spell){
- MutexList* stifle_list = immunities[IMMUNITY_TYPE_STIFLE];
- if (!stifle_list || stifle_list->size(true) == 0)
- return;
-
- stifle_list->Remove(spell);
+ immunities.Remove(IMMUNITY_TYPE_STIFLE, spell);
if (IsPlayer() && IsStifled() && !IsMezzedOrStunned() && !IsFeared())
((Player*)this)->UnlockAllSpells();
}
bool Entity::IsStifleImmune(){
- return (immunities[IMMUNITY_TYPE_STIFLE] && immunities[IMMUNITY_TYPE_STIFLE]->size(true) > 0);
+ return immunities.Has(IMMUNITY_TYPE_STIFLE);
}
void Entity::AddMezImmunity(LuaSpell* spell){
if (!spell)
return;
-
- if (!immunities[IMMUNITY_TYPE_MEZ])
- immunities[IMMUNITY_TYPE_MEZ] = new MutexList;
-
+
if (IsPlayer() && IsMezzed() && !IsStunned()){
((Player*)this)->SetPlayerControlFlag(4, 64, false);
if (!IsFeared() && !IsStifled())
((Player*)this)->UnlockAllSpells();
}
- immunities[IMMUNITY_TYPE_MEZ]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_MEZ, spell);
}
void Entity::RemoveMezImmunity(LuaSpell* spell){
- MutexList* mez_list = immunities[IMMUNITY_TYPE_MEZ];
- if (!mez_list || mez_list->size(true) == 0)
- return;
-
- mez_list->Remove(spell);
+ immunities.Remove(IMMUNITY_TYPE_MEZ, spell);
if (IsPlayer() && IsMezzed() && !IsStunned()){
((Player*)this)->SetPlayerControlFlag(4, 64, true);
@@ -3396,59 +3239,45 @@ void Entity::RemoveMezImmunity(LuaSpell* spell){
}
bool Entity::IsMezImmune(){
- return (immunities[IMMUNITY_TYPE_MEZ] && immunities[IMMUNITY_TYPE_MEZ]->size(true) > 0);
+ return immunities.Has(IMMUNITY_TYPE_MEZ);
}
void Entity::AddRootImmunity(LuaSpell* spell){
if (!spell)
return;
-
- if (!immunities[IMMUNITY_TYPE_ROOT])
- immunities[IMMUNITY_TYPE_ROOT] = new MutexList;
-
+
if (IsPlayer() && IsRooted())
((Player*)this)->SetPlayerControlFlag(1, 8, false);
- immunities[IMMUNITY_TYPE_ROOT]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_ROOT, spell);
}
void Entity::RemoveRootImmunity(LuaSpell* spell){
- MutexList* root_list = immunities[IMMUNITY_TYPE_ROOT];
- if (!root_list || root_list->size(true) == 0)
- return;
-
- root_list->Remove(spell);
-
+ immunities.Remove(IMMUNITY_TYPE_ROOT, spell);
+
if (IsPlayer() && IsRooted())
((Player*)this)->SetPlayerControlFlag(1, 8, true);
}
bool Entity::IsRootImmune(){
- return (immunities[IMMUNITY_TYPE_ROOT] && immunities[IMMUNITY_TYPE_ROOT]->size(true) > 0);
+ return immunities.Has(IMMUNITY_TYPE_ROOT);
}
void Entity::AddFearImmunity(LuaSpell* spell){
if (!spell)
return;
- if (!immunities[IMMUNITY_TYPE_FEAR])
- immunities[IMMUNITY_TYPE_FEAR] = new MutexList;
-
if (IsPlayer() && IsFeared()){
if (!IsMezzedOrStunned() && !IsStifled())
((Player*)this)->UnlockAllSpells();
((Player*)this)->SetPlayerControlFlag(4, 4, false);
}
- immunities[IMMUNITY_TYPE_FEAR]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_FEAR, spell);
}
void Entity::RemoveFearImmunity(LuaSpell* spell){
- MutexList* fear_list = immunities[IMMUNITY_TYPE_FEAR];
- if (!fear_list || fear_list->size(true) == 0)
- return;
-
- fear_list->Remove(spell);
+ immunities.Remove(IMMUNITY_TYPE_FEAR, spell);
if (IsPlayer() && IsFeared()){
if (!IsMezzedOrStunned() && !IsStifled())
@@ -3458,108 +3287,94 @@ void Entity::RemoveFearImmunity(LuaSpell* spell){
}
bool Entity::IsFearImmune(){
- return (immunities[IMMUNITY_TYPE_FEAR] && immunities[IMMUNITY_TYPE_FEAR]->size(true) > 0);
+ return immunities.Has(IMMUNITY_TYPE_FEAR);
}
void Entity::AddDazeImmunity(LuaSpell* spell){
if (!spell)
return;
- if (!immunities[IMMUNITY_TYPE_DAZE])
- immunities[IMMUNITY_TYPE_DAZE] = new MutexList;
-
- immunities[IMMUNITY_TYPE_DAZE]->Add(spell);
+ immunities.Add(IMMUNITY_TYPE_DAZE, spell);
}
void Entity::RemoveDazeImmunity(LuaSpell* spell){
- MutexList* daze_list = immunities[IMMUNITY_TYPE_DAZE];
- if (!daze_list || daze_list->size(true) == 0)
- return;
-
- daze_list->Remove(spell);
+ immunities.Remove(IMMUNITY_TYPE_DAZE, spell);
}
bool Entity::IsDazeImmune(){
- return (immunities[IMMUNITY_TYPE_DAZE] && immunities[IMMUNITY_TYPE_DAZE]->size(true) > 0);
+ return immunities.Has(IMMUNITY_TYPE_DAZE);
}
void Entity::AddImmunity(LuaSpell* spell, int8 type){
if (!spell)
return;
-
- if (!immunities[type])
- immunities[type] = new MutexList;
-
- immunities[type]->Add(spell);
+
+ immunities.Add(type, spell);
}
void Entity::RemoveImmunity(LuaSpell* spell, int8 type){
- MutexList* list = immunities[type];
- if (!list || list->size(true) == 0)
- return;
-
- list->Remove(spell);
+ immunities.Remove(type, spell);
}
bool Entity::IsImmune(int8 type){
- return (immunities[type] && immunities[type]->size(true) > 0);
+ return immunities.Has(type);
}
void Entity::RemoveEffectsFromLuaSpell(LuaSpell* spell){
if (!spell)
return;
- //Attempt to remove all applied effects from this spell when spell has been removed from just this target. Should improve performance/easier maitenance
- int32 effect_bitmask = spell->effect_bitmask;
- if (effect_bitmask == 0)
+ if (spell->effect_flags.none())
return;
- if (effect_bitmask & EFFECT_FLAG_STUN)
+ if (spell->effect_flags.has(EFFECT_IDX_STUN))
RemoveStunSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_ROOT)
+ if (spell->effect_flags.has(EFFECT_IDX_ROOT))
RemoveRootSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_MEZ)
+ if (spell->effect_flags.has(EFFECT_IDX_MEZ))
RemoveMezSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_STIFLE)
+ if (spell->effect_flags.has(EFFECT_IDX_STIFLE))
RemoveStifleSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_DAZE)
+ if (spell->effect_flags.has(EFFECT_IDX_DAZE))
RemoveDazeSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_FEAR)
+ if (spell->effect_flags.has(EFFECT_IDX_FEAR))
RemoveFearSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_SPELLBONUS)
+ if (spell->effect_flags.has(EFFECT_IDX_SPELLBONUS))
RemoveSpellBonus(spell);
- if (effect_bitmask & EFFECT_FLAG_SKILLBONUS)
+ if (spell->effect_flags.has(EFFECT_IDX_SKILLBONUS))
RemoveSkillBonus(spell->spell->GetSpellID());
- if (effect_bitmask & EFFECT_FLAG_STEALTH)
+ if (spell->effect_flags.has(EFFECT_IDX_STEALTH))
RemoveStealthSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_INVIS)
+ if (spell->effect_flags.has(EFFECT_IDX_INVIS))
RemoveInvisSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_SNARE)
+ if (spell->effect_flags.has(EFFECT_IDX_SNARE))
RemoveSnareSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_WATERWALK)
+ if (spell->effect_flags.has(EFFECT_IDX_WATERWALK))
RemoveWaterwalkSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_WATERJUMP)
+ if (spell->effect_flags.has(EFFECT_IDX_WATERJUMP))
RemoveWaterjumpSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_FLIGHT)
+ if (spell->effect_flags.has(EFFECT_IDX_FLIGHT))
RemoveFlightSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_GLIDE)
+ if (spell->effect_flags.has(EFFECT_IDX_GLIDE))
RemoveGlideSpell(spell);
- if (effect_bitmask & EFFECT_FLAG_AOE_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_AOE_IMMUNE))
RemoveAOEImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_STUN_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_STUN_IMMUNE))
RemoveStunImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_MEZ_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_MEZ_IMMUNE))
RemoveMezImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_DAZE_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_DAZE_IMMUNE))
RemoveDazeImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_ROOT_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_ROOT_IMMUNE))
RemoveRootImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_STIFLE_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_STIFLE_IMMUNE))
RemoveStifleImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_FEAR_IMMUNE)
+ if (spell->effect_flags.has(EFFECT_IDX_FEAR_IMMUNE))
RemoveFearImmunity(spell);
- if (effect_bitmask & EFFECT_FLAG_SAFEFALL)
+ if (spell->effect_flags.has(EFFECT_IDX_SAFEFALL))
RemoveSafefallSpell(spell);
+ if (spell->effect_flags.has(EFFECT_IDX_ILLUSION))
+ RemoveIllusionSpell(spell);
}
void Entity::RemoveSkillBonus(int32 spell_id){
@@ -3570,23 +3385,16 @@ void Entity::RemoveSkillBonus(int32 spell_id){
void Entity::AddFlightSpell(LuaSpell* spell){
if (!spell)
return;
-
- if (!control_effects[CONTROL_EFFECT_TYPE_FLIGHT])
- control_effects[CONTROL_EFFECT_TYPE_FLIGHT] = new MutexList;
-
- if (IsPlayer() && control_effects[CONTROL_EFFECT_TYPE_FLIGHT]->size(true) == 0)
+
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_FLIGHT))
((Player*)this)->SetPlayerControlFlag(5, 32, true);
- control_effects[CONTROL_EFFECT_TYPE_FLIGHT]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_FLIGHT, spell);
}
void Entity::RemoveFlightSpell(LuaSpell* spell){
- MutexList* flight_list = control_effects[CONTROL_EFFECT_TYPE_FLIGHT];
- if (!flight_list || flight_list->size(true) == 0)
- return;
-
- flight_list->Remove(spell);
- if (IsPlayer() && flight_list->size(true) == 0)
+ control_effects.Remove(CONTROL_EFFECT_TYPE_FLIGHT, spell);
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_FLIGHT))
((Player*)this)->SetPlayerControlFlag(5, 32, false);
}
@@ -3594,22 +3402,15 @@ void Entity::AddGlideSpell(LuaSpell* spell){
if (!spell)
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_GLIDE])
- control_effects[CONTROL_EFFECT_TYPE_GLIDE] = new MutexList;
-
- if (IsPlayer() && control_effects[CONTROL_EFFECT_TYPE_GLIDE]->size(true) == 0)
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_GLIDE))
((Player*)this)->SetPlayerControlFlag(4, 16, true);
- control_effects[CONTROL_EFFECT_TYPE_GLIDE]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_GLIDE, spell);
}
void Entity::RemoveGlideSpell(LuaSpell* spell){
- MutexList* glide_list = control_effects[CONTROL_EFFECT_TYPE_GLIDE];
- if (!glide_list || glide_list->size(true) == 0)
- return;
-
- glide_list->Remove(spell);
- if (IsPlayer() && glide_list->size(true) == 0)
+ control_effects.Remove(CONTROL_EFFECT_TYPE_GLIDE, spell);
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_GLIDE))
((Player*)this)->SetPlayerControlFlag(4, 16, false);
}
@@ -3617,25 +3418,32 @@ void Entity::AddSafefallSpell(LuaSpell* spell){
if (!spell)
return;
- if (!control_effects[CONTROL_EFFECT_TYPE_SAFEFALL])
- control_effects[CONTROL_EFFECT_TYPE_SAFEFALL] = new MutexList;
-
- if (IsPlayer() && control_effects[CONTROL_EFFECT_TYPE_SAFEFALL]->size(true) == 0)
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_SAFEFALL))
((Player*)this)->SetPlayerControlFlag(4, 32, true);
- control_effects[CONTROL_EFFECT_TYPE_SAFEFALL]->Add(spell);
+ control_effects.Add(CONTROL_EFFECT_TYPE_SAFEFALL, spell);
}
void Entity::RemoveSafefallSpell(LuaSpell* spell){
- MutexList* safe_list = control_effects[CONTROL_EFFECT_TYPE_SAFEFALL];
- if (!safe_list || safe_list->size(true) == 0)
- return;
-
- safe_list->Remove(spell);
- if (IsPlayer() && safe_list->size(true) == 0)
+ control_effects.Remove(CONTROL_EFFECT_TYPE_SAFEFALL, spell);
+ if (IsPlayer() && !control_effects.Has(CONTROL_EFFECT_TYPE_SAFEFALL))
((Player*)this)->SetPlayerControlFlag(4, 32, false);
}
+void Entity::AddIllusionSpell(LuaSpell* spell, int16 model_id){
+ if(!control_effects.Has(CONTROL_EFFECT_TYPE_ILLUSION)) {
+ control_effects.AddOrUpdate(CONTROL_EFFECT_TYPE_ILLUSION, spell, model_id);
+ SetIllusionModel(model_id, true);
+ }
+}
+
+void Entity::RemoveIllusionSpell(LuaSpell* spell) {
+ if(control_effects.Contains(CONTROL_EFFECT_TYPE_ILLUSION, spell)) {
+ SetIllusionModel(0, true);
+ }
+ control_effects.Remove(CONTROL_EFFECT_TYPE_ILLUSION, spell);
+}
+
void Entity::UpdateGroupMemberInfo(bool inGroupMgrLock, bool groupMembersLocked) {
if (!group_member_info || group_id == 0)
return;
@@ -3819,14 +3627,7 @@ void Entity::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
bool Entity::HasControlEffect(int8 type)
{
- if (type >= CONTROL_MAX_EFFECTS)
- return false;
-
- MutexList* spell_list = control_effects[type];
- if (!spell_list || spell_list->size(true) == 0)
- return false;
-
- return true;
+ return control_effects.Has(type);
}
void Entity::HaltMovement()
@@ -4174,16 +3975,9 @@ void Entity::SendControlEffectDetailsToClient(Client* client) {
client->Message(CHANNEL_COLOR_YELLOW, "Current control effects on %s", GetName());
client->Message(CHANNEL_COLOR_YELLOW, "-------------------------------");
for (int i = 0; i < CONTROL_MAX_EFFECTS; i++) {
- if(control_effects[i]) {
- MutexList* spells = control_effects[i];
- if(spells->size() > 0) {
- MutexList::iterator itr = spells->begin();
- while(itr.Next()){
- LuaSpell* spell = itr->value;
- if(spell && spell->spell && spell->spell->GetSpellData()) {
- client->Message(CHANNEL_COLOR_YELLOW, "Spell %s (%u) control effect %s", spell->spell->GetName(), spell->spell->GetSpellData()->id, GetControlEffectName(i).c_str());
- }
- }
+ for (LuaSpell* spell : control_effects.Snapshot(i)) {
+ if(spell && spell->spell && spell->spell->GetSpellData()) {
+ client->Message(CHANNEL_COLOR_YELLOW, "Spell %s (%u) control effect %s", spell->spell->GetName(), spell->spell->GetSpellData()->id, GetControlEffectName(i).c_str());
}
}
}
diff --git a/source/WorldServer/Entity.h b/source/WorldServer/Entity.h
index c0dccf9..e6cb2af 100644
--- a/source/WorldServer/Entity.h
+++ b/source/WorldServer/Entity.h
@@ -25,6 +25,7 @@
#include "MutexList.h"
#include "MutexVector.h"
#include "Trade.h"
+#include "EffectFlags.h"
#include
#include
#include
@@ -1115,6 +1116,7 @@ struct InfoStruct{
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
std::mutex classMutex;
std::unordered_map props;
+ EffectFlags spell_flags;
private:
std::string name_;
int8 class1_;
@@ -1413,33 +1415,6 @@ struct ThreatTransfer {
#define DISPELL_TYPE_CURE 0
#define DISPELL_TYPE_DISPELL 1
-#define CONTROL_EFFECT_TYPE_MEZ 1
-#define CONTROL_EFFECT_TYPE_STIFLE 2
-#define CONTROL_EFFECT_TYPE_DAZE 3
-#define CONTROL_EFFECT_TYPE_STUN 4
-#define CONTROL_EFFECT_TYPE_ROOT 5
-#define CONTROL_EFFECT_TYPE_FEAR 6
-#define CONTROL_EFFECT_TYPE_WALKUNDERWATER 7
-#define CONTROL_EFFECT_TYPE_JUMPUNDERWATER 8
-#define CONTROL_EFFECT_TYPE_INVIS 9
-#define CONTROL_EFFECT_TYPE_STEALTH 10
-#define CONTROL_EFFECT_TYPE_SNARE 11
-#define CONTROL_EFFECT_TYPE_FLIGHT 12
-#define CONTROL_EFFECT_TYPE_GLIDE 13
-#define CONTROL_EFFECT_TYPE_SAFEFALL 14
-#define CONTROL_MAX_EFFECTS 15 // always +1 to highest control effect
-
-#define IMMUNITY_TYPE_MEZ 1
-#define IMMUNITY_TYPE_STIFLE 2
-#define IMMUNITY_TYPE_DAZE 3
-#define IMMUNITY_TYPE_STUN 4
-#define IMMUNITY_TYPE_ROOT 5
-#define IMMUNITY_TYPE_FEAR 6
-#define IMMUNITY_TYPE_AOE 7
-#define IMMUNITY_TYPE_TAUNT 8
-#define IMMUNITY_TYPE_RIPOSTE 9
-#define IMMUNITY_TYPE_STRIKETHROUGH 10
-
//class Spell;
//class ZoneServer;
@@ -1985,6 +1960,8 @@ public:
void RemoveSafefallSpell(LuaSpell* spell);
void AddGlideSpell(LuaSpell* spell);
void RemoveGlideSpell(LuaSpell* spell);
+ void AddIllusionSpell(LuaSpell* spell, int16 model_id);
+ void RemoveIllusionSpell(LuaSpell* spell);
GroupMemberInfo* GetGroupMemberInfo() { return group_member_info; }
void SetGroupMemberInfo(GroupMemberInfo* info) { group_member_info = info; }
@@ -2110,6 +2087,10 @@ public:
return "SafeFall";
break;
}
+ case CONTROL_EFFECT_TYPE_ILLUSION:{
+ return "Illusion";
+ break;
+ }
default: {
return "Undefined";
break;
@@ -2136,8 +2117,8 @@ protected:
bool m_petDismissing;
private:
MutexList bonus_list;
- map*> control_effects;
- map*> immunities;
+ ControlEffects control_effects;
+ Immunities immunities;
float max_speed;
int8 deity;
sint16 regen_hp_rate;
@@ -2176,6 +2157,7 @@ private:
float speed_multiplier;
map snare_values;
+ mutable std::shared_mutex MSnareValues;
ThreatTransfer* m_threatTransfer;
diff --git a/source/WorldServer/LuaFunctions.cpp b/source/WorldServer/LuaFunctions.cpp
index abf38f6..9530a33 100644
--- a/source/WorldServer/LuaFunctions.cpp
+++ b/source/WorldServer/LuaFunctions.cpp
@@ -2465,8 +2465,7 @@ int EQ2Emu_lua_AddSpellBonus(lua_State* state) {
lua_interface->LogError("%s: Error applying spell bonus on non entity.", lua_interface->GetScriptName(state));
}
}
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SPELLBONUS))
- luaspell->effect_bitmask += EFFECT_FLAG_SPELLBONUS;
+ luaspell->effect_flags.add(EFFECT_IDX_SPELLBONUS);
}
else if (spawn && spawn->IsEntity()) {
((Entity*)spawn)->AddSpellBonus(luaspell, type, value, class_req, race_req, faction_req);
@@ -2540,8 +2539,7 @@ int EQ2Emu_lua_AddSpawnSpellBonus(lua_State* state) {
((Entity*)spawn)->AddSpellBonus(luaspell, type, value, class_req, race_req, faction_req);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SPELLBONUS))
- luaspell->effect_bitmask += EFFECT_FLAG_SPELLBONUS;
+ luaspell->effect_flags.add(EFFECT_IDX_SPELLBONUS);
if (spawn->IsPlayer())
((Player*)spawn)->SetCharSheetChanged(true);
@@ -2640,13 +2638,11 @@ int EQ2Emu_lua_AddSkillBonus(lua_State* state) {
if (packet)
client->QueuePacket(packet);
}
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SKILLBONUS))
- luaspell->effect_bitmask += EFFECT_FLAG_SKILLBONUS;
+ luaspell->effect_flags.add(EFFECT_IDX_SKILLBONUS);
}
else if (target->IsNPC()) {
((NPC*)target)->AddSkillBonus(spell_id, skill_id, value);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SKILLBONUS))
- luaspell->effect_bitmask += EFFECT_FLAG_SKILLBONUS;
+ luaspell->effect_flags.add(EFFECT_IDX_SKILLBONUS);
}
else
LogWrite(LUA__ERROR, 0, "LUA", "Error applying bonus buff on '%s'. Not a NPC or player.", target->GetName());
@@ -2746,77 +2742,65 @@ int EQ2Emu_lua_AddControlEffect(lua_State* state) {
if (target && target->IsEntity()) {
if (type == CONTROL_EFFECT_TYPE_MEZ) {
((Entity*)target)->AddMezSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_MEZ))
- luaspell->effect_bitmask += EFFECT_FLAG_MEZ;
+ luaspell->effect_flags.add(EFFECT_IDX_MEZ);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_STIFLE) {
((Entity*)target)->AddStifleSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_STIFLE))
- luaspell->effect_bitmask += EFFECT_FLAG_STIFLE;
+ luaspell->effect_flags.add(EFFECT_IDX_STIFLE);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_DAZE) {
((Entity*)target)->AddDazeSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_DAZE))
- luaspell->effect_bitmask += EFFECT_FLAG_DAZE;
+ luaspell->effect_flags.add(EFFECT_IDX_DAZE);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_STUN) {
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_STUN))
- luaspell->effect_bitmask += EFFECT_FLAG_STUN;
+ luaspell->effect_flags.add(EFFECT_IDX_STUN);
((Entity*)target)->AddStunSpell(luaspell);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_ROOT) {
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_ROOT))
- luaspell->effect_bitmask += EFFECT_FLAG_ROOT;
((Entity*)target)->AddRootSpell(luaspell);
+ luaspell->effect_flags.add(EFFECT_IDX_ROOT);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_FEAR) {
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_FEAR))
- luaspell->effect_bitmask += EFFECT_FLAG_FEAR;
((Entity*)target)->AddFearSpell(luaspell);
+ luaspell->effect_flags.add(EFFECT_IDX_FEAR);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_WALKUNDERWATER) {
((Entity*)target)->AddWaterwalkSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_WATERWALK))
- luaspell->effect_bitmask += EFFECT_FLAG_WATERWALK;
+ luaspell->effect_flags.add(EFFECT_IDX_WATERWALK);
}
else if (type == CONTROL_EFFECT_TYPE_JUMPUNDERWATER) {
((Entity*)target)->AddWaterjumpSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_WATERJUMP))
- luaspell->effect_bitmask += EFFECT_FLAG_WATERJUMP;
+ luaspell->effect_flags.add(EFFECT_IDX_WATERJUMP);
}
else if (type == CONTROL_EFFECT_TYPE_SNARE) {
((Entity*)target)->AddSnareSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SNARE))
- luaspell->effect_bitmask += EFFECT_FLAG_SNARE;
+ luaspell->effect_flags.add(EFFECT_IDX_SNARE);
if (target->IsNPC())
((NPC*)target)->Brain()->AddHate(luaspell->caster, 5);
}
else if (type == CONTROL_EFFECT_TYPE_FLIGHT) {
((Entity*)target)->AddFlightSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_FLIGHT))
- luaspell->effect_bitmask += EFFECT_FLAG_FLIGHT;
+ luaspell->effect_flags.add(EFFECT_IDX_FLIGHT);
}
else if (type == CONTROL_EFFECT_TYPE_GLIDE) {
((Entity*)target)->AddGlideSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_GLIDE))
- luaspell->effect_bitmask += EFFECT_FLAG_GLIDE;
+ luaspell->effect_flags.add(EFFECT_IDX_GLIDE);
}
else if (type == CONTROL_EFFECT_TYPE_SAFEFALL) {
((Entity*)target)->AddSafefallSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SAFEFALL))
- luaspell->effect_bitmask += EFFECT_FLAG_SAFEFALL;
+ luaspell->effect_flags.add(EFFECT_IDX_SAFEFALL);
}
else
lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
@@ -2828,63 +2812,51 @@ int EQ2Emu_lua_AddControlEffect(lua_State* state) {
else if (only_add_spawn && spawn && spawn->IsEntity()) {
if (type == CONTROL_EFFECT_TYPE_MEZ) {
((Entity*)spawn)->AddMezSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_MEZ))
- luaspell->effect_bitmask += EFFECT_FLAG_MEZ;
+ luaspell->effect_flags.add(EFFECT_IDX_MEZ);
}
else if (type == CONTROL_EFFECT_TYPE_STIFLE) {
((Entity*)spawn)->AddStifleSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_STIFLE))
- luaspell->effect_bitmask += EFFECT_FLAG_STIFLE;
+ luaspell->effect_flags.add(EFFECT_IDX_STIFLE);
}
else if (type == CONTROL_EFFECT_TYPE_DAZE) {
((Entity*)spawn)->AddDazeSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_DAZE))
- luaspell->effect_bitmask += EFFECT_FLAG_DAZE;
+ luaspell->effect_flags.add(EFFECT_IDX_DAZE);
}
else if (type == CONTROL_EFFECT_TYPE_STUN) {
((Entity*)spawn)->AddStunSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_STUN))
- luaspell->effect_bitmask += EFFECT_FLAG_STUN;
+ luaspell->effect_flags.add(EFFECT_IDX_STUN);
}
else if (type == CONTROL_EFFECT_TYPE_ROOT) {
((Entity*)spawn)->AddRootSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_ROOT))
- luaspell->effect_bitmask += EFFECT_FLAG_ROOT;
+ luaspell->effect_flags.add(EFFECT_IDX_ROOT);
}
else if (type == CONTROL_EFFECT_TYPE_FEAR) {
((Entity*)spawn)->AddFearSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_FEAR))
- luaspell->effect_bitmask += EFFECT_FLAG_FEAR;
+ luaspell->effect_flags.add(EFFECT_IDX_FEAR);
}
else if (type == CONTROL_EFFECT_TYPE_WALKUNDERWATER) {
((Entity*)spawn)->AddWaterwalkSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_WATERWALK))
- luaspell->effect_bitmask += EFFECT_FLAG_WATERWALK;
+ luaspell->effect_flags.add(EFFECT_IDX_WATERWALK);
}
else if (type == CONTROL_EFFECT_TYPE_JUMPUNDERWATER) {
((Entity*)spawn)->AddWaterjumpSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_WATERJUMP))
- luaspell->effect_bitmask += EFFECT_FLAG_WATERJUMP;
+ luaspell->effect_flags.add(EFFECT_IDX_WATERJUMP);
}
else if (type == CONTROL_EFFECT_TYPE_SNARE) {
((Entity*)spawn)->AddSnareSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SNARE))
- luaspell->effect_bitmask += EFFECT_FLAG_SNARE;
+ luaspell->effect_flags.add(EFFECT_IDX_SNARE);
}
else if (type == CONTROL_EFFECT_TYPE_FLIGHT) {
((Entity*)spawn)->AddFlightSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_FLIGHT))
- luaspell->effect_bitmask += EFFECT_FLAG_FLIGHT;
+ luaspell->effect_flags.add(EFFECT_IDX_FLIGHT);
}
else if (type == CONTROL_EFFECT_TYPE_GLIDE) {
((Entity*)spawn)->AddGlideSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_GLIDE))
- luaspell->effect_bitmask += EFFECT_FLAG_GLIDE;
+ luaspell->effect_flags.add(EFFECT_IDX_GLIDE);
}
else if (type == CONTROL_EFFECT_TYPE_SAFEFALL) {
((Entity*)spawn)->AddSafefallSpell(luaspell);
- if (!(luaspell->effect_bitmask & EFFECT_FLAG_SAFEFALL))
- luaspell->effect_bitmask += EFFECT_FLAG_SAFEFALL;
+ luaspell->effect_flags.add(EFFECT_IDX_SAFEFALL);
}
else
lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
@@ -2933,6 +2905,8 @@ int EQ2Emu_lua_RemoveControlEffect(lua_State* state) {
((Entity*)target)->RemoveGlideSpell(luaspell);
else if (type == CONTROL_EFFECT_TYPE_SAFEFALL)
((Entity*)target)->RemoveGlideSpell(luaspell);
+ else if (type == CONTROL_EFFECT_TYPE_ILLUSION)
+ ((Entity*)target)->RemoveIllusionSpell(luaspell);
else
lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
}
@@ -2963,6 +2937,8 @@ int EQ2Emu_lua_RemoveControlEffect(lua_State* state) {
((Entity*)spawn)->RemoveGlideSpell(luaspell);
else if (type == CONTROL_EFFECT_TYPE_SAFEFALL)
((Entity*)spawn)->RemoveSafefallSpell(luaspell);
+ else if (type == CONTROL_EFFECT_TYPE_ILLUSION)
+ ((Entity*)spawn)->RemoveIllusionSpell(luaspell);
else
lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
}
@@ -6836,13 +6812,11 @@ int EQ2Emu_lua_Stealth(lua_State* state) {
if (spawn->IsEntity()) {
if (type == 1) {
((Entity*)spawn)->AddStealthSpell(spell);
- if (!(spell->effect_bitmask & EFFECT_FLAG_STEALTH))
- spell->effect_bitmask += EFFECT_FLAG_STEALTH;
+ spell->effect_flags.add(EFFECT_IDX_STEALTH);
}
else if (type == 2) {
((Entity*)spawn)->AddInvisSpell(spell);
- if (!(spell->effect_bitmask & EFFECT_FLAG_INVIS))
- spell->effect_bitmask += EFFECT_FLAG_INVIS;
+ spell->effect_flags.add(EFFECT_IDX_INVIS);
}
return 0;
}
@@ -6859,13 +6833,11 @@ int EQ2Emu_lua_Stealth(lua_State* state) {
if (type == 1) {
((Entity*)spawn)->AddStealthSpell(spell);
- if (!(spell->effect_bitmask & EFFECT_FLAG_STEALTH))
- spell->effect_bitmask += EFFECT_FLAG_STEALTH;
+ spell->effect_flags.add(EFFECT_IDX_STEALTH);
}
else if (type == 2) {
((Entity*)spawn)->AddInvisSpell(spell);
- if (!(spell->effect_bitmask & EFFECT_FLAG_INVIS))
- spell->effect_bitmask += EFFECT_FLAG_INVIS;
+ spell->effect_flags.add(EFFECT_IDX_INVIS);
}
else {
lua_interface->LogError("%s: LUA Stealth command error: invalid stealth type given", lua_interface->GetScriptName(state));
@@ -9480,11 +9452,21 @@ int EQ2Emu_lua_SetIllusion(lua_State* state) {
lua_interface->ResetFunctionStack(state);
if (spell && spell->spell && spell->GetTargetCount() > 0) {
+ spell->effect_flags.add(EFFECT_IDX_ILLUSION);
ZoneServer* zone = spell->zone;
for (int32 id : spell->GetTargets()) {
Spawn* target = zone->GetSpawnByID(id);
- if (target)
- target->SetIllusionModel(model);
+ if (target) {
+ if(!target->IsEntity()) {
+ target->SetIllusionModel(model);
+ }
+ else if(model) {
+ ((Entity*)target)->AddIllusionSpell(spell, model);
+ }
+ else {
+ ((Entity*)target)->RemoveIllusionSpell(spell);
+ }
+ }
}
}
else {
@@ -9492,8 +9474,15 @@ int EQ2Emu_lua_SetIllusion(lua_State* state) {
lua_interface->LogError("%s: LUA SetIllusion command error: spawn is not valid", lua_interface->GetScriptName(state));
return 0;
}
-
- spawn->SetIllusionModel(model);
+ if(!spawn->IsEntity()) {
+ spawn->SetIllusionModel(model);
+ }
+ else if(model) {
+ ((Entity*)spawn)->AddIllusionSpell(nullptr, model);
+ }
+ else {
+ ((Entity*)spawn)->RemoveIllusionSpell(spell);
+ }
}
return 0;
@@ -9511,8 +9500,12 @@ int EQ2Emu_lua_ResetIllusion(lua_State* state) {
ZoneServer* zone = spell->zone;
for (int32 id : spell->GetTargets()) {
Spawn* target = zone->GetSpawnByID(id);
- if (target)
- target->SetIllusionModel(0);
+ if (target) {
+ if(target->IsEntity())
+ ((Entity*)target)->RemoveIllusionSpell(spell);
+ else
+ target->SetIllusionModel(0);
+ }
}
}
else {
@@ -9520,8 +9513,10 @@ int EQ2Emu_lua_ResetIllusion(lua_State* state) {
lua_interface->LogError("%s: LUA ResetIllusion command error: spawn is not valid", lua_interface->GetScriptName(state));
return 0;
}
-
- spawn->SetIllusionModel(0);
+ if(spawn->IsEntity())
+ ((Entity*)spawn)->RemoveIllusionSpell(spell);
+ else
+ spawn->SetIllusionModel(0);
}
return 0;
@@ -14913,4 +14908,45 @@ int EQ2Emu_lua_RemoveCharacterProperty(lua_State* state) {
Query query;
query.AddQueryAsync(((Player*)player)->GetCharacterID(), &database, Q_DELETE, "delete from character_properties where charid = %u and propname='%s'", ((Player*)player)->GetCharacterID(), propname.c_str());
return 0;
+}
+
+
+int EQ2Emu_lua_RemoveSpell(lua_State* state) {
+ Spawn* spawn = lua_interface->GetSpawn(state);
+ int32 spell_id = lua_interface->GetInt32Value(state, 2);
+ bool maintained_spell = lua_interface->GetBooleanValue(state, 3);
+ string reason = lua_interface->GetStringValue(state, 4);
+ lua_interface->ResetFunctionStack(state);
+
+ if(!spawn || !spawn->IsEntity()) {
+ lua_interface->LogError("%s: LUA RemoveSpell command error: entity is not valid", lua_interface->GetScriptName(state));
+ return 0;
+ }
+ if(!spawn->GetZone()) {
+ lua_interface->LogError("%s: LUA RemoveSpell command error: no valid zone", lua_interface->GetScriptName(state));
+ return 0;
+ }
+ if(!spell_id) {
+ lua_interface->LogError("%s: LUA RemoveSpell command error: spell id is not valid", lua_interface->GetScriptName(state));
+ return 0;
+ }
+
+ Entity* ent = (Entity*)spawn;
+
+ if(reason.length() < 1)
+ reason = "canceled";
+
+ if(maintained_spell) {
+ MaintainedEffects* effect = ent->GetMaintainedSpell(spell_id);
+ if(effect && effect->spell) {
+ ent->GetZone()->GetSpellProcess()->DeleteCasterSpell(effect->spell, reason, false);
+ }
+ }
+ else {
+ SpellEffects* effect = ent->GetSpellEffect(spell_id);
+ if(effect && effect->spell) {
+ ent->GetZone()->GetSpellProcess()->DeleteCasterSpell(effect->spell, reason, false, spawn);
+ }
+ }
+ return 0;
}
\ No newline at end of file
diff --git a/source/WorldServer/LuaFunctions.h b/source/WorldServer/LuaFunctions.h
index b66830b..71581c4 100644
--- a/source/WorldServer/LuaFunctions.h
+++ b/source/WorldServer/LuaFunctions.h
@@ -699,4 +699,5 @@ int EQ2Emu_lua_InSameRaid(lua_State* state);
int EQ2Emu_lua_GetRaid(lua_State* state);
int EQ2Emu_lua_AdjustHatePosition(lua_State* state);
int EQ2Emu_lua_RemoveCharacterProperty(lua_State* state);
+int EQ2Emu_lua_RemoveSpell(lua_State* state);
#endif
\ No newline at end of file
diff --git a/source/WorldServer/LuaInterface.cpp b/source/WorldServer/LuaInterface.cpp
index 857d5ce..dff85ba 100644
--- a/source/WorldServer/LuaInterface.cpp
+++ b/source/WorldServer/LuaInterface.cpp
@@ -1839,6 +1839,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
lua_register(state,"GetRaid", EQ2Emu_lua_GetRaid);
lua_register(state,"AdjustHatePosition", EQ2Emu_lua_AdjustHatePosition);
lua_register(state,"RemoveCharacterProperty", EQ2Emu_lua_RemoveCharacterProperty);
+ lua_register(state,"RemoveSpell", EQ2Emu_lua_RemoveSpell);
}
void LuaInterface::LogError(const char* error, ...) {
@@ -2320,7 +2321,6 @@ LuaSpell* LuaInterface::LoadSpellScript(const char* name) {
spell->had_dmg_remaining = false;
spell->slot_pos = 0;
spell->damage_remaining = 0;
- spell->effect_bitmask = 0;
spell->restored = false;
spell->has_proc = false;
spell->initial_caster_char_id = 0;
@@ -2670,7 +2670,6 @@ LuaSpell* LuaInterface::CreateSpellScript(const char* name, lua_State* existStat
new_spell->had_dmg_remaining = false;
new_spell->slot_pos = 0;
new_spell->damage_remaining = 0;
- new_spell->effect_bitmask = 0;
new_spell->caster = 0;
new_spell->initial_target = 0;
new_spell->spell = 0;
diff --git a/source/WorldServer/LuaInterface.h b/source/WorldServer/LuaInterface.h
index 7590319..80526b9 100644
--- a/source/WorldServer/LuaInterface.h
+++ b/source/WorldServer/LuaInterface.h
@@ -31,6 +31,7 @@
#include "Quests.h"
#include "zoneserver.h"
#include "client.h"
+#include "EffectFlags.h"
#include
@@ -116,7 +117,7 @@ struct LuaSpell{
bool had_triggers;
bool had_dmg_remaining;
Mutex MScriptMutex;
- int32 effect_bitmask;
+ EffectFlags effect_flags;
bool restored; // restored spell cross zone
std::atomic has_proc;
ZoneServer* zone;
diff --git a/source/WorldServer/Player.cpp b/source/WorldServer/Player.cpp
index 30ea840..6043912 100644
--- a/source/WorldServer/Player.cpp
+++ b/source/WorldServer/Player.cpp
@@ -7509,12 +7509,12 @@ void Player::SaveSpellEffects()
continue;
savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT,
- "insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u)",
+ "insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %llu, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u)",
database.getSafeEscapeString(info->spell_effects[i].spell->spell->GetName()).c_str(), caster_char_id,
target_char_id, 0 /*no target_type for spell_effects*/, DB_TYPE_SPELLEFFECTS /* db_effect_type for spell_effects */, info->spell_effects[i].spell->spell->IsCopiedSpell() ? info->spell_effects[i].spell->spell->GetSpellData()->inherited_spell_id : info->spell_effects[i].spell_id, i, info->spell_effects[i].spell->slot_pos,
info->spell_effects[i].icon, info->spell_effects[i].icon_backdrop, 0 /* no conc_used for spell_effects */, info->spell_effects[i].tier,
info->spell_effects[i].total_time, timestamp, database.getSafeEscapeString(info->spell_effects[i].spell->file_name.c_str()).c_str(), info->spell_effects[i].spell->spell->IsCopiedSpell(), GetCharacterID(),
- info->spell_effects[i].spell->damage_remaining, info->spell_effects[i].spell->effect_bitmask, info->spell_effects[i].spell->num_triggers, info->spell_effects[i].spell->had_triggers, info->spell_effects[i].spell->cancel_after_all_triggers,
+ info->spell_effects[i].spell->damage_remaining, info->spell_effects[i].spell->effect_flags.export_u64(), info->spell_effects[i].spell->num_triggers, info->spell_effects[i].spell->had_triggers, info->spell_effects[i].spell->cancel_after_all_triggers,
info->spell_effects[i].spell->crit, info->spell_effects[i].spell->last_spellattack_hit, info->spell_effects[i].spell->interrupted, info->spell_effects[i].spell->resisted, info->spell_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->spell_effects[i].spell).c_str()).c_str(), info->spell_effects[i].spell->initial_caster_level);
SaveCustomSpellFields(info->spell_effects[i].spell);
@@ -7542,11 +7542,11 @@ void Player::SaveSpellEffects()
if(info->maintained_effects[i].spell->spell->GetSpellData() && !info->maintained_effects[i].spell->spell->GetSpellData()->duration_until_cancel)
timestamp = info->maintained_effects[i].expire_timestamp - Timer::GetCurrentTime2();
savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT,
- "insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u)",
+ "insert into character_spell_effects (name, caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos, icon, icon_backdrop, conc_used, tier, total_time, expire_timestamp, lua_file, custom_spell, charid, damage_remaining, effect_bitmask, num_triggers, had_triggers, cancel_after_triggers, crit, last_spellattack_hit, interrupted, resisted, has_damaged, custom_function, caster_level) values ('%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %f, %u, '%s', %u, %u, %u, %llu, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u)",
database.getSafeEscapeString(info->maintained_effects[i].name).c_str(), caster_char_id, target_char_id, info->maintained_effects[i].target_type, DB_TYPE_MAINTAINEDEFFECTS /* db_effect_type for maintained_effects */, info->maintained_effects[i].spell->spell->IsCopiedSpell() ? info->maintained_effects[i].spell->spell->GetSpellData()->inherited_spell_id : info->maintained_effects[i].spell_id, i, info->maintained_effects[i].slot_pos,
info->maintained_effects[i].icon, info->maintained_effects[i].icon_backdrop, info->maintained_effects[i].conc_used, info->maintained_effects[i].tier,
info->maintained_effects[i].total_time, timestamp, database.getSafeEscapeString(info->maintained_effects[i].spell->file_name.c_str()).c_str(), info->maintained_effects[i].spell->spell->IsCopiedSpell(), GetCharacterID(),
- info->maintained_effects[i].spell->damage_remaining, info->maintained_effects[i].spell->effect_bitmask, info->maintained_effects[i].spell->num_triggers, info->maintained_effects[i].spell->had_triggers, info->maintained_effects[i].spell->cancel_after_all_triggers,
+ info->maintained_effects[i].spell->damage_remaining, info->maintained_effects[i].spell->effect_flags.export_u64(), info->maintained_effects[i].spell->num_triggers, info->maintained_effects[i].spell->had_triggers, info->maintained_effects[i].spell->cancel_after_all_triggers,
info->maintained_effects[i].spell->crit, info->maintained_effects[i].spell->last_spellattack_hit, info->maintained_effects[i].spell->interrupted, info->maintained_effects[i].spell->resisted, info->maintained_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->maintained_effects[i].spell).c_str()).c_str(), info->maintained_effects[i].spell->initial_caster_level);
SaveCustomSpellFields(info->maintained_effects[i].spell);
diff --git a/source/WorldServer/WorldDatabase.cpp b/source/WorldServer/WorldDatabase.cpp
index 7061bc2..84f7c08 100644
--- a/source/WorldServer/WorldDatabase.cpp
+++ b/source/WorldServer/WorldDatabase.cpp
@@ -8270,7 +8270,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
int8 custom_spell = result.GetInt32Str("custom_spell");
int32 damage_remaining = result.GetInt32Str("damage_remaining");
- int32 effect_bitmask = result.GetInt32Str("effect_bitmask");
+ int64 effect_bitmask = result.GetInt64Str("effect_bitmask");
int16 num_triggers = result.GetInt32Str("num_triggers");
int8 had_triggers = result.GetInt32Str("had_triggers");
int8 cancel_after_triggers = result.GetInt32Str("cancel_after_triggers");
@@ -8394,7 +8394,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
{
lua_spell->crit = crit;
lua_spell->damage_remaining = damage_remaining;
- lua_spell->effect_bitmask = effect_bitmask;
+ lua_spell->effect_flags.import_u64(effect_bitmask);
lua_spell->had_dmg_remaining = (damage_remaining>0) ? true : false;
lua_spell->had_triggers = had_triggers;
lua_spell->initial_caster_char_id = caster_char_id;