354 lines
11 KiB
C++
354 lines
11 KiB
C++
#include "precompile.h"
|
|
|
|
#include <a8/list.h>
|
|
|
|
#include "trigger.h"
|
|
#include "creature.h"
|
|
#include "metamgr.h"
|
|
#include "skill.h"
|
|
#include "room.h"
|
|
#include "human.h"
|
|
#include "car.h"
|
|
|
|
void Trigger::Init()
|
|
{
|
|
|
|
}
|
|
|
|
void Trigger::UnInit()
|
|
{
|
|
|
|
}
|
|
|
|
void Trigger::TakeonWeapon(Weapon* old_weapon, Weapon* new_weapon)
|
|
{
|
|
{
|
|
MetaData::Equip* weapon_meta = old_weapon ? old_weapon->meta : nullptr;
|
|
if (weapon_meta) {
|
|
for (int cond = kCondBuffUpdateWeaponId; cond <= kCondBuffUpdateWeaponType; cond++) {
|
|
TraverseCondBuffs
|
|
(cond,
|
|
[this, cond, weapon_meta] (Buff* buff, bool& stop)
|
|
{
|
|
if (weapon_meta->Match((CondAddBuff_e)cond,
|
|
buff->meta->int_param3,
|
|
buff->meta->int_param5)) {
|
|
switch (buff->meta->int_param2) {
|
|
case kWeaponOptTakeoff:
|
|
case kWeaponOptKeep:
|
|
{
|
|
RemoveBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
{
|
|
MetaData::Equip* weapon_meta = new_weapon ? new_weapon->meta : nullptr;
|
|
if (weapon_meta) {
|
|
for (int cond = kCondBuffUpdateWeaponId; cond <= kCondBuffUpdateWeaponType; cond++) {
|
|
TraverseCondBuffs
|
|
(cond,
|
|
[this, cond, weapon_meta] (Buff* buff, bool& stop)
|
|
{
|
|
if (weapon_meta->Match((CondAddBuff_e)cond,
|
|
buff->meta->int_param3,
|
|
buff->meta->int_param5)) {
|
|
switch (buff->meta->int_param2) {
|
|
case kWeaponOptTakeon:
|
|
{
|
|
AddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
break;
|
|
case kWeaponOptKeep:
|
|
{
|
|
TryAddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Trigger::Shot(MetaData::Equip* weapon_meta)
|
|
{
|
|
for (int cond = kCondBuffShotWeaponId; cond <= kCondBuffShotWeaponType; ++cond) {
|
|
TraverseCondBuffs
|
|
(cond,
|
|
[this, cond, weapon_meta] (Buff* buff, bool& stop)
|
|
{
|
|
if (weapon_meta->Match((CondAddBuff_e)cond,
|
|
buff->meta->int_param2,
|
|
buff->meta->int_param5)) {
|
|
AddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void Trigger::Kill(Creature* target)
|
|
{
|
|
if (owner_->IsHuman() && target->IsHuman()) {
|
|
owner_->AsHuman()->stats.kills++;
|
|
owner_->AsHuman()->stats.last_kill_frameno = owner_->room->GetFrameNo();
|
|
owner_->AsHuman()->kill_humans.insert(target->AsHuman());
|
|
owner_->AsHuman()->SyncAroundPlayers(__FILE__, __LINE__, __func__);
|
|
}
|
|
if (owner_->IsCar()) {
|
|
owner_->AsCar()->OnKillTarget(target);
|
|
}
|
|
++kill_num_;
|
|
TraverseCondBuffs
|
|
(kCondBuffKillTarget,
|
|
[this] (Buff* buff, bool& stop)
|
|
{
|
|
if (buff->meta->int_param2 > 0 && (kill_num_ % buff->meta->int_param2) == 0) {
|
|
AddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
});
|
|
}
|
|
|
|
void Trigger::UseItemAction(int slot_id)
|
|
{
|
|
TraverseCondBuffs
|
|
(kCondBuffEatDrug,
|
|
[this, slot_id] (Buff* buff, bool& stop)
|
|
{
|
|
if (buff->meta->param2_int_set.find(slot_id) != buff->meta->param2_int_set.end()) {
|
|
AddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
});
|
|
}
|
|
|
|
void Trigger::UseSkill(Skill* skill)
|
|
{
|
|
TraverseCondBuffs
|
|
(kCondBuffUseSkill,
|
|
[this, skill] (Buff* buff, bool& stop)
|
|
{
|
|
if (buff->meta->int_param2 == skill->meta->i->skill_id()) {
|
|
AddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
});
|
|
}
|
|
|
|
void Trigger::HpChg()
|
|
{
|
|
TraverseCondBuffs
|
|
(kCondBuffHp,
|
|
[this] (Buff* buff, bool& stop)
|
|
{
|
|
bool match = false;
|
|
switch (buff->meta->int_param2) {
|
|
case kHpOptLeAbs:
|
|
{
|
|
match = owner_->GetHP() < buff->meta->int_param3;
|
|
}
|
|
break;
|
|
case kHpOptLeRate:
|
|
{
|
|
//match = (owner_->GetHP() / owner_->GetMaxHP() * 100) < buff->meta->int_param3;
|
|
match = owner_->GetHP() / owner_->GetMaxHP() < buff->meta->param3;
|
|
}
|
|
break;
|
|
case kHpOptGeAbs:
|
|
{
|
|
match = owner_->GetHP() > buff->meta->int_param3;
|
|
}
|
|
break;
|
|
case kHpOptGeRate:
|
|
{
|
|
//match = (owner_->GetHP() / owner_->GetMaxHP() * 100) > buff->meta->int_param3;
|
|
match = owner_->GetHP() / owner_->GetMaxHP() > buff->meta->param3;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
if (match) {
|
|
TryAddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
} else {
|
|
RemoveBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
});
|
|
}
|
|
|
|
void Trigger::ReceiveDmg()
|
|
{
|
|
TriggeCondBuffAll(kCondBuffReceiveDmg);
|
|
}
|
|
|
|
void Trigger::Die()
|
|
{
|
|
{
|
|
std::vector<int> list;
|
|
owner_->TraverseBuff
|
|
(
|
|
[&list] (Buff* buff, bool& stop)
|
|
{
|
|
if (buff->meta->i->dead_remove()) {
|
|
list.push_back(buff->buff_uniid);
|
|
}
|
|
});
|
|
for (int buff_uniid : list) {
|
|
owner_->RemoveBuffByUniId(buff_uniid);
|
|
}
|
|
}
|
|
TriggeCondBuffAll(kCondBuffDid);
|
|
}
|
|
|
|
void Trigger::TraverseCondBuffs(int cond, std::function<void (Buff*, bool&)> func)
|
|
{
|
|
if (!IsValidCondBuff(cond)) {
|
|
A8_ABORT();
|
|
}
|
|
if (!owner_->room->BattleStarted()) {
|
|
return;
|
|
}
|
|
|
|
list_head* pos = nullptr;
|
|
list_head* next = nullptr;
|
|
list_head* head = &owner_->cond_buffs_[cond];
|
|
RemoveBuffCbConext cb;
|
|
cb.next = &next;
|
|
INIT_LIST_HEAD(&cb.entry);
|
|
list_for_each_safe(pos, next, head) {
|
|
if (list_empty(next)) {
|
|
Buff *next_buff = list_entry(next, Buff, cond_entry);
|
|
list_add_tail(&cb.entry, &next_buff->on_remove_contexts);
|
|
}
|
|
Buff *curr_buff = list_entry(pos, Buff, cond_entry);
|
|
bool stop = false;
|
|
func(curr_buff, stop);
|
|
if (!list_empty(&cb.entry)) {
|
|
list_del_init(&cb.entry);
|
|
}
|
|
if (stop) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Trigger::TriggeCondBuffAll(int cond)
|
|
{
|
|
if (!owner_->room->BattleStarted()) {
|
|
return;
|
|
}
|
|
|
|
std::shared_ptr<Ability> old_context_ability = owner_->context_ability;
|
|
a8::Vec2 old_context_dir = owner_->context_dir;
|
|
a8::Vec2 old_context_pos = owner_->context_pos;
|
|
owner_->context_dir = owner_->GetAttackDir();
|
|
owner_->context_pos = owner_->GetPos();
|
|
TraverseCondBuffs
|
|
(cond,
|
|
[this, cond] (Buff* buff, bool& stop)
|
|
{
|
|
AddBuffs(cond, buff->meta->param4_int_list);
|
|
});
|
|
owner_->context_dir = old_context_dir;
|
|
owner_->context_pos = old_context_pos;
|
|
owner_->context_ability = old_context_ability;
|
|
}
|
|
|
|
void Trigger::ActiveBuff(MetaData::Buff* buff_meta)
|
|
{
|
|
for (int cond = kCondBuffUpdateBuffId; cond <= kCondBuffUpdateBuffEffect; ++cond) {
|
|
TraverseCondBuffs
|
|
(cond,
|
|
[this, cond, buff_meta] (Buff* buff, bool& stop)
|
|
{
|
|
if (buff_meta->Match((CondAddBuff_e)cond, buff->meta->int_param3)) {
|
|
switch (buff->meta->int_param2) {
|
|
case kBuffOptActive:
|
|
{
|
|
AddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
break;
|
|
case kBuffOptKeep:
|
|
{
|
|
TryAddBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void Trigger::DeactiveBuff(MetaData::Buff* buff_meta)
|
|
{
|
|
for (int cond = kCondBuffUpdateBuffId; cond <= kCondBuffUpdateBuffEffect; ++cond) {
|
|
TraverseCondBuffs
|
|
(cond,
|
|
[this, cond, buff_meta] (Buff* buff, bool& stop)
|
|
{
|
|
if (buff_meta->Match((CondAddBuff_e)cond, buff->meta->int_param3)) {
|
|
switch (buff->meta->int_param2) {
|
|
case kBuffOptDeactive:
|
|
case kBuffOptKeep:
|
|
{
|
|
RemoveBuffs(buff->meta->int_param1, buff->meta->param4_int_list);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void Trigger::TryAddBuffs(int cond, std::vector<int>& buffids)
|
|
{
|
|
for (int buffid : buffids) {
|
|
if (!owner_->GetBuffById(buffid)) {
|
|
#ifdef DEBUG
|
|
owner_->MustBeAddBuff(owner_, buffid);
|
|
#else
|
|
owner_->TryAddBuff(owner_, buffid);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
void Trigger::AddBuffs(int cond, std::vector<int>& buffids)
|
|
{
|
|
for (int buffid : buffids) {
|
|
#ifdef DEBUG
|
|
owner_->MustBeAddBuff(owner_, buffid);
|
|
#else
|
|
owner_->TryAddBuff(owner_, buffid);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void Trigger::RemoveBuffs(int cond, std::vector<int>& buffids)
|
|
{
|
|
for (int buffid : buffids) {
|
|
owner_->RemoveBuffById(buffid);
|
|
}
|
|
}
|