knightonline/server/AIServer/RoomEvent.cpp

321 lines
7.4 KiB
C++

#include "stdafx.h"
#include "RoomEvent.h"
#include "resource.h"
#include "Npc.h"
CRoomEvent::CRoomEvent()
{
m_iZoneNumber = 0;
m_sRoomNumber = 0;
m_byStatus = RoomStatusInitialised;
m_iInitMinX = 0;
m_iInitMinZ = 0;
m_iInitMaxX = 0;
m_iInitMaxZ = 0;
m_iEndMinX = 0;
m_iEndMinZ = 0;
m_iEndMaxX = 0;
m_iEndMaxZ = 0;
m_byCheck = 0;
m_byRoomType = 0;
Initialize();
}
CRoomEvent::~CRoomEvent()
{
}
void CRoomEvent::Initialize()
{
m_tDelayTime = 0;
m_byLogicNumber = 1;
for(int i=0; i<MAX_CHECK_EVENT; i++) {
m_Logic[i].sNumber = 0;
m_Logic[i].sOption_1 = 0;
m_Logic[i].sOption_2 = 0;
m_Exec[i].sNumber = 0;
m_Exec[i].sOption_1 = 0;
m_Exec[i].sOption_2 = 0;
}
}
void CRoomEvent::MainRoom()
{
// 조건 검색먼저 해야 겠지..
bool bCheck = false, bRunCheck = false;
int event_num = m_Logic[m_byLogicNumber-1].sNumber;
bCheck = CheckEvent(event_num);
if( bCheck ) {
event_num = m_Exec[m_byLogicNumber-1].sNumber;
bRunCheck = RunEvent( event_num );
if( bRunCheck ) {
//wsprintf(notify, "** 알림 : [%d]방이 클리어 되어습니다. **", m_sRoomNumber);
//g_pMain->SendSystemMsg(notify, PUBLIC_CHAT);
m_byStatus = RoomStatusCleared;
}
}
}
bool CRoomEvent::CheckEvent(int event_num)
{
int nMinute = 0, nOption_1 = 0, nOption_2 = 0;
CNpc* pNpc = nullptr;
bool bRetValue = false;
if( m_byLogicNumber == 0 || m_byLogicNumber > MAX_CHECK_EVENT ) {
TRACE("### Check Event Fail :: array overflow = %d ###\n", m_byLogicNumber);
return false;
}
switch( event_num ) {
case 1: // 특정 몬스터를 죽이는 경우
nOption_1 = m_Logic[ m_byLogicNumber-1 ].sOption_1;
pNpc = GetNpcPtr( nOption_1 );
if( pNpc ) {
if( pNpc->m_byChangeType == 100 ) return true;
} else {
if (nOption_1 != 11510 && nOption_1 != 21510)
TRACE("### CheckEvent Error : monster nid = %d, logic=%d ###\n", nOption_1, m_byLogicNumber);
}
//TRACE("---Check Event : monster dead = %d \n", nMonsterNid);
break;
case 2: // 모든 몬스터를 죽여라
bRetValue = CheckMonsterCount( 0, 0, 3 );
if( bRetValue ) {
TRACE("모든 몬스터를 죽여라 죽임\n");
return true;
}
break;
case 3: // 몇분동안 버텨라
nMinute = m_Logic[ m_byLogicNumber-1 ].sOption_1;
nMinute = nMinute * 60; // 분을 초로 변환
if (UNIXTIME >= m_tDelayTime + nMinute ) { // 제한시간 종료
return true;
}
break;
case 4: // 목표지점까지 이동
break;
case 5: // 특정몬스터를 옵션2의 마리수 만큼 죽여라
nOption_1 = m_Logic[ m_byLogicNumber-1 ].sOption_1;
nOption_2 = m_Logic[ m_byLogicNumber-1 ].sOption_2;
bRetValue = CheckMonsterCount( nOption_1, nOption_2, 1 );
if( bRetValue ) {
TRACE("특정몬스터(%d)를 %d마리 죽임\n", nOption_1, nOption_2);
return true;
}
break;
default:
TRACE("### Check Event Fail :: event number = %d ###\n", event_num);
break;
}
return false;
}
bool CRoomEvent::RunEvent( int event_num )
{
CNpc* pNpc = nullptr;
int nOption_1 = 0, nOption_2 = 0;
bool bRetValue = false;
switch( event_num ) {
case 1: // 다른 몬스터의 출현
nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
pNpc = GetNpcPtr( nOption_1 );
if( pNpc ) {
pNpc->m_byChangeType = 3; // 몬스터 출현해주세여...
pNpc->SetLive();
}
else {
TRACE("### RunEvent Error : 몬스터 출현 할 수 없당 = %d, logic=%d ###\n", nOption_1, m_byLogicNumber);
}
if( m_byCheck == m_byLogicNumber ) { // 방이 클리어
return true;
}
else m_byLogicNumber++;
break;
case 2: // 문이 열림
nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
pNpc = GetNpcPtr( nOption_1 );
if( pNpc ) {
}
else {
TRACE("### RunEvent Error : 문 담당 몬스터 출현 할 수 없당 = %d, logic=%d ###\n", nOption_1, m_byLogicNumber);
}
//wsprintf(notify, "** 알림 : [%d] 문이 열립니다 **", m_sRoomNumber);
//g_pMain->SendSystemMsg(notify, PUBLIC_CHAT);
if( m_byCheck == m_byLogicNumber ) { // 방이 클리어
return true;
}
else m_byLogicNumber++;
break;
case 3: // 다른 몬스터로 변환
if( m_byCheck == m_byLogicNumber ) { // 방이 클리어
return true;
}
break;
case 4: // 특정몬스터 옵션2의 마리수만큼 출현
nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
nOption_2 = m_Exec[ m_byLogicNumber-1 ].sOption_2;
bRetValue = CheckMonsterCount( nOption_1, nOption_2, 2 );
//wsprintf(notify, "** 알림 : [%d, %d] 몬스터 출현 **", nOption_1, nOption_2);
//g_pMain->SendSystemMsg(notify, PUBLIC_CHAT);
if( m_byCheck == m_byLogicNumber ) { // 방이 클리어
return true;
}
else m_byLogicNumber++;
break;
case 100: // 특정몬스터 옵션2의 마리수만큼 출현
nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
nOption_2 = m_Exec[ m_byLogicNumber-1 ].sOption_2;
TRACE("RunEvent - room=%d, option1=%d, option2=%d\n", m_sRoomNumber, nOption_1, nOption_2);
if( nOption_1 != 0 ) {
EndEventSay( nOption_1, nOption_2 );
}
if( m_byCheck == m_byLogicNumber ) { // 방이 클리어
return true;
}
else m_byLogicNumber++;
break;
default:
TRACE("### RunEvent Fail :: event number = %d ###\n", event_num);
break;
}
return false;
}
CNpc* CRoomEvent::GetNpcPtr( int sid )
{
if (m_mapRoomNpcArray.IsEmpty())
{
if (sid != 11510 && sid != 21510)
TRACE("### RoomEvent-GetNpcPtr() : monster empty, sid=%d ###\n",sid);
return nullptr;
}
foreach_stlmap (itr, m_mapRoomNpcArray)
{
CNpc *pNpc = g_pMain->GetNpcPtr(itr->first);
if (pNpc == nullptr
|| pNpc->GetProtoID() != sid)
continue;
return pNpc;
}
return nullptr;
}
bool CRoomEvent::CheckMonsterCount( int sid, int count, int type )
{
int nMonsterCount = 0, nTotalMonster = 0;
bool bRetValue = false;
int nMonster = m_mapRoomNpcArray.GetSize();
if (nMonster == 0)
{
if (sid != 11510 && sid != 21510)
TRACE("### RoomEvent-GetNpcPtr() : monster empty, sid=%d ###\n",sid);
return nullptr;
}
foreach_stlmap (itr, m_mapRoomNpcArray)
{
CNpc *pNpc = g_pMain->GetNpcPtr(itr->first);
if (pNpc == nullptr)
continue;
if (type == 4)
{
if (pNpc->m_byRegenType == 2) pNpc->m_byRegenType = 0;
pNpc->m_byChangeType = 0;
}
else if (type == 3)
{
if (pNpc->m_byDeadType == 100) nMonsterCount++;
if (nMonsterCount == nMonster) bRetValue = true;
}
else if (pNpc->GetProtoID() == sid)
{
if (type == 1)
{
if (pNpc->m_byChangeType == 100) nMonsterCount++;
if (nMonsterCount == count) bRetValue = true;
}
else if (type == 2)
{
pNpc->m_byChangeType = 3; nMonsterCount++;
if (nMonsterCount == count) bRetValue = true;
}
}
}
return bRetValue;
}
void CRoomEvent::InitializeRoom()
{
m_byStatus = RoomStatusInitialised;
m_tDelayTime = 0;
m_byLogicNumber = 1;
CheckMonsterCount(0, 0, 4); // 몬스터의 m_byChangeType=0으로 초기화
}
void CRoomEvent::EndEventSay( int option1, int option2 )
{
std::string buff;
switch (option1)
{
case 1:
{
switch (option2)
{
case 1:
g_pMain->GetServerResource(IDS_KARUS_CATCH_1, &buff);
break;
case 2:
g_pMain->GetServerResource(IDS_KARUS_CATCH_2, &buff);
break;
case 11:
g_pMain->GetServerResource(IDS_ELMORAD_CATCH_1, &buff);
break;
case 12:
g_pMain->GetServerResource(IDS_ELMORAD_CATCH_2, &buff);
break;
}
g_pMain->SendSystemMsg(buff, WAR_SYSTEM_CHAT);
} break;
case 2:
g_pMain->GetServerResource(IDS_KARUS_PATHWAY + (option2-1), &buff);
g_pMain->SendSystemMsg(buff, WAR_SYSTEM_CHAT);
// this is normal, we need to send the following packet as well.
case 3:
{
Packet result(AG_BATTLE_EVENT, uint8(BATTLE_MAP_EVENT_RESULT));
result << uint8(option2);
g_pMain->Send(&result);
} break;
}
}