DragonNest/Server/DNGameServer/DnPartyTask.cpp
2024-12-20 16:56:44 +08:00

2029 lines
No EOL
124 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "DnPartyTask.h"
#include "GameSendPacket.h"
#include "DnWorld.h"
#include "DnWorldGrid.h"
#include "DnWorldSector.h"
#include "EtWorldEventControl.h"
#include "EtWorldEventArea.h"
#include "TaskManager.h"
#include "DnGameTask.h"
#include "DNTableFile.h"
#include "DnTableDB.h"
#include "DNGameDataManager.h"
#include "DnPlayerActor.h"
#include "DNGameRoom.h"
#include "DNUserSession.h"
#include "DNMasterConnection.h"
#include "DNMasterConnectionManager.h"
#include "DNLogConnection.h"
#include "DnDropItem.h"
#include "DnItemTask.h"
#include "DNDBConnectionManager.h"
#include "DNDBConnection.h"
#include "DNIsolate.h"
#if defined( PRE_ADD_NEWCOMEBACK )
#include "DnBlow.h"
#endif
CDnPartyTask::CDnPartyTask(CDNGameRoom * pRoom)
: CTask( pRoom )
, CMultiSingleton<CDnPartyTask, MAX_SESSION_COUNT>( pRoom )
{
//m_nPartyIndex = 0;
m_nEnteredGateIndex = -1;
m_bSyncComplete = false;
m_nRandomSeed = 0;
m_bWaitGate = false;
//m_nZoneCountTick = 0;
//m_nZoneEnterMapIdx = m_nZoneEnterGate = -1;
m_bHoldSharingReversionItem = false;
}
CDnPartyTask::~CDnPartyTask()
{
}
bool CDnPartyTask::Initialize()
{
m_Random.srand(timeGetTime());
return true;
}
void CDnPartyTask::Process( LOCAL_TIME LocalTime, float fDelta )
{
ULONG nCurTick = GetRoom()->GetGameTick();
DNVector(_KICKMEMBER)::iterator ii;
for (ii = m_KickList.begin(); ii != m_KickList.end(); )
{
if ((*ii).nKickTick < nCurTick && GetRoom()->GetRoomState() == _GAME_STATE_PLAY)
{
int nSeq = 0;
CDNGameRoom::PartyStruct * pStruct = GetRoom()->GetPartyDatabySessionID((*ii).Kick.nSessionID, nSeq);
if (pStruct)
{
pStruct->pSession->SendBackToVillage( true, (*ii).Kick.cKickKind );
}
ii = m_KickList.erase(ii);
}
else
ii++;
}
ProcessGetReversionItemList(LocalTime, fDelta);
/*if (m_nZoneCountTick != 0 && GetRoom()->GetGameTick() > m_nZoneCountTick)
{
CDnGameTask *pTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
int nStageConstructionLevel = -1;
if( nStageConstructionLevel == -1 ) nStageConstructionLevel = pTask->GetStageConstructionLevel();
if( nStageConstructionLevel == -1 ) nStageConstructionLevel = 0;
m_nRandomSeed = CRandom::Seed(GetRoom());
m_nEnteredGateIndex = m_nZoneEnterGate;
pTask->SetGateIndex(m_nZoneEnterGate);
GetRoom()->InitStateAndSync( m_nZoneEnterMapIdx, m_nZoneEnterGate, CRandom::Seed(GetRoom()), nStageConstructionLevel, true );
m_nZoneCountTick = 0;
m_nZoneEnterMapIdx = m_nZoneEnterGate = -1;
}*/
}
int CDnPartyTask::OnDispatchMessage(CDNUserSession * pSession, int nMainCmd, int nSubCmd, char *pData, int nLen )
{
switch( nMainCmd ) {
case CS_ROOM: return OnRecvRoomMessage(pSession, nSubCmd, pData, nLen );
case CS_PARTY: return OnRecvPartyMessage(pSession, nSubCmd, pData, nLen );
default : return ERROR_UNKNOWN_HEADER;
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvRoomMessage(CDNUserSession * pSession, int nSubCmd, char *pData, int nLen )
{
switch( nSubCmd ) {
case eRoom::CS_SYNC_WAIT: return OnRecvRoomSyncWait( pSession, (CSSyncWait*)pData, nLen );
}
return ERROR_UNKNOWN_HEADER;
}
int CDnPartyTask::OnRecvPartyMessage( CDNUserSession *pSession, int nSubCmd, char *pData, int nLen )
{
if (pSession->GetState() != SESSION_STATE_GAME_PLAY || pSession->IsCertified() == false)
{
g_Log.Log(LogType::_MOVEPACKET_SEQ, pSession, L"OnRecvPartyMessage RState[%d] UState[%d] SCMD[%d]\n", GetRoom()->GetRoomState(), pSession->GetState(), nSubCmd);
return ERROR_NONE;
}
switch( nSubCmd ) {
case eParty::CS_REFRESHGATEINFO: return OnRecvPartyRefreshGateInfo( pSession, (CSRefreshGateInfo *)pData, nLen );
case eParty::CS_STARTSTAGE: return OnRecvPartyStartStage( pSession, (CSStartStage *)pData, nLen );
case eParty::CS_CANCELSTAGE: return OnRecvPartyCancelStage( pSession, pData, nLen );
case eParty::CS_PARTYMEMBER_KICK: return OnRecvPartyMemberKick(pSession, pData, nLen);
case eParty::CS_SELECTDUNGEON: return OnRecvPartySelectDungeon(pSession, pData, nLen);
case eParty::CS_PARTYLEADER_SWAP: return OnRecvPartyLeaderSwap(pSession, pData, nLen);
case eParty::CS_JOINGETREVERSEITEM: return OnRecvPartyJoinGetReversionItem(pSession, pData);
case eParty::CS_ABSENT: return OnRecvPartyMemberAbsent(pSession, (CSMemberAbsent*)pData, nLen);
case eParty::CS_PARTYINVITE: return OnRecvPartyInviteMember(pSession, (CSInvitePartyMember*)pData, nLen);
case eParty::CS_SWAPMEMBERINDEX: return OnRecvPartySwapMemberIndex(pSession, (CSPartySwapMemberIndex*)pData, nLen);
#if defined( PRE_PARTY_DB )
case eParty::CS_PARTYMODIFY: return OnRecvPartyModify( pSession, (CSPartyInfoModify*)pData, nLen );
#endif // #if defined( PRE_PARTY_DB )
#if defined(PRE_MOD_REQ_JOIN_PARTY_ANSWER_MSG_APP)
case eParty::CS_PARTYASKJOINDECISION: return OnRecvPartyAskJoinDecision( pSession, (CSPartyAskJoinDecision*)pData, nLen );
#endif
case eParty::CS_GAMETOGAMESTAGE_ENTER: return OnRecvGameToGameStageEnter(pSession, (CSGameToGameStageEnter *)pData, nLen);
}
_DANGER_POINT();
return ERROR_UNKNOWN_HEADER;
}
int CDnPartyTask::OnRecvRoomSyncWait( CDNUserSession *pSession, CSSyncWait *pPacket, int nLen )
{
if (sizeof(CSSyncWait) != nLen)
return ERROR_INVALIDPACKET;
if (GetRoom()->GetRoomState() == _GAME_STATE_SYNC2SYNC)
{
pSession->SetSessionState(SESSION_STATE_SYNC_READY_2_DELAY);
#ifdef _DEBUG
g_Log.Log(LogType::_NORMAL, pSession, L"on PT_GAME_SYNC_WAIT : %s\n", pSession->GetCharacterName());
#endif
return ERROR_NONE;
}
pSession->FlushStoredPacket();
pSession->FlushPacketQueue();
for( DWORD i=0; i<GetUserCount(); i++ )
SendGameSyncWait( GetUserData(i), pSession->GetSessionID() );
int iPrevState = pSession->GetState();
pSession->SetSessionState(SESSION_STATE_READY_TO_PLAY);
#ifdef _DEBUG
g_Log.Log(LogType::_NORMAL, pSession, L"on PT_GAME_SYNC_WAIT[2] : %s RoomState:%d SessionState=%d\n", pSession->GetCharacterName(), GetRoom()->GetRoomState(), iPrevState );
#endif
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartyRefreshGateInfo( CDNUserSession *pSession, CSRefreshGateInfo *pPacket, int nLen )
{
if (sizeof(CSRefreshGateInfo) != nLen)
return ERROR_INVALIDPACKET;
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct )
{
if( pSession->GetActorHandle() )
{
CDnPlayerActor *pPlayer = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPlayer )
pPlayer->RecvPartyRefreshGateInfo( pPacket->Position );
}
pStruct->nEnteredGateIndex = ( pPacket->boEnter ) ? GetCheckGateIndex( pSession ) : -1;
if (CheckAndRequestGateIndex(pStruct->nEnteredGateIndex, pSession->GetPartyMemberIndex()) == false)
pStruct->nEnteredGateIndex = -1;
}
else
_DANGER_POINT(); //없어도 되는건가요?
return ERROR_NONE;
}
//rlkt dirty fix
int CDnPartyTask::OnRecvGameToGameStageEnter(CDNUserSession *pSession, CSGameToGameStageEnter *pPacket, int nLen)
{
//if (sizeof(CSGameToGameStageEnter) != nLen)
// return ERROR_INVALIDPACKET;
//CDnGameTask *pTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask("GameTask");
//int nMapIndex = pTask->GetMapTableID();
//GateStruct *pStruct = CDnWorld::GetInstance(GetRoom()).GetGateStruct(m_nEnteredGateIndex);
//if (m_nEnteredGateIndex == -1 || pStruct == NULL) {
// for (DWORD i = 0; i<GetUserCount(); i++) {
// GetUserData(i)->SendCancelStage(ERROR_PARTY_STARTSTAGE_FAIL);
// g_Log.Log(LogType::_ERROR, pSession, L"게임을 시작할 수 없습니다가 자꾸 뜬다 이거 나오면 .......\n");
// }
// return ERROR_NONE;
//}
//return ERROR_NONE;
////cSelectMapIndex
/*
if (sizeof(CSGameToGameStageEnter) != iLen)
return ERROR_INVALIDPACKET;
int TargetMapIndex = -1;
int TargetGateNo = -1;
char m_cGateSelect = pPacket->cSelectMapIndex;
SendSelectStage(m_cGateSelect);
TargetMapIndex = GetTargetMapIndex();
TargetGateNo = g_pDataManager->GetGateNoByGateNo(GetMapIndex(), m_cGateNo, m_cGateSelect);
if (TargetMapIndex <= 0 || m_pField == NULL)
{
if (GetPartyID() > 0)
{
CDNParty *pParty = g_pPartyManager->GetParty(GetPartyID());
if (pParty == NULL)
return ERROR_PARTY_STARTSTAGE_FAIL;
pParty->SendAllCancelStage(ERROR_PARTY_STARTSTAGE_FAIL);
}
else
{
m_cGateNo = -1;
m_cGateSelect = -1;
return ERROR_PARTY_STARTSTAGE_FAIL;
}
return ERROR_NONE;
}
// 파티가 Ready 된 후에 클라이언트에서 임의로 움직이거나 했을 경우 움직인 놈이 RefreshGateInfo 를 요청하면서
// 그 클라이언트의 GateIndex 가 -1 이 되버린다.
// 그럴 경우 파티원 전원이 시작이 안되기땜에 일단 여기서 파티원중 Ready 가 풀린놈이 있으면 시작을 못하게 하자.
// 혹은 StartStage 할때 다시 GateIndex 와 RandomSeed 를 보내줘도 되는데.. 이럴 경우 풀린놈이 거래따위를 하고
// 있다가 강제로 이동될 시 무슨일이 일어날지 모르니 일단은 Cancel 을 시키는 쪽으로 해두는 것이 좋을듯 함.
// 자기자신(리더 혹은 개인) 은 위에서 이미 게이트가 -1 일 경우에 TargetMapIndex 가 -1 나오면서 켄슬되므로 무시~
if (g_pMasterConnection->GetActive() == false)
return ERROR_GENERIC_MASTERCON_NOT_FOUND;
const sChannelInfo * pChannelInfo = g_pMasterConnection->GetChannelInfo(GetChannelID());
if (pChannelInfo == NULL)
return ERROR_PARTY_STARTSTAGE_FAIL;
int nFarmMapID = -1;
bool bEnterFarm = false;
bEnterFarm = g_pFarm->GetFarmMapID(pPacket->nFarmDBID, nFarmMapID);
GameTaskType::eType TaskType = m_pField->GetGameTaskType();
if (m_nGateType > 0)
TaskType = (GameTaskType::eType)m_nGateType;
CDNParty* pParty = NULL;
#if defined(_FINAL_BUILD)
if ((GetAccountLevel() <= AccountLevel_QA) && (GetAccountLevel() >= AccountLevel_New))
{
// GM 은 패스한다.
}
else
#endif // #if defined(_FINAL_BUILD)
{
if (!g_pDataManager->CheckChangeMap(GetMapIndex(), TargetMapIndex))
{
WCHAR wszBuf[100];
wsprintf(wszBuf, L"VILLAGE Prev[%d]->Next[%d]", GetMapIndex(), TargetMapIndex);
GetDBConnection()->QueryAddAbuseLog(this, ABUSE_MOVE_SERVERS, wszBuf);
}
}
if (GetPartyID() > 0)
{
if (bEnterFarm)
return ERROR_PARTY_STARTSTAGE_FAIL;
if (m_boPartyLeader == false)
return ERROR_PARTY_STARTSTAGE_FAIL;
pParty = g_pPartyManager->GetParty(GetPartyID());
if (pParty == NULL)
return ERROR_PARTY_STARTSTAGE_FAIL;
//파티상태라면 중복이동체크를 전유저에 걸처서 해보자
if (pParty->CheckPartyUserStartFlag() == false)
{
g_Log.Log(LogType::_GAMECONNECTLOG, this, L"CS_STARTSTAGE Repetitive Move\n");
return ERROR_PARTY_STARTSTAGE_FAIL;
}
if (pParty->DiffMemberGateNo(m_cGateNo))
{
if (g_pMasterConnection && g_pMasterConnection->GetActive())
{
pParty->SetStartGame(true);
pParty->SendSelectStage(m_cGateSelect);
g_pMasterConnection->SendReqGameID(TaskType, REQINFO_TYPE_PARTY, pParty->GetPartyID(), GetChannelID(), pParty->GetRandomSeed(), GetMapIndex(), m_cGateNo, pPacket->Difficulty, false, pParty, 0, m_cGateSelect); // GameID를 요청
}
else
{
pParty->SendAllCancelStage(ERROR_PARTY_STARTSTAGE_FAIL);
return ERROR_NONE;
}
}
else
{
pParty->SendAllCancelStage(ERROR_PARTY_STARTSTAGE_FAIL);
return ERROR_NONE;
}
}
else
{
if (g_pMasterConnection && g_pMasterConnection->GetActive())
{
if (bEnterFarm)
{
#if defined( PRE_ADD_FARM_DOWNSCALE )
int iAttr = Farm::Attr::None;
if (g_pFarm->GetFarmAttr(pPacket->nFarmDBID, iAttr) == false)
return ERROR_NONE;
#if defined( PRE_ADD_VIP_FARM )
if (iAttr&Farm::Attr::Vip)
{
if (bIsFarmVip() == false)
return ERROR_FARM_INVALID_VIP;
}
#endif // #if defined( PRE_ADD_VIP_FARM )
if (iAttr&Farm::Attr::GuildChampion)
{
// 길드농장 입장 검사
if (GetGuildUID().IsSet() == false || g_pGuildWarManager->GetPreWinGuildUID().IsSet() == false || g_pGuildWarManager->GetPreWinGuildUID() != GetGuildUID())
return ERROR_FARM_ENTERANCE_CONDITION;
}
SetLastSubVillageMapIndex(GetMapIndex());
g_pMasterConnection->SendReqGameID(GameTaskType::Farm, REQINFO_TYPE_FARM, m_nAccountDBID, GetChannelID(), timeGetTime(), nFarmMapID, 0, CONVERT_TO_DUNGEONDIFFICULTY(0), true, NULL, pPacket->nFarmDBID);
}
else
{
g_pMasterConnection->SendReqGameID(TaskType, REQINFO_TYPE_SINGLE, m_nAccountDBID, GetChannelID(), m_nSingleRandomSeed, GetMapIndex(), m_cGateNo, pPacket->Difficulty, false, NULL, 0, m_cGateSelect); // GameID를 요청
}
}
else
return ERROR_PARTY_STARTSTAGE_FAIL;
}
//여기까지 오면 마스터에 보낸것이다. 리턴메세지를 받기전까지는 제한처리를 위한 플래그세팅해주자
if (pParty)
{
//pParty가 유효하다면 파티단위 이동이 이루어진 것이다. 파티유저들의 플래그를 바꾸어 준다.
pParty->SetPartyUserStartFlag(true);
}
else
{
//아니라면 개인이동
m_bIsStartGame = true;
}
g_Log.Log(LogType::_NORMAL, this, L"[ADBID:%u, CDBID:%I64d, SID:%u, ObjID:%u] [CS_STARTSTAGE] TargetMap:%d, MapIndex:%d GateNo:%d\r\n", m_nAccountDBID, m_biCharacterDBID, GetSessionID(), m_BaseData.nObjectID, TargetMapIndex, GetMapIndex(), m_cGateNo);
return ERROR_NONE;*/
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartyStartStage( CDNUserSession *pSession, CSStartStage *pPacket, int nLen )
{
if (sizeof(CSStartStage) != nLen)
return ERROR_INVALIDPACKET;
m_bWaitGate = false;
//플로우 변경 요 타이밍에 마스터에 물어 봅니다.
CDnGameTask *pTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
if( pTask->IsPartyLeader( pSession ) == false )
return ERROR_NONE;
int nMapIndex = pTask->GetMapTableID();
GateStruct *pStruct = CDnWorld::GetInstance(GetRoom()).GetGateStruct( m_nEnteredGateIndex );
if( m_nEnteredGateIndex == -1 || pStruct == NULL ) {
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL );
g_Log.Log(LogType::_ERROR, pSession, L"게임을 시작할 수 없습니다가 자꾸 뜬다 이거 나오면 .......\n");
}
return ERROR_NONE;
}
TDUNGEONDIFFICULTY StageDifficulty = pPacket->Difficulty;
if( StageDifficulty >= Dungeon::Difficulty::Max )
StageDifficulty = pTask->GetStageDifficulty();
if( StageDifficulty < Dungeon::Difficulty::Easy )
StageDifficulty = Dungeon::Difficulty::Easy;
switch( pStruct->MapType )
{
case GlobalEnum::eMapTypeEnum::MAP_VILLAGE:
{
// 운영자난입 같은 경우 유저가 마을로 돌아갈 때 같이 보내준다.
if (g_pMasterConnectionManager->SendRequestNextVillageInfo(pSession->GetWorldSetID(), nMapIndex, m_nEnteredGateIndex, pPacket->bReturnVillage, GetRoom()) == false)
{
for( DWORD i=0; i<GetUserCount(); i++ )
GetUserData(i)->SendCancelStage( ERROR_GENERIC_MASTERCON_NOT_FOUND );
}
break;
}
case GlobalEnum::eMapTypeEnum::MAP_WORLDMAP:
// 여기서두 나중에 월드간 이동이 정말 가능한지 체크해주자.
#if defined(PRE_FIX_INITSTATEANDSYNC)
GetRoom()->ReserveInitStateAndSync( nMapIndex, m_nEnteredGateIndex, m_nRandomSeed, StageDifficulty, false );
#else
GetRoom()->InitStateAndSync( nMapIndex, m_nEnteredGateIndex, m_nRandomSeed, StageDifficulty, false );
#endif //#if defined(PRE_FIX_INITSTATEANDSYNC)
break;
case GlobalEnum::eMapTypeEnum::MAP_DUNGEON:
{
if (GetRoom()->IsInviting())
{
for( DWORD i=0; i<GetUserCount(); i++ )
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL );
return ERROR_NONE;
}
#if defined( PRE_PARTY_DB )
if( GetRoom()->bIsExistBreakIntoUser() )
{
for( DWORD i=0; i<GetUserCount(); i++ )
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL );
return ERROR_NONE;
}
#endif // #if defined( PRE_PARTY_DB )
#if defined (PRE_WORLDCOMBINE_PARTY)
if( GetRoom()->bIsWorldCombineParty())
{
TDUNGEONDIFFICULTY TargetDifficulty = GetRoom()->GetPartyDifficulty();
if (TargetDifficulty != StageDifficulty && TargetDifficulty != Dungeon::Difficulty::Max)
{
for( DWORD i=0; i<GetUserCount(); i++ )
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL );
return ERROR_NONE;
}
}
#endif // #if defined (PRE_WORLDCOMBINE_PARTY)
bool bDirectConnect = false;
int nGateIndex = m_nEnteredGateIndex;
switch( CDnWorld::GetInstance(GetRoom()).GetMapType() ) {
case EWorldEnum::MapTypeDungeon:
// 기존에 던전이였으면 계속해서 던전의 레벨을 이어가야한다.
StageDifficulty = pTask->GetStageDifficulty();
break;
case EWorldEnum::MapTypeWorldMap:
case EWorldEnum::MapTypeVillage:
// 기존에 월드맵 혹은 마을이였으면
// 여기서 시작할때 잠깐 체크.. 클라믿으면 안되니.. 월드맵 -> 던전 들어갈때만 체크하자.
// 리턴되면 할 수 없는 레벨을 선택했거나 제한레벨에 걸리는데두 시작한거다.
bool bCheckFatigue = true;
#if defined(PRE_ADD_WORLD_EVENT) // 이건 없어 집니다.
#else
TEvent * pEvent = GetRoom()->GetApplyEvent(_EVENT_1_FATIGUE);
if (pEvent)
bCheckFatigue = false;
#endif //#if defined(PRE_ADD_WORLD_EVENT)
if( m_nEnteredGateIndex != -1 ) {
if( pStruct->MapType == EWorldEnum::MapTypeDungeon ) {
DungeonGateStruct *pDungeonGate = NULL;
short nCancelCode = ERROR_NONE;
//bool bCancel = false;
if( pStruct->nMapIndex >= DUNGEONGATE_OFFSET ) {
pDungeonGate = (DungeonGateStruct *)pStruct;
if( pPacket->cSelectDungeonIndex < 0 || pPacket->cSelectDungeonIndex >= (char)pDungeonGate->pVecMapList.size() )
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL;
//bCancel = true;
else {
pDungeonGate = (DungeonGateStruct *)pDungeonGate->pVecMapList[pPacket->cSelectDungeonIndex];
nGateIndex = pDungeonGate->cStartGateIndex;
nMapIndex = pDungeonGate->nMapIndex;
bDirectConnect = true;
pSession->VerifyValidMap(nMapIndex);
}
}
else {
pDungeonGate = (DungeonGateStruct *)pStruct;
}
if( pDungeonGate->nFatigue[ StageDifficulty ] == 0 ) bCheckFatigue = false;
// 피로도 체크
if (bCheckFatigue)
{
if (CheckPartyFatigue() == false) //던전이라면 피로도 체크 한번 해본다.
{
for( DWORD i=0; i<GetUserCount(); i++ )
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL_FATIGUE_SHORTAGE );
return ERROR_NONE;
}
}
switch( pTask->GetGameTaskType() )
{
case GameTaskType::DarkLair:
StageDifficulty = Dungeon::Difficulty::Abyss;
break;
}
#if defined(PRE_ADD_CHALLENGE_DARKLAIR)
if( pDungeonGate->cCanDifficult[ StageDifficulty ] != TRUE )
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL;
if( nCancelCode == ERROR_NONE )
{
EWorldEnum::PermitGateEnum PermitFlag = EWorldEnum::PermitEnter;
if( g_pDataManager->IsCloseGateByTime(nMapIndex) )
PermitFlag = EWorldEnum::PermitClose;
if(PermitFlag == EWorldEnum::PermitEnter)
PermitFlag = pDungeonGate->CanEnterDungeon( GetRoom());
if( PermitFlag != EWorldEnum::PermitEnter )
{
if( PermitFlag & EWorldEnum::PermitLessPlayerLevel )
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL_ACTLEVEL_SHORTAGE;
else if( PermitFlag & EWorldEnum::PermitExceedTryCount )
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL_EXCEED_TRY_COUNT;
else if( PermitFlag & EWorldEnum::PermitNotEnoughItem )
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL_DUNGEONNEEDITEM_SHORTAGE;
else if( PermitFlag & EWorldEnum::PermitClose )
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL_NOT_AVAILABLE_TIME;
else
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL;
}
}
#else
if( nCancelCode == ERROR_NONE && ( pDungeonGate->cCanDifficult[ StageDifficulty ] != TRUE || pDungeonGate->CanEnterDungeon( GetRoom() ) != EWorldEnum::PermitEnter ) ) {
nCancelCode = ERROR_PARTY_STARTSTAGE_FAIL_ACTLEVEL_SHORTAGE;
}
#endif //#if defined(PRE_ADD_CHALLENGE_DARKLAIR)
if( nCancelCode != ERROR_NONE ) {
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetUserData(i)->SendCancelStage( nCancelCode );
}
return ERROR_NONE;
}
#if defined(PRE_ADD_CP_RANK)
// 어비스 일때는 베스트 랭킹 조회한다.
if(pTask->GetGameTaskType() != GameTaskType::DarkLair && StageDifficulty == Dungeon::Difficulty::Abyss)
{
CDNUserSession* pSession = NULL;
bool bFirst = true;
for( DWORD i=0; i<GetUserCount(); i++ )
{
pSession = GetUserData(i);
if( pSession )
{
if( bFirst )
{
pSession->GetDBConnection()->QueryGetStageClearBest(pSession, nMapIndex);
bFirst = false;
}
pSession->GetDBConnection()->QueryGetStageClearPersonalBest(pSession, nMapIndex);
}
}
}
#endif //#if defined(PRE_ADD_CP_RANK)
// 스테이지 시작 로그
BYTE cThreadID;
CDNDBConnection* pDBCon = g_pDBConnectionManager->GetDBConnection( cThreadID );
if( pDBCon )
{
pDBCon->QueryAddStageStartLog( cThreadID, GetRoom()->GetWorldSetID(), 0, GetRoom()->GetRoomLogIndex(), GetRoom()->GetPartyLogIndex(), static_cast<BYTE>(GetUserCount()), nMapIndex, static_cast<DBDNWorldDef::DifficultyCode::eCode>(StageDifficulty+1) );
GetRoom()->SetStageStartLogFlag( true );
GetRoom()->SetStageEndLogFlag( false );
}
}
}
break;
}
#if defined(PRE_FIX_INITSTATEANDSYNC)
GetRoom()->ReserveInitStateAndSync( nMapIndex, nGateIndex, m_nRandomSeed, StageDifficulty, bDirectConnect );
#else
GetRoom()->InitStateAndSync( nMapIndex, nGateIndex, m_nRandomSeed, StageDifficulty, bDirectConnect );
#endif //#if defined(PRE_FIX_INITSTATEANDSYNC)
}
break;
default:
{
// Map Type is Unknown
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL );
}
g_Log.Log(LogType::_ERROR, pSession, L"게임을 시작할 수 없습니다가 자꾸 뜬다 이거 나오면 쳇.......\n");
}
break;
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartyCancelStage( CDNUserSession *pSession, char *pPacket, int nLen )
{
if (nLen != 0)
return ERROR_INVALIDPACKET;
m_bWaitGate = false;
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetUserData(i)->SendCancelStage( ERROR_NONE );
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartyMemberKick(CDNUserSession * pSession, char * pPacket, int nLen)
{
CSPartyMemberKick * pKick = (CSPartyMemberKick*)pPacket;
if (sizeof(CSPartyMemberKick) != nLen)
return ERROR_INVALIDPACKET;
CDNGameRoom::PartyStruct * pPartyStruct = GetPartyData(pSession);
if (pPartyStruct && pPartyStruct->bLeader == true)
{
if (pPartyStruct->nEnteredGateIndex != -1) //게이트에 서있지 않아야 가능~
{
_DANGER_POINT(); //클라이언트에서 보내면 안되는거라 단거
return ERROR_NONE;
}
//정상이면 바로 하지 말고 5초 뒤에 하랍니다 ”?
int nSeq = 0;
CDNGameRoom::PartyStruct * pStruct = GetRoom()->GetPartyDatabySessionID(pKick->nSessionID, nSeq);
if (pStruct)
{
if (pStruct->pSession->GetAbsent() == false)
return ERROR_NONE;
_KICKMEMBER kick;
memset(&kick, 0, sizeof(kick));
kick.nKickTick = GetRoom()->GetGameTick() + (5 * 1000);
kick.nSessionID = pSession->GetSessionID();
kick.nAccountDBID = pSession->GetAccountDBID();
kick.cWorldID = (BYTE)pSession->GetWorldSetID();
kick.biCharacterDBID = pSession->GetCharacterDBID();
memcpy(&kick.Kick, pKick, sizeof(CSPartyMemberKick));
m_KickList.push_back(kick);
pStruct->pSession->SendCountDownMsg(true, 5, 3537, 2);
}
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartySelectDungeon(CDNUserSession * pSession, char * pPacket, int nLen)
{
CSSelectDunGeon * pMsg = (CSSelectDunGeon*)pPacket;
if (sizeof(CSSelectDunGeon) != nLen)
return ERROR_INVALIDPACKET;
for( DWORD i=0; i<GetUserCount(); i++ ) {
if( GetUserData(i) == pSession ) continue;
GetUserData(i)->SendSelectDungeonInfo(pMsg->nMapIndex, pMsg->cDiffyculty);
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartyLeaderSwap(CDNUserSession * pSession, char * pPacket, int nLen)
{
CSPartyLeaderSwap * pSwap = (CSPartyLeaderSwap*)pPacket;
if (sizeof(CSPartyLeaderSwap) != nLen)
return ERROR_INVALIDPACKET;
if (GetRoom())
{
int nSeq = 0;
CDNGameRoom::PartyStruct * pLeaderStruct = GetRoom()->GetPartyDatabySessionID(pSession->GetSessionID(), nSeq);
if ( pLeaderStruct && pLeaderStruct->bLeader == true)
{
int nNewSeq = 0;
CDNGameRoom::PartyStruct * pNewLeaderStruct = GetRoom()->GetPartyDatabySessionID(pSwap->nSessionID, nNewSeq);
if (pNewLeaderStruct)
{
if (pNewLeaderStruct->pSession->bIsGMTrace())
return ERROR_PARTY_LEADER_APPOINTMENTFAIL;
pLeaderStruct->bLeader = false;
pNewLeaderStruct->bLeader = true;
UpdateGateInfo();
for(DWORD i=0; i<GetUserCount(); i++)
{
if (GetUserData(i) != NULL)
GetUserData(i)->SendSwapPartyLeader(pSwap->nSessionID, ERROR_NONE);
}
#ifdef PRE_FIX_PARTY_STAGECLEAR_CHANGEMASTER
CDnGameTask *pTask = static_cast<CDnGameTask *>(GetRoom()->GetTaskMng()->GetTask( "GameTask" ));
if( pTask ) {
pTask->SetWarpDungeonClearToLeaderCheck(true);
}
#endif
return ERROR_NONE;
}
}
}
pSession->SendSwapPartyLeader(0, ERROR_PARTY_LEADER_APPOINTMENTFAIL);
return ERROR_NONE;
}
void CDnPartyTask::RequestPartyMember()
{
int nCnt = 0;
UINT nMember[PARTYMAX];
memset(nMember, 0, sizeof(nMember));
for( DWORD i=0; i<GetUserCount(); i++ )
{
if (GetUserData(i) != NULL)
{
nMember[nCnt] = GetUserData(i)->GetSessionID();
nCnt++;
}
}
for( DWORD i=0; i<GetUserCount(); i++ )
{
SendRefreshPartyMember(GetUserData(i), nMember, nCnt);
}
}
void CDnPartyTask::RequestSyncStart()
{
SetSyncComplete( true );
CDnGameTask *pTask = static_cast<CDnGameTask *>(GetRoom()->GetTaskMng()->GetTask( "GameTask" ));
if( pTask ) {
pTask->RequestGateInfo();
}
_RequestSyncStartMsg();
}
void CDnPartyTask::_RequestSyncStartMsg()
{
for( UINT i=0 ; i<GetUserCount() ; ++i )
{
CDNUserSession* pGameSession = GetUserData(i);
if( GetRoom() && pGameSession )
GetRoom()->OnRequestSyncStartMsg( pGameSession );
}
}
bool CDnPartyTask::CheckPartyFatigue()
{
#if defined( PRE_USA_FATIGUE )
for( DWORD i=0; i<GetUserCount(); i++ )
{
GetUserData(i)->SetNoFatigueEnter( false );
if ((GetUserData(i)->GetFatigue() <= 0) && (GetUserData(i)->GetWeeklyFatigue() <= 0) && (GetUserData(i)->GetPCBangFatigue() <= 0) && (GetUserData(i)->GetEventFatigue() <= 0) && (GetUserData(i)->GetVIPFatigue() <= 0))
GetUserData(i)->SetNoFatigueEnter( true );
}
return true;
#else
for( DWORD i=0; i<GetUserCount(); i++ ) {
if ((GetUserData(i)->GetFatigue() <= 0) && (GetUserData(i)->GetWeeklyFatigue() <= 0) && (GetUserData(i)->GetPCBangFatigue() <= 0) && (GetUserData(i)->GetEventFatigue() <= 0) && (GetUserData(i)->GetVIPFatigue() <= 0))
return false;
}
return true;
#endif // #if defined( PRE_USA_FATIGUE )
}
bool CDnPartyTask::CheckAndRequestGateIndex(int nGateNo, int nMemberIdx)
{
if( m_bWaitGate )
return false;
char cGateNo[PARTYMAX];
memset(cGateNo, -1, sizeof(cGateNo));
if( GetRoom() && GetRoom()->bIsFarmRoom() )
return false;
// 누군가 난입하는 녀석이 있으면 게이트 이동 못하게 막는다.
if (GetRoom())
{
bool bCheck = false;
int nRet = ERROR_NONE;
if (GetRoom()->bIsExistBreakIntoUser())
{
#if !defined( _FINAL_BUILD )
g_Log.Log( LogType::_NORMAL, L"누군가 난입하는 녀석이 있으면 게이트 이동 못하게 막는다.\r\n" );
#endif
bCheck = true;
nRet = ERROR_PARTY_REFRESHGATEFAIL_REQRETREAT;
}
if (GetRoom()->IsInviting())
{
#if !defined( _FINAL_BUILD )
g_Log.Log( LogType::_NORMAL, L"초대중이라면 게이트이동을 막는다.\r\n" );
#endif
bCheck = true;
nRet = ERROR_PARTY_REFRESHGATEFAIL_REQRETREAT;
}
if (IsPartySharingReversionItem())
{
bCheck = true;
nRet = ERROR_PARTY_DUNGEONWARPOUT_FAIL_ITEMSHARING;
}
if (bCheck)
{
//에러가 발생했다면 게이트값을 넣어서 보내준다.
if (nGateNo >= 0 && nMemberIdx >= 0 && nMemberIdx < PARTYMAX)
cGateNo[nMemberIdx] = (char)nGateNo;
SendRefreshGate(cGateNo, nRet);
return false;
}
}
bool bAllSame = false;
std::vector<std::pair<int, int>> vGate;
std::vector<std::pair<int, int>>::iterator ii;
CDnGameTask *pTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
m_nEnteredGateIndex = -1;
pTask->SetGateIndex( -1 );
int nDeadCount = 0;
int nGMCount = 0;
int nUserCount = GetUserCount();
for(int i = 0; i < nUserCount; i++)
{
if(GetUserData(i)->GetActorHandle() && GetUserData(i)->GetActorHandle()->IsDie())
{
nDeadCount++;
continue;
}
if( GetUserData(i)->bIsGMTrace() )
{
++nGMCount;
continue;
}
int nMemberIndex = GetRoom()->GetPartyIndex() > 0 ? GetUserData(i)->GetPartyMemberIndex() : i;
if (nMemberIndex < 0) continue;
cGateNo[nMemberIndex] = (char)GetPartyData(i)->nEnteredGateIndex;
if (cGateNo[nMemberIndex] != -1)
{
if (vGate.size() <= 0)
vGate.push_back(std::make_pair(cGateNo[nMemberIndex], 1));
else
{
for (ii = vGate.begin(); ii != vGate.end(); ii++)
if ((*ii).first == cGateNo[nMemberIndex])
(*ii).second++;
}
}
}
//게이트 정보를 업데이트 시켜준다.
SendRefreshGate(cGateNo, ERROR_NONE);
//어떤걸 만족하는지 찾는다.
int nTargetGate = -1;
for (ii = vGate.begin(); ii != vGate.end(); ii++)
{
if ((*ii).second == (nUserCount - nDeadCount - nGMCount)) {
bAllSame = true;
nTargetGate = (*ii).first;
}
}
char cDungeonEnterCount = 0;
char cCanEnter[5][5] = { false, };
char cPermitFlag[5] = { EWorldEnum::PermitEnter, };
if (bAllSame)
{
if( nTargetGate != -1 )
{
GateStruct *pStruct = CDnWorld::GetInstance(GetRoom()).GetGateStruct( nTargetGate );
if( pStruct && pStruct->PermitFlag != EWorldEnum::PermitEnter )
return false;
#if defined( PRE_PARTY_DB )
if( pStruct->MapType == EWorldEnum::MapTypeVillage )
{
int iPermitLevel = g_pDataManager->GetMapPermitLevel( pStruct->nMapIndex );
for( DWORD i=0 ; i<GetUserCount() ; ++i )
{
CDNUserSession* pTempSession = GetUserData(i);
if( pTempSession == NULL )
continue;
if( pTempSession->GetLevel() < iPermitLevel )
return false;
}
}
#endif // #if defined( PRE_PARTY_DB )
}
m_nRandomSeed = CRandom::Seed(GetRoom());//_rand(GetRoom());
m_nEnteredGateIndex = nTargetGate;
pTask->SetGateIndex( nTargetGate );
if( nTargetGate != -1 ) {
GateStruct *pStruct = CDnWorld::GetInstance(GetRoom()).GetGateStruct( nTargetGate );
if( pStruct )
{
if( pStruct->MapType == EWorldEnum::MapTypeDungeon )
{
m_nRandomSeed = pTask->CheckRecoveryDungeonHistorySeed( pStruct->nMapIndex, m_nRandomSeed );
// 던전 입구일 경우에는 GateInfo 에 CanEnter 관련 정보도 보내주도록 하자.
if( CDnWorld::GetInstance(GetRoom()).GetMapType() == EWorldEnum::MapTypeWorldMap ) {
DungeonGateStruct *pDungeonStruct = (DungeonGateStruct *)pStruct;
if( pStruct->nMapIndex >= DUNGEONGATE_OFFSET ) {
cDungeonEnterCount = (char)pDungeonStruct->pVecMapList.size();
for( int i=0; i<cDungeonEnterCount; i++ ) {
memcpy( cCanEnter[i], ((DungeonGateStruct *)pDungeonStruct->pVecMapList[i])->cCanDifficult, sizeof(bool)*5 );
cPermitFlag[i] = ((DungeonGateStruct *)pDungeonStruct->pVecMapList[i])->PermitFlag;
}
}
else {
cDungeonEnterCount = 1;
memcpy( cCanEnter[0], pDungeonStruct->cCanDifficult, sizeof(char)*5 );
cPermitFlag[0] = pDungeonStruct->PermitFlag;
}
}
}
}
}
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetUserData(i)->SendGateInfo( -1, (char)nTargetGate, cDungeonEnterCount, (char*)cCanEnter, (char*)cPermitFlag );
}
m_bWaitGate = true;
}
return true;
}
/*
void CDnPartyTask::CalcDungeonEnterGateCondition( CDnWorld::DungeonGateStruct *pStruct, short &nDungeonEnterPermit )
{
//던전 입장시 필요아이템검사
UINT nNeedItemID = pStruct->nNeedItemID;
int nNeedItemCount = pStruct->nNeedItemCount;
if (nNeedItemID > 0)
{
for( DWORD j=0; j<GetUserCount(); j++ ) {
nDungeonEnterPermit = GetUserData(j)->GetItem()->GetInventoryItemCount(nNeedItemID) >= nNeedItemCount ? ERROR_NONE : ERROR_PARTY_STARTSTAGE_FAIL_DUNGEONNEEDITEM_SHORTAGE;
if( nDungeonEnterPermit != ERROR_NONE ) break;
}
}
}
*/
int CDnPartyTask::GetCheckGateIndex( CDNUserSession *pSession )
{
if( !pSession ) return -1;
if( !pSession->GetActorHandle() ) return -1;
if (!GetRoom()) return -1;
CDnPlayerActor *pPlayer = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if(! pPlayer ) return -1;
if( pPlayer->IsDie() || pPlayer->IsHit() ) return -1;
for( DWORD i=0; i<CDnWorld::GetInstance(GetRoom()).GetGateCount(); i++ ) {
GateStruct *pStruct = CDnWorld::GetInstance(GetRoom()).GetGateStructFromIndex(i);
if (pStruct == NULL) continue;
if( !pStruct->pGateArea ) continue;
if( !pStruct->pGateArea->IsActive() ) continue;
if( pStruct->pGateArea->CheckArea( *pPlayer->GetStaticPosition(), true ) == false ) continue;
return (int)pStruct->cGateIndex;
}
return -1;
}
//void CDnPartyTask::ResetSync()
//{
// m_bSyncComplete = false;
// for( DWORD i=0; i<GetUserCount(); i++ ) {
// GetPartyData(i)->pSession->SetSessionState(SESSION_STATE_READY_TO_SYNC);
// //bSync = false;
// }
//}
void CDnPartyTask::ResetGateIndex()
{
m_bWaitGate = false;
m_nEnteredGateIndex = -1;
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetPartyData(i)->nEnteredGateIndex = -1;
}
}
void CDnPartyTask::OutPartyMember( UINT nOutPartyMemberUID, UINT nNewLeaderUID, char cKickKind )
{
CDNUserSession *pSession;
CDNUserSession *pOutSession = GetRoom()->GetUserSession( nOutPartyMemberUID );
if (pOutSession)
pOutSession->SetOutedMember();
#if defined( PRE_PARTY_DB )
if(pOutSession)
{
if ( pOutSession->GetGameRoom()->GetGameType() != REQINFO_TYPE_SINGLE )
{
DelPartyMemberDB( pOutSession );
}
}
#endif
for( DWORD i=0; i<GetUserCount(); i++ ) {
pSession = GetUserData(i);
bool bSendPartyOut = false;
if (pSession->GetGameRoom()->GetGameType() != REQINFO_TYPE_SINGLE || pSession->bIsGMTrace() || pSession->GetGameRoom()->bIsFarmRoom() )
bSendPartyOut = true;
if( pOutSession && pOutSession->bIsGMTrace() ) bSendPartyOut = true;
#if defined( PRE_WORLDCOMBINE_PARTY )
if(pSession->GetOutedMember() && pSession->GetSessionID() != nOutPartyMemberUID)
bSendPartyOut = false;
#endif
if( bSendPartyOut )
pSession->SendPartyOut(ERROR_NONE, cKickKind, nOutPartyMemberUID);
if (pSession->GetSessionID() == nOutPartyMemberUID)
{
#if !defined( PRE_PARTY_DB )
if (GetUserCountWithoutPartyOutUser() == 1)
{
// 파티 종료 로그
BYTE cThreadID;
CDNDBConnection* pDBCon = g_pDBConnectionManager->GetDBConnection( cThreadID );
if( pDBCon )
pDBCon->QueryAddPartyEndLog( cThreadID, GetRoom()->GetWorldSetID(), 0, GetRoom()->GetPartyLogIndex() );
}
#endif
continue;
}
if (nNewLeaderUID > 0)
{
pSession->SendChangeLeader(nNewLeaderUID);
#ifdef PRE_FIX_PARTY_STAGECLEAR_CHANGEMASTER
CDnGameTask *pTask = static_cast<CDnGameTask *>(GetRoom()->GetTaskMng()->GetTask( "GameTask" ));
if( pTask ) {
pTask->SetWarpDungeonClearToLeaderCheck(true);
}
#endif
}
}
#if defined( PRE_ADD_NEWCOMEBACK )
if( pOutSession && pOutSession->GetComebackAppellation() > 0 )
{
DelPartyMemberAppellation( pOutSession->GetComebackAppellation() );
}
#endif
}
void CDnPartyTask::UpdateGateInfo()
{
CDnGameTask *pTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
// Refresh 해보고 게이트의 변경사항이 생겼으면 게이트인포를 보낸다.
if( CDnWorld::GetInstance(GetRoom()).GetMapType() == EWorldEnum::MapTypeWorldMap ) {
CDnGameTask *pLocalTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
// 나갔을때는 게이트의 변화가 없더레도 리플레쉬 후 보내줘야 한다.
// 조건이 안되는 놈들의 리스트를 갱신해야하기 때문. if 체크 하지말자.
CDnWorld::GetInstance(GetRoom()).RefreshGate( pLocalTask->GetMapTableID() );
CDnWorld::GetInstance(GetRoom()).RefreshDungeonDifficult( pLocalTask->GetMapTableID() );
pLocalTask->RequestGateInfo();
}
// 던전 입장 상태였다면 캔슬해준다.
if( m_bWaitGate ) {
m_bWaitGate = false;
for( DWORD i=0; i<GetUserCount(); i++ ) {
GetUserData(i)->SendCancelStage( ERROR_PARTY_STARTSTAGE_FAIL );
}
}
// 던전 클리어 상태였다면 각 상태에 따라 처리해준다.
pTask->RefreshDungeonClearState();
}
#define MAX_DUPLICATE_DICE_COUNT 5
#define MAX_SERVER_DICE_WAIT_MSEC 60
void CDnPartyTask::AddRequestGetReversionItemUserInfo(ReversionItemGetUnit& unit, bool bSendUserJoin)
{
unit.userInfo.clear();
if (!unit.hDropItem)
{
return;
}
UINT i = 0;
for (; i < GetUserCount() ; ++i)
{
CDNUserSession* pGameSession = GetUserData(i);
if (GetRoom() && pGameSession )
{
if (pGameSession->bIsGMTrace())
continue;
if( !pGameSession->GetActorHandle() )
continue;
CDnPlayerActor *pPlayer = static_cast<CDnPlayerActor *>(pGameSession->GetActorHandle().GetPointer());
if (pPlayer->IsDie())
continue;
ReversionItemGetUserInfo getUserinfo;
getUserinfo.sessionID = pGameSession->GetSessionID();
unit.userInfo.push_back(getUserinfo);
if (bSendUserJoin)
pGameSession->SendRequestJoinGetReversionItem(unit.itemInfo, unit.hDropItem->GetUniqueID());
}
}
}
void CDnPartyTask::AddRequestGetReversionItem(const TItem& itemInfo, DnDropItemHandle hDropItem)
{
// todo : set?
if (IsEnableAddRequestGetReversionItem(hDropItem) == false)
return;
ReversionItemGetUnit unit;
unit.itemInfo = itemInfo;
unit.hDropItem = hDropItem;
AddRequestGetReversionItemUserInfo(unit, m_RequestGetReversionItemList.empty());
m_RequestGetReversionItemList.push_back(unit);
}
void CDnPartyTask::SendRequestJointGetReversionItem(const TItem& orgItemInfo, const DWORD& dropUniqueID)
{
UINT i = 0;
TItem itemInfo = orgItemInfo;
for (; i < GetUserCount() ; ++i)
{
CDNUserSession* pGameSession = GetUserData(i);
if (GetRoom() && pGameSession )
{
if (pGameSession->bIsGMTrace())
continue;
if( !pGameSession->GetActorHandle() )
continue;
CDnPlayerActor *pPlayer = static_cast<CDnPlayerActor *>(pGameSession->GetActorHandle().GetPointer());
if (pPlayer->IsDie())
continue;
pGameSession->SendRequestJoinGetReversionItem(itemInfo, dropUniqueID);
}
}
}
bool CDnPartyTask::IsEnableAddRequestGetReversionItem(DnDropItemHandle hDropItem)
{
if (!hDropItem)
return false;
std::deque<ReversionItemGetUnit>::iterator iter = m_RequestGetReversionItemList.begin();
for (; iter != m_RequestGetReversionItemList.end(); ++iter)
{
ReversionItemGetUnit& info = *iter;
if (!info.hDropItem)
return false;
if (info.hDropItem->GetUniqueID() == hDropItem->GetUniqueID())
return false;
}
return true;
}
bool CDnPartyTask::IsSameDiceNumber(const std::vector<ReversionItemGetUserInfo>& userList, int diceNumber) const
{
std::vector<ReversionItemGetUserInfo>::const_iterator iter = userList.begin();
for (; iter != userList.end(); ++iter)
{
const ReversionItemGetUserInfo& curUserInfo = *iter;
if (curUserInfo.diceValue == diceNumber)
return true;
}
return false;
}
int CDnPartyTask::Dice(const std::vector<ReversionItemGetUserInfo>& userList)
{
int i = 0;
int diceValue = 0;
for (; i < MAX_DUPLICATE_DICE_COUNT; ++i)
{
diceValue = m_Random.rand(0, MAXPARTYDICEGAMENUMBER);
if (IsSameDiceNumber(userList, diceValue) == false)
break;
}
if (i >= MAX_DUPLICATE_DICE_COUNT)
{
_DANGER_POINT();
return 0; // You are REALLY Unlucky guy!
}
return diceValue;
}
int CDnPartyTask::OnRecvPartyJoinGetReversionItem(CDNUserSession *pSession, char *pPacket)
{
CSJoinGetReversionItem* pJoinGet = (CSJoinGetReversionItem*)pPacket;
if (m_RequestGetReversionItemList.empty())
{
_DANGER_POINT();
return ERROR_ITEM_FAIL;
}
if (pSession && pJoinGet)
{
int diceValue = 0;
ReversionItemGetUnit& current = m_RequestGetReversionItemList.front();
std::vector<ReversionItemGetUserInfo>& curUserList = current.userInfo;
std::vector<ReversionItemGetUserInfo>::iterator iter = curUserList.begin();
for (; iter != curUserList.end(); ++iter)
{
ReversionItemGetUserInfo& info = *iter;
if (info.sessionID == pSession->GetSessionID())
{
#ifdef PRE_FIX_RECURSIVE_DICE
if (info.bJoinDecided)
return ERROR_NONE;
#endif
diceValue = info.diceValue = (pJoinGet->bJoin) ? Dice(curUserList) : -1;
info.bJoinDecided = true;
break;
}
}
UINT i = 0;
for (; i < GetUserCount() ; ++i)
{
CDNUserSession* pGameSession = GetUserData(i);
if (GetRoom() && pGameSession)
{
int weight = 0;
if (GetRoom()->bIsPartyJobDice() )
{
if (pSession)
{
if (g_pDataManager->IsItemNeedJobHistory(current.itemInfo.nItemID, pSession->GetStatusData()->cJobArray, true))
weight = MAXPARTYDICEGAMENUMBER + 1;
}
}
pGameSession->SendRollDiceForGetReversionItem(pSession->GetSessionID(), pJoinGet->bJoin, diceValue + weight);
}
}
}
return ERROR_NONE;
}
void CDnPartyTask::ClearReversionItemList()
{
std::deque<ReversionItemGetUnit>::iterator iter = m_RequestGetReversionItemList.begin();
for (; iter != m_RequestGetReversionItemList.end(); ++iter)
{
ReversionItemGetUnit& unit = *iter;
SAFE_RELEASE_SPTR(unit.hDropItem);
}
m_RequestGetReversionItemList.clear();
m_bHoldSharingReversionItem = false;
}
void CDnPartyTask::ProcessGetReversionItemList(LOCAL_TIME LocalTime, float fDelta)
{
if (m_RequestGetReversionItemList.empty() == false && m_bHoldSharingReversionItem == false)
{
DWORD decideUserCount = 0;
ReversionItemGetUserInfo winnerInfo;
ReversionItemGetUnit& current = m_RequestGetReversionItemList.front();
std::vector<ReversionItemGetUserInfo>& curUserList = current.userInfo;
std::vector<ReversionItemGetUserInfo>::iterator iter = curUserList.begin();
for (; iter != curUserList.end();)
{
ReversionItemGetUserInfo& userInfo = *iter;
int partyIdx = 0;
if (GetRoom()->GetUserSession(userInfo.sessionID) == NULL ||
GetRoom()->GetPartyDatabySessionID(userInfo.sessionID, partyIdx) == NULL)
{
iter = curUserList.erase(iter);
continue;
}
if (userInfo.bJoinDecided != false)
{
if (userInfo.diceValue >= 0)
{
int jobWeight = 0;
if (GetRoom() && GetRoom()->bIsPartyJobDice() )
{
CDNUserSession* pSession = GetRoom()->GetUserSession(userInfo.sessionID);
if (pSession)
{
if (g_pDataManager->IsItemNeedJobHistory(current.itemInfo.nItemID, pSession->GetStatusData()->cJobArray, true))
jobWeight = MAXPARTYDICEGAMENUMBER + 1;
}
}
int resultValue = userInfo.diceValue + jobWeight;
if (resultValue > winnerInfo.diceValue)
{
winnerInfo = userInfo;
winnerInfo.diceValue = resultValue;
}
}
++decideUserCount;
}
++iter;
}
/*
if (decideUserCount > (int)curUserList.size())
{
_DANGER_POINT();
return;
}
*/
if (decideUserCount >= (int)curUserList.size() || current.time > MAX_SERVER_DICE_WAIT_MSEC)
{
if (winnerInfo.IsEmpty() == false)
{
CDNUserSession* pWinnerSession = GetRoom()->GetUserSession(winnerInfo.sessionID);
if (pWinnerSession)
{
int cSlotIndex = -1;
// 실제로 아이템 먹은놈에게만 SC_ITEM 관련 메세지가 가고
// [누가] [어떤 아아템]을 먹었습니다. 라는 메세지를 따로 보내기도 뭐하니
// DropItem 에게 보낼때 정보를 가치 보내주도록 한다.
char cLootRule = ITEMLOOTRULE_NONE;
DnActorHandle hActor = pWinnerSession->GetActorHandle();
DWORD dwOnwerID = hActor->GetUniqueID();
if (current.hDropItem)
{
current.hDropItem->SetOwnerUniqueID(dwOnwerID);
current.hDropItem->LockReversionItem(false);
CDnItemTask::GetInstance(GetRoom()).PickUpItem( hActor, current.hDropItem, ITEMLOOTRULE_NONE );
}
UINT i = 0;
for (; i < GetUserCount() ; ++i)
{
CDNUserSession* pGameSession = GetUserData(i);
if (GetRoom() && pGameSession)
{
DWORD sessionId = UINT_MAX;
if (current.hDropItem)
sessionId = current.hDropItem->GetUniqueID();
pGameSession->SendResultGetReversionItem(pWinnerSession->GetSessionID(), current.itemInfo, sessionId);
}
}
m_RequestGetReversionItemList.pop_front();
if (m_RequestGetReversionItemList.empty() == false)
{
ReversionItemGetUnit& unit = m_RequestGetReversionItemList.front();
if (!unit.hDropItem)
{
g_Log.Log(LogType::_DANGERPOINT, pWinnerSession, L"ProcessGetReversionItemList nItemID:%d m_RequestGetReversionItemList.size(%d) UserCount(%d) == userInfoCount(%d) RState[%d] UState[%d] \n",
unit.itemInfo.nItemID, m_RequestGetReversionItemList.size(), GetUserCount(), unit.userInfo.size(), GetRoom()->GetRoomState(), pWinnerSession->GetState());
}
else
{
SendRequestJointGetReversionItem(unit.itemInfo, unit.hDropItem->GetUniqueID());
}
}
}
else
{
_DANGER_POINT();
}
}
else
{
UINT i = 0;
for (; i < GetUserCount() ; ++i)
{
CDNUserSession* pGameSession = GetUserData(i);
if (GetRoom() && pGameSession)
pGameSession->SendResultGetReversionItem(0, current.itemInfo, UINT_MAX);
}
if (current.hDropItem)
current.hDropItem->LockReversionItem(false);
m_RequestGetReversionItemList.pop_front();
if (m_RequestGetReversionItemList.empty() == false)
{
ReversionItemGetUnit& unit = m_RequestGetReversionItemList.front();
if (!unit.hDropItem)
{
g_Log.Log(LogType::_DANGERPOINT, L"ProcessGetReversionItemList(NoWINNER_Info) nItemID:%d m_RequestGetReversionItemList.size(%d) UserCount(%d) == userInfoCount(%d) RState[%d]\n",
unit.itemInfo.nItemID, m_RequestGetReversionItemList.size(), GetUserCount(), unit.userInfo.size(), GetRoom()->GetRoomState());
}
else
{
SendRequestJointGetReversionItem(unit.itemInfo, unit.hDropItem->GetUniqueID());
}
}
}
OutputDebug("---------- DICE END ----------\n");
}
current.time += fDelta;
}
}
bool CDnPartyTask::IsPartySharingReversionItem() const
{
return (m_RequestGetReversionItemList.empty() == false);
}
void CDnPartyTask::SendRefreshGate(char * pGateNo, int nRet)
{
//게이트 정보를 업데이트 시켜준다.
int nUserCount = GetRoom()->GetPartyIndex() > 0 ? GetRoom()->GetPartyMemberMax() : GetUserCount();
for(int i = 0; i < (int)GetUserCount(); i++)
{
GetUserData(i)->SendRefreshGateInfo(pGateNo, nUserCount, nRet);
}
}
void CDnPartyTask::HoldSharingReversionItem()
{
if (m_RequestGetReversionItemList.empty() == false)
{
ReversionItemGetUnit& current = m_RequestGetReversionItemList.front();
current.time = 0;
m_bHoldSharingReversionItem = true;
}
}
void CDnPartyTask::PickOutInvalidReversionItemUnit()
{
std::deque<ReversionItemGetUnit>::iterator riguIter = m_RequestGetReversionItemList.begin();
for (; riguIter != m_RequestGetReversionItemList.end();)
{
ReversionItemGetUnit& rigu = (*riguIter);
if (!rigu.hDropItem)
riguIter = m_RequestGetReversionItemList.erase(riguIter);
else
++riguIter;
}
}
void CDnPartyTask::ReleaseSharingReversionItem()
{
if (m_RequestGetReversionItemList.empty() == false && m_bHoldSharingReversionItem)
{
if (GetRoom() == NULL)
return;
PickOutInvalidReversionItemUnit();
if (m_RequestGetReversionItemList.empty() == false)
{
ReversionItemGetUnit& current = m_RequestGetReversionItemList.front();
std::vector<ReversionItemGetUserInfo>::iterator iter = current.userInfo.begin();
for (; iter != current.userInfo.end();)
{
ReversionItemGetUserInfo& curUserInfo = *iter;
CDNUserSession* pGameSession = GetRoom()->GetUserSession(curUserInfo.sessionID);
if (pGameSession)
{
if (curUserInfo.bJoinDecided == false)
pGameSession->SendRequestJoinGetReversionItem(current.itemInfo, current.hDropItem->GetUniqueID());
}
else
{
iter = current.userInfo.erase(iter);
continue;
}
++iter;
}
}
m_bHoldSharingReversionItem = false;
}
}
int CDnPartyTask::OnRecvPartyMemberAbsent(CDNUserSession * pSession, CSMemberAbsent * pPacket, int nLen)
{
pSession->SetAbsent(pPacket->cAbsentFlag == 0 ? true : false);
UINT i = 0;
for (; i < GetUserCount() ; ++i)
{
CDNUserSession* pGameSession = GetUserData(i);
if (GetRoom() && pGameSession)
pGameSession->SendMemberAbsent(pSession->GetSessionID(), pPacket->cAbsentFlag);
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartyInviteMember(CDNUserSession * pSession, CSInvitePartyMember * pPacket, int nLen)
{
if (sizeof(CSInvitePartyMember) - sizeof(pPacket->wszBuf) + (pPacket->cInviteMemberSize * sizeof(WCHAR)) != nLen)
return ERROR_INVALIDPACKET;
if (pPacket->cInviteMemberSize <= 0 || pPacket->cInviteMemberSize >= NAMELENMAX)
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_NONE;
}
if (GetRoom()->IsInviting())
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL_ALREADYINVITED);
return ERROR_NONE;
}
if (GetEnteredGate() != -1)
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_NONE;
}
WCHAR wszName[NAMELENMAX];
memset(wszName, 0, sizeof(wszName));
_wcscpy(wszName, NAMELENMAX, pPacket->wszBuf, pPacket->cInviteMemberSize);
if (!__wcsicmp_l(wszName, pSession->GetCharacterName()))
{
_DANGER_POINT();
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
if (GetRoom()->GetGameType() != REQINFO_TYPE_PARTY)
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
if (CDnWorld::GetInstance(GetRoom()).GetMapType()!= GlobalEnum::eMapTypeEnum::MAP_WORLDMAP)
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
if (pSession->GetIsolate()->IsIsolateItem(wszName))
{
pSession->SendIsolateResult(ERROR_ISOLATE_REQUESTFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
if( IsPartyLeader(pSession) == false )
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
#if defined( PRE_WORLDCOMBINE_PARTY )
if( GetRoom()->bIsWorldCombineParty() )
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
#endif // #if defined( PRE_WORLDCOMBINE_PARTY )
#if defined( PRE_PARTY_DB )
if (GetRoom()->GetUserCount()+GetRoom()->GetBreakIntoUserCount() >= PARTYCOUNTMAX || (int)GetRoom()->GetUserCount()+GetRoom()->GetBreakIntoUserCount() >= GetRoom()->GetPartyMemberMax())
#else
if (GetRoom()->GetUserCount() >= PARTYCOUNTMAX || (int)GetRoom()->GetUserCount() >= GetRoom()->GetPartyMemberMax())
#endif // #if defined( PRE_PARTY_DB )
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
CDnGameTask *pTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
if (pTask == NULL)
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_GENERIC_UNKNOWNERROR;
}
int nPermitCnt = g_pDataManager->GetMapPermitPartyCount(pTask->GetMapTableID());
if (nPermitCnt > 0 && nPermitCnt <= (int)GetRoom()->GetUserCountWithoutGM())
{
pSession->SendPartyInviteFail(ERROR_PARTY_INVITEFAIL);
return ERROR_NONE;
}
int nClassPassArr[PERMITMAPPASSCLASSMAX];
int nPermitLevel = 0;
memset(nClassPassArr, 0, sizeof(nClassPassArr));
pTask->GetPermitPassClassIDs(nClassPassArr, PERMITMAPPASSCLASSMAX);
nPermitLevel = pTask->GetPermitMapLevel();
//기본적으로 검사할 것을 다 한후에~ 마스터에 날려준다.
bool bret = g_pMasterConnectionManager->SendInvitePartyMember(GetRoom(), pSession->GetWorldSetID(), pTask->GetMapTableID(), pSession->GetGameRoom()->GetPartyChannelID(), pSession->GetAccountDBID(), pSession->GetCharacterName(), wszName, nClassPassArr, nPermitLevel);
if (bret)
{
if (GetRoom()->SetInviteCharacterName(wszName) == false)
_DANGER_POINT(); //이럼안데잉~
}
return ERROR_NONE;
}
int CDnPartyTask::OnRecvPartySwapMemberIndex(CDNUserSession * pSession, CSPartySwapMemberIndex * pPacket, int nLen)
{
if (GetRoom()->GetPartyIndex() == 0)
{ //거짓말하는 어린이는 지옥가요.
pSession->SendPartySwapMemberIndex(NULL, ERROR_PARTY_SWAPINDEX_FAIL);
return ERROR_NONE;
}
if (GetRoom()->IsPartyLeader(pSession->GetSessionID()) == false)
{
pSession->SendPartySwapMemberIndex(NULL, ERROR_PARTY_SWAPINDEX_FAIL);
return ERROR_NONE;
}
if (GetRoom()->PartySwapMemberIndex(pPacket) == false)
pSession->SendPartySwapMemberIndex(NULL, ERROR_PARTY_SWAPINDEX_FAIL);
return ERROR_NONE;
}
#if defined( PRE_PARTY_DB )
int CDnPartyTask::OnRecvPartyModify(CDNUserSession * pSession, CSPartyInfoModify * pPacket, int nLen)
{
if (GetRoom()->GetPartyIndex() <= 0)
return ERROR_NONE;
if (GetRoom()->IsPartyLeader(pSession->GetSessionID()) == false)
return ERROR_NONE;
// 월드존인지 검사
const TMapInfo* pMapInfo = g_pDataManager->GetMapInfo( pSession->GetMapIndex() );
if( pMapInfo == NULL )
return ERROR_NONE;
if( pMapInfo->MapType != GlobalEnum::MAP_WORLDMAP )
return ERROR_NONE;
// 게임서버에서는 BitFlag 옵션중 Party::BitFlag::WorldmapAllow Bit 만 변경 가능하다.
int iBitFlag = GetRoom()->GetPartyStructData().iBitFlag;
if( pPacket->iBitFlag&Party::BitFlag::WorldmapAllow && !(GetRoom()->GetPartyStructData().iBitFlag&Party::BitFlag::WorldmapAllow) )
{
iBitFlag |= Party::BitFlag::WorldmapAllow;
}
else if( !(pPacket->iBitFlag&Party::BitFlag::WorldmapAllow) && GetRoom()->GetPartyStructData().iBitFlag&Party::BitFlag::WorldmapAllow )
{
iBitFlag &= ~Party::BitFlag::WorldmapAllow;
}
else
{
return ERROR_NONE;
}
pSession->GetDBConnection()->QueryModParty( pSession, GetRoom()->GetPartyStructData(), iBitFlag );
return ERROR_NONE;
}
#if defined(PRE_MOD_REQ_JOIN_PARTY_ANSWER_MSG_APP)
int CDnPartyTask::OnRecvPartyAskJoinDecision(CDNUserSession * pSession, CSPartyAskJoinDecision * pPacket, int nLen)
{
if (GetRoom()->GetPartyIndex() <= 0)
{
pSession->SendAskJoinResult(ERROR_PARTY_ASKJOIN_RESULT_AGREE_FAIL);
return ERROR_NONE;
}
if (GetRoom()->IsPartyLeader(pSession->GetSessionID()) == false)
{
pSession->SendAskJoinResult(ERROR_PARTY_ASKJOIN_RESULT_AGREE_FAIL);
return ERROR_NONE;
}
// 월드존인지 검사
const TMapInfo* pMapInfo = g_pDataManager->GetMapInfo( pSession->GetMapIndex() );
if( pMapInfo == NULL || pMapInfo->MapType != GlobalEnum::MAP_WORLDMAP )
{
pSession->SendAskJoinResult(ERROR_PARTY_ASKJOIN_RESULT_AGREE_FAIL);
return ERROR_NONE;
}
// 상태부터 풀어준다.
pSession->IsWindowStateNoneSet(WINDOW_ISACCEPT);
if(pPacket->cRet == 0)
g_pMasterConnectionManager->SendResPartyAskJoin( pSession->GetWorldSetID(), ERROR_PARTY_ASKJOIN_RESULT_PARTYLEADER_DENIED, 0, pPacket->wszPartyAsker );
else
g_pMasterConnectionManager->SendAskJoinAgreeInfo( pSession->GetWorldSetID(), pPacket->wszPartyAsker, GetRoom()->GetPartyStructData().PartyID, GetRoom()->GetPartyStructData().iPassword );
return ERROR_NONE;
}
#endif //#if defined(PRE_MOD_REQ_JOIN_PARTY_ANSWER_MSG_APP)
void CDnPartyTask::AddPartyDB( CDNUserSession* pBreakIntoSession )
{
if( pBreakIntoSession || GetRoom()->GetGameType() != REQINFO_TYPE_PARTY )
return;
#if defined( PRE_WORLDCOMBINE_PARTY )
if( GetRoom()->bIsWorldCombineParty() == true )
{
Party::Data PartyData = GetRoom()->GetPartyStructData();
GetRoom()->GetDBConnection()->QueryAddWorldParty( g_Config.nManagedID, Party::LocationType::Worldmap, PartyData.iLocationID, &PartyData );
return;
}
#endif
CDNUserSession * pSession = NULL;
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( GetUserData(i) );
if(pStruct->bLeader)
{
pSession = GetUserData(i);
break;
}
}
}
if(pSession)
{
Party::AddPartyAndMemberGame PartyData;
memset(&PartyData, 0, sizeof(PartyData));
PartyData.PartyData = GetRoom()->GetPartyStructData();
GetRoom()->CopyPartyKickedMemberList( PartyData.nKickedMemberList );
int nCount = 0;
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( GetUserData(i) );
if( !pStruct->bLeader && pStruct->pSession )
{
PartyData.biCharacterDBID[nCount] = pStruct->pSession->GetCharacterDBID();
PartyData.nSessionID[nCount] = pStruct->pSession->GetSessionID();
#if defined( PRE_ADD_NEWCOMEBACK )
if( pStruct->pSession->GetComebackAppellation() > 0 )
PartyData.bCheckComebackAppellation[nCount] = true;
#endif
nCount++;
}
}
}
int iMapIndex = 0;
if( GetRoom()->m_bDirectConnect )
{
iMapIndex = GetRoom()->m_iMapIdx;
}
else
{
char szLabel[MAX_PATH];
DNTableFileFormat *pSox = GetDNTable( CDnTableDB::TMAP );
sprintf_s( szLabel, "_Gate%d_MapIndex_txt", GetRoom()->m_iGateIdx );
char* pszGateMapIndexs = pSox->GetFieldFromLablePtr( GetRoom()->m_iMapIdx, szLabel )->GetString();
std::vector<string> vGateMapIndexs;
TokenizeA(pszGateMapIndexs, vGateMapIndexs, ";");
if (GetRoom()->m_iGateSelect < vGateMapIndexs.size())
iMapIndex = atoi(vGateMapIndexs[GetRoom()->m_iGateSelect].c_str());
else
return;
}
GetRoom()->GetDBConnection()->QueryAddPartyAndMemberGame( pSession, g_Config.nManagedID, Party::LocationType::Worldmap, iMapIndex, &PartyData, GetRoom()->GetRoomID() );
}
}
void CDnPartyTask::AddPartyMemberDB( CDNUserSession* pSession )
{
CDNDBConnection* pDBCon = GetRoom()->GetDBConnection();
if( pDBCon && GetRoom()->GetPartyIndex() > 0 )
{
pDBCon->QueryJoinParty( pSession, GetRoom()->GetWorldSetID(), GetRoom()->GetPartyIndex(), GetRoom()->GetPartyMemberMax() );
}
}
void CDnPartyTask::DelPartyDB()
{
CDNDBConnection* pDBCon = GetRoom()->GetDBConnection();
if( pDBCon && GetRoom()->GetPartyIndex() > 0 )
{
pDBCon->QueryDelParty( GetRoom()->GetWorldSetID(), GetRoom()->GetPartyIndex() );
}
}
void CDnPartyTask::DelPartyMemberDB( CDNUserSession *pSession )
{
if( !pSession || GetRoom()->GetPartyIndex() == 0 )
return;
if (pSession->GetGameRoom()->GetGameType() != REQINFO_TYPE_SINGLE)
{
if( pSession->GetDBConnection() )
pSession->GetDBConnection()->QueryOutParty( GetRoom()->GetWorldSetID(), pSession->GetAccountDBID(), pSession->GetCharacterDBID(), pSession->GetSessionID(), GetRoom()->GetPartyIndex(), Party::QueryOutPartyType::Disconnect );
}
}
#endif // #if defined( PRE_PARTY_DB )
#if defined( PRE_ADD_NAMEDITEM_SYSTEM )
void CDnPartyTask::ApplyPartyEffectSkillItemData( CSUseItem *pPacket, TItemData *pItemData, UINT nUseSessionID, EffectSkillNameSpace::ShowEffectType::eType eType, bool bSendDB, bool bUseItem )
{
CDNUserSession * pSession = NULL;
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
pSession = GetUserData(i);
pSession->GetItem()->ApplyPartyEffectSkillItemData(pPacket, pItemData, nUseSessionID, eType, bSendDB, bUseItem);
}
}
}
#endif
#if defined( PRE_ADD_NEWCOMEBACK )
bool CDnPartyTask::CheckPartyMemberAppellation( int nAppellationID )
{
CDNUserSession * pSession = NULL;
if( nAppellationID > 0 )
{
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
pSession = GetUserData(i);
if(pSession)
{
if( pSession->GetComebackAppellation() == nAppellationID && !pSession->GetOutedMember() )
{
return true;
}
}
}
}
}
else
{
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
pSession = GetUserData(i);
if(pSession)
{
if( pSession->GetComebackAppellation() > 0 && !pSession->GetOutedMember() )
{
return true;
}
}
}
}
}
return false;
}
void CDnPartyTask::DelPartyMemberAppellation( int nAppellationID )
{
if( !CheckPartyMemberAppellation( nAppellationID ) )
{
TAppellationData *pAData = g_pDataManager->GetAppellationData( nAppellationID );
if( pAData )
{
TItemData* pBuffItemData = g_pDataManager->GetItemData( pAData->nSkillItemID );
if(pBuffItemData)
{
CDNUserSession * pSession = NULL;
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
pSession = GetUserData(i);
if(pSession && pSession->GetPlayerActor() )
{
TEffectSkillData* EffectSkill = pSession->GetItem()->GetEffectSkillItem( EffectSkillNameSpace::SearchType::SkillID, pBuffItemData->nSkillID );
if( EffectSkill )
{
CDNUserSession::RemoveEffectSkill(pSession->GetPlayerActor(), EffectSkill);
pSession->GetItem()->DelEffectSkillItem( pBuffItemData->nSkillID );
}
}
}
}
if( !CheckPartyMemberAppellation(0) && GetRoom() )
GetRoom()->SetComebackParty(false);
}
}
}
}
void CDnPartyTask::ApplyJoinMemberAppellation( CDNUserSession * pSession )
{
if( !pSession )
return;
CDNUserSession *pUserObj = NULL;
float fValue = 0.f;
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
pUserObj = GetUserData(i);
if( pUserObj->GetComebackAppellation() > 0 )
{
TAppellationData *pAData = g_pDataManager->GetAppellationData( pUserObj->GetComebackAppellation() );
if( pAData )
{
if( pAData->nSkillItemID > 0 )
{
CSUseItem pPacket;
memset(&pPacket, 0, sizeof(pPacket));
pPacket.biInvenSerial = pSession->GetItem()->MakeItemSerial();
TItemData* pBuffItemData = g_pDataManager->GetItemData( pAData->nSkillItemID );
if( pBuffItemData && g_pDataManager->IsUseItemAllowMapTypeCheck( pBuffItemData->nItemID, GetRoom()->m_iMapIdx ) )
pSession->GetItem()->ApplyPartyEffectSkillItemData(&pPacket, pBuffItemData, pSession->GetSessionID(), EffectSkillNameSpace::ShowEffectType::NONEEFFECT, false, true);
}
}
}
}
}
}
float CDnPartyTask::GetPlayerDropUpBlowValue()
{
CDNUserSession * pSession = NULL;
float fValue = 0.f;
for(int i=0;i<(int)GetUserCount();i++)
{
if( GetUserData(i) != NULL )
{
pSession = GetUserData(i);
if( pSession->GetPlayerActor() )
{
if ( pSession->GetPlayerActor()->IsAppliedThisStateBlow(STATE_BLOW::BLOW_270))
{
DNVector(DnBlowHandle) vlBlows;
pSession->GetPlayerActor()->GatherAppliedStateBlowByBlowIndex(STATE_BLOW::BLOW_270, vlBlows);
{
int nCount = (int)vlBlows.size();
for (int j = 0; j < nCount; ++j)
{
DnBlowHandle hBlow = vlBlows[j];
if (hBlow && hBlow->IsEnd() == false)
{
fValue += hBlow->GetFloatValue();
}
}
}
// 드랍률 증가는 한명만 있어도 바로 리턴시킴
return fValue;
}
}
}
}
return fValue;
}
#endif