703 lines
16 KiB
C++
703 lines
16 KiB
C++
#include "precompile.h"
|
|
|
|
#include "ability.h"
|
|
#include "buff.h"
|
|
#include "creature.h"
|
|
|
|
#include "mt/Equip.h"
|
|
#include "mt/Buff.h"
|
|
|
|
struct AttrAbsPtr
|
|
{
|
|
struct AttrAbs* data;
|
|
AttrAbsPtr(AttrAbs* data) { this->data = data; };
|
|
};
|
|
|
|
struct AttrAbs
|
|
{
|
|
list_head entry;
|
|
int attr_id;
|
|
float value;
|
|
std::shared_ptr<AttrAbsPtr> ptr;
|
|
|
|
AttrAbs(int attr_id, float value)
|
|
{
|
|
this->attr_id = attr_id;
|
|
this->value = value;
|
|
INIT_LIST_HEAD(&entry);
|
|
ptr = std::make_shared<AttrAbsPtr>(this);
|
|
}
|
|
|
|
};
|
|
|
|
struct AttrRatePtr
|
|
{
|
|
struct AttrRate* data;
|
|
AttrRatePtr(AttrRate* data) { this->data = data; };
|
|
};
|
|
|
|
struct AttrRate
|
|
{
|
|
list_head entry;
|
|
int attr_id;
|
|
float value;
|
|
std::shared_ptr<AttrRatePtr> ptr;
|
|
|
|
AttrRate(int attr_id, float value)
|
|
{
|
|
this->attr_id = attr_id;
|
|
this->value = value;
|
|
INIT_LIST_HEAD(&entry);
|
|
ptr = std::make_shared<AttrRatePtr>(this);
|
|
}
|
|
};
|
|
|
|
struct AttrAdditionPtr
|
|
{
|
|
struct AttrAddition* data;
|
|
AttrAdditionPtr(AttrAddition* data) { this->data = data; };
|
|
};
|
|
|
|
struct AttrAddition
|
|
{
|
|
list_head entry;
|
|
int attr_id;
|
|
float value;
|
|
std::shared_ptr<AttrAdditionPtr> ptr;
|
|
|
|
AttrAddition(int attr_id, float value)
|
|
{
|
|
this->attr_id = attr_id;
|
|
this->value = value;
|
|
INIT_LIST_HEAD(&entry);
|
|
ptr = std::make_shared<AttrAdditionPtr>(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<AttrRuducePtr> ptr;
|
|
|
|
AttrRuduce(int attr_id, float value)
|
|
{
|
|
this->attr_id = attr_id;
|
|
this->value = value;
|
|
INIT_LIST_HEAD(&entry);
|
|
ptr = std::make_shared<AttrRuducePtr>(this);
|
|
}
|
|
};
|
|
|
|
Ability::Ability(CreatureWeakPtr owner)
|
|
{
|
|
for (auto& tuple : attr_abs_) {
|
|
std::get<0>(tuple) = .0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : attr_rate_) {
|
|
std::get<0>(tuple) = .0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
|
|
void Ability::Clear()
|
|
{
|
|
|
|
for (auto& tuple : attr_abs_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
while (!list_empty(&std::get<1>(tuple))) {
|
|
AttrAbs* e = list_first_entry(&std::get<1>(tuple),
|
|
AttrAbs,
|
|
entry);
|
|
e->ptr->data = nullptr;
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
}
|
|
}
|
|
for (auto& tuple : attr_rate_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
while (!list_empty(&std::get<1>(tuple))) {
|
|
AttrRate* e = list_first_entry(&std::get<1>(tuple),
|
|
AttrRate,
|
|
entry);
|
|
e->ptr->data = nullptr;
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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<int>& 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_;
|
|
}
|
|
|
|
AttrAbsHandle Ability::AddAttrAbs(int attr_id, float value)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
auto p = new AttrAbs(attr_id, value);
|
|
list_add_tail(&p->entry, &std::get<1>(attr_abs_[attr_id]));
|
|
RecalcAttrAbs(attr_id);
|
|
return p->ptr;
|
|
}
|
|
return AttrAbsHandle();
|
|
}
|
|
|
|
void Ability::RemoveAttrAbs(AttrAbsHandle handle)
|
|
{
|
|
if (!handle.expired()) {
|
|
auto p = handle.lock();
|
|
list_del_init(&p->data->entry);
|
|
RecalcAttrAbs(p->data->attr_id);
|
|
delete p->data;
|
|
}
|
|
}
|
|
|
|
AttrRateHandle Ability::AddAttrRate(int attr_id, float value)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
auto p = new AttrRate(attr_id, value);
|
|
list_add_tail(&p->entry, &std::get<1>(attr_rate_[attr_id]));
|
|
RecalcAttrRate(attr_id);
|
|
return p->ptr;
|
|
}
|
|
return AttrRateHandle();
|
|
}
|
|
|
|
void Ability::RemoveAttrRate(AttrRateHandle handle)
|
|
{
|
|
if (!handle.expired()) {
|
|
auto p = handle.lock();
|
|
list_del_init(&p->data->entry);
|
|
RecalcAttrRate(p->data->attr_id);
|
|
delete p->data;
|
|
}
|
|
}
|
|
|
|
void Ability::RecalcAttrAbs(int attr_id)
|
|
{
|
|
list_head* head = &std::get<1>(attr_abs_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
float new_val = 0.0f;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrAbs* e = list_entry(pos,
|
|
AttrAbs,
|
|
entry);
|
|
new_val += e->value;
|
|
}
|
|
std::get<0>(attr_abs_[attr_id]) = new_val;
|
|
}
|
|
|
|
void Ability::RecalcAttrRate(int attr_id)
|
|
{
|
|
list_head* head = &std::get<1>(attr_rate_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
float new_val = 0.0f;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrRate* e = list_entry(pos,
|
|
AttrRate,
|
|
entry);
|
|
new_val += e->value;
|
|
}
|
|
std::get<0>(attr_rate_[attr_id]) = new_val;
|
|
}
|
|
|
|
float Ability::GetAttrAbs(int attr_id)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
return std::get<0>(attr_abs_[attr_id]);
|
|
} else {
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
float Ability::GetAttrRate(int attr_id)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
return std::get<0>(attr_rate_[attr_id]);
|
|
} else {
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
AttrAdditionHandle Ability::AddAttrAddition(int attr_id, float rate)
|
|
{
|
|
if (IsValidHumanAttr(attr_id) ||
|
|
IsValidHumanVirtualAttr(attr_id)) {
|
|
auto p = new AttrAddition(attr_id, rate);
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
list_add_tail(&p->entry, &std::get<1>(attr_add_[attr_id]));
|
|
} else {
|
|
list_add_tail(&p->entry, &std::get<1>(vattr_add_[attr_id - kHVAT_Begin]));
|
|
}
|
|
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::AddAttrRuduce(int attr_id, float rate)
|
|
{
|
|
if (IsValidHumanAttr(attr_id) ||
|
|
IsValidHumanVirtualAttr(attr_id)) {
|
|
auto p = new AttrRuduce(attr_id, rate);
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
list_add_tail(&p->entry, &std::get<1>(attr_dec_[attr_id]));
|
|
} else {
|
|
list_add_tail(&p->entry, &std::get<1>(vattr_dec_[attr_id - kHVAT_Begin]));
|
|
}
|
|
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)
|
|
{
|
|
list_head* head = nullptr;
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
head = &std::get<1>(attr_add_[attr_id]);
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
head = &std::get<1>(vattr_add_[attr_id - kHVAT_Begin]);
|
|
} else {
|
|
return;
|
|
}
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
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)
|
|
{
|
|
list_head* head = nullptr;
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
head = &std::get<1>(attr_dec_[attr_id]);
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
head = &std::get<1>(vattr_dec_[attr_id - kHVAT_Begin]);
|
|
} else {
|
|
return;
|
|
}
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
bool inited = false;
|
|
float new_val = 0.0f;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrRuduce* e = list_entry(pos,
|
|
AttrRuduce,
|
|
entry);
|
|
switch (attr_id) {
|
|
case kHAT_Speed:
|
|
{
|
|
new_val = std::max(new_val, e->value);
|
|
}
|
|
break;
|
|
case kHVAT_Dmg:
|
|
{
|
|
if (inited) {
|
|
new_val *= 1.0f - e->value;
|
|
} else {
|
|
new_val = 1.0f - e->value;
|
|
inited = true;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
new_val += e->value;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
std::get<0>(attr_dec_[attr_id]) = new_val;
|
|
}
|
|
|
|
float Ability::GetAttrAddition(int attr_id)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
return std::get<0>(attr_add_[attr_id]);
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
return std::get<0>(vattr_add_[attr_id - kHVAT_Begin]);
|
|
} else {
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
float Ability::GetAttrRuduce(int attr_id)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
return std::get<0>(attr_dec_[attr_id]);
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
return std::get<0>(vattr_dec_[attr_id - kHVAT_Begin]);
|
|
} else {
|
|
return 0.0f;
|
|
}
|
|
}
|