Files
2026-06-01 12:46:52 +02:00

1659 lines
70 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <vector>
#include <string>
#include <ctime>
#include <mmo/ArObject.h>
#include <toolkit/TimeSyncer.h>
#include <toolkit/KHash.h>
#include <toolkit/ILock.h>
#include <toolkit/XPropertySet.h>
#include "StructCreature.h"
#include "ItemInstance.h"
#include "StructInventory.h"
#include "StructItem.h"
#include "StructGold.h"
#include "StructQuestManager.h"
#include "GameMessage.h"
#include "SendMessage.h"
#include "GameDBManager.h"
#include "PlayerData.h"
#include "UID.h"
#include "StructTitleManager.h"
#include "StructTitle.h"
#include "StructWorldLocation.h" // Fraun for get location type 8/17/2025
#include "..\Community\PartyMatching.h"
struct PlayerDeleter : public ArSchedulerObject
{
virtual void onProcess( int nThreadIdx );
};
struct StructPlayer : public StructCreature, XPropertySet, StructInventory::InventoryEventReceiver, StructQuest::QuestEventHandler, StructTitle::TitleEventHandler
{
ITERATOR_DEFINITION( StructPlayer );
static iterator get( AR_HANDLE handle )
{
iterator It;
GameObject *p = *GameObject::get( handle );
if( p )
{
if( p->IsPlayer() ) It.set( p );
}
return It;
}
virtual bool IsSkillCastable()
{
if( IsRiding() || HasRidingState() ) return false;
return StructCreature::IsSkillCastable();
}
virtual bool IsMagicCastable()
{
if( IsRiding() || HasRidingState() ) return false;
return StructCreature::IsMagicCastable();
}
// 시스템
static void EraseReturnLobbyConnection( int conn_id );
int SetReturnLobbyConnection( class XIOCPConnection * pConn );
static void EraseFromAutoAccount( int account_id );
static void AddToAutoAccountList( int account_id );
static void ClearAutoAccountList();
static bool IsAutoAccount( int account_id );
static void BindProperty();
static StructPlayer* AllocPlayer();
static AR_HANDLE FindPlayer( const char *szName );
static void EraseFromPlayerList( const char *szName );
static bool RegisterAccount( struct IStreamSocketConnection * pConn, const char *szName );
static void UnRegisterAccount( const char *szName );
static IStreamSocketConnection * GetConnectionByAccount( const char * szAccount );
static const bool IsRegisteredAccount( const char * szAccount );
static const bool SetRegisteredConnectionByAccount( const char *szAccount, struct IStreamSocketConnection * pConn );
static size_t DoEachPlayer( ArObjectFunctor & _fo );
void DoEachPartyPlayer( ArObjectFunctor & _fo );
void DoEachGuildPlayer( ArObjectFunctor & _fo );
static void DoPlayer( AR_HANDLE handle, ArObjectFunctor & _fo );
static volatile LONG & GetPlayerCount();
// Cache for storing player name UID (Other managers only have PlayerUID and dont store player names redundantly; obtain and use them through the function below)
static const char * GetPlayerName( const PlayerUID nPlayerUID );
static void RegisterPlayerName( const PlayerUID nPlayerUID, const char * pszName );
static void ClearPlayerName();
// UID 할당용
static ItemUID GetMaxItemUID();
static void SetMaxItemUID( ItemUID id );
static void SetMaxSummonSID( int sid );
static void SetMaxFarmSID( int sid );
static int AllocSummonSID();
static int AllocFarmSID();
static void SetMaxPetSID( int sid );
static int AllocPetSID();
bool IsPlayer() const { return true; }
AR_HANDLE GetHandle() const { return m_hHandle; }
PlayerUID GetPlayerUID() const { return m_nUID; }
int GetAccountID() const;
const char * GetAccountName() const;
virtual int GetSID() const { return GetPlayerUID(); }
void Save( bool bOnlyCharacter = false );
virtual void OnUpdate();
AR_HANDLE GetTarget() const { return m_hTarget; }
void SetTarget( AR_HANDLE target );
struct SKILL_FUNCTOR { virtual void onSkill( const StructSkill* pSkill ) {} };
void EnumSummonPassiveSkill( SKILL_FUNCTOR & _fo ) const;
void EnumSummonAmplifyPassiveSkill( SKILL_FUNCTOR & _fo ) const;
bool CanLogoutNow();
// 스탯
virtual const CreatureStat & GetBaseStat() const;
int GetPermission() const { return m_nPermission; }
bool IsChatBlock() const { return GetArTime() / 100 < (unsigned) m_nChatBlockTime; }
int GetChatBlockTime() const { return std::max( m_nChatBlockTime - (int)( GetArTime() / 100 ), 0 ); }
int GetAdvChatCount() const { return m_nAdvChatCount; }
void SetChatBlockTime( int nBlockTime ) { m_nChatBlockTime = GetArTime() / 100 + nBlockTime; }
virtual const char* GetName() const { return m_szName; }
const char * GetAlias( const bool bRawAlias = false ) const { return ( bRawAlias || ( m_bUseAlias && strlen( m_szAlias ) > 0 ) ) ? m_szAlias : m_szName; }
virtual int GetCreatureGroup() const { return ( m_nChangingGroup == CREATURE_NONE ) ? CREATURE_HUMAN : m_nChangingGroup; }
bool ChangeName( const char * szNewName, const bool bRemoveFromFriendAndDenial, const bool bIgnoreNameChangeCount, const AR_HANDLE hItem );
void SetName( const char *szName );
void OnChangeName( const char * szName, const bool bRemoveFromFriendAndDenial, const bool bIgnoreNameChangeCount, const bool bSuccess );
void SetAlias( const char * szNewAlias ) { s_strcpy( m_szAlias, _countof( m_szAlias ), szNewAlias ); if( strlen( szNewAlias ) > 0 ) s_strcat( m_szAlias, _countof( m_szAlias ), "*" ); SendPropertyMessage( this, GetHandle(), "alias", m_szAlias ); }
void SetUseAlias( bool bUseAlias ) { m_bUseAlias = bUseAlias; }
bool IsUsingAlias() const { return m_bUseAlias; }
virtual unsigned char GetRace() const { return m_nRace; }
int GetSex() const { return m_nSex; }
void SetCreatureSpeed( unsigned char speed );
void SetWalk( bool bOn ) { m_bWalk = bOn; }
bool IsWalking() const { return m_bWalk; }
virtual void AddExp( __int64 exp, __int64 jp, bool bApplyStamina = true );
__int64 GetDeadEXPPenalty();
// 직업군
virtual bool IsHunter() const;
virtual bool IsFighter() const;
virtual bool IsMagician() const;
virtual bool IsSummoner() const;
bool IsChangeableJob( const int nTargetJob ) const;
bool ChangeJob( const _SKILL_RESET_METHOD eMethod, const int nTargetJob );
bool ResetJob( const int nTargetJobDepth );
bool SetRace( const _SKILL_RESET_METHOD eMethod, const unsigned char nTargetRace );
// 특성
virtual int GetTalentPoint() const { return m_nTalentPoint; }
virtual void SetTalentPoint( int nTalentPoint ) { m_nTalentPoint = nTalentPoint; SendPropertyMessage( this, GetHandle(), "tp", GetTalentPoint() ); }
int GetCharisma() const { return m_nCharisma; }
virtual int GetMoveSpeed() const;
// 혼돈 관련
int GetMaxChaos() const { return m_nMaxChaos; }
int GetChaos() const { return m_nChaos; }
//void SetChaos( int nChaos ) { m_nChaos = nChaos <= m_nMaxChaos ? nChaos : m_nMaxChaos; }
void AddChaos( int nChaos );
// 퀘스트 관련
bool StartQuest( QuestBase::QuestCode code, int nStartQuestID, bool bForce = false );
const bool AddPendingQuest( const QuestBase::QuestCode code, int nStartID );
bool EndQuest( QuestBase::QuestCode code, int nSelectRewardIdx = -1 );
bool DropQuest( QuestBase::QuestCode code );
const bool ResetFinishedQuest( QuestBase::QuestCode code );
int GetQuestProgress( QuestBase::QuestCode code ) const; // -1 : 아무것도 아님 0 : 수락가능 1 : 수행중 2 : 종료가능 255 : 이미종료
const int GetQuestStartTextID( QuestBase::QuestCode code ) const;
inline const size_t DoEachActiveQuest( StructQuestManager::QuestFunctor & _fo ) { return m_QuestManager.DoEachActiveQuest( _fo ); }
inline const size_t DoEachPendingQuest( StructQuestManager::QuestFunctor & _fo ) { return m_QuestManager.DoEachPendingQuest( _fo ); }
inline const size_t GetActiveQuestCount() { return m_QuestManager.GetActiveQuestCount(); }
int GetLastAcceptQuest() { return m_nLastAcceptQuest; }
const bool IsStartableQuest( QuestBase::QuestCode code ) const;
const bool IsPendingQuest( const QuestBase::QuestCode code ) const { return m_QuestManager.IsPendingQuest( code ); }
const bool IsInProgressQuest( QuestBase::QuestCode code ) const;
const bool IsFinishableQuest( QuestBase::QuestCode code ) const;
const bool IsTakeableQuestItem( QuestBase::QuestCode code ) const;
const time_t GetRemainQuestCoolTime( QuestBase::QuestCode code, time_t tCurrent ) const { return m_QuestManager.GetRemainQuestCoolTime( code, tCurrent ); }
const bool CheckFinishableQuestAndGetQuestStruct( QuestBase::QuestCode code, StructQuest** pQuest ) const;
inline StructQuest * FindQuest( QuestBase::QuestCode code ) const { return m_QuestManager.FindQuest( code ); }
void GetQuestByMonster( int nMonsterId, std::vector< StructQuest* > & vQuest, int type );
void UpdateQuestStatusByMonsterKill( int nMonsterId );
// 호칭 관련
inline const TitleBaseServer *GetMainTitle() { return m_pMainTitle; }
inline const TitleBaseServer *GetSubTitle( int nIndex ) { return m_pSubTitle[ nIndex ]; }
inline const AR_TIME GetRemainTitleTime() { return m_tRemainTitleTime; }
bool IsUsableTitle( int nCode );
bool SetMainTitle( int nCode );
bool SetSubTitle( int nIndex, int nCode );
bool OpenTitle( int nCode );
bool AchieveTitle( int nCode );
bool BookmarkTitle( int nCode );
void SetRemainTitleTime( int nRemainTitleTime ) { m_tRemainTitleTime = nRemainTitleTime; }
void UpdateTitleCondition( const int nTitleCondition, const __int64 nCount ) { m_TitleManager.UpdateTitleCondition( nTitleCondition, nCount ); }
void UpdateTitleConditionByMonsterKill( const int nMonsterID, const int nTamingCode ) { m_TitleManager.UpdateTitleConditionByMonsterKill( nMonsterID, nTamingCode ); }
void UpdateTitleConditionByItemGet( ItemBase::ItemCode nItemCode, const __int64 & nCount ) { m_TitleManager.UpdateTitleConditionByItemGet( nItemCode, nCount ); }
void UpdateTitleConditionByItemEquip( ItemBase::ItemCode nItemCode, const bool bEquip ) { m_TitleManager.UpdateTitleConditionByItemEquip( nItemCode, bEquip ); }
void UpdateTitleConditionByItemUse( ItemBase::ItemCode nItemCode ) { m_TitleManager.UpdateTitleConditionByItemUse( nItemCode ); }
void UpdateTitleConditionByItemCreateByMixing( std::vector< std::pair< StructItem *, __int64 > > & vCreatedItem ) { m_TitleManager.UpdateTitleConditionByItemCreateByMixing( vCreatedItem ); }
void UpdateTitleConditionBySummonEnhance( const int nTamingCode, const char nRate, const int nEnhance ) { m_TitleManager.UpdateTitleConditionBySummonEnhance( nTamingCode, nRate, nEnhance ); }
void UpdateTitleConditionBySummonTame( const int nTamingCode, const char nRate, const bool bSuccess ) { m_TitleManager.UpdateTitleConditionBySummonTame( nTamingCode, nRate, bSuccess ); }
void UpdateTitleConditionBySummonEquip( const int nTamingCode, const char nRate, const int nEnhance, const int nInc ) { m_TitleManager.UpdateTitleConditionBySummonEquip( nTamingCode, nRate, nEnhance, nInc ); }
void UpdateTitleConditionBySummonMount( const int nTamingCode, const bool bMount ) { m_TitleManager.UpdateTitleConditionBySummonMount( nTamingCode, bMount ); }
void UpdateTitleConditionBySummonPutOnBelt( std::vector< int > & vBeltCode ) { m_TitleManager.UpdateTitleConditionBySummonPutOnBelt( vBeltCode ); }
void UpdateTitleConditionByPKOn( const bool bPKOn ) { m_TitleManager.UpdateTitleConditionByPKOn( bPKOn ); }
void UpdateTitleConditionByDungeonSiegeStart( const int nDungeonID, const bool bIsAttackTeam ) { m_TitleManager.UpdateTitleConditionByDungeonSiegeStart( nDungeonID, bIsAttackTeam ); }
void UpdateTitleConditionByDungeonSiegeEnd( const int nDungeonID, const bool bIsAttackTeam, const bool bResult ) { m_TitleManager.UpdateTitleConditionByDungeonSiegeEnd( nDungeonID, bIsAttackTeam, bResult ); }
inline const bool IsAchievedTitle( int nCode ){ return m_TitleManager.IsAchievedTitle( nCode ); }
inline const size_t GetTitleCount() { return m_TitleManager.GetTitleCount(); }
inline const size_t GetTitleConditionCount() { return m_TitleManager.GetTitleConditionCount(); }
inline const size_t DoEachTitle( StructTitleManager::TitleFunctor & _fo ) { return m_TitleManager.DoEachTitle( _fo ); }
inline const size_t DoEachTitleCondition( StructTitleManager::TitleConditionFunctor & _fo ) { return m_TitleManager.DoEachTitleCondition( _fo ); }
// 아이템/재화 관련
const StructGold GetGold() const { return m_nGold; }
const StructGold GetStorageGold() const { return m_nStorageGold; }
const unsigned short ChangeStorageGold( const StructGold & gold );
const unsigned short ChangeGold( const StructGold & gold );
inline const int GetBaseModelId( int nIdx ) const { return m_nBaseModelId[nIdx]; }
inline void SetBaseModelId( int nIdx, int nModelId ) { m_nBaseModelId[nIdx] = nModelId; }
inline const int GetFaceTextureId() const { return m_nFaceTextureId; }
inline const int GetHairColorIndex() const { return m_nHairColorIndex; }
inline void SetHairColorIndex( const int nHairColorIndex ) { m_nHairColorIndex = nHairColorIndex; }
inline const unsigned int GetHairColorRGB() const { return m_nHairColorRGB; }
inline void SetHairColorRGB( const unsigned int nHairColorRGB ) { m_nHairColorRGB = nHairColorRGB; }
inline const unsigned int GetHideEquipFlag() const { return m_nHideEquipFlag; }
inline void SetHideEquipFlag( const unsigned int nHideEquipFlag ) { m_nHideEquipFlag = nHideEquipFlag; }
const char * GetClientInfo() const { return m_strClientInfo.c_str(); }
void SetClientInfo( const char* pValue ) { m_strClientInfo = pValue; }
const char * GetQuickSlot() const { return m_strQuickSlot.c_str(); }
void SetQuickSlot( const char* pValue ) { m_strQuickSlot = pValue; }
const char * GetCurrentKey() const { return m_strCurrentKey.c_str(); }
void SetCurrentKey( const char* pValue ) { m_strCurrentKey = pValue; }
const char * GetSavedKey() const { return m_strSavedKey.c_str(); }
void SetSavedKey( const char* pValue ) { m_strSavedKey = pValue; }
virtual bool IsUsingBow() const { return ( m_anWear[ ItemBase::WEAR_WEAPON ] ? m_anWear[ ItemBase::WEAR_WEAPON ]->IsBow() : false ); }
virtual bool IsUsingCrossBow() const { return ( m_anWear[ ItemBase::WEAR_WEAPON ] ? m_anWear[ ItemBase::WEAR_WEAPON ]->IsCrossBow() : false ); }
virtual bool TranslateWearPosition( ItemBase::ItemWearType & pos, struct StructItem* pItem, std::vector< int > * vpOverlappItemList = NULL );
//bool IsPopable( struct StructItem* pItem, unsigned count = 1 );
// 에테리얼 내구도 관련
virtual void ProcEtherealDurabilityConsumption( const bool bIsAttacker, const DamageType eDamageType, const int nDamage );
// 헌터홀릭 관련
const int GetHuntaholicPoint() const { return m_nHuntaholicPoint; }
// SetHuntaholicPoint는 HuntaholicManager에서 HuntaholicInfo::csInstanceDungeon, InstanceDungeon::csInstance 걸고 호출해야 함
void SetHuntaholicPoint( const int nPoint ) { m_nHuntaholicPoint = std::min( std::max( nPoint, 0 ), GameRule::HUNTAHOLIC_MAX_OWNABLE_POINT ); SendPropertyMessage( this, GetHandle(), "huntaholicpoint", GetHuntaholicPoint() ); }
const int GetHuntaholicEnterableCount() const { return m_nHuntaholicEnterableCount; }
void SetHuntaholicEnterableCount( const int nEnterableCount );
void AddHuntaholicEnterableCount( const int nEnterableCountInc );
const time_t GetNextHuntaholicEnterableCountRefill() const { return m_tNextHuntaholicEnterableCountRefill; }
// 충전된 에테리얼 스톤 내구도
const int GetEtherealStoneDurability() const { return m_nEtherealStoneDurability; }
void SetEtherealStoneDurability( const int nDurability ) { m_nEtherealStoneDurability = std::min( std::max( nDurability, 0 ), GameRule::MAX_ETHEREAL_STONE_DURABILITY ); SendPropertyMessage( this, GetHandle(), "ethereal_stone", GetEtherealStoneDurability() ); }
void AddEtherealStoneDurability( const int nAdd ) { SetEtherealStoneDurability( GetEtherealStoneDurability() + nAdd ); }
// 아이템 관련
bool IsMixable( StructItem * pItem );
bool IsErasable( StructItem * pItem );
bool IsDecomposable( StructItem * pItem );
bool IsRandomizable( StructItem * pItem );
bool IsSellable( StructItem * pItem );
bool IsTradable( StructItem * pItem );
bool IsDropable( StructItem * pItem );
bool IsTakeable( AR_HANDLE ItemHandle, const __int64 & cnt = 0 );
struct StructItem* PushItem( struct StructItem *pItem, const __int64 & cnt, bool bSkipUpdateItemToDB = false );
struct StructItem* PopItem( struct StructItem *pItem, const __int64 & cnt, bool bSkipUpdateItemToDB = false );
struct StructItem* DropItem( struct StructItem *pItem, const __int64 & count = 1 );
void ChangeItemPosition( bool is_storage, AR_HANDLE hItem_01, AR_HANDLE hItem_02 );
unsigned short ArrangeItem( const bool bIsStorage );
struct StructItem* onAfterChangeItemProperty( struct StructItem *pItem );
bool EraseBullet( const __int64 & count );
#define EraseItem( pItem, count ) EraseItem_( pItem, count, __FILE__, __LINE__ )
bool EraseItem_( struct StructItem *pItem, const __int64 & count = 1, const char* function = NULL, const int line = 0 );
bool EraseItemFromStorage( struct StructItem *pItem, const __int64 & count );
bool GiveItem( struct StructPlayer *pTarget, AR_HANDLE ItemHandle, const __int64 & count, AR_HANDLE * pResultItemHandle = NULL );
const size_t GetItemCount(); // 아이템의 수량이 아닌 아이템의 종류 수(인벤토리 차지 칸 수)이므로 size_t 사용
const size_t GetStorageItemCount();
const __int64 GetItemCount( ItemBase::ItemCode code );
struct StructItem* GetItem( unsigned idx );
struct StructItem* GetStorageItem( unsigned idx );
struct StructItem* FindItem( ItemUID uid ) const; // 이것 느림. 가급적 AR_HANDLE 로 찾을것.
struct StructItem* FindItem( ItemBase::ItemCode code ) const;
void FindItem( ItemBase::ItemCode code, std::vector< StructItem * > & vList );
struct StructItem* FindStorageItem( ItemBase::ItemCode code ) const;
struct StructItem* FindEmptySummonCard( ItemBase::ItemCode code ) const;
struct StructItem* FindEmptyPetCage( ItemBase::ItemCode code ) const;
struct StructItem* FindTamingSummonCard( ItemBase::ItemCode code ) const;
struct StructItem* FindFarmedSummonCard( ItemUID uid ) const;
unsigned short UseItem( struct StructItem *pItem, struct StructCreature *pTarget = NULL, const char *szParameter = NULL );
int IsUseableItem( struct StructItem *pItem, struct StructCreature * pTarget );
AR_TIME GetItemCoolTime( int group_id );
void SetItemCoolTime( int group_id, int cooltime );
void CloseStorage();
bool IsLoadingStorage() const { return m_nIsUsingStorage == LOADING_STORAGE; }
bool IsUsingStorage() const { return m_nIsUsingStorage == OPEN_STORAGE; }
bool MoveStorageToInventory( struct StructItem *pItem, const __int64 & cnt );
bool MoveInventoryToStorage( struct StructItem *pItem, const __int64 & cnt );
StructInventory * GetInventory() { return &m_Inventory; }
void ClearInventory();
inline void UpdateWeightWithInventory() { m_fWeight = (int)m_Inventory.GetWeight(); }
// 소환수 관련
void EquipSummon( AR_HANDLE* pCardHandle );
void AddSummon( struct StructSummon* pSummon, bool bSkipUpdateItemToDB = false, bool bSendMsg = true );
void RemoveSummon( struct StructSummon* pSummon, bool bSkipUpdateItemToDB = false );
void AddSummonToStorage( struct StructSummon* pSummon, bool bSkipUpdateItemToDB );
void RemoveSummonFromStorage( struct StructSummon* pSummon, bool bSkipUpdateItemToDB );
void RemoveAllSummonFromWorld();
void RemoveAllPetFromWorld();
struct StructSummon* GetSummon( int summon_sid );
struct StructSummon* GetSummon( AR_HANDLE handle );
struct StructSummon* GetSummonAt( int slot_index ) const { return ( m_aBindSummonCard[slot_index] ? m_aBindSummonCard[slot_index]->GetSummonStruct() : NULL ); }
struct StructItem* GetSummonCardAt( int slot_index ) const { return m_aBindSummonCard[slot_index]; }
void SetSummonCardAt( int slot_index, struct StructItem *pPtr ) { m_aBindSummonCard[slot_index] = pPtr; }
bool Summon( struct StructSummon * pSummon, const ArPosition & pos );
bool UnSummon( struct StructSummon * pSummon = NULL );
bool PendUnSummon( struct StructSummon * pSummon = NULL );
int GetPendingUnSummon() const { return m_nPendingUnSummon; }
struct StructSummon* GetMainSummon() const { return m_pMainSummon; }
struct StructSummon* GetSubSummon() const { return m_pSubSummon; }
void SetMainAndSubSummon();
bool IsSummonable() const { return m_bIsSummonable; }
int GetNextUnSummonTime() { return m_nNextUnSummonTime; }
struct StructItem* GetBeltSlotCardAt( int belt_slot_idx ) const { return m_aBeltSlotCard[belt_slot_idx]; }
struct StructItem* GetEquipmentOnBelt() const;
void SetNextUnSummonTime( int nNextUnSummonTime ) { m_nNextUnSummonTime = nNextUnSummonTime; }
void SetNameChangeTarget( const int uid ) { m_nNameChangeTarget = uid; }
int GetNameChangeTarget() const { return m_nNameChangeTarget; }
float GetActiveSummonExpAmp() const { return m_fActiveSummonExpAmp; }
void SetActiveSummonExpAmp( float fAmp ) { m_fActiveSummonExpAmp = fAmp; }
int GetGuildPoint() const { return m_nGuildPoint; }
int GetGuildTotalPoint() const { return m_nGuildTotalPoint; }
void SetGuildPoint( int nGuildPoint ) { m_nGuildPoint = nGuildPoint; }
void SetGuildTotalPoint( int nGuildTotalPoint ) { m_nGuildTotalPoint = nGuildTotalPoint; }
// 소환수 농장 관련
struct FARMED_SUMMON_INFO
{
FARMED_SUMMON_INFO( const int _farm_sid, struct StructItem *_item, const int _max_level, const bool _is_using_cracker, const bool _is_cash, const time_t _registration_time, const int _duration, const time_t _nursing_time )
: farm_sid( _farm_sid )
, item( _item )
, max_level( _max_level )
, is_using_cracker( _is_using_cracker )
, is_cash( _is_cash )
, registration_time( _registration_time )
, duration( _duration )
, nursing_time( _nursing_time )
{}
int farm_sid;
struct StructItem * item;
int max_level;
bool is_using_cracker;
bool is_cash;
time_t registration_time;
int duration;
time_t nursing_time;
};
bool FarmSummon( int nSlot, AR_HANDLE hCardHandle, int nDuration, bool bUseCracker, bool bCash );
bool RegainSummon( AR_HANDLE hHandle );
bool NurseSummon( AR_HANDLE hHandle );
void SetFarmedSummonInfo( int nSlot, FARMED_SUMMON_INFO *pFarmedSummonInfo ) { assert( ( nSlot >= 0 && nSlot < GameRule::FARM_MAX_COUNT ) && ( !m_vFarmedSummonInfo[nSlot] || pFarmedSummonInfo == NULL ) ); m_vFarmedSummonInfo[nSlot] = pFarmedSummonInfo; }
FARMED_SUMMON_INFO * GetFarmedSummonInfo( int nSlot ) { assert( nSlot >= 0 && nSlot < GameRule::FARM_MAX_COUNT ); return m_vFarmedSummonInfo[nSlot]; }
size_t GetFarmedSummonCount();
size_t GetNonCashFarmedSummonCount();
int GetFarmedSummonLevel( AR_HANDLE hHandle );
// 펫 관련
void AddPet( struct StructPet* pPet, bool bSkipUpdateItemToDB, bool bSendMsg = true );
void RemovePet( struct StructPet* pPet, bool bSkipUpdateItemToDB );
void AddPetToStorage( struct StructPet* pPet, bool bSkipUpdateItemToDB );
void RemovePetFromStorage( struct StructPet* pPet, bool bSkipUpdateItemToDB );
unsigned short SummonPet( struct StructPet* pPet );
bool UnSummonPet(); // 펫의 역소환은 소환수같이 즉시 하지 않고 전부 벡터에 보관했다가 StructPlayer:onProcess에서 함(락 문제 발생 소지 즐 -_ -)
struct StructPet* GetSummonedPet() const { return m_pSummonedPet; }
struct StructPet* GetPet( int nPet_sid );
bool ProcGlobalChatProcess( const char * pChat, int nChatType );
// 로그인 / 로그아웃 처리
void Login();
void LogoutNow( const int nCallerIdx );
void LogoutNowWithAccount( const int nCallerIdx );
void OnConnectionClosed( struct _CONNECTION_TAG * pTag );
bool IsLogin() const { return m_bIsLogin; }
void SetLastLogoutRequestedTime( const AR_TIME & t ) { m_nLastLogoutRequestedTime = t; }
const AR_TIME GetLastLogoutRequestedTime() { return m_nLastLogoutRequestedTime; }
// 파티 관련
void SetPartyID( int nPartyID ) { m_nPartyID = nPartyID; }
int GetPartyID() const { return m_nPartyID; }
bool IsInParty() const { return m_nPartyID != 0; }
bool HasItemPriority() const { return m_bItemPriority; }
void SetItemPriority() { m_bItemPriority = true; }
void ReleaseItemPriority() { m_bItemPriority = false; }
bool IsPartyInvitable( StructPlayer * pTarget) const;
// 길드 관련
void SetGuildID( int nGuildId ) { m_nGuildId = nGuildId; }
int GetGuildID() const { return m_nGuildId; }
void SetPrevGuildID( int nPrevGuildId ) { m_nPrevGuildId = nPrevGuildId; }
int GetPrevGuildID() const { return ( m_tGuildBlockTime > time( NULL ) ) ? m_nPrevGuildId : 0; }
bool IsInGuild() const { return ( m_nGuildId > 0 ); }
bool IsGuildInvitable( StructPlayer * pTarget ) const;
time_t GetGuildBlockTime() { return ( m_tGuildBlockTime > time( NULL ) ) ? m_tGuildBlockTime : 0; }
void SetGuildBlockTime( time_t guild_block_time ) { m_tGuildBlockTime = guild_block_time; }
const char GetGuildPermission() const { return m_nGuildPermission; }
void SetGuildPermission( const char nPermission ) { m_nGuildPermission = nPermission; }
// 메신저 관련
void AddFriend( const char * szName );
bool addFriend( const char * szName );
void AddFriendOf( const char * szName );
void AddDenial( const char * szName );
bool addDenial( const char * szName );
void AddDenialOf( const char * szName );
void DelFriend( const char * szName );
bool delFriend( const char * szName );
void DelFriendOf( const char * szName );
void DelDenial( const char * szName );
bool delDenial( const char * szName );
void DelDenialOf( const char * szName );
bool IsFriend( const char * szName );
bool IsFriendOf( const char * szName );
bool IsDenial( const char * szName );
bool IsDenialOf( const char * szName );
const size_t GetFriendCount() const { return m_vFriend.size(); }
const size_t GetFriendOfCount() const { return m_vFriendOf.size(); }
const size_t GetDenialCount() const { return m_vDenial.size(); }
const size_t GetDenialOfCount() const { return m_vDenialOf.size(); }
struct FriendDenialFunctor
{
virtual const bool operator()( std::string & strName ) = 0;
};
// 별로 이러고 싶진 않지만 락도 안 걸고 m_vDenial을 돌아주는 함수의 인터페이스를 외부에 노출하지 않으면 해결이 안 됨 -_ -;
friend void SendFriendsList( struct StructPlayer *pClient );
friend void SendStatusMessageToFriendOfPlayer( struct StructPlayer *pClient, bool bIsLogin );
const size_t DoEachFriend( FriendDenialFunctor & fo );
const size_t DoEachFriendOf( FriendDenialFunctor & fo );
const size_t DoEachDenial( FriendDenialFunctor & fo );
const size_t DoEachDenialOf( FriendDenialFunctor & fo );
// 플레이어 변수 ( named flag 라고 보면 됨 )
std::string GetFlag( const char *szKey ) const;
const bool RemoveFlag( const char *szKey );
const bool IsExistFlag( const char *szKey ) const;
void SetFlag( const char *szKey, const char *szData );
void EnumFlag( std::string & strValueList );
// 플레이어 어카운트 변수
std::string GetAccountFlag( const char *szKey ) const;
void SetAccountFlag( const char *szKey, const char *szData );
const bool RemoveAccountFlag( const char* szKey );
void EnumAccountFlag( std::string & strValueList );
// 노점 관련
enum BOOTH_STATUS
{
IS_NOT_BOOTH = 0,
SELL_BOOTH = 1,
BUY_BOOTH = 2,
};
enum STORAGE_STATUS
{
CLOSE_STORAGE = 0,
LOADING_STORAGE = 1,
OPEN_STORAGE = 2,
};
struct BOOTH_OPEN_ITEM_INFO
{
AR_HANDLE handle;
int cnt;
__int64 gold;
};
struct BOOTH_ITEM_INFO
{
StructItem* pItem;
int cnt;
__int64 gold;
};
struct BOOTH_ITEM_BUY_INFO
{
int nIdx;
int nCount;
};
bool OpenBooth( const char * szBoothName, const std::vector< StructPlayer::BOOTH_OPEN_ITEM_INFO > & vItemList, bool IsBuyBooth );
bool CloseBooth();
BOOTH_STATUS GetBoothStatus() { return m_BoothStatus; }
const char * GetBoothName();
const std::vector< StructPlayer::BOOTH_ITEM_INFO > & GetBoothItemList();
void WatchBooth( StructPlayer * pBooth );
void StopWatchBooth();
bool IsBoothWatching() const { return ( m_pBoothOpener != NULL ); }
bool BuyFromBooth( StructPlayer * pBuyer, std::vector<BOOTH_ITEM_BUY_INFO> & vBuyInfo );
bool SellToBooth( StructPlayer * pSeller, AR_HANDLE hItem, int nIdx, const __int64 & nCnt );
static XCriticalSection* GetBoothLock();
bool IsBoothOpen()
{
return GetBoothStatus() != IS_NOT_BOOTH;
}
virtual bool IsActable()
{
if( IsBoothOpen() ) return false;
return StructCreature::IsActable();
}
virtual bool IsMovable()
{
if( IsBoothOpen() ) return false;
return StructCreature::IsMovable();
}
virtual bool IsAttackable()
{
if( IsRiding() || HasRidingState() ) return false;
return StructCreature::IsAttackable();
}
const unsigned short IsBoothOpenable();
bool IsMountable( bool bByOnlyLocation )
{
if( !bByOnlyLocation )
{
if( !IsActable() || IsSitDown() || IsUsingSkill() || IsAttacking() || IsSitDown() )
return false;
}
if( IsInDungeon() || IsInSecretDungeon() || IsInInstanceDungeon() || IsInBattleArena() || IsInRamadanPrayerHall() ) return false;
return true;
}
bool IsItemPickable()
{
if( !IsActable() || IsSitDown() || IsUsingSkill() || IsAttacking() ) return false;
return true;
}
bool IsSitdownable()
{
if( !IsActable() || IsSitDown() || IsUsingSkill() || IsRiding() || HasRidingState() ) return false;
return true;
}
virtual bool IsItemUseable()
{
if( IsBoothOpen() ) return false;
return StructCreature::IsItemUseable();
}
virtual bool IsItemWearable()
{
if( IsBoothOpen() ) return false;
return StructCreature::IsItemWearable();
}
// 테이밍 관련
AR_HANDLE GetTamingTarget() const { return m_hTamingTarget; }
void SetTamingTarget( AR_HANDLE target ) { m_hTamingTarget = target; }
// 앉기/서기
void SitDown() { m_bIsSitDown = true; }
void StandUp() { m_bIsSitDown = false; onStandUp(); }
virtual bool IsSitDown() const { return m_bIsSitDown; }
// 모드
void SetBattleModeOn() { m_bIsBattleMode = true; }
void SetBattleModeOff() { m_bIsBattleMode = false; }
virtual bool IsBattleMode() const { return m_bIsBattleMode; }
// 라이딩 관련
// HasRidingState -> 아이템(탈것)으로 인한 라이딩
// IsRiding -> 내 소환수(크리처)의 패시브 스킬에 의한 라이딩
bool HasRidingState() { return !!m_nRidingStateCode; }
bool IsRiding() { return m_nRideIdx != MOUNT_NOTHING; }
inline bool IsApplyingFasterSpeedInRiding() { return m_bUseFasterSpeedInRiding; }
AR_HANDLE GetRideHandle();
struct StructSummon * GetRideObject() const;
int GetUnMountProbabilityOnDamage();
int GetUnMountProbabilityOnCriticalDamage();
enum
{
UNMOUNT_NORMAL = 0,
UNMOUNT_FALL = 1,
UNMOUNT_UNSUMMON = 2,
};
void MountSummon( AR_HANDLE handle );
void UnMount( const char flag = UNMOUNT_NORMAL, StructCreature * pCauser = NULL );
bool IsPendWarp() const { return m_nPendWarpX >= 0 && m_nPendWarpY >= 0; }
void ProcessWarp();
enum CONDITION_INFO
{
CONDITION_GOOD = 0,
CONDITION_AVERAGE = 1,
CONDITION_BAD = 2,
};
// 피로도 관련
int GetStamina() const { return m_nStamina; }
void AddStamina( int nStamina );
int GetStaminaRegenRate();
CONDITION_INFO GetCondition();
int GetLogoutDuration() const { return m_nLogoutDuration; }
void SetLogoutDuration( int nLogoutDuration ) { m_nLogoutDuration = nLogoutDuration; }
// 벨트 슬롯 관련
bool PutOnBelt( int pos, struct StructItem * pItem );
void PutOffBelt( int pos );
// Region and weather information
int GetLocationId() const { return m_nWorldLocationId; }
int GetLocationType() const { return static_cast<int>( WorldLocationManager::Instance().GetLocationType( GameContent::GetLocationId(GetX(), GetY()) ) ); }; // Fraun get location type 8/17/2025
void ChangeLocation( AR_UNIT x, AR_UNIT y, bool bByRequest = false, bool bBroadcast = true );
const bool IsInTown() const;
const bool IsInField() const;
const bool IsInBattleField() const;
const bool IsInEventmap() const;
const bool IsUsingTent() const { return m_bUsingTent; }
const bool IsInSiegeOrRaidDungeon() const;
const bool IsInSiegeDungeon() const;
const bool IsInDungeon() const;
const bool IsInSecretDungeon() const;
const bool IsInHuntaholic() const;
const bool IsInInstanceDungeon() const;
const bool IsInDeathmatch() const;
const bool IsInHorizon() const;
const bool IsInBattleArena() const;
const bool IsInRamadanPrayerHall() const;
const bool IsGaiaMember() const { return m_bIsGaiaMember; }
AR_TIME GetGaiaMemberRemainTime();
void SetGaiaMemberRemainTime( AR_TIME valid_time );
void SetSetSecrouteFreePass( bool bIsPremiumUser, int nRestSecond );
void SetAccountAuthority( int AuthorityType, int Duration );
// PK 관련
bool IsPKOn() { return m_bIsPK; }
void SetPKOn() { m_bIsPK = true; UpdateTitleConditionByPKOn( true ); }
void SetPKOff() { m_bIsPK = false; UpdateTitleConditionByPKOn( false ); }
bool IsPKOning() { return !!m_nTurnOnPkModeTime; }
bool IsPKOffing() { return !!m_nTurnOffPkModeTime; }
const c_fixed10 & GetImmoralPoint() const { return m_fImmoralPoint; }
void SetImmoralPoint( const c_fixed10 & fIP );
int GetPKC() { return m_nPKC; }
void IncPKC();
int GetDKC() { return m_nDKC; }
void IncDKC();
const bool IsBloodyCharacter() const { return ( m_fImmoralPoint >= GameRule::MORAL_LIMIT ); }
const bool IsDemoniacCharacter() const { return ( m_fImmoralPoint >= GameRule::CRIME_LIMIT ); }
const bool IsDungeonOriginalOwner() const;
const bool IsDungeonOriginalSieger() const;
bool IsInSecroute() const;
bool IsInForgotten() const;
bool IsInAncient() const;
bool IsInFloat() const;
bool IsInMoonTemple() const;
bool IsInChristmas() const;
virtual bool IsEnemy( StructCreature* pTarget, bool bIncludeHiding = false );
virtual bool IsAlly( StructCreature* pTarget );
virtual bool IsVisible( StructCreature *pTarget );
const bool IsInPKField() const;
const bool TurnOnPkMode( const bool bImmediateOn = false );
const bool TurnOffPkMode( const bool bImmediateOff = false );
// 스킬 관련
virtual int GetAllSkillTP() const;
virtual int IsLearnableSkill( int nSkillID, int nSkillLevel, int *nSkillTreeID );
void UpdateQuestStatusByItemEnhance( ItemBase::ItemCode code = 0 )
{
// 그닥 아름다운 방식은 아니지만 어차피 이벤트 없이는 그게 그거
// 당장 조금 예쁜 코드 짜기보다는 나중에 리팩토링할 생각을 합시다
m_QuestManager.UpdateQuestStatusByItemEnhance( &m_Inventory, code );
}
// 스크립트 관련
void UpdateQuestStatusByItemUpgrade();
void GetLastTownPosition( ArPosition * pPos ) const;
void StoreCurrentStatesOnEnterInstanceGame( bool bIncludeHPMP );
void GetPositionOnEnterInstanceGame( ArPosition * pPos ) const;
void RestoreStatesOnLeaveInstanceGame( bool bIncludeHPMP );
void OpenStorage( bool bStart = true );
void SetContactNPCHandle( AR_HANDLE handle ) { SetLastContact( "npc", handle ); }
AR_HANDLE GetContactNPCHandle() const { return GetLastContactLong( "npc" ); }
void SetNonNPCDialog( bool bNonNPCDialog ) { m_bNonNPCDialog = bNonNPCDialog; }
bool IsNonNPCDialog() { return m_bNonNPCDialog; }
void SetDialogTitle( const char *szString, int type = 0 );
std::string GetDialogTitle() const { return m_strDialogTitle; }
void SetDialogText( const char *szString );
void ClearDialogMenu();
void SetSpecialDialogMenu( const char * szString );
bool IsSpecialDialogMenu( const char * szString );
void ClearSpecialDialogMenu();
void SetFixedDialogTrigger( const char *szString );
bool IsFixedDialogTrigger( const char * szTrigger );
void ClearFixedDialogTrigger();
void AddDialogMenu( const char *szString, const char *szTrigger );
void AddTrigger( const char *szTrigger );
void SetTrigger( const char *szTrigger );
inline bool HasDialog() { return ( !m_strDialogTitle.empty() || !m_strDialogText.empty() ); }
const bool SetupQuestDialog( const QuestBase::QuestCode nQuestCode, const int nTextID, const int nDialogType = 0 );
void ShowDialog();
bool IsValidTrigger( const char *szTrigger );
void SetLastContactMarket( const char *szMarketName ) { SetLastContact( "market", szMarketName ); }
std::string GetLastContactMarket() const { return GetLastContactStr( "market" ); }
void PendWarp( int x, int y, unsigned char layer, int nInstanceDungeonType = -1, bool isForceWarp = false );
const unsigned short PendWarpToHuntaholicLobby( const int nHuntaholicID );
void PendWarpToDeathmatch( int instance_game_type );
void SetLastContact( const char * szKey, const char * szValue );
void SetLastContact( const char * szKey, int nValue );
std::string GetLastContactStr( const char * szKey ) const;
int GetLastContactLong( const char * szKey ) const;
// Time-related values (`int` in seconds, AR_TIME in 1/100 seconds)
int GetLoginDuration() const { return ( m_nLogoutTime ? ( ( m_nLogoutTime - m_nLoginTime ) / 100 ) : ( ( GetArTime() - m_nLoginTime ) / 100 ) ); }
AR_TIME GetLoginTime() const { return m_nLoginTime; }
AR_TIME GetLogoutTime() const { return m_nLogoutTime; }
int GetLoginCount() const { return m_nLoginCount; }
int GetTotalPlayTime() { return m_nTotalPlayTime + GetLoginDuration(); }
void SetTotalPlayTime( int nTotalPlayTime ) { m_nTotalPlayTime = nTotalPlayTime; }
AR_TIME GetLogoutTimer() const { return m_nLogoutTimer; }
void SetLogoutTimer( AR_TIME tm ) { m_nLogoutTimer = tm; }
// 프로퍼티 Set 이므로 프로퍼티 메시지 송신이 유발되며, 따라서 락이 잡힌 상태에서만 사용해야 함
void SetContinuousPlayTime( AR_TIME continuous_play_time );
const AR_TIME GetContinuousPlayTime() { return ( IsGameTimeLimited() ) ? m_nContinuousPlayTime : 0; }
void SetContinuousLogoutTime( AR_TIME continuous_logout_time ) { m_nContinuousLogoutTime = continuous_logout_time; }
const AR_TIME GetContinuousLogoutTime() { return ( IsGameTimeLimited() ) ? m_nContinuousLogoutTime : 0; }
void SetLastContinuousPlayTimeProcTime( AR_TIME last_playtime_proc_time ) { m_nLastContinuousPlayTimeProcTime = last_playtime_proc_time; }
const AR_TIME GetLastContinuousPlayTimeProcTime() { return ( IsGameTimeLimited() ) ? m_nLastContinuousPlayTimeProcTime : 0; }
// 호감도
void AddFavor( int favor_id, int favor );
void SetFavor( int favor_id, int favor, bool bDBJob = true );
int GetFavor( int favor_id ) const;
// DB 쿼리 관련
void DBQuery( struct GameDBManager::DBProc *pWork );
void onEndQuery();
// 전투 관련
virtual int onDamage( StructCreature * pFrom, Elemental::Type elementalType, DamageType damageType, int nDamage, bool bCritical );
void ProcImmoralPoint( StructPlayer * pKiller, int nChaos, bool bDecreaseProc = true );
// 대련 관련
const unsigned int GetCompeteID() const { return m_nCompeteID; }
void SetCompeteID( const unsigned int nCompeteID ) { m_nCompeteID = nCompeteID; SetNeedToBroadcastStatusFlag(); }
const bool IsCompeteDead() const { return m_StatusFlag.IsOn( STATUS_COMPETE_DEAD ); }
void SetCompeteDead( const bool bCompeteDead ) { m_StatusFlag.Set( STATUS_COMPETE_DEAD, bCompeteDead ); }
const bool IsInStartedCompete( const bool includeCounting ) const;
const bool ResurrectByCompete();
const bool ResurrectByDeathmatch();
// 배틀 아레나 관련
int GetBattleArenaID() const { return m_nArenaID; }
void SetBattleArenaID( const int nArenaID ) { m_nArenaID = nArenaID; }
unsigned char GetBattleArenaInstanceNo() const { return m_nArenaInstanceNo; }
void SetBattleArenaInstanceNo( const unsigned char nArenaInstanceNo ) { m_nArenaInstanceNo = nArenaInstanceNo; }
time_t GetBattleArenaBlockTime() const { return m_tArenaBlock; }
AR_TIME GetBattleArenaBlockTimeLeft() const { time_t t = time( NULL ); return ( m_tArenaBlock > t ) ? ( m_tArenaBlock - t ) * 100 : 0; }
void SetBattleArenaBlockTime( const time_t tArenaBlock ) { m_tArenaBlock = tArenaBlock; }
int GetBattleArenaPenaltyCount() const { return m_nArenaPenaltyCount; }
void SetBattleArenaPenaltyCount( const int nPenaltyCount ) { m_nArenaPenaltyCount = nPenaltyCount; }
time_t GetBattleArenaPenaltyDecTime() const { return ( m_nArenaPenaltyCount ) ? m_tArenaPenaltyDecrease : 0; }
void SetBattleArenaPenaltyDecTime( const time_t tPenaltyDec ) { m_tArenaPenaltyDecrease = tPenaltyDec; }
void IncBattleArenaPenalty();
int GetBattleArenaPoint() const { return m_nArenaPoint; }
void SetBattleArenaPoint( const int nArenaPoint ) { m_nArenaPoint = std::min( std::max( nArenaPoint, 0 ), GameRule::BATTLE_ARENA_MAX_OWNABLE_POINT ); SendPropertyMessage( this, GetHandle(), "ap", GetBattleArenaPoint() ); }
void AddBattleArenaPoint( const int nArenaPoint ) { SetBattleArenaPoint( GetBattleArenaPoint() + nArenaPoint ); }
int GetBattleArenaMVPCount() const { return m_nArenaMVPCount; }
void AddBattleArenaMVPCount() { ++m_nArenaMVPCount; }
int GetBattleArenaRecord( _BATTLE_ARENA_TYPE eType, bool bWin ) const { assert( eType >= 0 && eType < _countof( m_anArenaRecord ) ); return m_anArenaRecord[ eType ][ ( bWin ) ? 0 : 1 ]; }
void AddBattleArenaRecord( _BATTLE_ARENA_TYPE eType, bool bWin ) { assert( eType >= 0 && eType < _countof( m_anArenaRecord ) ); ++m_anArenaRecord[ eType ][ ( bWin ) ? 0 : 1 ]; }
// 오토 관련
bool IsAutoUsed() { return m_bAutoUsed; }
bool IsMoveReq() { return m_bMoveReq; }
void SetMoveReq( bool bMoveReq ) { m_bMoveReq = bMoveReq; }
void SetAutoUsed( bool AutoUsed = true) { m_bAutoUsed = AutoUsed; }
bool IsWarpEnded() { return m_bWarpEnded; }
void SetWarpEnded( bool WarpEnded = true ) { m_bWarpEnded = WarpEnded; }
int GetRegionUpdateNeedCount() const { return m_nRegionUpdateNeedCount; }
void IncRegionUpdateNeedCount() { InterlockedIncrement( &m_nRegionUpdateNeedCount ); }
void DecRegionUpdateNeedCount() { InterlockedDecrement( &m_nRegionUpdateNeedCount ); }
int GetInvalidScriptTriggerCount() const { return m_nInvalidScriptTriggerCount; }
void IncInvalidScriptTriggerCount() { InterlockedIncrement( &m_nInvalidScriptTriggerCount ); }
// 트레이드
bool IsTradableWith( StructPlayer * pTarget ) const;
void StartTrade( StructPlayer * pTarget );
bool IsTrading() const { return !!m_hTradeTarget; }
bool IsTradeFreezed() const { return m_bTradeFreezed; }
bool IsTradeConfirm() const { return m_bTradeAccepted; }
AR_HANDLE GetTradeTarget() const { return m_hTradeTarget; }
const StructGold GetTradeGold() const { return m_nTradeGold; }
bool AddItemToTradeWindow( StructItem * pItem, const __int64 & count );
bool ModifyItemCountInTradeWindow( StructItem * pItem, const __int64 & count );
bool RemoveItemFromTradeWindow( StructItem * pItem, const __int64 & count );
bool RemoveItemByQuittingDeathmatch();
void AddGoldToTradeWindow( const StructGold & gold );
void FreezeTrade();
void ConfirmTrade();
bool CheckTradeWeight();
bool CheckTradeItem();
bool ProcessTrade();
void CancelTrade( bool bIsNeedBroadcast = false );
bool ResurrectByPotion();
const bool ClearExpiredItem();
const bool ClearExpiredElementalEffect();
void AddToElementalEffectedItemList( StructItem * pItem );
void RemoveFromElementalEffectedItemList( StructItem * pItem );
int GetRideSpeedModifier() const { return m_nRideModifier; }
// PC방 프리미엄 서비스 용
void SetPCBangMode( char nPCBangMode );
char GetPCBangMode();
// 계정단위 이벤트 코드
void SetEventCode( int nEventCode ) { m_nEventCode = nEventCode; }
int GetEventCode() const { return m_nEventCode; }
// 로그인 시간과 보상 관련 (플레이 포인트, 시간제 이벤트)
void SetPlayTime( int nPlayTime ) { m_nPlayTime = nPlayTime; }
int GetPlayTime() { return m_nPlayTime; }
void AddPlayPoint( int nPoint ) { m_nPlayTimePoint += nPoint; }
int GetPlayPoint() const { return m_nPlayTimePoint; }
void SetPlayPoint( int nPoint ) { m_nPlayTimePoint = nPoint; }
void SetLastPlayTimeUpdateTime( AR_TIME t ) { m_nLastPlayTimeUpdateTime = t; }
AR_TIME GetLastPlayTimeUpdateTime() { return m_nLastPlayTimeUpdateTime; }
void SetLastTimeBasedEventTimeScript( AR_TIME t ) { m_nLastTimeBasedEventTimeScript = t; }
AR_TIME GetLastTimeBasedEventTimeScript() { return m_nLastTimeBasedEventTimeScript; }
void SetLastTimeBasedEventTimeDB( AR_TIME t ) { m_nLastTimeBasedEventTimeDB = t; }
AR_TIME GetLastTimeBasedEventTimeDB() { return m_nLastTimeBasedEventTimeDB; }
// 경매 관련
void SetNextAuctionUsableTime( AR_TIME t ) { m_nNextAuctionUsableTime = t; }
AR_TIME GetNextAuctionUsableTime() { return m_nNextAuctionUsableTime; }
// 게임 중독 시스템 용(유저 나이도 관련)
bool IsGameTimeLimited();
void SetAge( int nAge ) { m_nAge = nAge; }
const int GetAge() const { return m_nAge; }
// 이벤트 영역 진입 횟수 데이터
const int GetEventAreaEnterCount( const int nEventAreaID ) const;
void IncEventAreaEnterCount( const int nEventAreaID );
void SetEventAreaEnterCount( const int nEventAreaID, const int nEnterCount );
void InsertEventAreaID( const int nEventAreaID );
bool DeleteEventAreaID( const int nEventAreaID );
int GetInGameRX() const { return m_nRX; }
void SetInGameRX( int InGameRX ) { m_nRX = InGameRX; }
int GetInGameRY() const { return m_nRY; }
void SetInGameRY( int InGameRY ) { m_nRY = InGameRY; }
int GetInGameHX() const { return m_nHX; }
void SetInGameHX( int InGameHX ) { m_nHX = InGameHX; }
int GetInGameHY() const { return m_nHY; }
void SetInGameHY( int InGameHY ) { m_nHY = InGameHY; }
int GetArt() const { return nArt; }
int GetRtc() const { return nRtc; }
void SetArtRtc( int Art, int Rtc ) { nArt = Art; nRtc = Rtc; }
void AddTimePenalty( int cnt ) { nPenalty += cnt; }
// 이벤트용 전 월드 지속효과 부여 관련
struct EVENT_STATE
{
EVENT_STATE()
: eCode( static_cast< StructState::StateCode >( 0 ) )
, nLevel( 0 )
, nStateValue( 0 )
, strStateValue( "" )
{}
EVENT_STATE( const StructState::StateCode _eCode, const int _nLevel, const int _nStateValue, const char * _szStateValue )
: eCode( _eCode )
, nLevel( _nLevel )
, nStateValue( _nStateValue )
, strStateValue( _szStateValue )
{}
const bool operator ==( const EVENT_STATE & rhs ) const
{
return ( eCode == rhs.eCode && nLevel == rhs.nLevel && nStateValue == rhs.nStateValue && strStateValue == rhs.strStateValue );
}
StructState::StateCode eCode;
int nLevel;
int nStateValue;
std::string strStateValue;
};
// 이벤트용 전 월드 지속효과 부여 관련(지역 락, g_PlayerListLock 걸고 호출하면 안 됨)
static const bool AddEventState( const StructState::StateCode eCode, const int nLevel, const int nStateValue, const char * szStateValue );
static const bool RemoveEventState( const StructState::StateCode eCode );
static void ClearEventState();
static void GetEventStateList( std::vector< struct EVENT_STATE > & vList );
void ProcEventState();
// 크루 아이템을 이용한 지속효과로서 중첩 사용이 불가능하다.
const bool PendWorldState( const StructState::StateCode code, const int level, const AR_TIME time, const AR_TIME cooltime, const int itemcode );
const bool CastWorldState( const StructState::StateCode code, const int level, const AR_TIME time, const AR_TIME cooltime, const int itemcode );
// 크루 아이템을 이용한 지속효과로서 중첩 사용이 불가능하다. (파티원 용)
const bool PendPartyState(const StructState::StateCode code, const int level, const AR_TIME time, const AR_TIME cooltime, const int itemcode);
const bool CastPartyState(const StructState::StateCode code, const int level, const AR_TIME time, const AR_TIME cooltime, const int itemcode);
// 크루 아이템을 이용한 지속효과로서 중첩 사용이 불가능하다. (길드원 용)
const bool PendGuildState(const StructState::StateCode code, const int level, const AR_TIME time, const AR_TIME cooltime, const int itemcode);
const bool CastGuildState(const StructState::StateCode code, const int level, const AR_TIME time, const AR_TIME cooltime, const int itemcode);
//
const bool AddDungeonState();
const bool RemoveDungeonState();
// 기타 구현용
void SendCharacterInfo();
TimeSyncer m_TS;
struct IStreamSocketConnection* pConnection;
void SetAccount( const int nAccountID, const char *szAccount );
static ItemUID allocItemUID();
void SetSkinColor( DWORD skin_color ) { m_nSkinColor = skin_color; }
unsigned long GetSkinColor() const { return m_nSkinColor; }
void RequestSecurityNo( int nMode );
protected:
const bool clearExpiredItem( const std::vector< struct StructItem * > & vExpireItemList, bool bStorage );
virtual unsigned short putonItem( ItemBase::ItemWearType pos, struct StructItem * pItem ); // insert absolute position
virtual unsigned short putoffItem( ItemBase::ItemWearType pos ); // insert absolute position
void procDecreaseEXPAndDropItem( StructPlayer * pKiller, struct StructItem ** pDropWearItem, struct StructItem ** pDropInvenItem );
void addToBoothWatcher( StructPlayer * pWatcher );
void removeFromBoothWatcher( StructPlayer * pWatcher );
inline const bool isInLocationType( unsigned char nLocationType ) const;
private:
void setLocation( int idx ) { m_nWorldLocationId = idx; }
virtual const char* getClassName() { return "StructPlayer"; }
virtual void onProcess( int nThreadIdx );
virtual void onHPChange( int nPrevHP );
virtual void onMPChange( int nPrevMP );
virtual void onChangeProperty( const std::string & strKey, const char *data );
virtual void onBeforeChangeProperty( const std::string & strKey, const char *data );
virtual void onExpChange();
virtual void onEnergyChange();
virtual void onCantAttack( AR_HANDLE target, AR_TIME t );
virtual void onDead( StructCreature *pFrom, bool decreaseEXPOnDead = true );
virtual void onJobLevelUp();
virtual void onJPChange();
virtual void onRegisterSkill( int skill_uid, int skill_id, int skill_level, bool is_new_skill );
// 스킬 초기화 관련
virtual __int64 getJPAfterSkillReset() { return GetJobPoint() + GetAllSkillJP() + GetAllJobLevelJP(); }
virtual int getTPAfterSkillReset() { return GetTalentPoint() + GetAllSkillTP(); }
virtual void onResetSkill( const int jobDepth );
virtual void onRemoveSkill( StructSkill* removedSkill );
// 직업 초기화 관련
__int64 getJPAfterJobReset( int nTargetJobDepth );
// 전체 특성 포인트 중 기본으로 지급 받은 포인트를 제외한 특성 포인트만 남긴다.
// 다시 전직을 하면 지급을 받는다.
int getTPAfterJobReset( int nJobDepth ) { return m_nJobDepth >= GameRule::MIN_TALENT_POINT_JOB_DEPTH ? GetTalentPoint() - GameRule::DEFAULT_TALENT_POINT : GetTalentPoint(); }
void onBeforeResetJob() {};
void onAfterResetJob();
void onBeforeResetRace() {};
void onAfterResetRace();
virtual void procMoveSpeedChangement();
virtual void onAfterAddState( StructState & state );
virtual void onAfterRemoveState( StructState & state, const bool bByDead = false );
// 경험치 관련 루틴
void applyPenaltyByImmoralPoint( Experience& result );
void applyLimitBySummonLevel( Experience& result );
void applyPenaltyByGameTimeLimit( Experience& result );
const Experience getPCBangBonus( const Experience& input );
const Experience getStaminaBonus( const Experience& input, const __int64 gainExp, const bool forgotten = false );
const Experience getSuperSaveBonus( const Experience& input );
const Experience getPlayerKillerBonus(const Experience& input);
const Experience getInGameBonus( const Experience& input );
void distributeExpToSummons( const Experience& input, const __int64 summonStaminaSaveBonus );
void applyGameRuleLimit( Experience& result );
void openStorage();
void clearTradeInfo();
void broadcastBoothInfo();
void updateQuestStatus( StructQuest* pQuest );
void onStartQuest( StructQuest* pQuest );
void onEndQuest( StructQuest* pQuest );
void onDropQuest( StructQuest* pQuest );
void checkSummonEffectOnPlayer();
bool unSummon( struct StructSummon * pSummon );
void procPendingUnSummon();
bool unSummonPet( struct StructPet * pPet );
void procPendingUnSummonPet();
bool eraseItem( StructItem *pItem, const __int64 & count );
struct StructItem* popItem( struct StructItem *pItem, const __int64 & count = 1, bool bSkipUpdateItemToDB = false );
const bool procAutoRecover();
void onStandUp();
bool m_bDeadDialogProc;
bool m_bIsLogin;
bool m_bHasLogined;
AR_HANDLE m_hHandle;
AR_HANDLE m_hTamingTarget;
int m_nGuildPoint;
int m_nGuildTotalPoint;
// DB 에 있는 값들
char m_szAccountName[GameRule::MAX_ACCOUNT_LEN + 1];
int m_nAccountID;
int m_nChatBlockTime;
int m_nPermission;
int m_nHuntaholicPoint;
int m_nHuntaholicEnterableCount;
int m_nEtherealStoneDurability;
time_t m_tNextHuntaholicEnterableCountRefill;
StructGold m_nGold;
PlayerUID m_nUID;
char m_szName[31];
int m_nPartyID;
bool m_bItemPriority;
int m_nPrevPartyBroadcastedHP;
int m_nPrevPartyBroadcastedMP;
int m_nGuildId;
int m_nPrevGuildId;
char m_nGuildPermission;
int m_nSex;
int m_nTalentPoint;
int m_nCharisma;
int m_nLoginCount;
unsigned long m_nSkinColor;
int m_nBaseModelId[5];
int m_nFaceTextureId;
int m_nHairColorIndex;
unsigned int m_nHairColorRGB;
unsigned int m_nHideEquipFlag;
std::string m_strClientInfo;
std::string m_strQuickSlot;
std::string m_strCurrentKey;
std::string m_strSavedKey;
AR_TIME m_nLastGlobalChatTime;
AR_TIME m_nNextChatPenaltyDecreaseTime;
int m_nChatPenalty;
std::string m_strLastGlobalChat;
time_t m_nLastAdvChatTime;
int m_nAdvChatCount;
volatile LONG m_nNameChanged;
bool m_bAutoUsed;
time_t m_tGuildBlockTime;
bool m_bMoveReq;
bool m_bWarpEnded;
volatile LONG m_nRegionUpdateNeedCount;
AR_HANDLE m_hTarget; // 플레이어가 타게팅 하고 있는 Creature Handle
unsigned int m_nCompeteID;
int m_nArenaID;
unsigned char m_nArenaInstanceNo;
time_t m_tArenaBlock;
int m_nArenaPenaltyCount;
time_t m_tArenaPenaltyDecrease;
int m_nArenaPoint;
int m_nArenaMVPCount;
int m_anArenaRecord[ 3 /* _BATTLE_ARENA_TYPE */ ][ 2 /* win, lose */ ];
int m_nTotalPlayTime;
bool m_bUseAlias;
char m_szAlias[ 31 ];
int m_nCharacterChecksum;
struct PendedWorldState // 월드 버프는 락 문제로 비동기적으로 검, 현재 서버에는 비동기 관련 작업을 할 기반 자체가 없으므로 일단 우회
{
int itemcode;
int code;
int level;
int time;
int cooltime;
};
std::vector< PendedWorldState > m_vPendedWorldStateList;
std::vector< PendedWorldState > m_vPendedPartyStateList;
std::vector< PendedWorldState > m_vPendedGuildStateList;
// 워프 관련
AR_UNIT m_nPendWarpX, m_nPendWarpY;
unsigned char m_nPendWarpLayer;
int m_nPendWarpInstanceDungeonType;
bool m_bForceWarp; // 강제 워프에 사용 (true면 여러가지 입장 검사 안 함)
int m_nJobDepth;
AR_TIME m_nWarpEndTime;
AR_TIME m_nLoginTime;
AR_TIME m_nLogoutTime;
AR_TIME m_nLastCantAttackTime;
AR_TIME m_nLastSaveTime;
AR_TIME m_nLastExpSaveTime;
AR_TIME m_nLastProcessTime;
AR_TIME m_nLogoutTimer;
AR_TIME m_nLastLogoutRequestedTime; // 로비로 돌아가기/로그아웃 요청 시각(TS_CS_LOGOUT / TS_CS_RETURN_LOBBY 수신 시 검증 용)
AR_TIME m_nContinuousPlayTime; // _CONNECTION_TAG::nContinuousPlayTime을 플레이어에 보관 해두는 변수
AR_TIME m_nContinuousLogoutTime; // _CONNECTION_TAG::nContinuousLogoutTime을 플레이어에 보관 해두는 변수
AR_TIME m_nLastContinuousPlayTimeProcTime; // 위의 변수 2개를 처리하기 위한 타이머
// 노점
BOOTH_STATUS m_BoothStatus;
std::string m_strBoothName;
std::vector< BOOTH_ITEM_INFO > m_vBoothItem;
std::vector< StructPlayer * > m_vBoothWatcher;
StructPlayer* m_pBoothOpener;
bool m_bIsSitDown;
bool m_bIsBattleMode;
bool m_bStaminaSave;
bool m_bSuperSave;
enum _SUMMON_STAMINA_SAVE_TYPE
{
SUMMON_STAMINA_SAVE_WITHOUT_PENALTY = -1,
SUMMON_STAMINA_SAVE_NONE = 0,
SUMMON_STAMINA_SAVE_1X = 1,
SUMMON_STAMINA_SAVE_2X = 2,
SUMMON_STAMINA_SAVE_3X = 3,
SUMMON_STAMINA_SAVE_4X = 4,
};
_SUMMON_STAMINA_SAVE_TYPE m_eSummonStaminaSaveType;
bool m_bWalk;
// 트레이드
struct TradeItemInfo
{
TradeItemInfo( AR_HANDLE hItem, __int64 nCount )
: m_hItem( hItem )
, m_nCount( nCount )
{
}
AR_HANDLE m_hItem;
__int64 m_nCount;
};
bool m_bTradeFreezed;
bool m_bTradeAccepted;
StructGold m_nTradeGold;
std::vector< TradeItemInfo > m_vTradeItemList;
AR_HANDLE m_hTradeTarget;
unsigned short processTradeGold();
unsigned short processTradeItem();
// 퀘스트
int m_nLastAcceptQuest;
StructQuestManager m_QuestManager;
// 호칭
StructTitleManager m_TitleManager;
// 인벤토리
StructInventory m_Inventory;
StructInventory m_Storage;
AR_TIME m_nLastInvenArrangedTime;
AR_TIME m_nLastStorageArrangedTime;
AR_TIME m_nItemCoolTime[ ItemBase::MAX_COOLTIME_GROUP ];
std::vector< StructItem * > m_vCharmList;
std::vector< StructItem * > m_vElementalEffectedItem;
// 창고
volatile int m_nIsUsingStorage;
ItemUID m_nStorageGoldItemID;
volatile bool m_bIsStorageRequested;
volatile bool m_bIsStorageLoaded;
StructGold m_nStorageGold;
virtual void onAdd( struct StructInventory* pInventory, struct StructItem* pItem, bool bSkipUpdateItemToDB = false );
virtual void onRemove( struct StructInventory* pInventory, struct StructItem* pItem, bool bSkipUpdateItemToDB = false );
virtual void onChangeCount( struct StructInventory* pInventory, struct StructItem* pItem, bool bSkipUpdateItemToDB = false );
// 퀘스트
virtual void onProgressChanged( struct StructQuest *pQuest, QuestInstance::QUEST_PROGRESS oldProgress, QuestInstance::QUEST_PROGRESS newProgress );
virtual void onStatusChanged( struct StructQuest *pQuest );
void setSummonUpdate();
// 호칭 핸들러
virtual bool isReadInfoComplete() { return IsReadInfoComplete(); }
virtual void onTitleAchieved( StructTitle * pTitle );
virtual void onTitleOpened( StructTitle * pTitle );
// 이하 핸들러는 빈번한 변경이 발생할 수 있으므로 DB Query를 즉시 요청하지 않는다.
virtual void onTitleBookmarked( StructTitle * pTitle );
virtual void onConditionChanged( struct TitleConditionType * pCondition, const __int64 nCount );
int m_nWorldLocationId;
const struct StructWorldLocation * m_pWorldLocation;
// 피케이 관련
c_fixed10 m_fImmoralPoint;
int m_nPKC;
int m_nDKC;
bool m_bIsPK;
AR_TIME m_nTurnOnPkModeTime;
AR_TIME m_nTurnOffPkModeTime;
// 혼돈 관련 파라미터
int m_nMaxChaos;
int m_nChaos;
// 피로도 관련 파라미터
int m_nMaxStamina;
int m_nStamina;
int m_nStaminaRegenRate;
bool m_bUsingTent;
int m_nStaminaRegenBonus;
int m_nLogoutDuration; // 로그아웃 기간(분 단위)
// 가이아 상인 멤버쉽
bool m_bIsGaiaMember;
AR_TIME m_nGaiaValidTime;
// PC방 프리미엄 관련
char m_nPCBangMode;
// 계정단위 이벤트 코드
int m_nEventCode;
// 로그인 시간과 보상 관련 (플레이 포인트, 시간제 이벤트)
int m_nPlayTime;
AR_TIME m_nLastPlayTimeUpdateTime;
AR_TIME m_nLastTimeBasedEventTimeScript;
AR_TIME m_nLastTimeBasedEventTimeDB;
// 경매 관련
AR_TIME m_nNextAuctionUsableTime; // 경매에서 다음 처리 요청 가능한 시각(경매 동작 반복 시간 제한을 두기 위함)
// 게임 중독 방지 시스템 관련(유저 나이)
int m_nAge;
int m_nLastMin;
// 메신저 관련
std::vector< std::string > m_vFriend;
std::vector< std::string > m_vFriendOf;
std::vector< std::string > m_vDenial;
std::vector< std::string > m_vDenialOf;
// 소환수
std::vector< struct StructSummon* > m_vSummonList;
std::vector< struct StructSummon* > m_vStorageSummonList;
struct StructItem* m_aBindSummonCard[ 6 ];
struct StructItem* m_aBeltSlotCard[ 8 ];
int m_nBeltSlotMax;
float m_fBeltSlotAmp;
bool m_bIsSummonable;
bool m_bIsInfiniteSummonTime;
struct StructSummon* m_pMainSummon;
struct StructSummon* m_pSubSummon;
AR_TIME m_nDoubleSummonTime;
AR_TIME m_nNextUnSummonTime;
AR_TIME m_nLastBindSummonUpdateTime;
int m_nNameChangeTarget;
volatile LONG m_nPendingUnSummon;
enum PENDING_UNSUMMON_TYPE
{
UNSUMMON_MAIN = 1,
UNSUMMON_SUB = 2,
};
// 소환수 농장 관련
FARMED_SUMMON_INFO * m_vFarmedSummonInfo[GameRule::FARM_MAX_COUNT];
// 펫
XCriticalSection m_csPet; // 지역락 걸린 상태에서 사용해야 함
std::vector< struct StructPet * > m_vPetList;
std::vector< struct StructPet * > m_vStoragePetList;
std::vector< struct StructPet * > m_vPendingUnSummonPetList;
struct StructPet * m_pSummonedPet;
// 호칭
TitleBaseServer * m_pMainTitle;
TitleBaseServer * m_pSubTitle[5];
AR_TIME m_tRemainTitleTime;
AR_TIME m_nLastStaminaUpdateTime;
std::vector< struct StructSkill * > m_vSummonPassiveSkillList;
std::vector< struct StructSkill * > m_vAmplifySummonPassiveSkillList;
float m_fActiveSummonExpAmp;
float m_fDeactiveSummonExpAmp;
float m_fPassDamageRatio;
// 아이템 성능에 의한 스텟 계산시 보정치
int m_nRideModifier;
int m_nSpeedModifier;
int m_nMaxWeightModifier;
// 자동 회복 기능 관련
enum _RECOVER_TYPE
{
RECOVER_TYPE_HP = 1,
RECOVER_TYPE_MP = 2,
};
struct AUTO_RECOVER_INFO
{
AUTO_RECOVER_INFO( const _RECOVER_TYPE & eRecoverType, const c_fixed10 & fCondition, const c_fixed10 & fRecoverTo, const AR_HANDLE hItem, const int nOrderIndex )
: m_eRecoverType( eRecoverType )
, m_fCondition( fCondition )
, m_fRecoverTo( fRecoverTo )
, m_hItem( hItem )
, m_nOrderIndex( nOrderIndex )
{}
_RECOVER_TYPE m_eRecoverType;
c_fixed10 m_fCondition;
c_fixed10 m_fRecoverTo;
AR_HANDLE m_hItem;
int m_nOrderIndex;
};
std::vector< AUTO_RECOVER_INFO > m_vAutoRecoverInfo;
static const bool _AutoRecoverInfoArrangeItemPositionPreceder( const AUTO_RECOVER_INFO & lhs, const AUTO_RECOVER_INFO & rhs )
{
return lhs.m_nOrderIndex < rhs.m_nOrderIndex;
}
enum
{
MOUNT_NOTHING = 0,
MOUNT_ON_MAIN = 1,
MOUNT_ON_SUB = 2,
};
StructState::StateCode m_nRidingStateCode;
int m_nRideIdx; // 어떤 소환수에 Ride했는지.
bool m_bUseFasterSpeedInRiding; // 라이딩 시 기본 이속이 더 빠르면 기본 이속으로 적용해줄 것인지 여부
std::vector< FAVOR_INFO > m_vFavorInfo;
// 이벤트 영역 관련 데이터(대개 Lua 스크립트와 연결되므로 지역 락에 의해 보호함)
KHash< int, hashPr_mod_int > m_hsEventAreaEnterCount;
std::set< int > m_stEventAreaID;
// m_vEventState를 보호(지역 락 -> m_csEventState 순서여야 함)
static XCriticalSection s_csEventState;
static std::vector< EVENT_STATE > s_vEventState;
// 이하 구현을 위한 것들
int m_nPlayerListIndex;
int m_nReturnLobbyConnId;
// 스크립트
int m_nDialogType;
std::string m_strDialogTitle;
std::string m_strDialogText;
std::string m_strDialogMenu;
std::string m_strSpecialDialogMenu;
std::string m_strFixedDialogTrigger;
bool m_bNonNPCDialog;
volatile LONG m_nInvalidScriptTriggerCount;
// 플레이어 변수
mutable XCriticalSection m_csHash;
KHash< std::string, hashPr_string_nocase > m_hsValue;
// 플레이어 변수 - 계정 데이터
mutable XCriticalSection m_csHashAccount;
KHash< std::string, hashPr_string_nocase > m_hsValueAccount;
// 최근 contact 한 상점이름
//std::string m_strLastContactMarket;
KHash< std::string, hashPr_string_nocase > m_hsContact;
// 플레이어 이름 - UID 저장용 캐쉬(타 매니저에서 PlayerUID만 가지고있고 플레이어 이름을 중복해서 보관하지 않고 아래의 함수를 통해 얻어서 사용하도록 함)
static XCriticalSection s_csPlayerName;
static KHash< std::string *, hashPr_mod_basic< PlayerUID > > s_hsPlayerName;
StructPlayer( AR_HANDLE handle );
virtual ~StructPlayer();
friend struct DB_Login;
friend struct DB_UpdateCharacter;
friend struct DB_CreateCharacter;
friend struct DB_ReadStorageList;
friend struct DB_ChangeCharacterName;
friend struct PlayerDeleter;
// ArScheduler 에서 StructPlayer 를 지우기 위해 존재함.
// alloc/free 메커니즘에 관한 확실한 이해 전에는 수정 말것!
virtual bool ProcDelete();
virtual bool IsDeleteable();
// DB 관련
XCriticalSection m_bQueryLock;
std::list< struct GameDBManager::DBProc* > m_lQueryList;
// pc방, 스테미너 등 경험치 획득 방송이후에 추가 방송이 필요한 부분 관련
enum BONUS_TYPE
{
BONUS_PCBANG = 0,
BONUS_STAMINA = 1,
BONUS_PREMIUM_PCBANG = 2,
BONUS_SUMMON_STAMINA = 3,
BONUS_SUPER_SAVE = 4, // 성장의 물약(구 슈퍼 세이버)
BONUS_IN_GAME = 5, // 게임 내부 요인에 의한 보너스
MAX_BONUS_TYPE // 마지막 보너스 인덱스보다 1 크게 되므로 개수로 쓰면 됨
};
TS_SC_BONUS_EXP_JP::BONUS_INFO m_pBonusInfo[ MAX_BONUS_TYPE ];
inline void setBonusMsg( BONUS_TYPE BonusType, int nBonusRateAsPercent, __int64 nBounsExp, __int64 nBonusJp )
{
m_pBonusInfo[ BonusType ].type = BonusType;
m_pBonusInfo[ BonusType ].rate = nBonusRateAsPercent;
m_pBonusInfo[ BonusType ].exp = nBounsExp;
m_pBonusInfo[ BonusType ].jp = nBonusJp;
}
inline void clearPendingBonusMsg() {
// exp가 -1 이면 보너스 없는 거3~
for( int i = 0 ; i < MAX_BONUS_TYPE ; i++ )
{
m_pBonusInfo[i].exp = -1;
m_pBonusInfo[i].jp = -1;
}
}
void sendBonusExpJpMsg();
int m_nPlayTimePoint;
int m_nRX;
int m_nRY;
int m_nHX;
int m_nHY;
int nArt;
int nRtc;
int nPenalty;
// 스탯 관련 함수 및 변수들을 아래에 정리
private:
// --- 스탯 및 능력치 연산에 관련된 패시브 스킬들 적용하는 루틴 ---
virtual void applyPassiveSkillEffect( struct StructSkill * pSkill );
// --- 스탯 및 능력치 연산에 관련된 지속 효과들 적용하는 루틴 ---
virtual void applyState( StructState & state );
virtual void applyStatByState();
// --- 기타 예외적인 처리 ---
virtual void applyJobLevelBonus();
// --- 스탯 및 능력치 연산에 관련된 아이템 효과를 적용하는 루틴 ---
virtual void _applyEffectForState( const EffectInfo * pEffect );
virtual void onItemWearEffect( struct StructItem* pItem, bool bIsBaseVar, int type, c_fixed10 var1, c_fixed10 var2, float fItemRatio );
// --- 스탯 및 능력치 연산에 관련된 호칭 효과를 적용하는 루틴 ---
virtual void applyStatByTitle();
virtual void amplifyStatByTitle();
virtual void applyTitleEffect();
// --- 이하 핸들러들 ---
virtual void onBeforeCalculateStat();
virtual void onApplyStat();
virtual void onAfterCalculateAttributeByStat();
virtual void onModifyStatAndAttribute();
virtual void onCompleteCalculateStat();
void onModifyParameterForSummon();
void _applyCharm( const int type, const c_fixed10 & var1, const c_fixed10 & var2, struct StructItem * pItem );
void applyCharm( struct StructItem * pItem );
// party matching
public:
inline CPartyMatching* GetPartyMatching()
{
return m_party_matching;
}
inline void SetPartyMatching(CPartyMatching* pPartyMatching)
{
m_party_matching = pPartyMatching;
}
inline void SetPartyMatchingLeaderName(const char* name)
{
m_party_matching_leader_name = name;
}
inline std::string& GetPartyMatchingLeaderName()
{
return m_party_matching_leader_name;
}
private:
CPartyMatching* m_party_matching;
std::string m_party_matching_leader_name;
};
struct _CONNECTION_TAG
{
_CONNECTION_TAG( const char *_szAccountName )
: pPlayer( NULL )
, nAccountID( 0 )
, nVersion( -1 )
, nLastReadTime( GetArTime() )
, bAuthByAuthServer( false )
, nPCBangMode( 0 )
, nEventCode( 0 )
, nAge( 0 )
, nAgeLimitFlags( 0 )
, nContinuousPlayTime( 0 )
, nContinuousLogoutTime( 0 )
, nLastContinuousPlayTimeProcTime( GetArTime() )
, nConnId( 0 )
, pSecuritySolutionBuffer( NULL )
, bStorageSecurityCheck( false )
{
s_strcpy( szAccountName, _countof( szAccountName ), _szAccountName );
}
char szAccountName[GameRule::MAX_ACCOUNT_LEN + 1];
std::vector< std::string > vCharacterNameList;
StructPlayer* pPlayer;
int nAccountID;
int nVersion;
AR_TIME nLastReadTime;
bool bAuthByAuthServer; // Temporary
char nPCBangMode;
int nEventCode;
int nAge;
int nAgeLimitFlags;
AR_TIME nContinuousPlayTime;
AR_TIME nContinuousLogoutTime;
AR_TIME nLastContinuousPlayTimeProcTime;
int nConnId;
std::string strNameToDelete;
bool bStorageSecurityCheck;
void * pSecuritySolutionBuffer;
};