#include "precompile.h" #include "ability.h" #include "buff.h" #include "creature.h" #include "mt/Equip.h" #include "mt/Buff.h" struct AttrAdditionPtr { struct AttrAddition* data; AttrAdditionPtr(AttrAddition* data) { this->data = data; }; }; struct AttrAddition { list_head entry; int attr_id; float value; std::shared_ptr ptr; AttrAddition(int attr_id, float value) { this->attr_id = attr_id; this->value = value; INIT_LIST_HEAD(&entry); ptr = std::make_shared(this); } }; struct AttrRuducePtr { struct AttrRuduce* data; AttrRuducePtr(AttrRuduce* data) { this->data = data; }; }; struct AttrRuduce { list_head entry; int attr_id; float value; std::shared_ptr ptr; AttrRuduce(int attr_id, float value) { this->attr_id = attr_id; this->value = value; INIT_LIST_HEAD(&entry); ptr = std::make_shared(this); } }; Ability::Ability(CreatureWeakPtr owner) { for (auto& tuple : attr_add_) { std::get<0>(tuple) = .0f; INIT_LIST_HEAD(&std::get<1>(tuple)); } for (auto& tuple : attr_dec_) { std::get<0>(tuple) = .0f; INIT_LIST_HEAD(&std::get<1>(tuple)); } for (auto& tuple : vattr_add_) { std::get<0>(tuple) = .0f; INIT_LIST_HEAD(&std::get<1>(tuple)); } for (auto& tuple : vattr_dec_) { std::get<0>(tuple) = .0f; INIT_LIST_HEAD(&std::get<1>(tuple)); } Clear(); } float Ability::GetAttrAbs(int attr_id) { float attr_abs_val = GetBuffAttrAbs(attr_id); if (attr_id == kHAT_Atk || attr_id == kHAT_Def) { if (owner_.Get()) { } } return attr_abs_val; } float Ability::GetAttrRate(int attr_id) { float attr_rate_val = GetBuffAttrRate(attr_id) / 100.0f; return attr_rate_val; } float Ability::GetBuffAttrAbs(int attr_id) { if (IsValidHumanAttr(attr_id)) { return buff_attr_abs_[attr_id]; } return 0; } float Ability::GetBuffAttrRate(int attr_id) { if (IsValidHumanAttr(attr_id)) { return buff_attr_rate_[attr_id]; } return 0; } void Ability::Clear() { buff_attr_abs_ = {}; buff_attr_rate_ = {}; buff_attr_flag_ = {}; for (auto& tuple : attr_add_) { std::get<0>(tuple) = 0.0f; while (!list_empty(&std::get<1>(tuple))) { AttrAddition* e = list_first_entry(&std::get<1>(tuple), AttrAddition, entry); e->ptr->data = nullptr; list_del_init(&e->entry); delete e; } } for (auto& tuple : attr_dec_) { std::get<0>(tuple) = 0.0f; while (!list_empty(&std::get<1>(tuple))) { AttrRuduce* e = list_first_entry(&std::get<1>(tuple), AttrRuduce, entry); e->ptr->data = nullptr; list_del_init(&e->entry); delete e; } } for (auto& tuple : vattr_add_) { std::get<0>(tuple) = 0.0f; while (!list_empty(&std::get<1>(tuple))) { AttrAddition* e = list_first_entry(&std::get<1>(tuple), AttrAddition, entry); e->ptr->data = nullptr; list_del_init(&e->entry); delete e; } } for (auto& tuple : vattr_dec_) { std::get<0>(tuple) = 0.0f; while (!list_empty(&std::get<1>(tuple))) { AttrRuduce* e = list_first_entry(&std::get<1>(tuple), AttrRuduce, entry); e->ptr->data = nullptr; list_del_init(&e->entry); delete e; } } } float* Ability::GetBuffAttrAbsPtr(int attr_id) { if (!IsValidHumanAttr(attr_id)) { return nullptr; } buff_attr_flag_[attr_id] = 1; return &buff_attr_abs_[attr_id]; } float* Ability::GetBuffAttrRatePtr(int attr_id) { if (!IsValidHumanAttr(attr_id)) { return nullptr; } buff_attr_flag_[attr_id] = 1; return &buff_attr_rate_[attr_id]; } void Ability::AddSpeedAddition(float rate) { speed_addition_rate_ += rate; ++speed_addition_times_; } void Ability::DelSpeedAddition(float rate) { speed_addition_rate_ -= rate; speed_addition_rate_ = std::max(0.0f, speed_addition_rate_); --speed_addition_times_; #ifdef DEBUG if (speed_addition_times_ < 0) { abort(); } #endif } float Ability::GetSpeedAddition() { return speed_addition_rate_; } int Ability::GetSpeedAdditionTimes() { return speed_addition_times_; } void Ability::AddDmgRuduce(float rate) { dmg_ruduce_rate_ += rate; ++dmg_ruduce_times_; } void Ability::DelDmgRuduce(float rate) { dmg_ruduce_rate_ -= rate; dmg_ruduce_rate_ = std::max(0.0f, dmg_ruduce_rate_); --dmg_ruduce_times_; #ifdef DEBUG if (dmg_ruduce_times_ < 0) { abort(); } #endif } float Ability::GetDmgRuduce() { return dmg_ruduce_rate_; } int Ability::GetDmgRuduceTimes() { return dmg_ruduce_times_; } void Ability::AddDmgAddition(float rate) { dmg_addition_rate_ += rate; ++dmg_addition_times_; } void Ability::DelDmgAddition(float rate) { dmg_addition_rate_ -= rate; dmg_addition_rate_ = std::max(0.0f, dmg_addition_rate_); --dmg_addition_times_; #ifdef DEBUG if (dmg_addition_times_ < 0) { abort(); } #endif } float Ability::GetDmgAddition() { return dmg_addition_rate_; } int Ability::GetDmgAdditionTimes() { return dmg_addition_times_; } void Ability::AddDefAddition(float rate) { def_addition_rate_ += rate; ++def_addition_times_; } void Ability::DelDefAddition(float rate) { def_addition_rate_ -= rate; def_addition_rate_ = std::max(0.0f, def_addition_rate_); --def_addition_times_; #ifdef DEBUG if (def_addition_times_ < 0) { abort(); } #endif } float Ability::GetDefAddition() { return def_addition_rate_; } int Ability::GetDefAdditionTimes() { return def_addition_times_; } void Ability::AddAtkAddition(float rate) { atk_addition_rate_ += rate; ++atk_addition_times_; } void Ability::DelAtkAddition(float rate) { atk_addition_rate_ -= rate; atk_addition_rate_ = std::max(0.0f, atk_addition_rate_); --atk_addition_times_; #ifdef DEBUG if (atk_addition_times_ < 0) { abort(); } #endif } float Ability::GetAtkAddition() { return atk_addition_rate_; } int Ability::GetAtkAdditionTimes() { return atk_addition_times_; } void Ability::IncImmuneTimes(int tag) { auto itr = immune_tags_.find(tag); if (itr != immune_tags_.end()) { ++itr->second; } else { immune_tags_[tag] = 1; } } void Ability::DecImmuneTimes(int tag) { auto itr = immune_tags_.find(tag); if (itr != immune_tags_.end()) { --itr->second; if (itr->second <= 0) { immune_tags_.erase(itr); } } } bool Ability::CanImmune(int tag) { return immune_tags_.find(tag) != immune_tags_.end(); } bool Ability::CanImmune(const std::set& tags) { if (!immune_tags_.empty()) { for (int tag : tags) { if (CanImmune(tag)) { return true; } } } return false; } void Ability::AddSpeedRuduce(float rate) { speed_ruduce_rate_ += rate; ++speed_ruduce_times_; } void Ability::DelSpeedRuduce(float rate) { speed_ruduce_rate_ -= rate; speed_ruduce_rate_ = std::max(0.0f, speed_ruduce_rate_); --speed_ruduce_times_; if (speed_ruduce_times_ <= 0) { speed_ruduce_rate_ = 0; } #ifdef DEBUG if (speed_ruduce_times_ < 0) { abort(); } #endif } float Ability::GetSpeedRuduce() { #ifdef DEBUG1 if (std::abs(speed_ruduce_rate_) > 0.001f && owner_.Get() && owner_.Get()->IsPlayer()) { a8::XPrintf("speed_ruduce_rate:%f speed_ruduce_times_:%d\n", { speed_ruduce_rate_, speed_ruduce_times_ }); } #endif return speed_ruduce_rate_; } int Ability::GetSpeedRuduceTimes() { return speed_ruduce_times_; } void Ability::IncDisableShotTimes() { ++disable_shot_times_; } void Ability::DecDisableShotTimes() { --disable_shot_times_; disable_shot_times_ = std::max(0, disable_shot_times_); } int Ability::GetDisableShotTimes() { return disable_shot_times_; } void Ability::IncDisableUseSkillTimes() { ++disable_useskill_times_; } void Ability::DecDisableUseSkillTimes() { --disable_useskill_times_; disable_useskill_times_ = std::max(0, disable_useskill_times_); } int Ability::GetDisableUseSkillTimes() { return disable_useskill_times_; } void Ability::SetFixedSpeed(float speed) { fixed_speed_ = speed; ++fixed_speed_times_; } void Ability::UnSetFixedSpeed() { fixed_speed_ = 0.0f; fixed_speed_times_ = 0; } int Ability::GetFixedSpeedTimes() { return fixed_speed_times_; } float Ability::GetFixedSped() { return fixed_speed_; } AttrAdditionHandle Ability::AddAttr(int attr_id, float rate) { if (IsValidHumanAttr(attr_id)) { auto p = new AttrAddition(attr_id, rate); list_add_tail(&p->entry, &std::get<1>(attr_add_[attr_id])); RecalcAttrAddition(attr_id); return p->ptr; } return AttrAdditionHandle(); } void Ability::RemoveAttrAddition(AttrAdditionHandle handle) { if (!handle.expired()) { auto p = handle.lock(); list_del_init(&p->data->entry); RecalcAttrAddition(p->data->attr_id); delete p->data; } } AttrRuduceHandle Ability::DecAttr(int attr_id, float rate) { if (IsValidHumanAttr(attr_id)) { auto p = new AttrRuduce(attr_id, rate); list_add_tail(&p->entry, &std::get<1>(attr_dec_[attr_id])); RecalcAttrRuduce(attr_id); return p->ptr; } return AttrRuduceHandle(); } void Ability::RemoveAttrRuduce(AttrRuduceHandle handle) { if (!handle.expired()) { auto p = handle.lock(); list_del_init(&p->data->entry); RecalcAttrRuduce(p->data->attr_id); delete p->data; } } void Ability::RecalcAttrAddition(int attr_id) { if (!IsValidHumanAttr(attr_id)) { return; } list_head* pos = nullptr; list_head* next = nullptr; list_head* head = &std::get<1>(attr_add_[attr_id]); float new_val = 0.0f; list_for_each_safe(pos, next, head) { AttrAddition* e = list_entry(pos, AttrAddition, entry); new_val += e->value; } std::get<0>(attr_add_[attr_id]) = new_val; } void Ability::RecalcAttrRuduce(int attr_id) { if (!IsValidHumanAttr(attr_id)) { return; } list_head* pos = nullptr; list_head* next = nullptr; list_head* head = &std::get<1>(attr_dec_[attr_id]); float new_val = 0.0f; list_for_each_safe(pos, next, head) { AttrRuduce* e = list_entry(pos, AttrRuduce, entry); new_val += e->value; } std::get<0>(attr_dec_[attr_id]) = new_val; } float Ability::GetAttrAddition(int attr_id) { if (!IsValidHumanAttr(attr_id)) { return 0.0f; } return std::get<0>(attr_add_[attr_id]); } float Ability::GetAttrRuduce(int attr_id) { if (!IsValidHumanAttr(attr_id)) { return 0.0f; } return std::get<0>(attr_dec_[attr_id]); }