1
Fork 0
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:
Mordred 2018-01-22 08:42:14 +01:00 committed by GitHub
commit 31f460d4c4
9 changed files with 222 additions and 3 deletions

View file

@ -72,6 +72,12 @@ bool Core::Entity::Actor::isMob() const
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 */
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 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 */
Core::Action::ActionPtr Core::Entity::Actor::getCurrentAction() const
{

View file

@ -218,6 +218,8 @@ public:
bool isMob() const;
bool isEventNpc() const;
std::set< ActorPtr > getInRangeActors( bool includeSelf = false );
bool face( const Common::FFXIVARR_POSITION3& p );
@ -296,6 +298,7 @@ public:
PlayerPtr getAsPlayer();
BattleNpcPtr getAsBattleNpc();
EventNpcPtr getAsEventNpc();
Action::ActionPtr getCurrentAction() const;

View 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;
}

View 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

View file

@ -23,6 +23,7 @@
#include "Actor/Player.h"
#include "Actor/BattleNpc.h"
#include "Actor/EventNpc.h"
#include "Zone/Zone.h"
@ -35,6 +36,7 @@
#include <cinttypes>
#include "Network/PacketWrappers/PlayerSpawnPacket.h"
extern Core::Scripting::ScriptManager g_scriptMgr;
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() ) );
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" )
{

View file

@ -31,6 +31,7 @@ namespace Core
TYPE_FORWARD( Actor );
TYPE_FORWARD( Player );
TYPE_FORWARD( BattleNpc );
TYPE_FORWARD( EventNpc );
TYPE_FORWARD( BattleNpcTemplate );
}

View file

@ -3,7 +3,7 @@
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <common/Network/GamePacketNew.h>
#include <common/Util/UtilMath.h>
#include <common/Util/Util.h>
#include "Actor/Player.h"
#include "Forwards.h"
#include "Inventory/Inventory.h"
@ -119,7 +119,7 @@ namespace Server {
//m_data.unknown_60 = 3;
//m_data.unknown_61 = 7;
uint64_t currentTimeMs = Util::getTimeMs();
uint64_t currentTimeMs = Core::Util::getTimeMs();
for( auto const& effect : player.getStatusEffectMap() )
{

View file

@ -19,6 +19,7 @@
#include "Actor/Actor.h"
#include "Actor/Player.h"
#include "Actor/BattleNpc.h"
#include "Actor/EventNpc.h"
#include "Forwards.h"
@ -298,6 +299,12 @@ void Zone::pushActor( Entity::ActorPtr pActor )
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();
if( pPlayer->isLoadingComplete() )

View file

@ -40,6 +40,7 @@ protected:
std::unordered_map< int32_t, Entity::PlayerPtr > m_playerMap;
std::unordered_map< int32_t, Entity::BattleNpcPtr > m_BattleNpcMap;
std::unordered_map< int32_t, Entity::EventNpcPtr > m_EventNpcMap;
std::set< Entity::BattleNpcPtr > m_BattleNpcDeadMap;