mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-25 14:07:46 +00:00
Actors are now used as base for any entity
This commit is contained in:
parent
b806535f11
commit
dc1a7e4ae1
14 changed files with 278 additions and 262 deletions
|
@ -708,16 +708,6 @@ namespace Common {
|
|||
MountSkill = 0xD,
|
||||
};
|
||||
|
||||
/*! ModelType as found in eventsystemdefine.exd */
|
||||
enum ModelType : uint8_t
|
||||
{
|
||||
Human = 1,
|
||||
DemiHuman = 2,
|
||||
Monster = 3,
|
||||
SharedGroup = 4,
|
||||
Parts = 5
|
||||
};
|
||||
|
||||
typedef std::vector< PlayerStateFlag > PlayerStateFlagList;
|
||||
|
||||
} /* Common */
|
||||
|
|
|
@ -382,7 +382,7 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket<PlayerSpawn>
|
|||
uint8_t spawnIndex;
|
||||
uint8_t state;
|
||||
uint8_t persistantEmote;
|
||||
uint8_t type; // modelType -> eventSystemDefine
|
||||
uint8_t modelType; // modelType -> eventSystemDefine
|
||||
uint8_t subtype;
|
||||
uint8_t voice;
|
||||
uint16_t u25c;
|
||||
|
@ -458,7 +458,7 @@ struct FFXIVIpcNpcSpawn : FFXIVIpcBasePacket<NpcSpawn>
|
|||
uint8_t spawnIndex;
|
||||
uint8_t state;
|
||||
uint8_t persistantEmote;
|
||||
uint8_t type;
|
||||
uint8_t modelType;
|
||||
uint8_t subtype;
|
||||
uint8_t voice;
|
||||
uint16_t u25c;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <common/Util/UtilMath.h>
|
||||
|
||||
#include "ActionCollision.h"
|
||||
#include "Actor/Actor.h"
|
||||
#include "Actor/Chara.h"
|
||||
#include "Actor/Player.h"
|
||||
|
||||
|
@ -13,7 +14,7 @@ using namespace Core::Common;
|
|||
|
||||
// todo: add AoE actor limits (16, 32)
|
||||
|
||||
bool ActionCollision::isActorApplicable( Chara& chara, TargetFilter targetFilter )
|
||||
bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter )
|
||||
{
|
||||
bool actorApplicable = false;
|
||||
switch( targetFilter )
|
||||
|
@ -25,7 +26,7 @@ bool ActionCollision::isActorApplicable( Chara& chara, TargetFilter targetFilter
|
|||
}
|
||||
case TargetFilter::Players:
|
||||
{
|
||||
actorApplicable = chara.isPlayer();
|
||||
actorApplicable = actor.isPlayer();
|
||||
break;
|
||||
}
|
||||
case TargetFilter::Allies:
|
||||
|
@ -37,7 +38,7 @@ bool ActionCollision::isActorApplicable( Chara& chara, TargetFilter targetFilter
|
|||
case TargetFilter::Party:
|
||||
{
|
||||
// todo: implement party
|
||||
actorApplicable = chara.isPlayer();
|
||||
actorApplicable = actor.isPlayer();
|
||||
break;
|
||||
}
|
||||
case TargetFilter::Enemies:
|
||||
|
@ -47,15 +48,15 @@ bool ActionCollision::isActorApplicable( Chara& chara, TargetFilter targetFilter
|
|||
}
|
||||
}
|
||||
|
||||
return ( actorApplicable && chara.isAlive() );
|
||||
return ( actorApplicable && actor.getAsChara()->isAlive() );
|
||||
}
|
||||
|
||||
std::set< Core::Entity::CharaPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition,
|
||||
std::set< CharaPtr > actorsInRange,
|
||||
std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition,
|
||||
std::set< ActorPtr > actorsInRange,
|
||||
boost::shared_ptr< Core::Data::Action > actionInfo,
|
||||
TargetFilter targetFilter )
|
||||
{
|
||||
std::set< CharaPtr > actorsCollided;
|
||||
std::set< ActorPtr > actorsCollided;
|
||||
|
||||
switch( static_cast< ActionCollisionType >( actionInfo->castType ) )
|
||||
{
|
||||
|
|
|
@ -23,9 +23,9 @@ namespace Entity {
|
|||
{
|
||||
public:
|
||||
|
||||
static bool isActorApplicable( Chara& actor, TargetFilter targetFilter );
|
||||
static std::set< CharaPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition,
|
||||
std::set< CharaPtr > actorsInRange,
|
||||
static bool isActorApplicable( Actor& actor, TargetFilter targetFilter );
|
||||
static std::set< ActorPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition,
|
||||
std::set< ActorPtr > actorsInRange,
|
||||
boost::shared_ptr< Data::Action > actionInfo,
|
||||
TargetFilter targetFilter );
|
||||
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
#include "Actor.h"
|
||||
|
||||
#include "Player.h"
|
||||
#include <common/Network/PacketContainer.h>
|
||||
#include <common/Network/GamePacket.h>
|
||||
#include <common/Util/Util.h>
|
||||
#include <common/Util/UtilMath.h>
|
||||
|
||||
#include "Chara.h"
|
||||
#include "Network/GameConnection.h"
|
||||
#include "Player.h"
|
||||
#include "ServerZone.h"
|
||||
#include "Session.h"
|
||||
|
||||
extern Core::ServerZone g_serverZone;
|
||||
|
||||
Core::Entity::Actor::Actor( ObjKind type ) :
|
||||
m_objKind( type )
|
||||
|
@ -65,3 +75,165 @@ Core::Entity::PlayerPtr Core::Entity::Actor::getAsPlayer()
|
|||
return boost::dynamic_pointer_cast< Entity::Player, Entity::Actor >( shared_from_this() );
|
||||
}
|
||||
|
||||
/*!
|
||||
Add a given actor to the fitting in range set according to type
|
||||
but also to the global actor map
|
||||
|
||||
\param ActorPtr to add
|
||||
*/
|
||||
void Core::Entity::Actor::addInRangeActor( ActorPtr 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();
|
||||
|
||||
pPlayer->spawn( getAsPlayer() );
|
||||
|
||||
// if actor is a player, add it to the in range player set
|
||||
m_inRangePlayers.insert( pPlayer );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Remove a given actor from the matching in range set according to type
|
||||
but also to the global actor map
|
||||
|
||||
\param ActorPtr to remove
|
||||
*/
|
||||
void Core::Entity::Actor::removeInRangeActor( Actor& 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() );
|
||||
}
|
||||
|
||||
/*! \return true if there is at least one actor in the in range set */
|
||||
bool Core::Entity::Actor::hasInRangeActor() const
|
||||
{
|
||||
return ( m_inRangeActor.size() > 0 );
|
||||
}
|
||||
|
||||
void Core::Entity::Actor::removeFromInRange()
|
||||
{
|
||||
if( !hasInRangeActor() )
|
||||
return;
|
||||
|
||||
Entity::ActorPtr pCurAct;
|
||||
|
||||
for( auto& pCurAct : m_inRangeActor )
|
||||
{
|
||||
pCurAct->removeInRangeActor( *this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
check if a given actor is in the actors in range set
|
||||
|
||||
\param ActorPtr to be checked for
|
||||
\return true if the actor was found
|
||||
*/
|
||||
bool Core::Entity::Actor::isInRangeSet( ActorPtr pActor ) const
|
||||
{
|
||||
return !( m_inRangeActor.find( pActor ) == m_inRangeActor.end() );
|
||||
}
|
||||
|
||||
/*! \return ActorPtr of the closest actor in range, if none, nullptr */
|
||||
Core::Entity::ActorPtr Core::Entity::Actor::getClosestActor()
|
||||
{
|
||||
if( m_inRangeActor.empty() )
|
||||
// no actors in range, don't bother
|
||||
return nullptr;
|
||||
|
||||
ActorPtr tmpActor = nullptr;
|
||||
|
||||
// arbitrary high number
|
||||
float minDistance = 10000;
|
||||
|
||||
for( const auto& pCurAct : m_inRangeActor )
|
||||
{
|
||||
float distance = Math::Util::distance( getPos().x,
|
||||
getPos().y,
|
||||
getPos().z,
|
||||
pCurAct->getPos().x,
|
||||
pCurAct->getPos().y,
|
||||
pCurAct->getPos().z );
|
||||
|
||||
if( distance < minDistance )
|
||||
{
|
||||
minDistance = distance;
|
||||
tmpActor = pCurAct;
|
||||
}
|
||||
}
|
||||
|
||||
return tmpActor;
|
||||
}
|
||||
|
||||
|
||||
/*! Clear the whole in range set, this does no cleanup */
|
||||
void Core::Entity::Actor::clearInRangeSet()
|
||||
{
|
||||
m_inRangeActor.clear();
|
||||
m_inRangePlayers.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Send a packet to all players in range, potentially to self if set and is player
|
||||
|
||||
\param GamePacketPtr to send
|
||||
\param bool should be send to self?
|
||||
*/
|
||||
void Core::Entity::Actor::sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf )
|
||||
{
|
||||
|
||||
if( bToSelf && isPlayer() )
|
||||
{
|
||||
auto pPlayer = getAsPlayer();
|
||||
|
||||
auto pSession = g_serverZone.getSession( pPlayer->getId() );
|
||||
|
||||
// it might be that the player DC'd in which case the session would be invalid
|
||||
if( pSession )
|
||||
pSession->getZoneConnection()->queueOutPacket( pPacket );
|
||||
}
|
||||
|
||||
if( m_inRangePlayers.empty() )
|
||||
return;
|
||||
|
||||
for( const auto &pCurAct : m_inRangePlayers )
|
||||
{
|
||||
assert( pCurAct );
|
||||
pPacket->setValAt< uint32_t >( 0x04, m_id );
|
||||
pPacket->setValAt< uint32_t >( 0x08, pCurAct->getId() );
|
||||
// it might be that the player DC'd in which case the session would be invalid
|
||||
pCurAct->queuePacket( pPacket );
|
||||
}
|
||||
}
|
||||
|
||||
/*! \return list of actors currently in range */
|
||||
std::set< Core::Entity::ActorPtr > Core::Entity::Actor::getInRangeActors( bool includeSelf )
|
||||
{
|
||||
auto tempInRange = m_inRangeActor;
|
||||
|
||||
if( includeSelf )
|
||||
tempInRange.insert( shared_from_this() );
|
||||
|
||||
return tempInRange;
|
||||
}
|
|
@ -49,6 +49,10 @@ namespace Entity {
|
|||
/*! Type of the actor */
|
||||
ObjKind m_objKind;
|
||||
|
||||
/*! list of various actors in range */
|
||||
std::set< ActorPtr > m_inRangeActor;
|
||||
std::set< PlayerPtr > m_inRangePlayers;
|
||||
|
||||
public:
|
||||
explicit Actor( ObjKind type );
|
||||
virtual ~Actor() {};
|
||||
|
@ -69,6 +73,34 @@ namespace Entity {
|
|||
|
||||
bool isPlayer() const;
|
||||
|
||||
///// IN RANGE LOGIC ///////////////////////////////
|
||||
virtual void onRemoveInRangeActor( Actor& pActor ) {}
|
||||
|
||||
// check if another actor is in the actors in range set
|
||||
bool isInRangeSet( ActorPtr pActor ) const;
|
||||
|
||||
ActorPtr getClosestActor();
|
||||
|
||||
void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false );
|
||||
|
||||
// add an actor to in range set
|
||||
void addInRangeActor( ActorPtr pActor );
|
||||
|
||||
// remove an actor from the in range set
|
||||
void removeInRangeActor( Actor& actor );
|
||||
|
||||
// return true if there is at least one actor in the in range set
|
||||
bool hasInRangeActor() const;
|
||||
|
||||
void removeFromInRange();
|
||||
|
||||
// clear the whole in range set, this does no cleanup
|
||||
virtual void clearInRangeSet();
|
||||
|
||||
std::set< ActorPtr > getInRangeActors( bool includeSelf = false );
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
CharaPtr getAsChara();
|
||||
PlayerPtr getAsPlayer();
|
||||
};
|
||||
|
|
|
@ -52,16 +52,6 @@ std::string Core::Entity::Chara::getName() const
|
|||
return std::string( m_name );
|
||||
}
|
||||
|
||||
/*! \return list of actors currently in range */
|
||||
std::set< Core::Entity::CharaPtr > Core::Entity::Chara::getInRangeCharas( bool includeSelf )
|
||||
{
|
||||
auto tempInRange = m_inRangeCharas;
|
||||
|
||||
if( includeSelf )
|
||||
tempInRange.insert( getAsChara() );
|
||||
|
||||
return tempInRange;
|
||||
}
|
||||
|
||||
/*! \return current stance of the actors */
|
||||
Core::Entity::Chara::Stance Core::Entity::Chara::getStance() const
|
||||
|
@ -396,155 +386,6 @@ void Core::Entity::Chara::setCurrentAction( Core::Action::ActionPtr pAction )
|
|||
m_pCurrentAction = pAction;
|
||||
}
|
||||
|
||||
/*!
|
||||
check if a given actor is in the actors in range set
|
||||
|
||||
\param ActorPtr to be checked for
|
||||
\return true if the actor was found
|
||||
*/
|
||||
bool Core::Entity::Chara::isInRangeSet( CharaPtr pChara ) const
|
||||
{
|
||||
return !( m_inRangeCharas.find( pChara ) == m_inRangeCharas.end() );
|
||||
}
|
||||
|
||||
/*! \return ActorPtr of the closest actor in range, if none, nullptr */
|
||||
Core::Entity::CharaPtr Core::Entity::Chara::getClosestChara()
|
||||
{
|
||||
if( m_inRangeCharas.empty() )
|
||||
// no actors in range, don't bother
|
||||
return nullptr;
|
||||
|
||||
CharaPtr tmpActor = nullptr;
|
||||
|
||||
// arbitrary high number
|
||||
float minDistance = 10000;
|
||||
|
||||
for( const auto& pCurAct : m_inRangeCharas )
|
||||
{
|
||||
float distance = Math::Util::distance( getPos().x,
|
||||
getPos().y,
|
||||
getPos().z,
|
||||
pCurAct->getPos().x,
|
||||
pCurAct->getPos().y,
|
||||
pCurAct->getPos().z );
|
||||
|
||||
if( distance < minDistance )
|
||||
{
|
||||
minDistance = distance;
|
||||
tmpActor = pCurAct;
|
||||
}
|
||||
}
|
||||
|
||||
return tmpActor;
|
||||
}
|
||||
|
||||
/*!
|
||||
Send a packet to all players in range, potentially to self if set and is player
|
||||
|
||||
\param GamePacketPtr to send
|
||||
\param bool should be send to self?
|
||||
*/
|
||||
void Core::Entity::Chara::sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf )
|
||||
{
|
||||
|
||||
if( bToSelf && isPlayer() )
|
||||
{
|
||||
auto pPlayer = getAsPlayer();
|
||||
|
||||
auto pSession = g_serverZone.getSession( pPlayer->getId() );
|
||||
|
||||
// it might be that the player DC'd in which case the session would be invalid
|
||||
if( pSession )
|
||||
pSession->getZoneConnection()->queueOutPacket( pPacket );
|
||||
}
|
||||
|
||||
if( m_inRangePlayers.empty() )
|
||||
return;
|
||||
|
||||
for( const auto &pCurAct : m_inRangePlayers )
|
||||
{
|
||||
assert( pCurAct );
|
||||
pPacket->setValAt< uint32_t >( 0x04, m_id );
|
||||
pPacket->setValAt< uint32_t >( 0x08, pCurAct->m_id );
|
||||
// it might be that the player DC'd in which case the session would be invalid
|
||||
pCurAct->queuePacket( pPacket );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Add a given actor to the fitting in range set according to type
|
||||
but also to the global actor map
|
||||
|
||||
\param ActorPtr to add
|
||||
*/
|
||||
void Core::Entity::Chara::addInRangeChara( CharaPtr pChara )
|
||||
{
|
||||
|
||||
// if this is null, something went wrong
|
||||
assert( pChara );
|
||||
|
||||
// add actor to in range set
|
||||
m_inRangeCharas.insert( pChara );
|
||||
|
||||
if( pChara->isPlayer() )
|
||||
{
|
||||
auto pPlayer = pChara->getAsPlayer();
|
||||
|
||||
// if actor is a player, add it to the in range player set
|
||||
m_inRangePlayers.insert( pPlayer );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Remove a given actor from the matching in range set according to type
|
||||
but also to the global actor map
|
||||
|
||||
\param ActorPtr to remove
|
||||
*/
|
||||
void Core::Entity::Chara::removeInRangeChara( Chara& chara )
|
||||
{
|
||||
// call virtual event
|
||||
onRemoveInRangeChara( chara );
|
||||
|
||||
// remove actor from in range actor set
|
||||
m_inRangeCharas.erase( chara.getAsChara() );
|
||||
|
||||
// if actor is a player, despawn ourself for him
|
||||
// TODO: move to virtual onRemove?
|
||||
if( isPlayer() )
|
||||
chara.despawn( getAsPlayer() );
|
||||
|
||||
if( chara.isPlayer() )
|
||||
m_inRangePlayers.erase( chara.getAsPlayer() );
|
||||
}
|
||||
|
||||
/*! \return true if there is at least one actor in the in range set */
|
||||
bool Core::Entity::Chara::hasInRangeActor() const
|
||||
{
|
||||
return ( m_inRangeCharas.size() > 0 );
|
||||
}
|
||||
|
||||
void Core::Entity::Chara::removeFromInRange()
|
||||
{
|
||||
if( !hasInRangeActor() )
|
||||
return;
|
||||
|
||||
Entity::ActorPtr pCurAct;
|
||||
|
||||
for( auto& pCurAct : m_inRangeCharas )
|
||||
{
|
||||
pCurAct->removeInRangeChara( *this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*! Clear the whole in range set, this does no cleanup */
|
||||
void Core::Entity::Chara::clearInRangeSet()
|
||||
{
|
||||
m_inRangeCharas.clear();
|
||||
m_inRangePlayers.clear();
|
||||
}
|
||||
|
||||
/*! \return ZonePtr to the current zone, nullptr if not set */
|
||||
Core::ZonePtr Core::Entity::Chara::getCurrentZone() const
|
||||
{
|
||||
|
@ -682,7 +523,7 @@ void Core::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, u
|
|||
else
|
||||
{
|
||||
|
||||
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeCharas(true),
|
||||
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ),
|
||||
actionInfoPtr, TargetFilter::Enemies );
|
||||
|
||||
for( const auto& pHitActor : actorsCollided )
|
||||
|
@ -694,16 +535,17 @@ void Core::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, u
|
|||
sendToInRangeSet( effectPacket, true );
|
||||
|
||||
|
||||
if( pHitActor->isAlive() )
|
||||
pHitActor->onActionHostile( *this );
|
||||
if( pHitActor->getAsChara()->isAlive() )
|
||||
pHitActor->getAsChara()->onActionHostile( *this );
|
||||
|
||||
pHitActor->takeDamage( static_cast< uint32_t >( param1 ) );
|
||||
pHitActor->getAsChara()->takeDamage( static_cast< uint32_t >( param1 ) );
|
||||
|
||||
// Debug
|
||||
if ( isPlayer() )
|
||||
{
|
||||
if ( pHitActor->isPlayer() )
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" );
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) +
|
||||
" (" + pHitActor->getAsChara()->getName() + ")" );
|
||||
else
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) );
|
||||
}
|
||||
|
@ -734,7 +576,7 @@ void Core::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, u
|
|||
// todo: get proper packets: the following was just kind of thrown together from what we know.
|
||||
// atm buggy (packets look "delayed" from client)
|
||||
|
||||
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeCharas(true),
|
||||
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors(true),
|
||||
actionInfoPtr, TargetFilter::Allies );
|
||||
|
||||
for( auto pHitActor : actorsCollided )
|
||||
|
@ -743,13 +585,14 @@ void Core::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, u
|
|||
effectPacket.data().effectTarget = pHitActor->getId();
|
||||
|
||||
sendToInRangeSet( effectPacket, true );
|
||||
pHitActor->heal( calculatedHeal );
|
||||
pHitActor->getAsChara()->heal( calculatedHeal );
|
||||
|
||||
// Debug
|
||||
if( isPlayer() )
|
||||
{
|
||||
if( pHitActor->isPlayer() )
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" );
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) +
|
||||
" (" + pHitActor->getAsChara()->getName() + ")" );
|
||||
else
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) );
|
||||
}
|
||||
|
@ -972,3 +815,8 @@ bool Core::Entity::Chara::hasStatusEffect( uint32_t id )
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Chara::ModelType Chara::getModelType() const
|
||||
{
|
||||
return m_modelType;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,16 @@ public:
|
|||
SMachine = 0x08
|
||||
};
|
||||
|
||||
/*! ModelType as found in eventsystemdefine.exd */
|
||||
enum ModelType : uint8_t
|
||||
{
|
||||
Human = 1,
|
||||
DemiHuman = 2,
|
||||
Monster = 3,
|
||||
SharedGroup = 4,
|
||||
Parts = 5
|
||||
};
|
||||
|
||||
struct ActorStats
|
||||
{
|
||||
uint32_t max_mp = 0;
|
||||
|
@ -132,6 +142,8 @@ protected:
|
|||
Action::ActionPtr m_pCurrentAction;
|
||||
/*! Invincibility type */
|
||||
Common::InvincibilityType m_invincibilityType;
|
||||
/*! Type of model to use, humanoid for actors that use look data */
|
||||
ModelType m_modelType;
|
||||
|
||||
/*! Status effects */
|
||||
const uint8_t MAX_STATUS_EFFECTS = 30;
|
||||
|
@ -139,9 +151,6 @@ protected:
|
|||
std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList;
|
||||
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
||||
|
||||
std::set< CharaPtr > m_inRangeCharas;
|
||||
std::set< PlayerPtr > m_inRangePlayers;
|
||||
|
||||
public:
|
||||
Chara( ObjKind type );
|
||||
|
||||
|
@ -182,8 +191,6 @@ public:
|
|||
|
||||
std::string getName() const;
|
||||
|
||||
std::set< CharaPtr > getInRangeCharas( bool includeSelf = false );
|
||||
|
||||
bool face( const Common::FFXIVARR_POSITION3& p );
|
||||
|
||||
Stance getStance() const;
|
||||
|
@ -201,6 +208,8 @@ public:
|
|||
|
||||
Common::ClassJob getClass() const;
|
||||
|
||||
ModelType getModelType() const;
|
||||
|
||||
uint8_t getClassAsInt() const;
|
||||
|
||||
void setClass( Common::ClassJob classJob );
|
||||
|
@ -233,8 +242,6 @@ public:
|
|||
|
||||
virtual void autoAttack( CharaPtr pTarget );
|
||||
|
||||
virtual void onRemoveInRangeChara( Chara& pActor ) {}
|
||||
|
||||
virtual void onDeath() {};
|
||||
virtual void onDamageTaken( Chara& pSource ) {};
|
||||
virtual void onActionHostile( Chara& source ) {};
|
||||
|
@ -253,29 +260,6 @@ public:
|
|||
|
||||
void setCurrentAction( Action::ActionPtr pAction );
|
||||
|
||||
///// IN RANGE LOGIC /////
|
||||
|
||||
// check if another actor is in the actors in range set
|
||||
bool isInRangeSet( CharaPtr pChara ) const;
|
||||
|
||||
CharaPtr getClosestChara();
|
||||
|
||||
void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false );
|
||||
|
||||
// add an actor to in range set
|
||||
void addInRangeChara( CharaPtr pChara );
|
||||
|
||||
// remove an actor from the in range set
|
||||
void removeInRangeChara( Chara& chara );
|
||||
|
||||
// return true if there is at least one actor in the in range set
|
||||
bool hasInRangeActor() const;
|
||||
|
||||
void removeFromInRange();
|
||||
|
||||
// clear the whole in range set, this does no cleanup
|
||||
virtual void clearInRangeSet();
|
||||
|
||||
ZonePtr getCurrentZone() const;
|
||||
|
||||
void setCurrentZone( ZonePtr currZone );
|
||||
|
|
|
@ -80,6 +80,7 @@ Core::Entity::Player::Player() :
|
|||
m_queuedZoneing = nullptr;
|
||||
m_status = ActorStatus::Idle;
|
||||
m_invincibilityType = InvincibilityType::InvincibilityNone;
|
||||
m_modelType = ModelType::Human;
|
||||
|
||||
memset( m_questTracking, 0, sizeof( m_questTracking ) );
|
||||
memset( m_name, 0, sizeof( m_name ) );
|
||||
|
@ -819,10 +820,10 @@ void Core::Entity::Player::despawn( Entity::PlayerPtr pTarget )
|
|||
pPlayer->queuePacket( ActorControlPacket143( getId(), DespawnZoneScreenMsg, 0x04, getId(), 0x01 ) );
|
||||
}
|
||||
|
||||
Core::Entity::CharaPtr Core::Entity::Player::lookupTargetById( uint64_t targetId )
|
||||
Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId )
|
||||
{
|
||||
CharaPtr targetActor;
|
||||
auto inRange = getInRangeCharas(true);
|
||||
ActorPtr targetActor;
|
||||
auto inRange = getInRangeActors(true);
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
if( actor->getId() == targetId )
|
||||
|
@ -995,9 +996,9 @@ void Core::Entity::Player::update( int64_t currTime )
|
|||
auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::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_inRangeCharas )
|
||||
for( auto actor : m_inRangeActor )
|
||||
{
|
||||
if( actor->getId() == m_targetId && actor->isAlive() && mainWeap )
|
||||
if( actor->getId() == m_targetId && actor->getAsChara()->isAlive() && mainWeap )
|
||||
{
|
||||
// default autoattack range
|
||||
// TODO make this dependant on bnpc size
|
||||
|
@ -1017,7 +1018,7 @@ void Core::Entity::Player::update( int64_t currTime )
|
|||
if( ( currTime - m_lastAttack ) > mainWeap->getDelay() )
|
||||
{
|
||||
m_lastAttack = currTime;
|
||||
autoAttack( actor );
|
||||
autoAttack( actor->getAsChara() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -519,7 +519,7 @@ public:
|
|||
|
||||
bool actionHasCastTime( uint32_t actionId );
|
||||
|
||||
Core::Entity::CharaPtr lookupTargetById( uint64_t targetId );
|
||||
Core::Entity::ActorPtr lookupTargetById( uint64_t targetId );
|
||||
|
||||
bool isLogin() const;
|
||||
void setIsLogin( bool bIsLogin );
|
||||
|
|
|
@ -104,7 +104,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
", params: " + std::to_string( param1 ) + ", " +
|
||||
std::to_string( param2 ) + ", " + std::to_string( param3 ) );
|
||||
|
||||
Core::Entity::CharaPtr targetActor;
|
||||
Core::Entity::ActorPtr targetActor;
|
||||
|
||||
|
||||
if( player.getId() == param3 )
|
||||
|
@ -113,7 +113,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
else
|
||||
{
|
||||
auto inRange = player.getInRangeCharas();
|
||||
auto inRange = player.getInRangeActors();
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
if( actor->getId() == param3 )
|
||||
|
@ -138,7 +138,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
targetPlayer->setLookAt( CharaLook::Race, param1 );
|
||||
player.sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
|
||||
targetPlayer->spawn( targetPlayer );
|
||||
auto inRange = targetPlayer->getInRangeCharas();
|
||||
auto inRange = targetPlayer->getInRangeActors();
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
targetPlayer->despawn( actor->getAsPlayer() );
|
||||
|
@ -151,7 +151,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
targetPlayer->setLookAt( CharaLook::Tribe, param1 );
|
||||
player.sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
|
||||
targetPlayer->spawn( targetPlayer );
|
||||
auto inRange = targetPlayer->getInRangeCharas();
|
||||
auto inRange = targetPlayer->getInRangeActors();
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
targetPlayer->despawn( actor->getAsPlayer() );
|
||||
|
@ -164,7 +164,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
targetPlayer->setLookAt( CharaLook::Gender, param1 );
|
||||
player.sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
|
||||
targetPlayer->spawn( targetPlayer );
|
||||
auto inRange = targetActor->getInRangeCharas();
|
||||
auto inRange = targetActor->getInRangeActors();
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
targetPlayer->despawn( actor->getAsPlayer() );
|
||||
|
@ -216,7 +216,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Kill:
|
||||
{
|
||||
targetActor->takeDamage( 9999999 );
|
||||
targetActor->getAsChara()->takeDamage( 9999999 );
|
||||
player.sendNotice( "Killed " + std::to_string( targetActor->getId() ) );
|
||||
break;
|
||||
}
|
||||
|
@ -266,10 +266,10 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Inv:
|
||||
{
|
||||
if( targetActor->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill )
|
||||
targetActor->setInvincibilityType( Common::InvincibilityType::InvincibilityNone );
|
||||
if( targetActor->getAsChara()->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill )
|
||||
targetActor->getAsChara()->setInvincibilityType( Common::InvincibilityType::InvincibilityNone );
|
||||
else
|
||||
targetActor->setInvincibilityType( Common::InvincibilityType::InvincibilityRefill );
|
||||
targetActor->getAsChara()->setInvincibilityType( Common::InvincibilityType::InvincibilityRefill );
|
||||
|
||||
player.sendNotice( "Invincibility for " + targetPlayer->getName() +
|
||||
" was switched." );
|
||||
|
@ -439,10 +439,10 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
case GmCommand::Jump:
|
||||
{
|
||||
|
||||
auto inRange = player.getInRangeCharas();
|
||||
auto inRange = player.getInRangeActors();
|
||||
|
||||
player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
|
||||
targetActor->getRotation() );
|
||||
targetActor->getRot() );
|
||||
|
||||
player.sendNotice( "Jumping to " + targetPlayer->getName() + " in range." );
|
||||
break;
|
||||
|
|
|
@ -75,7 +75,7 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP
|
|||
}
|
||||
else
|
||||
{
|
||||
Core::Entity::CharaPtr targetActor = player.getAsPlayer();
|
||||
Core::Entity::ActorPtr targetActor = player.getAsPlayer();
|
||||
if( targetId != player.getId() )
|
||||
{
|
||||
targetActor = player.lookupTargetById( targetId );
|
||||
|
@ -83,11 +83,11 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP
|
|||
|
||||
if( !player.actionHasCastTime( action ) )
|
||||
{
|
||||
g_scriptMgr.onCastFinish( player, targetActor, action );
|
||||
g_scriptMgr.onCastFinish( player, targetActor->getAsChara(), action );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto pActionCast = Action::make_ActionCast( player.getAsPlayer(), targetActor, action );
|
||||
auto pActionCast = Action::make_ActionCast( player.getAsPlayer(), targetActor->getAsChara(), action );
|
||||
player.setCurrentAction( pActionCast );
|
||||
player.sendDebug( "setCurrentAction()" );
|
||||
player.getCurrentAction()->onStart();
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace Server {
|
|||
//m_data.u23 = 0x04;
|
||||
//m_data.u24 = 256;
|
||||
m_data.state = static_cast< uint8_t >( player.getStatus() );
|
||||
m_data.type = 1;
|
||||
m_data.modelType = player.getModelType();
|
||||
if( target.getId() == player.getId() )
|
||||
{
|
||||
m_data.spawnIndex = 0x00;
|
||||
|
|
|
@ -602,27 +602,15 @@ void Core::Zone::updateInRangeSet( Entity::CharaPtr pChara, Cell* pCell )
|
|||
// Add if range == 0 or distance is withing range.
|
||||
if( isInRange && !isInRangeSet )
|
||||
{
|
||||
if( pChara->isPlayer() )
|
||||
{
|
||||
auto pOwnPlayer = pChara->getAsPlayer();
|
||||
if( !pOwnPlayer->isLoadingComplete() )
|
||||
continue;
|
||||
|
||||
// spawn the actor for the player
|
||||
pCurAct->spawn( pOwnPlayer );
|
||||
}
|
||||
if( pChara->isPlayer() && !pChara->getAsPlayer()->isLoadingComplete() )
|
||||
continue;
|
||||
|
||||
if( pCurAct->isPlayer() )
|
||||
{
|
||||
auto pPlayer = pCurAct->getAsPlayer();
|
||||
if( !pPlayer->isLoadingComplete() )
|
||||
continue;
|
||||
if( pCurAct->isPlayer() && !pCurAct->getAsPlayer()->isLoadingComplete() )
|
||||
continue;
|
||||
|
||||
pChara->spawn( pPlayer );
|
||||
}
|
||||
|
||||
pChara->addInRangeChara( pCurAct );
|
||||
pCurAct->addInRangeChara( pChara );
|
||||
pChara->addInRangeActor( pCurAct );
|
||||
pCurAct->addInRangeActor( pChara );
|
||||
|
||||
// this is a hack to limit actor spawn in one packetset
|
||||
if( count++ > 12 )
|
||||
|
@ -630,8 +618,8 @@ void Core::Zone::updateInRangeSet( Entity::CharaPtr pChara, Cell* pCell )
|
|||
}
|
||||
else if( !isInRange && isInRangeSet )
|
||||
{
|
||||
pCurAct->removeInRangeChara( *pChara );
|
||||
pChara->removeInRangeChara( *pCurAct );
|
||||
pCurAct->removeInRangeActor( *pChara );
|
||||
pChara->removeInRangeActor( *pCurAct );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue