375 lines
12 KiB
C++
375 lines
12 KiB
C++
#include "precompile.h"
|
|
|
|
#include <a8/holder.h>
|
|
|
|
#include "buff/cond_add.h"
|
|
|
|
#include "creature.h"
|
|
#include "room.h"
|
|
|
|
#include "mt/Buff.h"
|
|
|
|
/*
|
|
装备武器
|
|
子弹命中
|
|
击杀
|
|
子弹结束
|
|
*/
|
|
|
|
void CondAddBuff::Activate()
|
|
{
|
|
switch ((CondAddBuff_e)meta->_int_buff_param1) {
|
|
case CondAddBuff_e::kBulletHit:
|
|
{
|
|
ProcBulletHit();
|
|
}
|
|
break;
|
|
case CondAddBuff_e::kBulletKill:
|
|
{
|
|
ProcBulletKill();
|
|
}
|
|
break;
|
|
case CondAddBuff_e::kBulletEnd:
|
|
{
|
|
ProcBulletEnd();
|
|
}
|
|
break;
|
|
case CondAddBuff_e::kDisengageBattle:
|
|
{
|
|
ProcDisengageBattle();
|
|
}
|
|
break;
|
|
case CondAddBuff_e::kLimitTimeKillTarget:
|
|
{
|
|
ProcLimitTimeKillTarget();
|
|
}
|
|
break;
|
|
case CondAddBuff_e::kReload:
|
|
{
|
|
ProcReload();
|
|
}
|
|
break;
|
|
case CondAddBuff_e::kShot:
|
|
{
|
|
ProcShot();
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CondAddBuff::Deactivate()
|
|
{
|
|
}
|
|
|
|
void CondAddBuff::ProcBulletHit()
|
|
{
|
|
const bool is_same_target = meta->_int_buff_param5 ? true : false;
|
|
const float interval_time = meta->_buff_param6 < 0.01 ? 9999999 : meta->_buff_param6;
|
|
const int hit_times = meta->_int_buff_param2;
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
int last_hit_target_id = 0;
|
|
int hited_times = 0;
|
|
long long last_hit_frameno = 0;
|
|
);
|
|
|
|
event_handlers_.push_back
|
|
(
|
|
owner->GetTrigger()->AddListener
|
|
(
|
|
kBulletHitEvent,
|
|
[this, context, is_same_target, interval_time, hit_times]
|
|
(const a8::Args& args)
|
|
{
|
|
IBullet* bullet = args.Get<IBullet*>(0);
|
|
Creature* c = args.Get<Creature*>(1);
|
|
if (context->last_hit_frameno > 0 &&
|
|
c->room->GetFrameNo() - context->last_hit_frameno > interval_time * SERVER_FRAME_RATE) {
|
|
context->hited_times = 0;
|
|
}
|
|
if (is_same_target) {
|
|
if (context->last_hit_target_id != c->GetUniId()) {
|
|
context->hited_times = 0;
|
|
}
|
|
}
|
|
context->last_hit_target_id = c->GetUniId();
|
|
++context->hited_times;
|
|
context->last_hit_frameno = c->room->GetFrameNo();
|
|
if (context->hited_times >= hit_times) {
|
|
{
|
|
if (!c->dead) {
|
|
c->TryAddBuff(owner, meta->_int_buff_param3, skill_meta);
|
|
}
|
|
if (!owner->dead) {
|
|
owner->TryAddBuff(owner, meta->_int_buff_param4, skill_meta);
|
|
}
|
|
}
|
|
context->last_hit_target_id = 0;
|
|
context->hited_times = 0;
|
|
context->last_hit_frameno = 0;
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
void CondAddBuff::ProcBulletKill()
|
|
{
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
);
|
|
|
|
event_handlers_.push_back
|
|
(
|
|
owner->GetTrigger()->AddListener
|
|
(
|
|
kBulletKill,
|
|
[this, context]
|
|
(const a8::Args& args)
|
|
{
|
|
IBullet* bullet = args.Get<IBullet*>(0);
|
|
Creature* c = args.Get<Creature*>(1);
|
|
if (!owner->dead) {
|
|
owner->TryAddBuff(owner, meta->_int_buff_param4, skill_meta);
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
void CondAddBuff::ProcBulletEnd()
|
|
{
|
|
|
|
}
|
|
|
|
void CondAddBuff::ProcDisengageBattle()
|
|
{
|
|
const float disengate_time = meta->GetBuffParam2(this);
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::vector<std::tuple<int, int>> hold_buff_list;
|
|
long long last_check_frameno = 0;
|
|
bool handled = false;
|
|
);
|
|
|
|
a8::XTimerWp timer = owner->room->xtimer.SetIntervalWpEx
|
|
(
|
|
disengate_time * SERVER_FRAME_RATE,
|
|
[this, context] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (!owner->dead && !context->handled) {
|
|
for (int buff_id : meta->_buff_param4_int_list) {
|
|
int buff_uniid = owner->TryAddBuff
|
|
(
|
|
GetCaster().Get(),
|
|
buff_id,
|
|
skill_meta
|
|
);
|
|
if (!meta->_buff_param5_int_set.empty()) {
|
|
context->hold_buff_list.push_back
|
|
(
|
|
std::make_tuple(buff_uniid, buff_id)
|
|
);
|
|
}
|
|
}
|
|
if (owner->room->GetFrameNo() - context->last_check_frameno > SERVER_FRAME_RATE * 10 &&
|
|
!meta->_buff_param5_int_set.empty() &&
|
|
context->hold_buff_list.size() > 0) {
|
|
for (int i = context->hold_buff_list.size() - 1; i >= 0; --i) {
|
|
if (!owner->GetBuffByUniId(std::get<0>(context->hold_buff_list[i]))) {
|
|
context->hold_buff_list.erase(context->hold_buff_list.begin() + i);
|
|
}
|
|
}
|
|
}
|
|
context->handled = true;
|
|
}
|
|
}
|
|
},
|
|
&xtimer_attacher);
|
|
|
|
auto cb =
|
|
[this, timer, context] (const a8::Args& args) mutable
|
|
{
|
|
if (timer.expired()) {
|
|
return;
|
|
}
|
|
if (!meta->_buff_param5_int_set.empty() &&
|
|
!context->hold_buff_list.empty()) {
|
|
for (auto& tuple : context->hold_buff_list) {
|
|
if (meta->_buff_param5_int_set.find(std::get<1>(tuple)) !=
|
|
meta->_buff_param5_int_set.end()) {
|
|
owner->RemoveBuffByUniId(std::get<0>(tuple));
|
|
}
|
|
}
|
|
context->hold_buff_list.clear();
|
|
}
|
|
context->handled = false;
|
|
owner->room->xtimer.ResetTimer(timer);
|
|
};
|
|
|
|
event_handlers_.push_back
|
|
(owner->GetTrigger()->AddListener
|
|
(
|
|
kReceiveDmgEvent,
|
|
cb
|
|
)
|
|
);
|
|
}
|
|
|
|
void CondAddBuff::ProcLimitTimeKillTarget()
|
|
{
|
|
const float time_limit = meta->GetBuffParam2(this);
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::map<int, std::tuple<a8::XTimerWp, std::weak_ptr<EventHandlerPtr>>> watch_targets;
|
|
);
|
|
|
|
auto holder = std::make_shared<a8::Holder>
|
|
(
|
|
[owner = owner->GetWeakPtrRef(), context] (const a8::Args& args) mutable
|
|
{
|
|
if (owner.Get() && !owner.Get()->room->IsDestorying()) {
|
|
for (auto& pair : context->watch_targets) {
|
|
owner.Get()->GetTrigger()->RemoveEventHandler(std::get<1>(pair.second));
|
|
}
|
|
}
|
|
});
|
|
|
|
auto cb =
|
|
[this, context, time_limit, holder] (const a8::Args& args) mutable
|
|
{
|
|
Creature* target = args.Get<Creature*>(0);
|
|
if (!target->dead) {
|
|
auto itr = context->watch_targets.find(target->GetUniId());
|
|
if (itr != context->watch_targets.end()) {
|
|
owner->room->xtimer.ResetTimer(std::get<0>(itr->second));
|
|
} else {
|
|
int target_uniid = target->GetUniId();
|
|
auto timer_wp = owner->room->xtimer.SetTimeoutWpEx
|
|
(
|
|
time_limit * SERVER_FRAME_RATE,
|
|
[this, context, target_uniid] (int event, const a8::Args* args)
|
|
{
|
|
auto itr = context->watch_targets.find(target_uniid);
|
|
if (itr != context->watch_targets.end()) {
|
|
Entity* e = owner->room->GetEntityByUniId(target_uniid);
|
|
if (e && e->IsCreature(owner->room)) {
|
|
Creature* c = (Creature*)e;
|
|
c->GetTrigger()->RemoveEventHandler(std::get<1>(itr->second));
|
|
}
|
|
context->watch_targets.erase(itr);
|
|
}
|
|
},
|
|
&xtimer_attacher);
|
|
auto handler = target->GetTrigger()->AddListener
|
|
(
|
|
kDieEvent,
|
|
[this, context, target_uniid] (const a8::Args& args)
|
|
{
|
|
if (owner->dead) {
|
|
return;
|
|
}
|
|
auto itr = context->watch_targets.find(target_uniid);
|
|
if (itr != context->watch_targets.end()) {
|
|
Entity* e = owner->room->GetEntityByUniId(target_uniid);
|
|
if (e && e->IsCreature(owner->room)) {
|
|
Creature* c = (Creature*)e;
|
|
auto buff_vars = std::make_shared<std::vector<float>>();
|
|
buff_vars->push_back(target_uniid);
|
|
owner->TryAddBuff(GetCaster().Get(),
|
|
meta->_int_buff_param4,
|
|
skill_meta,
|
|
nullptr,
|
|
buff_vars);
|
|
std::weak_ptr<EventHandlerPtr> handler = std::get<1>(itr->second);
|
|
context->watch_targets.erase(itr);
|
|
c->GetTrigger()->RemoveEventHandler(handler);
|
|
} else {
|
|
context->watch_targets.erase(itr);
|
|
}
|
|
}
|
|
});
|
|
event_handlers_.push_back(handler);
|
|
context->watch_targets[target->GetUniId()] = std::make_tuple(timer_wp, handler);
|
|
}
|
|
}
|
|
};
|
|
|
|
event_handlers_.push_back
|
|
(owner->GetTrigger()->AddListener
|
|
(
|
|
kAttackTargetEvent,
|
|
cb
|
|
)
|
|
);
|
|
}
|
|
|
|
void CondAddBuff::ProcReload()
|
|
{
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::vector<int> buffs;
|
|
);
|
|
|
|
event_handlers_.push_back
|
|
(owner->GetTrigger()->AddListener
|
|
(
|
|
kStartReloadEvent,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
if (!owner->dead) {
|
|
int buff_uniid = owner->TryAddBuff(GetCaster().Get(),
|
|
meta->_int_buff_param4,
|
|
skill_meta,
|
|
nullptr,
|
|
buff_vars);
|
|
if (buff_uniid > 0) {
|
|
context->buffs.push_back(buff_uniid);
|
|
}
|
|
}
|
|
}
|
|
)
|
|
);
|
|
|
|
event_handlers_.push_back
|
|
(owner->GetTrigger()->AddListener
|
|
(
|
|
kEndReloadEvent,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
for (int buff_uniid : context->buffs) {
|
|
owner->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
context->buffs.clear();
|
|
}
|
|
)
|
|
);
|
|
|
|
}
|
|
|
|
void CondAddBuff::ProcShot()
|
|
{
|
|
event_handlers_.push_back
|
|
(owner->GetTrigger()->AddListener
|
|
(
|
|
kShotEvent,
|
|
[this] (const a8::Args& args) mutable
|
|
{
|
|
if (!owner->dead) {
|
|
owner->TryAddBuff(GetCaster().Get(),
|
|
meta->_int_buff_param4,
|
|
skill_meta,
|
|
nullptr,
|
|
buff_vars);
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|