mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-25 14:07:46 +00:00
Merge pull request #220 from goaaats/eventnpc
zone: Add EventNpc + logic
This commit is contained in:
commit
31f460d4c4
9 changed files with 222 additions and 3 deletions
|
@ -72,6 +72,12 @@ bool Core::Entity::Actor::isMob() const
|
||||||
return m_objKind == ObjKind::BattleNpc;
|
return m_objKind == ObjKind::BattleNpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \return true if the actor is of type resident */
|
||||||
|
bool Core::Entity::Actor::isEventNpc() const
|
||||||
|
{
|
||||||
|
return m_objKind == ObjKind::EventNpc;
|
||||||
|
}
|
||||||
|
|
||||||
/*! \return list of actors currently in range */
|
/*! \return list of actors currently in range */
|
||||||
std::set< Core::Entity::ActorPtr > Core::Entity::Actor::getInRangeActors( bool includeSelf )
|
std::set< Core::Entity::ActorPtr > Core::Entity::Actor::getInRangeActors( bool includeSelf )
|
||||||
{
|
{
|
||||||
|
@ -418,6 +424,12 @@ Core::Entity::BattleNpcPtr Core::Entity::Actor::getAsBattleNpc()
|
||||||
return boost::reinterpret_pointer_cast< Entity::BattleNpc, Entity::Actor >( shared_from_this() );
|
return boost::reinterpret_pointer_cast< Entity::BattleNpc, Entity::Actor >( shared_from_this() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \return pointer to this instance as EventNpcPtr */
|
||||||
|
Core::Entity::EventNpcPtr Core::Entity::Actor::getAsEventNpc()
|
||||||
|
{
|
||||||
|
return boost::reinterpret_pointer_cast< Entity::EventNpc, Entity::Actor >( shared_from_this() );
|
||||||
|
}
|
||||||
|
|
||||||
/*! \return ActionPtr of the currently registered action, or nullptr */
|
/*! \return ActionPtr of the currently registered action, or nullptr */
|
||||||
Core::Action::ActionPtr Core::Entity::Actor::getCurrentAction() const
|
Core::Action::ActionPtr Core::Entity::Actor::getCurrentAction() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -218,6 +218,8 @@ public:
|
||||||
|
|
||||||
bool isMob() const;
|
bool isMob() const;
|
||||||
|
|
||||||
|
bool isEventNpc() const;
|
||||||
|
|
||||||
std::set< ActorPtr > getInRangeActors( bool includeSelf = false );
|
std::set< ActorPtr > getInRangeActors( bool includeSelf = false );
|
||||||
|
|
||||||
bool face( const Common::FFXIVARR_POSITION3& p );
|
bool face( const Common::FFXIVARR_POSITION3& p );
|
||||||
|
@ -296,6 +298,7 @@ public:
|
||||||
|
|
||||||
PlayerPtr getAsPlayer();
|
PlayerPtr getAsPlayer();
|
||||||
BattleNpcPtr getAsBattleNpc();
|
BattleNpcPtr getAsBattleNpc();
|
||||||
|
EventNpcPtr getAsEventNpc();
|
||||||
|
|
||||||
Action::ActionPtr getCurrentAction() const;
|
Action::ActionPtr getCurrentAction() const;
|
||||||
|
|
||||||
|
|
124
src/servers/sapphire_zone/Actor/EventNpc.cpp
Normal file
124
src/servers/sapphire_zone/Actor/EventNpc.cpp
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <common/Logging/Logger.h>
|
||||||
|
#include <common/Exd/ExdData.h>
|
||||||
|
#include <common/Util/Util.h>
|
||||||
|
#include <common/Util/UtilMath.h>
|
||||||
|
|
||||||
|
#include "Player.h"
|
||||||
|
#include "EventNpc.h"
|
||||||
|
|
||||||
|
#include "Network/PacketWrappers/MoveActorPacket.h"
|
||||||
|
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||||
|
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||||
|
|
||||||
|
using namespace Core::Common;
|
||||||
|
using namespace Core::Network::Packets;
|
||||||
|
using namespace Core::Network::Packets::Server;
|
||||||
|
|
||||||
|
extern Core::Logger g_log;
|
||||||
|
extern Core::Data::ExdData g_exdData;
|
||||||
|
|
||||||
|
uint32_t Core::Entity::EventNpc::m_nextID = 1249241694;
|
||||||
|
|
||||||
|
Core::Entity::EventNpc::EventNpc()
|
||||||
|
{
|
||||||
|
m_id = 0;
|
||||||
|
m_objKind = ObjKind::EventNpc;
|
||||||
|
m_status = ActorStatus::Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::Entity::EventNpc::~EventNpc()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::Entity::EventNpc::EventNpc( uint32_t enpcId, const Common::FFXIVARR_POSITION3& spawnPos, float rotation ) : Actor()
|
||||||
|
{
|
||||||
|
EventNpc::m_nextID++;
|
||||||
|
m_id = EventNpc::m_nextID;
|
||||||
|
|
||||||
|
m_pos = spawnPos;
|
||||||
|
m_posOrigin = spawnPos;
|
||||||
|
|
||||||
|
m_objKind = ObjKind::EventNpc;
|
||||||
|
|
||||||
|
m_targetId = static_cast< uint64_t >( INVALID_GAME_OBJECT_ID );
|
||||||
|
|
||||||
|
m_maxHp = 150;
|
||||||
|
m_maxMp = 100;
|
||||||
|
|
||||||
|
m_baseStats.max_hp = m_maxHp;
|
||||||
|
m_baseStats.max_mp = m_maxMp;
|
||||||
|
|
||||||
|
m_hp = m_maxHp;
|
||||||
|
m_mp = m_maxMp;
|
||||||
|
|
||||||
|
m_currentStance = Stance::Passive;
|
||||||
|
|
||||||
|
m_eNpcId = enpcId;
|
||||||
|
|
||||||
|
m_status = ActorStatus::Idle;
|
||||||
|
|
||||||
|
m_invincibilityType = InvincibilityType::InvincibilityNone;
|
||||||
|
m_rot = rotation;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// spawn this player for pTarget
|
||||||
|
// TODO: Retail additionally sends Look+Models for EventNpcs even though it is not needed, add when the new exd reader is implemented(also counts for BNPCs)
|
||||||
|
void Core::Entity::EventNpc::spawn( PlayerPtr pTarget )
|
||||||
|
{
|
||||||
|
ZoneChannelPacket< FFXIVIpcNpcSpawn > spawnPacket( getId(), pTarget->getId() );
|
||||||
|
|
||||||
|
|
||||||
|
spawnPacket.data().pos.x = m_pos.x;
|
||||||
|
spawnPacket.data().pos.y = m_pos.y;
|
||||||
|
spawnPacket.data().pos.z = m_pos.z;
|
||||||
|
|
||||||
|
spawnPacket.data().targetId = pTarget->getId();
|
||||||
|
spawnPacket.data().hPCurr = 1;
|
||||||
|
spawnPacket.data().hPMax = 1;
|
||||||
|
|
||||||
|
spawnPacket.data().bNPCBase = m_eNpcId;
|
||||||
|
spawnPacket.data().bNPCName = m_eNpcId;
|
||||||
|
spawnPacket.data().spawnIndex = pTarget->getSpawnIdForActorId( getId() );
|
||||||
|
|
||||||
|
spawnPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() );
|
||||||
|
|
||||||
|
spawnPacket.data().type = static_cast< uint8_t >( m_objKind );
|
||||||
|
|
||||||
|
pTarget->queuePacket( spawnPacket );
|
||||||
|
}
|
||||||
|
|
||||||
|
// despawn
|
||||||
|
void Core::Entity::EventNpc::despawn( ActorPtr pTarget )
|
||||||
|
{
|
||||||
|
|
||||||
|
auto pPlayer = pTarget->getAsPlayer();
|
||||||
|
|
||||||
|
pPlayer->freePlayerSpawnId( getId() );
|
||||||
|
|
||||||
|
ActorControlPacket143 controlPacket( m_id, DespawnZoneScreenMsg, 0x04, getId(), 0x01 );
|
||||||
|
pPlayer->queuePacket( controlPacket );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Core::Entity::EventNpc::getLevel() const
|
||||||
|
{
|
||||||
|
return m_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Entity::EventNpc::resetPos()
|
||||||
|
{
|
||||||
|
m_pos = m_posOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Core::Entity::EventNpc::getEnpcId() const
|
||||||
|
{
|
||||||
|
return m_eNpcId;
|
||||||
|
}
|
42
src/servers/sapphire_zone/Actor/EventNpc.h
Normal file
42
src/servers/sapphire_zone/Actor/EventNpc.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef _EVENTNPC_H
|
||||||
|
#define _EVENTNPC_H
|
||||||
|
|
||||||
|
#include "Actor.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
namespace Entity {
|
||||||
|
|
||||||
|
// class for Mobs inheriting from Actor
|
||||||
|
class EventNpc : public Actor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EventNpc();
|
||||||
|
~EventNpc();
|
||||||
|
|
||||||
|
EventNpc( uint32_t enpcId, const Common::FFXIVARR_POSITION3& spawnPos, float rotation );
|
||||||
|
|
||||||
|
// send spawn packets to pTarget
|
||||||
|
void spawn( PlayerPtr pTarget ) override;
|
||||||
|
|
||||||
|
// send despawn packets to pTarget
|
||||||
|
void despawn( ActorPtr pTarget ) override;
|
||||||
|
|
||||||
|
uint8_t getLevel() const override;
|
||||||
|
|
||||||
|
void resetPos();
|
||||||
|
|
||||||
|
uint32_t getEnpcId() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static uint32_t m_nextID;
|
||||||
|
Common::FFXIVARR_POSITION3 m_posOrigin;
|
||||||
|
uint8_t m_level;
|
||||||
|
uint32_t m_eNpcId;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
#include "Actor/BattleNpc.h"
|
#include "Actor/BattleNpc.h"
|
||||||
|
#include "Actor/EventNpc.h"
|
||||||
|
|
||||||
#include "Zone/Zone.h"
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include "Network/PacketWrappers/PlayerSpawnPacket.h"
|
||||||
|
|
||||||
extern Core::Scripting::ScriptManager g_scriptMgr;
|
extern Core::Scripting::ScriptManager g_scriptMgr;
|
||||||
extern Core::Data::ExdData g_exdData;
|
extern Core::Data::ExdData g_exdData;
|
||||||
|
@ -350,6 +352,33 @@ void Core::DebugCommandHandler::add( char * data, Entity::Player& player, boost:
|
||||||
Network::Packets::GamePacketPtr pPe( new Network::Packets::GamePacket( opcode, 0x30, player.getId(), player.getId() ) );
|
Network::Packets::GamePacketPtr pPe( new Network::Packets::GamePacket( opcode, 0x30, player.getId(), player.getId() ) );
|
||||||
player.queuePacket( pPe );
|
player.queuePacket( pPe );
|
||||||
}
|
}
|
||||||
|
else if( subCommand == "eventnpc-self" )
|
||||||
|
{
|
||||||
|
int32_t id;
|
||||||
|
|
||||||
|
sscanf( params.c_str(), "%d", &id );
|
||||||
|
|
||||||
|
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcNpcSpawn > spawnPacket( player.getId() );
|
||||||
|
spawnPacket.data().type = 3;
|
||||||
|
spawnPacket.data().pos = player.getPos();
|
||||||
|
spawnPacket.data().rotation = player.getRotation();
|
||||||
|
spawnPacket.data().bNPCBase = id;
|
||||||
|
spawnPacket.data().bNPCName = id;
|
||||||
|
spawnPacket.data().targetId = player.getId();
|
||||||
|
player.queuePacket( spawnPacket );
|
||||||
|
}
|
||||||
|
else if( subCommand == "eventnpc" )
|
||||||
|
{
|
||||||
|
int32_t id;
|
||||||
|
|
||||||
|
sscanf( params.c_str(), "%d", &id );
|
||||||
|
|
||||||
|
Entity::EventNpcPtr pENpc( new Entity::EventNpc( id, player.getPos(), player.getRotation() ) );
|
||||||
|
|
||||||
|
auto pZone = player.getCurrentZone();
|
||||||
|
pENpc->setCurrentZone( pZone );
|
||||||
|
pZone->pushActor( pENpc );
|
||||||
|
}
|
||||||
else if( subCommand == "actrl" )
|
else if( subCommand == "actrl" )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Core
|
||||||
TYPE_FORWARD( Actor );
|
TYPE_FORWARD( Actor );
|
||||||
TYPE_FORWARD( Player );
|
TYPE_FORWARD( Player );
|
||||||
TYPE_FORWARD( BattleNpc );
|
TYPE_FORWARD( BattleNpc );
|
||||||
|
TYPE_FORWARD( EventNpc );
|
||||||
TYPE_FORWARD( BattleNpcTemplate );
|
TYPE_FORWARD( BattleNpcTemplate );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
|
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
|
||||||
#include <common/Network/GamePacketNew.h>
|
#include <common/Network/GamePacketNew.h>
|
||||||
#include <common/Util/UtilMath.h>
|
#include <common/Util/Util.h>
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
#include "Forwards.h"
|
#include "Forwards.h"
|
||||||
#include "Inventory/Inventory.h"
|
#include "Inventory/Inventory.h"
|
||||||
|
@ -119,7 +119,7 @@ namespace Server {
|
||||||
//m_data.unknown_60 = 3;
|
//m_data.unknown_60 = 3;
|
||||||
//m_data.unknown_61 = 7;
|
//m_data.unknown_61 = 7;
|
||||||
|
|
||||||
uint64_t currentTimeMs = Util::getTimeMs();
|
uint64_t currentTimeMs = Core::Util::getTimeMs();
|
||||||
|
|
||||||
for( auto const& effect : player.getStatusEffectMap() )
|
for( auto const& effect : player.getStatusEffectMap() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Actor/Actor.h"
|
#include "Actor/Actor.h"
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
#include "Actor/BattleNpc.h"
|
#include "Actor/BattleNpc.h"
|
||||||
|
#include "Actor/EventNpc.h"
|
||||||
|
|
||||||
#include "Forwards.h"
|
#include "Forwards.h"
|
||||||
|
|
||||||
|
@ -298,6 +299,12 @@ void Zone::pushActor( Entity::ActorPtr pActor )
|
||||||
pBNpc->setPosition( pBNpc->getPos() );
|
pBNpc->setPosition( pBNpc->getPos() );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if( pActor->getAsEventNpc() )
|
||||||
|
{
|
||||||
|
Entity::EventNpcPtr pENpc = pActor->getAsEventNpc();
|
||||||
|
m_EventNpcMap[pENpc->getId()] = pENpc;
|
||||||
|
pENpc->setPosition( pENpc->getPos() );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +769,7 @@ void Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell )
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if( pActor->isMob() && pCurAct->isPlayer() && pActor->isAlive() )
|
else if( ( pActor->isMob() || pActor->isEventNpc() ) && pCurAct->isPlayer() && pActor->isAlive() )
|
||||||
{
|
{
|
||||||
auto pPlayer = pCurAct->getAsPlayer();
|
auto pPlayer = pCurAct->getAsPlayer();
|
||||||
if( pPlayer->isLoadingComplete() )
|
if( pPlayer->isLoadingComplete() )
|
||||||
|
|
|
@ -40,6 +40,7 @@ protected:
|
||||||
|
|
||||||
std::unordered_map< int32_t, Entity::PlayerPtr > m_playerMap;
|
std::unordered_map< int32_t, Entity::PlayerPtr > m_playerMap;
|
||||||
std::unordered_map< int32_t, Entity::BattleNpcPtr > m_BattleNpcMap;
|
std::unordered_map< int32_t, Entity::BattleNpcPtr > m_BattleNpcMap;
|
||||||
|
std::unordered_map< int32_t, Entity::EventNpcPtr > m_EventNpcMap;
|
||||||
|
|
||||||
std::set< Entity::BattleNpcPtr > m_BattleNpcDeadMap;
|
std::set< Entity::BattleNpcPtr > m_BattleNpcDeadMap;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue