Files
2022-10-26 12:25:11 +08:00

510 lines
18 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StdAfx.h"
#include ".\basetrigger.h"
#include "TriggerCommon.h"
#include "IConditionTrigger.h"
#include "IActionTrigger.h"
#include "ConditionInfo.h"
#include "ActionInfo.h"
#include "TriggerInfo.h"
#include "./TriggerManager.h"
#include <misc.h>
BaseTrigger::BaseTrigger()
: m_pTriggerManager(NULL)
, m_pTriggerInfo(NULL)
, activated_(false)
, runtime_config_(eRuntimeConfig_Null)
, need_action_by_runtime_config_(false)
, deletion_requested_(false)
, m_state(INACTIVATE_STATE)
, clicked_player_key_(0)
, object_key_(0)
{
ZeroMemory(&active_link_, sizeof(active_link_));
util::LList::Init(&active_link_);
active_link_.trigger = this;
active_link_.ordered_index = -1;
}
BaseTrigger::~BaseTrigger()
{
util::LList::Delete(&active_link_);
active_link_.ordered_index = -1;
//
Release();
}
void BaseTrigger::Release()
{
util::LList::Delete(&active_link_);
active_link_.ordered_index = -1;
//
FOREACH_CONTAINER(const CONDITION_TRIGGER_LIST::value_type& node, m_listConditionTrigger,
CONDITION_TRIGGER_LIST)
{
IConditionTrigger* condition_trigger = node;
_destroyCondition(condition_trigger);
}
FOREACH_CONTAINER(const ACTION_TRIGGER_LIST::value_type& node, m_listActionTrigger,
ACTION_TRIGGER_LIST)
{
IActionTrigger* action_trigger = node;
_destroyAction(action_trigger);
}
m_listConditionTrigger.clear();
m_listActionTrigger.clear();
OnRelease();
}
void BaseTrigger::Init(TriggerManager* trigger_manager, TriggerInfo* trigger_info)
{
m_pTriggerManager = trigger_manager;
ASSERT(m_listConditionTrigger.empty());
ASSERT(m_listActionTrigger.empty());
if (const TRIGGER_LIST* trigger_list = &m_pTriggerManager->GetTriggerList()) {
active_link_.ordered_index = static_cast<int>(trigger_list->size());
};
//__NA000000_090613_TRIGGER_LOGIC_REARRANGE__
runtime_config_ = this->eRuntimeConfig_Null;
need_action_by_runtime_config_ = false;
deletion_requested_ = false;
m_state = INACTIVATE_STATE;
_setInfo(trigger_info);
if (trigger_info->IsLoop()) {
runtime_config_ |= eRuntimeConfig_Loop;
};
if (trigger_info->IsAND() == false) {
runtime_config_ |= eRuntimeConfig_Or;
};
const ns_trigger::CONDITION_INFO_LIST& condition_info_list = \
m_pTriggerInfo->GetConditionInfoList();
m_listConditionTrigger.reserve(condition_info_list.size());
FOREACH_CONTAINER(const ns_trigger::CONDITION_INFO_LIST::value_type& node,
condition_info_list, ns_trigger::CONDITION_INFO_LIST)
{
ConditionInfo* condition_info = node;
_createCondition(condition_info);
#if defined(_SERVER)
switch (condition_info->TriggerType())
{
case eCONDITION_ENTER_AREA: runtime_config_ |= eRuntimeConfig_Area; break;
case eCONDITION_NPC_ENTER_AREA: runtime_config_ |= eRuntimeConfig_Area; break;
case eCONDITION_PASS_TIME: runtime_config_ |= eRuntimeConfig_Timer; break;
};
#endif
};
const ns_trigger::ACTION_INFO_LIST& action_info_list = m_pTriggerInfo->GetActionInfoList();
m_listActionTrigger.reserve(action_info_list.size());
FOREACH_CONTAINER(const ns_trigger::ACTION_INFO_LIST::value_type& node,
action_info_list, ns_trigger::ACTION_INFO_LIST)
{
ActionInfo* action_info = node;
_createAction(action_info);
};
}
void BaseTrigger::OnInit()
{
need_action_by_runtime_config_ = false;
deletion_requested_ = false;
clicked_player_key_ = 0;
object_key_ = 0;
SetActive(_getInfo()->IsActive());
// 업데이트 안함!
m_state = DONTUPDATE_STATE;
FOREACH_CONTAINER(const CONDITION_TRIGGER_LIST::value_type& node, m_listConditionTrigger,
CONDITION_TRIGGER_LIST)
{
IConditionTrigger* condition_trigger = node;
condition_trigger->Clear(); //< satisfied_ = false;
condition_trigger->OnInit();
if (condition_trigger->NeedUpdate()) {
m_state = UPDATE_STATE;
};
};
// 첫번째는 실행 : for always condition
// 비활성화 트리거의 경우라도 always에 있는 액션을 최초1회 무조건 실행하게 된다.
Execute();
}
bool BaseTrigger::Execute()
{
#if defined(_SERVER)
if (_ConditionCheck())
{
bool do_action = true;
if (runtime_config_ == eRuntimeConfig_EventOneTime) {
do_action = need_action_by_runtime_config_;
};
if (do_action) {
_Action();
}
else {
m_state = ACTIONUPDATE_STATE; // (WAVERIX) (090622) (WARNING) 상태제어...
};
return true;
}
else
{
_ConditionReset();
}
return false;
#else
if (_ConditionCheck())
{
_Action();
return true;
}
else
{
_ConditionReset();
}
return false;
#endif
}
bool BaseTrigger::_ConditionCheck()
{
if (m_pTriggerInfo->IsAND())
{
FOREACH_CONTAINER(const CONDITION_TRIGGER_LIST::value_type& node, m_listConditionTrigger,
CONDITION_TRIGGER_LIST)
{
IConditionTrigger* condition_trigger = node;
if (condition_trigger->IsSatisfied() == false) {
return false;
};
};
return true;
}
else // OR composed condtion
{
FOREACH_CONTAINER(const CONDITION_TRIGGER_LIST::value_type& node, m_listConditionTrigger,
CONDITION_TRIGGER_LIST)
{
IConditionTrigger* condition_trigger = node;
if (condition_trigger->IsSatisfied() != false) {
return true;
};
};
return false;
}
}
void BaseTrigger::_Action()
{
_OnAction();
FOREACH_CONTAINER(const ACTION_TRIGGER_LIST::value_type& node, m_listActionTrigger,
ACTION_TRIGGER_LIST)
{
IActionTrigger* action_trigger = node;
action_trigger->OnAction();
};
m_state = ACTIONUPDATE_STATE;
}
void BaseTrigger::_ConditionReset()
{
// 업데이트 안함!
m_state = DONTUPDATE_STATE;
FOREACH_CONTAINER(const CONDITION_TRIGGER_LIST::value_type& node, m_listConditionTrigger,
CONDITION_TRIGGER_LIST)
{
IConditionTrigger* condition_trigger = node;
condition_trigger->OnReset();
if (condition_trigger->NeedUpdate()) {
m_state = UPDATE_STATE;
};
};
}
void BaseTrigger::OnMsg(TRIGGER_MSG* trigger_msg)
{
FOREACH_CONTAINER(const CONDITION_TRIGGER_LIST::value_type& node, m_listConditionTrigger,
CONDITION_TRIGGER_LIST)
{
IConditionTrigger* condition_trigger = node;
// 조건체크후 만족하면 전체 만족 여부 체크
if (condition_trigger->OnMsg(trigger_msg))
{
// 현재 이벤트 메세지로 만족되었다.
// 전체 만족 체크
if (Execute()) {
return;
};
}
};
return;
}
#ifdef _DH_TRIGGER_LOG_MESSAGE_IN_TRIGGER
namespace util {
;
static TCHAR* GetConditionTypeString(WORD condition_type, TCHAR* message);
static TCHAR* GetActionTypeString(WORD condition_type, TCHAR* message);
};
static TCHAR* util::GetConditionTypeString(WORD condition_type, TCHAR* message)
{
switch(condition_type)
{
case eCONDITION_ALWAYS: sprintf(message, "?是\n");
break;
case eCONDITION_COMPARE_SWITCH: sprintf(message, "交?机比?\n");
break;
case eCONDITION_CLICK_OBJECT: sprintf(message, "???象\n");
break;
case eCONDITION_DAMAGE_OBJECT: sprintf(message, "受?象?害\n");
break;
case eCONDITION_COUNT_NPCKILL: sprintf(message, "??怪物?量\n");
break;
case eCONDITION_PASS_TIME: sprintf(message, "一定???流\n");
break;
case eCONDITION_ENTER_AREA: sprintf(message, "?入特定?域\n");
break;
case eCONDITION_HAVE_ITEM: sprintf(message, "?有物品\n");
break;
case eCONDITION_MULTI_SWITCH: sprintf(message, "多交?机比?\n");
break;
case eCONDITION_MISSION_POINT: sprintf(message, "?足任?点\n");
break;
case eCONDITION_COMPARE_VARIABLE: sprintf(message, "比??量\n");
break;
case eCONDITION_QUEST_PROGRESS: sprintf(message, "Quest完成????器\n");
break;
case eCONDITION_CHECK_CLASS_ID: sprintf(message, "用???置(依???器)\n");
break;
case eCONDITION_NPCKILL_FOR_UNITID: sprintf(message, "?到怪物?位\n");
break;
case eCONDITION_LIVE_PARTY_MEMBER: sprintf(message, "如果???于生存/死亡??\n");
break;
case eCONDITION_CHECK_OBJECT_HP: sprintf(message, "MapObject的HP?低于%?\n");
break;
case eCONDITION_DESTROY_OBJECT: sprintf(message, "mappobject被破?的?\n");
break;
case eCONDITION_CHECK_OBJECTKIND_HP: sprintf(message, "[UnitIDMapObject]的HP?低于%?\n");
break;
// _NA_002098_20110307_ADD_NPC_CONTROL_TRIGGER
case eCONDITION_NPC_ENTER_AREA: sprintf(message, "NPC?入特定?域\n");
break;
case eCONDITION_SERVER_EVENT: sprintf(message, "?生服?器事件\n");
break;
case eCONDITION_CHECK_TEAM: sprintf(message, "如果是???的?\n");
break;
case eCONDITION_COMPARE_SWITCH_EX: sprintf(message, "交?机比?(可?展)\n");
break;
case eCONDITION_MONSTER_ENTER_AREA: sprintf(message, "怪物?入特定?域\n");
break;
case eCONDITION_MAX: sprintf(message, "ConditonError \n");
break;
default:
sprintf(message, "unkown Conditon [%d]\n", condition_type);
break;
}
return message;
};
static TCHAR* util::GetActionTypeString(WORD condition_type, TCHAR* message)
{
switch(condition_type)
{
case eACTION_CHANGE_OBJECTANI: sprintf(message, "更改?象??\n");
break;
case eACTION_CHANGE_PATHTILE: sprintf(message, "更改?路瓷??性 \n");
break;
case eACTION_CHANGE_OBJECTSTATE: sprintf(message, "更改?象??\n");
break;
case eACTION_PLAY_EVENT: sprintf(message, "活?播放\n");
break;
case eACTION_SET_ISATTACK: sprintf(message, "可攻?/不可攻?”\n");
break;
case eACTION_PORTAL_PLAYER: sprintf(message, "玩家??\n");
break;
case eACTION_SET_OBJECTTHRUST: sprintf(message, "?象推送?置\n");
break;
case eACTION_APPLY_DAMAGE: sprintf(message, "?用?害\n");
break;
case eACTION_REFLECT_DAMAGE: sprintf(message, "反射?害\n");
break;
case eACTION_CREATE_MONSTER: sprintf(message, "?建怪物\n");
break;
case eACTION_DISPLAY_MSGBOX: sprintf(message, "消息??出\n");
break;
case eACTION_REMOVE_ITEM: sprintf(message, "?点物品?除\n");
break;
case eACTION_REWARD_PLAYER: sprintf(message, "玩家??\n");
break;
case eACTION_CLEAR_MISSION: sprintf(message, "任??果\n");
break;
case eACTION_PORTAL_RANDOM: sprintf(message, "?机??\n");
break;
case eACTION_NPC_RANDOM_AREA_MOVE: sprintf(message, "NPC?机?域移?\n");
break;
case eACTION_ACTIVATE_TRIGGER: sprintf(message, "禁用??器活?\n");
break;
case eACTION_AREA_DAMAGE: sprintf(message, "范??害\n");
break;
case eACTION_OPERATE_SWITCH: sprintf(message, "???算\n");
break;
case eACTION_OPERATE_VARIABLE: sprintf(message, "更改交?机?置\n");
break;
case eACTION_ROAD_CONNECT: sprintf(message, "打?/??道路?接\n");
break;
case eACTION_CREATE_DIR_MONSTER: sprintf(message, "生成怪物(方向)\n");
break;
case eACTION_CHANGE_LIGHT: sprintf(message, "更改光源?置\n");
break;
case eACTION_CHANGE_OBJECT_TYPE: sprintf(message, "改??象??\n");
break;
case eACTION_RANDOM_MAP_MOVE: sprintf(message, "移??机??\n");
break;
case eACTION_DROP_TRESUREBOX: sprintf(message, "掉落?箱\n");
break;
case eACTION_QUEST_SATISFACTION: sprintf(message, "?足任??件\n");
break;
case eACTION_QUEST_GRANT: sprintf(message, "?予任?\n");
break;
case eACTION_QUEST_SETUP: sprintf(message, "任?完成/失??置\n");
break;
case eACTION_USE_CATEGORY: sprintf(message, "使用(字段)的(??\n");
break;
case eACTION_HOLD_CHARACTER: sprintf(message, "(Character)在(???阻止移?\n");
break;
case eACTION_CREATE_MONSTER_GROUP: sprintf(message, "?建怪物?\n");
break;
case eACTION_SHOW_GUIDE_MSGBOX: sprintf(message, "引?消息??出\n");
break;
case eACTION_SHOW_OR_HIDE_UNIT: sprintf(message, "?元?示/消失\n");
break;
case eACTION_SHOW_OR_HIDE_MSGBOX: sprintf(message, "消息?的?示/消失\n");
break;
case eACTION_RANDOM_AREA_MOVE: sprintf(message, "移?玩家\n");
break;
case eACTION_RANDOM_MONSTER_SPAWN: sprintf(message, "怪物?机重生\n");
break;
case eACTION_TOWER_OF_TRIAL_SHOW_THE_FLOOR: sprintf(message, "eACTION_TOWER_OF_TRIAL_SHOW_THE_FLOOR\n");
break;
case eACTION_REMOVE_MONSTER: sprintf(message, "?除怪物\n");
break;
case eACTION_ADD_EXP: sprintf(message, "添加??\n");
break;
case eACTION_MONSTER_STAT_UP_OR_DOWN: sprintf(message, "增加/?少怪物的能力?之一。\n");
break;
case eACTION_RANDUM_TRIGER_ON_OR_OFF: sprintf(message, "打?/??其中一???器。\n");
break;
case eACTION_PLAY_MUSIC: sprintf(message, "重新生成?音文件。\n");
break;
case eACTION_DOWN_OBJETC_HP: sprintf(message, "削?地??象的HP。\n");
break;
case eACTION_CHANGE_ATTACK_KIND: sprintf(message, "使自己?得可攻?\n");
break;
case eACTION_ACTIVE_STAMP: sprintf(message, "更改?可刻印?? eCONDITION_DESTROY_OBJECT ?停???作\n");
break;
case eACTION_ATTACK_OBJECTKIND: sprintf(message, "攻?怪物/小分?/目?物]\n");
break;
case eACTION_ACTIVE_SKILL_OBJECTKIND: sprintf(message, "怪物/小分?/目?物]??技能ID。\n");
break;
case eACTION_SHOW_MESSAGEBOX_OBJECTKIND: sprintf(message, "在[Monster/小分?/?象]的位置?示“消息代?”消息。\n");
break;
case eACTION_SET_ATTACK_STATE_OBJECTKIND: sprintf(message, "怪物/小分?[攻?/停止]攻?[怪物]。\n");
break;
case eACTION_DESTROY_OBJECTKIND: sprintf(message, "?除怪物/小分?/目?物],[支付/未支付]。\n");
break;
case eACTION_CREATE_MONSTER_LINKED_MAPOBJECT: sprintf(message, "生成[?象]。MapOjpect?系NPC \n");
break;
case eACTION_CONTROL_TIMER: sprintf(message, "?示表\n");
break;
case eACTION_DO_COMMAND: sprintf(message, "?行??型??的操作(通???器?送消息)\n");
break;
case eACTION_MOVE_CONTROL: sprintf(message, "控制移?\n");
break;
case eACTION_ANIMATION_CONTROL: sprintf(message, "控制??\n");
break;
// _NA_002098_20110307_ADD_NPC_CONTROL_TRIGGER
case eACTION_NPC_APPLY_DAMAGE:
sprintf(message, _T("?怪物/小分?/目?物?用?害。\n"));
break;
//_NA_004777_20120428_ADD_COMPLETE_COLLECTION_TRIGGER
case eACTION_COMPLETE_COLLECTION:
sprintf(message, _T("采集完成后?行?作。(??\n"));
break;
case eACTION_APPLY_HPMPSD:
sprintf(message, _T("增加HP/MPSP/SD。\n"));
break;
case eACTION_CHANGE_OBJECT_HP:
sprintf(message, _T("[?象密?]??象的HP降低/提高[百分比/??][?字]\n"));
break;
case eACTION_CHANGE_RADAR_MAP:
sprintf(message, _T("更改雷??(迷??)。\n"));
break;
case eACTION_ATTACH_STATE_RANGE:
sprintf(message, _T("?予目?范??的玩家持????的??。\n"));
break;
case eACTION_CHANGE_PLAYER_HP:
sprintf(message, _T("[?伍/?人]的HP按[比率/??][?字]下降/上升]\n"));
break;
case eACTION_MAX:
sprintf(message, "error Action\n");
break;
default:
sprintf(message, "unknown Action [%d]\n", condition_type);
break;
}
return message;
};
#endif //_DH_TRIGGER_LOG_MESSAGE
const TCHAR* BaseTrigger::_DisplayTriggerInfo(TCHAR* const making_msg) const
{
#if !defined(_DH_TRIGGER_LOG_MESSAGE_IN_TRIGGER)
return making_msg;
#endif
#if defined(_DH_TRIGGER_LOG_MESSAGE_IN_TRIGGER)
TCHAR temp[256] = {0,};
sprintf(making_msg, _T("TRIGGER_DO_ACTION: ID(%u) GroupName(%s), CategoryName(%s), condition(%d)\n"),
m_pTriggerInfo->TriggerID() , m_pTriggerInfo->group_name(), m_pTriggerInfo->CategoryName(), m_pTriggerInfo->condition_index());
const ns_trigger::CONDITION_INFO_LIST& rConditions = m_pTriggerInfo->GetConditionInfoList();
FOREACH_CONTAINER(const ns_trigger::CONDITION_INFO_LIST::value_type& rNode,
rConditions, ns_trigger::CONDITION_INFO_LIST)
{
ConditionInfo* pInfo = rNode;
util::GetConditionTypeString(pInfo->TriggerType(), temp);
strcat(making_msg, temp);
}
const ns_trigger::ACTION_INFO_LIST& rActions = m_pTriggerInfo->GetActionInfoList();
FOREACH_CONTAINER(const ns_trigger::ACTION_INFO_LIST::value_type& rNode,
rActions, ns_trigger::ACTION_INFO_LIST)
{
ActionInfo* pInfo = rNode;
util::GetActionTypeString(pInfo->TriggerType(), temp);
strcat(making_msg, temp);
}
return making_msg;
#endif //_DH_TRIGGER_LOG_MESSAGE
}