1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-03 17:27:47 +00:00
sapphire/src/world/Actor/GameObject.cpp

361 lines
7.2 KiB
C++
Raw Normal View History

#include "GameObject.h"
2017-08-08 13:53:47 +02:00
2018-03-06 22:22:19 +01:00
#include <Network/PacketContainer.h>
2018-06-02 15:52:35 +02:00
2018-03-06 22:22:19 +01:00
#include <Util/UtilMath.h>
2018-06-28 00:07:07 +02:00
#include <utility>
#include <Service.h>
2019-07-21 22:33:33 +10:00
#include "Territory/Territory.h"
#include "Network/GameConnection.h"
#include "Chara.h"
#include "EventObject.h"
#include "Player.h"
#include "BNpc.h"
#include "WorldServer.h"
#include "Session.h"
#include "Manager/TerritoryMgr.h"
#include "StatusEffect/StatusEffect.h"
using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::Network::Packets;
//using namespace Sapphire::Network::Packets::Server;
2017-08-08 13:53:47 +02:00
GameObject::GameObject( ObjKind type ) :
m_objKind( type )
2017-08-08 13:53:47 +02:00
{
}
uint32_t GameObject::getId() const
2017-08-08 13:53:47 +02:00
{
return m_id;
2017-08-08 13:53:47 +02:00
}
void GameObject::setId( uint32_t id )
{
m_id = id;
}
ObjKind GameObject::getObjKind() const
2017-08-08 13:53:47 +02:00
{
return m_objKind;
2017-08-08 13:53:47 +02:00
}
FFXIVARR_POSITION3& GameObject::getPos()
2017-08-08 13:53:47 +02:00
{
return m_pos;
2017-08-08 13:53:47 +02:00
}
const FFXIVARR_POSITION3& GameObject::getPos() const
2019-04-05 13:15:14 +02:00
{
return m_pos;
}
void GameObject::setPos( float x, float y, float z, bool broadcastUpdate )
2017-08-08 13:53:47 +02:00
{
m_pos.x = x;
m_pos.y = y;
m_pos.z = z;
if( broadcastUpdate )
{
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
pZone->updateActorPosition( *this );
}
2017-08-08 13:53:47 +02:00
}
void GameObject::setPos( const FFXIVARR_POSITION3& pos, bool broadcastUpdate )
2017-08-08 13:53:47 +02:00
{
m_pos = pos;
if( broadcastUpdate )
{
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
pZone->updateActorPosition( *this );
}
}
float GameObject::getRot() const
{
return m_rot;
2017-09-06 20:25:58 +02:00
}
void GameObject::setRot( float rot )
2017-09-06 20:25:58 +02:00
{
m_rot = rot;
}
bool GameObject::isChara() const
{
return isPlayer() || isBattleNpc() || isEventNpc() || isRetainer() || isCompanion();
}
bool GameObject::isPlayer() const
{
return m_objKind == ObjKind::Player;
}
bool GameObject::isEventNpc() const
{
return m_objKind == ObjKind::EventNpc;
}
bool GameObject::isBattleNpc() const
{
return m_objKind == ObjKind::BattleNpc;
}
bool GameObject::isRetainer() const
{
return m_objKind == ObjKind::Retainer;
}
bool GameObject::isCompanion() const
{
return m_objKind == ObjKind::Companion;
}
bool GameObject::isEventObj() const
{
return m_objKind == ObjKind::EventObj;
}
bool GameObject::isHousingEventObj() const
{
return m_objKind == ObjKind::Housing;
}
bool GameObject::isAetheryte() const
{
return m_objKind == ObjKind::Aetheryte;
}
/*! \return pointer to this instance as GameObjectPtr */
CharaPtr GameObject::getAsChara()
{
if( !isChara() )
return nullptr;
return std::dynamic_pointer_cast< Chara, GameObject >( shared_from_this() );
}
/*! \return pointer to this instance as PlayerPtr */
PlayerPtr GameObject::getAsPlayer()
{
if( !isPlayer() )
return nullptr;
return std::dynamic_pointer_cast< Player, GameObject >( shared_from_this() );
}
/*! \return pointer to this instance as EventObjPtr */
EventObjectPtr GameObject::getAsEventObj()
{
if( !isEventObj() )
return nullptr;
return std::dynamic_pointer_cast< EventObject, GameObject >( shared_from_this() );
}
/*! \return pointer to this instance as BNpcPtr */
BNpcPtr GameObject::getAsBNpc()
{
if( !isBattleNpc() )
return nullptr;
return std::dynamic_pointer_cast< BNpc, GameObject >( shared_from_this() );
}
/*!
Add a given actor to the fitting in range set according to type
but also to the global actor map
\param GameObjectPtr to add
*/
void GameObject::addInRangeActor( GameObjectPtr pActor )
{
// if this is null, something went wrong
assert( pActor );
// add actor to in range set
m_inRangeActor.insert( pActor );
if( pActor->isPlayer() )
{
auto pPlayer = pActor->getAsPlayer();
spawn( pPlayer );
// if actor is a player, add it to the in range player set
m_inRangePlayers.insert( pPlayer );
}
else if( pActor->isBattleNpc() )
{
auto pBNpc = pActor->getAsBNpc();
// if actor is a player, add it to the in range player set
m_inRangeBNpc.insert( pBNpc );
}
}
/*!
Remove a given actor from the matching in range set according to type
but also to the global actor map
\param GameObjectPtr to remove
*/
void GameObject::removeInRangeActor( GameObject& actor )
{
// call virtual event
onRemoveInRangeActor( actor );
// remove actor from in range actor set
m_inRangeActor.erase( actor.shared_from_this() );
// if actor is a player, despawn ourself for him
// TODO: move to virtual onRemove?
if( isPlayer() )
actor.despawn( getAsPlayer() );
if( actor.isPlayer() )
m_inRangePlayers.erase( actor.getAsPlayer() );
if( actor.isBattleNpc() )
m_inRangeBNpc.erase( actor.getAsBNpc() );
}
/*! \return true if there is at least one actor in the in range set */
bool GameObject::hasInRangeActor() const
{
return ( !m_inRangeActor.empty() );
}
void GameObject::removeFromInRange()
{
if( !hasInRangeActor() )
return;
for( auto& pCurAct : m_inRangeActor )
{
pCurAct->removeInRangeActor( *this );
}
}
/*!
check if a given actor is in the actors in range set
\param GameObjectPtr to be checked for
\return true if the actor was found
*/
bool GameObject::isInRangeSet( GameObjectPtr pActor ) const
{
return !( m_inRangeActor.find( pActor ) == m_inRangeActor.end() );
}
/*! \return GameObjectPtr of the closest actor in range, if none, nullptr */
CharaPtr GameObject::getClosestChara()
{
if( m_inRangeActor.empty() )
// no actors in range, don't bother
return nullptr;
CharaPtr tmpActor = nullptr;
// arbitrary high number
float minDistance = 10000;
for( const auto& pCurAct : m_inRangeActor )
{
float distance = Util::distance( getPos().x, getPos().y, getPos().z, pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z );
if( distance < minDistance )
{
minDistance = distance;
tmpActor = pCurAct->getAsChara();
}
}
return tmpActor;
}
/*! Clear the whole in range set, this does no cleanup */
void GameObject::clearInRangeSet()
{
m_inRangeActor.clear();
m_inRangePlayers.clear();
m_inRangeBNpc.clear();
}
/*! \return list of actors currently in range */
std::set< GameObjectPtr > GameObject::getInRangeActors( bool includeSelf )
{
auto tempInRange = m_inRangeActor;
if( includeSelf )
tempInRange.insert( shared_from_this() );
return tempInRange;
}
std::set< uint64_t > GameObject::getInRangePlayerIds( bool includeSelf )
{
std::set< uint64_t > playerIds;
for( auto& player : m_inRangePlayers )
playerIds.insert( player->getCharacterId() );
if( isPlayer() && includeSelf )
playerIds.insert( getAsPlayer()->getCharacterId() );
return playerIds;
}
uint32_t GameObject::getTerritoryTypeId() const
{
return m_territoryTypeId;
}
void GameObject::setTerritoryTypeId( uint32_t territoryTypeId )
{
m_territoryTypeId = territoryTypeId;
}
uint32_t GameObject::getTerritoryId() const
{
return m_territoryId;
}
void GameObject::setTerritoryId( uint32_t territoryId )
{
m_territoryId = territoryId;
}
/*!
Get the current cellId of a region the actor is in
\return CellId
*/
CellId GameObject::getCellId() const
{
return m_cellId;
}
/*!
Set the current cellId the actor is in
\param CellId for the cell to be set
*/
void GameObject::setCellId( CellId cellId )
{
m_cellId = cellId;
2017-08-08 13:53:47 +02:00
}