forked from metin2/server
442 lines
9.3 KiB
C++
442 lines
9.3 KiB
C++
#include "stdafx.h"
|
||
#include "constants.h"
|
||
#include "config.h"
|
||
#include "questmanager.h"
|
||
#include "start_position.h"
|
||
#include "packet.h"
|
||
#include "buffer_manager.h"
|
||
#include "log.h"
|
||
#include "char.h"
|
||
#include "char_manager.h"
|
||
#include "OXEvent.h"
|
||
#include "desc.h"
|
||
|
||
bool COXEventManager::Initialize()
|
||
{
|
||
m_timedEvent = NULL;
|
||
m_map_char.clear();
|
||
m_map_attender.clear();
|
||
m_vec_quiz.clear();
|
||
|
||
SetStatus(OXEVENT_FINISH);
|
||
|
||
return true;
|
||
}
|
||
|
||
void COXEventManager::Destroy()
|
||
{
|
||
CloseEvent();
|
||
|
||
m_map_char.clear();
|
||
m_map_attender.clear();
|
||
m_vec_quiz.clear();
|
||
|
||
SetStatus(OXEVENT_FINISH);
|
||
}
|
||
|
||
OXEventStatus COXEventManager::GetStatus()
|
||
{
|
||
BYTE ret = quest::CQuestManager::instance().GetEventFlag("oxevent_status");
|
||
|
||
switch (ret)
|
||
{
|
||
case 0 :
|
||
return OXEVENT_FINISH;
|
||
|
||
case 1 :
|
||
return OXEVENT_OPEN;
|
||
|
||
case 2 :
|
||
return OXEVENT_CLOSE;
|
||
|
||
case 3 :
|
||
return OXEVENT_QUIZ;
|
||
|
||
default :
|
||
return OXEVENT_ERR;
|
||
}
|
||
|
||
return OXEVENT_ERR;
|
||
}
|
||
|
||
void COXEventManager::SetStatus(OXEventStatus status)
|
||
{
|
||
BYTE val = 0;
|
||
|
||
switch (status)
|
||
{
|
||
case OXEVENT_OPEN :
|
||
val = 1;
|
||
break;
|
||
|
||
case OXEVENT_CLOSE :
|
||
val = 2;
|
||
break;
|
||
|
||
case OXEVENT_QUIZ :
|
||
val = 3;
|
||
break;
|
||
|
||
case OXEVENT_FINISH :
|
||
case OXEVENT_ERR :
|
||
default :
|
||
val = 0;
|
||
break;
|
||
}
|
||
quest::CQuestManager::instance().RequestSetEventFlag("oxevent_status", val);
|
||
}
|
||
|
||
bool COXEventManager::Enter(LPCHARACTER pkChar)
|
||
{
|
||
if (GetStatus() == OXEVENT_FINISH)
|
||
{
|
||
sys_log(0, "OXEVENT : map finished. but char enter. %s", pkChar->GetName());
|
||
return false;
|
||
}
|
||
|
||
PIXEL_POSITION pos = pkChar->GetXYZ();
|
||
|
||
if (pos.x == 896500 && pos.y == 24600)
|
||
{
|
||
return EnterAttender(pkChar);
|
||
}
|
||
else if (pos.x == 896300 && pos.y == 28900)
|
||
{
|
||
return EnterAudience(pkChar);
|
||
}
|
||
else
|
||
{
|
||
sys_log(0, "OXEVENT : wrong pos enter %d %d", pos.x, pos.y);
|
||
return false;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
bool COXEventManager::EnterAttender(LPCHARACTER pkChar)
|
||
{
|
||
DWORD pid = pkChar->GetPlayerID();
|
||
|
||
m_map_char.insert(std::make_pair(pid, pid));
|
||
m_map_attender.insert(std::make_pair(pid, pid));
|
||
|
||
return true;
|
||
}
|
||
|
||
bool COXEventManager::EnterAudience(LPCHARACTER pkChar)
|
||
{
|
||
DWORD pid = pkChar->GetPlayerID();
|
||
|
||
m_map_char.insert(std::make_pair(pid, pid));
|
||
|
||
return true;
|
||
}
|
||
|
||
bool COXEventManager::AddQuiz(unsigned char level, const char* pszQuestion, bool answer)
|
||
{
|
||
if (m_vec_quiz.size() < (size_t) level + 1)
|
||
m_vec_quiz.resize(level + 1);
|
||
|
||
struct tag_Quiz tmpQuiz;
|
||
|
||
tmpQuiz.level = level;
|
||
strlcpy(tmpQuiz.Quiz, pszQuestion, sizeof(tmpQuiz.Quiz));
|
||
tmpQuiz.answer = answer;
|
||
|
||
m_vec_quiz[level].push_back(tmpQuiz);
|
||
return true;
|
||
}
|
||
|
||
bool COXEventManager::ShowQuizList(LPCHARACTER pkChar)
|
||
{
|
||
int c = 0;
|
||
|
||
for (size_t i = 0; i < m_vec_quiz.size(); ++i)
|
||
{
|
||
for (size_t j = 0; j < m_vec_quiz[i].size(); ++j, ++c)
|
||
{
|
||
pkChar->ChatPacket(CHAT_TYPE_INFO, "%d %s %s", m_vec_quiz[i][j].level, m_vec_quiz[i][j].Quiz, m_vec_quiz[i][j].answer ? LC_TEXT("<EFBFBD><EFBFBD>") : LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
|
||
}
|
||
}
|
||
|
||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>: %d"), c);
|
||
return true;
|
||
}
|
||
|
||
void COXEventManager::ClearQuiz()
|
||
{
|
||
for (unsigned int i = 0; i < m_vec_quiz.size(); ++i)
|
||
{
|
||
m_vec_quiz[i].clear();
|
||
}
|
||
|
||
m_vec_quiz.clear();
|
||
}
|
||
|
||
EVENTINFO(OXEventInfoData)
|
||
{
|
||
bool answer;
|
||
|
||
OXEventInfoData()
|
||
: answer( false )
|
||
{
|
||
}
|
||
};
|
||
|
||
EVENTFUNC(oxevent_timer)
|
||
{
|
||
static BYTE flag = 0;
|
||
OXEventInfoData* info = dynamic_cast<OXEventInfoData*>(event->info);
|
||
|
||
if ( info == NULL )
|
||
{
|
||
sys_err( "oxevent_timer> <Factor> Null pointer" );
|
||
return 0;
|
||
}
|
||
|
||
switch (flag)
|
||
{
|
||
case 0:
|
||
SendNoticeMap(LC_TEXT("10<EFBFBD>ʵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰڽ<CFB0><DABD>ϴ<EFBFBD>."), OXEVENT_MAP_INDEX, true);
|
||
flag++;
|
||
return PASSES_PER_SEC(10);
|
||
|
||
case 1:
|
||
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), OXEVENT_MAP_INDEX, true);
|
||
|
||
if (info->answer == true)
|
||
{
|
||
COXEventManager::instance().CheckAnswer(true);
|
||
SendNoticeMap(LC_TEXT("O <20>Դϴ<D4B4>"), OXEVENT_MAP_INDEX, true);
|
||
}
|
||
else
|
||
{
|
||
COXEventManager::instance().CheckAnswer(false);
|
||
SendNoticeMap(LC_TEXT("X <20>Դϴ<D4B4>"), OXEVENT_MAP_INDEX, true);
|
||
}
|
||
|
||
if (LC_IsJapan())
|
||
{
|
||
SendNoticeMap("??????X??O??????????B", OXEVENT_MAP_INDEX, true);
|
||
}
|
||
else
|
||
{
|
||
SendNoticeMap(LC_TEXT("5<EFBFBD><EFBFBD> <20><> Ʋ<><C6B2><EFBFBD><EFBFBD> <20>е<EFBFBD><D0B5><EFBFBD> <20>ٱ<EFBFBD><D9B1><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20><>Ű<EFBFBD>ڽ<EFBFBD><DABD>ϴ<EFBFBD>."), OXEVENT_MAP_INDEX, true);
|
||
}
|
||
|
||
flag++;
|
||
return PASSES_PER_SEC(5);
|
||
|
||
case 2:
|
||
COXEventManager::instance().WarpToAudience();
|
||
COXEventManager::instance().SetStatus(OXEVENT_CLOSE);
|
||
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>غ<EFBFBD><D8BA><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>."), OXEVENT_MAP_INDEX, true);
|
||
flag = 0;
|
||
break;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
bool COXEventManager::Quiz(unsigned char level, int timelimit)
|
||
{
|
||
if (m_vec_quiz.size() == 0) return false;
|
||
if (level > m_vec_quiz.size()) level = m_vec_quiz.size() - 1;
|
||
if (m_vec_quiz[level].size() <= 0) return false;
|
||
|
||
if (timelimit < 0) timelimit = 30;
|
||
|
||
int idx = Random::get<int>(0, m_vec_quiz[level].size() - 1);
|
||
|
||
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Դϴ<D4B4>."), OXEVENT_MAP_INDEX, true);
|
||
SendNoticeMap(m_vec_quiz[level][idx].Quiz, OXEVENT_MAP_INDEX, true);
|
||
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> O, Ʋ<><C6B2><EFBFBD><EFBFBD> X<><58> <20>̵<EFBFBD><CCB5><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>"), OXEVENT_MAP_INDEX, true);
|
||
|
||
if (m_timedEvent != NULL) {
|
||
event_cancel(&m_timedEvent);
|
||
}
|
||
|
||
OXEventInfoData* answer = AllocEventInfo<OXEventInfoData>();
|
||
|
||
answer->answer = m_vec_quiz[level][idx].answer;
|
||
|
||
timelimit -= 15;
|
||
m_timedEvent = event_create(oxevent_timer, answer, PASSES_PER_SEC(timelimit));
|
||
|
||
SetStatus(OXEVENT_QUIZ);
|
||
|
||
m_vec_quiz[level].erase(m_vec_quiz[level].begin()+idx);
|
||
return true;
|
||
}
|
||
|
||
bool COXEventManager::CheckAnswer(bool answer)
|
||
{
|
||
if (m_map_attender.size() <= 0) return true;
|
||
|
||
itertype(m_map_attender) iter = m_map_attender.begin();
|
||
itertype(m_map_attender) iter_tmp;
|
||
|
||
m_map_miss.clear();
|
||
|
||
int rect[4];
|
||
if (answer != true)
|
||
{
|
||
rect[0] = 892600;
|
||
rect[1] = 22900;
|
||
rect[2] = 896300;
|
||
rect[3] = 26400;
|
||
}
|
||
else
|
||
{
|
||
rect[0] = 896600;
|
||
rect[1] = 22900;
|
||
rect[2] = 900300;
|
||
rect[3] = 26400;
|
||
}
|
||
|
||
LPCHARACTER pkChar = NULL;
|
||
PIXEL_POSITION pos;
|
||
for (; iter != m_map_attender.end();)
|
||
{
|
||
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||
if (pkChar != NULL)
|
||
{
|
||
pos = pkChar->GetXYZ();
|
||
|
||
if (pos.x < rect[0] || pos.x > rect[2] || pos.y < rect[1] || pos.y > rect[3])
|
||
{
|
||
pkChar->EffectPacket(SE_FAIL);
|
||
iter_tmp = iter;
|
||
iter++;
|
||
m_map_attender.erase(iter_tmp);
|
||
m_map_miss.insert(std::make_pair(pkChar->GetPlayerID(), pkChar->GetPlayerID()));
|
||
}
|
||
else
|
||
{
|
||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դϴ<EFBFBD>!"));
|
||
// pkChar->CreateFly(Random::get(FLY_FIREWORK1, FLY_FIREWORK6), pkChar);
|
||
char chatbuf[256];
|
||
int len = snprintf(chatbuf, sizeof(chatbuf),
|
||
"%s %u %u", Random::get(0, 1) == 1 ? "cheer1" : "cheer2", (DWORD)pkChar->GetVID(), 0);
|
||
|
||
// <20><><EFBFBD>ϰ<EFBFBD><CFB0><EFBFBD> sizeof(chatbuf) <20>̻<EFBFBD><CCBB><EFBFBD> <20><><EFBFBD><EFBFBD> truncate<74>Ǿ<EFBFBD><C7BE>ٴ<EFBFBD> <20><>..
|
||
if (len < 0 || len >= (int) sizeof(chatbuf))
|
||
len = sizeof(chatbuf) - 1;
|
||
|
||
// \0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
++len;
|
||
|
||
TPacketGCChat pack_chat;
|
||
pack_chat.header = HEADER_GC_CHAT;
|
||
pack_chat.size = sizeof(TPacketGCChat) + len;
|
||
pack_chat.type = CHAT_TYPE_COMMAND;
|
||
pack_chat.id = 0;
|
||
|
||
TEMP_BUFFER buf;
|
||
buf.write(&pack_chat, sizeof(TPacketGCChat));
|
||
buf.write(chatbuf, len);
|
||
|
||
pkChar->PacketAround(buf.read_peek(), buf.size());
|
||
pkChar->EffectPacket(SE_SUCCESS);
|
||
|
||
++iter;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
itertype(m_map_char) err = m_map_char.find(iter->first);
|
||
if (err != m_map_char.end()) m_map_char.erase(err);
|
||
|
||
itertype(m_map_miss) err2 = m_map_miss.find(iter->first);
|
||
if (err2 != m_map_miss.end()) m_map_miss.erase(err2);
|
||
|
||
iter_tmp = iter;
|
||
++iter;
|
||
m_map_attender.erase(iter_tmp);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void COXEventManager::WarpToAudience()
|
||
{
|
||
if (m_map_miss.size() <= 0) return;
|
||
|
||
itertype(m_map_miss) iter = m_map_miss.begin();
|
||
LPCHARACTER pkChar = NULL;
|
||
|
||
for (; iter != m_map_miss.end(); ++iter)
|
||
{
|
||
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||
|
||
if (pkChar != NULL)
|
||
{
|
||
switch ( Random::get(0, 3))
|
||
{
|
||
case 0 : pkChar->Show(OXEVENT_MAP_INDEX, 896300, 28900); break;
|
||
case 1 : pkChar->Show(OXEVENT_MAP_INDEX, 890900, 28100); break;
|
||
case 2 : pkChar->Show(OXEVENT_MAP_INDEX, 896600, 20500); break;
|
||
case 3 : pkChar->Show(OXEVENT_MAP_INDEX, 902500, 28100); break;
|
||
default : pkChar->Show(OXEVENT_MAP_INDEX, 896300, 28900); break;
|
||
}
|
||
}
|
||
}
|
||
|
||
m_map_miss.clear();
|
||
}
|
||
|
||
bool COXEventManager::CloseEvent()
|
||
{
|
||
if (m_timedEvent != NULL) {
|
||
event_cancel(&m_timedEvent);
|
||
}
|
||
|
||
itertype(m_map_char) iter = m_map_char.begin();
|
||
|
||
LPCHARACTER pkChar = NULL;
|
||
for (; iter != m_map_char.end(); ++iter)
|
||
{
|
||
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||
|
||
if (pkChar != NULL)
|
||
pkChar->WarpSet(EMPIRE_START_X(pkChar->GetEmpire()), EMPIRE_START_Y(pkChar->GetEmpire()));
|
||
}
|
||
|
||
m_map_char.clear();
|
||
|
||
return true;
|
||
}
|
||
|
||
bool COXEventManager::LogWinner()
|
||
{
|
||
itertype(m_map_attender) iter = m_map_attender.begin();
|
||
|
||
for (; iter != m_map_attender.end(); ++iter)
|
||
{
|
||
LPCHARACTER pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||
|
||
if (pkChar)
|
||
LogManager::instance().CharLog(pkChar, 0, "OXEVENT", "LastManStanding");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool COXEventManager::GiveItemToAttender(DWORD dwItemVnum, BYTE count)
|
||
{
|
||
itertype(m_map_attender) iter = m_map_attender.begin();
|
||
|
||
for (; iter != m_map_attender.end(); ++iter)
|
||
{
|
||
LPCHARACTER pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||
|
||
if (pkChar)
|
||
{
|
||
pkChar->AutoGiveItem(dwItemVnum, count);
|
||
LogManager::instance().ItemLog(pkChar->GetPlayerID(), 0, count, dwItemVnum, "OXEVENT_REWARD", "", pkChar->GetDesc()->GetHostName(), dwItemVnum);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|