2024-06-01 15:59:51 -05:00

2004 lines
48 KiB
C++
Raw 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 <fstream>
#include "constants.h"
#include "buffer_manager.h"
#include "packet.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "char.h"
#include "char_manager.h"
#include "questmanager.h"
#include "text_file_loader.h"
#include "lzo_manager.h"
#include "item.h"
#include "config.h"
#include "xmas_event.h"
#include "target.h"
#include "party.h"
#include "locale_service.h"
#include "dungeon.h"
DWORD g_GoldDropTimeLimitValue = 0;
#ifdef ENABLE_NEWSTUFF
DWORD g_ItemDropTimeLimitValue = 0;
DWORD g_BoxUseTimeLimitValue = 0;
DWORD g_BuySellTimeLimitValue = 0;
bool g_NoDropMetinStone = false;
bool g_NoMountAtGuildWar = false;
bool g_NoPotionsOnPVP = false;
#endif
extern bool DropEvent_CharStone_SetValue(const std::string& name, int value);
extern bool DropEvent_RefineBox_SetValue (const std::string& name, int value);
namespace quest
{
using namespace std;
CQuestManager::CQuestManager()
: m_pSelectedDungeon(NULL), m_dwServerTimerArg(0), m_iRunningEventIndex(0), L(NULL), m_bNoSend (false),
m_CurrentRunningState(NULL), m_pCurrentCharacter(NULL), m_pCurrentNPCCharacter(NULL), m_pCurrentPartyMember(NULL),
m_pCurrentPC(NULL), m_iCurrentSkin(0), m_bError(false), m_pOtherPCBlockRootPC(NULL)
{
}
CQuestManager::~CQuestManager()
{
Destroy();
}
void CQuestManager::Destroy()
{
if (L)
{
lua_close(L);
L = NULL;
}
}
bool CQuestManager::Initialize()
{
if (g_bAuthServer)
return true;
if (!InitializeLua())
return false;
m_pSelectedDungeon = NULL;
m_mapEventName.emplace("click", QUEST_CLICK_EVENT);
m_mapEventName.emplace("kill", QUEST_KILL_EVENT);
m_mapEventName.emplace("timer", QUEST_TIMER_EVENT);
m_mapEventName.emplace("levelup", QUEST_LEVELUP_EVENT);
m_mapEventName.emplace("login", QUEST_LOGIN_EVENT);
m_mapEventName.emplace("logout", QUEST_LOGOUT_EVENT);
m_mapEventName.emplace("button", QUEST_BUTTON_EVENT);
m_mapEventName.emplace("info", QUEST_INFO_EVENT);
m_mapEventName.emplace("chat", QUEST_CHAT_EVENT);
m_mapEventName.emplace("in", QUEST_ATTR_IN_EVENT);
m_mapEventName.emplace("out", QUEST_ATTR_OUT_EVENT);
m_mapEventName.emplace("use", QUEST_ITEM_USE_EVENT);
m_mapEventName.emplace("server_timer", QUEST_SERVER_TIMER_EVENT);
m_mapEventName.emplace("enter", QUEST_ENTER_STATE_EVENT);
m_mapEventName.emplace("leave", QUEST_LEAVE_STATE_EVENT);
m_mapEventName.emplace("letter", QUEST_LETTER_EVENT);
m_mapEventName.emplace("take", QUEST_ITEM_TAKE_EVENT);
m_mapEventName.emplace("target", QUEST_TARGET_EVENT);
m_mapEventName.emplace("party_kill", QUEST_PARTY_KILL_EVENT);
m_mapEventName.emplace("unmount", QUEST_UNMOUNT_EVENT);
m_mapEventName.emplace("pick", QUEST_ITEM_PICK_EVENT);
m_mapEventName.emplace("sig_use", QUEST_SIG_USE_EVENT);
m_mapEventName.emplace("item_informer", QUEST_ITEM_INFORMER_EVENT);
#ifdef ENABLE_QUEST_DIE_EVENT
m_mapEventName.emplace("die", QUEST_DIE_EVENT);
#endif
#ifdef ENABLE_QUEST_BOOT_EVENT
m_mapEventName.emplace("boot", QUEST_BOOT_EVENT);
#endif
#ifdef ENABLE_QUEST_DND_EVENT
m_mapEventName.emplace("dnd", QUEST_DND_EVENT);
#endif
m_bNoSend = false;
m_iCurrentSkin = QUEST_SKIN_NORMAL;
{
ifstream inf((g_stQuestDir + "/questnpc.txt").c_str());
int line = 0;
if (!inf.is_open())
sys_err( "QUEST Cannot open 'questnpc.txt'");
else
sys_log(0, "QUEST can open 'questnpc.txt' (%s)", g_stQuestDir.c_str() );
while (1)
{
unsigned int vnum;
inf >> vnum;
line++;
if (inf.fail())
break;
string s;
getline(inf, s);
unsigned int li = 0, ri = s.size()-1;
while (li < s.size() && isspace(s[li])) li++;
while (ri > 0 && isspace(s[ri])) ri--;
if (ri < li)
{
sys_err("QUEST questnpc.txt:%d:npc name error",line);
continue;
}
s = s.substr(li, ri-li+1);
int n = 0;
str_to_number(n, s.c_str());
if (n)
continue;
//cout << '-' << s << '-' << endl;
if ( test_server )
sys_log(0, "QUEST reading script of %s(%d)", s.c_str(), vnum);
m_mapNPC[vnum].Set(vnum, s);
m_mapNPCNameID[s] = vnum;
}
// notarget quest
m_mapNPC[0].Set(0, "notarget");
}
SetEventFlag("guild_withdraw_delay", 1);
SetEventFlag("guild_disband_delay", 1);
return true;
}
unsigned int CQuestManager::FindNPCIDByName(const string& name)
{
map<string, unsigned int>::iterator it = m_mapNPCNameID.find(name);
return it != m_mapNPCNameID.end() ? it->second : 0;
}
void CQuestManager::SelectItem(unsigned int pc, unsigned int selection)
{
PC* pPC = GetPC(pc);
if (pPC && pPC->IsRunning() && pPC->GetRunningQuestState()->suspend_state == SUSPEND_STATE_SELECT_ITEM)
{
pPC->SetSendDoneFlag();
pPC->GetRunningQuestState()->args=1;
lua_pushnumber(pPC->GetRunningQuestState()->co,selection);
if (!RunState(*pPC->GetRunningQuestState()))
{
CloseState(*pPC->GetRunningQuestState());
pPC->EndRunning();
}
}
}
void CQuestManager::Confirm(unsigned int pc, EQuestConfirmType confirm, unsigned int pc2)
{
PC* pPC = GetPC(pc);
if (!pPC->IsRunning())
{
sys_err("no quest running for pc, cannot process input : %u", pc);
return;
}
if (pPC->GetRunningQuestState()->suspend_state != SUSPEND_STATE_CONFIRM)
{
sys_err("not wait for a confirm : %u %d", pc, pPC->GetRunningQuestState()->suspend_state);
return;
}
if (pc2 && !pPC->IsConfirmWait(pc2))
{
sys_err("not wait for a confirm : %u %d", pc, pPC->GetRunningQuestState()->suspend_state);
return;
}
pPC->ClearConfirmWait();
pPC->SetSendDoneFlag();
pPC->GetRunningQuestState()->args=1;
lua_pushnumber(pPC->GetRunningQuestState()->co, confirm);
AddScript("[END_CONFIRM_WAIT]");
SetSkinStyle(QUEST_SKIN_NOWINDOW);
SendScript();
if (!RunState(*pPC->GetRunningQuestState()))
{
CloseState(*pPC->GetRunningQuestState());
pPC->EndRunning();
}
}
int CQuestManager::ReadQuestCategoryFile(WORD q_index)
{
ifstream inf((g_stQuestDir + "/questcategory.txt").c_str());
int line = 0;
int c_qi = 99;
if (!inf.is_open())
sys_err( "QUEST Cannot open 'questcategory.txt'");
else
sys_log(0, "QUEST can open 'questcategory.txt' (%s)", g_stQuestDir.c_str() );
while (1)
{
string qn = CQuestManager::instance().GetQuestNameByIndex(q_index);
unsigned int category_num;
//enum
//{
// MAIN_QUEST, //0
// SUB_QUEST, //1
// COLLECT_QUEST, //2
// LEVELUP_QUEST, //3
// SCROLL_QUEST, //4
// SYSTEM_QUEST, //5
//};
inf >> category_num;
line++;
if (inf.fail())
break;
string s;
getline(inf, s);
unsigned int li = 0, ri = s.size()-1;
while (li < s.size() && isspace(s[li])) li++;
while (ri > 0 && isspace(s[ri])) ri--;
if (ri < li)
{
sys_err("QUEST questcategory.txt:%d:npc name error",line);
continue;
}
s = s.substr(li, ri-li+1);
int n = 0;
str_to_number(n, s.c_str());
if (n)
continue;
//cout << '-' << s << '-' << endl;
if ( test_server )
sys_log(0, "QUEST reading script of %s(%d)", s.c_str(), category_num);
if (qn == s)
{
c_qi = category_num;
break;
}
}
// notarget quest
//m_mapNPC[0].Set(0, "notarget");
return c_qi;
}
void CQuestManager::Input(unsigned int pc, const char* msg)
{
PC* pPC = GetPC(pc);
if (!pPC)
{
sys_err("no pc! : %u",pc);
return;
}
if (!pPC->IsRunning())
{
sys_err("no quest running for pc, cannot process input : %u", pc);
return;
}
if (pPC->GetRunningQuestState()->suspend_state != SUSPEND_STATE_INPUT)
{
sys_err("not wait for a input : %u %d", pc, pPC->GetRunningQuestState()->suspend_state);
return;
}
pPC->SetSendDoneFlag();
pPC->GetRunningQuestState()->args=1;
lua_pushstring(pPC->GetRunningQuestState()->co,msg);
if (!RunState(*pPC->GetRunningQuestState()))
{
CloseState(*pPC->GetRunningQuestState());
pPC->EndRunning();
}
}
void CQuestManager::Select(unsigned int pc, unsigned int selection)
{
PC* pPC;
if ((pPC = GetPC(pc)) && pPC->IsRunning() && pPC->GetRunningQuestState()->suspend_state==SUSPEND_STATE_SELECT)
{
pPC->SetSendDoneFlag();
if (!pPC->GetRunningQuestState()->chat_scripts.empty())
{
QuestState& old_qs = *pPC->GetRunningQuestState();
CloseState(old_qs);
if (selection >= pPC->GetRunningQuestState()->chat_scripts.size())
{
pPC->SetSendDoneFlag();
GotoEndState(old_qs);
pPC->EndRunning();
}
else
{
AArgScript* pas = pPC->GetRunningQuestState()->chat_scripts[selection];
ExecuteQuestScript(*pPC, pas->quest_index, pas->state_index, pas->script.GetCode(), pas->script.GetSize());
}
}
else
{
// on default
pPC->GetRunningQuestState()->args=1;
lua_pushnumber(pPC->GetRunningQuestState()->co,selection+1);
if (!RunState(*pPC->GetRunningQuestState()))
{
CloseState(*pPC->GetRunningQuestState());
pPC->EndRunning();
}
}
}
else
{
sys_err("wrong QUEST_SELECT request! : %d",pc);
}
}
void CQuestManager::Resume(unsigned int pc)
{
PC * pPC;
if ((pPC = GetPC(pc)) && pPC->IsRunning() && pPC->GetRunningQuestState()->suspend_state == SUSPEND_STATE_PAUSE)
{
pPC->SetSendDoneFlag();
pPC->GetRunningQuestState()->args = 0;
if (!RunState(*pPC->GetRunningQuestState()))
{
CloseState(*pPC->GetRunningQuestState());
pPC->EndRunning();
}
}
else
{
//cerr << pPC << endl;
//cerr << pPC->IsRunning() << endl;
//cerr << pPC->GetRunningQuestState()->suspend_state;
//cerr << SUSPEND_STATE_WAIT << endl;
//cerr << "wrong QUEST_WAIT request! : " << pc << endl;
sys_err("wrong QUEST_WAIT request! : %d",pc);
}
}
void CQuestManager::EnterState(DWORD pc, DWORD quest_index, int state)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnEnterState(*pPC, quest_index, state);
}
else
sys_err("QUEST no such pc id : %d", pc);
}
void CQuestManager::LeaveState(DWORD pc, DWORD quest_index, int state)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnLeaveState(*pPC, quest_index, state);
}
else
sys_err("QUEST no such pc id : %d", pc);
}
void CQuestManager::Letter(DWORD pc, DWORD quest_index, int state)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnLetter(*pPC, quest_index, state);
}
else
sys_err("QUEST no such pc id : %d", pc);
}
void CQuestManager::LogoutPC(LPCHARACTER ch)
{
PC * pPC = GetPC(ch->GetPlayerID());
if (pPC && pPC->IsRunning())
{
CloseState(*pPC->GetRunningQuestState());
pPC->CancelRunning();
}
Logout(ch->GetPlayerID());
if (ch == m_pCurrentCharacter)
{
m_pCurrentCharacter = NULL;
m_pCurrentPC = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
void CQuestManager::Login(unsigned int pc, const char * c_pszQuest)
{
PC * pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnLogin(*pPC, c_pszQuest);
}
else
{
sys_err("QUEST no such pc id : %d", pc);
}
}
void CQuestManager::Logout(unsigned int pc)
{
PC * pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnLogout(*pPC);
}
else
sys_err("QUEST no such pc id : %d", pc);
}
#define ENABLE_PARTYKILL
void CQuestManager::Kill(unsigned int pc, unsigned int npc)
{
//m_CurrentNPCRace = npc;
PC * pPC;
sys_log(0, "CQuestManager::Kill QUEST_KILL_EVENT (pc=%d, npc=%d)", pc, npc);
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
// kill call script
if (npc >= MAIN_RACE_MAX_NUM) //@fixme109
m_mapNPC[npc].OnKill(*pPC); //@warme004
m_mapNPC[QUEST_NO_NPC].OnKill(*pPC);
#ifdef ENABLE_PARTYKILL
// party_kill call script
LPCHARACTER ch = GetCurrentCharacterPtr();
LPPARTY pParty = ch->GetParty();
LPCHARACTER leader = pParty ? pParty->GetLeaderCharacter() : ch;
if (leader)
{
m_pCurrentPartyMember = ch;
if (npc >= MAIN_RACE_MAX_NUM) //@fixme109
m_mapNPC[npc].OnPartyKill(*GetPC(leader->GetPlayerID())); //@warme004
m_mapNPC[QUEST_NO_NPC].OnPartyKill(*GetPC(leader->GetPlayerID()));
pPC = GetPC(pc);
}
#endif
}
else
sys_err("QUEST: no such pc id : %d", pc);
}
#ifdef ENABLE_QUEST_DIE_EVENT
void CQuestManager::Die(unsigned int pc, unsigned int npc)
{
PC * pPC;
sys_log(0, "CQuestManager::Kill QUEST_DIE_EVENT (pc=%d, npc=%d)", pc, npc);
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnDie(*pPC);
}
else
sys_err("QUEST: no such pc id : %d", pc);
}
#endif
#ifdef ENABLE_QUEST_BOOT_EVENT
bool CQuestManager::Boot()
{
sys_log(0, "XXX Boot Call NPC %p", GetPCForce(0));
m_pCurrentPC = GetPCForce(0);
m_pCurrentCharacter = NULL;
m_pSelectedDungeon = NULL;
return m_mapNPC[QUEST_NO_NPC].OnBoot(*m_pCurrentPC);
}
#endif
#ifdef ENABLE_QUEST_DND_EVENT
bool CQuestManager::DND(uint32_t pc, LPITEM item_dnd, LPITEM item_victim, bool bReceiveAll)
{
if (test_server)
sys_log( 0, "CQuestManager::DND_EVENT Start: item_dnd(%d), item_victim(%d), PC(%d)", item_dnd->GetOriginalVnum(), item_victim->GetOriginalVnum(), pc);
PC * pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
return false;
}
// call script
SetCurrentItem(item_victim);
SetCurrentDNDItem(item_dnd);
return m_mapNPC[item_dnd->GetVnum()].OnDND(*pPC, bReceiveAll);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST DND_EVENT no such pc id : %d", pc);
return false;
}
}
#endif
bool CQuestManager::ServerTimer(unsigned int npc, unsigned int arg)
{
SetServerTimerArg(arg);
sys_log(0, "XXX ServerTimer Call NPC %p vnum %u arg %u", GetPCForce(0), npc, arg);
m_pCurrentPC = GetPCForce(0);
m_pCurrentCharacter = NULL;
m_pSelectedDungeon = NULL;
return m_mapNPC[npc].OnServerTimer(*m_pCurrentPC);
}
bool CQuestManager::Timer(unsigned int pc, unsigned int npc)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
{
return false;
}
// call script
return m_mapNPC[npc].OnTimer(*pPC);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST TIMER_EVENT no such pc id : %d", pc);
return false;
}
//cerr << "QUEST TIMER" << endl;
}
void CQuestManager::LevelUp(unsigned int pc)
{
PC * pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnLevelUp(*pPC);
}
else
{
sys_err("QUEST LEVELUP_EVENT no such pc id : %d", pc);
}
}
void CQuestManager::AttrIn(unsigned int pc, LPCHARACTER ch, int attr)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
m_pCurrentPartyMember = ch;
if (!CheckQuestLoaded(pPC))
return;
// call script
m_mapNPC[attr+QUEST_ATTR_NPC_START].OnAttrIn(*pPC);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST no such pc id : %d", pc);
}
}
void CQuestManager::AttrOut(unsigned int pc, LPCHARACTER ch, int attr)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
//m_pCurrentCharacter = ch;
m_pCurrentPartyMember = ch;
if (!CheckQuestLoaded(pPC))
return;
// call script
m_mapNPC[attr+QUEST_ATTR_NPC_START].OnAttrOut(*pPC);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST no such pc id : %d", pc);
}
}
bool CQuestManager::Target(unsigned int pc, DWORD dwQuestIndex, const char * c_pszTargetName, const char * c_pszVerb)
{
PC * pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return false;
bool bRet;
return m_mapNPC[QUEST_NO_NPC].OnTarget(*pPC, dwQuestIndex, c_pszTargetName, c_pszVerb, bRet);
}
return false;
}
void CQuestManager::QuestInfo(unsigned int pc, unsigned int quest_index)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
// call script
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
return;
}
m_bQuestInfoFlag = 1;
m_mapNPC[QUEST_NO_NPC].OnInfo(*pPC, quest_index);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST INFO_EVENT no such pc id : %d", pc);
}
}
void CQuestManager::QuestButton(unsigned int pc, unsigned int quest_index)
{
PC* pPC;
if ((pPC = GetPC(pc)))
{
// call script
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
}
return;
}
m_mapNPC[QUEST_NO_NPC].OnButton(*pPC, quest_index);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST CLICK_EVENT no such pc id : %d", pc);
}
}
bool CQuestManager::TakeItem(unsigned int pc, unsigned int npc, LPITEM item)
{
//m_CurrentNPCRace = npc;
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
}
return false;
}
// call script
SetCurrentItem(item);
return m_mapNPC[npc].OnTakeItem(*pPC);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST USE_ITEM_EVENT no such pc id : %d", pc);
return false;
}
}
bool CQuestManager::UseItem(unsigned int pc, LPITEM item, bool bReceiveAll)
{
if (test_server)
sys_log( 0, "questmanager::UseItem Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
}
return false;
}
// call script
SetCurrentItem(item);
/*
if (test_server)
{
sys_log( 0, "Quest UseItem Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
itertype(m_mapNPC) it = m_mapNPC.begin();
itertype(m_mapNPC) end = m_mapNPC.end();
for( ; it != end ; ++it)
{
sys_log( 0, "Quest UseItem : vnum : %d item Vnum : %d", it->first, item->GetOriginalVnum());
}
}
if(test_server)
sys_log( 0, "questmanager:useItem: mapNPCVnum : %d\n", m_mapNPC[item->GetVnum()].GetVnum());
*/
return m_mapNPC[item->GetVnum()].OnUseItem(*pPC, bReceiveAll);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST USE_ITEM_EVENT no such pc id : %d", pc);
return false;
}
}
bool CQuestManager::SIGUse(unsigned int pc, DWORD sig_vnum, LPITEM item, bool bReceiveAll)
{
if (test_server)
sys_log( 0, "questmanager::SIGUse Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
}
return false;
}
// call script
SetCurrentItem(item);
return m_mapNPC[sig_vnum].OnSIGUse(*pPC, bReceiveAll);
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST USE_ITEM_EVENT no such pc id : %d", pc);
return false;
}
}
bool CQuestManager::GiveItemToPC(unsigned int pc, LPCHARACTER pkChr)
{
if (!pkChr->IsPC())
return false;
PC * pPC = GetPC(pc);
if (pPC)
{
if (!CheckQuestLoaded(pPC))
return false;
TargetInfo * pInfo = CTargetManager::instance().GetTargetInfo(pc, TARGET_TYPE_VID, pkChr->GetVID());
if (pInfo)
{
bool bRet;
if (m_mapNPC[QUEST_NO_NPC].OnTarget(*pPC, pInfo->dwQuestIndex, pInfo->szTargetName, "click", bRet))
return true;
}
}
return false;
}
bool CQuestManager::Click(unsigned int pc, LPCHARACTER pkChrTarget)
{
PC * pPC = GetPC(pc);
if (pPC)
{
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
return false;
}
TargetInfo * pInfo = CTargetManager::instance().GetTargetInfo(pc, TARGET_TYPE_VID, pkChrTarget->GetVID());
if (test_server)
{
sys_log(0, "CQuestManager::Click(pid=%d, npc_name=%s) - target_info(%x)", pc, pkChrTarget->GetName(), pInfo);
}
if (pInfo)
{
bool bRet;
if (m_mapNPC[QUEST_NO_NPC].OnTarget(*pPC, pInfo->dwQuestIndex, pInfo->szTargetName, "click", bRet))
return bRet;
}
DWORD dwCurrentNPCRace = pkChrTarget->GetRaceNum();
if (pkChrTarget->IsNPC())
{
map<unsigned int, NPC>::iterator it = m_mapNPC.find(dwCurrentNPCRace);
if (it == m_mapNPC.end())
{
sys_log(0, "CQuestManager::Click(pid=%d, target_npc_name=%s) - NOT EXIST NPC RACE VNUM[%d]",
pc,
pkChrTarget->GetName(),
dwCurrentNPCRace); // @warme012
return false;
}
// call script
if (it->second.HasChat())
{
// if have chat, give chat
if (test_server)
sys_log(0, "CQuestManager::Click->OnChat");
if (!it->second.OnChat(*pPC))
{
if (test_server)
sys_log(0, "CQuestManager::Click->OnChat Failed");
return it->second.OnClick(*pPC);
}
return true;
}
else
{
// else click
return it->second.OnClick(*pPC);
}
}
return false;
}
else
{
//cout << "no such pc id : " << pc;
sys_err("QUEST CLICK_EVENT no such pc id : %d", pc);
return false;
}
//cerr << "QUEST CLICk" << endl;
}
void CQuestManager::Unmount(unsigned int pc)
{
PC * pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
return;
m_mapNPC[QUEST_NO_NPC].OnUnmount(*pPC);
}
else
sys_err("QUEST no such pc id : %d", pc);
}
void CQuestManager::ItemInformer(unsigned int pc,unsigned int vnum)
{
PC* pPC;
pPC = GetPC(pc);
m_mapNPC[QUEST_NO_NPC].OnItemInformer(*pPC,vnum);
}
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
void CQuestManager::LoadStartQuest(const string& quest_name, unsigned int idx)
{
for (itertype(g_setQuestObjectDir) it = g_setQuestObjectDir.begin(); it != g_setQuestObjectDir.end(); ++it)
{
const string& stQuestObjectDir = *it;
string full_name = stQuestObjectDir + "/begin_condition/" + quest_name;
ifstream inf(full_name.c_str());
if (inf.is_open())
{
sys_log(0, "QUEST loading begin condition for %s", quest_name.c_str());
istreambuf_iterator<char> ib(inf), ie;
copy(ib, ie, back_inserter(m_hmQuestStartScript[idx]));
}
}
}
bool CQuestManager::CanStartQuest(unsigned int quest_index, const PC& pc)
{
return CanStartQuest(quest_index);
}
bool CQuestManager::CanStartQuest(unsigned int quest_index)
{
THashMapQuestStartScript::iterator it;
if ((it = m_hmQuestStartScript.find(quest_index)) == m_hmQuestStartScript.end())
return true;
else
{
int x = lua_gettop(L);
lua_dobuffer(L, &(it->second[0]), it->second.size(), "StartScript");
int bStart = lua_toboolean(L, -1);
lua_settop(L, x);
return bStart != 0;
}
}
bool CQuestManager::CanEndQuestAtState(const string& quest_name, const string& state_name)
{
return false;
}
void CQuestManager::DisconnectPC(LPCHARACTER ch)
{
m_mapPC.erase(ch->GetPlayerID());
}
PC * CQuestManager::GetPCForce(unsigned int pc)
{
PCMap::iterator it;
if ((it = m_mapPC.find(pc)) == m_mapPC.end())
{
PC * pPC = &m_mapPC[pc];
pPC->SetID(pc);
return pPC;
}
return &it->second;
}
PC * CQuestManager::GetPC(unsigned int pc)
{
PCMap::iterator it;
LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindByPID(pc);
if (!pkChr)
return NULL;
m_pCurrentPC = GetPCForce(pc);
m_pCurrentCharacter = pkChr;
m_pSelectedDungeon = NULL;
return (m_pCurrentPC);
}
void CQuestManager::ClearScript()
{
m_strScript.clear();
m_iCurrentSkin = QUEST_SKIN_NORMAL;
}
void CQuestManager::AddScript(const string& str)
{
m_strScript+=str;
}
void CQuestManager::SendScript()
{
if (m_bNoSend)
{
m_bNoSend = false;
ClearScript();
return;
}
if (m_strScript=="[DONE]" || m_strScript == "[NEXT]")
{
if (m_pCurrentPC && !m_pCurrentPC->GetAndResetDoneFlag() && m_strScript=="[DONE]" && m_iCurrentSkin == QUEST_SKIN_NORMAL && !IsError())
{
ClearScript();
return;
}
m_iCurrentSkin = QUEST_SKIN_NOWINDOW;
}
//sys_log(0, "Send Quest Script to %s", GetCurrentCharacterPtr()->GetName());
//send -_-!
struct ::packet_script packet_script;
packet_script.header = HEADER_GC_SCRIPT;
packet_script.skin = m_iCurrentSkin;
packet_script.src_size = m_strScript.size();
packet_script.size = packet_script.src_size + sizeof(struct packet_script);
#ifdef ENABLE_QUEST_CATEGORY
packet_script.quest_flag = 0;
if(m_bQuestInfoFlag == 1)
packet_script.quest_flag = 1;
#endif
TEMP_BUFFER buf;
buf.write(&packet_script, sizeof(struct packet_script));
buf.write(&m_strScript[0], m_strScript.size());
if (GetCurrentCharacterPtr() && GetCurrentCharacterPtr()->GetDesc()) // @fixme174 (ch check)
GetCurrentCharacterPtr()->GetDesc()->Packet(buf.read_peek(), buf.size());
if (test_server)
sys_log(0, "m_strScript %s size %d", m_strScript.c_str(), buf.size());
#ifdef ENABLE_QUEST_CATEGORY
sys_log(0, "SendScript=====================On Quest flag %d", packet_script.quest_flag);
#endif
ClearScript();
m_bQuestInfoFlag = 0;
}
const char* CQuestManager::GetQuestStateName(const string& quest_name, const int state_index)
{
int x = lua_gettop(L);
lua_getglobal(L, quest_name.c_str());
if (lua_isnil(L,-1))
{
sys_err("QUEST wrong quest state file %s.%d", quest_name.c_str(), state_index);
lua_settop(L,x);
return "";
}
lua_pushnumber(L, state_index);
lua_gettable(L, -2);
const char* str = lua_tostring(L, -1);
lua_settop(L, x);
return str;
}
int CQuestManager::GetQuestStateIndex(const string& quest_name, const string& state_name)
{
int x = lua_gettop(L);
lua_getglobal(L, quest_name.c_str());
if (lua_isnil(L,-1))
{
sys_err("QUEST wrong quest state file %s.%s",quest_name.c_str(),state_name.c_str());
lua_settop(L,x);
return 0;
}
lua_pushstring(L, state_name.c_str());
lua_gettable(L, -2);
int v = (int)rint(lua_tonumber(L,-1));
lua_settop(L, x);
if ( test_server )
sys_log( 0,"[QUESTMANAGER] GetQuestStateIndex x(%d) v(%d) %s %s", v,x, quest_name.c_str(), state_name.c_str() );
return v;
}
void CQuestManager::SetSkinStyle(int iStyle)
{
if (iStyle<0 || iStyle >= QUEST_SKIN_COUNT)
{
m_iCurrentSkin = QUEST_SKIN_NORMAL;
}
else
m_iCurrentSkin = iStyle;
}
unsigned int CQuestManager::LoadTimerScript(const string& name)
{
map<string, unsigned int>::iterator it;
if ((it = m_mapTimerID.find(name)) != m_mapTimerID.end())
{
return it->second;
}
else
{
unsigned int new_id = UINT_MAX - m_mapTimerID.size();
m_mapNPC[new_id].Set(new_id, name);
m_mapTimerID.emplace(name, new_id);
return new_id;
}
}
unsigned int CQuestManager::GetCurrentNPCRace()
{
return GetCurrentNPCCharacterPtr() ? GetCurrentNPCCharacterPtr()->GetRaceNum() : 0;
}
LPITEM CQuestManager::GetCurrentItem()
{
return GetCurrentCharacterPtr() ? GetCurrentCharacterPtr()->GetQuestItemPtr() : NULL;
}
void CQuestManager::ClearCurrentItem()
{
if (GetCurrentCharacterPtr())
GetCurrentCharacterPtr()->ClearQuestItemPtr();
}
void CQuestManager::SetCurrentItem(LPITEM item)
{
if (GetCurrentCharacterPtr())
GetCurrentCharacterPtr()->SetQuestItemPtr(item);
}
#ifdef ENABLE_QUEST_DND_EVENT
LPITEM CQuestManager::GetCurrentDNDItem()
{
return GetCurrentCharacterPtr() ? GetCurrentCharacterPtr()->GetQuestDNDItemPtr() : NULL;
}
void CQuestManager::ClearCurrentDNDItem()
{
if (GetCurrentCharacterPtr())
GetCurrentCharacterPtr()->ClearQuestDNDItemPtr();
}
void CQuestManager::SetCurrentDNDItem(LPITEM item)
{
if (GetCurrentCharacterPtr())
GetCurrentCharacterPtr()->SetQuestDNDItemPtr(item);
}
#endif
LPCHARACTER CQuestManager::GetCurrentNPCCharacterPtr()
{
return GetCurrentCharacterPtr() ? GetCurrentCharacterPtr()->GetQuestNPC() : NULL;
}
const string & CQuestManager::GetCurrentQuestName()
{
return GetCurrentPC()->GetCurrentQuestName();
}
LPDUNGEON CQuestManager::GetCurrentDungeon()
{
LPCHARACTER ch = GetCurrentCharacterPtr();
if (!ch)
{
if (m_pSelectedDungeon)
return m_pSelectedDungeon;
return NULL;
}
return ch->GetDungeonForce();
}
void CQuestManager::RegisterQuest(const string & stQuestName, unsigned int idx)
{
assert(idx > 0);
itertype(m_hmQuestName) it;
if ((it = m_hmQuestName.find(stQuestName)) != m_hmQuestName.end())
return;
m_hmQuestName.emplace(stQuestName, idx);
LoadStartQuest(stQuestName, idx);
m_mapQuestNameByIndex.emplace(idx, stQuestName);
sys_log(0, "QUEST: Register %4u %s", idx, stQuestName.c_str());
}
unsigned int CQuestManager::GetQuestIndexByName(const string& name)
{
THashMapQuestName::iterator it = m_hmQuestName.find(name);
if (it == m_hmQuestName.end())
return 0; // RESERVED
return it->second;
}
const string & CQuestManager::GetQuestNameByIndex(unsigned int idx)
{
itertype(m_mapQuestNameByIndex) it;
if ((it = m_mapQuestNameByIndex.find(idx)) == m_mapQuestNameByIndex.end())
{
sys_err("cannot find quest name by index %u", idx);
assert(!"cannot find quest name by index");
static std::string st = "";
return st;
}
return it->second;
}
void CQuestManager::SendEventFlagList(LPCHARACTER ch)
{
itertype(m_mapEventFlag) it;
for (it = m_mapEventFlag.begin(); it != m_mapEventFlag.end(); ++it)
{
const string& flagname = it->first;
int value = it->second;
if (!test_server && value == 1 && flagname == "valentine_drop")
ch->ChatPacket(CHAT_TYPE_INFO, "%s %d prob 800", flagname.c_str(), value);
else if (!test_server && value == 1 && flagname == "newyear_wonso")
ch->ChatPacket(CHAT_TYPE_INFO, "%s %d prob 500", flagname.c_str(), value);
else if (!test_server && value == 1 && flagname == "newyear_fire")
ch->ChatPacket(CHAT_TYPE_INFO, "%s %d prob 1000", flagname.c_str(), value);
else
ch->ChatPacket(CHAT_TYPE_INFO, "%s %d", flagname.c_str(), value);
}
}
void CQuestManager::RequestSetEventFlag(const string& name, int value)
{
TPacketSetEventFlag p;
strlcpy(p.szFlagName, name.c_str(), sizeof(p.szFlagName));
p.lValue = value;
db_clientdesc->DBPacket(HEADER_GD_SET_EVENT_FLAG, 0, &p, sizeof(TPacketSetEventFlag));
}
void CQuestManager::SetEventFlag(const string& name, int value)
{
static const char* DROPEVENT_CHARTONE_NAME = "drop_char_stone";
static const int DROPEVENT_CHARTONE_NAME_LEN = strlen(DROPEVENT_CHARTONE_NAME);
int prev_value = m_mapEventFlag[name];
sys_log(0, "QUEST eventflag %s %d prev_value %d", name.c_str(), value, m_mapEventFlag[name]);
m_mapEventFlag[name] = value;
if (name == "mob_item")
{
CHARACTER_MANAGER::instance().SetMobItemRate(value);
}
else if (name == "mob_dam")
{
CHARACTER_MANAGER::instance().SetMobDamageRate(value);
}
else if (name == "mob_gold")
{
CHARACTER_MANAGER::instance().SetMobGoldAmountRate(value);
}
else if (name == "mob_gold_pct")
{
CHARACTER_MANAGER::instance().SetMobGoldDropRate(value);
}
else if (name == "user_dam")
{
CHARACTER_MANAGER::instance().SetUserDamageRate(value);
}
else if (name == "user_dam_buyer")
{
CHARACTER_MANAGER::instance().SetUserDamageRatePremium(value);
}
else if (name == "mob_exp")
{
CHARACTER_MANAGER::instance().SetMobExpRate(value);
}
else if (name == "mob_item_buyer")
{
CHARACTER_MANAGER::instance().SetMobItemRatePremium(value);
}
else if (name == "mob_exp_buyer")
{
CHARACTER_MANAGER::instance().SetMobExpRatePremium(value);
}
else if (name == "mob_gold_buyer")
{
CHARACTER_MANAGER::instance().SetMobGoldAmountRatePremium(value);
}
else if (name == "mob_gold_pct_buyer")
{
CHARACTER_MANAGER::instance().SetMobGoldDropRatePremium(value);
}
else if (name == "crcdisconnect")
{
DESC_MANAGER::instance().SetDisconnectInvalidCRCMode(value != 0);
}
else if (!name.compare(0,5,"xmas_"))
{
xmas::ProcessEventFlag(name, prev_value, value);
}
else if (name == "newyear_boom")
{
const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();
for (itertype(c_ref_set) it = c_ref_set.begin(); it != c_ref_set.end(); ++it)
{
LPCHARACTER ch = (*it)->GetCharacter();
if (!ch)
continue;
ch->ChatPacket(CHAT_TYPE_COMMAND, "newyear_boom %d", value);
}
}
else if ( name == "eclipse" )
{
std::string mode("");
if ( value == 1 )
{
mode = "dark";
}
else
{
mode = "light";
}
const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();
for (itertype(c_ref_set) it = c_ref_set.begin(); it != c_ref_set.end(); ++it)
{
LPCHARACTER ch = (*it)->GetCharacter();
if (!ch)
continue;
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode %s", mode.c_str());
}
}
else if (name == "day")
{
const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();
for (itertype(c_ref_set) it = c_ref_set.begin(); it != c_ref_set.end(); ++it)
{
LPCHARACTER ch = (*it)->GetCharacter();
if (!ch)
continue;
if (value)
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode dark");
}
else
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode light");
}
}
if (value && !prev_value)
{
struct SNPCSellFireworkPosition
{
long lMapIndex;
int x;
int y;
} positions[] = {
{ 1, 615, 618 },
{ 3, 500, 625 },
{ 21, 598, 665 },
{ 23, 476, 360 },
{ 41, 318, 629 },
{ 43, 478, 375 },
{ 0, 0, 0 },
};
SNPCSellFireworkPosition* p = positions;
while (p->lMapIndex)
{
if (map_allow_find(p->lMapIndex))
{
PIXEL_POSITION posBase;
if (!SECTREE_MANAGER::instance().GetMapBasePositionByMapIndex(p->lMapIndex, posBase))
{
sys_err("cannot get map base position %d", p->lMapIndex);
++p;
continue;
}
CHARACTER_MANAGER::instance().SpawnMob(xmas::MOB_XMAS_FIRWORK_SELLER_VNUM, p->lMapIndex, posBase.x + p->x * 100, posBase.y + p->y * 100, 0, false, -1);
}
p++;
}
}
else if (!value && prev_value)
{
CharacterVectorInteractor i;
if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(xmas::MOB_XMAS_FIRWORK_SELLER_VNUM, i))
{
CharacterVectorInteractor::iterator it = i.begin();
while (it != i.end()) {
M2_DESTROY_CHARACTER(*it++);
}
}
}
}
else if (name == "pre_event_hc")
{
const DWORD EventNPC = 20090;
struct SEventNPCPosition
{
long lMapIndex;
int x;
int y;
} positions[] = {
{ 3, 588, 617 },
{ 23, 397, 250 },
{ 43, 567, 426 },
{ 0, 0, 0 },
};
if (value && !prev_value)
{
SEventNPCPosition* pPosition = positions;
while (pPosition->lMapIndex)
{
if (map_allow_find(pPosition->lMapIndex))
{
PIXEL_POSITION pos;
if (!SECTREE_MANAGER::instance().GetMapBasePositionByMapIndex(pPosition->lMapIndex, pos))
{
sys_err("cannot get map base position %d", pPosition->lMapIndex);
++pPosition;
continue;
}
CHARACTER_MANAGER::instance().SpawnMob(EventNPC, pPosition->lMapIndex, pos.x+pPosition->x*100, pos.y+pPosition->y*100, 0, false, -1);
}
pPosition++;
}
}
else if (!value && prev_value)
{
CharacterVectorInteractor i;
if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(EventNPC, i))
{
CharacterVectorInteractor::iterator it = i.begin();
while (it != i.end())
{
LPCHARACTER ch = *it++;
switch (ch->GetMapIndex())
{
case 3:
case 23:
case 43:
M2_DESTROY_CHARACTER(ch);
break;
}
}
}
}
}
else if (name.compare(0, DROPEVENT_CHARTONE_NAME_LEN, DROPEVENT_CHARTONE_NAME)== 0)
{
DropEvent_CharStone_SetValue(name, value);
}
else if (name.compare(0, strlen("refine_box"), "refine_box")== 0)
{
DropEvent_RefineBox_SetValue(name, value);
}
else if (name == "gold_drop_limit_time")
{
g_GoldDropTimeLimitValue = value * 1000;
}
#ifdef ENABLE_NEWSTUFF
else if (name == "item_drop_limit_time")
{
g_ItemDropTimeLimitValue = value * 1000;
}
else if (name == "box_use_limit_time")
{
g_BoxUseTimeLimitValue = value * 1000;
}
else if (name == "buysell_limit_time")
{
g_BuySellTimeLimitValue = value * 1000;
}
else if (name == "no_drop_metin_stone")
{
g_NoDropMetinStone = !!value;
}
else if (name == "no_mount_at_guild_war")
{
g_NoMountAtGuildWar = !!value;
}
else if (name == "no_potions_on_pvp")
{
g_NoPotionsOnPVP = !!value;
}
#endif
else if (name == "new_xmas_event")
{
static DWORD new_santa = 20126;
if (value != 0)
{
CharacterVectorInteractor i;
bool map1_santa_exist = false;
bool map21_santa_exist = false;
bool map41_santa_exist = false;
if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(new_santa, i))
{
CharacterVectorInteractor::iterator it = i.begin();
while (it != i.end())
{
LPCHARACTER tch = *(it++);
if (tch->GetMapIndex() == 1)
{
map1_santa_exist = true;
}
else if (tch->GetMapIndex() == 21)
{
map21_santa_exist = true;
}
else if (tch->GetMapIndex() == 41)
{
map41_santa_exist = true;
}
}
}
if (map_allow_find(1) && !map1_santa_exist)
{
LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(1);
CHARACTER_MANAGER::instance().SpawnMob(new_santa, 1, pkSectreeMap->m_setting.iBaseX + 60800, pkSectreeMap->m_setting.iBaseY + 61700, 0, false, 90, true);
}
if (map_allow_find(21) && !map21_santa_exist)
{
LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(21);
CHARACTER_MANAGER::instance().SpawnMob(new_santa, 21, pkSectreeMap->m_setting.iBaseX + 59600, pkSectreeMap->m_setting.iBaseY + 61000, 0, false, 110, true);
}
if (map_allow_find(41) && !map41_santa_exist)
{
LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(41);
CHARACTER_MANAGER::instance().SpawnMob(new_santa, 41, pkSectreeMap->m_setting.iBaseX + 35700, pkSectreeMap->m_setting.iBaseY + 74300, 0, false, 140, true);
}
}
else
{
CharacterVectorInteractor i;
CHARACTER_MANAGER::instance().GetCharactersByRaceNum(new_santa, i);
for (CharacterVectorInteractor::iterator it = i.begin(); it != i.end(); it++)
{
M2_DESTROY_CHARACTER(*it);
}
}
}
}
int CQuestManager::GetEventFlag(const string& name)
{
map<string,int>::iterator it = m_mapEventFlag.find(name);
if (it == m_mapEventFlag.end())
return 0;
return it->second;
}
void CQuestManager::BroadcastEventFlagOnLogin(LPCHARACTER ch)
{
int iEventFlagValue;
if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("xmas_snow")))
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "xmas_snow %d", iEventFlagValue);
}
if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("xmas_boom")))
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "xmas_boom %d", iEventFlagValue);
}
if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("xmas_tree")))
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "xmas_tree %d", iEventFlagValue);
}
if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("day")))
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode dark");
}
if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("newyear_boom")))
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "newyear_boom %d", iEventFlagValue);
}
if ( (iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("eclipse")) )
{
std::string mode;
if ( iEventFlagValue == 1 ) mode = "dark";
else mode = "light";
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode %s", mode.c_str());
}
}
void CQuestManager::Reload()
{
lua_close(L);
m_mapNPC.clear();
m_mapNPCNameID.clear();
m_hmQuestName.clear();
m_mapTimerID.clear();
m_hmQuestStartScript.clear();
m_mapEventName.clear();
L = NULL;
Initialize();
for (itertype(m_registeredNPCVnum) it = m_registeredNPCVnum.begin(); it != m_registeredNPCVnum.end(); ++it)
{
char buf[256];
DWORD dwVnum = *it;
snprintf(buf, sizeof(buf), "%u", dwVnum);
m_mapNPC[dwVnum].Set(dwVnum, buf);
}
}
bool CQuestManager::ExecuteQuestScript(PC& pc, DWORD quest_index, const int state, const char* code, const int code_size, vector<AArgScript*>* pChatScripts, bool bUseCache)
{
return ExecuteQuestScript(pc, CQuestManager::instance().GetQuestNameByIndex(quest_index), state, code, code_size, pChatScripts, bUseCache);
}
bool CQuestManager::ExecuteQuestScript(PC& pc, const string& quest_name, const int state, const char* code, const int code_size, vector<AArgScript*>* pChatScripts, bool bUseCache)
{
QuestState qs = CQuestManager::instance().OpenState(quest_name, state);
if (pChatScripts)
qs.chat_scripts.swap(*pChatScripts);
if (bUseCache)
{
lua_getglobal(qs.co, "__codecache");
// stack : __codecache
lua_pushnumber(qs.co, (long)code);
// stack : __codecache (codeptr)
lua_rawget(qs.co, -2);
// stack : __codecache (compiled-code)
if (lua_isnil(qs.co, -1))
{
// cache miss
// load code to lua,
// save it to cache
// and only function remain in stack
lua_pop(qs.co, 1);
// stack : __codecache
luaL_loadbuffer(qs.co, code, code_size, quest_name.c_str());
// stack : __codecache (compiled-code)
lua_pushnumber(qs.co, (long)code);
// stack : __codecache (compiled-code) (codeptr)
lua_pushvalue(qs.co, -2);
// stack : __codecache (compiled-code) (codeptr) (compiled_code)
lua_rawset(qs.co, -4);
// stack : __codecache (compiled-code)
lua_remove(qs.co, -2);
// stack : (compiled-code)
}
else
{
// cache hit
lua_remove(qs.co, -2);
// stack : (compiled-code)
}
}
else
luaL_loadbuffer(qs.co, code, code_size, quest_name.c_str());
pc.SetQuest(quest_name, qs);
QuestState& rqs = *pc.GetRunningQuestState();
if (!CQuestManager::instance().RunState(rqs))
{
CQuestManager::instance().CloseState(rqs);
pc.EndRunning();
return false;
}
return true;
}
void CQuestManager::RegisterNPCVnum(DWORD dwVnum)
{
if (m_registeredNPCVnum.find(dwVnum) != m_registeredNPCVnum.end())
return;
m_registeredNPCVnum.emplace(dwVnum);
char buf[256];
DIR* dir;
for (itertype(g_setQuestObjectDir) it = g_setQuestObjectDir.begin(); it != g_setQuestObjectDir.end(); ++it)
{
const string& stQuestObjectDir = *it;
snprintf(buf, sizeof(buf), "%s/%u", stQuestObjectDir.c_str(), dwVnum);
sys_log(0, "%s", buf);
if ((dir = opendir(buf)))
{
closedir(dir);
snprintf(buf, sizeof(buf), "%u", dwVnum);
sys_log(0, "%s", buf);
m_mapNPC[dwVnum].Set(dwVnum, buf);
}
}
}
void CQuestManager::WriteRunningStateToSyserr()
{
const char * state_name = GetQuestStateName(GetCurrentQuestName(), GetCurrentState()->st);
string event_index_name = "";
for (itertype(m_mapEventName) it = m_mapEventName.begin(); it != m_mapEventName.end(); ++it)
{
if (it->second == m_iRunningEventIndex)
{
event_index_name = it->first;
break;
}
}
sys_err("LUA_ERROR: quest %s.%s %s", GetCurrentQuestName().c_str(), state_name, event_index_name.c_str() );
if (GetCurrentCharacterPtr() && test_server)
GetCurrentCharacterPtr()->ChatPacket(CHAT_TYPE_PARTY, "LUA_ERROR: quest %s.%s %s", GetCurrentQuestName().c_str(), state_name, event_index_name.c_str() );
}
#ifndef __WIN32__
void CQuestManager::QuestError(const char* func, int line, const char* fmt, ...)
{
char szMsg[4096];
va_list args;
va_start(args, fmt);
vsnprintf(szMsg, sizeof(szMsg), fmt, args);
va_end(args);
_sys_err(func, line, "%s", szMsg);
if (test_server)
{
LPCHARACTER ch = GetCurrentCharacterPtr();
if (ch)
{
ch->ChatPacket(CHAT_TYPE_PARTY, "error occurred on [%s:%d]", func,line);
ch->ChatPacket(CHAT_TYPE_PARTY, "%s", szMsg);
}
}
}
#else
void CQuestManager::QuestError(const char* func, int line, const char* fmt, ...)
{
char szMsg[4096];
va_list args;
va_start(args, fmt);
vsnprintf(szMsg, sizeof(szMsg), fmt, args);
va_end(args);
_sys_err(func, line, "%s", szMsg);
if (test_server)
{
LPCHARACTER ch = GetCurrentCharacterPtr();
if (ch)
{
ch->ChatPacket(CHAT_TYPE_PARTY, "error occurred on [%s:%d]", func,line);
ch->ChatPacket(CHAT_TYPE_PARTY, "%s", szMsg);
}
}
}
#endif
void CQuestManager::AddServerTimer(const std::string& name, DWORD arg, LPEVENT event)
{
sys_log(0, "XXX AddServerTimer %s %d %p", name.c_str(), arg, get_pointer(event));
if (m_mapServerTimer.find(make_pair(name, arg)) != m_mapServerTimer.end())
{
sys_err("already registered server timer name:%s arg:%u", name.c_str(), arg);
return;
}
m_mapServerTimer.emplace(make_pair(name, arg), event);
}
void CQuestManager::ClearServerTimerNotCancel(const std::string& name, DWORD arg)
{
m_mapServerTimer.erase(make_pair(name, arg));
}
void CQuestManager::ClearServerTimer(const std::string& name, DWORD arg)
{
itertype(m_mapServerTimer) it = m_mapServerTimer.find(make_pair(name, arg));
if (it != m_mapServerTimer.end())
{
LPEVENT event = it->second;
event_cancel(&event);
m_mapServerTimer.erase(it);
}
}
void CQuestManager::CancelServerTimers(DWORD arg)
{
auto erase_check = [&](auto&& it) {
if (it.first.second == arg) {
auto event = it.second; // copy ptr
event_cancel(&event);
}
return it.first.second == arg;
};
std::erase_if(m_mapServerTimer, erase_check); // @fixme311
}
void CQuestManager::SetServerTimerArg(DWORD dwArg)
{
m_dwServerTimerArg = dwArg;
}
DWORD CQuestManager::GetServerTimerArg()
{
return m_dwServerTimerArg;
}
void CQuestManager::SelectDungeon(LPDUNGEON pDungeon)
{
m_pSelectedDungeon = pDungeon;
}
bool CQuestManager::PickupItem(unsigned int pc, LPITEM item)
{
if (test_server)
sys_log( 0, "questmanager::PickupItem Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
PC* pPC;
if ((pPC = GetPC(pc)))
{
if (!CheckQuestLoaded(pPC))
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
if (ch)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD>Դϴ<D4B4>. <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD>ٷ<EFBFBD> <20>ֽʽÿ<CABD>."));
}
return false;
}
// call script
SetCurrentItem(item);
return m_mapNPC[item->GetVnum()].OnPickupItem(*pPC);
}
else
{
sys_err("QUEST PICK_ITEM_EVENT no such pc id : %d", pc);
return false;
}
}
void CQuestManager::BeginOtherPCBlock(DWORD pid)
{
LPCHARACTER ch = GetCurrentCharacterPtr();
if (NULL == ch)
{
sys_err("NULL?");
return;
}
/*
# 1. current pid = pid0 <- It will be m_pOtherPCBlockRootPC.
begin_other_pc_block(pid1)
# 2. current pid = pid1
begin_other_pc_block(pid2)
# 3. current_pid = pid2
end_other_pc_block()
end_other_pc_block()
*/
// when begin_other_pc_block(pid1)
if (m_vecPCStack.empty())
{
m_pOtherPCBlockRootPC = GetCurrentPC();
}
m_vecPCStack.emplace_back(GetCurrentCharacterPtr()->GetPlayerID());
GetPC(pid);
}
void CQuestManager::EndOtherPCBlock()
{
if (m_vecPCStack.size() == 0)
{
sys_err("m_vecPCStack is alread empty. CurrentQuest{Name(%s), State(%s)}", GetCurrentQuestName().c_str(), GetCurrentState()->_title.c_str());
return;
}
DWORD pc = m_vecPCStack.back();
m_vecPCStack.pop_back();
GetPC(pc);
if (m_vecPCStack.empty())
{
m_pOtherPCBlockRootPC = NULL;
}
}
bool CQuestManager::IsInOtherPCBlock()
{
return !m_vecPCStack.empty();
}
PC* CQuestManager::GetOtherPCBlockRootPC()
{
return m_pOtherPCBlockRootPC;
}
}
//martysama0134's 623a0779c74cb7565145d45548376308