1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-25 14:07:46 +00:00
sapphire/src/servers/sapphire_zone/Actor/PlayerEvent.cpp

416 lines
13 KiB
C++
Raw Normal View History

2018-03-06 22:22:19 +01:00
#include <Common.h>
#include <Logging/Logger.h>
#include <Network/PacketContainer.h>
#include <Config/ConfigMgr.h>
2017-08-08 13:53:47 +02:00
#include "Network/GameConnection.h"
#include "Network/PacketWrappers/ActorControlPacket142.h"
#include "Network/PacketWrappers/InitUIPacket.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/EventStartPacket.h"
#include "Network/PacketWrappers/EventPlayPacket.h"
#include "Network/PacketWrappers/EventFinishPacket.h"
#include "Network/PacketWrappers/DirectorPlayScenePacket.h"
2017-08-08 13:53:47 +02:00
#include "Action/EventAction.h"
#include "Action/EventItemAction.h"
2017-10-01 18:38:58 +02:00
#include "Zone/Zone.h"
#include "ServerZone.h"
#include "Framework.h"
2017-08-08 13:53:47 +02:00
2018-03-09 00:06:44 +01:00
extern Core::Framework g_fw;
2017-08-08 13:53:47 +02:00
using namespace Core::Common;
using namespace Core::Network::Packets;
using namespace Core::Network::Packets::Server;
2018-01-09 23:50:54 +01:00
void Core::Entity::Player::addEvent( Event::EventHandlerPtr pEvent )
2017-08-08 13:53:47 +02:00
{
m_eventHandlerMap[ pEvent->getId() ] = pEvent;
2017-08-08 13:53:47 +02:00
}
2018-01-09 23:50:54 +01:00
std::map< uint32_t, Core::Event::EventHandlerPtr >& Core::Entity::Player::eventList()
2017-08-08 13:53:47 +02:00
{
return m_eventHandlerMap;
2017-08-08 13:53:47 +02:00
}
2018-01-09 23:50:54 +01:00
Core::Event::EventHandlerPtr Core::Entity::Player::getEvent( uint32_t eventId )
2017-08-08 13:53:47 +02:00
{
auto it = m_eventHandlerMap.find( eventId );
if( it != m_eventHandlerMap.end() )
return it->second;
2017-08-08 13:53:47 +02:00
return Event::EventHandlerPtr( nullptr );
2017-08-08 13:53:47 +02:00
}
size_t Core::Entity::Player::getEventCount()
{
return m_eventHandlerMap.size();
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::removeEvent( uint32_t eventId )
{
auto it = m_eventHandlerMap.find( eventId );
if( it != m_eventHandlerMap.end() )
{
auto tmpEvent = it->second;
m_eventHandlerMap.erase( it );
}
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::checkEvent( uint32_t eventId )
{
auto pEvent = getEvent( eventId );
2017-11-28 00:09:36 +01:00
if( pEvent && !pEvent->hasPlayedScene() )
eventFinish( eventId, 1 );
2017-08-08 13:53:47 +02:00
}
2018-03-15 20:48:35 +11:00
void Core::Entity::Player::directorPlayScene( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam3,
uint32_t eventParam4, uint32_t eventParam5 )
{
if( flags & 0x02 )
setStateFlag( PlayerStateFlag::WatchingCutscene );
auto pEvent = getEvent( eventId );
if( !pEvent )
{
auto pLog = g_fw.get< Logger >();
pLog->error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" );
return;
}
pEvent->setPlayedScene( true );
pEvent->setEventReturnCallback( nullptr );
auto eventPlay = boost::make_shared< DirectorPlayScenePacket >( getId(), getId(), pEvent->getId(),
scene, flags, eventParam3, eventParam4, eventParam5 );
queuePacket( eventPlay );
}
void Core::Entity::Player::eventStart( uint64_t actorId, uint32_t eventId,
2018-01-09 23:50:54 +01:00
Event::EventHandler::EventType eventType, uint8_t eventParam1,
uint32_t eventParam2 )
2017-08-08 13:53:47 +02:00
{
auto newEvent = Event::make_EventHandler( this, actorId, eventId, eventType, eventParam2 );
addEvent( newEvent );
2017-08-08 13:53:47 +02:00
setStateFlag( PlayerStateFlag::InNpcEvent );
auto eventStart = boost::make_shared< EventStartPacket >( getId(), actorId, eventId,
eventType, eventParam1, eventParam2 );
queuePacket( eventStart );
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::playScene( uint32_t eventId, uint32_t scene,
2017-08-08 13:53:47 +02:00
uint32_t flags, uint32_t eventParam2,
uint32_t eventParam3 )
{
playScene( eventId, scene, flags, eventParam2, eventParam3, nullptr );
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::playScene( uint32_t eventId, uint32_t scene,
2018-01-09 23:50:54 +01:00
uint32_t flags, Event::EventHandler::SceneReturnCallback eventCallback )
2017-08-08 13:53:47 +02:00
{
playScene( eventId, scene, flags, 0, 0, eventCallback );
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::playScene( uint32_t eventId, uint32_t scene, uint32_t flags )
2017-08-08 13:53:47 +02:00
{
playScene( eventId, scene, flags, 0, 0, nullptr );
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::playScene( uint32_t eventId, uint32_t scene,
2017-08-08 13:53:47 +02:00
uint32_t flags, uint32_t eventParam2,
2018-01-09 23:50:54 +01:00
uint32_t eventParam3, Event::EventHandler::SceneReturnCallback eventCallback )
{
playScene( eventId, scene, flags, eventParam2, eventParam3, 0, eventCallback );
}
2018-07-22 23:20:12 +10:00
void Core::Entity::Player::playGilShop( uint32_t eventId, uint32_t flags,
Event::EventHandler::SceneReturnCallback eventCallback )
{
auto pEvent = bootstrapSceneEvent( eventId, flags );
if( !pEvent )
return;
2018-07-22 23:20:12 +10:00
pEvent->setPlayedScene( true );
pEvent->setEventReturnCallback( eventCallback );
pEvent->setSceneChainCallback( nullptr );
auto openGilShopPacket = makeZonePacket< Server::FFXIVIpcEventOpenGilShop >( getId() );
openGilShopPacket->data().eventId = eventId;
openGilShopPacket->data().sceneFlags = flags;
openGilShopPacket->data().actorId = getId();
openGilShopPacket->data().scene = 10;
queuePacket( openGilShopPacket );
}
Core::Event::EventHandlerPtr Core::Entity::Player::bootstrapSceneEvent( uint32_t eventId, uint32_t flags )
2017-08-08 13:53:47 +02:00
{
if( flags & 0x02 )
setStateFlag( PlayerStateFlag::WatchingCutscene );
auto pEvent = getEvent( eventId );
if( !pEvent && getEventCount() )
{
// We're trying to play a nested event, need to start it first.
eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 );
pEvent = getEvent( eventId );
}
else if( !pEvent )
{
auto pLog = g_fw.get< Logger >();
pLog->error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" );
return nullptr;
}
return pEvent;
}
void Core::Entity::Player::playScene( uint32_t eventId, uint32_t scene,
uint32_t flags, uint32_t eventParam2,
uint32_t eventParam3, uint32_t eventParam4,
Event::EventHandler::SceneReturnCallback eventCallback )
{
auto pEvent = bootstrapSceneEvent( eventId, flags );
if( !pEvent )
return;
pEvent->setPlayedScene( true );
pEvent->setEventReturnCallback( eventCallback );
pEvent->setSceneChainCallback( nullptr );
auto eventPlay = boost::make_shared< EventPlayPacket >( getId(), pEvent->getActorId(), pEvent->getId(),
scene, flags, eventParam2, eventParam3, eventParam4 );
2017-08-08 13:53:47 +02:00
queuePacket( eventPlay );
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::playSceneChain( uint32_t eventId, uint32_t scene, uint32_t flags,
uint32_t eventParam2, uint32_t eventParam3, uint32_t eventParam4,
Core::Event::EventHandler::SceneChainCallback sceneChainCallback )
2017-08-08 13:53:47 +02:00
{
auto pEvent = bootstrapSceneEvent( eventId, flags );
if( !pEvent )
return;
2017-08-08 13:53:47 +02:00
pEvent->setPlayedScene( true );
pEvent->setSceneChainCallback( sceneChainCallback );
pEvent->setEventReturnCallback( nullptr );
auto eventPlay = boost::make_shared< EventPlayPacket >( getId(), pEvent->getActorId(), pEvent->getId(),
scene, flags, eventParam2, eventParam3, eventParam4 );
2017-08-08 13:53:47 +02:00
queuePacket( eventPlay );
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::playSceneChain( uint32_t eventId, uint32_t scene, uint32_t flags,
uint32_t eventParam2, uint32_t eventParam3,
Core::Event::EventHandler::SceneChainCallback sceneChainCallback )
{
playSceneChain( eventId, scene, flags, eventParam2, eventParam3, 0, sceneChainCallback );
}
void Core::Entity::Player::playSceneChain( uint32_t eventId, uint32_t scene, uint32_t flags,
Core::Event::EventHandler::SceneChainCallback sceneChainCallback )
{
playSceneChain( eventId, scene, flags, 0, 0, 0, sceneChainCallback );
}
2017-08-08 13:53:47 +02:00
void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer )
{
auto pEvent = getEvent( eventId );
if( !pEvent )
{
auto pLog = g_fw.get< Logger >();
pLog->error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" );
return;
}
if( getEventCount() > 1 && pEvent->getEventType() != Event::EventHandler::Nest )
{
// this is the parent of a nested event, we can't finish it until the parent finishes
return;
}
switch( pEvent->getEventType() )
{
case Event::EventHandler::Nest:
{
2018-06-28 00:07:07 +02:00
queuePacket( boost::make_shared< EventFinishPacket >( getId(), pEvent->getId(),
pEvent->getEventType(), pEvent->getEventParam() ) );
2017-08-08 13:53:47 +02:00
removeEvent( pEvent->getId() );
auto events = eventList();
for( auto it : events )
{
if( it.second->hasPlayedScene() == false )
{
// TODO: not happy with this, this is also prone to break wit more than one remaining event in there
queuePacket( boost::make_shared< EventFinishPacket >( getId(), it.second->getId(),
it.second->getEventType(),
it.second->getEventParam() ) );
removeEvent( it.second->getId() );
}
2017-08-08 13:53:47 +02:00
}
break;
}
default:
{
2018-06-28 00:07:07 +02:00
queuePacket( boost::make_shared< EventFinishPacket >( getId(), pEvent->getId(),
pEvent->getEventType(), pEvent->getEventParam() ) );
2017-08-08 13:53:47 +02:00
break;
}
}
2017-08-08 13:53:47 +02:00
if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) )
unsetStateFlag( PlayerStateFlag::WatchingCutscene );
2017-08-08 13:53:47 +02:00
removeEvent( pEvent->getId() );
2017-08-08 13:53:47 +02:00
if( freePlayer == 1 )
unsetStateFlag( PlayerStateFlag::InNpcEvent );
2017-08-08 13:53:47 +02:00
}
2017-10-01 18:38:58 +02:00
void Core::Entity::Player::eventActionStart( uint32_t eventId,
uint32_t action,
ActionCallback finishCallback,
ActionCallback interruptCallback,
uint64_t additional )
{
auto pEventAction = Action::make_EventAction( getAsChara(), eventId, action,
finishCallback, interruptCallback, additional );
setCurrentAction( pEventAction );
auto pEvent = getEvent( eventId );
if( !pEvent && getEventCount() )
{
// We're trying to play a nested event, need to start it first.
eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 );
pEvent = getEvent( eventId );
}
else if( !pEvent )
{
auto pLog = g_fw.get< Logger >();
pLog->error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" );
return;
}
if( pEvent )
pEvent->setPlayedScene( true );
pEventAction->onStart();
2017-10-01 18:38:58 +02:00
}
void Core::Entity::Player::eventItemActionStart( uint32_t eventId,
uint32_t action,
ActionCallback finishCallback,
ActionCallback interruptCallback,
uint64_t additional )
{
Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsChara(), eventId, action,
finishCallback, interruptCallback, additional );
2017-10-01 18:38:58 +02:00
setCurrentAction( pEventItemAction );
2017-10-01 18:38:58 +02:00
pEventItemAction->onStart();
2017-10-01 18:38:58 +02:00
}
2017-08-08 13:53:47 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Core::Entity::Player::onLogin()
{
auto pConfig = g_fw.get< ConfigMgr >();
auto motd = pConfig->getValue< std::string >( "General.MotD", "" );
std::istringstream ss( motd );
std::string msg;
while( std::getline( ss, msg, ';' ) )
{
sendNotice( msg );
}
2017-08-08 13:53:47 +02:00
}
void Core::Entity::Player::onZoneStart()
{
}
void Core::Entity::Player::onZoneDone()
{
}
void Core::Entity::Player::onDeath()
{
}
// TODO: slightly ugly here and way too static. Needs too be done properly
void Core::Entity::Player::onTick()
{
bool sendUpdate = false;
if( !isAlive() || !isLoadingComplete() )
return;
2017-08-08 13:53:47 +02:00
uint32_t addHp = static_cast< uint32_t >( getMaxHp() * 0.1f + 1 );
uint32_t addMp = static_cast< uint32_t >( getMaxMp() * 0.06f + 1 );
uint32_t addTp = 100;
2017-08-08 13:53:47 +02:00
if( !m_actorIdTohateSlotMap.empty() )
{
addHp = static_cast< uint32_t >( getMaxHp() * 0.01f + 1 );
addMp = static_cast< uint32_t >( getMaxMp() * 0.02f + 1 );
addTp = 60;
}
2017-08-08 13:53:47 +02:00
if( m_hp < getMaxHp() )
{
2017-08-08 13:53:47 +02:00
if( m_hp + addHp < getMaxHp() )
m_hp += addHp;
else
m_hp = getMaxHp();
2017-08-08 13:53:47 +02:00
sendUpdate = true;
}
2017-08-08 13:53:47 +02:00
if( m_mp < getMaxMp() )
{
2017-08-08 13:53:47 +02:00
if( m_mp + addMp < getMaxMp() )
m_mp += addMp;
else
m_mp = getMaxMp();
2017-08-08 13:53:47 +02:00
sendUpdate = true;
}
2017-08-08 13:53:47 +02:00
if( m_tp < 1000 )
{
if( m_tp + addTp < 1000 )
m_tp += addTp;
else
m_tp = 1000;
2017-08-08 13:53:47 +02:00
sendUpdate = true;
}
2017-08-08 13:53:47 +02:00
if( sendUpdate )
sendStatusUpdate();
2017-08-08 13:53:47 +02:00
}