diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index b1d8170b..b55e2969 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -809,54 +809,84 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) break; case kBET_DelayAddBuff: { - if (caster->GetEntityType() == ET_Player) { + if (caster) { + SkillCasterState* caster_state = new SkillCasterState; + caster->FillSkillCasterState(caster_state); room->xtimer.AddDeadLineTimerAndAttach - ( - SERVER_FRAME_RATE * buff->meta->param1, - a8::XParams() - .SetSender(this) - .SetParam1(caster) - .SetParam2(buff->meta->param2) - .SetParam3(((Creature*)caster)->CurrentSkill()->meta), - [] (const a8::XParams& param) - { - Human* hum = (Human*)param.sender.GetUserData(); - Human* caster = (Human*)param.param1.GetUserData(); - int buff_id = param.param2; - MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData(); - MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); - if (buff_meta && skill == caster->CurrentSkill()->meta && caster) { - hum->AddBuff(caster, buff_meta, 1, skill); - } - }, - &buff->xtimer_attacher.timer_list_); + ( + SERVER_FRAME_RATE * buff->meta->param1, + a8::XParams() + .SetSender(this) + .SetParam1(caster_state) + .SetParam2(buff->meta->param2) + .SetParam3(((Creature*)caster)->CurrentSkill()->meta), + [] (const a8::XParams& param) + { + Creature* receiver = (Creature*)param.sender.GetUserData(); + SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData(); + if (caster_state->caster.Get()) { + int buff_id = param.param2; + MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData(); + MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); + if (buff_meta && + caster_state->caster.Get()->CurrentSkill() && + skill == caster_state->caster.Get()->CurrentSkill()->meta) { + SkillCasterState old_caster_state; + caster_state->caster.Get()->FillSkillCasterState(&old_caster_state); + caster_state->caster.Get()->RecoverSkillCasterState(caster_state); + receiver->AddBuff(caster_state->caster.Get(), buff_meta, 1, skill); + caster_state->caster.Get()->RecoverSkillCasterState(&old_caster_state); + } + } + }, + &buff->xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData(); + delete caster_state; + }); } } break; case kBET_IntervalAddBuff: { - room->xtimer.AddRepeatTimerAndAttach - ( - FRAME_RATE_MS / buff->meta->param1, - a8::XParams() - .SetSender(this) - .SetParam1(caster) - .SetParam2(buff->meta) - .SetParam3(((Creature*)caster)->CurrentSkill()->meta), - [] (const a8::XParams& param) - { - Human* hum = (Human*)param.sender.GetUserData(); - Human* caster = (Human*)param.param1.GetUserData(); - MetaData::Buff* mother_buff_meta = (MetaData::Buff*)param.param2.GetUserData(); - MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData(); - for (int buff_id : mother_buff_meta->param2_int_list) { - MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); - if (buff_meta && skill == caster->CurrentSkill()->meta && caster) { - hum->AddBuff(caster, buff_meta, 1, skill); + if (caster) { + SkillCasterState* caster_state = new SkillCasterState; + caster->FillSkillCasterState(caster_state); + room->xtimer.AddRepeatTimerAndAttach + ( + buff->meta->param1 / FRAME_RATE_MS, + a8::XParams() + .SetSender(this) + .SetParam1(caster_state) + .SetParam2(buff->meta) + .SetParam3(((Creature*)caster)->CurrentSkill()->meta), + [] (const a8::XParams& param) + { + Creature* receiver = (Creature*)param.sender.GetUserData(); + SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData(); + if (caster_state->caster.Get()) { + int buff_id = param.param2; + MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData(); + MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); + if (buff_meta && + caster_state->caster.Get()->CurrentSkill() && + skill == caster_state->caster.Get()->CurrentSkill()->meta) { + SkillCasterState old_caster_state; + caster_state->caster.Get()->FillSkillCasterState(&old_caster_state); + caster_state->caster.Get()->RecoverSkillCasterState(caster_state); + receiver->AddBuff(caster_state->caster.Get(), buff_meta, 1, skill); + caster_state->caster.Get()->RecoverSkillCasterState(&old_caster_state); + } } - } - }, - &buff->xtimer_attacher.timer_list_); + }, + &buff->xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData(); + delete caster_state; + }); + } } break; case kBET_SummonHero: @@ -1399,3 +1429,22 @@ bool Creature::CollisonDetection() } return false; } + +void Creature::FillSkillCasterState(SkillCasterState* caster_state) +{ + caster_state->caster.Attach(this); + caster_state->caster_pos = GetPos(); + caster_state->caster_skill_id = CurrentSkill() ? CurrentSkill()->meta->i->skill_id() : 0; + caster_state->caster_skill_target_id = skill_target_id_; + caster_state->caster_skill_dir = skill_dir_; + caster_state->caster_skill_distance = skill_distance_; + caster_state->caster_skill_param1 = skill_param1; +} + +void Creature::RecoverSkillCasterState(SkillCasterState* caster_state) +{ + skill_target_id_ = caster_state->caster_skill_target_id; + skill_dir_ = caster_state->caster_skill_dir; + skill_distance_ = caster_state->caster_skill_distance; + skill_param1 = caster_state->caster_skill_param1; +} diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 737ba023..5c5e1115 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -12,6 +12,17 @@ namespace MetaData class SkillPhase; } +struct SkillCasterState +{ + CreatureWeakPtr caster; + a8::Vec2 caster_pos; + int caster_skill_id = 0; + int caster_skill_target_id = 0; + a8::Vec2 caster_skill_dir; + float caster_skill_distance = 0.0f; + float caster_skill_param1 = 0.0f; +}; + struct xtimer_list; class Skill; class Obstacle; @@ -121,6 +132,8 @@ class Creature : public MoveableEntity void CheckSpecObject(); RoomObstacle* SummonObstacle(int id, const a8::Vec2& pos); bool CollisonDetection(); + void FillSkillCasterState(SkillCasterState* caster_state); + void RecoverSkillCasterState(SkillCasterState* caster_state); private: diff --git a/third_party/a8engine b/third_party/a8engine index 9f43c103..1bcc2495 160000 --- a/third_party/a8engine +++ b/third_party/a8engine @@ -1 +1 @@ -Subproject commit 9f43c10312f3f3adccab2d477365c0c1d9200e03 +Subproject commit 1bcc24955410e67342d5e44c2e35addff5111fca