2018-11-23 16:51:07 +11:00
|
|
|
|
#include <Common.h>
|
2021-11-27 00:53:57 +01:00
|
|
|
|
#include <Exd/ExdData.h>
|
2018-11-23 16:51:07 +11:00
|
|
|
|
#include <Util/Util.h>
|
2020-03-01 01:00:57 +11:00
|
|
|
|
#include <Service.h>
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
2018-12-23 03:53:08 +01:00
|
|
|
|
#include "EventMgr.h"
|
2021-11-27 00:53:57 +01:00
|
|
|
|
#include "PlayerMgr.h"
|
|
|
|
|
#include "ShopMgr.h"
|
2018-12-23 03:53:08 +01:00
|
|
|
|
#include "Event/EventHandler.h"
|
2021-11-27 00:53:57 +01:00
|
|
|
|
#include "Event/Director.h"
|
|
|
|
|
#include "Event/EventDefs.h"
|
|
|
|
|
|
|
|
|
|
#include "Network/GameConnection.h"
|
|
|
|
|
#include "Network/PacketWrappers/ActorControlPacket.h"
|
|
|
|
|
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
|
|
|
|
#include "Network/PacketWrappers/ServerNoticePacket.h"
|
|
|
|
|
#include "Network/PacketWrappers/EventStartPacket.h"
|
|
|
|
|
#include "Network/PacketWrappers/EventPlayPacket.h"
|
|
|
|
|
#include "Network/PacketWrappers/EventFinishPacket.h"
|
|
|
|
|
|
|
|
|
|
#include "Territory/Territory.h"
|
|
|
|
|
#include "Territory/InstanceContent.h"
|
|
|
|
|
#include "Territory/QuestBattle.h"
|
|
|
|
|
|
|
|
|
|
#include "Action/EventAction.h"
|
|
|
|
|
#include "WorldServer.h"
|
|
|
|
|
#include "Actor/Player.h"
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
2018-12-23 03:53:08 +01:00
|
|
|
|
using namespace Sapphire::Common;
|
2021-11-27 00:53:57 +01:00
|
|
|
|
using namespace Sapphire::Network::Packets;
|
|
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
|
|
|
|
using namespace Sapphire::World::Manager;
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
2018-12-23 03:53:08 +01:00
|
|
|
|
std::string Sapphire::World::Manager::EventMgr::getEventName( uint32_t eventId )
|
2018-11-23 16:51:07 +11:00
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
|
|
|
|
uint16_t eventType = eventId >> 16;
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
|
|
|
|
auto unknown = std::string{ "unknown" };
|
|
|
|
|
|
|
|
|
|
switch( eventType )
|
|
|
|
|
{
|
|
|
|
|
case Event::EventHandler::EventHandlerType::Quest:
|
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto questInfo = exdData.getRow< Component::Excel::Quest >( eventId );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
if( !questInfo )
|
|
|
|
|
return unknown + "Quest";
|
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
std::string name = questInfo->getString( questInfo->data().Text.Name );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
std::size_t pos = name.find_first_of( "_" );
|
|
|
|
|
|
|
|
|
|
return name.substr( 0, pos );
|
|
|
|
|
}
|
|
|
|
|
case Event::EventHandler::EventHandlerType::CustomTalk:
|
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto customTalkInfo = exdData.getRow< Component::Excel::CustomTalk >( eventId );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
if( !customTalkInfo )
|
|
|
|
|
return unknown + "CustomTalk";
|
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
std::string name = customTalkInfo->getString( customTalkInfo->data().Text.Name );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
std::size_t pos = name.find_first_of( "_" );
|
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
return name.substr( 0, pos );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
}
|
|
|
|
|
case Event::EventHandler::EventHandlerType::Opening:
|
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto openingInfo = exdData.getRow< Component::Excel::Opening >( eventId );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
if( openingInfo )
|
2021-11-27 00:53:57 +01:00
|
|
|
|
return openingInfo->getString( openingInfo->data().Script );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
return unknown + "Opening";
|
|
|
|
|
}
|
|
|
|
|
case Event::EventHandler::EventHandlerType::Aetheryte:
|
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto aetherInfo = exdData.getRow< Component::Excel::Aetheryte >( eventId & 0xFFFF );
|
|
|
|
|
if( !aetherInfo->data().Telepo )
|
2018-11-23 16:51:07 +11:00
|
|
|
|
return "Aetheryte";
|
|
|
|
|
return "Aethernet";
|
|
|
|
|
}
|
|
|
|
|
case Event::EventHandler::EventHandlerType::ICDirector:
|
|
|
|
|
{
|
2020-02-24 23:04:25 +11:00
|
|
|
|
// auto contentInfo = pExdData->get< Sapphire::Data::InstanceContent >( eventId & 0xFFFF );
|
|
|
|
|
return "InstanceContentDirector#" + std::to_string( eventId & 0xFFFF );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
}
|
2019-03-31 23:45:03 +02:00
|
|
|
|
case Event::EventHandler::EventHandlerType::QuestBattleDirector:
|
|
|
|
|
{
|
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto qbInfo = exdData.getRow< Component::Excel::QuestBattle >( eventId & 0xFFFF );
|
2019-03-31 23:45:03 +02:00
|
|
|
|
if( !qbInfo )
|
|
|
|
|
return "unknown";
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto questInfo = exdData.getRow< Component::Excel::Quest >( qbInfo->data().Quest );
|
2019-03-31 23:45:03 +02:00
|
|
|
|
if( !questInfo )
|
|
|
|
|
return "unknown";
|
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
std::string name = questInfo->getString( questInfo->data().Text.Name );
|
2019-03-31 23:45:03 +02:00
|
|
|
|
std::string remove( ",★_ '()[]-\x1a\x1\x2\x1f\x1\x3.:" );
|
2021-11-27 00:53:57 +01:00
|
|
|
|
Common::Util::eraseAllIn( name, remove );
|
2019-03-31 23:45:03 +02:00
|
|
|
|
name[ 0 ] = toupper( name[ 0 ] );
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
|
|
|
|
case Event::EventHandler::EventHandlerType::Warp:
|
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto warpInfo = exdData.getRow< Component::Excel::Warp >( eventId );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
if( warpInfo )
|
|
|
|
|
return "WarpTaxi";
|
|
|
|
|
return unknown + "ChocoboWarp"; //who know
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case Event::EventHandler::EventHandlerType::Shop:
|
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
//auto shopInfo = exdData.getRow< Component::Excel::ShopStruct >( eventId );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
|
|
|
|
return "GilShop" + std::to_string( eventId );
|
|
|
|
|
/*if( shopInfo )
|
|
|
|
|
{
|
|
|
|
|
if( shopInfo->name.empty() || shopInfo->name == " " )
|
|
|
|
|
return "GilShop" + std::to_string( eventId );
|
|
|
|
|
return shopInfo->name;
|
|
|
|
|
}*/
|
|
|
|
|
//return unknown + "GilShop";
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
return unknown;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
std::string Sapphire::World::Manager::EventMgr::getErrorCodeName( uint8_t errorCode )
|
|
|
|
|
{
|
|
|
|
|
switch ( errorCode )
|
|
|
|
|
{
|
|
|
|
|
case EventSceneError::EVENT_SCENE_SUCCESS:
|
|
|
|
|
{
|
|
|
|
|
return "SUCCESS";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_LUA_ERRRUN:
|
|
|
|
|
{
|
|
|
|
|
return "LUA_ERRRUN";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_LUA_ERRSYNTAX:
|
|
|
|
|
{
|
|
|
|
|
return "LUA_ERRSYNTAX";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_LUA_ERRMEM:
|
|
|
|
|
{
|
|
|
|
|
return "LUA_ERRMEM";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_LUA_ERRERR:
|
|
|
|
|
{
|
|
|
|
|
return "LUA_ERRERR";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_USER_CANCEL:
|
|
|
|
|
{
|
|
|
|
|
return "USER_CANCEL";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_SERVER_ABORT:
|
|
|
|
|
{
|
|
|
|
|
return "SERVER_ABORT";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_RELOAD:
|
|
|
|
|
{
|
|
|
|
|
return "RELOAD";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_LUA_THREAD_BUSY:
|
|
|
|
|
{
|
|
|
|
|
return "LUA_THREAD_BUSY";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_TARGET_CHANGED:
|
|
|
|
|
{
|
|
|
|
|
return "TARGET_CHANGED";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_CLIENT_ABORT:
|
|
|
|
|
{
|
|
|
|
|
return "CLIENT_ABORT";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_TARGET_LOST:
|
|
|
|
|
{
|
|
|
|
|
return "TARGET_LOST";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_BEFORE_PLAY:
|
|
|
|
|
{
|
|
|
|
|
return "BEFORE_PLAY";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_BIND_CHARACTER:
|
|
|
|
|
{
|
|
|
|
|
return "BIND_CHARACTER";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_TARGET_MOVE:
|
|
|
|
|
{
|
|
|
|
|
return "TARGET_MOVE";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_SCRIPT_NOT_READY:
|
|
|
|
|
{
|
|
|
|
|
return "SCRIPT_NOT_READY";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_TARGET_WARP:
|
|
|
|
|
{
|
|
|
|
|
return "TARGET_WARP";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_BIND_OBJECT:
|
|
|
|
|
{
|
|
|
|
|
return "BIND_OBJECT";
|
|
|
|
|
}
|
|
|
|
|
case EventSceneError::EVENT_SCENE_ERROR_MAX:
|
|
|
|
|
{
|
|
|
|
|
return "MAX";
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
return std::string{ "unknown" };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-23 03:53:08 +01:00
|
|
|
|
uint32_t Sapphire::World::Manager::EventMgr::mapEventActorToRealActor( uint32_t eventActorId )
|
2018-11-23 16:51:07 +11:00
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
|
|
|
|
auto levelInfo = exdData.getRow< Component::Excel::Level >( eventActorId );
|
2018-11-23 16:51:07 +11:00
|
|
|
|
if( levelInfo )
|
2021-11-27 00:53:57 +01:00
|
|
|
|
return levelInfo->data().BaseId;
|
2018-11-23 16:51:07 +11:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2021-11-27 00:53:57 +01:00
|
|
|
|
|
|
|
|
|
void Sapphire::World::Manager::EventMgr::handleReturnEventScene( Entity::Player& player, uint32_t eventId, uint16_t sceneId, uint8_t errorCode,
|
|
|
|
|
uint8_t numOfResults, const std::vector< uint32_t >& results )
|
|
|
|
|
{
|
|
|
|
|
std::string eventName = getEventName( eventId );
|
|
|
|
|
|
|
|
|
|
PlayerMgr::sendDebug( player, "eventId: {0} ({0:08X}) scene: {1}, errorCode: {2} numArgs: {3}",
|
|
|
|
|
eventId, sceneId, getErrorCodeName( errorCode ), numOfResults );
|
|
|
|
|
|
|
|
|
|
uint8_t index = 0;
|
|
|
|
|
for( auto r : results )
|
|
|
|
|
{
|
|
|
|
|
PlayerMgr::sendDebug( player, "arg#{0}: {1} ({1:08X})", index++, r );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto eventType = static_cast< uint16_t >( eventId >> 16 );
|
|
|
|
|
|
|
|
|
|
auto pEvent = player.getEvent( eventId );
|
|
|
|
|
if( pEvent )
|
|
|
|
|
{
|
|
|
|
|
pEvent->setPlayedScene( false );
|
|
|
|
|
// try to retrieve a stored callback
|
|
|
|
|
// if there is one, proceed to call it
|
|
|
|
|
Event::SceneResult result;
|
|
|
|
|
result.actorId = pEvent->getActorId();
|
|
|
|
|
result.eventId = eventId;
|
|
|
|
|
result.sceneId = sceneId;
|
|
|
|
|
result.errorCode = errorCode;
|
|
|
|
|
result.numOfResults = numOfResults;
|
|
|
|
|
result.results = results;
|
|
|
|
|
|
|
|
|
|
if( eventType == Event::EventHandler::EventHandlerType::Quest )
|
|
|
|
|
{
|
|
|
|
|
auto questId = static_cast< uint16_t >( eventId );
|
|
|
|
|
auto eventCallback = pEvent->getQuestEventReturnCallback();
|
|
|
|
|
if( eventCallback )
|
|
|
|
|
{
|
|
|
|
|
World::Quest preQ;
|
|
|
|
|
if( player.hasQuest( eventId ) )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
auto questIdx = player.getQuestIndex( questId );
|
|
|
|
|
auto& quest = player.getQuestByIndex( questIdx );
|
|
|
|
|
preQ = quest;
|
|
|
|
|
eventCallback( quest, player, result );
|
|
|
|
|
if( quest != preQ )
|
|
|
|
|
player.updateQuest( quest );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto newQuest = World::Quest( questId, 0, 0 );
|
|
|
|
|
preQ = newQuest;
|
|
|
|
|
eventCallback( newQuest, player, result );
|
|
|
|
|
if( newQuest != preQ )
|
|
|
|
|
player.updateQuest( newQuest );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if( auto chainCallback = pEvent->getQuestSceneChainCallback() )
|
|
|
|
|
{
|
|
|
|
|
if( player.hasQuest( eventId ) )
|
|
|
|
|
{
|
|
|
|
|
auto questIdx = player.getQuestIndex( questId );
|
|
|
|
|
auto& quest = player.getQuestByIndex( questIdx );
|
|
|
|
|
chainCallback( quest, player );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto newQuest = World::Quest( questId, 0, 0 );
|
|
|
|
|
chainCallback( newQuest, player );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto eventCallback = pEvent->getEventReturnCallback();
|
|
|
|
|
if( eventCallback )
|
|
|
|
|
{
|
|
|
|
|
eventCallback( player, result );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we might have a scene chain callback instead so check for that too
|
|
|
|
|
else if( auto chainCallback = pEvent->getSceneChainCallback() )
|
|
|
|
|
chainCallback( player );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkEvent( player, eventId );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::checkEvent( Sapphire::Entity::Player &player, uint32_t eventId )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = player.getEvent( eventId );
|
|
|
|
|
|
|
|
|
|
if( pEvent && !pEvent->hasPlayedScene() )
|
|
|
|
|
eventFinish( player, eventId, 1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EventMgr::eventFinish( Sapphire::Entity::Player& player, uint32_t eventId, uint32_t freePlayer )
|
|
|
|
|
{
|
|
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
|
|
|
|
auto pEvent = player.getEvent( eventId );
|
|
|
|
|
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
{
|
|
|
|
|
Logger::error( "Could not find event #{0}, event has not been started!", eventId );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( player.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:
|
|
|
|
|
{
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< EventFinishPacket >( player.getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam() ) );
|
|
|
|
|
player.removeEvent( pEvent->getId() );
|
|
|
|
|
|
|
|
|
|
auto callback = pEvent->getEventFinishCallback();
|
|
|
|
|
|
|
|
|
|
if( callback )
|
|
|
|
|
callback( player, pEvent->getActorId() );
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto events = player.getEventListRef();
|
|
|
|
|
for( const auto& it : events )
|
|
|
|
|
{
|
|
|
|
|
if( !it.second->hasPlayedScene() )
|
|
|
|
|
{
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(),
|
|
|
|
|
std::make_shared< EventFinishPacket >( player.getId(), it.second->getId(), it.second->getEventType(),
|
|
|
|
|
it.second->getEventParam() ) );
|
|
|
|
|
player.removeEvent( it.second->getId() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(),
|
|
|
|
|
std::make_shared< EventFinishPacket >( player.getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam() ) );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( player.hasStateFlag( PlayerStateFlag::WatchingCutscene ) )
|
|
|
|
|
player.unsetStateFlag( PlayerStateFlag::WatchingCutscene );
|
|
|
|
|
|
|
|
|
|
player.removeEvent( pEvent->getId() );
|
|
|
|
|
|
|
|
|
|
if( freePlayer == 1 )
|
|
|
|
|
player.unsetStateFlag( PlayerStateFlag::InNpcEvent );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::eventStart( Entity::Player& player, uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventType, uint8_t eventParam1,
|
|
|
|
|
uint32_t eventParam2, Event::EventHandler::EventFinishCallback callback )
|
|
|
|
|
{
|
|
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
|
|
|
|
auto newEvent = Event::make_EventHandler( actorId, eventId, eventType, eventParam2 );
|
|
|
|
|
newEvent->setEventFinishCallback( std::move( callback ) );
|
|
|
|
|
player.addEvent( newEvent );
|
|
|
|
|
|
|
|
|
|
player.setStateFlag( PlayerStateFlag::InNpcEvent );
|
|
|
|
|
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< EventStartPacket >( player.getId(), actorId, eventId, eventType, eventParam1, eventParam2 ) );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::eventActionStart( Entity::Player& player, uint32_t eventId, uint32_t action,
|
|
|
|
|
World::Action::ActionCallback finishCallback, World::Action::ActionCallback interruptCallback,
|
|
|
|
|
uint64_t additional )
|
|
|
|
|
{
|
|
|
|
|
auto pEventAction = World::Action::make_EventAction( player.getAsChara(), eventId, action, finishCallback, interruptCallback, additional );
|
|
|
|
|
|
|
|
|
|
auto pEvent = player.getEvent( eventId );
|
|
|
|
|
|
|
|
|
|
if( !pEvent && player.getEventCount() )
|
|
|
|
|
{
|
|
|
|
|
// We're trying to play a nested event, need to start it first.
|
|
|
|
|
eventStart( player, player.getId(), eventId, Event::EventHandler::Nest, 0, 0 );
|
|
|
|
|
pEvent = player.getEvent( eventId );
|
|
|
|
|
}
|
|
|
|
|
else if( !pEvent )
|
|
|
|
|
{
|
|
|
|
|
Logger::error( "Could not find event #{0}, event has not been started!", eventId );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( pEvent )
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
|
|
|
|
|
player.setCurrentAction( pEventAction );
|
|
|
|
|
pEventAction->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::eventItemActionStart( Entity::Player& player, uint32_t eventId, uint32_t action, World::Action::ActionCallback finishCallback,
|
|
|
|
|
World::Action::ActionCallback interruptCallback, uint64_t additional )
|
|
|
|
|
{
|
|
|
|
|
// Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsChara(), eventId, action,
|
|
|
|
|
// finishCallback, interruptCallback, additional );
|
|
|
|
|
//
|
|
|
|
|
// setCurrentAction( pEventItemAction );
|
|
|
|
|
//
|
|
|
|
|
// pEventItemAction->onStart();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EventMgr::playGilShop( Entity::Player& player, uint32_t eventId, uint32_t flags, uint32_t param1, Event::EventHandler::SceneReturnCallback eventCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if( param1 == 0 ) //list items
|
|
|
|
|
{
|
|
|
|
|
auto& shopMgr = Common::Service< ShopMgr >::ref();
|
|
|
|
|
std::vector< uint32_t > params = std::vector< uint32_t >();
|
|
|
|
|
|
|
|
|
|
params.push_back( 1 ); //command id
|
|
|
|
|
params.push_back( 40 ); //max items for sell
|
|
|
|
|
params.push_back( 1 ); //flag
|
|
|
|
|
uint8_t index;
|
|
|
|
|
for( index = 0; index < 40; index++ )
|
|
|
|
|
{
|
|
|
|
|
if( uint32_t price = shopMgr.getShopItemPrices( eventId, index ) )
|
|
|
|
|
params.push_back( price );
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
params[ 1 ] = static_cast< uint32_t >( params.size() - 3 ); //new max item size
|
|
|
|
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
|
|
|
|
|
|
|
|
|
for( auto it = player.getSoldItems()->cbegin(); it != player.getSoldItems()->cend(); ++it )
|
|
|
|
|
{
|
|
|
|
|
auto item = exdData.getRow< Component::Excel::Item >( it->first );
|
|
|
|
|
params.push_back( it->first ); //itemCatalogId
|
|
|
|
|
params.push_back( it->second ); //stack
|
|
|
|
|
params.push_back( item->data().Price ); //price
|
|
|
|
|
params.push_back( 0 );//flag isHQ
|
|
|
|
|
params.push_back( 0 );//numOfMateria
|
|
|
|
|
params.push_back( eventId ); //shopId
|
|
|
|
|
|
|
|
|
|
params.push_back( 0 );//signatureId
|
|
|
|
|
params.push_back( 0 );//signatureId
|
|
|
|
|
|
|
|
|
|
params.push_back( ( 1000 << 16 ) + 1000 );//durability + refine
|
|
|
|
|
params.push_back( 0 );//stain
|
|
|
|
|
params.push_back( 0 );//pattern
|
|
|
|
|
|
|
|
|
|
for( uint8_t slot = 0; slot < 5; slot++ ) //materia
|
|
|
|
|
{
|
|
|
|
|
params.push_back( 0 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
playScene( player, eventId, 40, flags, params, std::move( eventCallback ) );
|
|
|
|
|
}
|
|
|
|
|
else if( param1 == 2 ) //sell item
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::playScene( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags, std::vector< uint32_t > values,
|
|
|
|
|
Event::EventHandler::SceneReturnCallback eventCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
pEvent->setEventReturnCallback( eventCallback );
|
|
|
|
|
pEvent->setSceneChainCallback( nullptr );
|
|
|
|
|
pEvent->getScenePlayParams()->setParams( scene, values );
|
|
|
|
|
|
|
|
|
|
sendEventPlay( player, eventId, scene, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::playScene( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags, Event::EventHandler::SceneReturnCallback eventCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
pEvent->setEventReturnCallback( std::move( eventCallback ) );
|
|
|
|
|
pEvent->setSceneChainCallback( nullptr );
|
|
|
|
|
|
|
|
|
|
sendEventPlay( player, eventId, scene, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::playQuestScene( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags, Event::EventHandler::QuestSceneReturnCallback eventCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
pEvent->setQuestEventReturnCallback( std::move( eventCallback ) );
|
|
|
|
|
pEvent->setSceneChainCallback( nullptr );
|
|
|
|
|
|
|
|
|
|
sendEventPlay( player, eventId, scene, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::playSceneChain( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags,
|
|
|
|
|
Sapphire::Event::EventHandler::SceneChainCallback sceneChainCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
pEvent->setSceneChainCallback( std::move( sceneChainCallback ) );
|
|
|
|
|
pEvent->setEventReturnCallback( nullptr );
|
|
|
|
|
|
|
|
|
|
sendEventPlay( player, eventId, scene, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::playSceneChain( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags, std::vector< uint32_t > values,
|
|
|
|
|
Sapphire::Event::EventHandler::SceneChainCallback sceneChainCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
pEvent->setSceneChainCallback( sceneChainCallback );
|
|
|
|
|
pEvent->setEventReturnCallback( nullptr );
|
|
|
|
|
pEvent->getScenePlayParams()->setParams( scene, values );
|
|
|
|
|
|
|
|
|
|
sendEventPlay( player, eventId, scene, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EventMgr::playQuestSceneChain( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags,
|
|
|
|
|
Sapphire::Event::EventHandler::QuestSceneChainCallback sceneChainCallback )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = bootstrapSceneEvent( player, eventId, flags );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pEvent->setPlayedScene( true );
|
|
|
|
|
pEvent->setQuestSceneChainCallback( std::move( sceneChainCallback ) );
|
|
|
|
|
pEvent->setEventReturnCallback( nullptr );
|
|
|
|
|
pEvent->setQuestEventReturnCallback( nullptr );
|
|
|
|
|
|
|
|
|
|
sendEventPlay( player, eventId, scene, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EventMgr::sendEventPlay( Entity::Player& player, uint32_t eventId, uint32_t scene, uint32_t flags )
|
|
|
|
|
{
|
|
|
|
|
auto pEvent = player.getEvent( eventId );
|
|
|
|
|
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
FFXIVPacketBasePtr pPacket = nullptr;
|
|
|
|
|
size_t paramCount = 0;
|
|
|
|
|
if( auto pEventParams = pEvent->getScenePlayParams()->getParams( scene ) )
|
|
|
|
|
paramCount = pEventParams->size();
|
|
|
|
|
|
|
|
|
|
assert( paramCount <= 255 );
|
|
|
|
|
|
|
|
|
|
if( paramCount < 2 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket2 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if( paramCount < 4 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket4 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if( paramCount < 8 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket8 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if( paramCount < 16 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket16 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if( paramCount < 32 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket32 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if( paramCount < 64 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket64 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if( paramCount < 128 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket128 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
else if ( paramCount < 255 )
|
|
|
|
|
{
|
|
|
|
|
pPacket = std::move( std::make_shared< EventPlayPacket255 >( player, pEvent->getActorId(), pEvent->getId(), scene, flags ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(), pPacket );
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sapphire::Event::EventHandlerPtr EventMgr::bootstrapSceneEvent( Entity::Player& player, uint32_t eventId, uint32_t flags )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
auto pEvent = player.getEvent( eventId );
|
|
|
|
|
if( !pEvent )
|
|
|
|
|
{
|
|
|
|
|
Logger::error( "Could not find event #{0}, event has not been started!", eventId );
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( flags & CONDITION_CUTSCENE )
|
|
|
|
|
player.setStateFlag( PlayerStateFlag::WatchingCutscene );
|
|
|
|
|
|
|
|
|
|
return pEvent;
|
|
|
|
|
}
|