2018-03-06 22:22:19 +01:00
# include <Common.h>
# include <Util/Util.h>
# include <Util/UtilMath.h>
# include <Logging/Logger.h>
2021-11-27 00:53:57 +01:00
# include <Exd/ExdData.h>
2019-10-27 08:26:48 +01:00
2018-10-26 14:11:02 +02:00
# include <cmath>
2021-11-27 00:53:57 +01:00
# include <utility>
2020-02-29 22:30:10 +11:00
# include <Service.h>
2017-12-08 15:38:25 +01:00
# include "Session.h"
2017-08-08 13:53:47 +02:00
# include "Player.h"
2019-01-19 22:56:07 +01:00
# include "BNpc.h"
2017-08-08 13:53:47 +02:00
2018-12-01 00:27:16 +11:00
# include "Manager/TerritoryMgr.h"
2019-04-17 22:36:23 +02:00
# include "Manager/RNGMgr.h"
2021-11-27 00:53:57 +01:00
# include "Manager/PlayerMgr.h"
# include "Manager/PartyMgr.h"
2022-01-30 14:44:17 +01:00
# include "Manager/WarpMgr.h"
2023-02-10 08:56:58 +01:00
# include "Manager/FreeCompanyMgr.h"
2023-02-16 22:16:01 +01:00
# include "Manager/MapMgr.h"
2023-02-17 15:34:51 +01:00
# include "Manager/MgrUtil.h"
2023-02-20 11:24:02 +01:00
# include "Manager/ActionMgr.h"
2023-03-06 10:12:29 +01:00
# include "Manager/AchievementMgr.h"
2019-01-13 17:32:43 +01:00
# include "Territory/InstanceContent.h"
2018-11-10 19:00:13 +01:00
2017-12-08 15:38:25 +01:00
# include "Network/GameConnection.h"
2021-11-27 00:53:57 +01:00
# include "Network/PacketContainer.h"
# include "Network/CommonActorControl.h"
2019-10-09 18:14:53 +02:00
# include "Network/PacketWrappers/ActorControlPacket.h"
# include "Network/PacketWrappers/ActorControlSelfPacket.h"
2017-12-08 15:38:25 +01:00
2021-11-27 00:53:57 +01:00
# include "Network/PacketWrappers/PlayerSpawnPacket.h"
2022-01-06 20:25:50 +01:00
# include "Network/PacketWrappers/EffectPacket1.h"
2021-11-27 00:53:57 +01:00
# include "Network/PacketWrappers/InitZonePacket.h"
2017-12-08 15:38:25 +01:00
2023-03-07 10:25:55 +01:00
# include "Network/Util/PacketUtil.h"
2023-03-05 23:27:35 +01:00
2019-03-07 21:58:12 +11:00
# include "Action/Action.h"
2017-12-08 15:38:25 +01:00
# include "Math/CalcStats.h"
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
# include "WorldServer.h"
2018-03-02 07:22:25 -03:00
2023-02-16 08:24:39 +01:00
# include <Manager/TaskMgr.h>
# include <Task/ActionIntegrityTask.h>
2022-02-05 23:31:35 +01:00
using namespace Sapphire ;
2018-11-29 16:55:48 +01:00
using namespace Sapphire : : Common ;
using namespace Sapphire : : Network : : Packets ;
2021-11-27 00:53:57 +01:00
using namespace Sapphire : : Network : : Packets : : WorldPackets : : Server ;
2018-11-29 16:55:48 +01:00
using namespace Sapphire : : Network : : ActorControl ;
2018-12-01 00:27:16 +11:00
using namespace Sapphire : : World : : Manager ;
2022-02-05 23:31:35 +01:00
using namespace Sapphire : : Entity ;
2017-08-08 13:53:47 +02:00
2018-11-29 16:55:48 +01:00
using InventoryMap = std : : map < uint16_t , Sapphire : : ItemContainerPtr > ;
2018-07-24 23:58:08 +02:00
using InvSlotPair = std : : pair < uint16_t , int8_t > ;
using InvSlotPairVec = std : : vector < InvSlotPair > ;
2017-08-08 13:53:47 +02:00
// player constructor
2022-02-05 23:31:35 +01:00
Player : : Player ( ) :
2020-03-01 01:00:57 +11:00
Chara ( ObjKind : : Player ) ,
2021-11-27 00:53:57 +01:00
m_lastDBWrite ( 0 ) ,
2018-08-29 21:40:59 +02:00
m_bIsLogin ( false ) ,
2021-11-27 00:53:57 +01:00
m_characterId ( 0 ) ,
2018-08-29 21:40:59 +02:00
m_modelMainWeapon ( 0 ) ,
m_modelSubWeapon ( 0 ) ,
m_homePoint ( 0 ) ,
m_startTown ( 0 ) ,
m_townWarpFstFlags ( 0 ) ,
m_playTime ( 0 ) ,
2021-11-27 00:53:57 +01:00
m_lastActionTick ( 0 ) ,
2018-08-29 21:40:59 +02:00
m_bInCombat ( false ) ,
m_bLoadingComplete ( false ) ,
m_bAutoattack ( false ) ,
m_markedForRemoval ( false ) ,
m_mount ( 0 ) ,
m_emoteMode ( 0 ) ,
m_directorInitialized ( false ) ,
2019-02-06 08:49:57 +01:00
m_onEnterEventDone ( false ) ,
2020-01-05 17:09:27 +09:00
m_falling ( false ) ,
2021-08-10 15:55:10 +09:00
m_pQueuedAction ( nullptr ) ,
2021-11-27 00:53:57 +01:00
m_partyId ( 0 ) ,
m_onlineStatusCustom ( 0 ) ,
2022-01-12 11:11:47 +01:00
m_onlineStatus ( 0 ) ,
m_bIsConnected ( false )
2018-08-29 21:40:59 +02:00
{
m_id = 0 ;
m_currentStance = Stance : : Passive ;
m_onlineStatus = 0 ;
m_status = ActorStatus : : Idle ;
m_invincibilityType = InvincibilityType : : InvincibilityNone ;
2019-04-21 23:52:41 +10:00
m_radius = 1.f ;
2018-08-29 21:40:59 +02:00
memset ( m_name , 0 , sizeof ( m_name ) ) ;
memset ( m_searchMessage , 0 , sizeof ( m_searchMessage ) ) ;
2023-01-17 08:28:06 +01:00
std : : fill ( std : : begin ( m_questTracking ) , std : : end ( m_questTracking ) , 0 ) ;
2023-02-20 15:25:57 +01:00
std : : fill ( std : : begin ( m_condition ) , std : : end ( m_condition ) , 0 ) ;
2023-01-17 08:28:06 +01:00
std : : fill ( std : : begin ( m_classArray ) , std : : end ( m_classArray ) , 0 ) ;
std : : fill ( std : : begin ( m_expArray ) , std : : end ( m_expArray ) , 0 ) ;
2021-11-27 00:53:57 +01:00
2021-12-13 22:36:29 -03:00
for ( uint8_t i = 0 ; i < 80 ; + + i )
2021-11-27 00:53:57 +01:00
{
m_recast [ i ] = 0.0f ;
m_recastMax [ i ] = 0.0f ;
}
2018-08-29 21:40:59 +02:00
2021-12-13 22:36:29 -03:00
for ( auto & i : m_charaLandData )
2018-11-07 11:59:59 +01:00
{
2021-11-27 00:53:57 +01:00
memset ( & i , 0xFF , 8 ) ;
2023-01-23 22:58:25 +01:00
memset ( & i . landFlags , 0 , 8 ) ;
2018-11-07 11:59:59 +01:00
}
2018-08-29 21:40:59 +02:00
m_objSpawnIndexAllocator . init ( MAX_DISPLAYED_EOBJS ) ;
m_actorSpawnIndexAllocator . init ( MAX_DISPLAYED_ACTORS , true ) ;
2021-11-27 00:53:57 +01:00
initHateSlotQueue ( ) ;
initSpawnIdQueue ( ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
Player : : ~ Player ( ) = default ;
2017-08-08 13:53:47 +02:00
2022-02-05 23:31:35 +01:00
void Player : : unload ( )
2018-03-05 22:10:14 +11:00
{
2021-11-27 00:53:57 +01:00
// do one last update to db
updateSql ( ) ;
// reset isLogin and loading sequences just in case
setIsLogin ( false ) ;
2022-01-12 11:11:47 +01:00
setConnected ( false ) ;
2021-11-27 00:53:57 +01:00
setLoadingComplete ( false ) ;
// unset player for removal
setMarkedForRemoval ( false ) ;
syncLastDBWrite ( ) ;
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
2022-02-05 23:31:35 +01:00
uint32_t Player : : getMaxHp ( )
2017-08-08 13:53:47 +02:00
{
2023-02-21 07:58:53 +01:00
return m_maxHp ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getMaxMp ( )
2017-08-08 13:53:47 +02:00
{
2023-02-21 07:58:53 +01:00
return m_maxMp ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getPrevTerritoryId ( ) const
2021-11-27 00:53:57 +01:00
{
return m_prevTerritoryId ;
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getGmRank ( ) const
2017-09-11 18:59:50 +02:00
{
2018-08-29 21:40:59 +02:00
return m_gmRank ;
2017-09-11 18:59:50 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setGmRank ( uint8_t rank )
2017-09-11 18:59:50 +02:00
{
2018-08-29 21:40:59 +02:00
m_gmRank = rank ;
2017-09-11 18:59:50 +02:00
}
2022-02-05 23:31:35 +01:00
bool Player : : getGmInvis ( ) const
2018-04-18 21:00:20 +10:00
{
2018-08-29 21:40:59 +02:00
return m_gmInvis ;
2018-04-18 21:00:20 +10:00
}
2022-02-05 23:31:35 +01:00
void Player : : setGmInvis ( bool invis )
2018-04-18 21:00:20 +10:00
{
2018-08-29 21:40:59 +02:00
m_gmInvis = invis ;
2018-04-18 21:00:20 +10:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isActingAsGm ( ) const
2018-07-01 21:31:49 +10:00
{
2018-08-29 21:40:59 +02:00
auto status = getOnlineStatus ( ) ;
2021-11-27 00:53:57 +01:00
return status = = OnlineStatus : : GameMaster | | status = = OnlineStatus : : GameMaster1 | | status = = OnlineStatus : : GameMaster2 ;
2018-07-01 21:31:49 +10:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getMode ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_mode ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setMode ( uint8_t mode )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_mode = mode ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getStartTown ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_startTown ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setMarkedForRemoval ( bool removal )
2017-11-14 23:55:38 +01:00
{
2021-11-27 00:53:57 +01:00
m_markedForRemoval = removal ;
2017-11-14 23:55:38 +01:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isMarkedForRemoval ( ) const
2017-11-14 23:55:38 +01:00
{
2018-08-29 21:40:59 +02:00
return m_markedForRemoval ;
2017-11-14 23:55:38 +01:00
}
2022-02-05 23:31:35 +01:00
Common : : OnlineStatus Player : : getOnlineStatus ( ) const
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2018-04-18 21:00:20 +10:00
2018-08-29 21:40:59 +02:00
uint32_t statusDisplayOrder = 0xFF14 ;
2023-03-02 07:38:14 +01:00
auto applicableStatus = isConnected ( ) ? static_cast < uint32_t > ( OnlineStatus : : Online ) : static_cast < uint32_t > ( OnlineStatus : : Offline ) ;
2018-04-19 23:04:31 +10:00
2021-11-27 00:53:57 +01:00
for ( uint32_t i = 0 ; i < std : : numeric_limits < decltype ( m_onlineStatus ) > : : digits ; + + i )
2018-08-29 21:40:59 +02:00
{
2021-11-27 00:53:57 +01:00
bool bit = ( getFullOnlineStatusMask ( ) > > 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
2022-01-27 21:24:54 +01:00
auto pOnlineStatus = exdData . getRow < Excel : : OnlineStatus > ( i ) ;
2018-08-29 21:40:59 +02:00
if ( ! pOnlineStatus )
continue ;
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
if ( pOnlineStatus - > data ( ) . ListOrder < statusDisplayOrder )
2018-08-29 21:40:59 +02:00
{
// todo: also check that the status can actually be set here, otherwise we need to ignore it (and ban the player obv)
2021-11-27 00:53:57 +01:00
statusDisplayOrder = pOnlineStatus - > data ( ) . ListOrder ;
2018-08-29 21:40:59 +02:00
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
}
2022-02-05 23:31:35 +01:00
void Player : : setOnlineStatusMask ( uint64_t status )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_onlineStatus = status ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getOnlineStatusMask ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_onlineStatus ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getFullOnlineStatusMask ( ) const
2021-11-27 00:53:57 +01:00
{
return m_onlineStatus | m_onlineStatusCustom ;
}
/*! sets the list of current online status */
2022-02-05 23:31:35 +01:00
void Player : : setOnlineStatusCustomMask ( uint64_t status )
2021-11-27 00:53:57 +01:00
{
m_onlineStatusCustom = status ;
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getOnlineStatusCustomMask ( ) const
2021-11-27 00:53:57 +01:00
{
return m_onlineStatusCustom ;
}
2022-02-05 23:31:35 +01:00
void Player : : addOnlineStatus ( OnlineStatus status )
2021-11-27 00:53:57 +01:00
{
uint64_t statusValue = 1ull < < static_cast < uint8_t > ( status ) ;
uint64_t newFlags = ( getOnlineStatusMask ( ) & getOnlineStatusCustomMask ( ) ) | statusValue ;
setOnlineStatusMask ( newFlags ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendOnlineStatus ( * this ) ;
2021-11-27 00:53:57 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : addOnlineStatus ( const std : : vector < Common : : OnlineStatus > & status )
2021-11-27 00:53:57 +01:00
{
uint64_t newFlags = getOnlineStatusMask ( ) ;
for ( const auto & state : status )
{
uint64_t statusValue = 1ull < < static_cast < uint8_t > ( state ) ;
newFlags | = statusValue ;
}
setOnlineStatusMask ( newFlags ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendOnlineStatus ( * this ) ;
2021-11-27 00:53:57 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : removeOnlineStatus ( OnlineStatus status )
2021-11-27 00:53:57 +01:00
{
uint64_t statusValue = 1ull < < static_cast < uint8_t > ( status ) ;
uint64_t newFlags = getOnlineStatusMask ( ) ;
uint64_t newFlagsCustom = getOnlineStatusCustomMask ( ) ;
newFlags & = ~ statusValue ;
newFlagsCustom & = ~ statusValue ;
setOnlineStatusMask ( newFlags ) ;
setOnlineStatusCustomMask ( newFlagsCustom ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendOnlineStatus ( * this ) ;
2021-11-27 00:53:57 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : removeOnlineStatus ( const std : : vector < Common : : OnlineStatus > & status )
2021-11-27 00:53:57 +01:00
{
uint64_t newFlags = getOnlineStatusMask ( ) ;
uint64_t newFlagsCustom = getOnlineStatusCustomMask ( ) ;
for ( const auto & state : status )
{
uint64_t statusValue = 1ull < < static_cast < uint8_t > ( state ) ;
newFlags & = ~ statusValue ;
newFlagsCustom & = ~ statusValue ;
}
setOnlineStatusMask ( newFlags ) ;
setOnlineStatusCustomMask ( newFlagsCustom ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendOnlineStatus ( * this ) ;
2021-11-27 00:53:57 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : calculateStats ( )
2017-08-08 13:53:47 +02:00
{
2023-02-10 17:14:09 -03:00
calculateBonusStats ( ) ;
2018-08-29 21:40:59 +02:00
uint8_t tribe = getLookAt ( Common : : CharaLook : : Tribe ) ;
uint8_t level = getLevel ( ) ;
2021-11-27 00:53:57 +01:00
auto job = static_cast < uint8_t > ( getClass ( ) ) ;
2023-01-06 22:18:29 -05:00
auto deity = getGuardianDeity ( ) ;
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2018-03-09 00:06:44 +01:00
2022-01-27 21:24:54 +01:00
auto classInfo = exdData . getRow < Excel : : ClassJob > ( job ) ;
auto tribeInfo = exdData . getRow < Excel : : Tribe > ( tribe ) ;
2023-01-06 22:18:29 -05:00
auto deityInfo = exdData . getRow < Excel : : GuardianDeity > ( deity ) ;
2022-01-27 21:24:54 +01:00
auto paramGrowthInfo = exdData . getRow < Excel : : ParamGrow > ( level ) ;
2017-08-08 13:53:47 +02:00
2019-04-24 23:25:07 +10:00
float base = Math : : CalcStats : : calculateBaseStat ( * this ) ;
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
auto str = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > data ( ) . STR ) / 100 ) ) + tribeInfo - > data ( ) . STR ;
auto dex = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > data ( ) . DEX ) / 100 ) ) + tribeInfo - > data ( ) . DEX ;
auto vit = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > data ( ) . VIT ) / 100 ) ) + tribeInfo - > data ( ) . VIT ;
auto inte = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > data ( ) . INT_ ) / 100 ) ) + tribeInfo - > data ( ) . INT_ ;
auto mnd = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > data ( ) . MND ) / 100 ) ) + tribeInfo - > data ( ) . MND ;
auto pie = static_cast < uint32_t > ( base * ( static_cast < float > ( classInfo - > data ( ) . PIE ) / 100 ) ) + tribeInfo - > data ( ) . PIE ;
setStatValue ( BaseParam : : Strength , str ) ;
setStatValue ( BaseParam : : Dexterity , dex ) ;
setStatValue ( BaseParam : : Vitality , vit ) ;
setStatValue ( BaseParam : : Intelligence , inte ) ;
setStatValue ( BaseParam : : Mind , mnd ) ;
setStatValue ( BaseParam : : Piety , pie ) ;
auto determination = static_cast < uint32_t > ( base ) ;
auto skillSpeed = paramGrowthInfo - > data ( ) . ParamBase ;
auto spellSpeed = paramGrowthInfo - > data ( ) . ParamBase ;
auto accuracy = paramGrowthInfo - > data ( ) . ParamBase ;
auto critHitRate = paramGrowthInfo - > data ( ) . ParamBase ;
auto parry = paramGrowthInfo - > data ( ) . ParamBase ;
setStatValue ( BaseParam : : Determination , determination ) ;
setStatValue ( BaseParam : : SkillSpeed , skillSpeed ) ;
setStatValue ( BaseParam : : SpellSpeed , spellSpeed ) ;
setStatValue ( BaseParam : : CriticalHit , critHitRate ) ;
setStatValue ( BaseParam : : Accuracy , accuracy ) ;
setStatValue ( BaseParam : : Parry , parry ) ;
2018-01-31 11:43:22 +01:00
2021-11-27 00:53:57 +01:00
setStatValue ( BaseParam : : Haste , 100 ) ;
setStatValue ( BaseParam : : Defense , 0 ) ;
setStatValue ( BaseParam : : MagicDefense , 0 ) ;
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
setStatValue ( BaseParam : : FireResistance , classInfo - > data ( ) . Element [ 0 ] ) ;
setStatValue ( BaseParam : : IceResistance , classInfo - > data ( ) . Element [ 1 ] ) ;
setStatValue ( BaseParam : : WindResistance , classInfo - > data ( ) . Element [ 2 ] ) ;
setStatValue ( BaseParam : : EarthResistance , classInfo - > data ( ) . Element [ 3 ] ) ;
setStatValue ( BaseParam : : LightningResistance , classInfo - > data ( ) . Element [ 4 ] ) ;
setStatValue ( BaseParam : : WaterResistance , classInfo - > data ( ) . Element [ 5 ] ) ;
2019-03-20 21:29:34 +01:00
2021-11-27 00:53:57 +01:00
setStatValue ( BaseParam : : AttackPower , str ) ;
setStatValue ( BaseParam : : AttackMagicPotency , inte ) ;
setStatValue ( BaseParam : : HealingMagicPotency , mnd ) ;
2017-08-19 11:28:04 +09:00
2023-01-06 22:18:29 -05:00
setStatValue ( BaseParam : : PiercingResistance , 0 ) ;
2023-02-21 07:58:53 +01:00
m_maxMp = Math : : CalcStats : : calculateMaxMp ( * this ) ;
2017-08-08 13:53:47 +02:00
2023-02-21 07:58:53 +01:00
m_maxHp = Math : : CalcStats : : calculateMaxHp ( * this ) ;
2017-08-08 13:53:47 +02:00
2023-02-21 07:58:53 +01:00
if ( m_mp > m_maxMp )
m_mp = m_maxMp ;
2017-08-08 13:53:47 +02:00
2023-02-21 07:58:53 +01:00
if ( m_hp > m_maxHp )
m_hp = m_maxHp ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setAutoattack ( bool mode )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_bAutoattack = mode ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isAutoattackOn ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_bAutoattack ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
bool Player : : exitInstance ( )
2018-01-29 13:05:33 +11:00
{
2022-01-30 14:44:17 +01:00
auto & warpMgr = Common : : Service < WarpMgr > : : ref ( ) ;
2019-01-13 17:32:43 +01:00
2019-04-09 23:17:00 +02:00
resetHp ( ) ;
resetMp ( ) ;
2023-02-20 11:24:02 +01:00
warpMgr . requestMoveTerritory ( * this , WarpType : : WARP_TYPE_CONTENT_END_RETURN , getPrevTerritoryId ( ) , getPrevPos ( ) , getPrevRot ( ) ) ;
2019-01-13 17:32:43 +01:00
2018-08-29 21:40:59 +02:00
return true ;
2018-01-29 13:05:33 +11:00
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getPlayTime ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_playTime ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getRace ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return getLookAt ( CharaLook : : Race ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getGender ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return getLookAt ( CharaLook : : Gender ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : initSpawnIdQueue ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_actorSpawnIndexAllocator . freeAllSpawnIndexes ( ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getSpawnIdForActorId ( uint32_t actorId )
2017-08-08 13:53:47 +02:00
{
2019-01-28 21:02:51 +11:00
auto index = m_actorSpawnIndexAllocator . getNextFreeSpawnIndex ( actorId ) ;
if ( index = = m_actorSpawnIndexAllocator . getAllocFailId ( ) )
{
Logger : : warn ( " Failed to spawn Chara#{0} for Player#{1} - no remaining spawn indexes available. "
" Consider lowering InRangeDistance in world config. " ,
actorId , getId ( ) ) ;
2021-11-27 00:53:57 +01:00
PlayerMgr : : sendUrgent ( * this , " Failed to spawn Chara#{0} for you - no remaining spawn slots. See world log. " , actorId ) ;
2019-01-28 21:02:51 +11:00
}
return index ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
bool 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
}
2022-02-05 23:31:35 +01:00
void Player : : registerAetheryte ( uint8_t aetheryteId )
2017-08-08 13:53:47 +02:00
{
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 ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , LearnTeleport , aetheryteId , 1 ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isAetheryteRegistered ( uint8_t aetheryteId ) const
2017-08-08 13:53:47 +02:00
{
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
}
2022-02-05 23:31:35 +01:00
Player : : Discovery & 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
}
2023-03-05 23:27:35 +01:00
void Player : : discover ( int16_t mapId , int16_t subId )
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2018-03-09 00:06:44 +01:00
2021-11-27 00:53:57 +01:00
int32_t offset ;
2017-08-08 13:53:47 +02:00
2023-03-05 23:27:35 +01:00
auto info = exdData . getRow < Excel : : Map > ( mapId ) ;
2021-11-27 00:53:57 +01:00
if ( ! info )
2020-03-03 08:37:19 +00:00
{
2023-03-05 23:27:35 +01:00
PlayerMgr : : sendDebug ( * this , " discover(): Could not obtain map data for map_id == {0} " , mapId ) ;
2020-03-03 08:37:19 +00:00
return ;
}
2023-03-05 23:27:35 +01:00
const auto & mapData = info - > data ( ) ;
2017-08-08 13:53:47 +02:00
2023-03-05 23:27:35 +01:00
if ( mapData . IsUint16Discovery )
offset = 2 * mapData . DiscoveryIndex ;
else
offset = 320 + 4 * mapData . DiscoveryIndex ;
2017-08-08 13:53:47 +02:00
2023-03-05 23:27:35 +01:00
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( subId , value , index ) ;
2017-08-08 13:53:47 +02:00
2023-03-05 23:27:35 +01:00
m_discovery [ offset + 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
2022-01-27 21:24:54 +01:00
uint32_t exp = ( exdData . getRow < Excel : : ParamGrow > ( level ) - > data ( ) . NextExp * 5 / 100 ) ;
2018-08-29 21:40:59 +02:00
gainExp ( exp ) ;
2017-08-08 13:53:47 +02:00
2020-03-02 08:52:28 +00:00
// gain 10x additional EXP if entire map is completed
2023-03-05 23:27:35 +01:00
uint32_t mask = mapData . DiscoveryFlag ;
2020-03-02 08:52:28 +00:00
uint32_t discoveredAreas ;
2021-11-27 00:53:57 +01:00
if ( info - > data ( ) . IsUint16Discovery )
2020-03-02 08:52:28 +00:00
{
2023-03-05 23:27:35 +01:00
discoveredAreas = ( m_discovery [ offset + 1 ] < < 8 ) | m_discovery [ offset ] ;
2020-03-02 08:52:28 +00:00
}
else
{
discoveredAreas = ( m_discovery [ offset + 3 ] < < 24 ) |
( m_discovery [ offset + 2 ] < < 16 ) |
( m_discovery [ offset + 1 ] < < 8 ) |
m_discovery [ offset ] ;
}
bool allDiscovered = ( ( discoveredAreas & mask ) = = mask ) ;
2017-08-08 13:53:47 +02:00
2020-03-02 08:52:28 +00:00
if ( allDiscovered )
{
gainExp ( exp * 10 ) ;
}
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isNewAdventurer ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_bNewAdventurer ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setNewAdventurer ( bool state )
2017-08-08 13:53:47 +02:00
{
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
}
2022-02-05 23:31:35 +01:00
void Player : : resetDiscovery ( )
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
memset ( m_discovery . data ( ) , 0 , m_discovery . size ( ) ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-28 08:40:57 +01:00
void Player : : setRewardFlag ( Common : : UnlockEntry unlockId )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
2021-11-27 00:53:57 +01:00
auto unlock = static_cast < uint16_t > ( unlockId ) ;
Util : : valueToFlagByteIndexValue ( unlock , 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
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , SetRewardFlag , unlock , 1 ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void 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 ;
2023-03-06 13:27:56 +01:00
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , ToggleOrchestrionUnlock , songId , 1 , itemId ) ;
2017-10-09 20:09:49 +02:00
}
2022-02-10 18:50:44 +01:00
bool Player : : hasReward ( Common : : UnlockEntry unlockId ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
uint16_t index ;
uint8_t value ;
2021-11-27 00:53:57 +01:00
Util : : valueToFlagByteIndexValue ( static_cast < uint16_t > ( unlockId ) , 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
}
2023-02-16 22:16:01 +01:00
bool Player : : hasMount ( uint32_t mountId ) const
{
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
auto mount = exdData . getRow < Excel : : Mount > ( mountId ) ;
if ( ! mount | | mount - > data ( ) . MountOrder = = - 1 | | mount - > data ( ) . Model = = 0 )
return false ;
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( mount - > data ( ) . MountOrder , value , index ) ;
return m_mountGuide [ index ] & value ;
}
2022-02-05 23:31:35 +01:00
void Player : : gainExp ( uint32_t amount )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
uint32_t currentExp = getExp ( ) ;
uint16_t level = getLevel ( ) ;
2023-03-06 13:27:56 +01:00
auto currentClass = static_cast < uint8_t > ( getClass ( ) ) ;
2017-08-08 13:53:47 +02:00
2020-02-27 00:59:28 +09:00
if ( level > = Common : : MAX_PLAYER_LEVEL )
{
setExp ( 0 ) ;
if ( currentExp ! = 0 )
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , UpdateUiExp , currentClass , 0 ) ;
2021-11-27 00:53:57 +01:00
2020-02-27 00:59:28 +09:00
return ;
}
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2017-08-08 13:53:47 +02:00
2022-01-27 21:24:54 +01:00
uint32_t neededExpToLevel = exdData . getRow < Excel : : ParamGrow > ( level ) - > data ( ) . NextExp ;
uint32_t neededExpToLevelPlus1 = exdData . getRow < Excel : : ParamGrow > ( level + 1 ) - > data ( ) . NextExp ;
2017-08-08 13:53:47 +02:00
2018-08-29 21:40:59 +02:00
if ( ( currentExp + amount ) > = neededExpToLevel )
{
// levelup
2023-03-06 13:27:56 +01:00
amount = ( currentExp + amount - neededExpToLevel ) > neededExpToLevelPlus1 ? neededExpToLevelPlus1 - 1 : ( currentExp + amount - neededExpToLevel ) ;
2023-03-05 23:27:35 +01:00
2020-02-27 00:59:28 +09:00
if ( level + 1 > = Common : : MAX_PLAYER_LEVEL )
amount = 0 ;
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
setExp ( amount ) ;
levelUp ( ) ;
2018-08-29 21:40:59 +02:00
}
else
setExp ( currentExp + amount ) ;
2023-03-05 23:27:35 +01:00
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , GainExpMsg , currentClass , amount ) ;
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , UpdateUiExp , currentClass , getExp ( ) ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : levelUp ( )
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
2021-11-27 00:53:57 +01:00
setLevel ( getLevel ( ) + 1 ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getLevel ( ) const
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-27 21:24:54 +01:00
uint8_t classJobIndex = exdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > data ( ) . WorkIndex ;
2018-08-29 21:40:59 +02:00
return static_cast < uint8_t > ( m_classArray [ classJobIndex ] ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getLevelSync ( ) const
2021-11-27 00:53:57 +01:00
{
// TODO: implement levelSync
return getLevel ( ) ;
}
2023-03-05 23:27:35 +01:00
uint8_t Player : : getLevelForClass ( Common : : ClassJob classJobId ) const
2017-08-09 14:38:46 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2023-03-05 23:27:35 +01:00
uint8_t classJobIndex = exdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( classJobId ) ) - > data ( ) . WorkIndex ;
2018-08-29 21:40:59 +02:00
return static_cast < uint8_t > ( m_classArray [ classJobIndex ] ) ;
2017-08-09 14:38:46 +02:00
}
2023-02-11 17:20:21 +01:00
Common : : ClassJob Player : : getFirstClass ( ) const
{
return m_firstClass ;
}
2022-02-05 23:31:35 +01:00
bool Player : : isClassJobUnlocked ( Common : : ClassJob classJob ) const
2018-08-26 16:19:05 +10:00
{
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
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getExp ( ) const
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-27 21:24:54 +01:00
uint8_t classJobIndex = exdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > data ( ) . WorkIndex ;
2018-08-29 21:40:59 +02:00
return m_expArray [ classJobIndex ] ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setExp ( uint32_t amount )
2018-08-29 21:40:59 +02:00
{
2022-01-24 09:20:34 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-27 21:24:54 +01:00
uint8_t classJobIndex = exdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > data ( ) . WorkIndex ;
2018-08-29 21:40:59 +02:00
m_expArray [ classJobIndex ] = amount ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isInCombat ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_bInCombat ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setInCombat ( bool mode )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
//m_lastAttack = GetTickCount();
m_bInCombat = mode ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setClassJob ( Common : : ClassJob classJob )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_class = classJob ;
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
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendStatusUpdate ( * this ) ;
2023-03-08 09:20:08 +01:00
Network : : Util : : Packet : : sendActorControl ( getInRangePlayerIds ( true ) , getId ( ) , ClassJobChange , 4 ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendHudParam ( * this ) ;
2023-02-16 22:16:01 +01:00
Service < World : : Manager : : MapMgr > : : ref ( ) . updateQuests ( * this ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setLevel ( uint8_t level )
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-27 21:24:54 +01:00
uint8_t classJobIndex = exdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) - > data ( ) . WorkIndex ;
2018-08-29 21:40:59 +02:00
m_classArray [ classJobIndex ] = level ;
2023-03-06 13:27:56 +01:00
calculateStats ( ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendBaseParams ( * this ) ;
Network : : Util : : Packet : : sendHudParam ( * this ) ;
Network : : Util : : Packet : : sendStatusUpdate ( * this ) ;
2023-04-18 16:42:25 +01:00
Network : : Util : : Packet : : sendActorControl ( getInRangePlayerIds ( true ) , getId ( ) , LevelUpEffect , static_cast < uint8_t > ( getClass ( ) ) , getLevel ( ) , getLevel ( ) - 1 ) ;
auto & achvMgr = Common : : Service < World : : Manager : : AchievementMgr > : : ref ( ) ;
achvMgr . progressAchievementByType < Common : : Achievement : : Type : : Classjob > ( * this , static_cast < uint32_t > ( getClass ( ) ) ) ;
Service < World : : Manager : : MapMgr > : : ref ( ) . updateQuests ( * this ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setLevelForClass ( uint8_t level , Common : : ClassJob classjob )
2017-08-09 14:38:46 +02:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-27 21:24:54 +01:00
uint8_t classJobIndex = exdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( classjob ) ) - > data ( ) . WorkIndex ;
2017-12-16 23:00:04 +11:00
2018-08-29 21:40:59 +02:00
if ( m_classArray [ classJobIndex ] = = 0 )
2021-11-27 00:53:57 +01:00
insertDbClass ( classJobIndex , level ) ;
2017-12-16 23:00:04 +11:00
2018-08-29 21:40:59 +02:00
m_classArray [ classJobIndex ] = level ;
2022-01-14 19:06:23 +01:00
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , ClassJobUpdate , static_cast < uint8_t > ( classjob ) , getLevelForClass ( classjob ) ) ;
2017-08-09 14:38:46 +02:00
2023-03-06 10:12:29 +01:00
auto & achvMgr = Common : : Service < World : : Manager : : AchievementMgr > : : ref ( ) ;
achvMgr . progressAchievementByType < Common : : Achievement : : Type : : Classjob > ( * this , static_cast < uint32_t > ( classjob ) ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getModelForSlot ( Common : : GearModelSlot 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
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getModelMainWeapon ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_modelMainWeapon ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getModelSubWeapon ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_modelSubWeapon ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getModelSystemWeapon ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_modelSystemWeapon ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getAetheryteMaskAt ( uint8_t index ) const
2017-08-08 13:53:47 +02:00
{
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
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getBirthDay ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_birthDay ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getBirthMonth ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_birthMonth ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getGuardianDeity ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_guardianDeity ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getLookAt ( uint8_t index ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_customize [ index ] ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setLookAt ( uint8_t index , uint8_t value )
2017-08-08 13:53:47 +02:00
{
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
2022-02-05 23:31:35 +01:00
void Player : : spawn ( Entity : : PlayerPtr pTarget )
2017-08-08 13:53:47 +02:00
{
2021-12-02 19:47:31 +01:00
Logger : : debug ( " Spawning {0} for {1} " , getName ( ) , pTarget - > getName ( ) ) ;
2021-12-01 01:03:36 +01:00
auto spawnPacket = std : : make_shared < PlayerSpawnPacket > ( * this , * pTarget ) ;
2023-02-17 15:34:51 +01:00
server ( ) . queueForPlayer ( pTarget - > getCharacterId ( ) , spawnPacket ) ;
2017-08-08 13:53:47 +02:00
}
// despawn
2022-02-05 23:31:35 +01:00
void Player : : despawn ( Entity : : PlayerPtr pTarget )
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
const auto & pPlayer = pTarget ;
2019-01-04 12:34:19 +01:00
Logger : : debug ( " Despawning {0} for {1} " , getName ( ) , pTarget - > getName ( ) ) ;
2018-02-21 18:06:52 +01:00
2018-08-29 21:40:59 +02:00
pPlayer - > freePlayerSpawnId ( getId ( ) ) ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , WarpStart , 4 , getId ( ) , 1 ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
GameObjectPtr Player : : lookupTargetById ( uint64_t targetId )
2017-08-10 22:06:05 +02:00
{
2021-11-27 00:53:57 +01:00
GameObjectPtr targetActor ;
2018-08-29 21:40:59 +02:00
auto inRange = getInRangeActors ( true ) ;
2021-11-27 00:53:57 +01:00
for ( const auto & actor : inRange )
2018-08-29 21:40:59 +02:00
{
if ( actor - > getId ( ) = = targetId )
targetActor = actor ;
}
return targetActor ;
2017-08-10 22:06:05 +02:00
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getLastDBWrite ( ) const
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
return m_lastDBWrite ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setVoiceId ( uint8_t voiceId )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_voice = voiceId ;
2017-08-08 13:53:47 +02:00
}
2023-03-05 23:27:35 +01:00
void Player : : setGrandCompany ( uint8_t gc )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_gc = gc ;
2023-03-05 23:27:35 +01:00
if ( m_gcRank [ gc ] = = 0 )
m_gcRank [ gc ] = 1 ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendGrandCompany ( * this ) ;
2017-08-08 13:53:47 +02:00
}
2023-03-05 23:27:35 +01:00
void Player : : setGrandCompanyRankAt ( uint8_t index , uint8_t rank )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_gcRank [ index ] = rank ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendGrandCompany ( * this ) ;
2017-08-08 13:53:47 +02:00
}
2023-02-20 16:41:04 +01:00
const Player : : Condition & Player : : getConditions ( ) const
2017-08-08 13:53:47 +02:00
{
2023-02-20 15:25:57 +01:00
return m_condition ;
2017-08-08 13:53:47 +02:00
}
2023-02-20 16:41:04 +01:00
bool Player : : hasCondition ( Common : : PlayerCondition flag ) const
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto iFlag = static_cast < int32_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
2023-02-20 15:25:57 +01:00
return ( m_condition [ index ] & value ) ! = 0 ;
2017-08-08 13:53:47 +02:00
}
2023-02-20 15:25:57 +01:00
void Player : : setCondition ( Common : : PlayerCondition flag )
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
auto iFlag = static_cast < int32_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
2023-02-20 15:25:57 +01:00
m_condition [ index ] | = value ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendCondition ( * this ) ;
2023-03-06 10:12:29 +01:00
}
void Player : : setConditions ( const std : : vector < Common : : PlayerCondition > & flags )
{
for ( auto flag : flags )
{
auto iFlag = static_cast < int32_t > ( flag ) ;
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( iFlag , value , index ) ;
m_condition [ index ] | = value ;
}
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendCondition ( * this ) ;
2017-08-08 13:53:47 +02:00
}
2023-02-20 15:25:57 +01:00
void Player : : removeCondition ( Common : : PlayerCondition flag )
2017-08-08 13:53:47 +02:00
{
2023-02-20 16:41:04 +01:00
if ( ! hasCondition ( flag ) )
2018-08-29 21:40:59 +02:00
return ;
2017-08-08 13:53:47 +02:00
2021-11-27 00:53:57 +01:00
auto iFlag = static_cast < int32_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
2023-02-20 15:25:57 +01:00
m_condition [ index ] ^ = value ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendCondition ( * this ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : update ( uint64_t tickCount )
2017-08-08 13:53:47 +02:00
{
2023-02-10 12:11:11 -03:00
// todo: better way to handle this override chara update
Service < World : : Manager : : PlayerMgr > : : ref ( ) . onUpdate ( * this , tickCount ) ;
2017-08-08 13:53:47 +02:00
2019-04-04 23:29:52 +02:00
Chara : : update ( tickCount ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : freePlayerSpawnId ( uint32_t actorId )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
auto spawnId = m_actorSpawnIndexAllocator . freeUsedSpawnIndex ( actorId ) ;
2017-08-08 13:53:47 +02:00
2019-01-28 20:29:30 +11:00
// actor was never spawned for this player
if ( spawnId = = m_actorSpawnIndexAllocator . getAllocFailId ( ) )
return ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendDeletePlayer ( * this , actorId , spawnId ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
Player : : AetheryteList & 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 */
2022-02-05 23:31:35 +01:00
void Player : : setHomepoint ( uint8_t aetheryteId )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_homePoint = aetheryteId ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , SetHomepoint , aetheryteId ) ;
2017-08-08 13:53:47 +02:00
}
/*! get homepoint */
2022-02-05 23:31:35 +01:00
uint8_t Player : : getHomepoint ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_homePoint ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
Player : : ClassList & 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
}
2022-02-05 23:31:35 +01:00
Player : : ExpList & 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
}
2022-02-05 23:31:35 +01:00
Player : : HowToList & 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
}
2022-02-05 23:31:35 +01:00
const Player : : UnlockList & 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
}
2022-02-05 23:31:35 +01:00
const Player : : OrchestrionList & Player : : getOrchestrionBitmask ( ) const
2017-10-09 20:09:49 +02:00
{
2018-08-29 21:40:59 +02:00
return m_orchestrion ;
2022-01-16 22:48:55 +01:00
}
2023-02-10 12:11:11 -03:00
void Player : : setOrchestrionBitmask ( const Player : : OrchestrionList & orchestrion )
{
m_orchestrion = orchestrion ;
}
2022-02-05 23:31:35 +01:00
void Player : : unlockMount ( uint32_t mountId )
2022-01-16 22:48:55 +01:00
{
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-27 21:24:54 +01:00
auto mount = exdData . getRow < Excel : : Mount > ( mountId ) ;
2022-01-16 22:48:55 +01:00
2022-01-16 23:19:10 +01:00
if ( mount - > data ( ) . MountOrder = = - 1 )
2022-01-16 22:48:55 +01:00
return ;
m_mountGuide [ mount - > data ( ) . MountOrder / 8 ] | = ( 1 < < ( mount - > data ( ) . MountOrder % 8 ) ) ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , SetMountBitmask , mount - > data ( ) . MountOrder , 1 ) ;
2017-10-09 20:09:49 +02:00
}
2023-01-23 21:39:12 +01:00
void Player : : unlockCompanion ( uint32_t companionId )
{
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
auto companion = exdData . getRow < Excel : : Companion > ( companionId ) ;
//if( companion->data(). == -1 )
// return;
uint16_t index ;
uint8_t value ;
Util : : valueToFlagByteIndexValue ( companionId , value , index ) ;
m_minionGuide [ index ] | = value ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , LearnCompanion , companionId , 1 ) ;
2023-01-23 21:39:12 +01:00
}
Player : : MinionList & Player : : getMinionGuideBitmask ( )
{
return m_minionGuide ;
}
2022-02-05 23:31:35 +01:00
Player : : MountList & Player : : getMountGuideBitmask ( )
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
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getCharacterId ( ) const
2021-08-30 10:16:05 +02:00
{
2021-11-27 00:53:57 +01:00
return m_characterId ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getVoiceId ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_voice ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getGc ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_gc ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
const std : : array < uint8_t , 3 > & 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
}
2022-02-05 23:31:35 +01:00
bool Player : : isLoadingComplete ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_bLoadingComplete ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setLoadingComplete ( bool bComplete )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_bLoadingComplete = bComplete ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setSearchInfo ( uint8_t selectRegion , uint8_t selectClass , const char * searchMessage )
2017-08-08 13:53:47 +02:00
{
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
}
2022-02-05 23:31:35 +01:00
const char * Player : : getSearchMessage ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return & m_searchMessage [ 0 ] ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getSearchSelectRegion ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_searchSelectRegion ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getSearchSelectClass ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_searchSelectClass ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : updateHowtosSeen ( uint32_t howToId )
2017-08-08 13:53:47 +02:00
{
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
}
2022-02-05 23:31:35 +01:00
void Player : : initHateSlotQueue ( )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_freeHateSlotQueue = std : : queue < uint8_t > ( ) ;
2021-11-27 00:53:57 +01:00
for ( int32_t i = 1 ; i < 26 ; + + i )
2018-08-29 21:40:59 +02:00
m_freeHateSlotQueue . push ( i ) ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : hateListAdd ( const BNpc & bnpc )
2019-01-19 22:56:07 +01:00
{
if ( ! m_freeHateSlotQueue . empty ( ) )
{
uint8_t hateId = m_freeHateSlotQueue . front ( ) ;
m_freeHateSlotQueue . pop ( ) ;
2021-11-27 00:53:57 +01:00
m_actorIdTohateSlotMap [ bnpc . getId ( ) ] = hateId ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendHateList ( * this ) ;
2019-01-19 22:56:07 +01:00
}
}
2022-02-05 23:31:35 +01:00
void Player : : hateListRemove ( const BNpc & bnpc )
2019-01-19 22:56:07 +01:00
{
auto it = m_actorIdTohateSlotMap . begin ( ) ;
for ( ; it ! = m_actorIdTohateSlotMap . end ( ) ; + + it )
{
2021-11-27 00:53:57 +01:00
if ( it - > first = = bnpc . getId ( ) )
2019-01-19 22:56:07 +01:00
{
uint8_t hateSlot = it - > second ;
m_freeHateSlotQueue . push ( hateSlot ) ;
m_actorIdTohateSlotMap . erase ( it ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendHateList ( * this ) ;
2019-01-19 22:56:07 +01:00
return ;
}
}
}
2022-02-05 23:31:35 +01:00
bool Player : : hateListHasEntry ( const BNpc & bnpc )
2019-01-19 22:56:07 +01:00
{
2021-11-27 00:53:57 +01:00
return std : : any_of ( m_actorIdTohateSlotMap . begin ( ) , m_actorIdTohateSlotMap . end ( ) ,
[ bnpc ] ( const auto & entry ) { return entry . first = = bnpc . getId ( ) ; } ) ;
2019-01-19 22:56:07 +01:00
}
2022-02-05 23:31:35 +01:00
const std : : map < uint32_t , uint8_t > & Player : : getActorIdToHateSlotMap ( )
2017-08-08 13:53:47 +02:00
{
2021-11-27 00:53:57 +01:00
return m_actorIdTohateSlotMap ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : onMobAggro ( const BNpc & bnpc )
2019-01-19 22:56:07 +01:00
{
2021-11-27 00:53:57 +01:00
hateListAdd ( bnpc ) ;
2023-04-30 19:36:24 +09:00
setCondition ( PlayerCondition : : InCombat ) ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControl ( * this , getId ( ) , SetBattle , 1 ) ;
2019-01-19 22:56:07 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : onMobDeaggro ( const BNpc & bnpc )
2019-01-19 22:56:07 +01:00
{
2021-11-27 00:53:57 +01:00
hateListRemove ( bnpc ) ;
2019-01-19 22:56:07 +01:00
if ( m_actorIdTohateSlotMap . empty ( ) )
2023-04-30 19:36:24 +09:00
{
removeCondition ( PlayerCondition : : InCombat ) ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControl ( * this , getId ( ) , SetBattle , 0 ) ;
2023-04-30 19:36:24 +09:00
}
2019-01-19 22:56:07 +01:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isLogin ( ) const
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
return m_bIsLogin ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setIsLogin ( bool bIsLogin )
2017-08-08 13:53:47 +02:00
{
2018-08-29 21:40:59 +02:00
m_bIsLogin = bIsLogin ;
2017-08-08 13:53:47 +02:00
}
2022-02-05 23:31:35 +01:00
Player : : TitleList & Player : : getTitleList ( )
2018-02-17 01:20:40 +01:00
{
2018-08-29 21:40:59 +02:00
return m_titleList ;
2018-02-17 01:20:40 +01:00
}
2022-02-05 23:31:35 +01:00
uint16_t 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
}
2022-02-05 23:31:35 +01:00
void Player : : addTitle ( uint16_t titleId )
2017-10-09 00:31:31 -03:00
{
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
}
2022-02-05 23:31:35 +01:00
void 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
2024-01-10 20:36:08 -08:00
if ( ( m_titleList [ index ] & value ) = = 0 & & titleId ! = 0 ) // Player doesn't have title and is not "no title" - bail
2018-08-29 21:40:59 +02:00
return ;
2017-10-09 01:56:47 -03:00
2018-08-29 21:40:59 +02:00
m_activeTitle = titleId ;
2023-03-08 09:20:08 +01:00
Network : : Util : : Packet : : sendActorControl ( getInRangePlayerIds ( true ) , getId ( ) , SetTitle , titleId ) ;
2017-10-04 23:19:38 -03:00
}
2023-01-27 18:54:54 -03:00
const Player : : AchievementData & Player : : getAchievementData ( ) const
2023-01-19 13:03:54 -03:00
{
return m_achievementData ;
}
2023-01-27 18:54:54 -03:00
void Player : : setAchievementData ( const Player : : AchievementData & achievementData )
2023-01-23 22:58:07 -03:00
{
2023-01-27 18:54:54 -03:00
m_achievementData = achievementData ;
2023-01-23 22:58:07 -03:00
}
2022-02-05 23:31:35 +01:00
void Player : : setMaxGearSets ( uint8_t amount )
2022-01-14 19:06:23 +01:00
{
m_equippedMannequin = amount ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , SetMaxGearSets , m_equippedMannequin ) ;
2022-01-14 19:06:23 +01:00
}
2023-02-12 23:11:26 +01:00
void Player : : addGearSet ( )
{
uint8_t amount = 1 ;
if ( getMaxGearSets ( ) = = 0 )
{
// unlock 5 gearsets the first time
amount = 5 ;
setRewardFlag ( UnlockEntry : : GearSets ) ;
}
setMaxGearSets ( getMaxGearSets ( ) + amount ) ;
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getMaxGearSets ( ) const
2022-01-14 19:06:23 +01:00
{
return m_equippedMannequin ;
}
2023-03-05 23:27:35 +01:00
void Player : : setConfigFlags ( uint16_t state )
2017-10-05 20:24:58 +02:00
{
2023-03-05 23:27:35 +01:00
m_configFlags = static_cast < uint8_t > ( state ) ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendConfigFlags ( * this ) ;
2017-10-05 20:24:58 +02:00
}
2023-03-05 23:27:35 +01:00
uint8_t Player : : getConfigFlags ( ) const
2017-10-05 20:24:58 +02:00
{
2023-03-05 23:27:35 +01:00
return m_configFlags ;
2017-10-05 20:24:58 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setMount ( uint32_t mountId )
2017-10-17 21:31:00 +02:00
{
2021-11-27 00:53:57 +01:00
m_mount = mountId ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendMount ( * this ) ;
2017-10-18 17:54:17 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setCompanion ( uint8_t id )
2019-02-02 23:06:57 +11:00
{
2023-03-06 10:12:29 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
auto companion = exdData . getRow < Excel : : Companion > ( id ) ;
if ( ! companion )
return ;
2019-02-02 23:06:57 +11:00
m_companionId = id ;
2023-03-06 10:12:29 +01:00
2023-03-08 09:20:08 +01:00
Network : : Util : : Packet : : sendActorControl ( getInRangePlayerIds ( true ) , getId ( ) , ToggleCompanion , id ) ;
2019-02-02 23:06:57 +11:00
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getCurrentCompanion ( ) const
2019-02-02 23:06:57 +11:00
{
return m_companionId ;
}
2022-02-05 23:31:35 +01:00
uint8_t Player : : getCurrentMount ( ) const
2017-10-18 17:54:17 +02:00
{
2018-08-29 21:40:59 +02:00
return m_mount ;
2017-10-17 21:31:00 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setPersistentEmote ( uint32_t emoteId )
2018-07-09 01:19:42 -03:00
{
2018-08-29 21:40:59 +02:00
m_emoteMode = emoteId ;
2018-07-09 01:19:42 -03:00
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getPersistentEmote ( ) const
2018-07-09 01:19:42 -03:00
{
2018-08-29 21:40:59 +02:00
return m_emoteMode ;
2018-07-09 01:19:42 -03:00
}
2022-02-05 23:31:35 +01:00
void Player : : autoAttack ( CharaPtr pTarget )
2017-08-08 13:53:47 +02:00
{
2022-01-24 09:20:34 +01:00
auto & teriMgr = Common : : Service < World : : Manager : : TerritoryMgr > : : ref ( ) ;
2023-02-20 11:24:02 +01:00
auto & actionMgr = Common : : Service < World : : Manager : : ActionMgr > : : ref ( ) ;
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2022-01-10 23:50:44 +01:00
auto pZone = teriMgr . getTerritoryByGuId ( getTerritoryId ( ) ) ;
2018-08-29 21:40:59 +02:00
auto mainWeap = getItemAt ( Common : : GearSet0 , Common : : GearSetSlot : : MainHand ) ;
2017-08-11 00:58:35 -03:00
2019-01-20 13:36:34 +01:00
pTarget - > onActionHostile ( getAsChara ( ) ) ;
2017-08-11 00:58:35 -03:00
2020-03-01 01:00:57 +11:00
auto & RNGMgr = Common : : Service < World : : Manager : : RNGMgr > : : ref ( ) ;
auto variation = static_cast < uint32_t > ( RNGMgr . getRandGenerator < float > ( 0 , 3 ) . next ( ) ) ;
2019-04-17 22:36:23 +02:00
2023-03-12 20:46:27 +01:00
actionMgr . handleTargetedAction ( * this , 7 , pTarget - > getId ( ) , 0 ) ;
2023-02-20 11:24:02 +01: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
/////////////////////////////
2022-02-05 23:31:35 +01:00
uint32_t Player : : getCFPenaltyTimestamp ( ) const
2017-08-19 11:28:04 +09:00
{
2018-08-29 21:40:59 +02:00
return m_cfPenaltyUntil ;
2017-08-19 11:28:04 +09:00
}
2022-02-05 23:31:35 +01:00
void Player : : setCFPenaltyTimestamp ( uint32_t timestamp )
2017-08-19 11:28:04 +09:00
{
2018-08-29 21:40:59 +02:00
m_cfPenaltyUntil = timestamp ;
2017-08-19 11:28:04 +09:00
}
2022-02-05 23:31:35 +01:00
uint32_t Player : : getCFPenaltyMinutes ( ) const
2017-08-19 11:28:04 +09:00
{
2019-06-02 00:34:22 +10:00
auto currentTimestamp = Common : : Util : : getTimeSeconds ( ) ;
2018-08-29 21:40:59 +02:00
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 ;
2021-11-27 00:53:57 +01:00
return static_cast < uint32_t > ( std : : ceil ( static_cast < float > ( deltaTime ) / 60 ) ) ;
2017-08-19 11:28:04 +09:00
}
2022-02-05 23:31:35 +01:00
void Player : : setCFPenaltyMinutes ( uint32_t minutes )
2017-08-19 11:28:04 +09:00
{
2019-06-02 00:34:22 +10:00
auto currentTimestamp = Common : : Util : : getTimeSeconds ( ) ;
2019-01-19 21:20:23 -02:00
setCFPenaltyTimestamp ( currentTimestamp + minutes * 60 ) ;
2017-08-19 11:28:04 +09:00
}
2017-08-20 02:24:19 +02:00
2022-02-05 23:31:35 +01:00
uint8_t Player : : getOpeningSequence ( ) const
2017-08-20 02:24:19 +02:00
{
2018-08-29 21:40:59 +02:00
return m_openingSequence ;
2017-08-20 02:24:19 +02:00
}
2022-02-05 23:31:35 +01:00
void Player : : setOpeningSequence ( uint8_t seq )
2017-08-20 02:24:19 +02:00
{
2018-08-29 21:40:59 +02:00
m_openingSequence = seq ;
2017-09-22 22:03:57 +09:00
}
2022-02-05 23:31:35 +01:00
uint16_t Player : : getItemLevel ( ) const
2017-11-16 00:03:36 -02:00
{
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.
2022-02-05 23:31:35 +01:00
void Player : : setEorzeaTimeOffset ( uint64_t timestamp )
2017-09-22 22:03:57 +09:00
{
2018-08-29 21:40:59 +02:00
// TODO: maybe change to persistent?
2019-07-29 22:22:45 +10:00
auto packet = makeZonePacket < FFXIVIpcEorzeaTimeOffset > ( getId ( ) ) ;
2018-08-29 21:40:59 +02:00
packet - > data ( ) . timestamp = timestamp ;
2017-09-22 22:03:57 +09:00
2018-08-29 21:40:59 +02:00
// Send to single player
2023-02-17 15:34:51 +01:00
server ( ) . queueForPlayer ( getCharacterId ( ) , packet ) ;
2017-09-22 22:03:57 +09:00
}
2018-01-28 22:36:43 +01:00
2022-02-05 23:31:35 +01:00
uint32_t Player : : getPrevTerritoryTypeId ( ) const
2018-01-28 22:36:43 +01:00
{
2021-11-27 00:53:57 +01:00
return m_prevTerritoryTypeId ;
}
2018-02-23 23:47:21 +01:00
2022-02-05 23:31:35 +01:00
void 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
}
2022-02-05 23:31:35 +01:00
bool 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
2024-05-17 16:44:44 -07:00
void Player : : teleportQuery ( uint16_t aetheryteId , bool useAetheryteTicket )
2019-02-08 21:20:53 +11:00
{
2021-11-27 00:53:57 +01:00
auto & exdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2019-03-07 21:58:12 +11:00
// TODO: only register this action if enough gil is in possession
2022-01-27 21:24:54 +01:00
auto targetAetheryte = exdData . getRow < Excel : : Aetheryte > ( aetheryteId ) ;
2019-03-07 21:58:12 +11:00
2023-03-05 23:27:35 +01:00
if ( ! targetAetheryte )
return ;
2019-03-07 21:58:12 +11:00
2023-03-05 23:27:35 +01:00
auto fromAetheryte = exdData . getRow < Excel : : Aetheryte > ( exdData . getRow < Excel : : TerritoryType > ( getTerritoryTypeId ( ) ) - > data ( ) . Aetheryte ) ;
2019-03-07 21:58:12 +11:00
2024-05-17 16:44:44 -07:00
// calculate cost - does not apply for favorite points or homepoints
// if using aetheryte ticket, cost is 0
auto cost = useAetheryteTicket ? 0 : static_cast < uint16_t > (
2023-03-05 23:27:35 +01:00
( std : : sqrt ( std : : pow ( fromAetheryte - > data ( ) . CostPosX - targetAetheryte - > data ( ) . CostPosX , 2 ) +
2024-05-17 16:44:44 -07:00
std : : pow ( fromAetheryte - > data ( ) . CostPosY - targetAetheryte - > data ( ) . CostPosY , 2 ) ) / 2 ) + 100 ) ;
2019-03-07 21:58:12 +11:00
2023-03-05 23:27:35 +01:00
// cap at 999 gil
cost = std : : min < uint16_t > ( 999 , cost ) ;
2019-03-07 21:58:12 +11:00
2023-03-05 23:27:35 +01:00
bool insufficientGil = getCurrency ( Common : : CurrencyType : : Gil ) < cost ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , OnExecuteTelepo , insufficientGil ? 2 : 0 , aetheryteId ) ;
2023-03-05 23:27:35 +01:00
if ( ! insufficientGil )
{
m_teleportQuery . targetAetheryte = aetheryteId ;
m_teleportQuery . cost = cost ;
2024-05-17 16:44:44 -07:00
m_teleportQuery . useAetheryteTicket = useAetheryteTicket ;
2019-03-07 21:58:12 +11:00
}
2023-03-05 23:27:35 +01:00
else
{
clearTeleportQuery ( ) ;
}
2019-03-07 21:58:12 +11:00
}
2022-02-05 23:31:35 +01:00
Sapphire : : Common : : PlayerTeleportQuery Player : : getTeleportQuery ( ) const
2019-03-07 21:58:12 +11:00
{
return m_teleportQuery ;
}
2022-02-05 23:31:35 +01:00
void Player : : clearTeleportQuery ( )
2019-03-07 21:58:12 +11:00
{
memset ( & m_teleportQuery , 0x0 , sizeof ( Common : : PlayerTeleportQuery ) ) ;
2018-02-18 01:50:20 +01:00
}
2018-02-23 23:47:21 +01:00
2022-02-05 23:31:35 +01:00
uint8_t Player : : getNextObjSpawnIndexForActorId ( uint32_t actorId )
2018-02-23 23:47:21 +01:00
{
2019-01-28 21:02:51 +11:00
auto index = m_objSpawnIndexAllocator . getNextFreeSpawnIndex ( actorId ) ;
if ( index = = m_objSpawnIndexAllocator . getAllocFailId ( ) )
{
Logger : : warn ( " Failed to spawn EObj#{0} for Player#{1} - no remaining spawn indexes available. "
" Consider lowering InRangeDistance in world config. " ,
actorId , getId ( ) ) ;
2021-11-27 00:53:57 +01:00
PlayerMgr : : sendUrgent ( * this , " Failed to spawn EObj#{0} for you - no remaining spawn slots. See world log. " , actorId ) ;
2019-01-28 21:02:51 +11:00
return index ;
}
return index ;
2018-02-28 23:53:20 +11:00
}
2022-02-05 23:31:35 +01:00
void Player : : setDyeingInfo ( uint32_t itemToDyeContainer , uint32_t itemToDyeSlot , uint32_t dyeBagContainer , uint32_t dyeBagSlot )
2020-03-14 00:31:14 -07:00
{
m_dyeingInfo . itemToDyeContainer = itemToDyeContainer ;
m_dyeingInfo . itemToDyeSlot = itemToDyeSlot ;
m_dyeingInfo . dyeBagContainer = dyeBagContainer ;
m_dyeingInfo . dyeBagSlot = dyeBagSlot ;
}
2022-02-05 23:31:35 +01:00
void Player : : dyeItemFromDyeingInfo ( )
2020-03-14 00:31:14 -07:00
{
uint32_t itemToDyeContainer = m_dyeingInfo . itemToDyeContainer ;
uint32_t itemToDyeSlot = m_dyeingInfo . itemToDyeSlot ;
uint32_t dyeBagContainer = m_dyeingInfo . dyeBagContainer ;
uint32_t dyeBagSlot = m_dyeingInfo . dyeBagSlot ;
2023-03-06 10:12:29 +01:00
setCondition ( Common : : PlayerCondition : : None1 ) ;
2020-03-16 01:35:49 -07:00
auto itemToDye = getItemAt ( itemToDyeContainer , itemToDyeSlot ) ;
auto dyeToUse = getItemAt ( dyeBagContainer , dyeBagSlot ) ;
2020-03-14 00:31:14 -07:00
2021-11-27 00:53:57 +01:00
if ( ! itemToDye | | ! dyeToUse )
return ;
2020-03-14 00:31:14 -07:00
2023-02-08 21:44:51 +01:00
if ( ! removeItem ( dyeToUse - > getId ( ) ) )
return ;
2020-03-14 00:31:14 -07:00
uint32_t stainColorID = dyeToUse - > getAdditionalData ( ) ;
2023-02-08 21:44:51 +01:00
bool shouldDye = stainColorID ! = 0 ;
bool invalidateGearSet = stainColorID ! = itemToDye - > getStain ( ) ;
2020-03-16 01:35:49 -07:00
itemToDye - > setStain ( stainColorID ) ;
2020-03-14 00:31:14 -07:00
2020-03-16 02:08:35 -07:00
insertInventoryItem ( static_cast < Sapphire : : Common : : InventoryType > ( itemToDyeContainer ) , static_cast < uint16_t > ( itemToDyeSlot ) , itemToDye ) ;
2021-11-27 00:53:57 +01:00
writeItem ( itemToDye ) ;
2023-02-08 21:44:51 +01:00
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , DyeMsg , itemToDye - > getId ( ) , shouldDye , invalidateGearSet ) ;
2020-03-14 00:31:14 -07:00
}
2023-02-09 20:56:26 +01:00
void Player : : setGlamouringInfo ( uint32_t itemToGlamourContainer , uint32_t itemToGlamourSlot , uint32_t glamourBagContainer , uint32_t glamourBagSlot , bool shouldGlamour )
{
m_glamouringInfo . itemToGlamourContainer = itemToGlamourContainer ;
m_glamouringInfo . itemToGlamourSlot = itemToGlamourSlot ;
m_glamouringInfo . glamourBagContainer = glamourBagContainer ;
m_glamouringInfo . glamourBagSlot = glamourBagSlot ;
m_glamouringInfo . shouldGlamour = shouldGlamour ;
}
void Player : : glamourItemFromGlamouringInfo ( )
{
auto & playerMgr = Service < World : : Manager : : PlayerMgr > : : ref ( ) ;
uint32_t itemToGlamourContainer = m_glamouringInfo . itemToGlamourContainer ;
uint32_t itemToGlamourSlot = m_glamouringInfo . itemToGlamourSlot ;
uint32_t glamourBagContainer = m_glamouringInfo . glamourBagContainer ;
uint32_t glamourBagSlot = m_glamouringInfo . glamourBagSlot ;
bool shouldGlamour = m_glamouringInfo . shouldGlamour ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendCondition ( * this ) ;
2023-02-09 20:56:26 +01:00
auto itemToGlamour = getItemAt ( itemToGlamourContainer , itemToGlamourSlot ) ;
auto glamourToUse = getItemAt ( glamourBagContainer , glamourBagSlot ) ;
//auto prismToUse = getItemAt( glamourBagContainer, glamourBagSlot );
if ( ! itemToGlamour )
return ;
//if( !removeItem( prismToUse->getId() ) )
// return;
uint32_t patternID = itemToGlamour - > getPattern ( ) ;
bool invalidateGearSet = shouldGlamour ? patternID ! = glamourToUse - > getId ( ) : true ;
if ( shouldGlamour )
{
itemToGlamour - > setPattern ( glamourToUse - > getId ( ) ) ;
itemToGlamour - > setStain ( glamourToUse - > getStain ( ) ) ;
}
else
{
itemToGlamour - > setPattern ( 0 ) ;
itemToGlamour - > setStain ( 0 ) ;
}
itemToGlamour - > setGlamModelIds ( ) ;
insertInventoryItem ( static_cast < Sapphire : : Common : : InventoryType > ( itemToGlamourContainer ) , static_cast < uint16_t > ( itemToGlamourSlot ) , itemToGlamour ) ;
writeItem ( itemToGlamour ) ;
if ( shouldGlamour )
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , GlamourCastMsg , itemToGlamour - > getId ( ) , glamourToUse - > getId ( ) , invalidateGearSet ) ;
2023-02-09 20:56:26 +01:00
else
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , GlamourRemoveMsg , itemToGlamour - > getId ( ) , invalidateGearSet ) ;
2023-02-09 20:56:26 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : resetObjSpawnIndex ( )
2018-02-28 23:53:20 +11:00
{
2018-08-29 21:40:59 +02:00
m_objSpawnIndexAllocator . freeAllSpawnIndexes ( ) ;
2018-02-28 23:53:20 +11:00
}
2022-02-05 23:31:35 +01:00
void Player : : freeObjSpawnIndexForActorId ( uint32_t actorId )
2018-02-28 23:53:20 +11:00
{
2018-08-29 21:40:59 +02:00
auto spawnId = m_objSpawnIndexAllocator . freeUsedSpawnIndex ( actorId ) ;
2018-03-01 23:17:35 +01:00
2019-01-28 20:29:30 +11:00
// obj was never spawned for this player
if ( spawnId = = m_objSpawnIndexAllocator . getAllocFailId ( ) )
return ;
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendDeleteObject ( * this , spawnId ) ;
2018-03-02 02:55:02 +11:00
}
2018-02-28 23:53:20 +11:00
2022-02-05 23:31:35 +01:00
bool Player : : isObjSpawnIndexValid ( uint8_t index )
2018-03-02 02:55:02 +11:00
{
2018-08-29 21:40:59 +02:00
return m_objSpawnIndexAllocator . isSpawnIndexValid ( index ) ;
2018-02-24 23:53:32 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : setOnEnterEventDone ( bool isDone )
2018-02-24 23:53:32 +01:00
{
2018-08-29 21:40:59 +02:00
m_onEnterEventDone = isDone ;
2018-02-24 23:53:32 +01:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isOnEnterEventDone ( ) const
2018-02-24 23:53:32 +01:00
{
2018-08-29 21:40:59 +02:00
return m_onEnterEventDone ;
2018-02-24 23:53:32 +01:00
}
2018-11-07 11:59:59 +01:00
2022-02-05 23:31:35 +01:00
void Player : : setLandFlags ( uint8_t flagSlot , uint32_t landFlags , Common : : LandIdent ident )
2018-11-07 11:59:59 +01:00
{
2021-11-27 00:53:57 +01:00
auto & server = Common : : Service < World : : WorldServer > : : ref ( ) ;
m_charaLandData [ flagSlot ] . landId = ident ;
2023-01-27 22:33:16 +01:00
m_charaLandData [ flagSlot ] . landId . worldId = static_cast < int16_t > ( server . getWorldId ( ) ) ;
2023-01-23 22:58:25 +01:00
m_charaLandData [ flagSlot ] . landFlags = landFlags ;
2018-11-10 22:04:40 +01:00
}
2018-11-07 11:59:59 +01:00
2022-02-05 23:31:35 +01:00
Sapphire : : Common : : HuntingLogEntry & Player : : getHuntingLogEntry ( uint8_t index )
2019-03-26 00:04:27 +01:00
{
assert ( index < m_huntingLogEntries . size ( ) ) ;
return m_huntingLogEntries [ index ] ;
}
2019-03-26 23:08:34 +01:00
2022-02-05 23:31:35 +01:00
void Player : : updateHuntingLog ( uint16_t id )
2019-03-28 22:58:40 +01:00
{
std : : vector < uint32_t > rankRewards { 2500 , 10000 , 20000 , 30000 , 40000 } ;
const auto maxRank = 4 ;
2021-11-27 00:53:57 +01:00
auto & pExdData = Common : : Service < Data : : ExdData > : : ref ( ) ;
2023-01-19 14:34:53 -06:00
// make sure we get the matching base-class if a job is being used
auto classJobInfo = pExdData . getRow < Excel : : ClassJob > ( static_cast < uint8_t > ( getClass ( ) ) ) ;
if ( ! classJobInfo )
return ;
auto currentClassId = classJobInfo - > data ( ) . MainClass ;
2019-03-28 22:58:40 +01:00
2021-11-27 00:53:57 +01:00
auto & logEntry = m_huntingLogEntries [ currentClassId - 1 ] ;
2019-03-28 22:58:40 +01:00
bool logChanged = false ;
2019-04-06 17:17:56 +02:00
2019-03-28 22:58:40 +01:00
bool allSectionsComplete = true ;
for ( int i = 1 ; i < = 10 ; + + i )
{
bool sectionComplete = true ;
bool sectionChanged = false ;
2021-11-27 00:53:57 +01:00
auto monsterNoteId = static_cast < uint32_t > ( classJobInfo - > data ( ) . MainClass * 10000 + logEntry . rank * 10 + i ) ;
2022-01-27 21:24:54 +01:00
auto note = pExdData . getRow < Excel : : MonsterNote > ( monsterNoteId ) ;
2019-04-06 11:44:06 +11:00
// for classes that don't have entries, if the first fails the rest will fail
if ( ! note )
break ;
2019-03-28 22:58:40 +01:00
for ( auto x = 0 ; x < 4 ; + + x )
{
2022-01-27 21:24:54 +01:00
auto note1 = pExdData . getRow < Excel : : MonsterNoteTarget > ( note - > data ( ) . Target [ x ] ) ;
2021-12-07 00:51:09 +01:00
if ( note1 - > data ( ) . Monster = = id & & logEntry . entries [ i - 1 ] [ x ] < note - > data ( ) . NeededKills [ x ] )
2019-03-28 22:58:40 +01:00
{
logEntry . entries [ i - 1 ] [ x ] + + ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , HuntingLogEntryUpdate , monsterNoteId , x , logEntry . entries [ i - 1 ] [ x ] ) ;
2019-03-28 22:58:40 +01:00
logChanged = true ;
sectionChanged = true ;
}
2021-12-07 00:51:09 +01:00
if ( logEntry . entries [ i - 1 ] [ x ] ! = note - > data ( ) . NeededKills [ x ] )
2019-03-28 22:58:40 +01:00
sectionComplete = false ;
}
if ( logChanged & & sectionComplete & & sectionChanged )
{
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , HuntingLogSectionFinish , monsterNoteId , i , 0 ) ;
2021-11-27 00:53:57 +01:00
gainExp ( note - > data ( ) . RewardExp ) ;
2019-03-28 22:58:40 +01:00
}
if ( ! sectionComplete )
{
allSectionsComplete = false ;
}
}
if ( logChanged & & allSectionsComplete )
{
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , HuntingLogRankFinish , 4 ) ;
2019-03-28 22:58:40 +01:00
gainExp ( rankRewards [ logEntry . rank ] ) ;
if ( logEntry . rank < 4 )
{
logEntry . rank + + ;
memset ( logEntry . entries , 0 , 40 ) ;
2023-03-09 21:54:30 +01:00
Network : : Util : : Packet : : sendActorControlSelf ( * this , getId ( ) , HuntingLogRankUnlock , currentClassId , logEntry . rank + 1 , 0 ) ;
2019-03-28 22:58:40 +01:00
}
}
2019-04-07 16:04:36 +10:00
2019-04-06 11:44:06 +11:00
if ( logChanged )
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendHuntingLog ( * this ) ;
2019-03-28 22:58:40 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : setActiveLand ( uint8_t land , uint8_t ward )
2019-04-24 23:25:07 +10:00
{
m_activeLand . plot = land ;
m_activeLand . ward = ward ;
}
2022-02-05 23:31:35 +01:00
Sapphire : : Common : : ActiveLand Player : : getActiveLand ( ) const
2019-04-24 23:25:07 +10:00
{
return m_activeLand ;
}
2020-01-05 17:09:27 +09:00
2022-02-05 23:31:35 +01:00
bool Player : : hasQueuedAction ( ) const
2020-01-05 17:09:27 +09:00
{
return m_pQueuedAction ! = nullptr ;
}
2022-02-05 23:31:35 +01:00
void Player : : setQueuedAction ( Sapphire : : World : : Action : : ActionPtr pAction )
2020-01-05 17:09:27 +09:00
{
2020-01-05 20:49:50 +09:00
m_pQueuedAction = std : : move ( pAction ) ; // overwrite previous queued action if any
2020-01-05 17:09:27 +09:00
}
2022-02-05 23:31:35 +01:00
void Player : : setLastActionTick ( uint64_t tick )
2021-11-27 00:53:57 +01:00
{
m_lastActionTick = tick ;
}
2022-02-05 23:31:35 +01:00
uint64_t Player : : getLastActionTick ( ) const
2021-11-27 00:53:57 +01:00
{
return m_lastActionTick ;
}
2022-02-05 23:31:35 +01:00
void Player : : setRecastGroup ( uint8_t index , float time )
2021-11-27 00:53:57 +01:00
{
m_recast [ index ] = time ;
if ( time > m_recastMax [ index ] )
m_recastMax [ index ] = time ;
}
2022-02-05 23:31:35 +01:00
float Player : : getRecastGroup ( uint8_t index ) const
2021-11-27 00:53:57 +01:00
{
return m_recast [ index ] ;
}
2023-03-06 10:12:29 +01:00
const std : : array < float , 80 > & Player : : getRecastGroups ( ) const
2021-11-27 00:53:57 +01:00
{
2023-03-06 10:12:29 +01:00
return m_recast ;
}
const std : : array < float , 80 > & Player : : getRecastGroupsMax ( ) const
{
return m_recastMax ;
2021-11-27 00:53:57 +01:00
}
2022-02-05 23:31:35 +01:00
void Player : : resetRecastGroups ( )
2021-11-27 00:53:57 +01:00
{
for ( size_t i = 0 ; i < 80 ; + + i )
{
m_recast [ i ] = 0.0f ;
m_recastMax [ i ] = 0.0f ;
}
2023-03-07 10:25:55 +01:00
Network : : Util : : Packet : : sendRecastGroups ( * this ) ;
2021-11-27 00:53:57 +01:00
}
2022-02-05 23:31:35 +01:00
bool Player : : checkAction ( )
2020-01-05 17:09:27 +09:00
{
if ( m_pCurrentAction = = nullptr )
return false ;
if ( m_pCurrentAction - > update ( ) )
{
if ( m_pCurrentAction - > isInterrupted ( ) & & m_pCurrentAction - > getInterruptType ( ) ! = Common : : ActionInterruptType : : DamageInterrupt )
m_pQueuedAction = nullptr ;
m_pCurrentAction = nullptr ;
if ( hasQueuedAction ( ) )
{
2021-11-27 00:53:57 +01:00
PlayerMgr : : sendDebug ( * this , " Queued skill start: {0} " , m_pQueuedAction - > getId ( ) ) ;
2020-01-05 17:09:27 +09:00
if ( m_pQueuedAction - > hasCastTime ( ) )
setCurrentAction ( m_pQueuedAction ) ;
m_pQueuedAction - > start ( ) ;
m_pQueuedAction = nullptr ;
}
}
return true ;
2020-03-03 08:37:19 +00:00
}
2020-04-24 19:24:04 +09:00
2022-02-05 23:31:35 +01:00
uint64_t Player : : getPartyId ( ) const
2020-05-11 06:25:25 +09:00
{
2021-11-27 00:53:57 +01:00
return m_partyId ;
2020-05-11 06:25:25 +09:00
}
2022-02-05 23:31:35 +01:00
void Player : : setPartyId ( uint64_t partyId )
2020-05-11 06:25:25 +09:00
{
2021-11-27 00:53:57 +01:00
m_partyId = partyId ;
2020-05-11 06:25:25 +09:00
}
2023-02-20 11:24:02 +01:00
Player : : FriendListIDVec & Player : : getFriendListId ( )
2021-12-01 21:30:12 -03:00
{
return m_friendList ;
}
2021-12-13 22:36:29 -03:00
2022-02-05 23:31:35 +01:00
Player : : FriendListDataVec & Player : : getFriendListData ( )
2021-12-01 21:30:12 -03:00
{
return m_friendInviteList ;
}
2023-02-20 11:24:02 +01:00
Player : : FriendListIDVec & Player : : getBlacklistId ( )
2021-12-13 22:36:29 -03:00
{
return m_blacklist ;
}
2022-02-05 23:31:35 +01:00
void Player : : setFalling ( bool state , const Common : : FFXIVARR_POSITION3 & pos , bool ignoreDamage )
2022-01-05 20:56:02 -03:00
{
bool isFalling = m_falling ;
auto initialPos = m_initialFallPos ;
// update internal values - only use scoped values for old state
m_falling = state ;
m_initialFallPos = pos ;
if ( ignoreDamage )
return ;
// if the player is currently falling and new state is grounded - calc and apply fall dmg
if ( isFalling & & ! state )
{
// calc height difference
auto fallHeight = initialPos . y - pos . y ;
// if we've hit the breakpoint in fall damage (min: 10y)
if ( fallHeight > = 10.f )
{
2023-02-10 15:21:48 -03:00
// calculate how much damage to deal out (max. 30y : 100%)
2022-01-06 20:25:50 +01:00
float deltaMax = std : : min ( fallHeight , 30.f ) ;
2022-01-05 20:56:02 -03:00
// get hp percentage starting from 0.1, increasing to 100% at max height
2022-01-06 20:25:50 +01:00
float hpPer = std : : min ( 0.1f + ( deltaMax - 10.f ) / 20.f , 1.f ) ;
2022-01-05 20:56:02 -03:00
2022-01-27 18:35:19 -03:00
auto damage = static_cast < uint32_t > ( getMaxHp ( ) * hpPer ) ;
2022-01-05 20:56:02 -03:00
// check if player has aggro - if not, player should "live"
if ( m_actorIdTohateSlotMap . empty ( ) )
{
// "trick" client into thinking we took more damage than internally passed to takeDamage, if > playerHp
uint32_t surviveDamage = damage ;
if ( surviveDamage > = getHp ( ) )
{
surviveDamage = ( getHp ( ) - 1 ) ;
}
takeDamage ( surviveDamage ) ;
}
else
{
// no mercy on hated players
takeDamage ( damage ) ;
}
2023-03-08 09:20:08 +01:00
Network : : Util : : Packet : : sendActorControl ( getInRangePlayerIds ( true ) , getId ( ) , SetFallDamage , damage ) ;
2022-01-05 20:56:02 -03:00
}
}
}
2022-02-05 23:31:35 +01:00
bool Player : : isFalling ( ) const
2022-01-05 20:56:02 -03:00
{
return m_falling ;
}
2022-02-05 23:31:35 +01:00
void Player : : setLastPcSearchResult ( std : : vector < uint32_t > result )
2020-05-11 06:25:25 +09:00
{
2021-11-27 00:53:57 +01:00
m_lastPcSearch = std : : move ( result ) ;
2020-05-11 06:25:25 +09:00
}
2022-02-05 23:31:35 +01:00
std : : vector < uint32_t > & Player : : getLastPcSearchResult ( )
2020-04-24 19:24:04 +09:00
{
2021-11-27 00:53:57 +01:00
return m_lastPcSearch ;
2020-04-24 19:24:04 +09:00
}
2022-02-05 23:31:35 +01:00
const FFXIVARR_POSITION3 & Player : : getPrevPos ( ) const
2020-04-24 19:24:04 +09:00
{
2021-11-27 00:53:57 +01:00
return m_prevPos ;
}
2020-04-24 19:24:04 +09:00
2022-02-05 23:31:35 +01:00
float Player : : getPrevRot ( ) const
2021-11-27 00:53:57 +01:00
{
return m_prevRot ;
2020-04-24 19:24:04 +09:00
}
2022-02-05 23:31:35 +01:00
bool Player : : isConnected ( ) const
2022-01-12 11:11:47 +01:00
{
return m_bIsConnected ;
}
2022-02-05 23:31:35 +01:00
void Player : : setConnected ( bool isConnected )
2022-01-12 11:11:47 +01:00
{
m_bIsConnected = isConnected ;
}
2022-01-30 14:44:17 +01:00
2022-02-05 23:31:35 +01:00
void Player : : updatePrevTerritory ( )
2022-01-30 14:44:17 +01:00
{
auto & teriMgr = Common : : Service < World : : Manager : : TerritoryMgr > : : ref ( ) ;
2023-01-26 22:39:50 +01:00
if ( teriMgr . isDefaultTerritory ( getTerritoryTypeId ( ) ) | | teriMgr . isHousingTerritory ( getTerritoryTypeId ( ) ) )
2022-01-30 14:44:17 +01:00
{
m_prevTerritoryTypeId = getTerritoryTypeId ( ) ;
m_prevTerritoryId = getTerritoryId ( ) ;
m_prevPos = m_pos ;
m_prevRot = m_rot ;
}
}
2023-01-27 11:13:57 +01:00
const CharaLandData & Entity : : Player : : getCharaLandData ( Common : : LandFlagsSlot slot ) const
{
return m_charaLandData [ slot ] ;
}