510 lines
18 KiB
C++
510 lines
18 KiB
C++
#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, "[UnitID,MapObject]的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/MP(SP)/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
|
||
}
|
||
|