diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 4dd9faeb..135993e4 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -12,10 +12,11 @@ enum CreatureStatus { CS_AlreadyLordMode = 1, - CS_Disable = 2, - CS_Collisioning = 3, - CS_DisableAttack = 8, - CS_ForceTeam = 9, + CS_Disable, + CS_Collisioning, + CS_DisableAttack, + CS_ForceTeam, + CS_PreDieSuspended, CS_End }; diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 3408c4d7..23a65433 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -1129,63 +1129,35 @@ void Human::FillSMGameOver(cs::SMGameOver& msg) void Human::BeKill(int killer_id, const std::string& killer_name, int weapon_id) { -#ifdef DEBUG - if (IsPlayer()) { - a8::XPrintf("BeKill %d\n", {GetUniId()}); - } -#endif - if (!dead && !room->IsGameOver() && !real_dead) { - KillInfo info; - { - info.killer_id = killer_id; - info.killer_name = killer_name; - info.weapon_id = weapon_id; - } - - { - ++stats.dead_times; - stats.killer_id = killer_id; - stats.killer_name = killer_name; - stats.weapon_id = weapon_id; - } - { - Entity* killer = room->GetEntityByUniId(killer_id); - if (killer && killer->IsCreature(room)) { - ((Creature*)killer)->GetTrigger()->Kill(this, weapon_id); - } - } - if (room->IsPveRoom()){ - dead = true; - real_dead = false; - downed = false; - SetHP(0.0f); - KillMgr::Instance()->OnHumanDead(this, &info); - room->frame_event.AddDead(GetWeakPtrRef(), 1000 * 15); - dead_timer = room->xtimer.AddDeadLineTimerAndAttach - (MetaMgr::Instance()->revive_time * SERVER_FRAME_RATE, + if (!dead && !room->IsGameOver() && !real_dead && !a8::HasBitFlag(status, CS_PreDieSuspended)) { + GetTrigger()->PreDie(); + if (over_delay_time > 0) { + a8::SetBitFlag(status, CS_PreDieSuspended); + room->xtimer.AddDeadLineTimerAndAttach + (over_delay_time / FRAME_RATE_MS, a8::XParams() - .SetSender(this), + .SetSender(this) + .SetParam1(killer_id) + .SetParam2(killer_name) + .SetParam3(weapon_id), [] (const a8::XParams& param) { Human* hum = (Human*)param.sender.GetUserData(); - hum->real_dead = true; + hum->over_delay_time = 0; + a8::UnSetBitFlag(hum->status, CS_PreDieSuspended); + hum->InternalBeKill + ( + param.param1, + param.param2.GetString(), + param.param3 + ); }, &xtimer_attacher.timer_list_, [] (const a8::XParams& param) { - Human* hum = (Human*)param.sender.GetUserData(); - hum->dead_timer = nullptr; }); - } else { - dead = true; - real_dead = true; - downed = false; - SetHP(0.0f); - dead_frameno = room->GetFrameNo(); - GetTrigger()->Die(); - OnDie(); - KillMgr::Instance()->OnHumanDead(this, &info); - room->frame_event.AddDead(GetWeakPtrRef(), 0); + } else { + InternalBeKill(killer_id, killer_name, weapon_id); } } } @@ -1894,24 +1866,7 @@ void Human::SendGameOver() } else { if (!sending_battlereport_) { sending_battlereport_ = true; - if (over_delay_time > 0) { - room->xtimer.AddDeadLineTimerAndAttach - (over_delay_time / FRAME_RATE_MS, - a8::XParams() - .SetSender(this), - [] (const a8::XParams& param) - { - Human* hum = (Human*)param.sender.GetUserData(); - hum->SendBattleReport(); - hum->over_delay_time = 0; - }, - &xtimer_attacher.timer_list_, - [] (const a8::XParams& param) - { - }); - } else { - SendBattleReport(); - } + SendBattleReport(); } if (!is_game_end_) { GameLog::Instance()->GameEnd((Player*)this); @@ -4384,3 +4339,66 @@ void Human::WinPveScore(int score) { stats.pve_rank_score += score; } + +void Human::InternalBeKill(int killer_id, const std::string& killer_name, int weapon_id) +{ +#ifdef DEBUG + if (IsPlayer()) { + a8::XPrintf("BeKill %d\n", {GetUniId()}); + } +#endif + if (!dead && !room->IsGameOver() && !real_dead) { + KillInfo info; + { + info.killer_id = killer_id; + info.killer_name = killer_name; + info.weapon_id = weapon_id; + } + + { + ++stats.dead_times; + stats.killer_id = killer_id; + stats.killer_name = killer_name; + stats.weapon_id = weapon_id; + } + { + Entity* killer = room->GetEntityByUniId(killer_id); + if (killer && killer->IsCreature(room)) { + ((Creature*)killer)->GetTrigger()->Kill(this, weapon_id); + } + } + if (room->IsPveRoom()){ + dead = true; + real_dead = false; + downed = false; + SetHP(0.0f); + KillMgr::Instance()->OnHumanDead(this, &info); + room->frame_event.AddDead(GetWeakPtrRef(), 1000 * 15); + dead_timer = room->xtimer.AddDeadLineTimerAndAttach + (MetaMgr::Instance()->revive_time * SERVER_FRAME_RATE, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Human* hum = (Human*)param.sender.GetUserData(); + hum->real_dead = true; + }, + &xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + Human* hum = (Human*)param.sender.GetUserData(); + hum->dead_timer = nullptr; + }); + } else { + dead = true; + real_dead = true; + downed = false; + SetHP(0.0f); + dead_frameno = room->GetFrameNo(); + GetTrigger()->Die(); + OnDie(); + KillMgr::Instance()->OnHumanDead(this, &info); + room->frame_event.AddDead(GetWeakPtrRef(), 0); + } + } +} diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 3484084a..2b28cfd8 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -390,6 +390,7 @@ private: void NextReload(int prev_weapon_id, int prev_weapon_idx); void DoGetOnWithLoot(Loot* loot_entity); void DoGetOnWithCar(Car* car); + void InternalBeKill(int killer_id, const std::string& killer_name, int weapon_id); virtual void AddBuffPostProc(Creature* caster, Buff* buff) override; virtual void OnBuffRemove(Buff& buff) override; virtual void DoSkillPreProc(int skill_id, int target_id, const a8::Vec2& target_pos) override; diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 456fed6a..3437bd64 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -1010,7 +1010,7 @@ namespace MetaData auto field_desc = descriptor->FindFieldByName(a8::Format("phase%d_param3", {idx})); phase.param3_str = reflection->GetString(*(metatable::Skill*)i, field_desc); } - if (phase.func_id != kSkill_FuncNone) { + { phase.param1 = a8::XValue(phase.param1_str); phase.param2 = a8::XValue(phase.param2_str); phase.param3 = a8::XValue(phase.param3_str); @@ -1035,7 +1035,10 @@ namespace MetaData phase.param3_ints.push_back(a8::XValue(str)); } } - phases.push_back(phase); + if (phase.func_id != kSkill_FuncNone) { + phases.push_back(phase); + } + raw_phases.push_back(phase); } } } diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index 80f0e29f..aef64aa4 100644 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -322,6 +322,7 @@ namespace MetaData std::set buff_list; std::map> trigger_type_buffs; std::vector phases; + std::vector raw_phases; bool IsTurnOverSkill() const; int GetMagicId() const; private: diff --git a/server/gameserver/skill.cc b/server/gameserver/skill.cc index f9619204..5f757e04 100644 --- a/server/gameserver/skill.cc +++ b/server/gameserver/skill.cc @@ -468,7 +468,7 @@ void Skill::ProcSWZB() { owner->GetTrigger()->AddListener ( - kDieEvent, + kPreDieEvent, [this] (const std::vector& params) { CreatureWeakPtr sender = owner->GetWeakPtrRef(); @@ -516,8 +516,8 @@ void Skill::ProcSWZB() SkillHelper::GetSwzbEffect(meta), 0 ); - if (!meta->phases.empty()) { - owner->over_delay_time = meta->phases.at(0).param1; + if (!meta->raw_phases.empty()) { + owner->over_delay_time = meta->raw_phases.at(0).param1; } #ifdef DEBUG { diff --git a/server/gameserver/trigger.cc b/server/gameserver/trigger.cc index 0928156e..d1e41bab 100644 --- a/server/gameserver/trigger.cc +++ b/server/gameserver/trigger.cc @@ -232,6 +232,11 @@ void Trigger::ReceiveDmg() DispatchEvent(kReceiveDmgEvent, {}); } +void Trigger::PreDie() +{ + DispatchEvent(kPreDieEvent, {}); +} + void Trigger::Die() { { diff --git a/server/gameserver/trigger.h b/server/gameserver/trigger.h index 8546387c..e871a2d3 100644 --- a/server/gameserver/trigger.h +++ b/server/gameserver/trigger.h @@ -25,6 +25,7 @@ enum EventId_e kShotEvent, kReceiveDmgEvent, kKillEvent, + kPreDieEvent, kDieEvent, kShieldDestoryEvent, kFlyHookPullEvent, @@ -62,6 +63,7 @@ public: void UseSkill(Skill* skill); void HpChg(); void ReceiveDmg(); + void PreDie(); void Die(); void ActiveBuff(MetaData::Buff* buff_meta); void DeactiveBuff(MetaData::Buff* buff_meta);