2018-03-02 07:22:25 -03:00
# include <boost/make_shared.hpp>
2018-03-06 22:22:19 +01:00
# include <Common.h>
# include <Util/Util.h>
# include <Util/UtilMath.h>
# include <Logging/Logger.h>
# include <Exd/ExdDataGenerated.h>
# include <Network/PacketContainer.h>
2018-06-23 21:38:04 +02:00
# include <Network/CommonActorControl.h>
2018-07-21 23:32:10 +10:00
# include <Network/PacketWrappers/EffectPacket.h>
2017-12-08 15:38:25 +01:00
# include "Session.h"
2017-08-08 13:53:47 +02:00
# include "Player.h"
2018-01-27 23:52:49 +01:00
# include "Zone/TerritoryMgr.h"
2017-12-08 15:38:25 +01:00
# include "Zone/Zone.h"
2018-03-02 07:22:25 -03:00
# include "Zone/ZonePosition.h"
2017-12-08 15:38:25 +01:00
# include "Network/GameConnection.h"
# include "Network/PacketWrappers/ActorControlPacket142.h"
# include "Network/PacketWrappers/ActorControlPacket143.h"
2018-02-18 01:50:20 +01:00
# include "Network/PacketWrappers/ActorControlPacket144.h"
2017-12-08 15:38:25 +01:00
# include "Network/PacketWrappers/InitUIPacket.h"
# include "Network/PacketWrappers/ServerNoticePacket.h"
# include "Network/PacketWrappers/ChatPacket.h"
# include "Network/PacketWrappers/ModelEquipPacket.h"
# include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
# include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
# include "Network/PacketWrappers/PlayerSpawnPacket.h"
2018-03-02 07:22:25 -03:00
# include "Script/ScriptMgr.h"
2017-12-08 15:38:25 +01:00
# include "Action/Action.h"
2018-03-06 00:10:36 +01:00
# include "Action/ActionTeleport.h"
2017-12-08 15:38:25 +01:00
# include "Action/EventAction.h"
# include "Action/EventItemAction.h"
2018-03-02 07:22:25 -03:00
2017-12-08 15:38:25 +01:00
# include "Math/CalcStats.h"
# include "Math/CalcBattle.h"
2017-08-08 13:53:47 +02:00
2018-03-02 07:22:25 -03:00
# include "ServerZone.h"
# include "Framework.h"
2018-03-09 00:06:44 +01:00
extern Core : : Framework g_fw ;
2017-08-08 13:53:47 +02:00
using namespace Core : : Common ;
using namespace Core : : Network : : Packets ;
using namespace Core : : Network : : Packets : : Server ;
2018-06-23 21:38:04 +02:00
using namespace Core : : Network : : ActorControl ;
2017-08-08 13:53:47 +02:00
2018-07-24 23:58:08 +02:00
using InventoryMap = std : : map < uint16_t , Core : : ItemContainerPtr > ;
using InvSlotPair = std : : pair < uint16_t , int8_t > ;
using InvSlotPairVec = std : : vector < InvSlotPair > ;
2017-08-08 13:53:47 +02:00
// player constructor
Core : : Entity : : Player : : Player ( ) :
2018-08-29 21:40:59 +02:00
Chara ( ObjKind : : Player ) ,
m_lastWrite ( 0 ) ,
m_lastPing ( 0 ) ,
m_bIsLogin ( false ) ,
m_contentId ( 0 ) ,
m_modelMainWeapon ( 0 ) ,
m_modelSubWeapon ( 0 ) ,
m_homePoint ( 0 ) ,
m_startTown ( 0 ) ,
m_townWarpFstFlags ( 0 ) ,
m_playTime ( 0 ) ,
m_bInCombat ( false ) ,
m_bLoadingComplete ( false ) ,
m_bMarkedForZoning ( false ) ,
m_zoningType ( Common : : ZoneingType : : None ) ,
m_bAutoattack ( false ) ,
m_markedForRemoval ( false ) ,
m_mount ( 0 ) ,
m_emoteMode ( 0 ) ,
m_directorInitialized ( false ) ,
m_onEnterEventDone ( false )
{
m_id = 0 ;
m_currentStance = Stance : : Passive ;
m_onlineStatus = 0 ;
m_queuedZoneing = nullptr ;
m_status = ActorStatus : : Idle ;
m_invincibilityType = InvincibilityType : : InvincibilityNone ;
memset ( m_questTracking , 0 , sizeof ( m_questTracking ) ) ;
memset ( m_name , 0 , sizeof ( m_name ) ) ;
memset ( m_stateFlags , 0 , sizeof ( m_stateFlags ) ) ;
memset ( m_searchMessage , 0 , sizeof ( m_searchMessage ) ) ;
memset ( m_classArray , 0 , sizeof ( m_classArray ) ) ;
memset ( m_expArray , 0 , sizeof ( m_expArray ) ) ;
m_objSpawnIndexAllocator . init ( MAX_DISPLAYED_EOBJS ) ;
m_actorSpawnIndexAllocator . init ( MAX_DISPLAYED_ACTORS , true ) ;
2017-08-08 13:53:47 +02:00
}
Core : : Entity : : Player : : ~ Player ( )
{
}
2018-03-05 22:10:14 +11:00
void Core : : Entity : : Player : : injectPacket ( std : : string path )
{
2018-08-29 21:40:59 +02:00
auto pServerZone = g_fw . get < ServerZone > ( ) ;
auto session = pServerZone - > getSession ( getId ( ) ) ;
if ( session )
session - > getZoneConnection ( ) - > injectPacket ( path , * this ) ;
2018-03-05 22:10:14 +11:00
}
2017-08-08 13:53:47 +02:00
// TODO: add a proper calculation based on race / job / level / gear
uint32_t Core : : Entity : : Player : : getMaxHp ( )
{
2018-08-29 21:40:59 +02:00
return m_baseStats . max_hp ;
2017-08-08 13:53:47 +02:00
}
uint32_t Core : : Entity : : Player : : getMaxMp ( )
{
2018-08-29 21:40:59 +02:00
return m_baseStats . max_mp ;
2017-08-08 13:53:47 +02:00
}
uint16_t Core : : Entity : : Player : : getZoneId ( ) const
{
2018-08-29 21:40:59 +02:00
return m_zoneId ;
2017-08-08 13:53:47 +02:00
}
2017-09-11 18:59:50 +02:00
uint8_t Core : : Entity : : Player : : getGmRank ( ) const
{
2018-08-29 21:40:59 +02:00
return m_gmRank ;
2017-09-11 18:59:50 +02:00
}
void Core : : Entity : : Player : : setGmRank ( uint8_t rank )
{
2018-08-29 21:40:59 +02:00
m_gmRank = rank ;
2017-09-11 18:59:50 +02:00
}
2018-04-18 21:00:20 +10:00
bool Core : : Entity : : Player : : getGmInvis ( ) const
{
2018-08-29 21:40:59 +02:00
return m_gmInvis ;
2018-04-18 21:00:20 +10:00
}
void Core : : Entity : : Player : : setGmInvis ( bool invis )
{
2018-08-29 21:40:59 +02:00
m_gmInvis = invis ;
2018-04-18 21:00:20 +10:00
}
2018-07-02 07:31:23 +10:00
bool Core : : Entity : : Player : : isActingAsGm ( ) const
2018-07-01 21:31:49 +10:00
{
2018-08-29 21:40:59 +02:00
auto status = getOnlineStatus ( ) ;
return status = = OnlineStatus : : GameMaster | | status = = OnlineStatus : : GameMaster1 | |
status = = OnlineStatus : : GameMaster2 ;
2018-07-01 21:31:49 +10:00
}
2017-08-08 13:53:47 +02:00
uint8_t Core : : Entity : : Player : : getMode ( ) const
{
2018-08-29 21:40:59 +02:00
return m_mode ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setMode ( uint8_t mode )
{
2018-08-29 21:40:59 +02:00
m_mode = mode ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getStartTown ( ) const
{
2018-08-29 21:40:59 +02:00
return m_startTown ;
2017-08-08 13:53:47 +02:00
}
2017-11-14 23:55:38 +01:00
void Core : : Entity : : Player : : setMarkedForRemoval ( )
{
2018-08-29 21:40:59 +02:00
m_markedForRemoval = true ;
2017-11-14 23:55:38 +01:00
}
bool Core : : Entity : : Player : : isMarkedForRemoval ( ) const
{
2018-08-29 21:40:59 +02:00
return m_markedForRemoval ;
2017-11-14 23:55:38 +01:00
}
2018-07-02 07:31:23 +10:00
Core : : Common : : OnlineStatus Core : : Entity : : Player : : getOnlineStatus ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
if ( ! pExdData )
return OnlineStatus : : Online ;
2018-04-18 21:00:20 +10:00
2018-08-29 21:40:59 +02:00
uint32_t statusDisplayOrder = 0xFF14 ;
uint32_t applicableStatus = static_cast < uint32_t > ( OnlineStatus : : Online ) ;
2018-04-19 23:04:31 +10:00
2018-08-29 21:40:59 +02:00
for ( uint32_t i = 0 ; i < std : : numeric_limits < decltype ( m_onlineStatus ) > : : digits ; i + + )
{
bool bit = ( m_onlineStatus > > i ) & 1 ;
2018-04-18 21:00:20 +10:00
2018-08-29 21:40:59 +02:00
if ( ! bit )
continue ;
2018-04-18 21:00:20 +10:00
2018-08-29 21:40:59 +02:00
auto pOnlineStatus = pExdData - > get < Data : : OnlineStatus > ( i ) ;
if ( ! pOnlineStatus )
continue ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( pOnlineStatus - > priority < statusDisplayOrder )
{
// todo: also check that the status can actually be set here, otherwise we need to ignore it (and ban the player obv)
statusDisplayOrder = pOnlineStatus - > priority ;
applicableStatus = i ;
}
}
2018-04-24 20:34:36 +10:00
2018-08-29 21:40:59 +02:00
return static_cast < OnlineStatus > ( applicableStatus ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setOnlineStatusMask ( uint64_t status )
{
2018-08-29 21:40:59 +02:00
m_onlineStatus = status ;
2017-08-08 13:53:47 +02:00
}
uint64_t Core : : Entity : : Player : : getOnlineStatusMask ( ) const
{
2018-08-29 21:40:59 +02:00
return m_onlineStatus ;
2017-08-08 13:53:47 +02:00
}
2017-08-30 23:08:10 +02:00
void Core : : Entity : : Player : : prepareZoning ( uint16_t targetZone , bool fadeOut , uint8_t fadeOutTime , uint16_t animation )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto preparePacket = makeZonePacket < FFXIVIpcPrepareZoning > ( getId ( ) ) ;
preparePacket - > data ( ) . targetZone = targetZone ;
preparePacket - > data ( ) . fadeOutTime = fadeOutTime ;
preparePacket - > data ( ) . animation = animation ;
preparePacket - > data ( ) . fadeOut = static_cast < uint8_t > ( fadeOut ? 1 : 0 ) ;
queuePacket ( preparePacket ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : calculateStats ( )
{
2018-08-29 21:40:59 +02:00
uint8_t tribe = getLookAt ( Common : : CharaLook : : Tribe ) ;
uint8_t level = getLevel ( ) ;
uint8_t job = static_cast < uint8_t > ( getClass ( ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
2018-03-09 00:06:44 +01:00
2018-08-29 21:40:59 +02:00
auto classInfo = pExdData - > get < Core : : Data : : ClassJob > ( job ) ;
auto tribeInfo = pExdData - > get < Core : : Data : : Tribe > ( tribe ) ;
auto paramGrowthInfo = pExdData - > get < Core : : Data : : ParamGrow > ( level ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
// TODO: put formula somewhere else...
float base = Math : : CalcStats : : calculateBaseStat ( getAsPlayer ( ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_baseStats . str = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > modifierStrength ) / 100 ) +
tribeInfo - > sTR ) ;
m_baseStats . dex = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > modifierDexterity ) / 100 ) +
tribeInfo - > dEX ) ;
m_baseStats . vit = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > modifierVitality ) / 100 ) +
tribeInfo - > vIT ) ;
m_baseStats . inte = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > modifierIntelligence ) / 100 ) +
tribeInfo - > iNT ) ;
m_baseStats . mnd = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > modifierMind ) / 100 ) +
tribeInfo - > mND ) ;
m_baseStats . pie = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > modifierPiety ) / 100 ) +
tribeInfo - > pIE ) ;
2018-01-31 11:43:22 +01:00
2018-08-29 21:40:59 +02:00
m_baseStats . skillSpeed = paramGrowthInfo - > baseSpeed ;
m_baseStats . spellSpeed = paramGrowthInfo - > baseSpeed ;
m_baseStats . accuracy = paramGrowthInfo - > baseSpeed ;
m_baseStats . critHitRate = paramGrowthInfo - > baseSpeed ;
m_baseStats . attackPotMagic = paramGrowthInfo - > baseSpeed ;
m_baseStats . healingPotMagic = paramGrowthInfo - > baseSpeed ;
m_baseStats . tenacity = paramGrowthInfo - > baseSpeed ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_baseStats . max_mp = Math : : CalcStats : : calculateMaxMp ( getAsPlayer ( ) ) ;
2017-08-19 11:28:04 +09:00
2018-08-29 21:40:59 +02:00
m_baseStats . max_hp = Math : : CalcStats : : calculateMaxHp ( getAsPlayer ( ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( m_mp > m_baseStats . max_mp )
m_mp = m_baseStats . max_mp ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( m_hp > m_baseStats . max_hp )
m_hp = m_baseStats . max_hp ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_baseStats . determination = static_cast < uint32_t > ( base ) ;
2017-08-08 13:53:47 +02:00
}
2018-02-20 22:46:44 +01:00
void Core : : Entity : : Player : : setAutoattack ( bool mode )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_bAutoattack = mode ;
m_lastAttack = Util : : getTimeMs ( ) ;
2017-08-08 13:53:47 +02:00
}
bool Core : : Entity : : Player : : isAutoattackOn ( ) const
{
2018-08-29 21:40:59 +02:00
return m_bAutoattack ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : sendStats ( )
{
2018-06-28 00:07:07 +02:00
2018-08-29 21:40:59 +02:00
auto statPacket = makeZonePacket < FFXIVIpcPlayerStats > ( getId ( ) ) ;
statPacket - > data ( ) . strength = m_baseStats . str ;
statPacket - > data ( ) . dexterity = m_baseStats . dex ;
statPacket - > data ( ) . vitality = m_baseStats . vit ;
statPacket - > data ( ) . intelligence = m_baseStats . inte ;
statPacket - > data ( ) . mind = m_baseStats . mnd ;
statPacket - > data ( ) . piety = m_baseStats . pie ;
statPacket - > data ( ) . determination = m_baseStats . determination ;
statPacket - > data ( ) . hp = m_baseStats . max_hp ;
statPacket - > data ( ) . mp = m_baseStats . max_mp ;
statPacket - > data ( ) . accuracy = m_baseStats . accuracy ;
statPacket - > data ( ) . attack = m_baseStats . attack ;
statPacket - > data ( ) . attackMagicPotency = m_baseStats . attackPotMagic ;
statPacket - > data ( ) . healingMagicPotency = m_baseStats . healingPotMagic ;
statPacket - > data ( ) . skillSpeed = m_baseStats . skillSpeed ;
statPacket - > data ( ) . spellSpeed = m_baseStats . spellSpeed ;
statPacket - > data ( ) . spellSpeed1 = m_baseStats . spellSpeed ;
statPacket - > data ( ) . spellSpeedMod = 100 ;
statPacket - > data ( ) . criticalHitRate = m_baseStats . spellSpeed ;
statPacket - > data ( ) . defense = m_baseStats . spellSpeed ;
statPacket - > data ( ) . magicDefense = m_baseStats . spellSpeed ;
statPacket - > data ( ) . attack = m_baseStats . spellSpeed ;
queuePacket ( statPacket ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : teleport ( uint16_t aetheryteId , uint8_t type )
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
auto pTeriMgr = g_fw . get < TerritoryMgr > ( ) ;
2018-03-09 00:06:44 +01:00
2018-08-29 21:40:59 +02:00
auto data = pExdData - > get < Core : : Data : : Aetheryte > ( aetheryteId ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( data = = nullptr )
{
return ;
}
setStateFlag ( PlayerStateFlag : : BetweenAreas ) ;
auto targetPos = pTeriMgr - > getTerritoryPosition ( data - > level . at ( 0 ) ) ;
Common : : FFXIVARR_POSITION3 pos ;
pos . x = 0 ;
pos . y = 0 ;
pos . z = 0 ;
float rot = 0 ;
if ( targetPos ! = nullptr )
{
pos = targetPos - > getTargetPosition ( ) ;
rot = targetPos - > getTargetRotation ( ) ;
}
sendDebug ( " Teleport: " + pExdData - > get < Core : : Data : : PlaceName > ( data - > placeName ) - > name + " " +
pExdData - > get < Core : : Data : : PlaceName > ( data - > aethernetName ) - > name +
" ( " + std : : to_string ( data - > territory ) + " ) " ) ;
// TODO: this should be simplified and a type created in server_common/common.h.
if ( type = = 1 ) // teleport
{
prepareZoning ( data - > territory , true , 1 , 112 ) ; // TODO: Really?
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ActorDespawnEffect , 0x04 ) ) ;
setZoningType ( Common : : ZoneingType : : Teleport ) ;
}
else if ( type = = 2 ) // aethernet
{
prepareZoning ( data - > territory , true , 1 , 112 ) ;
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ActorDespawnEffect , 0x04 ) ) ;
setZoningType ( Common : : ZoneingType : : Teleport ) ;
}
else if ( type = = 3 ) // return
{
prepareZoning ( data - > territory , true , 1 , 111 ) ;
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ActorDespawnEffect , 0x03 ) ) ;
setZoningType ( Common : : ZoneingType : : Return ) ;
}
m_queuedZoneing = boost : : make_shared < QueuedZoning > ( data - > territory , pos , Util : : getTimeMs ( ) , rot ) ;
2017-09-13 11:46:17 +02:00
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : forceZoneing ( uint32_t zoneId )
{
2018-08-29 21:40:59 +02:00
m_queuedZoneing = boost : : make_shared < QueuedZoning > ( zoneId , getPos ( ) , Util : : getTimeMs ( ) , 0.f ) ;
//performZoning( zoneId, Common::ZoneingType::None, getPos() );
2017-08-08 13:53:47 +02:00
}
2017-08-10 16:31:48 +02:00
void Core : : Entity : : Player : : returnToHomepoint ( )
{
2018-08-29 21:40:59 +02:00
setZoningType ( Common : : ZoneingType : : Return ) ;
teleport ( getHomepoint ( ) , 3 ) ;
2017-08-10 16:31:48 +02:00
}
2017-08-08 13:53:47 +02:00
void Core : : Entity : : Player : : setZone ( uint32_t zoneId )
{
2018-08-29 21:40:59 +02:00
auto pTeriMgr = g_fw . get < TerritoryMgr > ( ) ;
m_onEnterEventDone = false ;
if ( ! pTeriMgr - > movePlayer ( zoneId , getAsPlayer ( ) ) )
{
// todo: this will require proper handling, for now just return the player to their previous area
m_pos = m_prevPos ;
m_rot = m_prevRot ;
m_zoneId = m_prevZoneId ;
2018-02-04 18:53:19 +01:00
2018-08-29 21:40:59 +02:00
if ( ! pTeriMgr - > movePlayer ( m_zoneId , getAsPlayer ( ) ) )
return ;
}
2018-02-04 18:53:19 +01:00
2018-08-29 21:40:59 +02:00
sendZonePackets ( ) ;
2017-08-08 13:53:47 +02:00
}
2018-01-29 13:05:33 +11:00
bool Core : : Entity : : Player : : setInstance ( uint32_t instanceContentId )
{
2018-08-29 21:40:59 +02:00
auto pTeriMgr = g_fw . get < TerritoryMgr > ( ) ;
m_onEnterEventDone = false ;
auto instance = pTeriMgr - > getInstanceZonePtr ( instanceContentId ) ;
if ( ! instance )
return false ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
return setInstance ( instance ) ;
2018-01-29 13:05:33 +11:00
}
bool Core : : Entity : : Player : : setInstance ( ZonePtr instance )
{
2018-08-29 21:40:59 +02:00
m_onEnterEventDone = false ;
if ( ! instance )
return false ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
auto pTeriMgr = g_fw . get < TerritoryMgr > ( ) ;
2018-03-09 00:06:44 +01:00
2018-08-29 21:40:59 +02:00
// zoning within the same zone won't cause the prev data to be overwritten
if ( instance - > getTerritoryId ( ) ! = m_zoneId )
{
m_prevPos = m_pos ;
m_prevRot = m_rot ;
m_prevZoneId = m_zoneId ;
}
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
if ( ! pTeriMgr - > movePlayer ( instance , getAsPlayer ( ) ) )
return false ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
sendZonePackets ( ) ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
return true ;
2018-01-29 13:05:33 +11:00
}
bool Core : : Entity : : Player : : exitInstance ( )
{
2018-08-29 21:40:59 +02:00
auto pTeriMgr = g_fw . get < TerritoryMgr > ( ) ;
if ( ! pTeriMgr - > movePlayer ( m_prevZoneId , getAsPlayer ( ) ) )
return false ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
m_pos = m_prevPos ;
m_rot = m_prevRot ;
m_zoneId = m_prevZoneId ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
sendZonePackets ( ) ;
2018-01-29 13:05:33 +11:00
2018-08-29 21:40:59 +02:00
return true ;
2018-01-29 13:05:33 +11:00
}
2017-08-08 13:53:47 +02:00
uint32_t Core : : Entity : : Player : : getPlayTime ( ) const
{
2018-08-29 21:40:59 +02:00
return m_playTime ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getRace ( ) const
{
2018-08-29 21:40:59 +02:00
return getLookAt ( CharaLook : : Race ) ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getGender ( ) const
{
2018-08-29 21:40:59 +02:00
return getLookAt ( CharaLook : : Gender ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : initSpawnIdQueue ( )
{
2018-08-29 21:40:59 +02:00
m_actorSpawnIndexAllocator . freeAllSpawnIndexes ( ) ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getSpawnIdForActorId ( uint32_t actorId )
{
2018-08-29 21:40:59 +02:00
return m_actorSpawnIndexAllocator . getNextFreeSpawnIndex ( actorId ) ;
2017-08-08 13:53:47 +02:00
}
2018-03-02 02:55:02 +11:00
bool Core : : Entity : : Player : : isActorSpawnIdValid ( uint8_t spawnIndex )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_actorSpawnIndexAllocator . isSpawnIndexValid ( spawnIndex ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : registerAetheryte ( uint8_t aetheryteId )
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( aetheryteId , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_aetheryte [ index ] | = value ;
queuePacket ( makeActorControl143 ( getId ( ) , LearnTeleport , aetheryteId , 1 ) ) ;
2017-08-08 13:53:47 +02:00
}
bool Core : : Entity : : Player : : isAetheryteRegistered ( uint8_t aetheryteId ) const
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( aetheryteId , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
return ( m_aetheryte [ index ] & value ) ! = 0 ;
2017-08-08 13:53:47 +02:00
}
2018-08-29 21:40:59 +02:00
uint8_t * Core : : Entity : : Player : : getDiscoveryBitmask ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_discovery ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : discover ( int16_t map_id , int16_t sub_id )
{
2018-08-29 21:40:59 +02:00
// map.exd field 12 -> index in one of the two discovery sections, if field 15 is false, need to use 2nd section
// section 1 starts at 4 - 2 bytes each
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
// section to starts at 320 - 4 bytes long
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
2018-03-09 00:06:44 +01:00
2018-08-29 21:40:59 +02:00
int32_t offset = 4 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto info = pExdData - > get < Core : : Data : : Map > (
pExdData - > get < Core : : Data : : TerritoryType > ( getCurrentZone ( ) - > getTerritoryId ( ) ) - > map ) ;
if ( info - > discoveryArrayByte )
offset = 4 + 2 * info - > discoveryIndex ;
else
offset = 324 + 4 * info - > discoveryIndex ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
int32_t index = offset + sub_id / 8 ;
uint8_t bitIndex = sub_id % 8 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint8_t value = 1 < < bitIndex ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_discovery [ index ] | = value ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint16_t level = getLevel ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint32_t exp = ( pExdData - > get < Core : : Data : : ParamGrow > ( level ) - > expToNext * 5 / 100 ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
gainExp ( exp ) ;
2017-08-08 13:53:47 +02:00
}
bool Core : : Entity : : Player : : isNewAdventurer ( ) const
{
2018-08-29 21:40:59 +02:00
return m_bNewAdventurer ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setNewAdventurer ( bool state )
{
2018-08-29 21:40:59 +02:00
//if( !state )
//{
// unsetStateFlag( PlayerStateFlag::NewAdventurer );
//}
//else
//{
// setStateFlag( PlayerStateFlag::NewAdventurer );
//}
m_bNewAdventurer = state ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : resetDiscovery ( )
{
2018-08-29 21:40:59 +02:00
memset ( m_discovery , 0 , sizeof ( m_discovery ) ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : changePosition ( float x , float y , float z , float o )
{
2018-08-29 21:40:59 +02:00
Common : : FFXIVARR_POSITION3 pos ;
pos . x = x ;
pos . y = y ;
pos . z = z ;
m_queuedZoneing = boost : : make_shared < QueuedZoning > ( getZoneId ( ) , pos , Util : : getTimeMs ( ) , o ) ;
2017-08-08 13:53:47 +02:00
}
2018-07-04 19:28:54 +10:00
void Core : : Entity : : Player : : learnAction ( uint16_t actionId )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( actionId , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_unlocks [ index ] | = value ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
queuePacket ( makeActorControl143 ( getId ( ) , ToggleActionUnlock , actionId , 1 ) ) ;
2017-08-08 13:53:47 +02:00
}
2017-10-09 20:17:43 +02:00
void Core : : Entity : : Player : : learnSong ( uint8_t songId , uint32_t itemId )
2017-10-09 20:09:49 +02:00
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( songId , value , index ) ;
2017-10-09 20:09:49 +02:00
2018-08-29 21:40:59 +02:00
m_orchestrion [ index ] | = value ;
2017-10-09 20:09:49 +02:00
2018-08-29 21:40:59 +02:00
queuePacket ( makeActorControl143 ( getId ( ) , ToggleOrchestrionUnlock , songId , 1 , itemId ) ) ;
2017-10-09 20:09:49 +02:00
}
2017-08-08 13:53:47 +02:00
bool Core : : Entity : : Player : : isActionLearned ( uint8_t actionId ) const
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( actionId , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
return ( m_unlocks [ index ] & value ) ! = 0 ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : gainExp ( uint32_t amount )
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
2018-03-09 00:06:44 +01:00
2018-08-29 21:40:59 +02:00
uint32_t currentExp = getExp ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint16_t level = getLevel ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint32_t neededExpToLevel = pExdData - > get < Core : : Data : : ParamGrow > ( level ) - > expToNext ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint32_t neededExpToLevelplus1 = pExdData - > get < Core : : Data : : ParamGrow > ( level + 1 ) - > expToNext ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
queuePacket ( makeActorControl143 ( getId ( ) , GainExpMsg , static_cast < uint8_t > ( getClass ( ) ) , amount ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( level > = 70 ) // temporary fix for leveling over levelcap
{
queuePacket ( makeActorControl143 ( getId ( ) , UpdateUiExp , static_cast < uint8_t > ( getClass ( ) ) , amount ) ) ;
return ;
}
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( ( currentExp + amount ) > = neededExpToLevel )
{
// levelup
amount = ( currentExp + amount - neededExpToLevel ) > neededExpToLevelplus1 ?
neededExpToLevelplus1 - 1 :
( currentExp + amount - neededExpToLevel ) ;
setExp ( amount ) ;
gainLevel ( ) ;
queuePacket ( makeActorControl143 ( getId ( ) , UpdateUiExp , static_cast < uint8_t > ( getClass ( ) ) , amount ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
}
else
{
queuePacket (
makeActorControl143 ( getId ( ) , UpdateUiExp , static_cast < uint8_t > ( getClass ( ) ) , currentExp + amount ) ) ;
setExp ( currentExp + amount ) ;
}
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
sendStatusUpdate ( ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : gainLevel ( )
{
2018-08-29 21:40:59 +02:00
setLevel ( getLevel ( ) + 1 ) ;
calculateStats ( ) ;
sendStats ( ) ;
sendStatusUpdate ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_hp = getMaxHp ( ) ;
m_mp = getMaxMp ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto effectListPacket = makeZonePacket < FFXIVIpcStatusEffectList > ( getId ( ) ) ;
effectListPacket - > data ( ) . classId = static_cast < uint8_t > ( getClass ( ) ) ;
effectListPacket - > data ( ) . level1 = getLevel ( ) ;
effectListPacket - > data ( ) . level = getLevel ( ) ;
effectListPacket - > data ( ) . current_hp = getMaxHp ( ) ;
effectListPacket - > data ( ) . current_mp = getMaxMp ( ) ;
effectListPacket - > data ( ) . currentTp = 1000 ;
effectListPacket - > data ( ) . max_hp = getMaxHp ( ) ;
effectListPacket - > data ( ) . max_mp = getMaxMp ( ) ;
sendToInRangeSet ( effectListPacket , true ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( makeActorControl142 ( getId ( ) , LevelUpEffect , static_cast < uint8_t > ( getClass ( ) ) ,
getLevel ( ) , getLevel ( ) - 1 ) , true ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto classInfoPacket = makeZonePacket < FFXIVIpcUpdateClassInfo > ( getId ( ) ) ;
classInfoPacket - > data ( ) . classId = static_cast < uint8_t > ( getClass ( ) ) ;
classInfoPacket - > data ( ) . level1 = getLevel ( ) ;
classInfoPacket - > data ( ) . level = getLevel ( ) ;
classInfoPacket - > data ( ) . nextLevelIndex = getLevel ( ) ;
classInfoPacket - > data ( ) . currentExp = getExp ( ) ;
queuePacket ( classInfoPacket ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : sendStatusUpdate ( bool toSelf )
{
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( boost : : make_shared < UpdateHpMpTpPacket > ( * this ) , true ) ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getLevel ( ) const
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
uint8_t classJobIndex = pExdData - > get < Core : : Data : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > expArrayIndex ;
return static_cast < uint8_t > ( m_classArray [ classJobIndex ] ) ;
2017-08-08 13:53:47 +02:00
}
2017-12-08 15:38:25 +01:00
uint8_t Core : : Entity : : Player : : getLevelForClass ( Common : : ClassJob pClass ) const
2017-08-09 14:38:46 +02:00
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
uint8_t classJobIndex = pExdData - > get < Core : : Data : : ClassJob > ( static_cast < uint8_t > ( pClass ) ) - > expArrayIndex ;
return static_cast < uint8_t > ( m_classArray [ classJobIndex ] ) ;
2017-08-09 14:38:46 +02:00
}
2018-08-26 16:19:05 +10:00
bool Core : : Entity : : Player : : isClassJobUnlocked ( Common : : ClassJob classJob ) const
{
2018-08-29 21:40:59 +02:00
// todo: need to properly check if a job is unlocked, at the moment we just check the class array which will return true for every job if the base class is unlocked
return getLevelForClass ( classJob ) ! = 0 ;
2018-08-26 16:19:05 +10:00
}
2017-08-08 13:53:47 +02:00
uint32_t Core : : Entity : : Player : : getExp ( ) const
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
uint8_t classJobIndex = pExdData - > get < Core : : Data : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > expArrayIndex ;
return m_expArray [ classJobIndex ] ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setExp ( uint32_t amount )
2018-08-29 21:40:59 +02:00
{
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
uint8_t classJobIndex = pExdData - > get < Core : : Data : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > expArrayIndex ;
m_expArray [ classJobIndex ] = amount ;
2017-08-08 13:53:47 +02:00
}
bool Core : : Entity : : Player : : isInCombat ( ) const
{
2018-08-29 21:40:59 +02:00
return m_bInCombat ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setInCombat ( bool mode )
{
2018-08-29 21:40:59 +02:00
//m_lastAttack = GetTickCount();
m_bInCombat = mode ;
2017-08-08 13:53:47 +02:00
}
2017-12-08 15:38:25 +01:00
void Core : : Entity : : Player : : setClassJob ( Common : : ClassJob classJob )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_class = classJob ;
uint8_t level = getLevel ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( getHp ( ) > getMaxHp ( ) )
m_hp = getMaxHp ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( getMp ( ) > getMaxMp ( ) )
m_mp = getMaxMp ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_tp = 0 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto classInfoPacket = makeZonePacket < FFXIVIpcPlayerClassInfo > ( getId ( ) ) ;
classInfoPacket - > data ( ) . classId = static_cast < uint8_t > ( getClass ( ) ) ;
classInfoPacket - > data ( ) . level = getLevel ( ) ;
queuePacket ( classInfoPacket ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ClassJobChange , 0x04 ) , true ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
sendStatusUpdate ( true ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setLevel ( uint8_t level )
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
uint8_t classJobIndex = pExdData - > get < Core : : Data : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > expArrayIndex ;
m_classArray [ classJobIndex ] = level ;
2017-08-08 13:53:47 +02:00
}
2017-12-08 15:38:25 +01:00
void Core : : Entity : : Player : : setLevelForClass ( uint8_t level , Common : : ClassJob classjob )
2017-08-09 14:38:46 +02:00
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
uint8_t classJobIndex = pExdData - > get < Core : : Data : : ClassJob > ( static_cast < uint8_t > ( classjob ) ) - > expArrayIndex ;
2017-12-16 23:00:04 +11:00
2018-08-29 21:40:59 +02:00
if ( m_classArray [ classJobIndex ] = = 0 )
insertDbClass ( classJobIndex ) ;
2017-12-16 23:00:04 +11:00
2018-08-29 21:40:59 +02:00
m_classArray [ classJobIndex ] = level ;
2017-08-09 14:38:46 +02:00
}
2017-08-08 13:53:47 +02:00
void Core : : Entity : : Player : : sendModel ( )
{
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( boost : : make_shared < ModelEquipPacket > ( * getAsPlayer ( ) ) , true ) ;
2017-08-08 13:53:47 +02:00
}
2018-08-25 22:56:46 +10:00
uint32_t Core : : Entity : : Player : : getModelForSlot ( Common : : GearSetSlot slot )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_modelEquip [ slot ] ;
2017-08-08 13:53:47 +02:00
}
2018-08-25 22:56:46 +10:00
void Core : : Entity : : Player : : setModelForSlot ( Common : : GearSetSlot slot , uint32_t val )
2017-10-02 16:00:26 +02:00
{
2018-08-29 21:40:59 +02:00
m_modelEquip [ slot ] = val ;
2017-10-02 16:00:26 +02:00
}
2017-08-08 13:53:47 +02:00
uint64_t Core : : Entity : : Player : : getModelMainWeapon ( ) const
{
2018-08-29 21:40:59 +02:00
return m_modelMainWeapon ;
2017-08-08 13:53:47 +02:00
}
uint64_t Core : : Entity : : Player : : getModelSubWeapon ( ) const
{
2018-08-29 21:40:59 +02:00
return m_modelSubWeapon ;
2017-08-08 13:53:47 +02:00
}
uint64_t Core : : Entity : : Player : : getModelSystemWeapon ( ) const
{
2018-08-29 21:40:59 +02:00
return m_modelSystemWeapon ;
2017-08-08 13:53:47 +02:00
}
int8_t Core : : Entity : : Player : : getAetheryteMaskAt ( uint8_t index ) const
{
2018-08-29 21:40:59 +02:00
if ( index > sizeof ( m_aetheryte ) )
return 0 ;
return m_aetheryte [ index ] ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getBirthDay ( ) const
{
2018-08-29 21:40:59 +02:00
return m_birthDay ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getBirthMonth ( ) const
{
2018-08-29 21:40:59 +02:00
return m_birthMonth ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getGuardianDeity ( ) const
{
2018-08-29 21:40:59 +02:00
return m_guardianDeity ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getLookAt ( uint8_t index ) const
{
2018-08-29 21:40:59 +02:00
return m_customize [ index ] ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setLookAt ( uint8_t index , uint8_t value )
{
2018-08-29 21:40:59 +02:00
m_customize [ index ] = value ;
2017-08-08 13:53:47 +02:00
}
// spawn this player for pTarget
2017-12-08 15:38:25 +01:00
void Core : : Entity : : Player : : spawn ( Entity : : PlayerPtr pTarget )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto pLog = g_fw . get < Logger > ( ) ;
pLog - > debug ( " [ " + std : : to_string ( pTarget - > getId ( ) ) + " ] Spawning " +
getName ( ) + " for " +
pTarget - > getName ( ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
pTarget - > queuePacket ( boost : : make_shared < PlayerSpawnPacket > ( * getAsPlayer ( ) , * pTarget ) ) ;
2017-08-08 13:53:47 +02:00
}
// despawn
2018-02-10 01:21:31 +01:00
void Core : : Entity : : Player : : despawn ( Entity : : PlayerPtr pTarget )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto pPlayer = pTarget ;
auto pLog = g_fw . get < Logger > ( ) ;
pLog - > debug ( " despawning " + getName ( ) + " for " + pTarget - > getName ( ) ) ;
2018-02-21 18:06:52 +01:00
2018-08-29 21:40:59 +02:00
pPlayer - > freePlayerSpawnId ( getId ( ) ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
pPlayer - > queuePacket ( makeActorControl143 ( getId ( ) , DespawnZoneScreenMsg , 0x04 , getId ( ) , 0x01 ) ) ;
2017-08-08 13:53:47 +02:00
}
2018-02-22 15:31:10 +01:00
Core : : Entity : : ActorPtr Core : : Entity : : Player : : lookupTargetById ( uint64_t targetId )
2017-08-10 22:06:05 +02:00
{
2018-08-29 21:40:59 +02:00
ActorPtr targetActor ;
auto inRange = getInRangeActors ( true ) ;
for ( auto actor : inRange )
{
if ( actor - > getId ( ) = = targetId )
targetActor = actor ;
}
return targetActor ;
2017-08-10 22:06:05 +02:00
}
2017-08-08 13:53:47 +02:00
void Core : : Entity : : Player : : setLastPing ( uint32_t ping )
{
2018-08-29 21:40:59 +02:00
m_lastPing = ping ;
2017-08-08 13:53:47 +02:00
}
uint32_t Core : : Entity : : Player : : getLastPing ( ) const
{
2018-08-29 21:40:59 +02:00
return m_lastPing ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setVoiceId ( uint8_t voiceId )
{
2018-08-29 21:40:59 +02:00
m_voice = voiceId ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setGc ( uint8_t gc )
{
2018-08-29 21:40:59 +02:00
m_gc = gc ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto gcAffPacket = makeZonePacket < FFXIVGCAffiliation > ( getId ( ) ) ;
gcAffPacket - > data ( ) . gcId = m_gc ;
gcAffPacket - > data ( ) . gcRank [ 0 ] = m_gcRank [ 0 ] ;
gcAffPacket - > data ( ) . gcRank [ 1 ] = m_gcRank [ 1 ] ;
gcAffPacket - > data ( ) . gcRank [ 2 ] = m_gcRank [ 2 ] ;
queuePacket ( gcAffPacket ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setGcRankAt ( uint8_t index , uint8_t rank )
{
2018-08-29 21:40:59 +02:00
m_gcRank [ index ] = rank ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto gcAffPacket = makeZonePacket < FFXIVGCAffiliation > ( getId ( ) ) ;
gcAffPacket - > data ( ) . gcId = m_gc ;
gcAffPacket - > data ( ) . gcRank [ 0 ] = m_gcRank [ 0 ] ;
gcAffPacket - > data ( ) . gcRank [ 1 ] = m_gcRank [ 1 ] ;
gcAffPacket - > data ( ) . gcRank [ 2 ] = m_gcRank [ 2 ] ;
queuePacket ( gcAffPacket ) ;
2017-08-08 13:53:47 +02:00
}
2017-10-01 18:38:58 +02:00
const uint8_t * Core : : Entity : : Player : : getStateFlags ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_stateFlags ;
2017-08-08 13:53:47 +02:00
}
2017-08-10 22:06:05 +02:00
bool Core : : Entity : : Player : : actionHasCastTime ( uint32_t actionId ) //TODO: Add logic for special cases
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
auto actionInfoPtr = pExdData - > get < Core : : Data : : Action > ( actionId ) ;
if ( actionInfoPtr - > preservesCombo )
return false ;
2017-08-15 16:19:55 +02:00
2018-08-29 21:40:59 +02:00
return actionInfoPtr - > cast100ms ! = 0 ;
2017-08-15 16:19:55 +02:00
2017-08-10 22:06:05 +02:00
}
2017-12-08 15:38:25 +01:00
bool Core : : Entity : : Player : : hasStateFlag ( Common : : PlayerStateFlag flag ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
int32_t iFlag = static_cast < uint32_t > ( flag ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( iFlag , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
return ( m_stateFlags [ index ] & value ) ! = 0 ;
2017-08-08 13:53:47 +02:00
}
2017-12-08 15:38:25 +01:00
void Core : : Entity : : Player : : setStateFlag ( Common : : PlayerStateFlag flag )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto prevOnlineStatus = getOnlineStatus ( ) ;
int32_t iFlag = static_cast < uint32_t > ( flag ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( iFlag , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_stateFlags [ index ] | = value ;
sendStateFlags ( ) ;
2018-01-11 14:59:39 +01:00
2018-08-29 21:40:59 +02:00
auto newOnlineStatus = getOnlineStatus ( ) ;
2018-01-11 14:59:39 +01:00
2018-08-29 21:40:59 +02:00
if ( prevOnlineStatus ! = newOnlineStatus )
sendToInRangeSet ( makeActorControl142 ( getId ( ) , SetStatusIcon ,
static_cast < uint8_t > ( getOnlineStatus ( ) ) ) , true ) ;
2017-08-08 13:53:47 +02:00
}
2017-08-13 18:28:05 +02:00
void Core : : Entity : : Player : : setStateFlags ( std : : vector < Common : : PlayerStateFlag > flags )
{
2018-08-29 21:40:59 +02:00
for ( const auto & flag : flags )
{
setStateFlag ( flag ) ;
}
2017-08-13 18:28:05 +02:00
}
2017-08-08 13:53:47 +02:00
void Core : : Entity : : Player : : sendStateFlags ( )
{
2018-08-29 21:40:59 +02:00
queuePacket ( boost : : make_shared < PlayerStateFlagsPacket > ( * getAsPlayer ( ) ) ) ;
2017-08-08 13:53:47 +02:00
}
2017-12-08 15:38:25 +01:00
void Core : : Entity : : Player : : unsetStateFlag ( Common : : PlayerStateFlag flag )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
if ( ! hasStateFlag ( flag ) )
return ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto prevOnlineStatus = getOnlineStatus ( ) ;
2018-01-11 14:59:39 +01:00
2018-08-29 21:40:59 +02:00
int32_t iFlag = static_cast < uint32_t > ( flag ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( iFlag , value , index ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_stateFlags [ index ] ^ = value ;
sendStateFlags ( ) ;
2018-01-11 14:59:39 +01:00
2018-08-29 21:40:59 +02:00
auto newOnlineStatus = getOnlineStatus ( ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( prevOnlineStatus ! = newOnlineStatus )
sendToInRangeSet ( makeActorControl142 ( getId ( ) , SetStatusIcon , static_cast < uint8_t > ( getOnlineStatus ( ) ) ) ,
true ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : update ( int64_t currTime )
{
2018-08-29 21:40:59 +02:00
// a zoning is pending, lets do it
if ( m_queuedZoneing & & ( currTime - m_queuedZoneing - > m_queueTime ) > 800 )
{
Common : : FFXIVARR_POSITION3 targetPos = m_queuedZoneing - > m_targetPosition ;
if ( getCurrentZone ( ) - > getTerritoryId ( ) ! = m_queuedZoneing - > m_targetZone )
{
performZoning ( m_queuedZoneing - > m_targetZone , targetPos , m_queuedZoneing - > m_targetRotation ) ;
}
else
{
auto setActorPosPacket = makeZonePacket < FFXIVIpcActorSetPos > ( getId ( ) ) ;
setActorPosPacket - > data ( ) . r16 = Math : : Util : : floatToUInt16Rot ( m_queuedZoneing - > m_targetRotation ) ;
setActorPosPacket - > data ( ) . waitForLoad = 0x04 ;
setActorPosPacket - > data ( ) . x = targetPos . x ;
setActorPosPacket - > data ( ) . y = targetPos . y ;
setActorPosPacket - > data ( ) . z = targetPos . z ;
sendToInRangeSet ( setActorPosPacket , true ) ;
setPos ( targetPos ) ;
}
m_queuedZoneing . reset ( ) ;
return ;
}
if ( m_hp < = 0 & & m_status ! = ActorStatus : : Dead )
die ( ) ;
if ( ! isAlive ( ) )
return ;
updateStatusEffects ( ) ;
m_lastUpdate = currTime ;
if ( ! checkAction ( ) )
{
if ( m_targetId & & m_currentStance = = Common : : Stance : : Active & & isAutoattackOn ( ) )
{
auto mainWeap = getItemAt ( Common : : GearSet0 , Common : : GearSetSlot : : MainHand ) ;
// @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need...
for ( auto actor : m_inRangeActor )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
if ( actor - > getId ( ) = = m_targetId & & actor - > getAsChara ( ) - > isAlive ( ) & & mainWeap )
{
// default autoattack range
// TODO make this dependant on bnpc size
uint32_t range = 7 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
// default autoattack range for ranged classes
if ( getClass ( ) = = ClassJob : : Machinist | |
getClass ( ) = = ClassJob : : Bard | |
getClass ( ) = = ClassJob : : Archer )
range = 25 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( Math : : Util : : distance ( getPos ( ) . x , getPos ( ) . y , getPos ( ) . z ,
actor - > getPos ( ) . x , actor - > getPos ( ) . y , actor - > getPos ( ) . z ) < = range )
{
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( ( currTime - m_lastAttack ) > mainWeap - > getDelay ( ) )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_lastAttack = currTime ;
autoAttack ( actor - > getAsChara ( ) ) ;
2017-08-08 13:53:47 +02:00
}
2018-08-29 21:40:59 +02:00
}
}
2017-08-08 13:53:47 +02:00
}
2018-08-29 21:40:59 +02:00
}
}
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( ( currTime - m_lastTickTime ) > 3000 )
{
// add 3 seconds to total play time
m_playTime + = 3 ;
m_lastTickTime = currTime ;
onTick ( ) ;
}
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : onMobKill ( uint16_t nameId )
{
2018-08-29 21:40:59 +02:00
auto pScriptMgr = g_fw . get < Scripting : : ScriptMgr > ( ) ;
pScriptMgr - > onMobKill ( * getAsPlayer ( ) , nameId ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : freePlayerSpawnId ( uint32_t actorId )
{
2018-08-29 21:40:59 +02:00
auto spawnId = m_actorSpawnIndexAllocator . freeUsedSpawnIndex ( actorId ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
auto freeActorSpawnPacket = makeZonePacket < FFXIVIpcActorFreeSpawn > ( getId ( ) ) ;
freeActorSpawnPacket - > data ( ) . actorId = actorId ;
freeActorSpawnPacket - > data ( ) . spawnId = spawnId ;
queuePacket ( freeActorSpawnPacket ) ;
2017-08-08 13:53:47 +02:00
}
2018-08-29 21:40:59 +02:00
uint8_t * Core : : Entity : : Player : : getAetheryteArray ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_aetheryte ;
2017-08-08 13:53:47 +02:00
}
/*! set homepoint */
void Core : : Entity : : Player : : setHomepoint ( uint8_t aetheryteId )
{
2018-08-29 21:40:59 +02:00
m_homePoint = aetheryteId ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
queuePacket ( makeActorControl143 ( getId ( ) , SetHomepoint , aetheryteId ) ) ;
2017-08-08 13:53:47 +02:00
}
/*! get homepoint */
uint8_t Core : : Entity : : Player : : getHomepoint ( ) const
{
2018-08-29 21:40:59 +02:00
return m_homePoint ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
uint16_t * Core : : Entity : : Player : : getClassArray ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_classArray ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
const uint16_t * Core : : Entity : : Player : : getClassArray ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_classArray ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
uint32_t * Core : : Entity : : Player : : getExpArray ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_expArray ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
const uint32_t * Core : : Entity : : Player : : getExpArray ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_expArray ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
uint8_t * Core : : Entity : : Player : : getHowToArray ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_howTo ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
const uint8_t * Core : : Entity : : Player : : getHowToArray ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_howTo ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
const uint8_t * Core : : Entity : : Player : : getUnlockBitmask ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_unlocks ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
const uint8_t * Core : : Entity : : Player : : getOrchestrionBitmask ( ) const
2017-10-09 20:09:49 +02:00
{
2018-08-29 21:40:59 +02:00
return m_orchestrion ;
2017-10-09 20:09:49 +02:00
}
2017-12-07 23:59:03 +01:00
const uint8_t * Core : : Entity : : Player : : getMountGuideBitmask ( ) const
2017-12-03 17:24:11 +01:00
{
2018-08-29 21:40:59 +02:00
return m_mountGuide ;
2017-12-03 17:24:11 +01:00
}
2017-08-08 13:53:47 +02:00
uint64_t Core : : Entity : : Player : : getContentId ( ) const
{
2018-08-29 21:40:59 +02:00
return m_contentId ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getVoiceId ( ) const
{
2018-08-29 21:40:59 +02:00
return m_voice ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getGc ( ) const
{
2018-08-29 21:40:59 +02:00
return m_gc ;
2017-08-08 13:53:47 +02:00
}
2017-12-07 23:59:03 +01:00
const uint8_t * Core : : Entity : : Player : : getGcRankArray ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_gcRank ;
2017-08-08 13:53:47 +02:00
}
2018-06-28 00:07:07 +02:00
void Core : : Entity : : Player : : queuePacket ( Network : : Packets : : FFXIVPacketBasePtr pPacket )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto pServerZone = g_fw . get < ServerZone > ( ) ;
auto pSession = pServerZone - > getSession ( m_id ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( ! pSession )
return ;
2017-11-28 00:09:36 +01:00
2018-08-29 21:40:59 +02:00
auto pZoneCon = pSession - > getZoneConnection ( ) ;
2017-11-28 00:09:36 +01:00
2018-08-29 21:40:59 +02:00
if ( pZoneCon )
pZoneCon - > queueOutPacket ( pPacket ) ;
2017-08-08 13:53:47 +02:00
}
2018-06-28 00:07:07 +02:00
void Core : : Entity : : Player : : queueChatPacket ( Network : : Packets : : FFXIVPacketBasePtr pPacket )
2017-08-22 23:53:20 +02:00
{
2018-08-29 21:40:59 +02:00
auto pServerZone = g_fw . get < ServerZone > ( ) ;
auto pSession = pServerZone - > getSession ( m_id ) ;
2017-08-22 23:53:20 +02:00
2018-08-29 21:40:59 +02:00
if ( ! pSession )
return ;
2017-08-22 23:53:20 +02:00
2018-08-29 21:40:59 +02:00
auto pChatCon = pSession - > getChatConnection ( ) ;
2017-11-28 00:09:36 +01:00
2018-08-29 21:40:59 +02:00
if ( pChatCon )
pChatCon - > queueOutPacket ( pPacket ) ;
2017-08-22 23:53:20 +02:00
}
2017-08-08 13:53:47 +02:00
bool Core : : Entity : : Player : : isLoadingComplete ( ) const
{
2018-08-29 21:40:59 +02:00
return m_bLoadingComplete ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setLoadingComplete ( bool bComplete )
{
2018-08-29 21:40:59 +02:00
m_bLoadingComplete = bComplete ;
2017-08-08 13:53:47 +02:00
}
2018-08-29 21:40:59 +02:00
void Core : : Entity : : Player : : performZoning ( uint16_t zoneId , const Common : : FFXIVARR_POSITION3 & pos , float rotation )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_pos = pos ;
m_zoneId = zoneId ;
m_bMarkedForZoning = true ;
setRot ( rotation ) ;
setZone ( zoneId ) ;
2017-08-08 13:53:47 +02:00
}
bool Core : : Entity : : Player : : isMarkedForZoning ( ) const
{
2018-08-29 21:40:59 +02:00
return m_bMarkedForZoning ;
2017-08-08 13:53:47 +02:00
}
ZoneingType Core : : Entity : : Player : : getZoningType ( ) const
{
2018-08-29 21:40:59 +02:00
return m_zoningType ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setZoningType ( Common : : ZoneingType zoneingType )
{
2018-08-29 21:40:59 +02:00
m_zoningType = zoneingType ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setSearchInfo ( uint8_t selectRegion , uint8_t selectClass , const char * searchMessage )
{
2018-08-29 21:40:59 +02:00
m_searchSelectRegion = selectRegion ;
m_searchSelectClass = selectClass ;
memset ( & m_searchMessage [ 0 ] , 0 , sizeof ( searchMessage ) ) ;
strcpy ( & m_searchMessage [ 0 ] , searchMessage ) ;
2017-08-08 13:53:47 +02:00
}
const char * Core : : Entity : : Player : : getSearchMessage ( ) const
{
2018-08-29 21:40:59 +02:00
return & m_searchMessage [ 0 ] ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getSearchSelectRegion ( ) const
{
2018-08-29 21:40:59 +02:00
return m_searchSelectRegion ;
2017-08-08 13:53:47 +02:00
}
uint8_t Core : : Entity : : Player : : getSearchSelectClass ( ) const
{
2018-08-29 21:40:59 +02:00
return m_searchSelectClass ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : sendNotice ( const std : : string & message ) //Purple Text
{
2018-08-29 21:40:59 +02:00
queuePacket ( boost : : make_shared < ServerNoticePacket > ( getId ( ) , message ) ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : sendUrgent ( const std : : string & message ) //Red Text
{
2018-08-29 21:40:59 +02:00
queuePacket ( boost : : make_shared < ChatPacket > ( * getAsPlayer ( ) , ChatType : : ServerUrgent , message ) ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : sendDebug ( const std : : string & message ) //Grey Text
{
2018-08-29 21:40:59 +02:00
queuePacket ( boost : : make_shared < ChatPacket > ( * getAsPlayer ( ) , ChatType : : ServerDebug , message ) ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : updateHowtosSeen ( uint32_t howToId )
{
2018-08-29 21:40:59 +02:00
uint8_t index = howToId / 8 ;
uint8_t bitIndex = howToId % 8 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
uint8_t value = 1 < < bitIndex ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
m_howTo [ index ] | = value ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : initHateSlotQueue ( )
{
2018-08-29 21:40:59 +02:00
m_freeHateSlotQueue = std : : queue < uint8_t > ( ) ;
for ( int32_t i = 1 ; i < 26 ; i + + )
m_freeHateSlotQueue . push ( i ) ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : sendHateList ( )
{
2018-08-29 21:40:59 +02:00
auto hateListPacket = makeZonePacket < FFXIVIpcHateList > ( getId ( ) ) ;
hateListPacket - > data ( ) . numEntries = m_actorIdTohateSlotMap . size ( ) ;
auto it = m_actorIdTohateSlotMap . begin ( ) ;
for ( int32_t i = 0 ; it ! = m_actorIdTohateSlotMap . end ( ) ; + + it , i + + )
{
hateListPacket - > data ( ) . entry [ i ] . actorId = it - > first ;
hateListPacket - > data ( ) . entry [ i ] . hatePercent = 100 ;
}
queuePacket ( hateListPacket ) ;
2017-08-08 13:53:47 +02:00
}
bool Core : : Entity : : Player : : isLogin ( ) const
{
2018-08-29 21:40:59 +02:00
return m_bIsLogin ;
2017-08-08 13:53:47 +02:00
}
void Core : : Entity : : Player : : setIsLogin ( bool bIsLogin )
{
2018-08-29 21:40:59 +02:00
m_bIsLogin = bIsLogin ;
2017-08-08 13:53:47 +02:00
}
2017-12-08 15:38:25 +01:00
uint8_t * Core : : Entity : : Player : : getTitleList ( )
2017-10-09 00:31:31 -03:00
{
2018-08-29 21:40:59 +02:00
return m_titleList ;
2017-10-09 00:31:31 -03:00
}
2018-02-17 01:20:40 +01:00
const uint8_t * Core : : Entity : : Player : : getTitleList ( ) const
{
2018-08-29 21:40:59 +02:00
return m_titleList ;
2018-02-17 01:20:40 +01:00
}
2017-10-09 14:13:23 +02:00
uint16_t Core : : Entity : : Player : : getTitle ( ) const
2017-10-09 02:06:31 -03:00
{
2018-08-29 21:40:59 +02:00
return m_activeTitle ;
2017-10-09 02:06:31 -03:00
}
2017-10-09 00:31:31 -03:00
void Core : : Entity : : Player : : addTitle ( uint16_t titleId )
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( titleId , value , index ) ;
2017-10-09 00:31:31 -03:00
2018-08-29 21:40:59 +02:00
m_titleList [ index ] | = value ;
2017-10-09 00:31:31 -03:00
}
2017-10-04 23:30:45 -03:00
void Core : : Entity : : Player : : setTitle ( uint16_t titleId )
2017-10-04 23:19:38 -03:00
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( titleId , value , index ) ;
2017-10-09 01:56:47 -03:00
2018-08-29 21:40:59 +02:00
if ( ( m_titleList [ index ] & value ) = = 0 ) // Player doesn't have title - bail
return ;
2017-10-09 01:56:47 -03:00
2018-08-29 21:40:59 +02:00
m_activeTitle = titleId ;
2017-10-09 01:56:47 -03:00
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( makeActorControl142 ( getId ( ) , SetTitle , titleId ) , true ) ;
2017-10-04 23:19:38 -03:00
}
2017-10-06 00:13:29 +02:00
void Core : : Entity : : Player : : setEquipDisplayFlags ( uint8_t state )
2017-10-05 20:24:58 +02:00
{
2018-08-29 21:40:59 +02:00
m_equipDisplayFlags = state ;
auto paramPacket = makeZonePacket < FFXIVIpcEquipDisplayFlags > ( getId ( ) ) ;
paramPacket - > data ( ) . bitmask = m_equipDisplayFlags ;
sendToInRangeSet ( paramPacket , true ) ;
2017-10-05 20:24:58 +02:00
}
2017-10-06 00:13:29 +02:00
uint8_t Core : : Entity : : Player : : getEquipDisplayFlags ( ) const
2017-10-05 20:24:58 +02:00
{
2018-08-29 21:40:59 +02:00
return m_equipDisplayFlags ;
2017-10-05 20:24:58 +02:00
}
2017-10-17 21:31:00 +02:00
void Core : : Entity : : Player : : mount ( uint32_t id )
{
2018-08-29 21:40:59 +02:00
m_mount = id ;
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ActorControlType : : SetStatus ,
static_cast < uint8_t > ( Common : : ActorStatus : : Mounted ) ) , true ) ;
sendToInRangeSet ( makeActorControl143 ( getId ( ) , 0x39e , 12 ) , true ) ; //?
2017-10-18 17:54:17 +02:00
2018-08-29 21:40:59 +02:00
auto mountPacket = makeZonePacket < FFXIVIpcMount > ( getId ( ) ) ;
mountPacket - > data ( ) . id = id ;
sendToInRangeSet ( mountPacket , true ) ;
2017-10-18 17:54:17 +02:00
}
void Core : : Entity : : Player : : dismount ( )
{
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ActorControlType : : SetStatus ,
static_cast < uint8_t > ( Common : : ActorStatus : : Idle ) ) , true ) ;
sendToInRangeSet ( makeActorControl143 ( getId ( ) , ActorControlType : : Dismount , 1 ) , true ) ;
m_mount = 0 ;
2017-10-18 17:54:17 +02:00
}
uint8_t Core : : Entity : : Player : : getCurrentMount ( ) const
{
2018-08-29 21:40:59 +02:00
return m_mount ;
2017-10-17 21:31:00 +02:00
}
2018-07-09 01:19:42 -03:00
void Core : : Entity : : Player : : setPersistentEmote ( uint32_t emoteId )
{
2018-08-29 21:40:59 +02:00
m_emoteMode = emoteId ;
2018-07-09 01:19:42 -03:00
}
uint32_t Core : : Entity : : Player : : getPersistentEmote ( ) const
{
2018-08-29 21:40:59 +02:00
return m_emoteMode ;
2018-07-09 01:19:42 -03:00
}
2018-02-20 22:46:44 +01:00
void Core : : Entity : : Player : : autoAttack ( CharaPtr pTarget )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto mainWeap = getItemAt ( Common : : GearSet0 , Common : : GearSetSlot : : MainHand ) ;
2017-08-11 00:58:35 -03:00
2018-08-29 21:40:59 +02:00
pTarget - > onActionHostile ( * this ) ;
//uint64_t tick = Util::getTimeMs();
//srand(static_cast< uint32_t >(tick));
2017-08-11 00:58:35 -03:00
2018-08-29 21:40:59 +02:00
uint32_t damage = static_cast < uint32_t > ( mainWeap - > getAutoAttackDmg ( ) ) ;
uint32_t variation = 0 + rand ( ) % 3 ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( getClass ( ) = = ClassJob : : Machinist | | getClass ( ) = = ClassJob : : Bard | | getClass ( ) = = ClassJob : : Archer )
{
auto effectPacket = boost : : make_shared < Server : : EffectPacket > ( getId ( ) , pTarget - > getId ( ) , 8 ) ;
effectPacket - > setRotation ( Math : : Util : : floatToUInt16Rot ( getRot ( ) ) ) ;
2018-07-21 23:32:10 +10:00
2018-08-29 21:40:59 +02:00
Server : : EffectEntry entry ;
entry . value = damage ;
entry . effectType = Common : : ActionEffectType : : Damage ;
entry . hitSeverity = Common : : ActionHitSeverityType : : NormalDamage ;
2018-07-21 23:32:10 +10:00
2018-08-29 21:40:59 +02:00
effectPacket - > addEffect ( entry ) ;
2018-07-21 23:32:10 +10:00
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( effectPacket , true ) ;
}
else
{
auto effectPacket = boost : : make_shared < Server : : EffectPacket > ( getId ( ) , pTarget - > getId ( ) , 7 ) ;
effectPacket - > setRotation ( Math : : Util : : floatToUInt16Rot ( getRot ( ) ) ) ;
2018-07-21 23:32:10 +10:00
2018-08-29 21:40:59 +02:00
Server : : EffectEntry entry ;
entry . value = damage ;
entry . effectType = Common : : ActionEffectType : : Damage ;
entry . hitSeverity = Common : : ActionHitSeverityType : : NormalDamage ;
2018-07-21 23:32:10 +10:00
2018-08-29 21:40:59 +02:00
effectPacket - > addEffect ( entry ) ;
2018-07-21 23:32:10 +10:00
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( effectPacket , true ) ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
}
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
pTarget - > takeDamage ( damage ) ;
2017-08-19 11:28:04 +09:00
2017-08-08 13:53:47 +02:00
}
2017-08-14 17:10:19 +02:00
2017-08-19 11:28:04 +09:00
/////////////////////////////
// Content Finder
/////////////////////////////
uint32_t Core : : Entity : : Player : : getCFPenaltyTimestamp ( ) const
{
2018-08-29 21:40:59 +02:00
return m_cfPenaltyUntil ;
2017-08-19 11:28:04 +09:00
}
void Core : : Entity : : Player : : setCFPenaltyTimestamp ( uint32_t timestamp )
{
2018-08-29 21:40:59 +02:00
m_cfPenaltyUntil = timestamp ;
2017-08-19 11:28:04 +09:00
}
uint32_t Core : : Entity : : Player : : getCFPenaltyMinutes ( ) const
{
2018-08-29 21:40:59 +02:00
auto currentTimestamp = Core : : Util : : getTimeSeconds ( ) ;
auto endTimestamp = getCFPenaltyTimestamp ( ) ;
2017-08-19 11:28:04 +09:00
2018-08-29 21:40:59 +02:00
// check if penalty timestamp already passed current time
if ( currentTimestamp > endTimestamp )
return 0 ;
2017-08-19 11:28:04 +09:00
2018-08-29 21:40:59 +02:00
auto deltaTime = endTimestamp - currentTimestamp ;
return static_cast < uint32_t > ( ceil ( static_cast < float > ( deltaTime ) / 60 ) ) ;
2017-08-19 11:28:04 +09:00
}
void Core : : Entity : : Player : : setCFPenaltyMinutes ( uint32_t minutes )
{
2018-08-29 21:40:59 +02:00
auto currentTimestamp = Core : : Util : : getTimeSeconds ( ) ;
setCFPenaltyTimestamp ( static_cast < uint32_t > ( currentTimestamp + minutes * 60 ) ) ;
2017-08-19 11:28:04 +09:00
}
2017-08-20 02:24:19 +02:00
uint8_t Core : : Entity : : Player : : getOpeningSequence ( ) const
{
2018-08-29 21:40:59 +02:00
return m_openingSequence ;
2017-08-20 02:24:19 +02:00
}
void Core : : Entity : : Player : : setOpeningSequence ( uint8_t seq )
{
2018-08-29 21:40:59 +02:00
m_openingSequence = seq ;
2017-09-22 22:03:57 +09:00
}
2017-11-16 00:03:36 -02:00
uint16_t Core : : Entity : : Player : : getItemLevel ( ) const
{
2018-08-29 21:40:59 +02:00
return m_itemLevel ;
2017-11-16 00:03:36 -02:00
}
2017-09-22 22:03:57 +09:00
/// Tells client to offset their eorzean time by given timestamp.
void Core : : Entity : : Player : : setEorzeaTimeOffset ( uint64_t timestamp )
{
2018-08-29 21:40:59 +02:00
// TODO: maybe change to persistent?
auto packet = makeZonePacket < FFXIVIpcEorzeaTimeOffset > ( getId ( ) ) ;
packet - > data ( ) . timestamp = timestamp ;
2017-09-22 22:03:57 +09:00
2018-08-29 21:40:59 +02:00
// Send to single player
queuePacket ( packet ) ;
2017-09-22 22:03:57 +09:00
}
2018-01-28 22:36:43 +01:00
2018-02-17 01:20:40 +01:00
void Core : : Entity : : Player : : setTerritoryId ( uint32_t territoryId )
2018-01-28 22:36:43 +01:00
{
2018-08-29 21:40:59 +02:00
m_zoneId = territoryId ;
2018-01-28 22:36:43 +01:00
}
2018-02-17 01:20:40 +01:00
uint32_t Core : : Entity : : Player : : getTerritoryId ( ) const
2018-01-28 22:36:43 +01:00
{
2018-08-29 21:40:59 +02:00
return m_zoneId ;
2018-01-28 22:36:43 +01:00
}
2018-02-17 01:20:40 +01:00
void Core : : Entity : : Player : : sendZonePackets ( )
2018-01-28 22:36:43 +01:00
{
2018-08-29 21:40:59 +02:00
getCurrentZone ( ) - > onBeforePlayerZoneIn ( * this ) ;
2018-02-23 23:47:21 +01:00
2018-08-29 21:40:59 +02:00
auto initPacket = makeZonePacket < FFXIVIpcInit > ( getId ( ) ) ;
initPacket - > data ( ) . charId = getId ( ) ;
queuePacket ( initPacket ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
sendInventory ( ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
if ( isLogin ( ) )
{
queuePacket ( makeActorControl143 ( getId ( ) , SetCharaGearParamUI , m_equipDisplayFlags , 1 ) ) ;
}
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
// set flags, will be reset automatically by zoning ( only on client side though )
//setStateFlag( PlayerStateFlag::BetweenAreas );
//setStateFlag( PlayerStateFlag::BetweenAreas1 );
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
sendStats ( ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
// only initialize the UI if the player in fact just logged in.
if ( isLogin ( ) )
{
auto contentFinderList = makeZonePacket < FFXIVIpcCFAvailableContents > ( getId ( ) ) ;
2018-06-28 00:07:07 +02:00
2018-08-29 21:40:59 +02:00
for ( auto i = 0 ; i < sizeof ( contentFinderList - > data ( ) . contents ) ; i + + )
{
// unlock all contents for now
contentFinderList - > data ( ) . contents [ i ] = 0xFF ;
}
queuePacket ( contentFinderList ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
queuePacket ( boost : : make_shared < InitUIPacket > ( * this ) ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
auto classInfoPacket = makeZonePacket < FFXIVIpcPlayerClassInfo > ( getId ( ) ) ;
classInfoPacket - > data ( ) . classId = static_cast < uint8_t > ( getClass ( ) ) ;
classInfoPacket - > data ( ) . unknown = 1 ;
classInfoPacket - > data ( ) . level = getLevel ( ) ;
classInfoPacket - > data ( ) . level1 = getLevel ( ) ;
queuePacket ( classInfoPacket ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
m_itemLevel = calculateEquippedGearItemLevel ( ) ;
sendItemLevel ( ) ;
}
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
auto initZonePacket = makeZonePacket < FFXIVIpcInitZone > ( getId ( ) ) ;
initZonePacket - > data ( ) . zoneId = getCurrentZone ( ) - > getTerritoryId ( ) ;
initZonePacket - > data ( ) . weatherId = static_cast < uint8_t > ( getCurrentZone ( ) - > getCurrentWeather ( ) ) ;
initZonePacket - > data ( ) . bitmask = 0x1 ;
initZonePacket - > data ( ) . unknown5 = 0x2A ;
initZonePacket - > data ( ) . festivalId = getCurrentZone ( ) - > getCurrentFestival ( ) ;
initZonePacket - > data ( ) . pos . x = getPos ( ) . x ;
initZonePacket - > data ( ) . pos . y = getPos ( ) . y ;
initZonePacket - > data ( ) . pos . z = getPos ( ) . z ;
queuePacket ( initZonePacket ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
if ( isLogin ( ) )
{
auto unk322 = makeZonePacket < FFXIVARR_IPC_UNK322 > ( getId ( ) ) ;
queuePacket ( unk322 ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
auto unk320 = makeZonePacket < FFXIVARR_IPC_UNK320 > ( getId ( ) ) ;
queuePacket ( unk320 ) ;
}
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
if ( getLastPing ( ) = = 0 )
sendQuestInfo ( ) ;
2018-01-28 22:36:43 +01:00
2018-08-29 21:40:59 +02:00
getCurrentZone ( ) - > onPlayerZoneIn ( * this ) ;
2018-02-04 23:58:45 +01:00
2018-08-29 21:40:59 +02:00
m_bMarkedForZoning = false ;
2018-01-28 22:36:43 +01:00
}
2018-02-07 00:00:48 +01:00
2018-02-17 01:20:40 +01:00
void Core : : Entity : : Player : : setDirectorInitialized ( bool isInitialized )
2018-02-07 00:00:48 +01:00
{
2018-08-29 21:40:59 +02:00
m_directorInitialized = isInitialized ;
2018-02-07 00:00:48 +01:00
}
2018-02-17 01:20:40 +01:00
bool Core : : Entity : : Player : : isDirectorInitialized ( ) const
2018-02-07 00:00:48 +01:00
{
2018-08-29 21:40:59 +02:00
return m_directorInitialized ;
2018-02-07 00:00:48 +01:00
}
2018-02-17 01:20:40 +01:00
2018-02-18 01:50:20 +01:00
void Core : : Entity : : Player : : sendTitleList ( )
2018-02-17 01:20:40 +01:00
{
2018-08-29 21:40:59 +02:00
auto titleListPacket = makeZonePacket < FFXIVIpcPlayerTitleList > ( getId ( ) ) ;
memcpy ( titleListPacket - > data ( ) . titleList , getTitleList ( ) , sizeof ( titleListPacket - > data ( ) . titleList ) ) ;
2018-02-17 01:20:40 +01:00
2018-08-29 21:40:59 +02:00
queuePacket ( titleListPacket ) ;
2018-02-17 01:20:40 +01:00
}
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
void
Core : : Entity : : Player : : sendZoneInPackets ( uint32_t param1 , uint32_t param2 = 0 , uint32_t param3 = 0 , uint32_t param4 = 0 ,
bool shouldSetStatus = false )
2018-04-19 22:22:20 +10:00
{
2018-08-29 21:40:59 +02:00
auto zoneInPacket = makeActorControl143 ( getId ( ) , ZoneIn , param1 , param2 , param3 , param4 ) ;
auto SetStatusPacket = makeActorControl142 ( getId ( ) , SetStatus , static_cast < uint8_t > ( Common : : ActorStatus : : Idle ) ) ;
2018-04-19 22:22:20 +10:00
2018-08-29 21:40:59 +02:00
if ( ! getGmInvis ( ) )
sendToInRangeSet ( zoneInPacket , true ) ;
if ( shouldSetStatus )
sendToInRangeSet ( SetStatusPacket ) ;
else
queuePacket ( zoneInPacket ) ;
if ( shouldSetStatus )
queuePacket ( SetStatusPacket ) ;
2018-04-19 22:22:20 +10:00
2018-08-29 21:40:59 +02:00
setZoningType ( Common : : ZoneingType : : None ) ;
unsetStateFlag ( PlayerStateFlag : : BetweenAreas ) ;
2018-04-19 22:22:20 +10:00
}
2018-02-18 01:50:20 +01:00
void Core : : Entity : : Player : : finishZoning ( )
{
2018-08-29 21:40:59 +02:00
switch ( getZoningType ( ) )
{
case ZoneingType : : None :
sendZoneInPackets ( 0x01 ) ;
break ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
case ZoneingType : : Teleport :
sendZoneInPackets ( 0x01 , 0 , 0 , 110 ) ;
break ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
case ZoneingType : : Return :
case ZoneingType : : ReturnDead :
{
if ( getStatus ( ) = = Common : : ActorStatus : : Dead )
2018-02-18 01:50:20 +01:00
{
2018-08-29 21:40:59 +02:00
resetHp ( ) ;
resetMp ( ) ;
setStatus ( Common : : ActorStatus : : Idle ) ;
sendZoneInPackets ( 0x01 , 0x01 , 0 , 111 , true ) ;
2018-02-18 01:50:20 +01:00
}
2018-08-29 21:40:59 +02:00
else
sendZoneInPackets ( 0x01 , 0x00 , 0 , 111 ) ;
}
2018-04-19 22:22:20 +10:00
break ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
case ZoneingType : : FadeIn :
break ;
}
2018-02-18 01:50:20 +01:00
}
2018-07-08 23:18:01 +02:00
void Core : : Entity : : Player : : emote ( uint32_t emoteId , uint64_t targetId , bool isSilent )
2018-02-18 01:50:20 +01:00
{
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( makeActorControl144 ( getId ( ) , ActorControlType : : Emote ,
emoteId , 0 , isSilent ? 1 : 0 , 0 , targetId ) ) ;
2018-02-18 01:50:20 +01:00
}
2018-07-08 23:44:37 +02:00
void Core : : Entity : : Player : : emoteInterrupt ( )
{
2018-08-29 21:40:59 +02:00
sendToInRangeSet ( makeActorControl142 ( getId ( ) , ActorControlType : : EmoteInterrupt ) ) ;
2018-07-08 23:44:37 +02:00
}
2018-02-24 23:53:32 +01:00
void Core : : Entity : : Player : : teleportQuery ( uint16_t aetheryteId )
2018-02-18 01:50:20 +01:00
{
2018-08-29 21:40:59 +02:00
auto pExdData = g_fw . get < Data : : ExdDataGenerated > ( ) ;
// TODO: only register this action if enough gil is in possession
auto targetAetheryte = pExdData - > get < Core : : Data : : Aetheryte > ( aetheryteId ) ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
if ( targetAetheryte )
{
auto fromAetheryte = pExdData - > get < Core : : Data : : Aetheryte > (
pExdData - > get < Core : : Data : : TerritoryType > ( getZoneId ( ) ) - > aetheryte ) ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
// calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets
auto cost = static_cast < uint16_t > (
( sqrt ( pow ( fromAetheryte - > aetherstreamX - targetAetheryte - > aetherstreamX , 2 ) +
pow ( fromAetheryte - > aetherstreamY - targetAetheryte - > aetherstreamY , 2 ) ) / 2 ) + 100 ) ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
// cap at 999 gil
cost = cost > uint16_t { 999 } ? uint16_t { 999 } : cost ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
bool insufficientGil = getCurrency ( Common : : CurrencyType : : Gil ) < cost ;
// TODO: figure out what param1 really does
queuePacket ( makeActorControl143 ( getId ( ) , TeleportStart , insufficientGil ? 2 : 0 , aetheryteId ) ) ;
2018-02-18 01:50:20 +01:00
2018-08-29 21:40:59 +02:00
if ( ! insufficientGil )
{
Action : : ActionPtr pActionTeleport ;
pActionTeleport = Action : : make_ActionTeleport ( getAsPlayer ( ) , aetheryteId , cost ) ;
setCurrentAction ( pActionTeleport ) ;
}
}
2018-02-18 01:50:20 +01:00
}
2018-02-23 23:47:21 +01:00
2018-02-28 23:53:20 +11:00
uint8_t Core : : Entity : : Player : : getNextObjSpawnIndexForActorId ( uint32_t actorId )
2018-02-23 23:47:21 +01:00
{
2018-08-29 21:40:59 +02:00
return m_objSpawnIndexAllocator . getNextFreeSpawnIndex ( actorId ) ;
2018-02-28 23:53:20 +11:00
}
void Core : : Entity : : Player : : resetObjSpawnIndex ( )
{
2018-08-29 21:40:59 +02:00
m_objSpawnIndexAllocator . freeAllSpawnIndexes ( ) ;
2018-02-28 23:53:20 +11:00
}
void Core : : Entity : : Player : : freeObjSpawnIndexForActorId ( uint32_t actorId )
{
2018-08-29 21:40:59 +02:00
auto spawnId = m_objSpawnIndexAllocator . freeUsedSpawnIndex ( actorId ) ;
2018-03-01 23:17:35 +01:00
2018-08-29 21:40:59 +02:00
auto freeObjectSpawnPacket = makeZonePacket < FFXIVIpcObjectDespawn > ( getId ( ) ) ;
freeObjectSpawnPacket - > data ( ) . spawnIndex = spawnId ;
queuePacket ( freeObjectSpawnPacket ) ;
2018-03-02 02:55:02 +11:00
}
2018-02-28 23:53:20 +11:00
2018-03-02 02:55:02 +11:00
bool Core : : Entity : : Player : : isObjSpawnIndexValid ( uint8_t index )
{
2018-08-29 21:40:59 +02:00
return m_objSpawnIndexAllocator . isSpawnIndexValid ( index ) ;
2018-02-24 23:53:32 +01:00
}
void Core : : Entity : : Player : : setOnEnterEventDone ( bool isDone )
{
2018-08-29 21:40:59 +02:00
m_onEnterEventDone = isDone ;
2018-02-24 23:53:32 +01:00
}
bool Core : : Entity : : Player : : isOnEnterEventDone ( ) const
{
2018-08-29 21:40:59 +02:00
return m_onEnterEventDone ;
2018-02-24 23:53:32 +01:00
}
2018-03-05 23:01:55 +01:00