aozhiwei ddabd0787d 1
2023-03-16 15:56:28 +08:00

366 lines
10 KiB
C++

#include "precompile.h"
#include <math.h>
#include <float.h>
#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;
}
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));
}
if (!meta->res_scale().empty()) {
res_scale = meta->GetResScale(this);
res_scale_frameno = owner->room->GetFrameNo();
}
}
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<SkillCasterState>();
caster_.Get()->FillSkillCasterState(caster_state.get());
#if 1
const mt::Skill* skill = skill_meta;
#else
const mt::Skill* skill = caster_.Get()->CurrentSkillMeta();
#endif
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<Ability> 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 * SERVER_FRAME_RATE,
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 false;
}
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<Bullet*>(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()
{
}
void Buff::Deactivate()
{
}