diff --git a/server/gameserver/buff.cc b/server/gameserver/buff.cc index cd15c2f..548806c 100644 --- a/server/gameserver/buff.cc +++ b/server/gameserver/buff.cc @@ -9,6 +9,16 @@ #include "incubator.h" #include "car.h" +Buff::Buff() +{ + +} + +void Buff::Initialize() +{ + +} + int Buff::GetLeftTime() { int passed_ms = (owner->room->GetFrameNo() - add_frameno) * FRAME_RATE_MS; diff --git a/server/gameserver/buff.h b/server/gameserver/buff.h index fdbcc9d..33ff2bd 100644 --- a/server/gameserver/buff.h +++ b/server/gameserver/buff.h @@ -26,7 +26,11 @@ class Buff a8::XTimerAttacher xtimer_attacher; long long add_frameno = 0; int skill_lv = 0; + list_head effect_entry; + list_head depend_entry; + Buff(); + void Initialize(); int GetLeftTime(); int GetLastingTime(); bool NeedSync(Human* hum); diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index 484ca22..23b9f8a 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -133,7 +133,16 @@ bool Creature::HasBuffEffect(int buff_effect_id) Buff* Creature::GetBuffByEffectId(int effect_id) { - return IsValidBuffEffect(effect_id) ? buff_effect_[effect_id] : nullptr; + if (!IsValidBuffEffect(effect_id)) { + return nullptr; + } + list_head* list = &buff_effect_[effect_id]; + if (list_empty(list)) { + return nullptr; + } else { + Buff* buff = list_first_entry(list, Buff, effect_entry); + return buff; + } } Buff* Creature::GetBuffById(int buff_id) @@ -159,6 +168,9 @@ void Creature::AddBuff(Creature* caster, if (IsImmuneBuffEffect(buff_meta->i->buff_effect())) { return; } + if (buff_meta->i->depend_effect() != 0 && !HasBuffEffect(buff_meta->i->depend_effect())) { + return; + } if (!buff_meta->EffectCanStack()) { Buff* buff = GetBuffByEffectId(buff_meta->i->buff_effect()); if (buff) { @@ -186,7 +198,14 @@ void Creature::AddBuff(Creature* caster, buff->skill_meta = buff_skill_meta; buff->add_frameno = room->GetFrameNo(); buff->xtimer_attacher.xtimer = &room->xtimer; - buff_effect_[buff->meta->i->buff_effect()] = buff; + list_add_tail(&buff_effect_[buff->meta->i->buff_effect()], &buff->effect_entry); + if (buff->meta->i->depend_effect() != 0 && + IsValidBuffEffect(buff->meta->i->depend_effect())) { + list_add_tail(&depend_effect_[buff->meta->i->depend_effect()], &buff->depend_entry); + } else { + INIT_LIST_HEAD(&buff->depend_entry); + } + buff->Initialize(); { room->xtimer.AddDeadLineTimerAndAttach ( @@ -207,6 +226,14 @@ void Creature::AddBuff(Creature* caster, if (!buff->meta->i->only_server()) { room->frame_event.AddBuff(GetWeakPtrRef(), buff); } + if (!buff->meta->child_buff_list.empty()) { + for (int child_buff_id : buff->meta->child_buff_list) { + MetaData::Buff* child_buff_meta = MetaMgr::Instance()->GetBuff(child_buff_id); + if (child_buff_meta) { + AddBuff(caster, child_buff_meta, skill_lv, buff_skill_meta); + } + } + } #ifdef DEBUG SendDebugMsg(a8::Format("添加buff_id:%d buff_effect:%d", { @@ -249,8 +276,9 @@ void Creature::RemoveBuffById(int buff_id) for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { Buff& buff = *itr; if (buff.meta->i->buff_id() == buff_id) { - if (buff_effect_[buff.meta->i->buff_effect()] == &(*itr)) { - buff_effect_[buff.meta->i->buff_effect()] = nullptr; + list_del_init(&buff.effect_entry); + if (!list_empty(&buff.depend_entry)) { + list_del_init(&buff.depend_entry); } removed_buffs.push_back(buff.meta); OnBuffRemove(buff); @@ -279,6 +307,18 @@ void Creature::RemoveBuffById(int buff_id) break; } } + for (int child_buff_id : buff_meta->child_buff_list) { + RemoveBuffById(child_buff_id); + } + if (!HasBuffEffect(buff_meta->i->buff_effect()) && + !list_empty(&depend_effect_[buff_meta->i->buff_effect()])) { + struct list_head work_list; + list_replace_init(&depend_effect_[buff_meta->i->buff_effect()], &work_list); + while (!list_empty(&work_list)) { + Buff* buff = list_first_entry(&work_list, Buff, depend_entry); + RemoveBuffById(buff->meta->i->buff_id()); + } + } } RecalcBuffAttr(); #ifdef DEBUG @@ -337,9 +377,7 @@ void Creature::RemoveBuffByEffectId(int buff_effect_id) void Creature::ClearBuffList() { for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { - if (buff_effect_[itr->meta->i->buff_effect()] == &(*itr)) { - buff_effect_[itr->meta->i->buff_effect()] = nullptr; - } + list_del_init(&itr->effect_entry); OnBuffRemove(*itr); } buff_list_.clear(); @@ -945,6 +983,12 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) void Creature::Initialize() { MoveableEntity::Initialize(); + for (auto& node : buff_effect_) { + INIT_LIST_HEAD(&node); + } + for (auto& node : depend_effect_) { + INIT_LIST_HEAD(&node); + } } void Creature::SetMoveDir(const a8::Vec2& move_dir) diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index fc9328d..ee62f73 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -213,7 +213,8 @@ private: CreatureWeakPtrChunk weak_ptr_chunk_; std::array buff_attr_abs_ = {}; std::array buff_attr_rate_ = {}; - std::array buff_effect_ = {}; + std::array buff_effect_ = {}; + std::array depend_effect_ = {}; std::list buff_list_; std::list> slave_heros_; std::list> slave_things_; diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 77ac27b..3e403f2 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -719,6 +719,13 @@ namespace MetaData int_param2 = a8::XValue(i->buff_param2()); int_param3 = a8::XValue(i->buff_param3()); int_param4 = a8::XValue(i->buff_param4()); + { + std::vector strings; + a8::Split(i->child_buff(), strings, '|'); + for (auto& str : strings) { + child_buff_list.push_back(a8::XValue(str)); + } + } { std::vector strings; a8::Split(i->immune_buffeffect_list(), strings, '|'); diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index eeb0e23..e15a8e7 100755 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -204,6 +204,8 @@ namespace MetaData std::vector>> post_remove_action; std::set immune_buffeffect; std::vector> hero_infos; + + std::vector child_buff_list; }; struct SkillPhase diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index db9faa6..38f0004 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -236,6 +236,8 @@ message Buff optional string post_remove_action = 13; optional int32 only_server = 14; optional int32 only_self = 15; + optional int32 depend_effect = 16; + optional string child_buff = 17; } message Drop