#include "precompile.h" #include "skill.h" #include "creature.h" #include "room.h" #include "metamgr.h" #include "trigger.h" #include "skillhelper.h" #include "entityfactory.h" #include "explosion.h" #include "buff.h" void Skill::Initialzie() { curr_times_ = GetMaxTimes(); switch (meta->i->skill_type()) { case kActiveSkill: { InitActiveSkill(); } break; case kPassiveSkill: { InitPassiveSkill(); } break; default: { } break; } } int Skill::GetCd() { return meta->i->skill_cd() * 1000; } int Skill::GetPassedTime() { if (!inc_times_timer_) { A8_ABORT(); } if (GetCurrTimes() >= GetMaxTimes()) { return GetCd(); } else { int remain_time = owner->room->xtimer.GetRemainTime(inc_times_timer_); int passed_time = GetCd() - remain_time * FRAME_RATE_MS; passed_time = std::max(0, passed_time); return passed_time; } } int Skill::GetLeftTime() { int passed_time = GetPassedTime(); int skill_left_time = std::max(0, GetCd() - passed_time); return skill_left_time; } void Skill::FillMFSkill(cs::MFSkill* skill_pb) { skill_pb->set_skill_id(meta->i->skill_id()); skill_pb->set_left_time(GetLeftTime()); skill_pb->set_cd_time(GetCd()); skill_pb->set_curr_times(GetCurrTimes()); skill_pb->set_max_times(GetMaxTimes()); if (minor_type_) { int minor_left_time = std::max(0, minor_cd_time_ - (int)(owner->room->GetFrameNo() - minor_frameno_)); skill_pb->set_minor_type(minor_type_); skill_pb->set_minor_left_time(minor_left_time); skill_pb->set_minor_cd_time(minor_cd_time_); skill_pb->set_left_time(GetCd()); #ifdef DEBUG a8::XPrintf("type: %d, lefttime:%d cd_time:%d\n", { minor_type_, minor_left_time, minor_cd_time_ }); #endif } } void Skill::DecTimes() { if (!inc_times_timer_) { A8_ABORT(); } if (GetCurrTimes() >= GetMaxTimes()) { owner->room->xtimer.ModifyTimer(inc_times_timer_, GetCd() / FRAME_RATE_MS); } --curr_times_; if (curr_times_ < 0) { curr_times_ = 0; } } int Skill::GetCurrTimes() { return curr_times_; } int Skill::GetMaxTimes() { return meta->i->max_times(); } void Skill::NotifySkillState() { if (owner->IsHuman()) { if (GetCurrTimes() < GetMaxTimes()) { owner->room->frame_event.AddSkillCdChg(owner->AllocWeakPtr(), meta->i->skill_id(), GetCd()); } else { owner->room->frame_event.AddSkillCdChg(owner->AllocWeakPtr(), meta->i->skill_id(), 0); } owner->room->frame_event.AddSkillCurrTimesChg(owner->AllocWeakPtr(), meta->i->skill_id(), GetCurrTimes()); } } void Skill::ResetSkillCd() { if (!meta->IsTurnOverSkill()) { curr_times_ = 0; if (inc_times_timer_) { owner->room->xtimer.ModifyTimer(inc_times_timer_, GetCd() / FRAME_RATE_MS); NotifySkillState(); } } } void Skill::Accelerate(int time) { if (inc_times_timer_) { int remain_time = owner->room->xtimer.GetRemainTime(inc_times_timer_) * FRAME_RATE_MS; remain_time += time; remain_time = std::max(remain_time, 0); owner->room->xtimer.ModifyTimer(inc_times_timer_, remain_time / FRAME_RATE_MS); NotifySkillState(); } } void Skill::LockCastPhase() { if (meta->i->cast_time() > 0) { int buff_uniid = owner->TryAddBuff(owner, kVertigoBuffId); Buff* buff = owner->GetBuffByUniId(buff_uniid); if (buff && buff->remover_timer) { owner->room->xtimer.ModifyTimer(buff->remover_timer, meta->i->cast_time() / FRAME_RATE_MS); } } } int Skill::GetCurrExp() { return curr_exp_; } void Skill::SetCurrExp(int exp) { curr_exp_ = std::max(0, exp); } int Skill::GetMaxExp() { return meta->i->up_exp(); } void Skill::AddMinorMode( int minor_type, int minor_cd_time, std::function cb ) { if (minor_mode_timer_) { owner->room->xtimer.DeleteTimer(minor_mode_timer_); minor_mode_timer_ = nullptr; } minor_type_ = minor_type; minor_cd_time_ = minor_cd_time; minor_frameno_ = owner->room->GetFrameNo(); minor_cb_ = cb; minor_mode_timer_ = owner->room->xtimer.AddDeadLineTimerAndAttach (minor_cd_time / FRAME_RATE_MS, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { Skill* skill = (Skill*)param.sender.GetUserData(); }, &xtimer_attacher.timer_list_, [] (const a8::XParams& param) { Skill* skill = (Skill*)param.sender.GetUserData(); skill->minor_type_ = SMT_NONE; skill->minor_cd_time_ = 0; skill->minor_frameno_ = 0; skill->minor_cb_ = nullptr; skill->minor_mode_timer_ = nullptr; } ); owner->need_sync_active_player = true; } void Skill::DoMinorMode() { if (GetMinorType() != SMT_NONE) { minor_cb_(); minor_type_ = SMT_NONE; minor_cd_time_ = 0; minor_cb_ = nullptr; ResetSkillCd(); owner->need_sync_active_player = true; } } void Skill::InitActiveSkill() { inc_times_timer_ = owner->room->xtimer.AddRepeatTimerAndAttach ( GetCd() / FRAME_RATE_MS, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { Skill* skill = (Skill*)param.sender.GetUserData(); if (skill->GetCurrTimes() < skill->GetMaxTimes()) { skill->curr_times_++; skill->NotifySkillState(); } }, &xtimer_attacher.timer_list_); } void Skill::InitPassiveSkill() { switch (meta->GetMagicId()) { case MAGIC_SJXY: { ProcSJXY(); } break; case MAGIC_SSJS: { ProcSSJS(); } break; case MAGIC_JSHX: { ProcJSHX(); } break; case MAGIC_SWZB: { ProcSWZB(); } break; case MAGIC_CMXD: { ProcCMXD(); } break; case MAGIC_MYXY: { ProcMYXY(); } break; case MAGIC_GZJS: { ProcGZJS(); } break; case MAGIC_JYFH: { ProcJYFH(); } break; case MAGIC_FH: { ProcFH(); } break; case MAGIC_YSHF: { ProcYSHF(); } break; default: { } break; } } void Skill::ProcSJXY() { int shot_times = 0; std::map hited_objs; owner->GetTrigger()->AddListener ( kBulletHitEvent, [this, shot_times, hited_objs] (const std::vector& params) mutable { ++shot_times; Bullet* bullet = std::any_cast(params.at(0)); Creature* target = std::any_cast(params.at(1)); if (shot_times % meta->number_meta->int_ratio == 0) { if ((rand() % 100) < meta->number_meta->float_probability * 100) { bool is_hit = false; auto itr = hited_objs.find(target->GetUniId()); if (itr == hited_objs.end()) { hited_objs[target->GetUniId()] = owner->room->GetFrameNo(); is_hit = true; } else { if ((owner->room->GetFrameNo() - itr->second) >= meta->number_meta->float_cd * SERVER_FRAME_RATE) { itr->second = owner->room->GetFrameNo(); is_hit = true; } }//endif itr if (is_hit) { target->TryAddBuffAndSetTime(owner, kVertigoBuffId, meta->number_meta->float_cd * 1000); } } } } ); } void Skill::ProcSSJS() { owner->GetTrigger()->AddListener ( kReceiveDmgEvent, [this] (const std::vector& params) { if (GetLeftTime() <= 0) { } } ); } void Skill::ProcJSHX() { owner->GetTrigger()->AddListener ( kKillEvent, [this] (const std::vector& params) { if (!owner->dead) { float add_hp = SkillHelper::GetJshxHp(owner, meta); owner->AddHp(add_hp); } } ); } void Skill::ProcSWZB() { owner->GetTrigger()->AddListener ( kDieEvent, [this] (const std::vector& params) { CreatureWeakPtr sender = owner->GetWeakPtrRef(); a8::Vec2 center = owner->GetPos(); std::shared_ptr e = EntityFactory::Instance()->MakeExplosion(); e->SetHitCb ( [sender, center] (const std::vector& params) mutable { #if 0 if (sender.Get()) { Entity* e = std::any_cast(params.at(0)); if (e->IsCreature()) { } } #endif } ); e->EnemyAndObstacleAttack ( owner->GetWeakPtrRef(), owner->GetPos(), SkillHelper::GetSwzbRadius(meta), SkillHelper::GetSwzbEffect(meta), SkillHelper::GetSwzbDmg(meta) ); } ); } void Skill::ProcCMXD() { owner->GetTrigger()->AddListener ( kShieldDestoryEvent, [this] (const std::vector& params) { Buff* hold_shield_buff = owner->GetBuffByEffectId(kBET_HoldShield); if (hold_shield_buff) { } } ); } void Skill::ProcMYXY() { } void Skill::ProcGZJS() { } void Skill::ProcJYFH() { owner->GetTrigger()->AddListener ( kRescueEvent, [] (const std::vector& params) { } ); } void Skill::ProcFH() { owner->GetTrigger()->AddListener ( kDieEvent, [] (const std::vector& params) { } ); } void Skill::ProcYSHF() { owner->GetTrigger()->AddListener ( kYsRemoveEvent, [this] (const std::vector& params) { Buff* buff = std::any_cast(params.at(0)); if (buff->remover_timer && !buff->owner->dead) { int buff_time = owner->room->xtimer.GetRemainTime(buff->remover_timer) * FRAME_RATE_MS; int remain_time = buff_time - meta->number_meta->float_time * 1000; if (remain_time > 100) { owner->room->xtimer.AddDeadLineTimerAndAttach ( meta->number_meta->float_time * 1000 / FRAME_RATE_MS, a8::XParams() .SetSender(owner) .SetParam1(buff->meta->i->buff_id()) .SetParam2(remain_time) .SetParam3(buff->skill_meta), [] (const a8::XParams& param) { Creature* c = (Creature*)param.sender.GetUserData(); int buff_id = param.param1; int remain_time = param.param2; MetaData::Skill* skill_meta = (MetaData::Skill*)param.param3.GetUserData(); if (!c->HasBuffEffect(kBET_Hide)) { c->TryAddBuffAndSetTime(c, buff_id, remain_time, skill_meta); } }, &owner->xtimer_attacher.timer_list_); } } } ); }