990 lines
28 KiB
C++
990 lines
28 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);
|
|
}
|
|
};
|
|
|
|
struct AttrDirectPtr
|
|
{
|
|
struct AttrDirect* data;
|
|
AttrDirectPtr(AttrDirect* data) { this->data = data; };
|
|
};
|
|
|
|
struct AttrDirect
|
|
{
|
|
list_head entry;
|
|
int attr_id;
|
|
float value;
|
|
std::shared_ptr<AttrDirectPtr> ptr;
|
|
|
|
AttrDirect(int attr_id, float value)
|
|
{
|
|
this->attr_id = attr_id;
|
|
this->value = value;
|
|
INIT_LIST_HEAD(&entry);
|
|
ptr = std::make_shared<AttrDirectPtr>(this);
|
|
}
|
|
};
|
|
|
|
Ability::Ability(CreatureWeakPtr owner)
|
|
{
|
|
for (auto& tuple : attr_abs_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : attr_rate_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : attr_add_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : attr_dec_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : vattr_add_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : vattr_dec_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
INIT_LIST_HEAD(&std::get<1>(tuple));
|
|
}
|
|
for (auto& tuple : attr_direct_) {
|
|
std::get<0>(tuple) = 0.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;
|
|
}
|
|
}
|
|
for (auto& tuple : attr_direct_) {
|
|
std::get<0>(tuple) = 0.0f;
|
|
while (!list_empty(&std::get<1>(tuple))) {
|
|
AttrDirect* e = list_first_entry(&std::get<1>(tuple),
|
|
AttrDirect,
|
|
entry);
|
|
e->ptr->data = nullptr;
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
}
|
|
}
|
|
|
|
switch_times_ = {};
|
|
immune_tags_.clear();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
std::get<0>(attr_add_[attr_id]) = new_val;
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
std::get<0>(vattr_add_[attr_id - kHVAT_Begin]) = 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;
|
|
}
|
|
}
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
std::get<0>(attr_dec_[attr_id]) = new_val;
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
std::get<0>(vattr_dec_[attr_id - kHVAT_Begin]) = 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;
|
|
}
|
|
}
|
|
|
|
void Ability::GMDelBaseAttr(int type, int attr_id, int idx)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
if (type == 1) {
|
|
list_head* head = &std::get<1>(attr_abs_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
if (idx == -1 || idx == i) {
|
|
AttrAbs* e = list_entry(pos,
|
|
AttrAbs,
|
|
entry);
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
if (idx > -1) {
|
|
break;
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
RecalcAttrAbs(attr_id);
|
|
} else if (type == 2) {
|
|
list_head* head = &std::get<1>(attr_rate_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
if (idx == -1 || idx == i) {
|
|
AttrRate* e = list_entry(pos,
|
|
AttrRate,
|
|
entry);
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
if (idx > -1) {
|
|
break;
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
RecalcAttrRate(attr_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Ability::GMClearBaseAttr(int type)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Ability::GMDelGrowAttr(int type, int attr_id, int idx)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
if (type == 1) {
|
|
list_head* head = &std::get<1>(attr_add_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
if (idx == -1 || idx == i) {
|
|
AttrAddition* e = list_entry(pos,
|
|
AttrAddition,
|
|
entry);
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
if (idx > -1) {
|
|
break;
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
RecalcAttrAddition(attr_id);
|
|
} else if (type == 2) {
|
|
list_head* head = &std::get<1>(attr_dec_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
if (idx == -1 || idx == i) {
|
|
AttrRuduce* e = list_entry(pos,
|
|
AttrRuduce,
|
|
entry);
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
if (idx > -1) {
|
|
break;
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
RecalcAttrRuduce(attr_id);
|
|
}
|
|
} else if (IsValidHumanVirtualAttr(attr_id)) {
|
|
if (type == 1) {
|
|
list_head* head = &std::get<1>(vattr_add_[attr_id - kHVAT_Begin]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
if (idx == -1 || idx == i) {
|
|
AttrAddition* e = list_entry(pos,
|
|
AttrAddition,
|
|
entry);
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
if (idx > -1) {
|
|
break;
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
RecalcAttrAddition(attr_id);
|
|
} else if (type == 2) {
|
|
list_head* head = &std::get<1>(vattr_dec_[attr_id - kHVAT_Begin]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
if (idx == -1 || idx == i) {
|
|
AttrRuduce* e = list_entry(pos,
|
|
AttrRuduce,
|
|
entry);
|
|
list_del_init(&e->entry);
|
|
delete e;
|
|
if (idx > -1) {
|
|
break;
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
RecalcAttrRuduce(attr_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Ability::GMClearGrowAttr(int type)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> Ability::GMShowAttrs()
|
|
{
|
|
std::vector<std::string> strings;
|
|
{
|
|
std::vector<std::string> tmp_strings;
|
|
int attr_id = 0;
|
|
for (auto& tuple : attr_abs_) {
|
|
list_head* head = &std::get<1>(tuple);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
std::string data = a8::Format("attr_id:%d value:%f [", {attr_id, std::get<0>(tuple)});
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrAbs* e = list_entry(pos,
|
|
AttrAbs,
|
|
entry);
|
|
data += "" + a8::XValue(e->value).GetString() + ",";
|
|
++i;
|
|
}
|
|
if (i > 0) {
|
|
data += "]";
|
|
tmp_strings.push_back(data);
|
|
}
|
|
++attr_id;
|
|
}
|
|
strings.push_back("基础属性定值:");
|
|
if (tmp_strings.empty()) {
|
|
strings.push_back("无");
|
|
} else {
|
|
for (auto& str : tmp_strings) {
|
|
strings.push_back(str);
|
|
}
|
|
}
|
|
}
|
|
{
|
|
std::vector<std::string> tmp_strings;
|
|
int attr_id = 0;
|
|
for (auto& tuple : attr_rate_) {
|
|
list_head* head = &std::get<1>(tuple);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
std::string data = a8::Format("attr_id:%d value:%f [", {attr_id, std::get<0>(tuple)});
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrRate* e = list_entry(pos,
|
|
AttrRate,
|
|
entry);
|
|
data += "" + a8::XValue(e->value).GetString() + ",";
|
|
++i;
|
|
}
|
|
if (i > 0) {
|
|
data += "]";
|
|
tmp_strings.push_back(data);
|
|
}
|
|
++attr_id;
|
|
}
|
|
strings.push_back("基础属性百分比:");
|
|
if (tmp_strings.empty()) {
|
|
strings.push_back("无");
|
|
} else {
|
|
for (auto& str : tmp_strings) {
|
|
strings.push_back(str);
|
|
}
|
|
}
|
|
}
|
|
{
|
|
std::vector<std::string> tmp_strings;
|
|
int attr_id = 0;
|
|
for (auto& tuple : attr_add_) {
|
|
list_head* head = &std::get<1>(tuple);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
std::string data = a8::Format("attr_id:%d value:%f [", {attr_id, std::get<0>(tuple)});
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrAddition* e = list_entry(pos,
|
|
AttrAddition,
|
|
entry);
|
|
data += "" + a8::XValue(e->value).GetString() + ",";
|
|
++i;
|
|
}
|
|
if (i > 0) {
|
|
data += "]";
|
|
tmp_strings.push_back(data);
|
|
}
|
|
++attr_id;
|
|
}
|
|
strings.push_back("成长属性增:");
|
|
if (tmp_strings.empty()) {
|
|
strings.push_back("无");
|
|
} else {
|
|
for (auto& str : tmp_strings) {
|
|
strings.push_back(str);
|
|
}
|
|
}
|
|
}
|
|
{
|
|
std::vector<std::string> tmp_strings;
|
|
int attr_id = 0;
|
|
for (auto& tuple : vattr_add_) {
|
|
list_head* head = &std::get<1>(tuple);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
std::string data = a8::Format("attr_id:%d value:%f [", {attr_id + kHVAT_Begin,
|
|
std::get<0>(tuple)});
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrAddition* e = list_entry(pos,
|
|
AttrAddition,
|
|
entry);
|
|
data += "" + a8::XValue(e->value).GetString() + ",";
|
|
++i;
|
|
}
|
|
if (i > 0) {
|
|
data += "]";
|
|
tmp_strings.push_back(data);
|
|
}
|
|
++attr_id;
|
|
}
|
|
strings.push_back("成长属性增(虚):");
|
|
if (tmp_strings.empty()) {
|
|
strings.push_back("无");
|
|
} else {
|
|
for (auto& str : tmp_strings) {
|
|
strings.push_back(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
std::vector<std::string> tmp_strings;
|
|
int attr_id = 0;
|
|
for (auto& tuple : attr_dec_) {
|
|
list_head* head = &std::get<1>(tuple);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
std::string data = a8::Format("attr_id:%d value:%f [", {attr_id, std::get<0>(tuple)});
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrRuduce* e = list_entry(pos,
|
|
AttrRuduce,
|
|
entry);
|
|
data += "" + a8::XValue(e->value).GetString() + ",";
|
|
++i;
|
|
}
|
|
if (i > 0) {
|
|
data += "]";
|
|
tmp_strings.push_back(data);
|
|
}
|
|
++attr_id;
|
|
}
|
|
strings.push_back("成长属性减:");
|
|
if (tmp_strings.empty()) {
|
|
strings.push_back("无");
|
|
} else {
|
|
for (auto& str : tmp_strings) {
|
|
strings.push_back(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
std::vector<std::string> tmp_strings;
|
|
int attr_id = 0;
|
|
for (auto& tuple : vattr_dec_) {
|
|
list_head* head = &std::get<1>(tuple);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
std::string data = a8::Format("减 attr_id:%d value:%f [", {attr_id + kHVAT_Begin,
|
|
std::get<0>(tuple)});
|
|
int i = 0;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrRuduce* e = list_entry(pos,
|
|
AttrRuduce,
|
|
entry);
|
|
data += "" + a8::XValue(e->value).GetString() + ",";
|
|
++i;
|
|
}
|
|
if (i > 0) {
|
|
data += "]";
|
|
tmp_strings.push_back(data);
|
|
}
|
|
++attr_id;
|
|
}
|
|
strings.push_back("成长属性减(虚):");
|
|
if (tmp_strings.empty()) {
|
|
strings.push_back("无");
|
|
} else {
|
|
for (auto& str : tmp_strings) {
|
|
strings.push_back(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
return strings;
|
|
}
|
|
|
|
void Ability::IncSwitch(int type)
|
|
{
|
|
if (type >= kSwitchTimeBegin && type < kSwitchTimeEnd) {
|
|
++switch_times_[type];
|
|
} else {
|
|
abort();
|
|
}
|
|
}
|
|
|
|
void Ability::DecSwitch(int type)
|
|
{
|
|
if (type >= kSwitchTimeBegin && type < kSwitchTimeEnd) {
|
|
--switch_times_[type];
|
|
} else {
|
|
abort();
|
|
}
|
|
}
|
|
|
|
int Ability::GetSwitchTimes(int type)
|
|
{
|
|
if (type >= kSwitchTimeBegin && type < kSwitchTimeEnd) {
|
|
return switch_times_[type];
|
|
} else {
|
|
abort();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
AttrDirectHandle Ability::AddAttrDirect(int attr_id, float value)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
auto p = new AttrDirect(attr_id, value);
|
|
list_add_tail(&p->entry, &std::get<1>(attr_direct_[attr_id]));
|
|
RecalcAttrDirect(attr_id);
|
|
return p->ptr;
|
|
}
|
|
return AttrDirectHandle();
|
|
}
|
|
|
|
void Ability::RemoveAttrDirect(AttrDirectHandle handle)
|
|
{
|
|
if (!handle.expired()) {
|
|
auto p = handle.lock();
|
|
list_del_init(&p->data->entry);
|
|
RecalcAttrDirect(p->data->attr_id);
|
|
delete p->data;
|
|
}
|
|
}
|
|
|
|
float Ability::GetAttrDirect(int attr_id)
|
|
{
|
|
if (IsValidHumanAttr(attr_id)) {
|
|
return std::get<0>(attr_direct_[attr_id]);
|
|
} else {
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
void Ability::RecalcAttrDirect(int attr_id)
|
|
{
|
|
list_head* head = &std::get<1>(attr_direct_[attr_id]);
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
float new_val = 0.0f;
|
|
list_for_each_safe(pos, next, head) {
|
|
AttrDirect* e = list_entry(pos,
|
|
AttrDirect,
|
|
entry);
|
|
new_val = std::max(e->value, new_val);
|
|
}
|
|
std::get<0>(attr_direct_[attr_id]) = new_val;
|
|
}
|