1990 lines
66 KiB
C++
1990 lines
66 KiB
C++
#include "precompile.h"
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/vec2.hpp>
|
|
|
|
#include <a8/collision.h>
|
|
|
|
#include "buff/callfunc.h"
|
|
|
|
#include "creature.h"
|
|
#include "ability.h"
|
|
#include "room.h"
|
|
#include "skill.h"
|
|
#include "movement.h"
|
|
#include "mapinstance.h"
|
|
#include "trigger.h"
|
|
#include "human.h"
|
|
#include "team.h"
|
|
#include "collision.h"
|
|
#include "netdata.h"
|
|
#include "hero.h"
|
|
#include "obstacle.h"
|
|
#include "car.h"
|
|
#include "app.h"
|
|
#include "bullet.h"
|
|
#include "virtualbullet.h"
|
|
#include "shot.h"
|
|
#include "entityfactory.h"
|
|
#include "gridcell.h"
|
|
|
|
#include "mt/Buff.h"
|
|
#include "mt/Equip.h"
|
|
#include "mt/Skill.h"
|
|
#include "mt/SkillNumber.h"
|
|
|
|
void CallFuncBuff::Activate()
|
|
{
|
|
int buff_id = meta->buff_id();
|
|
hold_weapon_ = owner->GetCurrWeapon();
|
|
switch ((BuffCallFunc_e)meta->_int_buff_param1) {
|
|
case BuffCallFunc_e::kAddMinorMode:
|
|
{
|
|
ProcAddMinorMode();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kInternalRangeAddBuff:
|
|
{
|
|
ProcIntervalRangeAddBuffFunc();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kDecHp:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
if (GetCaster().Get()) {
|
|
float dmg = hold_param2_;
|
|
dmg = owner->GetNetData()->CalcSkillReceiveDmg(GetCaster().Get(), dmg);
|
|
float dmg_out = 0.0f;
|
|
owner->DecHP(dmg,
|
|
GetCaster().Get()->GetUniId(),
|
|
GetCaster().Get()->GetName(),
|
|
VP_Buff,
|
|
GetCaster().Get()->GetUniId(),
|
|
GetCaster().Get()->GetName(),
|
|
dmg_out,
|
|
0,
|
|
0
|
|
);
|
|
owner->GetTrigger()->Attacked(GetCaster().Get());
|
|
}
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kMarkTag:
|
|
{
|
|
ProcMarkTag();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kRemoveBuff:
|
|
{
|
|
ProcRemoveBuff();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kFlashMove:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
ProcFlashMove();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAddEnergyShield:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
ProcAddEnergyShield();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAddHp:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
ProcAddHp();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAddMaxHp:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
ProcAddMaxHp();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kFlashMoveToPos:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
ProcFlashMoveToPos();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kLightCircle:
|
|
{
|
|
ProcLightCircle();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSyncProp:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
ProcSyncProp();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSetBulletBornOffset:
|
|
{
|
|
owner->GetCurrWeapon()->bullet_born_offset_ptr = &meta->_bullet_born_offset;
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSummonHeroSepcPoint:
|
|
{
|
|
SummonHeroSpecPoint();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSummonHeroSpecDistance:
|
|
{
|
|
SummonHeroSpecDistance();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kClearSummonHero:
|
|
{
|
|
ClearSummonHero();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kImmuneAllMove:
|
|
{
|
|
owner->GetAbility()->IncSwitch(kDisableMoveEffectTimes);
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kDmgForward:
|
|
{
|
|
owner->GetAbility()->IncSwitch(kEnableDmgForwardTimes);
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSetGunBuffId:
|
|
{
|
|
owner->GetCurrWeapon()->buff_id = meta->_int_buff_param2;
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSummonObstacleSepcPoint:
|
|
{
|
|
SummonObstacleSpecPoint();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSummonObstacleSpecDistance:
|
|
{
|
|
SummonObstacleSpecDistance();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kClearSummonObstacle:
|
|
{
|
|
ClearSummonObstacle();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kDecSkillCd:
|
|
{
|
|
DecSkillCd();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kRefreshHp:
|
|
{
|
|
owner->SetMaxHP(owner->GetNetData()->GetMaxHP());
|
|
owner->SetHP(owner->GetNetData()->GetMaxHP());
|
|
owner->room->frame_event.AddHpChg(owner->GetWeakPtrRef());
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSummonCarSpecPoint:
|
|
{
|
|
SummonCarSpecPoint();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kRangeHoldBuff:
|
|
{
|
|
RangeHoldBuff();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kPlayFlyEffect:
|
|
{
|
|
PlayFlyEffect();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSpecCenterRangeHoldBuff:
|
|
{
|
|
SpecCenterRangeHoldBuff();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kLispEval:
|
|
{
|
|
LispEval();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kThrowKnife:
|
|
{
|
|
ThrowKnife();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kDirectAbsDecHP:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
if (GetCaster().Get()) {
|
|
float dmg = hold_param2_;
|
|
float dmg_out = 0.0f;
|
|
owner->DecHP(dmg,
|
|
GetCaster().Get()->GetUniId(),
|
|
GetCaster().Get()->GetName(),
|
|
VP_Buff,
|
|
GetCaster().Get()->GetUniId(),
|
|
GetCaster().Get()->GetName(),
|
|
dmg_out,
|
|
0,
|
|
0
|
|
);
|
|
owner->GetTrigger()->Attacked(GetCaster().Get());
|
|
}
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAccumulatePower:
|
|
{
|
|
AccumulatePower();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kCallShot:
|
|
{
|
|
Shot();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kBatchRandomPosSummonObstacle:
|
|
{
|
|
BatchRandomPosSummonObstacle();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kOnBreakSkill:
|
|
{
|
|
OnBreakSkill();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kBreakSkill:
|
|
{
|
|
BreakSkill();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kBuffEffectCondAdd:
|
|
{
|
|
BuffEffectCondAdd();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kRandAdd:
|
|
{
|
|
RandAdd();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kShowExplosion:
|
|
{
|
|
ShowExplosion();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAddArmorShield:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
AddArmorShield();
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kBulletDmgCalcProc:
|
|
{
|
|
hold_param2_ = meta->GetBuffParam2(this);
|
|
BulletDmgCalcProc();
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::Deactivate()
|
|
{
|
|
int buff_id = meta->buff_id();
|
|
if (deactivate_cb_) {
|
|
deactivate_cb_();
|
|
}
|
|
switch ((BuffCallFunc_e)meta->_int_buff_param1) {
|
|
case BuffCallFunc_e::kAddMinorMode:
|
|
{
|
|
if (skill_meta) {
|
|
Skill* skill = owner->GetSkill(skill_meta->_base_skill_meta->skill_id());
|
|
skill->CancelMinorMode();
|
|
}
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSetBulletBornOffset:
|
|
{
|
|
hold_weapon_->bullet_born_offset_ptr = nullptr;
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kImmuneAllMove:
|
|
{
|
|
owner->GetAbility()->DecSwitch(kDisableMoveEffectTimes);
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kDmgForward:
|
|
{
|
|
owner->GetAbility()->DecSwitch(kEnableDmgForwardTimes);
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kSetGunBuffId:
|
|
{
|
|
hold_weapon_->buff_id = 0;
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAddEnergyShield:
|
|
{
|
|
float dur_time = meta->GetBuffParam3(this);
|
|
if (dur_time > 0.00001f) {
|
|
owner->ClearEnergyShield();
|
|
}
|
|
}
|
|
break;
|
|
case BuffCallFunc_e::kAddArmorShield:
|
|
{
|
|
float dur_time = meta->GetBuffParam3(this);
|
|
if (dur_time > 0.00001f) {
|
|
owner->ClearArmorShield();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcIntervalRangeAddBuffFunc()
|
|
{
|
|
owner->room->xtimer.SetIntervalEx
|
|
(
|
|
meta->_buff_param4 / FRAME_RATE_MS,
|
|
[this] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
owner->TraverseCreatures
|
|
(
|
|
[this] (Creature* c, bool& stop)
|
|
{
|
|
if (c->dead) {
|
|
return;
|
|
}
|
|
if (owner->GetUniId() == c->GetUniId()) {
|
|
return;
|
|
}
|
|
if (!GetCaster().Get()) {
|
|
return;
|
|
}
|
|
if (GetCaster().Get()->team_id != c->team_id) {
|
|
if (owner->GetPos().Distance2D2(c->GetPos()) < meta->_buff_param2) {
|
|
c->TryAddBuff(GetCaster().Get(), meta->_int_buff_param3, skill_meta);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
&xtimer_attacher
|
|
);
|
|
}
|
|
|
|
void CallFuncBuff::ProcAddMinorMode()
|
|
{
|
|
if (skill_meta) {
|
|
float dur_time = meta->GetBuffParam3(this);
|
|
Skill* skill = owner->GetSkill(skill_meta->_base_skill_meta->skill_id());
|
|
if (skill) {
|
|
auto owner_ptr = owner->GetWeakPtrRef();
|
|
auto meta_ptr = meta;
|
|
auto skill_meta_ptr = skill_meta;
|
|
#ifdef MYDEBUG
|
|
if (owner_ptr.Get()->IsPlayer()) {
|
|
a8::XPrintf("ProcAddMinorMode buff_uniid:%d buff_id:%d dur_time:%d\n",
|
|
{
|
|
buff_uniid,
|
|
meta->buff_id(),
|
|
dur_time});
|
|
}
|
|
#endif
|
|
skill->AddMinorMode
|
|
(
|
|
meta->_int_buff_param2,
|
|
dur_time * 1000,
|
|
[owner_ptr, meta_ptr, skill_meta_ptr] (int action) mutable
|
|
{
|
|
if (owner_ptr.Get()) {
|
|
if (action == kSmaClick) {
|
|
for (int buff_id : meta_ptr->_buff_param6_int_list) {
|
|
owner_ptr.Get()->RemoveBuffById(buff_id);
|
|
}
|
|
for (int buff_id : meta_ptr->_buff_param4_int_list) {
|
|
#ifdef MYDEBUG
|
|
if (owner_ptr.Get()->IsPlayer() && meta_ptr->buff_id() == 207041) {
|
|
a8::XPrintf("addminor buff_id:%d\n", {buff_id});
|
|
}
|
|
#endif
|
|
if (buff_id > 0) {
|
|
owner_ptr.Get()->TryAddBuff(owner_ptr.Get(), buff_id, skill_meta_ptr);
|
|
} else {
|
|
owner_ptr.Get()->RemoveBuffById(std::abs(buff_id));
|
|
}
|
|
}
|
|
#if 0
|
|
} else if (action == kSmaTimeOut) {
|
|
#else
|
|
} else if (action == kSmaTimeOut || action == kSmaCancel) {
|
|
#endif
|
|
for (int buff_id : meta_ptr->_buff_param7_int_list) {
|
|
owner_ptr.Get()->RemoveBuffById(buff_id);
|
|
}
|
|
for (int buff_id : meta_ptr->_buff_param5_int_list) {
|
|
owner_ptr.Get()->TryAddBuff(owner_ptr.Get(), buff_id, skill_meta_ptr);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
meta->buff_id());
|
|
#ifdef MYDEBUG1
|
|
if (owner_ptr.Get()->IsPlayer()) {
|
|
a8::XPrintf("ProcAddMinorMode buff_uniid:%d buff_id:%d dur_time:%d frame_no:%d 2222222222222222\n",
|
|
{
|
|
buff_uniid,
|
|
meta->buff_id(),
|
|
dur_time,
|
|
owner_ptr.Get()->room->GetFrameNo(),
|
|
});
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcMarkTag()
|
|
{
|
|
switch (meta->_int_buff_param2) {
|
|
case 1:
|
|
{
|
|
owner->SetBuffTag(meta->_int_buff_param3, meta->_int_buff_param4);
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
owner->IncBuffTag(meta->_int_buff_param3, meta->_int_buff_param4);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcRemoveBuff()
|
|
{
|
|
for (int buff_effect : meta->_buff_param2_int_list) {
|
|
owner->RemoveBuffByEffectId(buff_effect);
|
|
}
|
|
for (int buff_id : meta->_buff_param3_int_list) {
|
|
owner->RemoveBuffById(buff_id);
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcFlashMove()
|
|
{
|
|
float distance = owner->context_pos.Distance2D2(owner->GetPos());
|
|
if (distance > 0.00001f) {
|
|
glm::vec3 move_dir = owner->GetPos().CalcDir(owner->context_pos);
|
|
GlmHelper::Normalize(move_dir);
|
|
float move_distance = std::min(distance, hold_param2_);
|
|
glm::vec3 hit_point = glm::vec3(0.0f, 0.0f, 0.0f);
|
|
bool hit_result = false;
|
|
|
|
glm::vec3 start = owner->GetPos().ToGlmVec3();
|
|
glm::vec3 end = owner->GetPos().ToGlmVec3() + move_dir * move_distance;
|
|
owner->room->map_instance->Scale(start);
|
|
owner->room->map_instance->Scale(end);
|
|
|
|
bool ret = owner->room->map_instance->Raycast
|
|
(
|
|
start,
|
|
end,
|
|
hit_point,
|
|
hit_result,
|
|
owner->room->map_instance->GetMoveIncludeFlags(),
|
|
owner->room->map_instance->GetMoveExcludeFlags());
|
|
if (ret) {
|
|
owner->room->map_instance->UnScale(hit_point);
|
|
owner->GetMovement()->ClearPath();
|
|
owner->context_real_pos = hit_point;
|
|
|
|
Position new_pos;
|
|
new_pos.FromGlmVec3(hit_point);
|
|
|
|
glm::vec3 move_dir = hit_point - owner->GetPos().ToGlmVec3();
|
|
if (GlmHelper::IsEqual2D(hit_point,
|
|
owner->GetPos().ToGlmVec3())) {
|
|
return;
|
|
}
|
|
GlmHelper::Normalize(move_dir);
|
|
owner->SetMoveDir(move_dir);
|
|
owner->SetAttackDir(move_dir);
|
|
|
|
App::Instance()->verify_set_pos = 1;
|
|
owner->SetPos(new_pos);
|
|
App::Instance()->verify_set_pos = 0;
|
|
owner->room->grid_service->MoveCreature(owner);
|
|
if (owner->IsCar()) {
|
|
Car* car = owner->AsCar();
|
|
if (car->GetDriver()) {
|
|
App::Instance()->verify_set_pos = 1;
|
|
car->GetDriver()->SetPos(new_pos);
|
|
car->SyncPos();
|
|
car->GetDriver()->GetMovement()->ClearPath();
|
|
App::Instance()->verify_set_pos = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
owner->context_real_pos = owner->GetPos().ToGlmVec3();
|
|
}
|
|
|
|
void CallFuncBuff::ProcAddEnergyShield()
|
|
{
|
|
int buff_id = meta->buff_id();
|
|
if (!owner->dead && !owner->downed) {
|
|
float dur_time = meta->GetBuffParam3(this);
|
|
if (dur_time < 0.00001f) {
|
|
dur_time = 99999999;
|
|
}
|
|
if (owner->energy_shield > 0) {
|
|
is_valid_ = false;
|
|
owner->GetTrigger()->UpdateEnergyShield(hold_param2_, dur_time);
|
|
} else {
|
|
owner->AddEnergyShield(hold_param2_);
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kUpdateEnergyShieldEvent,
|
|
[this] (const a8::Args& args) mutable
|
|
{
|
|
int value = args.Get<int>(0);
|
|
int new_time = args.Get<int>(1);
|
|
owner->AddEnergyShield(value);
|
|
}));
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kDestoryEnergyShieldEvent,
|
|
[this] (const a8::Args& args) mutable
|
|
{
|
|
owner->RemoveBuffByUniId(buff_uniid);
|
|
}));
|
|
owner->room->xtimer.SetTimeoutWpEx
|
|
(
|
|
dur_time / FRAME_RATE_MS,
|
|
[owner = owner, buff_uniid = buff_uniid] (int event, const a8::Args* args) mutable
|
|
{
|
|
if (a8::TIMER_DELETE_EVENT == event) {
|
|
owner->ClearEnergyShield();
|
|
owner->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
},
|
|
&owner->xtimer_attacher);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcAddHp()
|
|
{
|
|
int buff_id = meta->buff_id();
|
|
if (!owner->dead && !owner->downed) {
|
|
if (std::abs(owner->GetMaxHP() - owner->GetHP()) < 0.001f) {
|
|
is_valid_ = false;
|
|
} else {
|
|
owner->AddHp(hold_param2_);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcFlashMoveToPos()
|
|
{
|
|
float x = meta->GetBuffParam2(this);
|
|
float y = meta->GetBuffParam3(this);
|
|
float z = meta->GetBuffParam4(this);
|
|
|
|
owner->GetMovement()->ClearPath();
|
|
|
|
App::Instance()->verify_set_pos = 1;
|
|
owner->GetMutablePos().FromGlmVec3(glm::vec3(x, y, z));
|
|
App::Instance()->verify_set_pos = 0;
|
|
owner->room->grid_service->MoveCreature(owner);
|
|
#if 0
|
|
owner->room->frame_event.AddPropChg(owner->GetWeakPtrRef(),
|
|
kPropFlyTo,
|
|
0,
|
|
0,
|
|
false);
|
|
#endif
|
|
}
|
|
|
|
void CallFuncBuff::ProcLightCircle()
|
|
{
|
|
if (!skill_meta) {
|
|
return;
|
|
}
|
|
if (skill_meta->GetMagicId() != MAGIC_30601_DJS) {
|
|
return;
|
|
}
|
|
|
|
struct InnerObject
|
|
{
|
|
CreatureWeakPtr c;
|
|
std::set<int> buff_uniids;
|
|
|
|
void OnEnter()
|
|
{
|
|
|
|
}
|
|
|
|
void OnLeave()
|
|
{
|
|
}
|
|
|
|
};
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
a8::XTimerWp passive_skill_timer;
|
|
a8::XTimerWp active_skill_timer;
|
|
std::map<int, InnerObject> in_human_infos;
|
|
const mt::Skill* active_skill_meta = nullptr;
|
|
int keep_buff_uniid = 0;
|
|
);
|
|
|
|
|
|
auto on_enter =
|
|
[this, context] (Human* hum)
|
|
{
|
|
if (context->in_human_infos.find(hum->GetUniId()) != context->in_human_infos.end()) {
|
|
abort();
|
|
}
|
|
const mt::Skill* curr_skill_meta = context->active_skill_meta ?
|
|
context->active_skill_meta : skill_meta;
|
|
|
|
InnerObject o;
|
|
o.c = hum->GetWeakPtrRef();
|
|
|
|
const mt::Skill* old_skill_meta = skill_meta;
|
|
skill_meta = curr_skill_meta;
|
|
if (context->active_skill_meta) {
|
|
for (int buff_id : meta->_buff_param3_int_list) {
|
|
o.buff_uniids.insert(hum->TryAddBuff(GetCaster().Get(), buff_id, skill_meta));
|
|
}
|
|
} else {
|
|
for (int buff_id : meta->_buff_param2_int_list) {
|
|
o.buff_uniids.insert(hum->TryAddBuff(GetCaster().Get(), buff_id, skill_meta));
|
|
}
|
|
}
|
|
skill_meta = old_skill_meta;
|
|
|
|
context->in_human_infos[hum->GetUniId()] = o;
|
|
context->in_human_infos[hum->GetUniId()].OnEnter();
|
|
};
|
|
auto on_stay =
|
|
[this, context] (Human* hum)
|
|
{
|
|
};
|
|
auto on_leave =
|
|
[this, context] (Human* hum)
|
|
{
|
|
auto itr = context->in_human_infos.find(hum->GetUniId());
|
|
if (itr == context->in_human_infos.end()) {
|
|
abort();
|
|
}
|
|
for (int buff_uniid : itr->second.buff_uniids) {
|
|
hum->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
itr->second.OnLeave();
|
|
};
|
|
auto check_cb =
|
|
[this, context, on_enter, on_stay, on_leave]
|
|
()
|
|
{
|
|
if (owner->HasBuffEffect(kBET_Fly) ||
|
|
owner->HasBuffEffect(kBET_Jump)) {
|
|
return;
|
|
}
|
|
const mt::Skill* curr_skill_meta = context->active_skill_meta ?
|
|
context->active_skill_meta : skill_meta;
|
|
if (!owner->dead) {
|
|
float range = curr_skill_meta->_number_meta->_float_range2;
|
|
int size = 0;
|
|
std::array<Human*, MAX_TEAM_NUM> hit_humans;
|
|
owner->GetTeam()->TraverseMembers
|
|
(
|
|
[this, range, &hit_humans, &size] (Human* hum) mutable
|
|
{
|
|
if (!hum->dead &&
|
|
Collision::CheckCC(owner, owner->GetRadius(),
|
|
hum, range)) {
|
|
if (size < MAX_TEAM_NUM) {
|
|
hit_humans[size++] = hum;
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
std::vector<Human*> leave_humans;
|
|
for (auto& pair : context->in_human_infos) {
|
|
bool found = false;
|
|
for (int i = 0; i < size; ++i){
|
|
if (hit_humans[i] == pair.second.c.Get()) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
on_leave(pair.second.c.Get()->AsHuman());
|
|
leave_humans.push_back(pair.second.c.Get()->AsHuman());
|
|
}
|
|
}
|
|
for (Human* hum : leave_humans) {
|
|
context->in_human_infos.erase(hum->GetUniId());
|
|
}
|
|
for (int i = 0; i < size; ++i){
|
|
if (context->in_human_infos.find(hit_humans[i]->GetUniId()) ==
|
|
context->in_human_infos.end()) {
|
|
on_enter(hit_humans[i]);
|
|
on_stay(hit_humans[i]);
|
|
} else {
|
|
on_stay(hit_humans[i]);
|
|
}
|
|
}
|
|
} else {
|
|
if (!context->in_human_infos.empty()) {
|
|
for (auto& pair : context->in_human_infos) {
|
|
on_leave(pair.second.c.Get()->AsHuman());
|
|
}
|
|
context->in_human_infos.clear();
|
|
}
|
|
}
|
|
};
|
|
context->passive_skill_timer = owner->room->xtimer.SetIntervalWpEx
|
|
(
|
|
SERVER_FRAME_RATE,
|
|
[this, context, on_enter, on_stay, on_leave, check_cb]
|
|
(int event, const a8::Args* args) mutable
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
check_cb();
|
|
} else if (kActiveDjsSkillTimerEvent == event) {
|
|
for (auto& pair : context->in_human_infos) {
|
|
on_leave(pair.second.c.Get()->AsHuman());
|
|
}
|
|
context->in_human_infos.clear();
|
|
context->active_skill_meta = args->Get<const mt::Skill*>(0);
|
|
Buff* buff = owner->GetBuffByUniId(context->keep_buff_uniid);
|
|
if (buff) {
|
|
buff->res_scale = 2.0f;
|
|
buff->res_scale_frameno = owner->room->GetFrameNo();
|
|
owner->room->frame_event.AddBuff(owner->GetWeakPtrRef(), buff);
|
|
}
|
|
check_cb();
|
|
} else if (kDeactiveDjsSkillTimerEvent == event) {
|
|
for (auto& pair : context->in_human_infos) {
|
|
on_leave(pair.second.c.Get()->AsHuman());
|
|
}
|
|
context->in_human_infos.clear();
|
|
context->active_skill_meta = nullptr;
|
|
Buff* buff = owner->GetBuffByUniId(context->keep_buff_uniid);
|
|
if (buff) {
|
|
buff->res_scale = 1.0f;
|
|
buff->res_scale_frameno = owner->room->GetFrameNo();
|
|
owner->room->frame_event.AddBuff(owner->GetWeakPtrRef(), buff);
|
|
}
|
|
check_cb();
|
|
}
|
|
},
|
|
&xtimer_attacher);
|
|
|
|
{
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kUseSkillEvent,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
if (context->passive_skill_timer.expired()) {
|
|
return;
|
|
}
|
|
Skill* skill = args.Get<Skill*>(0);
|
|
if (skill->GetBaseSkillMeta()->GetMagicId() == MAGIC_20601_DJS) {
|
|
if (!context->active_skill_timer.expired()) {
|
|
return;
|
|
}
|
|
a8::Args event_args({skill->GetBaseSkillMeta()});
|
|
owner->room->xtimer.FireEvent(context->passive_skill_timer,
|
|
kActiveDjsSkillTimerEvent,
|
|
&event_args);
|
|
context->active_skill_timer = owner->room->xtimer.SetTimeoutWpEx
|
|
(
|
|
skill->GetCurrSkillMeta()->_number_meta->_float_time * SERVER_FRAME_RATE,
|
|
[this, context] (int event, const a8::Args* args) mutable
|
|
{
|
|
if (a8::TIMER_DELETE_EVENT == event) {
|
|
a8::Args event_args({});
|
|
owner->room->xtimer.FireEvent(context->passive_skill_timer,
|
|
kDeactiveDjsSkillTimerEvent,
|
|
&event_args);
|
|
}
|
|
},
|
|
&xtimer_attacher);
|
|
}
|
|
}
|
|
));
|
|
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kDieEvent,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
if (context->keep_buff_uniid) {
|
|
owner->RemoveBuffByUniId(context->keep_buff_uniid);
|
|
context->keep_buff_uniid = 0;
|
|
}
|
|
}
|
|
));
|
|
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kStartJump,
|
|
[this, context, on_leave] (const a8::Args& args) mutable
|
|
{
|
|
if (context->keep_buff_uniid) {
|
|
for (auto& pair : context->in_human_infos) {
|
|
on_leave(pair.second.c.Get()->AsHuman());
|
|
}
|
|
context->in_human_infos.clear();
|
|
owner->RemoveBuffByUniId(context->keep_buff_uniid);
|
|
context->keep_buff_uniid = 0;
|
|
}
|
|
}
|
|
));
|
|
|
|
owner->GetTrigger()->AddListener
|
|
(
|
|
kEndJump,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
if (context->keep_buff_uniid) {
|
|
owner->RemoveBuffByUniId(context->keep_buff_uniid);
|
|
context->keep_buff_uniid = 0;
|
|
}
|
|
context->keep_buff_uniid = owner->TryAddBuff(GetCaster().Get(), meta->_int_buff_param4, skill_meta);
|
|
}
|
|
);
|
|
|
|
}
|
|
{
|
|
context->keep_buff_uniid = owner->TryAddBuff(GetCaster().Get(), meta->_int_buff_param4, skill_meta);
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcSyncProp()
|
|
{
|
|
float type = meta->GetBuffParam2(this);
|
|
float sub_type = meta->GetBuffParam3(this);
|
|
float value = meta->GetBuffParam4(this);
|
|
int only_self = meta->GetBuffParam6(this);
|
|
owner->room->frame_event.AddPropChg
|
|
(
|
|
owner->GetWeakPtrRef(),
|
|
type,
|
|
sub_type,
|
|
value,
|
|
only_self > 0);
|
|
}
|
|
|
|
void CallFuncBuff::SummonHeroSpecPoint()
|
|
{
|
|
int hero_id = meta->_int_buff_param2;
|
|
float x = meta->GetBuffParam3(this);
|
|
float y = meta->GetBuffParam4(this);
|
|
float z = meta->GetBuffParam5(this);
|
|
if (!owner->dead || meta->dead_valid() != 0) {
|
|
Hero* hero = owner->SummonHero(this,
|
|
glm::vec3(x, y, z),
|
|
owner->GetAttackDir());
|
|
if (hero) {
|
|
std::shared_ptr<std::vector<float>> vars = std::make_shared<std::vector<float>>();
|
|
vars->push_back(hero->GetUniId());
|
|
for (int buff_id : meta->_buff_param6_int_list) {
|
|
hero->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
vars
|
|
);
|
|
}
|
|
if (meta->_int_buff_param8) {
|
|
owner->GetTrigger()->AddListener
|
|
(
|
|
kDieEvent,
|
|
[hero_ptr = hero->GetWeakPtrRef(), hero_id] (const a8::Args& args) mutable
|
|
{
|
|
if (hero_ptr.Get() && hero_ptr.Get()->AsHero()->master.Get()) {
|
|
if (!hero_ptr.Get()->room->IsGameOver()) {
|
|
hero_ptr.Get()->AsHero()->master.Get()->RemoveSurplusHero(hero_id, 0);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::SummonHeroSpecDistance()
|
|
{
|
|
int hero_id = meta->_int_buff_param2;
|
|
float distance = meta->GetBuffParam3(this);
|
|
if (!owner->dead || meta->dead_valid() != 0) {
|
|
bool hit_result;
|
|
glm::vec3 hit_point;
|
|
glm::vec3 start = owner->GetPos().ToGlmVec3();
|
|
glm::vec3 end = owner->GetPos().ToGlmVec3() + owner->GetAttackDir() * distance;
|
|
glm::vec3 born_pos = owner->GetPos().ToGlmVec3() + owner->GetAttackDir() * distance;
|
|
owner->room->map_instance->Scale(start);
|
|
owner->room->map_instance->Scale(end);
|
|
if (owner->room->map_instance->Raycast
|
|
(
|
|
start,
|
|
end,
|
|
hit_point,
|
|
hit_result,
|
|
owner->room->map_instance->GetMoveIncludeFlags(),
|
|
owner->room->map_instance->GetMoveExcludeFlags()
|
|
)) {
|
|
owner->room->map_instance->UnScale(hit_point);
|
|
born_pos = hit_point;
|
|
}
|
|
Hero* hero = owner->SummonHero(this,
|
|
born_pos,
|
|
owner->GetAttackDir());
|
|
if (hero) {
|
|
std::shared_ptr<std::vector<float>> vars = std::make_shared<std::vector<float>>();
|
|
vars->push_back(hero->GetUniId());
|
|
for (int buff_id : meta->_buff_param6_int_list) {
|
|
hero->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
vars
|
|
);
|
|
}
|
|
if (meta->_int_buff_param8) {
|
|
owner->GetTrigger()->AddListener
|
|
(
|
|
kDieEvent,
|
|
[hero_ptr = hero->GetWeakPtrRef(), hero_id] (const a8::Args& args) mutable
|
|
{
|
|
if (hero_ptr.Get() && hero_ptr.Get()->AsHero()->master.Get()) {
|
|
if (!hero_ptr.Get()->room->IsGameOver()) {
|
|
hero_ptr.Get()->AsHero()->master.Get()->RemoveSurplusHero(hero_id, 0);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ClearSummonHero()
|
|
{
|
|
int hero_id = meta->_int_buff_param2;
|
|
float hero_num = meta->GetBuffParam3(this);
|
|
owner->RemoveSurplusHero(hero_id, hero_num);
|
|
}
|
|
|
|
void CallFuncBuff::SummonObstacleSpecPoint()
|
|
{
|
|
int id = meta->_int_buff_param2;
|
|
float x = meta->GetBuffParam3(this);
|
|
float y = meta->GetBuffParam4(this);
|
|
float z = meta->GetBuffParam5(this);
|
|
if (!owner->dead || meta->dead_valid() != 0) {
|
|
Obstacle* ob = owner->SummonObstacle(this,
|
|
id,
|
|
glm::vec3(x, y, z),
|
|
owner->GetAttackDir());
|
|
if (ob) {
|
|
if (meta->has_buff_param7()) {
|
|
float rotate = meta->GetBuffParam7(this);
|
|
ob->SetRotate(rotate);
|
|
}
|
|
if (meta->has_buff_param8()) {
|
|
float scale = meta->GetBuffParam8(this);
|
|
ob->scale = scale;
|
|
}
|
|
std::shared_ptr<std::vector<float>> vars = std::make_shared<std::vector<float>>();
|
|
vars->push_back(ob->GetUniId());
|
|
for (int buff_id : meta->_buff_param6_int_list) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
vars
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::SummonObstacleSpecDistance()
|
|
{
|
|
int hero_id = meta->_int_buff_param2;
|
|
float distance = meta->GetBuffParam3(this);
|
|
if (!owner->dead || meta->dead_valid() != 0) {
|
|
bool hit_result;
|
|
glm::vec3 hit_point;
|
|
glm::vec3 start = owner->GetPos().ToGlmVec3();
|
|
glm::vec3 end = owner->GetPos().ToGlmVec3() + owner->GetAttackDir() * distance;
|
|
glm::vec3 born_pos = owner->GetPos().ToGlmVec3() + owner->GetAttackDir() * distance;
|
|
owner->room->map_instance->Scale(start);
|
|
owner->room->map_instance->Scale(end);
|
|
if (owner->room->map_instance->Raycast
|
|
(
|
|
start,
|
|
end,
|
|
hit_point,
|
|
hit_result,
|
|
owner->room->map_instance->GetMoveIncludeFlags(),
|
|
owner->room->map_instance->GetMoveExcludeFlags()
|
|
)) {
|
|
owner->room->map_instance->UnScale(hit_point);
|
|
born_pos = hit_point;
|
|
}
|
|
Obstacle* ob = owner->SummonObstacle(this,
|
|
hero_id,
|
|
born_pos,
|
|
owner->GetAttackDir());
|
|
if (ob) {
|
|
std::shared_ptr<std::vector<float>> vars = std::make_shared<std::vector<float>>();
|
|
vars->push_back(ob->GetUniId());
|
|
for (int buff_id : meta->_buff_param6_int_list) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
vars
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ClearSummonObstacle()
|
|
{
|
|
int id = meta->_int_buff_param2;
|
|
float num = meta->GetBuffParam3(this);
|
|
int obj_uniid = meta->GetBuffParam4(this);
|
|
if (obj_uniid > 0) {
|
|
owner->RemoveSurplusObstacleByUniid(obj_uniid);
|
|
}
|
|
if (id > 0) {
|
|
owner->RemoveSurplusObstacle(id, num);
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::DecSkillCd()
|
|
{
|
|
int skill_id = meta->_int_buff_param2;
|
|
float rate = meta->GetBuffParam3(this);
|
|
Skill* skill = owner->GetSkill(skill_id);
|
|
if (skill) {
|
|
float cd = skill->GetCd();
|
|
float dec_time = skill->GetCd() * rate;
|
|
skill->Accelerate(-dec_time);
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ProcAddMaxHp()
|
|
{
|
|
if (!owner->dead && !owner->downed) {
|
|
owner->SetMaxHP(owner->GetMaxHP() + hold_param2_);
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::SummonCarSpecPoint()
|
|
{
|
|
float delay_time = meta->GetBuffParam2(this);
|
|
int oper_type = meta->GetBuffParam3(this);
|
|
int oper = meta->GetBuffParam4(this);
|
|
int car_id = meta->GetBuffParam5(this);
|
|
float x = meta->GetBuffParam6(this);
|
|
float y = meta->GetBuffParam7(this);
|
|
float z = meta->GetBuffParam8(this);
|
|
std::shared_ptr<std::set<int>> special_operators;
|
|
switch (oper_type) {
|
|
case 1:
|
|
{
|
|
special_operators = std::make_shared<std::set<int>>();
|
|
special_operators->insert(oper);
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
Team* team = owner->room->GetTeam(oper);
|
|
if (team) {
|
|
special_operators = std::make_shared<std::set<int>>();
|
|
team->TraverseMembers
|
|
(
|
|
[special_operators] (Human* hum)
|
|
{
|
|
special_operators->insert(hum->GetUniId());
|
|
return true;
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
owner->room->xtimer.SetTimeoutWpEx
|
|
(
|
|
delay_time / FRAME_RATE_MS,
|
|
[room = owner->room, car_id, x, y, z, special_operators]
|
|
(int event, const a8::Args* args) mutable
|
|
{
|
|
if (a8::TIMER_DELETE_EVENT == event) {
|
|
if (!room->IsGameOver()) {
|
|
const mt::Equip* equip_meta = mt::Equip::GetById(car_id);
|
|
if (equip_meta && equip_meta->equip_type() == EQUIP_TYPE_CAR) {
|
|
int car_uniid = room->AllocUniid();
|
|
Car* c = room->CreateCar(nullptr,
|
|
car_uniid,
|
|
equip_meta,
|
|
glm::vec3(x, y, z),
|
|
0,
|
|
special_operators.get());
|
|
}
|
|
}
|
|
}
|
|
},
|
|
&owner->room->xtimer_attacher_);
|
|
}
|
|
|
|
void CallFuncBuff::RangeHoldBuff()
|
|
{
|
|
InternalRangeHoldBuff
|
|
(
|
|
[this] (glm::vec3& center)
|
|
{
|
|
center = owner->GetPos().ToGlmVec3();
|
|
return true;
|
|
});
|
|
}
|
|
|
|
void CallFuncBuff::PlayFlyEffect()
|
|
{
|
|
if (GetCaster().Get()) {
|
|
owner->room->frame_event.AddPropChgEx
|
|
(GetCaster(),
|
|
kPropFlyEffect,
|
|
meta->_int_buff_param2,
|
|
owner->GetUniId(),
|
|
0,
|
|
0,
|
|
0);
|
|
}
|
|
owner->TryAddBuff(GetCaster().Get(), meta->_int_buff_param4, skill_meta);
|
|
}
|
|
|
|
void CallFuncBuff::LispEval()
|
|
{
|
|
for (int i = 1; i <= 8; ++i) {
|
|
switch (i) {
|
|
case 1:
|
|
{
|
|
if (!meta->buff_param1().empty()) {
|
|
meta->GetBuffParam1(this);
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
if (!meta->buff_param2().empty()) {
|
|
meta->GetBuffParam2(this);
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
if (!meta->buff_param3().empty()) {
|
|
meta->GetBuffParam3(this);
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
{
|
|
if (!meta->buff_param4().empty()) {
|
|
meta->GetBuffParam4(this);
|
|
}
|
|
}
|
|
break;
|
|
case 5:
|
|
{
|
|
if (!meta->buff_param5().empty()) {
|
|
meta->GetBuffParam5(this);
|
|
}
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
if (!meta->buff_param6().empty()) {
|
|
meta->GetBuffParam6(this);
|
|
}
|
|
}
|
|
break;
|
|
case 7:
|
|
{
|
|
if (!meta->buff_param7().empty()) {
|
|
meta->GetBuffParam7(this);
|
|
}
|
|
}
|
|
break;
|
|
case 8:
|
|
{
|
|
if (!meta->buff_param8().empty()) {
|
|
meta->GetBuffParam8(this);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::SpecCenterRangeHoldBuff()
|
|
{
|
|
glm::vec3 init_center = glm::vec3
|
|
(
|
|
meta->GetBuffParam6(this),
|
|
meta->GetBuffParam7(this),
|
|
meta->GetBuffParam8(this)
|
|
);
|
|
#ifdef MYDEBUG
|
|
if (owner->IsPlayer()) {
|
|
a8::XPrintf("init_center:%f %f %f\n",
|
|
{
|
|
init_center.x,
|
|
init_center.y,
|
|
init_center.z,
|
|
}
|
|
);
|
|
}
|
|
#endif
|
|
InternalRangeHoldBuff
|
|
(
|
|
[this, init_center] (glm::vec3& center)
|
|
{
|
|
center = init_center;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
void CallFuncBuff::InternalRangeHoldBuff(std::function<bool(glm::vec3&)> get_center_func)
|
|
{
|
|
int buff_id = meta->buff_id();
|
|
if (owner->dead && !meta->dead_valid()) {
|
|
return;
|
|
}
|
|
struct InnerObject
|
|
{
|
|
CreatureWeakPtr c;
|
|
std::vector<int> buff_uniids;
|
|
|
|
void OnEnter()
|
|
{
|
|
|
|
}
|
|
|
|
void OnLeave()
|
|
{
|
|
}
|
|
|
|
};
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::map<int, InnerObject> in_human_infos;
|
|
);
|
|
|
|
auto on_enter =
|
|
[this, context] (Creature* hum)
|
|
{
|
|
if (context->in_human_infos.find(hum->GetUniId()) != context->in_human_infos.end()) {
|
|
abort();
|
|
}
|
|
InnerObject o;
|
|
o.c = hum->GetWeakPtrRef();
|
|
|
|
if (meta->buff_id() == 203032) {
|
|
int i = 0;
|
|
#ifdef MYDEBUG
|
|
a8::XPrintf("aaaaaaaaaaaa a_team_id:%d b_team_id:%d\n",
|
|
{
|
|
owner->team_id,
|
|
hum->team_id
|
|
});
|
|
#endif
|
|
}
|
|
|
|
if (owner->team_id == hum->team_id) {
|
|
for (int buff_id : meta->_buff_param4_int_list) {
|
|
o.buff_uniids.push_back(hum->TryAddBuff(GetCaster().Get(), buff_id, skill_meta));
|
|
}
|
|
} else {
|
|
for (int buff_id : meta->_buff_param3_int_list) {
|
|
o.buff_uniids.push_back(hum->TryAddBuff(GetCaster().Get(), buff_id, skill_meta));
|
|
}
|
|
}
|
|
|
|
context->in_human_infos[hum->GetUniId()] = o;
|
|
context->in_human_infos[hum->GetUniId()].OnEnter();
|
|
};
|
|
auto on_stay =
|
|
[this, context] (Creature* hum)
|
|
{
|
|
};
|
|
auto on_leave =
|
|
[this, context] (Creature* hum)
|
|
{
|
|
auto itr = context->in_human_infos.find(hum->GetUniId());
|
|
if (itr == context->in_human_infos.end()) {
|
|
abort();
|
|
}
|
|
for (int buff_uniid : itr->second.buff_uniids) {
|
|
hum->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
itr->second.OnLeave();
|
|
};
|
|
auto check_cb =
|
|
[this, context, on_enter, on_stay, on_leave, get_center_func]
|
|
()
|
|
{
|
|
float range = meta->GetBuffParam2(this);
|
|
std::set<Creature*> hit_humans;
|
|
glm::vec3 center;
|
|
if (get_center_func(center)) {
|
|
std::set<GridCell*> grid_list;
|
|
owner->room->grid_service->GetAllCellsByXy
|
|
(
|
|
owner->room,
|
|
center.x,
|
|
center.z,
|
|
grid_list);
|
|
owner->room->grid_service->TraverseCreatures
|
|
(owner->room->GetRoomIdx(),
|
|
grid_list,
|
|
[this, range, &hit_humans, ¢er] (Creature* c, bool& stop)
|
|
{
|
|
if (!c->dead && c->IsHuman() && a8::IntersectCylinderCylinder
|
|
(
|
|
center, owner->GetRadius(), 10,
|
|
c->GetPos().ToGlmVec3(), range, 10
|
|
)) {
|
|
hit_humans.insert(c);
|
|
}
|
|
});
|
|
}
|
|
std::vector<Human*> leave_humans;
|
|
for (auto& pair : context->in_human_infos) {
|
|
if (hit_humans.find(pair.second.c.Get()) == hit_humans.end()) {
|
|
on_leave(pair.second.c.Get()->AsHuman());
|
|
leave_humans.push_back(pair.second.c.Get()->AsHuman());
|
|
}
|
|
}
|
|
for (Human* hum : leave_humans) {
|
|
context->in_human_infos.erase(hum->GetUniId());
|
|
}
|
|
for (Creature* hum : hit_humans) {
|
|
if (context->in_human_infos.find(hum->GetUniId()) ==
|
|
context->in_human_infos.end()) {
|
|
on_enter(hum);
|
|
on_stay(hum);
|
|
} else {
|
|
on_stay(hum);
|
|
}
|
|
}
|
|
};
|
|
auto check_timer = owner->room->xtimer.SetIntervalWpEx
|
|
(
|
|
SERVER_FRAME_RATE,
|
|
[this, context, on_enter, on_stay, on_leave, check_cb]
|
|
(int event, const a8::Args* args) mutable
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (meta->buff_id() == 303013) {
|
|
int i = 0;
|
|
}
|
|
check_cb();
|
|
}
|
|
},
|
|
&owner->xtimer_attacher);
|
|
auto clear_func =
|
|
[this, context, check_timer] () mutable
|
|
{
|
|
if (!check_timer.expired()) {
|
|
owner->room->xtimer.Delete(check_timer);
|
|
}
|
|
for (auto& pair : context->in_human_infos) {
|
|
for (int buff_uniid : pair.second.buff_uniids) {
|
|
if (pair.second.c.Get()) {
|
|
pair.second.c.Get()->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
}
|
|
}
|
|
context->in_human_infos.clear();
|
|
};
|
|
{
|
|
if (!meta->dead_valid()) {
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kDieEvent,
|
|
[this, clear_func] (const a8::Args& args) mutable
|
|
{
|
|
clear_func();
|
|
}
|
|
));
|
|
}
|
|
deactivate_cb_ =
|
|
[this, clear_func] () mutable
|
|
{
|
|
clear_func();
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
void CallFuncBuff::ThrowKnife()
|
|
{
|
|
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, glm::radians((float)meta->_buff_param4_int_list[i]));
|
|
Position bullet_born_pos = owner->GetPos();
|
|
bullet_born_pos.AddGlmVec3(bullet_dir * meta->_buff_param3);
|
|
int bullet_uniid = owner->room->AllocUniid();
|
|
int shot_uniid = 0;
|
|
owner->room->frame_event.AddBullet
|
|
(bullet_uniid,
|
|
owner->GetWeakPtrRef(),
|
|
weapon_meta,
|
|
1,
|
|
bullet_born_pos.ToGlmVec3(),
|
|
bullet_dir,
|
|
0,
|
|
0,
|
|
0,
|
|
nullptr,
|
|
shot_uniid);
|
|
auto p = std::make_shared<VirtualBullet>();
|
|
p->bullet_uniid = bullet_uniid;
|
|
//p->weapon_uniid = bullet->weapon_uniid;
|
|
//p->skill_meta = bullet->skill_meta;
|
|
p->gun_meta = weapon_meta;
|
|
p->bullet_meta = weapon_meta;
|
|
p->sender = owner->GetWeakPtrRef();
|
|
//p->passenger = bullet->passenger;
|
|
p->room = owner->room;
|
|
//p->is_pre_battle_bullet = bullet->IsPreBattleBullet();
|
|
p->dir = bullet_dir;
|
|
p->born_pos = bullet_born_pos;
|
|
p->born_dir = bullet_dir;
|
|
p->shot_uniid = shot_uniid;
|
|
p->Init();
|
|
owner->room->AddTask(bullet_uniid, std::make_shared<a8::CommonCbProcEx>
|
|
(
|
|
[p] (const a8::Args* args)
|
|
{
|
|
if (!p->IsDone()) {
|
|
p->Update(50);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::AccumulatePower()
|
|
{
|
|
owner->room->xtimer.SetTimeoutEx
|
|
(
|
|
std::max((long long)0, owner->room->xtimer.GetRemainTime(remover_timer) - 1),
|
|
[this] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
const mt::Equip* equip_meta = mt::Equip::GetById(meta->GetBuffParam2(this));
|
|
if (equip_meta) {
|
|
if (!owner->dead && owner->downed) {
|
|
InternalShot(owner,
|
|
owner->GetCurrWeapon()->meta,
|
|
equip_meta,
|
|
skill_meta,
|
|
0,
|
|
owner->GetCurrWeapon()->weapon_uniid,
|
|
0);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
&xtimer_attacher);
|
|
}
|
|
|
|
void CallFuncBuff::Shot()
|
|
{
|
|
int id = meta->GetBuffParam2(this);
|
|
float x = meta->GetBuffParam3(this);
|
|
float y = meta->GetBuffParam4(this);
|
|
float z = meta->GetBuffParam5(this);
|
|
int duration = meta->GetBuffParam8(this);
|
|
const mt::Equip* gun_meta = mt::Equip::GetById(id);
|
|
if (gun_meta) {
|
|
const mt::Equip* bullet_meta = mt::Equip::GetById(gun_meta->use_bullet());
|
|
if (!bullet_meta) {
|
|
return;
|
|
}
|
|
bool force_client_report = meta->_buff_param6_int_set.find(1) != meta->_buff_param6_int_set.end();
|
|
bool spec_target_pos = meta->_buff_param6_int_set.find(2) != meta->_buff_param6_int_set.end();
|
|
bool ignore_original_dmg = meta->_buff_param6_int_set.find(3) != meta->_buff_param6_int_set.end();
|
|
bool no_adjust_attack_dir = meta->_buff_param6_int_set.find(4) != meta->_buff_param6_int_set.end();
|
|
|
|
if (force_client_report) {
|
|
owner->GetAbility()->IncSwitch(kForceClientReportBullet);
|
|
}
|
|
if (ignore_original_dmg) {
|
|
owner->GetAbility()->IncSwitch(kIgnoreOriginalDmg);
|
|
}
|
|
CreatureWeakPtr owner_wp = owner->GetWeakPtrRef();
|
|
int buff_uniid_copy = buff_uniid;
|
|
auto meta_copy = meta;
|
|
auto on_bullet_exit =
|
|
[owner_wp, buff_uniid_copy, meta_copy] (Bullet* bullet) mutable
|
|
{
|
|
if (owner_wp.Get() && !owner_wp.Get()->IsDestorying()) {
|
|
std::shared_ptr<std::vector<float>> vars = std::make_shared<std::vector<float>>();
|
|
vars->push_back(bullet->GetPos().GetX());
|
|
vars->push_back(bullet->GetPos().GetY());
|
|
vars->push_back(bullet->GetPos().GetZ());
|
|
for (int buff_id : meta_copy->_buff_param7_int_list) {
|
|
owner_wp.Get()->TryAddBuff(
|
|
owner_wp.Get(),
|
|
buff_id,
|
|
bullet->skill_meta,
|
|
nullptr,
|
|
vars
|
|
);
|
|
}
|
|
}
|
|
};
|
|
glm::vec3 old_attack_dir = owner->GetAttackDir();
|
|
#ifdef MYDEBUG
|
|
a8::XPrintf("buff.call_shot target_pos:%f %f %f attack_dir:%f %f %f\n",
|
|
{
|
|
x,
|
|
y,
|
|
z,
|
|
owner->GetAttackDir().x,
|
|
owner->GetAttackDir().y,
|
|
owner->GetAttackDir().z,
|
|
});
|
|
#endif
|
|
if (spec_target_pos) {
|
|
glm::vec3 target_pos = glm::vec3(x, y, z);
|
|
glm::vec3 attack_dir = target_pos - owner->GetPos().ToGlmVec3();
|
|
float fly_distance = 0.0f;
|
|
if (GlmHelper::IsZero(attack_dir)) {
|
|
if (GlmHelper::IsZero(owner->GetAttackDir())) {
|
|
owner->SetAttackDir(GlmHelper::UP);
|
|
}
|
|
attack_dir = owner->GetAttackDir();
|
|
} else {
|
|
GlmHelper::Normalize(attack_dir);
|
|
fly_distance = GlmHelper::Norm2D(target_pos - owner->GetPos().ToGlmVec3());
|
|
owner->SetAttackDir(attack_dir);
|
|
}
|
|
fly_distance = std::max(200.0f, fly_distance);
|
|
fly_distance = std::min(400.0f, fly_distance);
|
|
InternalShot(owner,
|
|
gun_meta,
|
|
bullet_meta,
|
|
skill_meta,
|
|
fly_distance,
|
|
owner->GetCurrWeapon()->weapon_uniid,
|
|
0,
|
|
on_bullet_exit,
|
|
duration);
|
|
} else {
|
|
InternalShot(owner,
|
|
owner->GetCurrWeapon()->meta,
|
|
owner->GetCurrWeapon()->bullet_meta,
|
|
skill_meta,
|
|
0,
|
|
owner->GetCurrWeapon()->weapon_uniid,
|
|
0,
|
|
on_bullet_exit,
|
|
duration);
|
|
}
|
|
if (force_client_report) {
|
|
owner->GetAbility()->DecSwitch(kForceClientReportBullet);
|
|
}
|
|
if (ignore_original_dmg) {
|
|
owner->GetAbility()->DecSwitch(kIgnoreOriginalDmg);
|
|
}
|
|
if (!no_adjust_attack_dir) {
|
|
owner->SetAttackDir(old_attack_dir);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::BatchRandomPosSummonObstacle()
|
|
{
|
|
int id = meta->GetBuffParam2(this);
|
|
int num = meta->GetBuffParam3(this);
|
|
float x = meta->GetBuffParam4(this);
|
|
float y = meta->GetBuffParam5(this);
|
|
float z = meta->GetBuffParam6(this);
|
|
float range = meta->GetBuffParam7(this);
|
|
if (!owner->dead || meta->dead_valid() != 0 && num > 0) {
|
|
num = std::min(30, num);
|
|
glm::vec3 center = glm::vec3(x, y, z);
|
|
for (int i = 0; i < num; ++i) {
|
|
glm::vec3 out_point = center;
|
|
bool ret = owner->room->map_instance->RandPoint(center, range, out_point);
|
|
if (ret) {
|
|
Obstacle* ob = owner->SummonObstacle(this,
|
|
id,
|
|
out_point,
|
|
owner->GetAttackDir());
|
|
if (ob) {
|
|
std::shared_ptr<std::vector<float>> vars = std::make_shared<std::vector<float>>();
|
|
vars->push_back(ob->GetUniId());
|
|
vars->push_back(ob->GetPos().GetX());
|
|
vars->push_back(ob->GetPos().GetY());
|
|
vars->push_back(ob->GetPos().GetZ());
|
|
for (int buff_id : meta->_buff_param8_int_list) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
vars
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::OnBreakSkill()
|
|
{
|
|
|
|
}
|
|
|
|
void CallFuncBuff::BreakSkill()
|
|
{
|
|
Buff* selected_buff = nullptr;
|
|
for (auto buff_id : meta->_buff_param2_int_list) {
|
|
selected_buff = owner->GetBuffById(buff_id);
|
|
if (selected_buff) {
|
|
break;
|
|
}
|
|
}
|
|
if (selected_buff) {
|
|
a8::Args args({this});
|
|
selected_buff->PreExec(&args);
|
|
int buff_uniid = selected_buff->buff_uniid;
|
|
for (auto buff_id : meta->_buff_param3_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
if (selected_buff) {
|
|
selected_buff->PostExec(&args);
|
|
owner->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
} else {
|
|
for (auto buff_id : meta->_buff_param4_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::BuffEffectCondAdd()
|
|
{
|
|
Buff* selected_buff = nullptr;
|
|
for (auto buff_effect : meta->_buff_param2_int_list) {
|
|
selected_buff = owner->GetBuffByEffectId(buff_effect);
|
|
if (selected_buff) {
|
|
break;
|
|
}
|
|
}
|
|
if (selected_buff) {
|
|
for (auto buff_id : meta->_buff_param3_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
selected_buff = owner->GetBuffByUniId(buff_uniid);
|
|
} else {
|
|
for (auto buff_id : meta->_buff_param4_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::PreExec(const a8::Args* args)
|
|
{
|
|
switch ((BuffCallFunc_e)meta->_int_buff_param1) {
|
|
case BuffCallFunc_e::kOnBreakSkill:
|
|
{
|
|
OnBreakSkillPreExec();
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::PostExec(const a8::Args* args)
|
|
{
|
|
switch ((BuffCallFunc_e)meta->_int_buff_param1) {
|
|
case BuffCallFunc_e::kOnBreakSkill:
|
|
{
|
|
OnBreakSkillPostExec();
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::OnBreakSkillPreExec()
|
|
{
|
|
for (auto buff_id : meta->_buff_param2_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::OnBreakSkillPostExec()
|
|
{
|
|
for (auto buff_id : meta->_buff_param3_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::RandAdd()
|
|
{
|
|
int buff_id = meta->buff_id();
|
|
hold_param2_ = meta->GetBuffParam2(this) * 100;
|
|
if (hold_param2_ >= a8::RandEx(0, 100)) {
|
|
for (auto buff_id : meta->_buff_param3_int_list) {
|
|
if (buff_id > 0) {
|
|
owner->TryAddBuff(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta,
|
|
init_args,
|
|
buff_vars
|
|
);
|
|
} else {
|
|
owner->RemoveBuffById(-buff_id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::ShowExplosion()
|
|
{
|
|
if (owner->dead && !meta->dead_valid()) {
|
|
return;
|
|
}
|
|
int explosion_effect = meta->GetBuffParam2(this);
|
|
float x = meta->GetBuffParam3(this);
|
|
float y = meta->GetBuffParam4(this);
|
|
float z = meta->GetBuffParam5(this);
|
|
Position center;
|
|
center.FromGlmVec3(glm::vec3(x, y, z));
|
|
owner->room->frame_event.AddExplosionEx
|
|
(owner->GetWeakPtrRef(),
|
|
0,
|
|
center,
|
|
explosion_effect,
|
|
0);
|
|
}
|
|
|
|
void CallFuncBuff::AddArmorShield()
|
|
{
|
|
if (!owner->dead && !owner->downed) {
|
|
float dur_time = meta->GetBuffParam3(this);
|
|
if (dur_time < 0.00001f) {
|
|
dur_time = 99999999;
|
|
}
|
|
if (owner->armor_shield > 0) {
|
|
is_valid_ = false;
|
|
#if 0
|
|
owner->GetTrigger()->UpdateArmorShield(hold_param2_, dur_time);
|
|
#endif
|
|
} else {
|
|
owner->AddArmorShield(hold_param2_);
|
|
#if 0
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kUpdateArmorShieldEvent,
|
|
[this] (const a8::Args& args) mutable
|
|
{
|
|
int value = args.Get<int>(0);
|
|
int new_time = args.Get<int>(1);
|
|
owner->AddArmorShield(value);
|
|
}));
|
|
event_handlers_.push_back(owner->GetTrigger()->AddListener
|
|
(
|
|
kDestoryArmorShieldEvent,
|
|
[this] (const a8::Args& args) mutable
|
|
{
|
|
owner->RemoveBuffByUniId(buff_uniid);
|
|
}));
|
|
#endif
|
|
owner->room->xtimer.SetTimeoutWpEx
|
|
(
|
|
dur_time / FRAME_RATE_MS,
|
|
[owner = owner, buff_uniid = buff_uniid] (int event, const a8::Args* args) mutable
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
owner->ClearArmorShield();
|
|
owner->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
},
|
|
&owner->xtimer_attacher);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallFuncBuff::BulletDmgCalcProc()
|
|
{
|
|
int target_type = (int)hold_param2_;
|
|
if (target_type == 0 || target_type == 1) {
|
|
if (!owner->dead && !owner->downed) {
|
|
int attr_id = meta->GetBuffParam3(this);
|
|
float attr_val = meta->GetBuffParam4(this);
|
|
float cond = meta->GetBuffParam5(this);
|
|
AttrHandle attr_handle;
|
|
auto clear_func =
|
|
[this, target_type, &attr_handle] (Creature* c)
|
|
{
|
|
if (target_type == 0) {
|
|
owner->GetAbility()->RemoveAttr(attr_handle);
|
|
} else if (target_type == 1) {
|
|
c->GetAbility()->RemoveAttr(attr_handle);
|
|
}
|
|
};
|
|
auto start_handle = owner->GetTrigger()->AddListener
|
|
(
|
|
kBulletDmgStartEvent,
|
|
[this, &attr_handle, target_type, attr_id, attr_val, cond, clear_func]
|
|
(const a8::Args& args) mutable
|
|
{
|
|
Creature* target = args.Get<Creature*>(0);
|
|
clear_func(target);
|
|
if (IsValidHumanAttr(attr_id) ||
|
|
IsValidHumanVirtualAttr(attr_id)) {
|
|
if (target->GetMaxHP() > 0.0f) {
|
|
bool match = target->GetHP() / target->GetMaxHP() < cond;
|
|
if (match) {
|
|
if (target_type == 0) {
|
|
attr_handle = owner->GetAbility()->AddAttr(attr_id, attr_val);
|
|
} else if (target_type == 1) {
|
|
attr_handle = target->GetAbility()->AddAttr(attr_id, attr_val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
auto end_handle = owner->GetTrigger()->AddListener
|
|
(
|
|
kBulletDmgEndEvent,
|
|
[this, clear_func] (const a8::Args& args) mutable
|
|
{
|
|
Creature* target = args.Get<Creature*>(0);
|
|
clear_func(target);
|
|
});
|
|
deactivate_cb_ =
|
|
[this, start_handle, end_handle, clear_func] () mutable
|
|
{
|
|
owner->GetTrigger()->RemoveEventHandler(start_handle);
|
|
owner->GetTrigger()->RemoveEventHandler(end_handle);
|
|
};
|
|
}
|
|
}
|
|
}
|