#include "precompile.h" #include "creature.h" #include "metamgr.h" #include "room.h" #include "skill.h" bool Creature::HasBuffEffect(int buff_effect_id) { return GetBuffByEffectId(buff_effect_id) != nullptr; } Buff* Creature::GetBuffByEffectId(int effect_id) { return IsValidBuffEffect(effect_id) ? buff_effect_[effect_id] : nullptr; } Buff* Creature::GetBuffById(int buff_id) { for (Buff& buff : buff_list_) { if (buff.meta->i->buff_id() == buff_id) { return &buff; } } return nullptr; } void Creature::AddBuff(Creature* caster, MetaData::Buff* buff_meta, int skill_lv, MetaData::Skill* buff_skill_meta) { if (GetBuffById(buff_meta->i->buff_id())) { return; } if (IsImmuneBuffEffect(buff_meta->i->buff_effect())) { return; } if (!buff_meta->EffectCanStack()) { Buff* buff = GetBuffByEffectId(buff_meta->i->buff_effect()); if (buff) { RemoveBuffById(buff->meta->i->buff_id()); } } if (buff_meta->i->buff_effect() == kBET_OnceChgAttr) { if ((int)buff_meta->param1== kHAT_Hp) { if ((int)buff_meta->param2 == 1) { //绝对值 ability.hp += buff_meta->param3; ability.hp = std::min(ability.max_hp, ability.hp); } else if ((int)buff_meta->param2 == 2) { //百分比 ability.hp *= 1 + buff_meta->param3; ability.hp = std::min(ability.max_hp, ability.hp); } SyncAroundPlayers(__FILE__, __LINE__, __func__); } } Buff* buff = &a8::FastAppend(buff_list_); buff->skill_lv = skill_lv; buff->owner = this; buff->meta = buff_meta; 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; { room->xtimer.AddDeadLineTimerAndAttach ( buff_meta->i->duration_time() * SERVER_FRAME_RATE, a8::XParams() .SetSender(this) .SetParam1(buff_meta->i->buff_id()), [] (const a8::XParams& param) { Creature* c = (Creature*)param.sender.GetUserData(); c->RemoveBuffById(param.param1); }, &buff->xtimer_attacher.timer_list_ ); } AddBuffPostProc(caster, buff); #ifdef DEBUG SendDebugMsg(a8::Format("添加buff_id:%d buff_effect:%d", { buff_meta->i->buff_id(), buff_meta->i->buff_effect() })); #endif } bool Creature::IsImmuneBuffEffect(int buff_effect) { for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { if (itr->meta->IsImmuneBuffEffect(buff_effect)) { return true; } } return false; } void Creature::MustBeAddBuff(Creature* caster, int buff_id) { MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); if (!buff_meta) { abort(); } AddBuff(caster, buff_meta, 1); } void Creature::RemoveBuffById(int buff_id) { for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { const 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; } OnBuffRemove(buff); buff_list_.erase(itr); break; } } RecalcBuffAttr(); #ifdef DEBUG SendDebugMsg(a8::Format("移除buff_id:%d", { buff_id })); #endif } void Creature::SendDebugMsg(const std::string& debug_msg) { } void Creature::AddBuffPostProc(Creature* caster, Buff* buff) { } void Creature::RecalcBuffAttr() { buff_attr_abs_ = {}; buff_attr_rate_ = {}; for (auto& buff : buff_list_) { if (buff.meta->i->buff_effect() == kBET_ChgAttr || buff.meta->i->buff_effect() == kBET_Car) { int attr_type = (int)buff.meta->param1; int calc_type = (int)buff.meta->param2; if (IsValidHumanAttr(attr_type)) { if (calc_type == 1) { buff_attr_abs_[attr_type] += buff.meta->param3; } else if (calc_type == 2) { buff_attr_rate_[attr_type] += buff.meta->param3; } } } } } void Creature::OnBuffRemove(const Buff& buff) { } void Creature::RemoveBuffByEffectId(int buff_effect_id) { Buff* buff = GetBuffByEffectId(buff_effect_id); if (buff) { RemoveBuffById(buff->meta->i->buff_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; } OnBuffRemove(*itr); } buff_list_.clear(); buff_effect_ = {}; buff_attr_abs_ = {}; buff_attr_rate_ = {}; RecalcBuffAttr(); } float Creature::GetBuffAttrAbs(int attr_type) { if (IsValidHumanAttr(attr_type)) { return buff_attr_abs_[attr_type]; } return 0; } float Creature::GetBuffAttrRate(int attr_type) { if (IsValidHumanAttr(attr_type)) { return buff_attr_rate_[attr_type]; } return 0; } void Creature::FillBuffList(::google::protobuf::RepeatedPtrField<::cs::MFBuff>* pb_buff_list) { for (auto& itr : buff_list_) { auto buff = pb_buff_list->Add(); itr.FillMFBuff(buff); } } void Creature::AddPassiveSkill(MetaData::Skill* skill_meta) { if (!HasPassiveSkill(skill_meta)) { xtimer_list* tmp_timer = room->xtimer.AddRepeatTimerAndAttach ( SERVER_FRAME_RATE * skill_meta->i->skill_cd(), a8::XParams() .SetSender(this) .SetParam1(skill_meta), [] (const a8::XParams& param) { Creature* c = (Creature*)param.sender.GetUserData(); MetaData::Skill* skill_meta = (MetaData::Skill*)param.param1.GetUserData(); c->ClearPassiveSkillBuff(skill_meta); c->AddPassiveSkillBuff(skill_meta); }, &xtimer_attacher.timer_list_); passive_skill_metas_[skill_meta] = tmp_timer; AddPassiveSkillBuff(skill_meta); if (skill_meta->i->skill_cd() > 10000) { //永久被动被动技能 AddPassiveSkillBuff(skill_meta); } } } void Creature::RemovePassiveSkill(MetaData::Skill* skill_meta) { auto itr = passive_skill_metas_.find(skill_meta); if (itr != passive_skill_metas_.end()) { ClearPassiveSkillBuff(skill_meta); room->xtimer.DeleteTimer(itr->second); passive_skill_metas_.erase(itr); } } void Creature::ClearPassiveSkill() { std::vector del_skills; del_skills.reserve(passive_skill_metas_.size()); for (auto& pair : passive_skill_metas_) { del_skills.push_back(pair.first); } for (MetaData::Skill* skill_meta : del_skills) { RemovePassiveSkill(skill_meta); } } bool Creature::HasPassiveSkill(MetaData::Skill* skill_meta) { return passive_skill_metas_.find(skill_meta) != passive_skill_metas_.end(); } void Creature::ClearPassiveSkillBuff(MetaData::Skill* skill_meta) { for (int buff_id : skill_meta->buff_list) { Buff* buff = GetBuffById(buff_id); if (buff && (buff->meta->i->buff_target() == kBuffTargetSelf || buff->meta->i->buff_target() == kBuffTargetFriendly)) { RemoveBuffById(buff_id); } } } void Creature::AddPassiveSkillBuff(MetaData::Skill* skill_meta) { if (!skill_meta) { return; } MetaData::Skill* old_curr_skill = skill_meta_; int old_skill_target_id_ = skill_target_id_; a8::Vec2 old_skill_target_pos_ = skill_target_pos_; skill_meta_ = skill_meta; skill_target_id_ = GetEntityUniId(); skill_target_pos_ = GetPos(); std::set target_list; SelectSkillTargets(GetPos(), target_list); TriggerBuff(target_list, kBTT_UseSkill); skill_meta_= old_curr_skill; skill_target_id_ = old_skill_target_id_; skill_target_pos_ = old_skill_target_pos_; } void Creature::SelectSkillTargets(const a8::Vec2& target_pos, std::set& target_list) { } void Creature::TriggerBuff(std::set& target_list, BuffTriggerType_e trigger_type) { for (Entity* entity : target_list) { TriggerOneObjectBuff(entity, trigger_type); } } void Creature::TriggerOneObjectBuff(Entity* target, BuffTriggerType_e trigger_type) { } Skill* Creature::GetSkill(int skill_id) { auto itr = skill_hash_.find(skill_id); return itr != skill_hash_.end() ? itr->second : nullptr; } bool Creature::CanUseSkill(int skill_id) { Skill* skill = GetSkill(skill_id); if (!skill) { return false; } return skill->GetLeftTime() <= 0; } void Creature::DoSkill(int skill_id, int target_id, const a8::Vec2& target_pos) { DoSkillPreProc(skill_id, target_id, target_pos); skill_target_id_ = target_id; skill_target_pos_ = target_pos; if (CanUseSkill(skill_id)) { ResetSkill(); playing_skill = true; CurrentSkill()->last_use_frameno = room->GetFrameNo(); if (skill_meta_->i->skill_target() == kST_Self ) { skill_target_id_ = GetEntityUniId(); } Entity* entity = room->GetEntityByUniId(skill_target_id_); if (entity && entity->IsEntityType(ET_Player)) { Creature* c = (Creature*)entity; std::set target_list; skill_target_pos_ = c->GetPos(); SelectSkillTargets(c->GetPos(), target_list); TriggerBuff(target_list, kBTT_UseSkill); if (!skill_meta_->phases.empty() && skill_meta_->phases[0].time_offset <= 0) { UpdateSkill(); } } else { playing_skill = false; } if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } DoSkillPostProc(true, skill_id, target_id, target_pos); } else { DoSkillPostProc(false, skill_id, target_id, target_pos); } } void Creature::DoSkillPreProc(int skill_id, int target_id, const a8::Vec2& target_pos) { } void Creature::DoSkillPostProc(bool used, int skill_id, int target_id, const a8::Vec2& target_pos) { } void Creature::ResetSkill() { #if 0 use_skill = false; #endif curr_skill_phase = 0; skill_dir = a8::Vec2(); skill_target_pos_ = a8::Vec2(); skill_param1 = 0.0f; playing_skill = false; } void Creature::UpdateSkill() { if (skill_meta_) { if (curr_skill_phase < skill_meta_->phases.size()) { MetaData::SkillPhase* phase = &skill_meta_->phases[curr_skill_phase]; if (phase->time_offset >= CurrentSkill()->GetLeftTime()) { ProcSkillPhase(phase); ++curr_skill_phase; } } else { playing_skill = false; } } } void Creature::ProcSkillPhase(MetaData::SkillPhase* phase) { switch (phase->func_id) { case kSkill_TurnOver: { } break; case kSkill_JumpTo: { } break; case kSkill_Shot: { Entity* entity = room->GetEntityByUniId(skill_target_id_); MetaData::Equip* weapon_meta = MetaMgr::Instance()->GetEquip(phase->param1.GetInt()); if (weapon_meta && entity) { float target_distance = entity->GetPos().Distance(GetPos()); MetaData::EquipUpgrade* weapon_upgrade_meta = MetaMgr::Instance()->GetEquipUpgrade(weapon_meta->i->id()); MetaData::Equip* bullet_meta = MetaMgr::Instance()->GetEquip(weapon_meta->i->use_bullet()); if (bullet_meta && target_distance > 0.00001f) { a8::Vec2 old_attack_dir = attack_dir; attack_dir = entity->GetPos() - GetPos(); attack_dir.Normalize(); #if 0 InternalShot ( this, weapon_meta, weapon_upgrade_meta, bullet_meta, 1, skill_meta_->i->skill_id(), target_distance, false); #endif attack_dir = old_attack_dir; } } } break; case kSkill_Pull: { } break; default: { } break; } } MetaData::SkillPhase* Creature::GetCurrSkillPhase() { return curr_skill_phase < skill_meta_->phases.size() ? &skill_meta_->phases[curr_skill_phase] : nullptr; } Skill* Creature::CurrentSkill() { return nullptr; }