#include "precompile.h" #include #include #include "buff.h" #include "human.h" #include "room.h" #include "skill.h" #include "incubator.h" #include "car.h" #include "frameevent.h" #include "skillhelper.h" #include "trigger.h" #include "virtualbullet.h" #include "ability.h" #include "bullet.h" #include "glmhelper.h" #include "pbutils.h" #include "creature.h" #include "mt/Param.h" #include "mt/Buff.h" #include "mt/Skill.h" #include "mt/SkillNumber.h" #include "mt/Equip.h" Buff::Buff() { } Buff::~Buff() { int i = 0; if (meta->buff_id() == 207014) { int i = 0; } if (meta->buff_id() == 207018) { int i = 0; } } void Buff::Init() { INIT_LIST_HEAD(&effect_entry); INIT_LIST_HEAD(&depend_entry); INIT_LIST_HEAD(&cond_entry); INIT_LIST_HEAD(&on_remove_contexts); for (int effect_id : meta->_effect_list) { effect_list_.push_back(owner->AddEffect(effect_id)); } } void Buff::UnInit() { list_del_init(&effect_entry); if (!list_empty(&depend_entry)) { list_del_init(&depend_entry); } if (!list_empty(&cond_entry)) { list_del_init(&cond_entry); } while (!list_empty(&on_remove_contexts)) { RemoveBuffCbConext* cb = list_last_entry(&on_remove_contexts, RemoveBuffCbConext, entry); *cb->next = (*cb->next)->next; list_del_init(&cb->entry); } ClearEventHandlers(); for (auto& effect : effect_list_) { owner->RemoveEffect(effect); } effect_list_.clear(); } int Buff::GetLeftTime() { int passed_ms = (owner->room->GetFrameNo() - add_frameno) * FRAME_RATE_MS; return std::max(GetLastingTime() - passed_ms, 0); } int Buff::GetLastingTime() { return meta->GetDurationTime(this) * 1000; } void Buff::InternalTimerAddBuff() { if (!caster_.Get()) { return; } auto caster_state = std::make_shared(); caster_.Get()->FillSkillCasterState(caster_state.get()); const mt::Skill* skill = caster_.Get()->CurrentSkillMeta(); auto timer_func = [this, caster_state, skill] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { if (!caster_state->caster.Get()) { return; } Creature* receiver = owner; CreatureWeakPtr caster = caster_state->caster; std::shared_ptr old_context_ability = receiver->context_ability; glm::vec3 old_context_dir = receiver->context_dir; Position old_context_pos = receiver->context_pos; #if 0 receiver->context_dir = receiver->GetAttackDir(); receiver->context_pos = receiver->GetPos(); #endif int buff_id = meta->_int_buff_param2; const mt::Buff* buff_meta = mt::Buff::GetById(buff_id); if (buff_meta) { SkillCasterState old_caster_state; caster.Get()->FillSkillCasterState(&old_caster_state); caster.Get()->RecoverSkillCasterState(caster_state.get()); //!!!在AddBuff的过程可能删除buff导致caster_state野指针 receiver->AddBuff(caster.Get(), buff_meta, skill); #if 0 caster.Get()->RecoverSkillCasterState(&old_caster_state); #endif } receiver->context_dir = old_context_dir; receiver->context_pos = old_context_pos; receiver->context_ability = old_context_ability; } }; switch (meta->buff_effect() ) { case kBET_DelayAddBuff: { owner->room->xtimer.SetTimeoutEx ( meta->_buff_param1 * SERVER_FRAME_RATE, timer_func, &xtimer_attacher ); } break; case kBET_IntervalAddBuff: { owner->room->xtimer.SetIntervalEx ( meta->_buff_param1 / FRAME_RATE_MS, timer_func, &xtimer_attacher ); } break; default: { } break; } } bool Buff::NeedSync(Human* hum) { return !meta->only_server() || !(meta->only_self() && owner == hum); } bool Buff::FreezeOperate() { return meta->buff_effect() == kBET_Become && !hold_weapons_.empty(); } void Buff::RecoverHoldWeapons() { #ifdef DEBUG1 caster_.Get()->SendDebugMsg(a8::Format("RecoverHoldWeapons buff:%d hold_curr_weapon_idx:%d", { meta->buff_id(), hold_curr_weapon_idx_ })); #endif for (auto& weapon : hold_weapons_) { if (weapon.weapon_idx >= 0 && weapon.weapon_idx < caster_.Get()->weapons.size()) { caster_.Get()->weapons[weapon.weapon_idx] = weapon; } } if (hold_curr_weapon_idx_ >=0 && hold_curr_weapon_idx_ <= caster_.Get()->weapons.size() && caster_.Get()->weapons[hold_curr_weapon_idx_].weapon_id != 0) { Weapon* next_weapon = &caster_.Get()->weapons[hold_curr_weapon_idx_]; caster_.Get()->SetCurrWeapon(next_weapon); } else { if (!hold_weapons_.empty()) { Weapon* next_weapon = caster_.Get()->AutoChgWeapon(); if (next_weapon) { caster_.Get()->SetCurrWeapon(next_weapon); } } } #ifdef DEBUG1 for (auto& w : caster_.Get()->weapons) { caster_.Get()->SendDebugMsg(a8::Format("weapon_idx:%d weapon_id:%d", { w.weapon_idx, w.weapon_id })); } #endif hold_weapons_.clear(); caster_.Get()->MarkSyncActivePlayer(__FILE__, __LINE__, __func__); caster_.Get()->SyncAroundPlayers(__FILE__, __LINE__, __func__); } CreatureWeakPtr& Buff::GetCaster() { return caster_; } void Buff::SetCaster(Creature* caster) { if (caster) { caster_.Attach(caster); } else { caster_.Reset(); } } void Buff::CalcPassengerShotOffset() { if (meta->buff_effect() == kBET_Passenger && caster_.Get()->IsHuman()) { Human* hum = (Human*)caster_.Get(); if (hum->GetCar() && hum->GetCar()->GetCurrWeapon()) { { //换座位时清除之前的状态 RecoverHoldWeapons(); } hold_weapons_.push_back(hum->weapons[hum->GetCar()->GetCurrWeapon()->weapon_idx]); hum->weapons[hum->GetCar()->GetCurrWeapon()->weapon_idx] = *hum->GetCar()->GetCurrWeapon(); hum->SetCurrWeapon(&hum->weapons[hum->GetCar()->GetCurrWeapon()->weapon_idx]); if (hum->GetCar()->meta && hum->GetSeat() < hum->GetCar()->meta->_shoot_offsets.size() && std::get<0>(hum->GetCar()->meta->_shoot_offsets[hum->GetSeat()]) ) { hum->shoot_offset = std::get<1>(hum->GetCar()->meta->_shoot_offsets[hum->GetSeat()]); } } } } void Buff::ClearEventHandlers() { for (auto& handler : event_handlers_) { if (!handler.expired()) { owner->GetTrigger()->RemoveEventHandler(handler); } } event_handlers_.clear(); } void Buff::PreProcess() { switch (meta->buff_effect()) { case kBET_CallFunc: { switch (meta->_int_buff_param1) { case 1: { event_handlers_.push_back ( owner->GetTrigger()->AddListener ( kTriggerBulletHitBuffEvent, [this] (const a8::Args& args) { Bullet* bullet = args.Get(0); ProcSputteringFunc(bullet); })); } break; default: { } break; } } break; default: { } break; } #ifdef DEBUG if (owner->IsPlayer()) { if (meta->buff_effect() == kBET_Vertigo) { int i = 0; } } #endif // 999 #if 1 if (meta->buff_id() == 8042) { #ifdef DEBUG { a8::XPrintf("添加减速%f", {meta->_buff_param3}); } #endif if (owner->GetAbility()->GetSpeedRuduceTimes() <= 0) { owner->GetAbility()->AddSpeedRuduce(-meta->_buff_param3/100.0f); } } #endif } void Buff::ProcSputteringFunc(Bullet* bullet) { const mt::Equip* weapon_meta = mt::Equip::GetById(meta->_int_buff_param2); if (!weapon_meta) { return; } for (int i = 0; i < meta->_buff_param4_int_list.size(); ++i) { glm::vec3 bullet_dir = GlmHelper::UP; GlmHelper::RotateY(bullet_dir, meta->_buff_param4_int_list[i] / 180.f); Position bullet_born_pos = owner->GetPos(); bullet_born_pos.AddGlmVec3(bullet_dir * meta->_buff_param3); int bullet_uniid = owner->room->AllocUniid(); owner->room->frame_event.AddBullet (bullet_uniid, owner->GetWeakPtrRef(), weapon_meta, 1, bullet_born_pos.ToGlmVec3(), bullet_dir, 0, 0, 0); VirtualBullet* p = new VirtualBullet(); p->bullet_uniid = bullet_uniid; p->weapon_uniid = bullet->weapon_uniid; p->skill_meta = bullet->skill_meta; p->gun_meta = bullet->gun_meta; p->bullet_meta = bullet->meta; p->sender = bullet->sender; p->passenger = bullet->passenger; p->room = bullet->room; p->is_pre_battle_bullet = bullet->IsPreBattleBullet(); p->dir = bullet_dir; p->born_pos = bullet_born_pos; p->born_dir = bullet_dir; p->Init(); owner->room->AddTask(bullet_uniid, p); } } void Buff::Activate() { const mt::Buff* buff_meta = meta; switch (meta->buff_effect()) { case kBET_CrazyMode: { owner->RecalcBuffAttr(); } break; default: { } break; } } void Buff::Deactivate() { }