Files
2022-10-26 12:25:11 +08:00

1395 lines
46 KiB
C++

#include "StdAfx.h"
#include "CollectionManager.h"
#include "CollectionParser.h"
#include "QuestManager_Concrete.h"
#include <AreaConquestCommonHeader.h>
#include "LotteryInfoParser.h"
#include "ItemManager.h"
#include <PublicMath.h>
#include "ServerOptionParserEx.h"
#include "MovementChecker.h"
#include "CollectedList.h"
#include <PacketStruct_DG.h>
#include "CollectionStateInfo.h"
#include "Collection.h"
#include "ObjectFactory.h"
#include "GameDominationField.h"
#include "GameGuildManager.h"
#include "GameGuild.h"
#include <SkillAttrCalculator.h>
#include "StatusManager.h"
#include "GameField.h"
#include "TriggerManager.h"
#include "TriggerManagerEx.h"
#include "GameMissionRoom.h"
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
#include <ChaosZoneSystem/PacketStruct_ChaosZoneSystem.h>
#include <GameInstanceDungeon.h>
#include <World/ChaosZoneSystem/ChaosZone.h>
#include <world/ChaosZoneSystem/BattleGround.h>
#ifdef _NA_008334_20150608_SONNENSCHEIN
#include <World/ChaosZoneSystem/SonnenSchein.h>
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
#include <World/ChaosZoneSystem/OneDaysGuildMission.h>
#endif //(_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
//==================================================================================================
// CHANGES: f110527.3L, memory usage optimization
struct CollectionManager::CollectionStateInfoManager
{
static CollectionStateInfo* Create(Collection* collection,
CHARGUID collector, WzVector& collector_pos);
static void Release(CollectionStateInfo* state_info);
};
CollectionStateInfo* CollectionManager::CollectionStateInfoManager::Create(
Collection* collection, CHARGUID collector, WzVector& collector_pos)
{
CollectionStateInfo* state_info = TAllocNew(CollectionStateInfo);
if (state_info->Init(collection, collector, collector_pos) == false)
{
Release(state_info);
return NULL;
};
collection->SetStateInfo(state_info);
return state_info;
}
void CollectionManager::CollectionStateInfoManager::Release(CollectionStateInfo* state_info)
{
Collection* collection = state_info->GetCollection();
if (collection) {
collection->SetStateInfo(NULL);
};
state_info->Release();
TAllocDelete(CollectionStateInfo, state_info);
}
//==================================================================================================
//
CollectionManager::CollectionManager(GameField* pField)
:m_pField(pField)
{
m_Hash.Initialize(MAX_FIELD_COLLECTION_NUM);
}
void CollectionManager::Release()
{
ACTIVE_COLLECTION_HASH_IT it = m_Hash.begin(), end = m_Hash.end();
while( it != end )
{
CollectionStateInfoManager::Release(*it);
++it;
}
m_Hash.clear();
}
//{__NA001283_20090221_COLLECTION_SYNC
// 보상
// 클라의 채집은 시작Ani -> 채집Ani -> 완료Ani 로 나뉜다.
// 서버와 클라는 시작시간은 동기화 하나 완료 시간은 동기화 하지않는다.
// 타이밍에 따라 서버가 채집 완료 하고 클라는 채집 취소 하는 현상이 발생한다.
// 정확한 타이밍을 위해 클라가 완료Ani에 서버쪽으로 동기화 패킷을 보내고,
// 서버는 이 타이밍에 보상과, 완료 처리를 한다.
// 서버쪽 완료 상황은 플레이어가 저장, 동기화 패킷에 의해 보상한다.
// pCollectionInfo <- 저장해두어야할 정보
// 클라에서는 성공이든 취소든 둘중 하나의 정보를 전달함을 보장해야 한다.
// 하지만 이경우에도 동기화의 문제는 발생한다.
// 정보의 전달이 보장되어도 타이밍이 늦는다면, 이후 채집물의 정보를 클라에 줄것인가의 결정
// 에 영향을 미친다.
// 채집물의 기본 활성 딜레이 타임으로 문제 해결은 되나,
// 렉이나 의도적인 경우 아직 보상전이므로 느낌표가 다시 생겨난다.
RC::eCOLLECT_RESULT CollectionManager::Success(Player* player)
{
if (player == NULL)
{
return RC::RC_COLLECT_FAIL;
}
CollectedList* collect_list = player->GetCollectedList();
DWORD object_key_collected = 0;
CollectionInfo* collect_info = collect_list->GetSuccessCollectionInfo(object_key_collected);
if (collect_info == NULL)
{
return RC::RC_COLLECT_NOTEXIST;
}
WzID collect_id = collect_info->m_CollectionID;
//gamelulu_dev_note : 각인 오브젝트인 경우에만 아래와 같이 성공 여부를
//먼저 검사한다. 각인 조건이 맞지 않으면 각인은 실패로 끝나며 보상또한 없다.
const PairIsStampReturnValue is_stamp = _IsStamp(collect_id);
if (is_stamp.first != false)
{
GameZone* pGameZone = player->GetGameZonePtr();
if (eZONETYPE_DOMINATION_FIELD == pGameZone->GetZoneType())
{
GameDominationField* pZone = (GameDominationField*)pGameZone;
#ifdef _NA_006826_20130722_DOMINATION_RENEWAL
if (pZone->IsSuccessStamp() == false) {
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
pZone->SuccessStamp(player);
#else
//_NA_20110406_CHANGE_RULE_FOR_DOMINATION_JOIN
if (pZone->IsSuccessStamp() == false)
{
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
pZone->SuccessStamp();
#endif // _NA_006826_20130722_DOMINATION_RENEWAL
GAMELOG->LogDomination(ACT_DOMINATION_STAMP_COMPLETE, player, NULL);
}
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(collect_id))
{
// 현재 플레이어가 배틀그라운드존에 위치하는지 체크
if (player->IsThereBattleGroundZone() == false)
{
SUNLOG(eCRITICAL_LOG, TEXT("[%s|%d] player is not in battle ground"),
__FUNCTION__, __LINE__);
return RC::RC_COLLECT_FAIL;
}
BattleGround* const battle_ground = static_cast<BattleGround*>(player->GetCurrentChaosZone());
if (battle_ground) {
battle_ground->SuccessSealing(player, collect_id);
}
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
else if (_IsSonnenScheinStamp(collect_id) == TRUE)
{
//SonnenSchein에서의 각인 성공 처리
if (player->GetChaosZoneType() == eCHAOSZONE_TYPE_SONNENSCHEIN)
{
ChaosZone* zone = player->GetCurrentChaosZone();
if (zone == NULL) {
return RC::RC_COLLECT_FAIL;
}
SonnenSchein* sonnenschein = static_cast<SonnenSchein*>(zone);
sonnenschein->SuccessStamp(player);
}
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if (_IsOneDaysGuildmissionStamp(collect_id) == TRUE)
{
// 일일길드미션 각인 성공 처리
if (player->GetChaosZoneType() == eCHAOSZONE_TYPE_ONEDAYSGUILDMISSION)
{
ChaosZone* zone = player->GetCurrentChaosZone();
if (zone == NULL) {
return RC::RC_COLLECT_FAIL;
}
OneDaysGuildMission* onedaysguildmission = static_cast<OneDaysGuildMission*>(zone);
onedaysguildmission->SuccessStamp(player);
}
}
#endif //(_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
// 채집에 성공해도 아이템 보상 하지 않는 채집물도 있다.(각인)
if (collect_info->m_ItemCode != 0)
{
MSG_CG_COLLECT_OBTAIN_CMD obtain_msg;
#ifdef _NA_000000_20120416_COLLECT_OBTAIN_QUESTCODE
obtain_msg.quest_code_ = collect_info->m_Condition[CollectionInfo::QUEST];
#endif
RC::eITEM_RESULT result_code = _RewardItem(player, collect_info, obtain_msg.m_tagInventory);
if( result_code != RC::RC_ITEM_SUCCESS )
{
if( result_code == RC::RC_ITEM_HAVENOTSPACE )
{
return RC::RC_COLLECT_FAIL_HAVENOTSPACE;
}
else
{
return RC::RC_COLLECT_FAIL_REWORD_ITEM;
}
}
player->SendPacket( &obtain_msg, obtain_msg.GetSize() );
}
//AC처리
BASE_ITEMINFO* item_info = ItemInfoParser::Instance()->GetItemInfo(collect_info->m_ItemCode);
if (item_info)
{
//C_NA_0_20100520_ACSYSTEM_CHANGED
player->GetACManager()->IncConditionValue((int)item_info->m_wACCode,
item_info->m_byACReferenceID,
collect_info->m_ItemCode);
}
//ac정보의 경우 동기화를 위해 DBP에 바로 저장한다.
player->SerializeInfoToDBProxy();
#ifdef _NA_004777_20120428_ADD_COMPLETE_COLLECTION_TRIGGER
//------------------------------------------------------------------------------
// 채집 트리거 체크
// 다음 미션때 채집 포인터가 보여야 하기때문에
// 미션 트리거용 채집일경우에는 DB 에 기록하지 않는다.
DWORD condition_trigger = collect_info->m_Condition[CollectionInfo::TRIGGER];
if (condition_trigger != 0) // 미션내 채집물
{
GameField* const field = player->GetField();
if (field != NULL)
{
TRIGGER_COMPLETE_COLLECTION msg;
msg.object_key = object_key_collected;
field->GetTriggerManager()->OnMsg(&msg);
}
// 미션 내부에서는 한명이 채집을 성공하면 나머지 인원들도 채집을 성공한걸로 간주..
// 채집된 리스트에 채집물 키값을 넣어준다.
const GameField::_PLAYER_HASH& players = field->GetRefPlayerList();
FOREACH_CONTAINER(
const GameField::_PLAYER_HASH::value_type& player_pair, players, GameField::_PLAYER_HASH)
{
Player* const field_player = player_pair.second;
if (obj_util::IsValid(field_player, __FUNCTION__, __LINE__) == false)
{
continue;
}
CollectedList* const field_player_collect_list = field_player->GetCollectedList();
field_player_collect_list->Add(collect_id);
}
}
else // 필드 채집물
{
collect_list->Add(collect_id);
MSG_DG_COLLECT_ADD_SYN msg;
msg.m_CollectionID = collect_id;
player->SendToGameDBPServer( &msg, sizeof(msg) );
}
#else
collect_list->Add(collect_id);
MSG_DG_COLLECT_ADD_SYN msg;
msg.m_CollectionID = collect_id;
player->SendToGameDBPServer( &msg, sizeof(msg) );
#endif //_NA_004777_20120428_ADD_COMPLETE_COLLECTION_TRIGGER
return RC::RC_COLLECT_SUCCESS;
}
//}__NA001283_20090221_COLLECTION_SYNC
RC::eCOLLECT_RESULT CollectionManager::GmCancel( WzID CollectionID )
{
ACTIVE_COLLECTION_HASH_IT it = m_Hash.begin(), end = m_Hash.end();
while( it != end )
{
CollectionStateInfo* pState = *it;
if( CollectionID != pState->GetCollectionID() )
{
++it;
continue;
}
Player* const pPlayer = PlayerManager::Instance()->FindPlayerByCharKey( pState->GetCollector() );
if( pPlayer )
{
Cancel(pPlayer);
}
else
{
Collection* pCollection = pState->GetCollection();
if( pCollection )
{
m_pField->LeaveField( pCollection );
ObjectFactory::Instance()->FreeObject( pCollection );
}
_Respawn(pState);
}
return RC::RC_COLLECT_SUCCESS;
}
return RC::RC_COLLECT_FAIL;
}
VOID CollectionManager::_StartStamp( Player* player, WzID collection_id )
{
const CollectionInfo* conllection_info = CollectionParser::Instance()->FindCollectionInfo(collection_id);
if (conllection_info != NULL)
{
StatusManager* status_manager = player->GetStatusManager();
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
status_manager->AllocStampStatus(conllection_info->m_dwCollectingTime);
#else
//아이언 바디, 강철 상태는 각인시 사라진다.
status_manager->Remove(eCHAR_STATE_STEEL);
status_manager->Remove(eCHAR_STATE_IMMUNITY_DAMAGE);
status_manager->AllocStatus(eCHAR_STATE_STAMP, conllection_info->m_dwCollectingTime);
#endif //_NA_007667_20141001_WITCHBLADE_SKILL
}
MSG_CG_DOMINATION_BEGIN_STAMP_BRD brd_msg;
brd_msg.m_nStampID = collection_id;
#ifdef _NA_007128_20140326_MONDSCHIEN_DOMINATION
GameGuild* pRequestGuild = g_GameGuildManager.FindGuild(player->GetGuildGuid());
_tcsncpy(brd_msg.m_stamp_guild_name, pRequestGuild->GetGuildName(), MAX_GUILDNAME_LENGTH);
#else
_SendStampPacket(brd_msg, player, collection_id);
#endif
//_NA_20110406_CHANGE_RULE_FOR_DOMINATION_JOIN
//각인 시작시간을 저장한다.
GameZone* game_zone = player->GetGameZonePtr();
if (game_zone->GetZoneType() == eZONETYPE_DOMINATION_FIELD )
{
GameDominationField* zone = static_cast<GameDominationField*>(game_zone);
zone->SetStampStartTime();
#ifdef _NA_007128_20140326_MONDSCHIEN_DOMINATION
zone->SendPacketToAll(&brd_msg, sizeof(brd_msg));
#endif
}
GAMELOG->LogDomination(ACT_DOMINATION_STAMP_START, player, NULL);
}
VOID CollectionManager::_CancelStamp(Player* player, WzID collection_id)
{
MSG_CG_DOMINATION_CANCLE_STAMP_BRD brd_msg;
brd_msg.m_nStampID = collection_id;
if (player == NULL)
{
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
else
{
StatusManager* status_manager = player->GetStatusManager();
status_manager->Remove(eCHAR_STATE_STAMP);
#ifdef _NA_007128_20140326_MONDSCHIEN_DOMINATION
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
#else
_SendStampPacket(brd_msg, player, collection_id);
#endif
}
//_NA_20110406_CHANGE_RULE_FOR_DOMINATION_JOIN
//각인 시작시간을 초기화 한다.
#ifdef _NA_008256_20150428_MODIFY_CANCLE_STAMP_LOGIC
GameZone* game_zone = m_pField->GetGameZone();
#else
GameZone* game_zone = player->GetGameZonePtr();
#endif // _NA_008256_20150428_MODIFY_CANCLE_STAMP_LOGIC
if (game_zone->GetZoneType() == eZONETYPE_DOMINATION_FIELD )
{
GameDominationField* zone = static_cast<GameDominationField*>(game_zone);
zone->InitStampCheckTime();
}
}
template<typename PacketType>
VOID CollectionManager::_SendStampPacket(PacketType& BrdMsg, Player* pPlayer, WzID CollectionID)
{
GameGuild* pRequestGuild = g_GameGuildManager.FindGuild(pPlayer->GetGuildGuid());
GameField* pField = pPlayer->GetField();
if (NULL != pField &&
NULL != pRequestGuild)
{
const FIELDCODE fieldCode = pField->GetFieldCode();
pRequestGuild->SendPacketFieldMember(BrdMsg, fieldCode);
}
}
//
RC::eCOLLECT_RESULT CollectionManager::Cancel( Player* pPlayer )
{
ASSERT(pPlayer);
CollectedList* pCollected = pPlayer->GetCollectedList();
DWORD ObjKeyCollection = pCollected->GetObjKeyCollecting();
if( 0 == ObjKeyCollection )
return RC::RC_COLLECT_CHAR_NOTCOLLECTING;
CollectionStateInfo* pStateInfo = _FindStateInfo(ObjKeyCollection);
if( !pStateInfo )
return RC::RC_COLLECT_NOTCOLLECTING;
if( false == pStateInfo->CanCancel(pPlayer->GetCharGuid()) )
return RC::RC_COLLECT_FAIL_CANCEL;
const WzID collectionID = pStateInfo->GetCollectionID();
;{
MSGSUB_COLLECT_CANCEL_BRD msg_brd;
msg_brd.object_key = ObjKeyCollection;
msg_brd.collection_id = collectionID;
msg_brd.collector = pPlayer->GetObjectKey();
pPlayer->SendPacketAroundForSync(&msg_brd);
};
//각인 취소
const PairIsStampReturnValue is_stamp = _IsStamp(collectionID);
if (is_stamp.first == true)
{
_CancelStamp(pPlayer, collectionID);
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(collectionID))
{
_CancelSealing(pPlayer, collectionID);
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
else if (_IsSonnenScheinStamp(collectionID) == TRUE) {
_CancelSonnenScheinStamp(pPlayer, collectionID);
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if (_IsOneDaysGuildmissionStamp(collectionID) == TRUE) {
_CancelOneDaysGuildmissionStamp(pPlayer, collectionID);
}
#endif //(_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
pStateInfo->Cancel();
pCollected->EndCollecting();
return RC::RC_COLLECT_SUCCESS;
}
// 채집자가 없는 채집물의 채집 취소.
RC::eCOLLECT_RESULT CollectionManager::Cancel( CollectionStateInfo* pStateInfo )
{
ASSERT(pStateInfo);
const WzID collectionID = pStateInfo->GetCollectionID();
;{
MSGSUB_COLLECT_CANCEL_BRD msg_brd;
msg_brd.object_key = pStateInfo->GetObjectKey();
msg_brd.collection_id = collectionID;
msg_brd.collector = 0;
const Collection* pCollection = pStateInfo->GetCollection();
const SECTOR_IDX sector_idx = pCollection->GetSectorIndex();
m_pField->SendPacketAroundForSync(sector_idx, &msg_brd);
};
//각인 취소
const PairIsStampReturnValue is_stamp = _IsStamp(collectionID);
if (is_stamp.first == true)
{
_CancelStamp(NULL, collectionID);
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(collectionID))
{
_CancelSealing(NULL, collectionID);
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
else if (_IsSonnenScheinStamp(collectionID) == TRUE) {
_CancelSonnenScheinStamp(NULL, collectionID);
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if (_IsOneDaysGuildmissionStamp(collectionID) == TRUE) {
_CancelOneDaysGuildmissionStamp(NULL, collectionID);
}
#endif //(_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
pStateInfo->Cancel();
return RC::RC_COLLECT_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
RC::eCOLLECT_RESULT CollectionManager::Collect(DWORD ObjKeyCollection, Player* pPlayer, WzVector& wvClientCurPos)
{
CollectedList* pCollectedList = pPlayer->GetCollectedList();
if( false != pCollectedList->IsCollecting() )
{
//클라에서 연속클릭시 두번 연달아 들어올수 있으며,
//이 경우 NAK를 클라에 보냄으로 클라측에선 채집이 취소된다.
//그럼으로 서버에서도 채집취소를 BRD한다.
RC::eCOLLECT_RESULT rc= Cancel(pPlayer);
SUNLOG( eDEV_LOG, "[CollectionManager::Collect] 채집중 채집시도 케릭터[%s] 채집물[%d] cancel[%s]",
pPlayer->GetCharName(), ObjKeyCollection, RC::RC_COLLECT_SUCCESS != rc?"fail":"success" );
return RC::RC_COLLECT_ALREADY_COLLECTING;
}
Collection* pCollection = (Collection*)m_pField->FindObject( COLLECTION_OBJECT, ObjKeyCollection );
if( NULL == pCollection )
return RC::RC_COLLECT_NOTEXIST;
if( false == IsCollectable(ObjKeyCollection) )
return RC::RC_COLLECT_ALREADY_COLLECTED;
//.//
RC::eCOLLECT_RESULT rc = RC::RC_COLLECT_FAIL;
MAPOBJECT_INFO* pObjInfo = pCollection->GetMapObjectInfo();
rc = _ChkDistance(pPlayer,wvClientCurPos,pObjInfo->wvPos);
if( RC::RC_COLLECT_SUCCESS != rc )
return rc;
rc = ChkCondision( pPlayer, pObjInfo->CollectionID );
if( RC::RC_COLLECT_SUCCESS != rc )
return rc;
if (pPlayer->IsDead())
{
const PairIsStampReturnValue is_stamp = _IsStamp(pObjInfo->CollectionID);
if (false != is_stamp.first)
{
return RC::RC_COLLECT_FAIL_STAMP_DEAD_CHAR;
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(pObjInfo->CollectionID))
{
return RC::RC_COLLECT_FAIL_STAMP_DEAD_CHAR;
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
else if (_IsSonnenScheinStamp(pObjInfo->CollectionID) == TRUE) {
return RC::RC_COLLECT_FAIL_STAMP_DEAD_CHAR;
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if (_IsOneDaysGuildmissionStamp(pObjInfo->CollectionID) == TRUE) {
return RC::RC_COLLECT_FAIL_STAMP_DEAD_CHAR;
}
#endif //(_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
else
return RC::RC_COLLECT_FAIL_REWORD_DEAD_CHAR;
}
//.//
if( false == _Collect(pCollection,pPlayer) )
return RC::RC_COLLECT_FAIL;
// 보상 검사용으로 현재 채집 중인 채집물을 넣어둔다.
pCollectedList->BeginCollecting(ObjKeyCollection);
//.//
// 하위 패킷으로 클라 채집모션이 시작 (자신과 자신 주변)
;{
MSGSUB_COLLECT_ACTION_BRD msg_brd;
msg_brd.object_key = ObjKeyCollection;
msg_brd.collection_id = pObjInfo->CollectionID;
msg_brd.collector = pPlayer->GetObjectKey();
pPlayer->SendPacketAroundForSync(&msg_brd);
};
const PairIsStampReturnValue is_stamp = _IsStamp(pObjInfo->CollectionID);
if (is_stamp.first == true)
{
// 각인 시작을 동일필드 길드멤버에게 보낸다.
_StartStamp(pPlayer, pObjInfo->CollectionID);
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(pObjInfo->CollectionID))
{
_StartSealing(pPlayer, pObjInfo->CollectionID);
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
else if (_IsSonnenScheinStamp(pObjInfo->CollectionID) == TRUE) {
_StartSonnenScheinStamp(pPlayer, pObjInfo->CollectionID);
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if (_IsOneDaysGuildmissionStamp(pObjInfo->CollectionID) == TRUE) {
_StartOneDaysGuildmissionStamp(pPlayer, pObjInfo->CollectionID);
}
#endif //(_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
//채집시 해제되는 상태
pPlayer->Player_TransOff();
#ifdef _DEBUG
char ch[5] = {0,};
SUNLOG( eDEV_LOG, "[SEND MSG_CG_COLLECT_ACTION_BRD] SENDER_ [%s][%d] _ "
"ObjKeyCollection[%d] CollectionID[%s] Collector[%d]",
pPlayer->GetCharName(),pPlayer->GetCharGuid(),
ObjKeyCollection, WzIDToString(ch,pObjInfo->CollectionID), pPlayer->GetObjectKey() );
#endif
return RC::RC_COLLECT_SUCCESS;
}
bool CollectionManager::_Collect( Collection* pCollection, Player* pPlayer )
{
CollectionStateInfo* pStateInfo = _FindStateInfo(pCollection->GetObjectKey());
if( NULL != pStateInfo ||
NULL != pCollection->GetStateInfo() )
return false;
WzVector vServerPos;
pPlayer->GetPos( &vServerPos );
pStateInfo = CollectionStateInfoManager::Create(pCollection, pPlayer->GetCharGuid(), vServerPos );
if( NULL == pStateInfo )
return false;
if( false == pStateInfo->StartCollect() )
{
CollectionStateInfoManager::Release(pStateInfo);
return false;
}
m_Hash.Add(pStateInfo, pCollection->GetObjectKey());
return true;
}
RC::eCOLLECT_RESULT CollectionManager::_ChkDistance( Player* pPlayer, WzVector& wvClientCurPos, WzVector& wvCollectionPos )
{
WzVector vResultCurPos;
if( FALSE == pPlayer->CorrectPosition(wvClientCurPos, vResultCurPos) )
return RC::RC_COLLECT_POSITION_INVALID;
FLOAT fCurPosDiff = Math_Vector2DLength( vResultCurPos, wvCollectionPos );
if( MAX_COLLECT_DISTANCE_OBJ < fCurPosDiff )
return RC::RC_COLLECT_DISTANCE_INVALID;
return RC::RC_COLLECT_SUCCESS;
}
CollectionManager::PairIsStampReturnValue CollectionManager::_IsStamp(WzID CollectionID)
{
const CollectionInfo* pCollectInfo =
CollectionParser::Instance()->FindCollectionInfo(CollectionID);
if( NULL != pCollectInfo )
{
const DWORD dwStamp = pCollectInfo->m_Condition[CollectionInfo::STAMP];
const bool is_stamp = CollectionInfo::OBJ_STAMP == dwStamp ||
CollectionInfo::OBJ_STAMP_USE_GUILD_MASTER == dwStamp;
return std::make_pair(is_stamp, dwStamp);
}
return std::make_pair(false,0);
}
RC::eCOLLECT_RESULT CollectionManager::ChkCondision( Player* pPlayer, WzID CollectionID )
{
const CollectionInfo* pCollectInfo = CollectionParser::Instance()->FindCollectionInfo(CollectionID);
if( NULL == pCollectInfo )
{
return RC::RC_COLLECT_NOTEXIST;
}
// 0값은 조건 없음 값.
const QCODE qCode = (QCODE)pCollectInfo->m_Condition[CollectionInfo::QUEST];
const int iACCode = (int)pCollectInfo->m_Condition[CollectionInfo::AC];
const DWORD dwObjID = pCollectInfo->m_Condition[CollectionInfo::MAPOBJID];
const DWORD dwCount = pCollectInfo->m_Condition[CollectionInfo::COUNT];
if( 0 != qCode )
{
Quest* pQuest = pPlayer->GetQuestManager()->FindQuest(qCode);
if( NULL == pQuest || QS_NORMAL != pQuest->GetQState() )
{
return RC::RC_COLLECT_FAIL_QCONDISION;
}
//------------------------------------------------------------------------------
//
ItemManager* item_manager = pPlayer->GetItemManager();
QuestInfo* quest_info = pQuest->GetQuestInfo();
if (quest_info == NULL)
{
SUNLOG(eCRITICAL_LOG, _T("[%s:%d] cannot find quest info : %d"),
__FUNCTION__, __LINE__, qCode);
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
QUEST_CONDITION_ITEM_INFO* quest_condition_item_info = \
static_cast<QUEST_CONDITION_ITEM_INFO*>(
quest_info->FindCompleteCondition(eQUEST_CONDITION_ITEM));
if (quest_condition_item_info == NULL)
{
SUNLOG(eCRITICAL_LOG, _T("[%s:%d] cannot find quest complete condition item info : %d"),
__FUNCTION__, __LINE__, qCode);
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
for(int i = 0; i < quest_condition_item_info->GetItemArrayCount(); ++i)
{
if(quest_condition_item_info->GetItemCode(i) == pCollectInfo->m_ItemCode)
{
// 충분한 개수의 아이템이 있는지 체크
int item_count = quest_condition_item_info->GetItemNum(i);
int exist_count = item_manager->ExistItem(SI_INVENTORY, pCollectInfo->m_ItemCode, item_count);
if (exist_count >= item_count)
{
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
}
}
//
//------------------------------------------------------------------------------
}
if( 0 != iACCode )
{
AchievementManager* pACMgr = pPlayer->GetACManager();
if( NULL == pACMgr || FALSE == pACMgr->CanCollectTreasureBox(iACCode) )
return RC::RC_COLLECT_FAIL_ACCONDISION;
}
const PairIsStampReturnValue is_stamp = _IsStamp(CollectionID);
if (false != is_stamp.first)
{
GUILDGUID guildGuid = pPlayer->GetGuildGuid();
if (INVALID_GUILDGUID == guildGuid ||
ePRS_AT_DOMINATION_FIELD != pPlayer->GetGameZoneState())
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
GameDominationField* pZone = (GameDominationField*)pPlayer->GetGameZonePtr();
#ifdef _NA_006826_20130722_DOMINATION_RENEWAL
if (guildGuid == pZone->GetDefenseGuild())
{
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
// 지역점령전 시간이 종료되기전에 공성측에서 지역 점령 했을 경우..
if (pZone->GetOffenseGuild() == 0 && pZone->GetEventState() == DOMINATION_EVENT_END)
{
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
const GUILDGUID defense_guild_guild = pZone->GetDefenseGuild();
GameGuild* const defense_game_guild = g_GameGuildManager.FindGuild(defense_guild_guild);
if (defense_game_guild)
{
GuildRelationSystem::GuildRelationEntry* defense_guild_entry = \
defense_game_guild->GetRelationEntry();
if (defense_guild_entry)
{
eGUILD_RELATION relation = \
defense_guild_entry->GetRelationType(guildGuid);
if (relation == eGUILD_RELATION_ALLIENCE)
{
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
}
}
#else
if (guildGuid != pZone->GetOffenseGuild())
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
#endif // _NA_006826_20130722_DOMINATION_RENEWAL
// 길드 마스터만 각인 가능한 각인물 추가. [5/13/2010 lst1024]
// OBJ_STAMP : 공격 길드원 각인 가능
// OBJ_STAMP_USE_GUILD_MASTER : 공격 길드 마스터만 가능
if (is_stamp.second == CollectionInfo::OBJ_STAMP_USE_GUILD_MASTER &&
pPlayer->GetCharInfo()->m_eGuildDuty != eGUILD_DUTY_MASTER)
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(CollectionID))
{
// 플레이어가 현재 배틀그라운드존에 있는지 체크
if (pPlayer->IsThereBattleGroundZone() == false)
{
SUNLOG(eCRITICAL_LOG, TEXT("[%s|%d] player is not in battle ground"),
__FUNCTION__, __LINE__);
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
const BattleGround* const battle_ground = \
static_cast<BattleGround*>(pPlayer->GetCurrentChaosZone());
if (battle_ground == NULL || battle_ground->CanCheckSealing(pPlayer, CollectionID) == false) {
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
else if(_IsSonnenScheinStamp(CollectionID) == TRUE)
{
GUILDGUID guildGuid = pPlayer->GetGuildGuid();
if (INVALID_GUILDGUID == guildGuid) {
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
if (pPlayer->GetChaosZoneType() != eCHAOSZONE_TYPE_SONNENSCHEIN)
{
SUNLOG(eCRITICAL_LOG, TEXT("[%s|%d] player is not in SonnenSchein"),
__FUNCTION__, __LINE__);
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
SonnenSchein* sonnenschein = static_cast<SonnenSchein*>(pPlayer->GetCurrentChaosZone());
if (sonnenschein == NULL) {
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
if (guildGuid != sonnenschein->GetRoomGuildGuid()) {
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
//소넨샤인 끝났는지 상태체크
// Start상태에서 각인가능한건 정상적 케이스
// None상태 각인가능은 GM으로 생성된 소넨샤인을 위한 것
if (sonnenschein->GetEventState() != SONNENSCHEIN_EVENT_STATE_START &&
sonnenschein->GetEventState() != SONNENSCHEIN_EVENT_STATE_NONE) {
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if(_IsOneDaysGuildmissionStamp(CollectionID) == TRUE)
{
GUILDGUID guildGuid = pPlayer->GetGuildGuid();
if (INVALID_GUILDGUID == guildGuid) {
return RC::RC_COLLECT_FAIL_STAMP_CONDISION;
}
if (pPlayer->GetChaosZoneType() != eCHAOSZONE_TYPE_ONEDAYSGUILDMISSION)
{
SUNLOG(eCRITICAL_LOG, TEXT("[%s|%d] player is not in OneDaysGuildMission"),
__FUNCTION__, __LINE__);
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
OneDaysGuildMission* onedaysguildmission = static_cast<OneDaysGuildMission*>(pPlayer->GetCurrentChaosZone());
if (onedaysguildmission == NULL) {
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
}
#endif //_NA_008543_20151027_ONE_DAYS_GUILD_MISSION
else if( 0 != dwCount )
{
CollectedList* pCollectedList = pPlayer->GetCollectedList();
if( NULL == pCollectedList || pCollectedList->GetCount(CollectionID) >= dwCount )
return RC::RC_COLLECT_FAIL_COUNTCONDISION;
}
if (0 != dwObjID)
{
GameField* pGameField = pPlayer->GetField();
if (NULL == pGameField)
return RC::RC_COLLECT_FAIL_OBJECTID_CONDISION;
const MapNpc* pMapNpc = pGameField->FindMapNpc(Conv_MapObjectKey(dwObjID));
// 기획자의 실수로 오브젝트의 ID가 잘못 기입된 경우.
if (NULL == pMapNpc)
return RC::RC_COLLECT_FAIL_OBJECTID_CONDISION;
if (pMapNpc->IsAlive())
return RC::RC_COLLECT_FAIL_OBJECTID_CONDISION;
}
return RC::RC_COLLECT_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 보상스크립트로의 연결을 추천했으나,
// 기획자가 복권 스크립트의 형식을 채집스크립트가 일부 가지는 형식을 원함.
RC::eITEM_RESULT CollectionManager::_RewardItem( Player* pPlayer, CollectionInfo* pInfo, INVENTORY_TOTAL_INFO& OUT TotalInfo )
{
ItemManager* pMgr = pPlayer->GetItemManager();
MiniSlotInfo slotinfo;
slotinfo.Index = pInfo->m_ItemCode;
slotinfo.Random = pInfo->m_byScriptType;
slotinfo.ItemTypeIndex = pInfo->m_IGType;
SCItemSlot *pSlot = pMgr->GetItemFunctionLottery().MakeItemByLotteryInfo(
slotinfo, slotinfo.Random, NULL);
if( NULL == pSlot ||
0 == pSlot->GetNum() )
{
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_RewardItem] 보상 정보가 잘못되었다. [pSlot %s NULL], ItemNum[%d]",
pSlot?"!=":"==", pSlot?pSlot->GetNum():-1 );
return RC::RC_ITEM_NOINFO;
}
RC::eITEM_RESULT rc = RC::RC_ITEM_FAILED;
if( FALSE==pSlot->IsOverlap() )
rc = pMgr->Obtain( *pSlot, pSlot->GetNum(), &TotalInfo);
else
rc = pMgr->Obtain( pSlot->GetItemCode(), pSlot->GetNum(), &TotalInfo);
if( RC::RC_ITEM_SUCCESS != rc )
{
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_RewardItem][%s]에게 보상아이템 지급 실패했다. err[%d] ItemCode[%d] Num[%d] Overlap[%s]",
pPlayer->GetCharName(), rc, pSlot->GetItemCode(), pSlot->GetNum(), TRUE==pSlot->IsOverlap()?"true":"false" );
}
return rc;
}
//
void CollectionManager::_Collected( CollectionStateInfo* pStateInfo )
{
ASSERT(pStateInfo);
Player* const pPlayer = PlayerManager::Instance()->FindPlayerByCharKey( pStateInfo->GetCollector() );
S_TRY
{
if( NULL == pPlayer )
S_THROW(RC::RC_COLLECT_FAIL_REWORD_EXIT_CHAR);
//_NA001385_20090924_DOMINATION_STAMP
if( pPlayer->IsDead() )
{
const WzID collection_id = pStateInfo->GetCollectionID();
const PairIsStampReturnValue is_stamp = _IsStamp(collection_id);
if (false != is_stamp.first)
{
S_THROW(RC::RC_COLLECT_FAIL_STAMP_DEAD_CHAR);
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (_IsSealingStrongPoint(collection_id))
{
S_THROW(RC::RC_COLLECT_FAIL_STAMP_DEAD_CHAR);
}
else
{
S_THROW(RC::RC_COLLECT_FAIL_REWORD_DEAD_CHAR);
}
}
CollectedList* pCollectedList = pPlayer->GetCollectedList();
if( pStateInfo->GetObjectKey() != pCollectedList->GetObjKeyCollecting() )
S_THROW(RC::RC_COLLECT_FAIL_REWORD_WRONG_COLLECTOBJKEY);
WzVector vServerPos;
pPlayer->GetPos( &vServerPos );
FLOAT fCurPosDiff = Math_Vector2DLength( vServerPos, pStateInfo->GetCollectorPos() );
if( MAX_COLLECT_DISTANCE_CHAR < fCurPosDiff )
{
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_Collected] [%s]가 채집보상 유효 거리를 벗어났다. 거리차[%d]",
pPlayer->GetCharName(), fCurPosDiff );
S_THROW(RC::RC_COLLECT_FAIL_REWORD_POS);
}
const MAPOBJECT_INFO* pMapObjectInfo = pStateInfo->GetMapObjectInfo();
fCurPosDiff = Math_Vector2DLength( vServerPos, pMapObjectInfo->wvPos );
if( MAX_COLLECT_DISTANCE_OBJ < fCurPosDiff )
S_THROW(RC::RC_COLLECT_FAIL_REWORD_DISTANCE);
}
S_CATCH(DWORD, err)
{
// 채집시 클라이언트의 강제종료등이 발생할경우
// 필드에 다른 플레이어가 없다면 update는 이루어 지지 않으며, _Collected()로
// 들어 오지 않는다.
// 이 경우 다른 플레이어의 진입시 RC_COLLECT_FAIL_REWORD_EXIT_CHAR가
// 같은 플레이어 재진입시 RC_COLLECT_FAIL_REWORD_WRONG_COLLECTOBJKEY의 에러를 받는다.
// 이경우 채집자와 채집물은 서로 관계가 없는 상태이다.
// 그러므로 채집물 기준으로 주위에 자신(채집물)의 취소를 알린다.
RC::eCOLLECT_RESULT rc = RC::RC_COLLECT_SUCCESS;
switch(err)
{
case RC::RC_COLLECT_FAIL_REWORD_EXIT_CHAR:
case RC::RC_COLLECT_FAIL_REWORD_WRONG_COLLECTOBJKEY:
rc = Cancel(pStateInfo);
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_Collected] Player가 존재 하지 않아 채집물 주변에 취소를 알린다.");
break;
default:
{
rc = Cancel(pPlayer);
MSG_CG_COLLECT_ACTION_NAK msgNAK;
msgNAK.m_byErrorCode = err;
pPlayer->SendPacket(&msgNAK, sizeof(msgNAK));
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_Collected] [%s] 에게 실패 메시지를 보낸다.", pPlayer->GetCharName());
}
}
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_Collected] 채집후처리 에러[%d] cancel[%s]",
err, RC::RC_COLLECT_SUCCESS != rc?"fail":"success" );
return;
}
// 채집종료(성공) 알림
CollectedList* pCollectedList = pPlayer->GetCollectedList();
CollectionInfo* pCollectionInfo = pStateInfo->GetCollectionInfo();
pCollectedList->SetSuccessCollectionInfo(pCollectionInfo);
pCollectedList->EndCollecting();
Collection* pCollection = pStateInfo->GetCollection();
if( pCollection )
{
m_pField->LeaveField( pCollection );
ObjectFactory::Instance()->FreeObject( pCollection );
}
pStateInfo->StartRespawn();
}
void CollectionManager::_Respawn( CollectionStateInfo* pStateInfo )
{
MAPOBJECT_INFO* pMapInfo = pStateInfo->GetMapObjectInfo();
if( NULL == pMapInfo )
{
char ch[5] = {0,};
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_Respawn] pStateInfo 정보에 맵정보가 없어 활성화 시킬수 없다[%s].", WzIDToString(ch, pStateInfo->GetCollectionID()) );
return;
}
DWORD ObjKey = pStateInfo->GetObjectKey();
CollectionStateInfoManager::Release(pStateInfo);
m_Hash.Remove(ObjKey);
m_pField->CreateCollection(pMapInfo);
}
void CollectionManager::_Cancel( CollectionStateInfo* pStateInfo )
{
DWORD ObjKey = pStateInfo->GetObjectKey();
CollectionStateInfoManager::Release(pStateInfo);
m_Hash.Remove(ObjKey);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//
void CollectionManager::Update()
{
BYTE stat = 0;
bool delete_iterator = false;
ACTIVE_COLLECTION_HASH_IT it = m_Hash.begin(), end = m_Hash.end();
while( it != end )
{
CollectionStateInfo* pStateInfo = *it;
if( NULL == pStateInfo )
{
SUNLOG( eCRITICAL_LOG, "CollectionManager::Update() 잘못된 상태 정보를 포함하고 있다." );
++it;
continue;
}
delete_iterator = false;
if (pStateInfo->update(&stat))
{
switch(stat)
{
// 채집완료
case CollectionStateInfo::Collecting:
_Collected(pStateInfo);
break;
// 스폰완료
case CollectionStateInfo::Respawning:
{
MAPOBJECT_INFO* pMapInfo = pStateInfo->GetMapObjectInfo();
if (pMapInfo)
{
CollectionStateInfoManager::Release(pStateInfo);
it = m_Hash.erase(it);
m_pField->CreateCollection(pMapInfo);
delete_iterator = true;
}
else
{
char ch[5] = {0,};
SUNLOG( eCRITICAL_LOG, "[CollectionManager::_Respawn] pStateInfo 정보에 맵정보가 없어 활성화 시킬수 없다[%s].", WzIDToString(ch, pStateInfo->GetCollectionID()) );
}
}
break;
}
}
if( CollectionStateInfo::cancel == stat )
{
CollectionStateInfoManager::Release(pStateInfo);
it = m_Hash.erase(it);
delete_iterator = true;
}
if (delete_iterator == false)
++it;
}
}
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
bool CollectionManager::_IsSealingStrongPoint(WzID collection_id)
{
const CollectionInfo* const collection_info =
CollectionParser::Instance()->FindCollectionInfo(collection_id);
if (collection_info == NULL)
{
return false;
}
const DWORD stamp = collection_info->m_Condition[CollectionInfo::STAMP];
return (CollectionInfo::OBJ_BATTLE_GROUND_STRONGPOINT == stamp) ? true : false;
}
void CollectionManager::_StartSealing(Player* player, WzID collection_id)
{
if (player->IsThereBattleGroundZone() == false)
{
SUNLOG(eCRITICAL_LOG, TEXT("[%s|%d] player is not in battle ground"),
__FUNCTION__, __LINE__);
return;
}
const CollectionInfo* conllection_info = CollectionParser::Instance()->FindCollectionInfo(collection_id);
if (conllection_info != NULL)
{
StatusManager* status_manager = player->GetStatusManager();
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
status_manager->AllocStampStatus(conllection_info->m_dwCollectingTime);
#else
//아이언 바디, 강철 상태는 각인시 사라진다.
status_manager->Remove(eCHAR_STATE_STEEL);
status_manager->Remove(eCHAR_STATE_IMMUNITY_DAMAGE);
status_manager->AllocStatus(eCHAR_STATE_STAMP, conllection_info->m_dwCollectingTime);
#endif //_NA_007667_20141001_WITCHBLADE_SKILL
}
BattleGround* const battle_ground = static_cast<BattleGround*>(player->GetCurrentChaosZone());
if (battle_ground == NULL)
{
return;
}
if (battle_ground->StartSealing(player, collection_id) == false)
{
Cancel(player);
}
}
void CollectionManager::_CancelSealing(Player* player, WzID collection_id)
{
GameInstanceDungeon* const instance_dungeon =
static_cast<GameInstanceDungeon*>(m_pField->GetGameZone());
if (instance_dungeon == NULL) {
return;
}
ChaosZoneManager* const chaoszone_manager = instance_dungeon->GetChaosZoneManager();
if (chaoszone_manager == NULL || chaoszone_manager->GetChaosZoneType() != kBattleGround) {
return;
}
BattleGround* const battle_ground = static_cast<BattleGround*>(chaoszone_manager->GetCurrentZone());
if (battle_ground == NULL) {
return;
}
if (player)
{
StatusManager* status_manager = player->GetStatusManager();
status_manager->Remove(eCHAR_STATE_STAMP);
}
battle_ground->CancelSealing(player, collection_id);
}
#ifdef _NA_008334_20150608_SONNENSCHEIN
BOOL CollectionManager::_IsSonnenScheinStamp( WzID collection_id )
{
const CollectionInfo* pCollectInfo = CollectionParser::Instance()->FindCollectionInfo(collection_id);
if( NULL != pCollectInfo )
{
const DWORD dwStamp = pCollectInfo->m_Condition[CollectionInfo::STAMP];
const bool is_stamp = (CollectionInfo::OBJ_SONNENSCHEIN_STAMP == dwStamp);
return is_stamp;
}
return FALSE;
}
VOID CollectionManager::_StartSonnenScheinStamp( Player* player, WzID collection_id )
{
//각인상태를 건다
const CollectionInfo* conllection_info = CollectionParser::Instance()->FindCollectionInfo(collection_id);
if (conllection_info != NULL)
{
StatusManager* status_manager = player->GetStatusManager();
status_manager->AllocStampStatus(conllection_info->m_dwCollectingTime);
}
MSG_CG_SONNENSCHEIN_BEGIN_STAMP_BRD brd_msg;
brd_msg.stamp_id = collection_id;
//각인 시작시간을 저장한다.
if(player->GetChaosZoneType() == eCHAOSZONE_TYPE_SONNENSCHEIN)
{
//SonnenSchein에서의 각인
ChaosZone* chaos_zone = player->GetCurrentChaosZone();
if (chaos_zone != NULL)
{
SonnenSchein* sonnenschein = static_cast<SonnenSchein*>(chaos_zone);
sonnenschein->SetStampStartTime();
//packet send
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
}
}
VOID CollectionManager::_CancelSonnenScheinStamp( Player* player, WzID collection_id )
{
MSG_CG_SONNENSCHEIN_CANCEL_STAMP_BRD brd_msg;
brd_msg.stamp_id = collection_id;
if (player == NULL) {
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
else
{
StatusManager* status_manager = player->GetStatusManager();
status_manager->Remove(eCHAR_STATE_STAMP);
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
//각인 시작시간을 초기화 한다.
//Player가 NULL일 수 있는 함수이므로 GameZone을 통해 직접 SonnenSchein에 접근한다
GameInstanceDungeon* const instance_dungeon =
static_cast<GameInstanceDungeon*>(m_pField->GetGameZone());
if (instance_dungeon == NULL) {
return;
}
ChaosZoneManager* const chaoszone_manager = instance_dungeon->GetChaosZoneManager();
if (chaoszone_manager == NULL || chaoszone_manager->GetChaosZoneType() != eCHAOSZONE_TYPE_SONNENSCHEIN) {
return;
}
SonnenSchein* const sonnenschein = static_cast<SonnenSchein*>(chaoszone_manager->GetCurrentZone());
if (sonnenschein == NULL) {
return;
}
sonnenschein->InitStampCheckTime();
}
#endif //_NA_008334_20150608_SONNENSCHEIN
#ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION
BOOL CollectionManager::_IsOneDaysGuildmissionStamp( WzID collection_id )
{
const CollectionInfo* pCollectInfo = CollectionParser::Instance()->FindCollectionInfo(collection_id);
if( NULL != pCollectInfo )
{
const DWORD dwStamp = pCollectInfo->m_Condition[CollectionInfo::STAMP];
const bool is_stamp = (CollectionInfo::OBJ_ONEDYSGUILDMISSION_STAMP == dwStamp);
return is_stamp;
}
return FALSE;
}
VOID CollectionManager::_StartOneDaysGuildmissionStamp( Player* player, WzID collection_id )
{
//각인상태를 건다
const CollectionInfo* conllection_info = CollectionParser::Instance()->FindCollectionInfo(collection_id);
if (conllection_info != NULL)
{
StatusManager* status_manager = player->GetStatusManager();
status_manager->AllocStampStatus(conllection_info->m_dwCollectingTime);
}
MSG_CG_ONEDAYSGUILDMISSION_BEGIN_STAMP_BRD brd_msg;
brd_msg.stamp_id = collection_id;
//각인 시작시간을 저장한다.
if(player->GetChaosZoneType() == eCHAOSZONE_TYPE_ONEDAYSGUILDMISSION)
{
// 일일길드미션에서의 각인
ChaosZone* chaos_zone = player->GetCurrentChaosZone();
if (chaos_zone != NULL)
{
OneDaysGuildMission* Onedaysguildmission = static_cast<OneDaysGuildMission*>(chaos_zone);
Onedaysguildmission->SetStampStartTime();
//packet send
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
}
}
VOID CollectionManager::_CancelOneDaysGuildmissionStamp( Player* player, WzID collection_id )
{
MSG_CG_ONEDAYSGUILDMISSION_CANCEL_STAMP_BRD brd_msg;
brd_msg.stamp_id = collection_id;
if (player == NULL) {
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
else
{
StatusManager* status_manager = player->GetStatusManager();
status_manager->Remove(eCHAR_STATE_STAMP);
m_pField->SendPacketToAll(&brd_msg, sizeof(brd_msg));
}
//각인 시작시간을 초기화 한다.
//Player가 NULL일 수 있는 함수이므로 GameZone을 통해 직접 oneDaysGuildMission에 접근한다
GameInstanceDungeon* const instance_dungeon =
static_cast<GameInstanceDungeon*>(m_pField->GetGameZone());
if (instance_dungeon == NULL) {
return;
}
ChaosZoneManager* const chaoszone_manager = instance_dungeon->GetChaosZoneManager();
if (chaoszone_manager == NULL || chaoszone_manager->GetChaosZoneType() != eCHAOSZONE_TYPE_SONNENSCHEIN) {
return;
}
OneDaysGuildMission* const onedaysguildmission = static_cast<OneDaysGuildMission*>(chaoszone_manager->GetCurrentZone());
if (onedaysguildmission == NULL) {
return;
}
onedaysguildmission->InitStampCheckTime();
}
#endif // (_NA_008543_20151027_ONE_DAYS_GUILD_MISSION)
////////////////////////////////////////////////////////////////////////////////////////////////