Files
Sun1602/ProgramCommon/SSQ/SSQInfoStruct.cpp
T
2022-10-26 12:25:11 +08:00

492 lines
13 KiB
C++

#include "stdafx.h"
#include "SSQInfoStruct.h"
#include "SSQInfoParser.h"
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// <SSQInfoStruct.cpp>
// <Decriptions>
// - 타락한 사원 SSQ(Survival Soloing Quest)
// <Lists>
// - SSQInfo
// - SSQPattern
//
//───────────────────────────────────────────────────────────
// <DEFINITIONs>
inline SSQInfo::WzTmFmt _ConvertToWzTmFmt( const WORD hour, const WORD minute )
{
return (SSQInfo::WzTmFmt)(hour)*100 + (minute);
}
//───────────────────────────────────────────────────────────
// <INTERFACEs>
inline const SSQInfo::TimeRange* const
SSQInfo::_FindMatchTimeRange(
const SSQInfo::TimeRange* const pBegin
, const SSQInfo::TimeRange* const pEnd
, const SSQInfo::WzTmFmt calctime
, DWORD* OUT pIndex
) const
{
const TimeRange* const pFind =
std::find_if( pBegin, pEnd, boost::bind( &TimeRange::OnTime, _1, calctime ) );
if( pIndex )
*pIndex = (DWORD)( ((BYTE*)pFind - (BYTE*)pBegin)/sizeof(TimeRange) );
return pFind;
}
bool SSQInfo::IsSSQOpenTime( const SYSTEMTIME* IN pSysTime, DWORD* OUT pIndex ) const
{
if( !pSysTime )
{
SYSTEMTIME sysTime;
util::TimeSync::GetLocalTime( &sysTime );
pSysTime = &sysTime;
}
const WzTmFmt calctime = _ConvertToWzTmFmt( pSysTime->wHour, pSysTime->wMinute );
const SSQInfo::TimeRange* const pEnd = &m_TimeRange[MI_ENTER_TIME_SECTION_MAX];
const TimeRange* const pFind =
_FindMatchTimeRange( &m_TimeRange[0], pEnd, calctime, pIndex );
return pFind != pEnd;
}
bool SSQInfo::IsNoticeTime( const SYSTEMTIME* IN pSysTime, DWORD* OUT pIndex ) const
{
if( !pSysTime )
{
SYSTEMTIME sysTime;
util::TimeSync::GetLocalTime( &sysTime );
pSysTime = &sysTime;
}
const WzTmFmt calctime = _ConvertToWzTmFmt( pSysTime->wHour, pSysTime->wMinute );
const SSQInfo::TimeRange* const pEnd = &m_CTimeNotice[MI_ENTER_TIME_SECTION_MAX];
const TimeRange* const pFind =
_FindMatchTimeRange( &m_CTimeNotice[0], pEnd, calctime, pIndex );
return pFind != pEnd;
}
bool SSQInfo::IsWaitingTime( const SYSTEMTIME* IN pSysTime, DWORD* OUT pIndex ) const
{
if( !pSysTime )
{
SYSTEMTIME sysTime;
util::TimeSync::GetLocalTime( &sysTime );
pSysTime = &sysTime;
}
const WzTmFmt calctime = _ConvertToWzTmFmt( pSysTime->wHour, pSysTime->wMinute );
const SSQInfo::TimeRange* const pEnd = &m_CTimeWaiting[MI_ENTER_TIME_SECTION_MAX];
const TimeRange* const pFind =
_FindMatchTimeRange( &m_CTimeWaiting[0], pEnd, calctime, pIndex );
return pFind != pEnd;
}
bool SSQInfo::IsBattleTime( const SYSTEMTIME* IN pSysTime, DWORD* OUT pIndex ) const
{
if( !pSysTime )
{
SYSTEMTIME sysTime;
util::TimeSync::GetLocalTime( &sysTime );
pSysTime = &sysTime;
}
const WzTmFmt calctime = _ConvertToWzTmFmt( pSysTime->wHour, pSysTime->wMinute );
const SSQInfo::TimeRange* const pEnd = &m_CTimeBattle[MI_ENTER_TIME_SECTION_MAX];
const TimeRange* const pFind =
_FindMatchTimeRange( &m_CTimeBattle[0], pEnd, calctime, pIndex );
return pFind!=pEnd;
}
#ifdef _SERVER
//───────────────────────────────────────────────────────────
// <지진 발생 조건>
struct sEARTHQUAKE_CONDNODE
{
SSQInfo::MINUTE_T OverThan; // 지연 시간
SSQInfo::COUNT_T RemainCnt; // 남은 인원
inline bool OnSatisfiedCondition( const sEARTHQUAKE_CONDNODE& rQuery ) const
{
return (rQuery.RemainCnt<RemainCnt) || (OverThan<=rQuery.OverThan);
}
};
static const sEARTHQUAKE_CONDNODE
sc_EQ_Cond[SSQInfo::MI_EARTHQUAKE_SECTION_MAX] =
{
// 지연시간 | 남은 인원
{ 3, 70 } // 1단계
, { 6, 50 } // 2단계
, { 9, 30 } // 3단계
, { 12, 10 } // 4단계
};
bool
SSQInfo::IsSatisfiedEarthquakeCondition(
const SSQInfo::MINUTE_T elapsedTm
, const SSQInfo::COUNT_T curplayercnt
) const //for SERVER
{
const sEARTHQUAKE_CONDNODE* const pEnd = &sc_EQ_Cond[MI_EARTHQUAKE_SECTION_MAX];
const sEARTHQUAKE_CONDNODE* pIt = &sc_EQ_Cond[0];
const sEARTHQUAKE_CONDNODE cmproot = { elapsedTm, curplayercnt };
for( ; pIt!=pEnd ; ++pIt )
{
const sEARTHQUAKE_CONDNODE& rCur = *pIt;
if( rCur.OnSatisfiedCondition( cmproot ) )
break;
}
return pIt!=pEnd;
}
MONSTERCODE
SSQInfo::GetRandomRegenMonster() const
{
const WORD rnd_val = (WORD)RandomNumberGenerator::GetRandomNumberRange( 0, m_SummonedNpcInfo.MaxRegenValue );
const SSQInfo::SUMMONED_NPC_NODE* pIt = m_SummonedNpcInfo.List;
const SSQInfo::SUMMONED_NPC_NODE* const pItEnd = &m_SummonedNpcInfo.List[m_SummonedNpcInfo.Count];
for( ; pIt != pItEnd ; ++pIt )
{
const SSQInfo::SUMMONED_NPC_NODE& rNode = *pIt;
if( rnd_val < rNode.m_SumRatio )
break;
}
if( FlowControl::FCAssert( pIt != pItEnd ) )
{
const SSQInfo::SUMMONED_NPC_NODE& rNode = *pIt;
return rNode.m_NPCCode;
}
return m_SummonedNpcInfo.List[0].m_NPCCode;
}
#endif //_SERVER
//
//───────────────────────────────────────────────────────────
//───────────────────────────────────────────────────────────
//
namespace nsSSQ
{
//───────────────────────────────────────────────────────────
VOID
SSQTicketTimeInfo::Init()
{
tmTableIndex = SSQInfo::MI_ENTER_TIME_SECTION_MAX;
tmMode = eTM_None;
countdownTick = 0;
check_start_tick= 0;
ZeroMemory( &systemTime, sizeof(systemTime) );
}
//───────────────────────────────────────────────────────────
const DWORD portal_close_timeout_c = 4; // 4'00"
//////////////////////////////////////////////////////////////////////////
//───────────────────────────────────────────────────────────
inline VOID
SSQTicketTimeInfo::_CalculationTime()
{
const DWORD post_enterable_pre_close_interval = portal_close_timeout_c*60*1000;
const DWORD cur_tick = GetTickCount();
const DWORD elapsed = !check_start_tick ? ULONG_MAX : cur_tick - check_start_tick;
( countdownTick > elapsed )
? countdownTick -= elapsed
: countdownTick = 0
;
check_start_tick = cur_tick;
ZeroMemory( &systemTime, sizeof(systemTime) );
if( !countdownTick )
{
tmMode = eTM_None;
return;
}
DWORD pole_tick = countdownTick;
if( post_enterable_pre_close_interval < countdownTick )
{
tmMode = eTM_EnterableTimeout;
pole_tick -= post_enterable_pre_close_interval;
}
else
{
tmMode = eTM_CloseTimeout;
}
const DWORD one_second = 1;
const DWORD one_minute = 60*one_second;
const DWORD one_hour = 60*one_minute;
DWORD calc_var = (DWORD)(pole_tick/1000);
systemTime.wHour = calc_var < one_hour ? 0 : WORD(calc_var/one_hour);
calc_var %= one_hour;
systemTime.wMinute = calc_var < one_minute ? 0 : WORD(calc_var/one_minute);
calc_var %= one_minute;
systemTime.wSecond = WORD(calc_var);
}
//───────────────────────────────────────────────────────────
// condition ] GetStatus() = { eTM_EnterableTimeout, eTM_CloseTimeout }
// action ] const SYSTEMTIME& countdown = GetTicketTimeInfo();
// - used field = { countdown.wHour, countdown.wMinute, countdown.wSecond }
const SYSTEMTIME&
SSQTicketTimeInfo::GetTicketTimeInfo()
{
switch( tmMode )
{
case eTM_Transaction:
break;
case eTM_EnterableTimeout:
case eTM_CloseTimeout:
_CalculationTime();
break;
case eTM_None:
default:
tmMode = eTM_None;
ZeroMemory( &systemTime, sizeof(systemTime) );
break;
}
return systemTime;
}
//───────────────────────────────────────────────────────────
//
// 서버로부터 받은 정보 설정.
VOID
SSQTicketTimeInfo::QueryResult( const SSQTicketInfo& rTicketInfo )
{
static_cast<SSQTicketInfo&>(*this) = rTicketInfo;
check_start_tick = GetTickCount();
}
//───────────────────────────────────────────────────────────
//
#ifdef _SERVER
//////////////////////////////////////////////////////////////////////////
const DWORD cTicketTimeRangeArrSize = SSQInfo::MI_ENTER_TIME_SECTION_MAX + 1;
static SSQInfo::TimeRange sTicketTimeRange[cTicketTimeRangeArrSize] =
{
0,
};
//////////////////////////////////////////////////////////////////////////
//───────────────────────────────────────────────────────────
BOOLEAN
SSQTicketTimeInfo::Update( const SYSTEMTIME* const pCurSysTime ) // for Server
{
const WORD acm24h = 24*60; // 스크립트 없으면? 죽는 거지 뭐...
const SSQInfoParser::SSQINFO_TABLE& rTable = SSQInfoParser::Instance()->GetRefSSQInfo();
if(rTable.empty())
return FALSE;
static const SSQInfo* const pSSQInfoPole = rTable.begin()->second;
if(!sTicketTimeRange[cTicketTimeRangeArrSize-1].End)
{ //calculation
CopyMemory(&sTicketTimeRange, &pSSQInfoPole->m_TimeRange, sizeof(pSSQInfoPole->m_TimeRange));
for(DWORD idx = 0; idx < SSQInfo::MI_ENTER_TIME_SECTION_MAX; ++idx)
{
SSQInfo::TimeRange& range = sTicketTimeRange[idx];
_ConvertWzTmFmt2AcmTime(range);
if(range.Start)
range.End = range.Start + portal_close_timeout_c;
}
{
SSQInfo::TimeRange& range_s = sTicketTimeRange[0];
SSQInfo::TimeRange& range_d = sTicketTimeRange[cTicketTimeRangeArrSize-1];
range_d.Start = range_s.Start + acm24h;
range_d.End = range_s.End + acm24h;
}
}
const SSQInfo::WzTmFmt check_time = pCurSysTime->wHour * 60 + pCurSysTime->wMinute;
DWORD find_index = 0;
BOOLEAN pre_enterable = FALSE, post_enterable = FALSE;
for( ; find_index < cTicketTimeRangeArrSize; ++find_index)
{
SSQInfo::TimeRange& range = sTicketTimeRange[find_index];
pre_enterable = check_time < range.Start;
post_enterable = !pre_enterable && (check_time < range.End);
if( pre_enterable | post_enterable )
break;
}
tmTableIndex = BYTE(find_index);
tmMode = pre_enterable ? eTM_EnterableTimeout : eTM_CloseTimeout;
//const SSQInfo::WzTmFmt countdownPole
// = pre_enterable
// ? sTicketTimeRange[find_index].Start
// : sTicketTimeRange[find_index].End
// ;
const SSQInfo::WzTmFmt countdownPole //= sTicketTimeRange[find_index].End;
= (sTicketTimeRange[find_index].End - check_time)
? (sTicketTimeRange[find_index].End - check_time) - 1
: 0
;
countdownTick = (DWORD)(60 - pCurSysTime->wSecond) * 1000;
countdownTick += countdownPole * 60 * 1000;
//countdownTick += (countdownPole-check_time)*60*1000;
//printf( "Update info Idx[%u] Mod[%u] CountdownTick[%u]- \n", tmTableIndex, tmMode, countdownTick );
return TRUE;
}
#endif //_SERVER
//───────────────────────────────────────────────────────────
}; // end namespace nsSSQ
//───────────────────────────────────────────────────────────
namespace nsSSQ { namespace Observer {
struct NextIndexes
{
union {
struct {
BYTE Q, W, E;
};
BYTE Indexes[3];
};
};
const Info::eCoordinates
Controller::GetNextIndex( const Info::eCoordinates current_idx, const Info::eKeyCmd inputed_cmd )
{
static const NextIndexes cKeyCmdTable[Info::eCoord_Slots] =
{
// Q W E curPos
{ Info::eCoord_1, Info::eCoord_2, Info::eCoord_3, }, /*eCoord_0*/
{ Info::eCoord_2, Info::eCoord_3, Info::eCoord_0, }, /*eCoord_1*/
{ Info::eCoord_3, Info::eCoord_0, Info::eCoord_1, }, /*eCoord_2*/
{ Info::eCoord_0, Info::eCoord_1, Info::eCoord_2, }, /*eCoord_3*/
};
if( ((DWORD)current_idx < (DWORD)Info::eCoord_Slots)
&& ((DWORD)inputed_cmd < (DWORD)Info::eKeyCmd_Max)
)
{
return (Info::eCoordinates)cKeyCmdTable[current_idx].Indexes[inputed_cmd];
}
return Info::eCoord_Slots;
};
const WzVector*
Controller::GetPosByIndex( const Info::eCoordinates inputed_idx )
{
static const WzVector cObserverCoordinateTable[Info::eCoord_Slots] =
{ // X Y Z
{ 200.00f, 177.42f, 8.77f }, /*eCoord_0*/
{ 176.96f, 199.87f, 8.77f }, /*eCoord_1*/
{ 200.00f, 223.44f, 8.77f }, /*eCoord_2*/
{ 222.10f, 199.89f, 8.77f }, /*eCoord_3*/
};
return ((DWORD)inputed_idx < (DWORD)Info::eCoord_Slots)
? &cObserverCoordinateTable[inputed_idx]
: 0
;
};
} }; // end namespace nsSSQ::Observer
namespace nsSSQ { namespace Rules {
typedef Observer::Info Info;
const eC2G_ReqRule
GetC2G_RequestRule( const Info::eRequest request )
{
static const C2G_RequestRule
C2G_RequestRuleSet[Info::eRequest_Max] =
{
{ Info::eRequest_None
, eC2G_ReqRule
( eC2G_ReqRule_BlockRequest
)
},
{ Info::eRequest_Observer
, eC2G_ReqRule
( eC2G_ReqRule_CondInSSQField
| eC2G_ReqRule_CondObserverModeOff
| eC2G_ReqRule_CondDeadState
)
},
{ Info::eRequest_Leave
, eC2G_ReqRule
( eC2G_ReqRule_CondInSSQField
| eC2G_ReqRule_CondDeadState
)
},
{ Info::eRequest_ChangeCoord
, eC2G_ReqRule
( eC2G_ReqRule_CondInSSQField
| eC2G_ReqRule_CondObserverModeOn
| eC2G_ReqRule_CondDeadState
)
},
};
//////////////////////////////////////////////////////////////////////////
const eC2G_ReqRule ruleset
= (DWORD)request < (DWORD)Info::eRequest_Max
? C2G_RequestRuleSet[request].RuleSet
: C2G_RequestRuleSet[Info::eRequest_None].RuleSet
;
return ruleset;
}
}}; //end namespace nsSSQ::Rules
//───────────────────────────────────────────────────────────