1116 lines
34 KiB
C++
1116 lines
34 KiB
C++
#include "Stdafx.h"
|
|
#include "ExtraNPCManager.h"
|
|
|
|
#include "NPCInfoParser.h"
|
|
#include "PublicMath.h"
|
|
|
|
#include "Player.h"
|
|
#include "ItemManager.h"
|
|
#include "InventorySlotContainer.h"
|
|
#include "SyncMerchant.h"
|
|
#include "GameZone.h"
|
|
#include "GameDominationManager.h"
|
|
#include <PacketStruct_CG_SmartNPC.h>
|
|
#include <PacketStruct_SmartNPCSystem.h>
|
|
|
|
#include "AuMD5Encrypt.h"
|
|
#include <lua/lua_manager.h>
|
|
#include <TinyXml/tinyxml.h>
|
|
#include <json/json.h>
|
|
|
|
#include "ServerOptionParserEx.h"
|
|
|
|
//==================================================================================================
|
|
|
|
ExtraNPCManager g_ExtraNPCManager;
|
|
|
|
ExtraNPCManager::ExtraNPCManager()
|
|
{
|
|
|
|
}
|
|
|
|
BOOL
|
|
ExtraNPCManager::IsLengthCanUseNPC( CODETYPE NPCCODE, Player* pPlayer, eNPC_TYPE eCheckNPCType )
|
|
{
|
|
GameField* const game_field = pPlayer->GetField();
|
|
if (game_field == NULL) {
|
|
return false;
|
|
};
|
|
EXTRA_NPCINFO * pExtraNPCInfo = NPCInfoParser::Instance()->GetExtraInfo(NPCCODE);
|
|
if( pExtraNPCInfo == NULL )
|
|
{
|
|
SUNLOG( eCRITICAL_LOG, "없는 ExtraNPC 참조 : IsCanUseNPC()" );
|
|
return FALSE;
|
|
}
|
|
|
|
bool violated_field_check = (pExtraNPCInfo->m_FieldID != game_field->GetFieldCode());
|
|
#ifdef __NA002642_TUTORIAL_LOAD_BALANCE_SUPPORT
|
|
GameZone* const game_zone = game_field->GetGameZone();
|
|
if (violated_field_check && (game_zone->GetMapCode() == HardCode::MAPCODE_for_TUTORIAL_FIELD)) {
|
|
violated_field_check = false;
|
|
}
|
|
#endif
|
|
if (violated_field_check)
|
|
{
|
|
SUNLOG(eCRITICAL_LOG, "다른 Zone 에서 NPC 이용 시도(hacking) - shogen" );
|
|
return FALSE;
|
|
}
|
|
|
|
if( eCheckNPCType != eNPC_TYPE_NONE && pExtraNPCInfo->m_eNPCTYPE != eCheckNPCType )
|
|
{
|
|
SUNLOG(eCRITICAL_LOG, "잘못된 NPC 이용 시도(hacking)" );
|
|
return FALSE;
|
|
}
|
|
|
|
// (WAVERIX) (090825) (CHANGES) 퀘스트 수락시 NPC와의 거리 소수점 단위 오차로 인해 정상 동작 안하는 문제 수정
|
|
// 그 외에도 사용하는 함수인 관계로 좀 여유를 두었다. 높이도 고려되는 값이라 클라이언트와 미묘한
|
|
// 오차가 발생한다.
|
|
|
|
const float DistanceThisWithNpcSquared = (DISTANCE_NPC_MEET + 0.3f) * (DISTANCE_NPC_MEET + 0.3f);
|
|
|
|
// using the unit id that is changed by _NA_0_20100222_UNIT_TRIGGERS_REGEN
|
|
float distance_current = 0.f;
|
|
|
|
if (pExtraNPCInfo->m_unitID != 0)
|
|
{
|
|
GameField* const field = pPlayer->GetField();
|
|
NPC* const npc = field->FindNPCForUnitID(pExtraNPCInfo->m_unitID);
|
|
|
|
if (!npc)
|
|
return false;
|
|
|
|
distance_current = Math_VectorLength2(*npc->GetPosPtr(), *pPlayer->GetPosPtr());
|
|
}
|
|
else
|
|
{
|
|
BOOST_STATIC_ASSERT(_countof(pExtraNPCInfo->m_fNPCPos) == 3 &&
|
|
sizeof(pExtraNPCInfo->m_fNPCPos) == sizeof(WzVector));
|
|
|
|
distance_current = Math_VectorLength2((WzVector&)(pExtraNPCInfo->m_fNPCPos),
|
|
*pPlayer->GetPosPtr());
|
|
}
|
|
|
|
if(!(distance_current < DistanceThisWithNpcSquared))
|
|
return false;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//==================================================================================================
|
|
// NOTE: f110704.5L
|
|
bool ExtraNPCManager::CheckProtectedNpc(SyncMerchant* check_npc) const
|
|
{
|
|
const DWORD unit_id = check_npc->GetRegenID();
|
|
if (unit_id == 0) {
|
|
return false;
|
|
};
|
|
const BASE_NPCINFO* npc_info = check_npc->GetBaseInfo();
|
|
const EXTRA_NPCINFO* extra_npc_info = \
|
|
NPCInfoParser::Instance()->GetExtraInfo(npc_info->m_MonsterCode);
|
|
if (extra_npc_info == NULL) {
|
|
return false;
|
|
};
|
|
if (unit_id != extra_npc_info->m_unitID) {
|
|
return false;
|
|
};
|
|
// Check ExtraNpcInfo.NpcType
|
|
if (extra_npc_info->m_eNPCTYPE != eNPC_TYPE_PROTECTS) {
|
|
return false;
|
|
};
|
|
return true;
|
|
}
|
|
|
|
#ifdef _NA_000000_20140120_SMART_NPC_SYSTEM
|
|
bool ExtraNPCManager::initialize()
|
|
{
|
|
TiXmlDocument manager_document;
|
|
if(!manager_document.LoadFile("data\\NPCManager\\NpcManager.xml"))
|
|
return false;
|
|
|
|
TiXmlNode* link_files_node = manager_document.FirstChild("LinkFile");
|
|
if(!link_files_node)
|
|
return false;
|
|
|
|
for (TiXmlElement* lua_file = link_files_node->FirstChildElement("LUAFile"); \
|
|
lua_file; lua_file = lua_file->NextSiblingElement())
|
|
{
|
|
TiXmlElement* name_element = lua_file->FirstChildElement("NAME");
|
|
const CHAR* lua_file_name = (name_element) ? name_element->GetText() : NULL;
|
|
|
|
CLuaStreamPack* lua_pack = new CLuaStreamPack;
|
|
if (lua_pack == NULL) {
|
|
SUNLOG(eCRITICAL_LOG, "lua stream pack new operator fail");
|
|
continue;
|
|
}
|
|
|
|
CHAR file_name_path[MAX_PATH] = { 0, };
|
|
_snprintf(file_name_path, sizeof(file_name_path), \
|
|
"data\\NPCManager\\%s", lua_file_name);
|
|
|
|
if (lua_pack->open(file_name_path, (Decrypt_CFunction)ExtraNPCManager::Decrypt) == false) {
|
|
SUNLOG(eCRITICAL_LOG, "%s open fail", lua_file_name);
|
|
delete lua_pack;
|
|
continue;
|
|
}
|
|
|
|
lua_stream_pack_array_.push_back(lua_pack);
|
|
|
|
for (TiXmlElement* npc_id_element = lua_file->FirstChildElement("NPCID"); \
|
|
npc_id_element; npc_id_element = npc_id_element->NextSiblingElement())
|
|
{
|
|
int npc_id = atoi(npc_id_element->GetText());
|
|
|
|
npc_script_map_.insert(LuaStreamPackMap::value_type(npc_id, lua_pack));
|
|
}
|
|
}
|
|
|
|
if (initialize_lua_handler() == false)
|
|
return false;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
TiXmlDocument dialog_document_;
|
|
if(!dialog_document_.LoadFile("data\\NPCManager\\NpcDialog.xml"))
|
|
return false;
|
|
|
|
TiXmlNode* dialog_node = dialog_document_.FirstChild("NpcDialog");
|
|
if(!dialog_node)
|
|
return false;
|
|
|
|
TiXmlNode* menu_list_node = dialog_node->FirstChild("MenuList");
|
|
if(!menu_list_node)
|
|
return false;
|
|
|
|
for (TiXmlElement* menu_element = menu_list_node->FirstChildElement("Menu"); \
|
|
menu_element; menu_element = menu_element->NextSiblingElement())
|
|
{
|
|
Json::Value menu;
|
|
|
|
int menu_index;
|
|
menu_element->Attribute("ID", &menu_index);
|
|
menu["ID"] = menu_index;
|
|
|
|
TiXmlElement* type_element = menu_element->FirstChildElement("TYPE");
|
|
const CHAR* TYPE = (type_element) ? type_element->GetText() : NULL;
|
|
menu["TYPE"] = (TYPE) ? atoi(TYPE) : 1;
|
|
|
|
TiXmlElement* title_element = menu_element->FirstChildElement("TITLE");
|
|
const CHAR* title_string = (title_element) ? title_element->GetText() : NULL;
|
|
menu["TITLE"] = title_string;
|
|
|
|
TiXmlElement* dialog_element = menu_element->FirstChildElement("Dialog");
|
|
const CHAR* dialog_string = (dialog_element) ? dialog_element->GetText() : NULL;
|
|
menu["DIALOG"] = dialog_string;
|
|
|
|
Json::Value button_array;
|
|
for (TiXmlElement* button_element = menu_element->FirstChildElement("Button");
|
|
button_element; button_element = button_element->NextSiblingElement())
|
|
{
|
|
Json::Value button;
|
|
|
|
TiXmlElement* EID_elem = button_element->FirstChildElement("EID");
|
|
const CHAR* EID = (EID_elem) ? EID_elem->GetText() : NULL;
|
|
if (EID) {
|
|
button["EID"] = atoi(EID);
|
|
}
|
|
|
|
TiXmlElement* STEP_elem = button_element->FirstChildElement("STEP");
|
|
const CHAR* STEP = (STEP_elem) ? STEP_elem->GetText() : NULL;
|
|
if (STEP) {
|
|
button["STEP"] = atoi(STEP);
|
|
}
|
|
|
|
TiXmlElement* TEXT_elem = button_element->FirstChildElement("TEXT");
|
|
const CHAR* TEXT = (TEXT_elem) ? TEXT_elem->GetText() : NULL;
|
|
if (TEXT) {
|
|
button["TEXT"] = TEXT;
|
|
}
|
|
|
|
button_array.append(button);
|
|
}
|
|
|
|
menu["BUTTONS"] = button_array;
|
|
|
|
//Json::StyledWriter writer;
|
|
Json::FastWriter writer;
|
|
std::string menu_dialog_string = writer.write(menu);
|
|
//std::cout << menu_dialog_string << std::endl << menu_dialog_string.length() << std::endl;
|
|
|
|
if (false == menu_string_.insert( \
|
|
StringMap::value_type(menu_index, menu_dialog_string)).second)
|
|
{
|
|
SUNLOG(eCRITICAL_LOG, "[%s:%d] duplicated menu id - %d", \
|
|
__FUNCTION__, __LINE__, menu_index);
|
|
}
|
|
}
|
|
|
|
TiXmlNode* messagebox_list_node = dialog_node->FirstChild("MessageBoxList");
|
|
if(!messagebox_list_node)
|
|
return false;
|
|
|
|
for (TiXmlElement* group_element = messagebox_list_node->FirstChildElement("Group"); \
|
|
group_element; group_element = group_element->NextSiblingElement())
|
|
{
|
|
int group_index;
|
|
group_element->Attribute("ID", &group_index);
|
|
|
|
for (TiXmlElement* message_element = group_element->FirstChildElement("Message"); \
|
|
message_element; message_element = message_element->NextSiblingElement())
|
|
{
|
|
int message_index;
|
|
message_element->Attribute("ID", &message_index);
|
|
|
|
const CHAR* message_string = message_element->GetText();
|
|
std::string s(message_string, strlen(message_string));
|
|
messagebox_string_[group_index][message_index] = s;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void ExtraNPCManager::release()
|
|
{
|
|
for(std::list<CLuaStreamPack*>::iterator it = lua_stream_pack_array_.begin(); \
|
|
it != lua_stream_pack_array_.end(); ++it)
|
|
{
|
|
CLuaStreamPack* pack = (*it);
|
|
if (pack) {
|
|
delete (pack);
|
|
pack = NULL;
|
|
}
|
|
}
|
|
|
|
lua_stream_pack_array_.clear();
|
|
npc_script_map_.clear();
|
|
menu_string_.clear();
|
|
lua_handler_.close();
|
|
}
|
|
|
|
CLuaStreamPack* ExtraNPCManager::find_lua_pack(CODETYPE npc_code)
|
|
{
|
|
LuaStreamPackMap::iterator it = npc_script_map_.find(npc_code);
|
|
if (it == npc_script_map_.end())
|
|
return NULL;
|
|
|
|
return (it->second);
|
|
}
|
|
|
|
bool ExtraNPCManager::initialize_lua_handler()
|
|
{
|
|
if (lua_handler_.initialize((LuaHandler::OnRegister_CFunction)register_functions) != true)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
int ExtraNPCManager::register_functions( lua_State* lua_state )
|
|
{
|
|
if(lua_state == NULL)
|
|
return -1;
|
|
|
|
lua_register(lua_state, "ShowMessageBox", ExtraNPCManager::OnShowMessageBox);
|
|
lua_register(lua_state, "ShowMenu", ExtraNPCManager::OnShowMenu);
|
|
|
|
lua_register(lua_state, "GetClass", ExtraNPCManager::GetCharacterClass);
|
|
lua_register(lua_state, "GetLevel", ExtraNPCManager::GetCharacterLevel);
|
|
/*lua_register(lua_state, "GetExp", ExtraNPCManager::GetCharacterExp);*/ // 현재 루아 라이브러리가 int64를 지원 안하므로 사용불가
|
|
|
|
lua_register(lua_state, "GetInventoryEmptyCount", ExtraNPCManager::GetInventoryEmptySlotCount);
|
|
lua_register(lua_state, "CheckItemCount", ExtraNPCManager::CheckItemCount);
|
|
lua_register(lua_state, "RobItem", ExtraNPCManager::RobItem);
|
|
lua_register(lua_state, "GiveItem", ExtraNPCManager::GiveItem);
|
|
|
|
lua_register(lua_state, "ZoneChange", ExtraNPCManager::ZoneChange);
|
|
lua_register(lua_state, "CheckPotalToDominationField", ExtraNPCManager::CheckPotalToDominationField);
|
|
lua_register(lua_state, "SendDominationMinimapList", ExtraNPCManager::SendDominationMinimapList);
|
|
|
|
lua_register(lua_state, "IsDominationGoing", ExtraNPCManager::IsDominationGoing);
|
|
lua_register(lua_state, "IsDominationChannel", ExtraNPCManager::IsDominationChannel);
|
|
lua_register(lua_state, "SetAttendance", ExtraNPCManager::SetAttendance);
|
|
lua_register(lua_state, "GetAttendance", ExtraNPCManager::GetAttendance);
|
|
|
|
#ifdef _NA_007488_20140811_MONDSCHUEN_INITIALIZE_N_REWARD
|
|
lua_register(lua_state, "GetDominationGuildGuid", ExtraNPCManager::GetDominationGuildGuid);
|
|
lua_register(lua_state, "GetCharacterGuildGuid", ExtraNPCManager::GetCharacterGuildGuid);
|
|
#endif // _NA_000000_20140811_MONDSCHUEN_INITIALIZE_N_REWARD
|
|
|
|
/*lua_register(lua_state, "CastSkill", AgsmNpcManager::CastSkill);
|
|
lua_register(lua_state, "Move", AgsmNpcManager::Move);
|
|
lua_register(lua_state, "ReturnTown", AgsmNpcManager::ReturnTown);
|
|
lua_register(lua_state, "SetDefaultInvincible", AgsmNpcManager::SetDefaultInvincible);*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ExtraNPCManager::execute_script_main( int CID, int NID, int EID, int STEP, CLuaStreamPack* lua_pack )
|
|
{
|
|
if( /*CID == 0 || EID == 0 ||*/ !lua_pack )
|
|
return -1;
|
|
|
|
lua_State* lua_state = lua_handler_.state_;
|
|
if(lua_state == NULL)
|
|
return -1;
|
|
|
|
if (lua_pack->do_buffer(lua_state) == false)
|
|
return -1;
|
|
|
|
lua_getglobal(lua_state, "Main");
|
|
lua_pushnumber(lua_state, CID);
|
|
lua_pushnumber(lua_state, NID);
|
|
lua_pushnumber(lua_state, EID);
|
|
lua_pushnumber(lua_state, STEP);
|
|
|
|
int status = lua_pcall(lua_state, 4, 1, 0);
|
|
|
|
if (status != 0)
|
|
{
|
|
char strCharBuff[256] = { 0, };
|
|
_snprintf(strCharBuff, sizeof(strCharBuff), "%s", lua_tostring(lua_state, -1));
|
|
//AuLogFile_s("Log\\LuaError.log", strCharBuff);
|
|
|
|
fprintf(stderr, "\t%s\n", strCharBuff);
|
|
lua_pop(lua_state, 1);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int ret = 0;
|
|
while (lua_gettop(lua_state))
|
|
{
|
|
switch (lua_type(lua_state, lua_gettop(lua_state)))
|
|
{
|
|
case LUA_TNUMBER:
|
|
ret = (int)lua_tonumber(lua_state, lua_gettop(lua_state));
|
|
break;
|
|
default:
|
|
ret = -1;
|
|
break;
|
|
}
|
|
lua_pop(lua_state, 1 );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ExtraNPCManager::execute_script_menu( int CID, int NID, int EID, int STEP, CLuaStreamPack* lua_pack )
|
|
{
|
|
if( /*CID == 0 || EID == 0 ||*/ !lua_pack )
|
|
return -1;
|
|
|
|
lua_State* lua_state = lua_handler_.state_;
|
|
if(lua_state == NULL)
|
|
return -1;
|
|
|
|
if (lua_pack->do_buffer(lua_state) == false)
|
|
return -1;
|
|
|
|
lua_getglobal(lua_state, "OnMenu");
|
|
lua_pushnumber(lua_state, CID);
|
|
lua_pushnumber(lua_state, NID);
|
|
lua_pushnumber(lua_state, EID);
|
|
lua_pushnumber(lua_state, STEP);
|
|
|
|
int status = lua_pcall(lua_state, 4, 1, 0);
|
|
|
|
if (status != 0)
|
|
{
|
|
char strCharBuff[256] = { 0, };
|
|
_snprintf(strCharBuff, sizeof(strCharBuff), "%s", lua_tostring(lua_state, -1));
|
|
//AuLogFile_s("Log\\LuaError.log", strCharBuff);
|
|
|
|
fprintf(stderr, "\t%s\n", strCharBuff);
|
|
lua_pop(lua_state, 1);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int ret = 0;
|
|
while (lua_gettop(lua_state))
|
|
{
|
|
switch (lua_type(lua_state, lua_gettop(lua_state)))
|
|
{
|
|
case LUA_TNUMBER:
|
|
ret = (int)lua_tonumber(lua_state, lua_gettop(lua_state));
|
|
break;
|
|
default:
|
|
ret = -1;
|
|
break;
|
|
}
|
|
lua_pop(lua_state, 1 );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ExtraNPCManager::execute_script_messagebox( int CID, int NID, int EID, int STEP, \
|
|
CLuaStreamPack* lua_pack, CHAR* _data, WORD _data_size)
|
|
{
|
|
if( /*CID == 0 || EID == 0 ||*/ !lua_pack )
|
|
return -1;
|
|
|
|
std::string data_string(_data, _data_size);
|
|
Json::Value messagebox_data;
|
|
Json::Reader reader;
|
|
reader.parse(data_string, messagebox_data);
|
|
|
|
int button_index = messagebox_data.get("BUTTON", 0).asInt();
|
|
Json::Value temp_value = messagebox_data.get("STRING", "");
|
|
const char* input_string = temp_value.asCString();
|
|
|
|
DWORD itemcode = 0;
|
|
|
|
lua_State* lua_state = lua_handler_.state_;
|
|
if(lua_state == NULL)
|
|
return -1;
|
|
|
|
if (lua_pack->do_buffer(lua_state) == false)
|
|
return -1;
|
|
|
|
lua_getglobal(lua_state, "OnMessageBox");
|
|
lua_pushnumber(lua_state, CID);
|
|
lua_pushnumber(lua_state, NID);
|
|
lua_pushnumber(lua_state, EID);
|
|
lua_pushnumber(lua_state, STEP);
|
|
|
|
lua_pushnumber(lua_state, button_index);
|
|
lua_pushstring(lua_state, input_string);
|
|
lua_pushnumber(lua_state, itemcode);
|
|
|
|
int status = lua_pcall(lua_state, 7, 1, 0);
|
|
|
|
if (status != 0)
|
|
{
|
|
char strCharBuff[256] = { 0, };
|
|
_snprintf(strCharBuff, sizeof(strCharBuff), "%s", lua_tostring(lua_state, -1));
|
|
//AuLogFile_s("Log\\LuaError.log", strCharBuff);
|
|
|
|
fprintf(stderr, "\t%s\n", strCharBuff);
|
|
lua_pop(lua_state, 1);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int ret = 0;
|
|
while (lua_gettop(lua_state))
|
|
{
|
|
switch (lua_type(lua_state, lua_gettop(lua_state)))
|
|
{
|
|
case LUA_TNUMBER:
|
|
ret = (int)lua_tonumber(lua_state, lua_gettop(lua_state));
|
|
break;
|
|
default:
|
|
ret = -1;
|
|
break;
|
|
}
|
|
lua_pop(lua_state, 1 );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ExtraNPCManager::OnShowMessageBox( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -7);
|
|
INT32 NID = (INT32)lua_tonumber(lua_state, -6);
|
|
INT32 EID = (INT32)lua_tonumber(lua_state, -5);
|
|
INT32 STEP = (INT32)lua_tonumber(lua_state, -4);
|
|
|
|
INT32 message_type = (INT32)lua_tonumber(lua_state, -3);
|
|
INT32 group_index = (INT32)lua_tonumber(lua_state, -2);
|
|
INT32 message_index = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 7);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 1;
|
|
|
|
Json::Value message_box;
|
|
message_box["TYPE"] = message_type;
|
|
message_box["string"] = g_ExtraNPCManager.messagebox_string_[group_index][message_index];
|
|
|
|
Json::FastWriter writer;
|
|
std::string message_box_dialog = writer.write(message_box);
|
|
|
|
MSG_CG_NPCDIALOG_SHOWMESSAGEBOX_CMD packet(CID, NID, EID, STEP);
|
|
packet.data_length_ = message_box_dialog.length();
|
|
memcpy(packet.data_, message_box_dialog.c_str(), message_box_dialog.length());
|
|
player->SendPacket(&packet, sizeof(packet));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ExtraNPCManager::OnShowMenu( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -3);
|
|
INT32 NID = (INT32)lua_tonumber(lua_state, -2);
|
|
INT32 MenuID = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 3);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 1;
|
|
|
|
StringMap::iterator it = g_ExtraNPCManager.menu_string_.find(MenuID);
|
|
if (it == g_ExtraNPCManager.menu_string_.end()) {
|
|
SUNLOG(eCRITICAL_LOG, "[%s:%d] invalid menu id - %d", __FUNCTION__, __LINE__, MenuID);
|
|
return 1;
|
|
}
|
|
|
|
std::string& menu_dialog = it->second;
|
|
if (menu_dialog == "") {
|
|
SUNLOG(eCRITICAL_LOG, "[%s:%d] invalid menu id - %d", __FUNCTION__, __LINE__, MenuID);
|
|
return 1;
|
|
}
|
|
|
|
MSG_CG_NPCDIALOG_SHOWMENU_CMD packet(CID, NID, /*EID*/0, /*STEP*/0);
|
|
packet.data_length_ = menu_dialog.length();
|
|
memcpy(packet.data_, menu_dialog.c_str(), menu_dialog.length());
|
|
player->SendPacket(&packet, sizeof(packet));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ExtraNPCManager::execute_script_attendance(int CID, int NID, int EID, int STEP, \
|
|
CLuaStreamPack* lua_pack, int result)
|
|
{
|
|
if( /*CID == 0 || EID == 0 ||*/ !lua_pack )
|
|
return -1;
|
|
|
|
lua_State* lua_state = lua_handler_.state_;
|
|
if(lua_state == NULL)
|
|
return -1;
|
|
|
|
if (lua_pack->do_buffer(lua_state) == false)
|
|
return -1;
|
|
|
|
lua_getglobal(lua_state, "OnAttendance");
|
|
lua_pushnumber(lua_state, CID);
|
|
lua_pushnumber(lua_state, NID);
|
|
lua_pushnumber(lua_state, EID);
|
|
lua_pushnumber(lua_state, STEP);
|
|
|
|
lua_pushnumber(lua_state, result);
|
|
|
|
int status = lua_pcall(lua_state, 5, 1, 0);
|
|
|
|
if (status != 0)
|
|
{
|
|
char strCharBuff[256] = { 0, };
|
|
_snprintf(strCharBuff, sizeof(strCharBuff), "%s", lua_tostring(lua_state, -1));
|
|
//AuLogFile_s("Log\\LuaError.log", strCharBuff);
|
|
|
|
fprintf(stderr, "\t%s\n", strCharBuff);
|
|
lua_pop(lua_state, 1);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int ret = 0;
|
|
while (lua_gettop(lua_state))
|
|
{
|
|
switch (lua_type(lua_state, lua_gettop(lua_state)))
|
|
{
|
|
case LUA_TNUMBER:
|
|
ret = (int)lua_tonumber(lua_state, lua_gettop(lua_state));
|
|
break;
|
|
default:
|
|
ret = -1;
|
|
break;
|
|
}
|
|
lua_pop(lua_state, 1 );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ExtraNPCManager::ParseCGPacket(MSG_BASE* recv_msg)
|
|
{
|
|
MSG_CG_CHARINFO_SMARTNPC_PACKET* const packet = \
|
|
static_cast<MSG_CG_CHARINFO_SMARTNPC_PACKET*>(recv_msg);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByUserKey( packet->m_dwKey );
|
|
if( !player || !player->GetField()) return;
|
|
|
|
if (packet->CID != player->GetObjectKey()) {
|
|
SUNLOG(eCRITICAL_LOG, "[%s:%d] invalid character object key - %d", \
|
|
__FUNCTION__, __LINE__, player->GetCharGuid());
|
|
return;
|
|
}
|
|
|
|
if (IsLengthCanUseNPC(packet->NID, player, eNPC_TYPE_SMARTNPC) == false) {
|
|
return;
|
|
}
|
|
|
|
DWORD CID = packet->CID;
|
|
DWORD NID = packet->NID;
|
|
DWORD EID = packet->EID;
|
|
DWORD STEP = packet->STEP;
|
|
|
|
NPCInfoParser* const npc_parser = NPCInfoParser::Instance();
|
|
EXTRA_NPCINFO* const extra_info = npc_parser->GetExtraInfo(NID);
|
|
if (NULL == extra_info)
|
|
return;
|
|
CLuaStreamPack* lua_pack = g_ExtraNPCManager.find_lua_pack(extra_info->m_NPCCODE);
|
|
if (NULL == lua_pack)
|
|
return;
|
|
|
|
switch(packet->packet_type)
|
|
{
|
|
case NPCDIALOG_OPERATION_CMD:
|
|
{
|
|
MSG_CG_NPCDIALOG_OPERATION_CMD* packet2 = \
|
|
static_cast<MSG_CG_NPCDIALOG_OPERATION_CMD*>(packet);
|
|
|
|
execute_script_main(CID, NID, EID, STEP, lua_pack);
|
|
//
|
|
} break;
|
|
case NPCDIALOG_ON_CLICK_MENU_CMD:
|
|
{
|
|
MSG_CG_NPCDIALOG_ON_CLICK_MENU_CMD* packet2 = \
|
|
static_cast<MSG_CG_NPCDIALOG_ON_CLICK_MENU_CMD*>(packet);
|
|
|
|
execute_script_menu(CID, NID, EID, STEP, lua_pack);
|
|
//
|
|
} break;
|
|
case NPCDIALOG_ON_CLICK_SHOWMESSAGEBOX_CMD:
|
|
{
|
|
MSG_CG_NPCDIALOG_ON_CLICK_SHOWMESSAGEBOX_CMD* packet2 = \
|
|
static_cast<MSG_CG_NPCDIALOG_ON_CLICK_SHOWMESSAGEBOX_CMD*>(packet);
|
|
|
|
execute_script_messagebox(CID, NID, EID, STEP, lua_pack, \
|
|
packet2->data_, packet2->data_length_);
|
|
//
|
|
} break;
|
|
}
|
|
}
|
|
|
|
void ExtraNPCManager::ParseDGPacket( MSG_BASE* recv_msg )
|
|
{
|
|
MSG_DG_EVENT_SMARTNPC_SYSTEM* packet = static_cast<MSG_DG_EVENT_SMARTNPC_SYSTEM*>(recv_msg);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByUserKey( packet->m_dwKey );
|
|
if( !player || !player->GetField()) return;
|
|
|
|
if (packet->CID != player->GetObjectKey())
|
|
{
|
|
SUNLOG(eCRITICAL_LOG, "[%s:%d] invalid character object key - %d", \
|
|
__FUNCTION__, __LINE__, player->GetCharGuid());
|
|
return;
|
|
}
|
|
|
|
DWORD CID = packet->CID;
|
|
DWORD NID = packet->NID;
|
|
DWORD EID = packet->EID;
|
|
DWORD STEP = packet->STEP;
|
|
|
|
NPCInfoParser* const npc_parser = NPCInfoParser::Instance();
|
|
EXTRA_NPCINFO* const extra_info = npc_parser->GetExtraInfo(NID);
|
|
if (NULL == extra_info) {
|
|
return;
|
|
}
|
|
|
|
CLuaStreamPack* lua_pack = g_ExtraNPCManager.find_lua_pack(extra_info->m_NPCCODE);
|
|
if (NULL == lua_pack) {
|
|
return;
|
|
}
|
|
|
|
switch(packet->packet_type)
|
|
{
|
|
case DG_SMARTNPC_SET_ATTENDANCE_ACK:
|
|
{
|
|
MSG_SMARTNPC_SET_ATTENDANCE_ACK* packet2 = \
|
|
static_cast<MSG_SMARTNPC_SET_ATTENDANCE_ACK*>(packet);
|
|
|
|
execute_script_attendance(CID, NID, EID, STEP, lua_pack, packet2->result);
|
|
//
|
|
} break;
|
|
case DG_SMARTNPC_GET_ATTENDANCE_ACK:
|
|
{
|
|
MSG_SMARTNPC_GET_ATTENDANCE_ACK* packet2 = \
|
|
static_cast<MSG_SMARTNPC_GET_ATTENDANCE_ACK*>(packet);
|
|
|
|
execute_script_attendance(CID, NID, EID, STEP, lua_pack, packet2->result);
|
|
//
|
|
} break;
|
|
}
|
|
}
|
|
|
|
bool ExtraNPCManager::Decrypt( char* buffer, unsigned bufferSize )
|
|
{
|
|
const CHAR* NPCMANAGER_HASHKEY = "npcmanager_key";
|
|
AuMD5Encrypt md5;
|
|
|
|
return md5.DecryptString( NPCMANAGER_HASHKEY, buffer, bufferSize ) ? true : false;
|
|
}
|
|
|
|
int ExtraNPCManager::GetCharacterClass( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
const eCHAR_TYPE char_type = player->GetCharType();
|
|
|
|
lua_pushinteger(lua_state, char_type);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* 현재 루아 라이브러리가 int64를 지원하지 않으므로 사용 불가
|
|
int ExtraNPCManager::GetCharacterExp( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
const EXPTYPE char_exp = player->GetExp();
|
|
|
|
lua_pushunsigned(lua_state, char_exp);
|
|
|
|
return 1;
|
|
}
|
|
*/
|
|
|
|
int ExtraNPCManager::GetCharacterLevel( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
const LEVELTYPE char_level = player->GetLevel();
|
|
|
|
lua_pushinteger(lua_state, char_level);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::GetInventoryEmptySlotCount( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
ItemManager* const item_manager = player->GetItemManager();
|
|
SCSlotContainer* const inventory_container = item_manager->GetItemSlotContainer(SI_INVENTORY);
|
|
const POSTYPE empty_slot_count = inventory_container->GetEmptySlotNum();
|
|
|
|
lua_pushinteger(lua_state, empty_slot_count);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::CheckItemCount( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -2);
|
|
SLOTCODE ItemTID = (SLOTCODE)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 2);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
ItemManager* const item_manager = player->GetItemManager();
|
|
int item_count = item_manager->ExistItem(SI_INVENTORY, ItemTID, USHRT_MAX);
|
|
|
|
lua_pushinteger(lua_state, item_count);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::RobItem( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -3);
|
|
SLOTCODE ItemTID = (SLOTCODE)lua_tonumber(lua_state, -2);
|
|
POSTYPE Count = (POSTYPE)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 3);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
MSG_CG_ITEM_LOSE_ACK msg_ack;
|
|
ItemManager* const item_manager = player->GetItemManager();
|
|
RC::eITEM_RESULT result = item_manager->DeleteAllKindOfItem( \
|
|
1, &ItemTID, &Count, &msg_ack.m_ItemInfo);
|
|
|
|
if (result == RC::RC_ITEM_SUCCESS) {
|
|
player->SendPacket(&msg_ack, msg_ack.GetSize());
|
|
GAMELOG->LogMultiItem( ITEM_SMARTNPC_ROB, player, 1, &ItemTID, &Count );
|
|
}
|
|
|
|
lua_pushinteger(lua_state, (result == RC::RC_ITEM_SUCCESS));
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::GiveItem( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -3);
|
|
SLOTCODE ItemTID = (SLOTCODE)lua_tonumber(lua_state, -2);
|
|
POSTYPE Count = (POSTYPE)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 3);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL)
|
|
return 0;
|
|
|
|
MSG_CG_ITEM_PICK_ACK msg_ack;
|
|
ItemManager* const item_manager = player->GetItemManager();
|
|
RC::eITEM_RESULT result = item_manager->ObtainAllKindOfItem( \
|
|
1, &ItemTID, &Count, &msg_ack.m_ItemInfo);
|
|
|
|
if (result == RC::RC_ITEM_SUCCESS) {
|
|
player->SendPacket(&msg_ack, msg_ack.GetSize());
|
|
GAMELOG->LogMultiItem( ITEM_SMARTNPC_GIVE, player, 1, &ItemTID, &Count );
|
|
}
|
|
|
|
lua_pushinteger(lua_state, (result == RC::RC_ITEM_SUCCESS));
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::ZoneChange(lua_State* lua_state)
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -2);
|
|
ZONEKEY ZoneCode = (ZONEKEY)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 2);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
MSG_AG_ZONE_PORTAL_FIELD_MOVE_ACK ack;
|
|
ack.m_wIndex = ZoneCode;
|
|
player->SendPacket( &ack, sizeof(ack) );
|
|
|
|
lua_pushinteger(lua_state, 1); // success
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::CheckPotalToDominationField( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -2);
|
|
ZONEKEY ZoneCode = (ZONEKEY)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 2);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
const RC::ePORTAL_RESULT retValue = player->CanPortal();
|
|
if (RC::RC_PORTAL_CAN_SUCCESS != retValue)
|
|
{
|
|
lua_pushinteger(lua_state, -1); // fail
|
|
return 1;
|
|
}
|
|
|
|
//점령전 맵으로 이동할 경우
|
|
GameDominationManager* const domination_manager = GameDominationManager::Instance();
|
|
if (domination_manager->IsDominationArea(ZoneCode) == false ||
|
|
domination_manager->CanEnterDominationField(player, ZoneCode) == false)
|
|
{
|
|
lua_pushinteger(lua_state, -2); // fail
|
|
return 1;
|
|
}
|
|
|
|
lua_pushinteger(lua_state, 1); // success
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::SendDominationMinimapList( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
GameDominationManager* const domination_manager = GameDominationManager::Instance();
|
|
|
|
MSG_CG_DOMINATION_MINIMAP_LIST_ACK sendMsg;
|
|
sendMsg.m_ResultCode = RC::DOMINATION_RESULT_SUCCESS;
|
|
sendMsg.m_NumDominationGuild =
|
|
domination_manager->GetMiniMapInfo(sendMsg.m_GuildInfo, _countof(sendMsg.m_GuildInfo));
|
|
player->SendPacket(&sendMsg, sendMsg.GetSize());
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ExtraNPCManager::SetAttendance( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -6);
|
|
INT32 NID = (INT32)lua_tonumber(lua_state, -5);
|
|
INT32 EID = (INT32)lua_tonumber(lua_state, -4);
|
|
INT32 STEP = (INT32)lua_tonumber(lua_state, -3);
|
|
INT32 attendance_type = (INT32)lua_tonumber(lua_state, -2);
|
|
INT32 attendance_data = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 6);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
switch(attendance_type)
|
|
{
|
|
case /*eAttendanceType::*/MONDSCHIEN_DOMINATION:
|
|
{
|
|
MSG_SMARTNPC_SET_ATTENDANCE_SYN msg(CID, NID, EID, STEP);
|
|
msg.attendance_type = /*eAttendanceType::*/MONDSCHIEN_DOMINATION;
|
|
msg.attendance_data = attendance_data;
|
|
player->SendToGameDBPServer(&msg, sizeof(msg));
|
|
} break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ExtraNPCManager::IsDominationGoing( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -2);
|
|
ZONEKEY MapCode = (ZONEKEY)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 2);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
GameDominationManager* const domination_manager = GameDominationManager::Instance();
|
|
// IsDeleteMember 함수를 점령전 진행중인지 확인하는 용도로 활용
|
|
bool is_going = !(domination_manager->IsDeleteMember(MapCode));
|
|
|
|
lua_pushinteger(lua_state, is_going);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::GetAttendance( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -6);
|
|
INT32 NID = (INT32)lua_tonumber(lua_state, -5);
|
|
INT32 EID = (INT32)lua_tonumber(lua_state, -4);
|
|
INT32 STEP = (INT32)lua_tonumber(lua_state, -3);
|
|
INT32 attendance_type = (INT32)lua_tonumber(lua_state, -2);
|
|
INT32 attendance_time = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 6);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
switch(attendance_type)
|
|
{
|
|
case /*eAttendanceType::*/MONDSCHIEN_DOMINATION:
|
|
{
|
|
MSG_SMARTNPC_GET_ATTENDANCE_SYN msg(CID, NID, EID, STEP);
|
|
msg.attendance_type = /*eAttendanceType::*/MONDSCHIEN_DOMINATION;
|
|
msg.attendance_time = attendance_time;
|
|
player->SendToGameDBPServer(&msg, sizeof(msg));
|
|
} break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _NA_007488_20140811_MONDSCHUEN_INITIALIZE_N_REWARD
|
|
int ExtraNPCManager::GetDominationGuildGuid( lua_State* lua_state )
|
|
{
|
|
ZONEKEY MapCode = (ZONEKEY)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
GameDominationManager* const domination_manager = GameDominationManager::Instance();
|
|
|
|
const DOMINATION_INFO* domi_info = domination_manager->GetDominationInfo(MapCode);
|
|
if (domi_info == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
lua_pushinteger(lua_state, domi_info->m_inGuildInfo.m_GuildGuid);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExtraNPCManager::GetCharacterGuildGuid( lua_State* lua_state )
|
|
{
|
|
INT32 CID = (INT32)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
lua_pushinteger(lua_state, player->GetGuildGuid());
|
|
|
|
return 1;
|
|
}
|
|
#endif // _NA_000000_20140811_MONDSCHUEN_INITIALIZE_N_REWARD
|
|
|
|
int ExtraNPCManager::IsDominationChannel( lua_State* lua_state )
|
|
{
|
|
DWORD CID = (DWORD)lua_tonumber(lua_state, -1);
|
|
|
|
lua_pop(lua_state, 1);
|
|
|
|
Player* player = PlayerManager::Instance()->FindPlayerByObjKey(CID);
|
|
if (player == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _NA_20110610_MOVE_DOMINATION_CHANNEL_INFO
|
|
const BYTE channel_id = GameOptionParser::Instance()->GetGameOption().m_byDominationChannel;
|
|
#else
|
|
const BYTE channel_id = ServerOptionParserEx::Instance()->GetServerOption().m_byDominationChannel;
|
|
#endif
|
|
if (channel_id != g_pGameServer->GetKey().GetChannelID())
|
|
{
|
|
lua_pushinteger(lua_state, 0); // fail
|
|
return 1;
|
|
}
|
|
|
|
lua_pushinteger(lua_state, 1); // success
|
|
return 1;
|
|
}
|
|
|
|
#endif //_NA_000000_20140120_SMART_NPC_SYSTEM
|