This commit is contained in:
aozhiwei 2023-11-08 15:56:22 +08:00
parent c9d024e54e
commit 9a460eecba
2 changed files with 164 additions and 138 deletions

View File

@ -1,5 +1,7 @@
#include "precompile.h"
#include <a8/collision.h>
#include "buff/callfunc.h"
#include "creature.h"
@ -183,6 +185,11 @@ void CallFuncBuff::Activate()
PlayFlyEffect();
}
break;
case BuffCallFunc_e::kSpecCenterRangeHoldBuff:
{
SpecCenterRangeHoldBuff();
}
break;
default:
{
}
@ -992,145 +999,7 @@ void CallFuncBuff::SummonCarSpecPoint()
void CallFuncBuff::RangeHoldBuff()
{
if (owner->dead) {
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 (owner->team_id == hum->team_id) {
for (int buff_id : meta->_buff_param3_int_list) {
o.buff_uniids.push_back(hum->TryAddBuff(GetCaster().Get(), buff_id, skill_meta));
}
} else {
for (int buff_id : meta->_buff_param4_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]
()
{
float range = meta->GetBuffParam2(this);
std::set<Creature*> hit_humans;
owner->room->TraverseAliveHumanList
(
[this, range, &hit_humans] (Human* hum) mutable
{
if (Collision::CheckCC(owner, owner->GetRadius(),
hum, range)) {
hit_humans.insert(hum);
}
return true;
});
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) {
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();
};
{
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::PlayFlyEffect()
@ -1215,3 +1084,156 @@ void CallFuncBuff::LispEval()
}
}
}
void CallFuncBuff::SpecCenterRangeHoldBuff()
{
}
void CallFuncBuff::InternalRangeHoldBuff(std::function<bool(glm::vec3&)> get_center_func)
{
if (owner->dead) {
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 (owner->team_id == hum->team_id) {
for (int buff_id : meta->_buff_param3_int_list) {
o.buff_uniids.push_back(hum->TryAddBuff(GetCaster().Get(), buff_id, skill_meta));
}
} else {
for (int buff_id : meta->_buff_param4_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;
owner->room->TraverseAliveHumanList
(
[this, range, &hit_humans, &get_center_func] (Human* hum) mutable
{
glm::vec3 center;
if (get_center_func(center)) {
if (a8::IntersectCylinderCylinder
(
center, owner->GetRadius(), 10,
hum->GetPos().ToGlmVec3(), range, 10
)) {
hit_humans.insert(hum);
}
}
return true;
});
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) {
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();
};
{
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();
};
}
}

View File

@ -34,6 +34,7 @@ A8_DECLARE_CLASS_ENUM(BuffCallFunc_e, int,
kRangeHoldBuff = 34,
kPlayFlyEffect = 35,
kLispEval = 36,
kSpecCenterRangeHoldBuff = 37,
);
@ -67,6 +68,9 @@ class CallFuncBuff : public Buff
void RangeHoldBuff();
void PlayFlyEffect();
void LispEval();
void SpecCenterRangeHoldBuff();
void InternalRangeHoldBuff(std::function<bool(glm::vec3&)> get_center_func);
float hold_param2_ = 0.0;
Weapon* hold_weapon_ = nullptr;