355 lines
9.9 KiB
C++
355 lines
9.9 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, false, nullptr, buff_vars);
|
|
#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;
|
|
}
|
|
};
|
|
|
|
float param1 = meta->GetBuffParam1(this);
|
|
switch (meta->buff_effect() ) {
|
|
case kBET_DelayAddBuff:
|
|
{
|
|
owner->room->xtimer.SetTimeoutEx
|
|
(
|
|
param1 * SERVER_FRAME_RATE,
|
|
timer_func,
|
|
&xtimer_attacher
|
|
);
|
|
}
|
|
break;
|
|
case kBET_IntervalAddBuff:
|
|
{
|
|
owner->room->xtimer.SetIntervalEx
|
|
(
|
|
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
|
|
}
|
|
|
|
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,
|
|
nullptr);
|
|
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()
|
|
{
|
|
}
|