game2005/server/gameserver/creature.cc
aozhiwei ba5229b31e 1
2021-03-18 18:50:08 +08:00

468 lines
13 KiB
C++

#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<MetaData::Skill*> 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<Entity*> 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<Entity*>& target_list)
{
}
void Creature::TriggerBuff(std::set<Entity*>& 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<Entity*> 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;
}