1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-25 11:07:45 +00:00

public content support and wedding prep work

This commit is contained in:
collett 2021-08-09 02:38:20 +09:00
parent 9985b8232b
commit 40ecbb8765
24 changed files with 809 additions and 11 deletions

View file

@ -0,0 +1,29 @@
#include <ScriptObject.h>
#include <Actor/Player.h>
using namespace Sapphire;
class RegFstEternalCeremonyGuideRoom : public Sapphire::ScriptAPI::EventScript
{
public:
RegFstEternalCeremonyGuideRoom() : Sapphire::ScriptAPI::EventScript( 720912 )
{
}
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
{
Scene00000( player );
}
void Scene00000( Entity::Player& player )
{
player.playSceneChain( getId(), 0, HIDE_HOTBAR, bindScene( &RegFstEternalCeremonyGuideRoom::Scene00001 ) );
}
void Scene00001( Entity::Player& player )
{
player.playScene( getId(), 1, HIDE_HOTBAR );
}
};
EXPOSE_SCRIPT( RegFstEternalCeremonyGuideRoom );

View file

@ -0,0 +1,51 @@
#include <ScriptObject.h>
#include <Territory/InstanceContent.h>
#include "Actor/Player.h"
#include "Territory/PublicContent.h"
using namespace Sapphire;
class SanctumOfTheTwelve : public Sapphire::ScriptAPI::PublicContentScript
{
public:
SanctumOfTheTwelve() : Sapphire::ScriptAPI::PublicContentScript( 1 ) { }
void onInit( PublicContent& instance ) override
{
}
void onUpdate( PublicContent& instance, uint64_t tickCount ) override
{
}
void onPlayerZoneIn( PublicContent& instance, Entity::Player& player ) override
{
player.setPosAndSendActorMove( 0, 250, -50, player.getRot() );
}
void onLeaveTerritory( PublicContent& instance, Entity::Player& player ) override
{
}
void onEnterTerritory( PublicContent& instance, Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
{
player.directorPlayScene( instance.getDirectorId(), 1, NONE, 0, 0, 0 );
}
void onDebug( Entity::Player& player, uint32_t param ) override
{
auto instance = player.getCurrentPublicContent();
if( !instance || instance->getDirectorId() != getId() )
return;
player.sendUrgent( "SanctumOfTheTwelve: debug {}", param );
player.eventStart( player.getId(), instance->getDirectorId(), Event::EventHandler::EnterTerritory, 1, player.getZoneId() );
player.directorPlayScene( instance->getDirectorId(), 3, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, 0, 1, param );
}
};
EXPOSE_SCRIPT( SanctumOfTheTwelve );

View file

@ -351,7 +351,7 @@ Sapphire::InstanceContentPtr Sapphire::Entity::Actor::getCurrentInstance() const
return nullptr; return nullptr;
} }
/*! \return QuestBattlePtr to the current instance, nullptr if not an instance or not set */ /*! \return QuestBattlePtr to the current instance, nullptr if not a quest battle or not set */
Sapphire::QuestBattlePtr Sapphire::Entity::Actor::getCurrentQuestBattle() const Sapphire::QuestBattlePtr Sapphire::Entity::Actor::getCurrentQuestBattle() const
{ {
if( m_pCurrentTerritory ) if( m_pCurrentTerritory )
@ -360,6 +360,15 @@ Sapphire::QuestBattlePtr Sapphire::Entity::Actor::getCurrentQuestBattle() const
return nullptr; return nullptr;
} }
/*! \return PublicContentPtr to the current instance, nullptr if not a public content or not set */
Sapphire::PublicContentPtr Sapphire::Entity::Actor::getCurrentPublicContent() const
{
if( m_pCurrentTerritory )
return m_pCurrentTerritory->getAsPublicContent();
return nullptr;
}
/*! /*!
Get the current cell of a region the actor is in Get the current cell of a region the actor is in

View file

@ -130,6 +130,8 @@ namespace Sapphire::Entity
QuestBattlePtr getCurrentQuestBattle() const; QuestBattlePtr getCurrentQuestBattle() const;
PublicContentPtr getCurrentPublicContent() const;
// get the current cell of a region the actor is in // get the current cell of a region the actor is in
Cell* getCellPtr(); Cell* getCellPtr();

View file

@ -59,7 +59,7 @@ void Sapphire::Event::Director::sendDirectorVars( Sapphire::Entity::Player& play
void Sapphire::Event::Director::sendDirectorInit( Sapphire::Entity::Player& player ) const void Sapphire::Event::Director::sendDirectorInit( Sapphire::Entity::Player& player ) const
{ {
Logger::debug( "DirectorID#{}, QuestBattleID#{}", m_directorId, m_contentId ); Logger::debug( "DirectorID#{}, ContentId#{}", m_directorId, m_contentId );
player.queuePacket( makeActorControlSelf( player.getId(), DirectorInit, m_directorId, m_contentId ) ); player.queuePacket( makeActorControlSelf( player.getId(), DirectorInit, m_directorId, m_contentId ) );
} }

View file

@ -79,6 +79,7 @@ namespace Sapphire::Event
Adventure = 0x0021, Adventure = 0x0021,
DailyQuestSupply = 0x0022, DailyQuestSupply = 0x0022,
ICDirector = 0x8003, ICDirector = 0x8003,
PublicContentDirector = 0x8004,
QuestBattleDirector = 0x8006, QuestBattleDirector = 0x8006,
}; };

View file

@ -24,6 +24,7 @@ TYPE_FORWARD( HousingZone );
TYPE_FORWARD( House ); TYPE_FORWARD( House );
TYPE_FORWARD( InstanceContent ); TYPE_FORWARD( InstanceContent );
TYPE_FORWARD( QuestBattle ); TYPE_FORWARD( QuestBattle );
TYPE_FORWARD( PublicContent );
TYPE_FORWARD( Item ); TYPE_FORWARD( Item );
TYPE_FORWARD( ItemContainer ); TYPE_FORWARD( ItemContainer );
TYPE_FORWARD( ZonePosition ); TYPE_FORWARD( ZonePosition );

View file

@ -32,6 +32,7 @@
#include "Territory/HousingZone.h" #include "Territory/HousingZone.h"
#include "Territory/InstanceContent.h" #include "Territory/InstanceContent.h"
#include "Territory/QuestBattle.h" #include "Territory/QuestBattle.h"
#include "Territory/PublicContent.h"
#include "Manager/TerritoryMgr.h" #include "Manager/TerritoryMgr.h"
#include "Event/EventDefs.h" #include "Event/EventDefs.h"
@ -60,6 +61,8 @@ Sapphire::World::Manager::DebugCommandMgr::DebugCommandMgr()
registerCommand( "script", &DebugCommandMgr::script, "Server script utilities.", 1 ); registerCommand( "script", &DebugCommandMgr::script, "Server script utilities.", 1 );
registerCommand( "instance", &DebugCommandMgr::instance, "Instance utilities", 1 ); registerCommand( "instance", &DebugCommandMgr::instance, "Instance utilities", 1 );
registerCommand( "questbattle", &DebugCommandMgr::questBattle, "Quest battle utilities", 1 ); registerCommand( "questbattle", &DebugCommandMgr::questBattle, "Quest battle utilities", 1 );
registerCommand( "pc", &DebugCommandMgr::pc, "Public content utilities", 1 );
registerCommand( "publiccontent", &DebugCommandMgr::pc, "Public content utilities", 1 );
registerCommand( "qb", &DebugCommandMgr::questBattle, "Quest battle utilities", 1 ); registerCommand( "qb", &DebugCommandMgr::questBattle, "Quest battle utilities", 1 );
registerCommand( "housing", &DebugCommandMgr::housing, "Housing utilities", 1 ); registerCommand( "housing", &DebugCommandMgr::housing, "Housing utilities", 1 );
} }
@ -670,6 +673,12 @@ void Sapphire::World::Manager::DebugCommandMgr::get( char* data, Entity::Player&
instance->getInstanceContentId(), instance->getDirectorId(), instance->getSequence(), instance->getInstanceContentId(), instance->getDirectorId(), instance->getSequence(),
instance->getBranch(), instance->getCurrentBGM() ); instance->getBranch(), instance->getCurrentBGM() );
} }
else if( auto instance = player.getCurrentPublicContent() )
{
player.sendNotice( "Public content info:\nContentId: {}, DirectorId: {}\nSequence: {}, Branch: {}",
instance->getContentId(), instance->getDirectorId(), instance->getSequence(),
instance->getBranch() );
}
} }
else else
{ {
@ -890,6 +899,12 @@ void Sapphire::World::Manager::DebugCommandMgr::script( char* data, Entity::Play
player.sendDebug( "Queued script reload for script: {0}", params ); player.sendDebug( "Queued script reload for script: {0}", params );
} }
} }
else if ( subCommand == "debug" )
{
uint32_t id, param;
sscanf( params.c_str(), "%u %u", &id, &param );
scriptMgr.onDebug( id, player, param );
}
else else
{ {
player.sendDebug( "Unknown script subcommand: {0}", subCommand ); player.sendDebug( "Unknown script subcommand: {0}", subCommand );
@ -1375,3 +1390,99 @@ void Sapphire::World::Manager::DebugCommandMgr::housing( char* data, Entity::Pla
player.sendDebug( "Unknown sub command." ); player.sendDebug( "Unknown sub command." );
} }
} }
void Sapphire::World::Manager::DebugCommandMgr::pc( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command )
{
auto& terriMgr = Common::Service< TerritoryMgr >::ref();
std::string cmd( data ), params, subCommand;
auto cmdPos = cmd.find_first_of( ' ' );
if( cmdPos != std::string::npos )
{
params = cmd.substr( cmdPos + 1 );
auto p = params.find_first_of( ' ' );
if( p != std::string::npos )
{
subCommand = params.substr( 0, p );
params = params.substr( subCommand.length() + 1 );
}
else
subCommand = params;
}
if( subCommand == "create" || subCommand == "cr" )
{
uint32_t contentFinderConditionId;
sscanf( params.c_str(), "%d", &contentFinderConditionId );
auto instance = terriMgr.createPublicContent( contentFinderConditionId );
if( instance )
player.sendDebug( "Created instance with id#{0} -> {1}", instance->getGuId(), instance->getName() );
else
player.sendDebug( "Failed to create instance with id#{0}", contentFinderConditionId );
}
else if ( subCommand == "create2" || subCommand == "cr2" )
{
uint16_t contentId, terriId;
sscanf( params.c_str(), "%hu %hu", &contentId, &terriId );
auto instance = terriMgr.createPublicContent( contentId, terriId );
if( instance )
player.sendDebug( "Created instance with id#{0} -> {1}", instance->getGuId(), instance->getName() );
else
player.sendDebug( "Failed to create instance with id#{0}, territory#{1}. Server console output may contain additional info.", contentId, terriId );
}
else if( subCommand == "remove" || subCommand == "rm" )
{
uint32_t terriId;
sscanf( params.c_str(), "%d", &terriId );
if( terriMgr.removeTerritoryInstance( terriId ) )
player.sendDebug( "Removed instance with id#{0}", terriId );
else
player.sendDebug( "Failed to remove instance with id#{0}", terriId );
}
else if( subCommand == "return" || subCommand == "ret" )
{
player.exitInstance();
}
else if( subCommand == "set" )
{
uint32_t index;
uint32_t value;
sscanf( params.c_str(), "%d %d", &index, &value );
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
if( !instance )
return;
instance->setVar( static_cast< uint8_t >( index ), static_cast< uint8_t >( value ) );
}
else if( subCommand == "seq" )
{
uint8_t seq;
sscanf( params.c_str(), "%hhu", &seq );
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
if( !instance )
return;
instance->setSequence( seq );
}
else if( subCommand == "branch" )
{
uint8_t branch;
sscanf( params.c_str(), "%hhu", &branch );
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
if( !instance )
return;
instance->setBranch( branch );
}
}

View file

@ -53,6 +53,7 @@ namespace Sapphire::World::Manager
void instance( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command ); void instance( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
void questBattle( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command ); void questBattle( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
void pc( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
void housing( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command) ; void housing( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command) ;

View file

@ -74,6 +74,13 @@ std::string Sapphire::World::Manager::EventMgr::getEventName( uint32_t eventId )
name[ 0 ] = toupper( name[ 0 ] ); name[ 0 ] = toupper( name[ 0 ] );
return name; return name;
} }
case Event::EventHandler::EventHandlerType::PublicContentDirector:
{
auto pcInfo = exdData.get< Sapphire::Data::PublicContent >( eventId & 0x0000FFFF );
if( !pcInfo )
return "unknown";
return pcInfo->name;
}
case Event::EventHandler::EventHandlerType::Warp: case Event::EventHandler::EventHandlerType::Warp:

View file

@ -13,6 +13,7 @@
#include "Territory/ZonePosition.h" #include "Territory/ZonePosition.h"
#include "Territory/InstanceContent.h" #include "Territory/InstanceContent.h"
#include "Territory/QuestBattle.h" #include "Territory/QuestBattle.h"
#include "Territory/PublicContent.h"
#include "TerritoryMgr.h" #include "TerritoryMgr.h"
#include "HousingMgr.h" #include "HousingMgr.h"
@ -111,7 +112,13 @@ bool Sapphire::World::Manager::TerritoryMgr::isInstanceContentTerritory( uint32_
intendedUse == TerritoryIntendedUse::RaidFights || intendedUse == TerritoryIntendedUse::RaidFights ||
intendedUse == TerritoryIntendedUse::Raids || intendedUse == TerritoryIntendedUse::Raids ||
intendedUse == TerritoryIntendedUse::TreasureMapInstance || intendedUse == TerritoryIntendedUse::TreasureMapInstance ||
intendedUse == TerritoryIntendedUse::EventTrial; intendedUse == TerritoryIntendedUse::EventTrial ||
intendedUse == TerritoryIntendedUse::DiademV1 ||
intendedUse == TerritoryIntendedUse::DiademV2 ||
intendedUse == TerritoryIntendedUse::DiademV3 ||
intendedUse == TerritoryIntendedUse::Eureka ||
intendedUse == TerritoryIntendedUse::Bozja ||
intendedUse == TerritoryIntendedUse::Wedding;
} }
bool Sapphire::World::Manager::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const bool Sapphire::World::Manager::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const
@ -306,8 +313,8 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createQuestBattle
if( !pQuestInfo ) if( !pQuestInfo )
return nullptr; return nullptr;
if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) ) //if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) )
return nullptr; // return nullptr;
auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType ); auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType );
@ -340,8 +347,8 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createInstanceCon
if( !pInstanceContent ) if( !pInstanceContent )
return nullptr; return nullptr;
if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) ) //if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) )
return nullptr; // return nullptr;
auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType ); auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType );
@ -361,6 +368,68 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createInstanceCon
return pZone; return pZone;
} }
Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createPublicContent( uint32_t contentFinderConditionId )
{
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto pContentFinderCondition = exdData.get< Sapphire::Data::ContentFinderCondition >( contentFinderConditionId );
if( !pContentFinderCondition )
return nullptr;
auto contentId = pContentFinderCondition->content;
auto pPublicContent = exdData.get< Sapphire::Data::PublicContent >( contentId );
if( !pPublicContent )
return nullptr;
auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType );
if( !pTeri || pContentFinderCondition->name.empty() )
return nullptr;
Logger::debug( "Starting instance for PublicContent id: {0} ({1})", contentId, pContentFinderCondition->name );
auto pZone = make_PublicContent( pPublicContent, pContentFinderCondition->territoryType, getNextInstanceId(),
pTeri->name, pContentFinderCondition->name, contentId );
pZone->init();
m_publicContentIdToInstanceMap[ contentId ][ pZone->getGuId() ] = pZone;
m_guIdToTerritoryPtrMap[ pZone->getGuId() ] = pZone;
m_instanceZoneSet.insert( pZone );
return pZone;
}
Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createPublicContent( uint16_t contentId, uint16_t territoryId )
{
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto pPublicContent = exdData.get< Sapphire::Data::PublicContent >( contentId );
if( !pPublicContent )
return nullptr;
if( pPublicContent->contentFinderCondition > 0 )
{
Logger::warn( "the public content {} has a ContentFinderCondition value of {}, create the instance using it instead.", contentId, pPublicContent->contentFinderCondition );
return nullptr;
}
auto pTeri = getTerritoryDetail( territoryId );
if( !pTeri )
return nullptr;
Logger::debug( "Starting instance for PublicContent id: {0} ({1})", contentId, pPublicContent->name );
auto pZone = make_PublicContent( pPublicContent, territoryId, getNextInstanceId(), pTeri->name, pPublicContent->name, contentId );
pZone->init();
m_publicContentIdToInstanceMap[ contentId ][ pZone->getGuId() ] = pZone;
m_guIdToTerritoryPtrMap[ pZone->getGuId() ] = pZone;
m_instanceZoneSet.insert( pZone );
return pZone;
}
Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::findOrCreateHousingInterior( const Common::LandIdent landIdent ) Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::findOrCreateHousingInterior( const Common::LandIdent landIdent )
{ {
// check if zone already spawned first // check if zone already spawned first
@ -445,11 +514,21 @@ bool Sapphire::World::Manager::TerritoryMgr::removeTerritoryInstance( uint32_t g
m_instanceZoneSet.erase( pZone ); m_instanceZoneSet.erase( pZone );
m_territorySet.erase( pZone ); m_territorySet.erase( pZone );
if( isInstanceContentTerritory( pZone->getTerritoryTypeId() ) ) if( pZone->getAsInstanceContent() )
{ {
auto instance = std::dynamic_pointer_cast< InstanceContent >( pZone ); auto instance = std::dynamic_pointer_cast< InstanceContent >( pZone );
m_instanceContentIdToInstanceMap[ instance->getInstanceContentId() ].erase( pZone->getGuId() ); m_instanceContentIdToInstanceMap[ instance->getInstanceContentId() ].erase( pZone->getGuId() );
} }
else if( pZone->getAsPublicContent() )
{
auto instance = std::dynamic_pointer_cast< PublicContent >( pZone );
m_publicContentIdToInstanceMap[ instance->getContentId() ].erase( pZone->getGuId() );
}
else if( pZone->getAsQuestBattle() )
{
auto instance = std::dynamic_pointer_cast< QuestBattle >( pZone );
m_questBattleIdToInstanceMap[ instance->getQuestBattleId() ].erase( pZone->getGuId() );
}
else else
m_territoryTypeIdToInstanceGuidMap[ pZone->getTerritoryTypeId() ].erase( pZone->getGuId() ); m_territoryTypeIdToInstanceGuidMap[ pZone->getTerritoryTypeId() ].erase( pZone->getGuId() );
@ -617,7 +696,7 @@ bool Sapphire::World::Manager::TerritoryMgr::movePlayer( TerritoryPtr pZone, Sap
if( pHousing ) if( pHousing )
pPlayer->setTerritoryId( pHousing->getLandSetId() ); pPlayer->setTerritoryId( pHousing->getLandSetId() );
} }
else if( isInstanceContentTerritory( pZone->getTerritoryTypeId() ) ) else if( pZone->getAsInstanceContent() || pZone->getAsQuestBattle() || pZone->getAsPublicContent() )
{ {
pPlayer->setTerritoryId( pZone->getGuId() ); pPlayer->setTerritoryId( pZone->getGuId() );
} }

View file

@ -120,6 +120,9 @@ namespace Sapphire::World::Manager
TerritoryPtr createQuestBattle( uint32_t contentFinderConditionId ); TerritoryPtr createQuestBattle( uint32_t contentFinderConditionId );
TerritoryPtr createPublicContent( uint32_t contentFinderConditionId );
TerritoryPtr createPublicContent( uint16_t contentId, uint16_t territoryId );
void createAndJoinQuestBattle( Entity::Player& player, uint16_t contentFinderConditionId ); void createAndJoinQuestBattle( Entity::Player& player, uint16_t contentFinderConditionId );
TerritoryPtr findOrCreateHousingInterior( const Common::LandIdent landIdent ); TerritoryPtr findOrCreateHousingInterior( const Common::LandIdent landIdent );
@ -181,6 +184,7 @@ namespace Sapphire::World::Manager
using InstanceContentIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >; using InstanceContentIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >;
using QuestBattleIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >; using QuestBattleIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >;
using QuestBattleIdToContentFinderCondMap = std::unordered_map< uint16_t, uint16_t >; using QuestBattleIdToContentFinderCondMap = std::unordered_map< uint16_t, uint16_t >;
using PublicContentIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >;
using PlayerIdToInstanceIdMap = std::unordered_map< uint32_t, uint32_t >; using PlayerIdToInstanceIdMap = std::unordered_map< uint32_t, uint32_t >;
using PositionMap = std::unordered_map< int32_t, ZonePositionPtr >; using PositionMap = std::unordered_map< int32_t, ZonePositionPtr >;
using InstanceIdList = std::vector< uint32_t >; using InstanceIdList = std::vector< uint32_t >;
@ -198,9 +202,12 @@ namespace Sapphire::World::Manager
/*! map holding actual instances of InstanceContent */ /*! map holding actual instances of InstanceContent */
InstanceContentIdToInstanceMap m_instanceContentIdToInstanceMap; InstanceContentIdToInstanceMap m_instanceContentIdToInstanceMap;
/*! map holding actual instances of InstanceContent */ /*! map holding actual instances of QuestBattle */
QuestBattleIdToInstanceMap m_questBattleIdToInstanceMap; QuestBattleIdToInstanceMap m_questBattleIdToInstanceMap;
/*! map holding actual instances of PublicContent */
PublicContentIdToInstanceMap m_publicContentIdToInstanceMap;
/*! flat map for easier lookup of instances by guid */ /*! flat map for easier lookup of instances by guid */
InstanceIdToTerritoryPtrMap m_guIdToTerritoryPtrMap; InstanceIdToTerritoryPtrMap m_guIdToTerritoryPtrMap;

View file

@ -24,6 +24,7 @@
#include "Territory/InstanceContent.h" #include "Territory/InstanceContent.h"
#include "Territory/QuestBattle.h" #include "Territory/QuestBattle.h"
#include "Territory/PublicContent.h"
#include "Session.h" #include "Session.h"
@ -60,6 +61,14 @@ void Sapphire::Network::GameConnection::eventHandlerTalk( const Packets::FFXIVAR
{ {
instance->onTalk( player, eventId, actorId ); instance->onTalk( player, eventId, actorId );
} }
else if( auto instance = player.getCurrentQuestBattle() )
{
instance->onTalk( player, eventId, actorId );
}
else if( auto instance = player.getCurrentPublicContent() )
{
instance->onTalk( player, eventId, actorId );
}
bool eventCalled = false; bool eventCalled = false;
if( eventType == Event::EventHandler::EventHandlerType::Warp ) if( eventType == Event::EventHandler::EventHandlerType::Warp )
@ -196,6 +205,11 @@ void Sapphire::Network::GameConnection::eventHandlerEnterTerritory( const Packet
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 1, player.getZoneId() ); player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 1, player.getZoneId() );
instance->onEnterTerritory( player, eventId, param1, param2 ); instance->onEnterTerritory( player, eventId, param1, param2 );
} }
else if( auto instance = player.getCurrentPublicContent() )
{
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 1, player.getZoneId() );
instance->onEnterTerritory( player, eventId, param1, param2 );
}
else else
{ {
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() ); player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() );

View file

@ -31,6 +31,10 @@ namespace Sapphire::ScriptAPI
return m_type; return m_type;
} }
void ScriptObject::onDebug( Entity::Player& player, uint32_t param )
{
}
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
StatusEffectScript::StatusEffectScript( uint32_t effectId ) : StatusEffectScript::StatusEffectScript( uint32_t effectId ) :
@ -232,5 +236,31 @@ namespace Sapphire::ScriptAPI
{ {
} }
PublicContentScript::PublicContentScript( uint32_t contentId ) :
ScriptObject( uint32_t{ 0x8004 } << 16 | contentId, typeid( PublicContentScript ).hash_code() )
{
}
void PublicContentScript::onInit( PublicContent& instance )
{
}
void PublicContentScript::onUpdate( PublicContent& instance, uint64_t tickCount )
{
}
void PublicContentScript::onPlayerZoneIn( PublicContent& instance, Entity::Player& player )
{
}
void PublicContentScript::onLeaveTerritory( PublicContent& instance, Entity::Player& player )
{
}
void PublicContentScript::onEnterTerritory( PublicContent& instance, Entity::Player& player, uint32_t eventId,
uint16_t param1, uint16_t param2 )
{
}
} }

View file

@ -46,6 +46,8 @@ namespace Sapphire::ScriptAPI
* @return The hash_code of the script * @return The hash_code of the script
*/ */
virtual std::size_t getType() const; virtual std::size_t getType() const;
virtual void onDebug( Sapphire::Entity::Player& player, uint32_t param );
}; };
@ -245,6 +247,23 @@ namespace Sapphire::ScriptAPI
uint16_t param1, uint16_t param2 ); uint16_t param1, uint16_t param2 );
}; };
class PublicContentScript : public ScriptObject
{
public:
explicit PublicContentScript( uint32_t contentId );
virtual void onInit( Sapphire::PublicContent& instance );
virtual void onUpdate( Sapphire::PublicContent& instance, uint64_t tickCount );
virtual void onPlayerZoneIn( Sapphire::PublicContent& instance, Sapphire::Entity::Player& player );
virtual void onLeaveTerritory( Sapphire::PublicContent& instance, Sapphire::Entity::Player& player );
virtual void onEnterTerritory( Sapphire::PublicContent& instance, Sapphire::Entity::Player& player, uint32_t eventId,
uint16_t param1, uint16_t param2 );
};
} }
#endif #endif

View file

@ -130,5 +130,17 @@ namespace Sapphire::Scripting
{ {
return std::make_shared< NativeScriptMgr >(); return std::make_shared< NativeScriptMgr >();
} }
Sapphire::ScriptAPI::ScriptObject* NativeScriptMgr::getScript( uint32_t scriptId )
{
for( auto typedMap : m_scripts )
{
auto script = typedMap.second.find( scriptId );
if( script == typedMap.second.end() )
continue;
return script->second;
}
return nullptr;
}
} }

View file

@ -116,6 +116,8 @@ namespace Sapphire::Scripting
return dynamic_cast< T* >( script->second ); return dynamic_cast< T* >( script->second );
} }
Sapphire::ScriptAPI::ScriptObject* getScript( uint32_t scriptId );
}; };

View file

@ -7,6 +7,7 @@
#include "Territory/Territory.h" #include "Territory/Territory.h"
#include "Territory/InstanceContent.h" #include "Territory/InstanceContent.h"
#include "Territory/QuestBattle.h" #include "Territory/QuestBattle.h"
#include "Territory/PublicContent.h"
#include "Actor/Player.h" #include "Actor/Player.h"
#include "Actor/EventObject.h" #include "Actor/EventObject.h"
#include "ServerMgr.h" #include "ServerMgr.h"
@ -147,6 +148,13 @@ bool Sapphire::Scripting::ScriptMgr::loadDir( const std::string& dirname, std::s
} }
} }
void Sapphire::Scripting::ScriptMgr::onDebug( uint32_t id, Entity::Player& player, uint32_t param )
{
auto script = m_nativeScriptMgr->getScript( id );
if( script )
script->onDebug( player, param );
}
void Sapphire::Scripting::ScriptMgr::onPlayerFirstEnterWorld( Entity::Player& player ) void Sapphire::Scripting::ScriptMgr::onPlayerFirstEnterWorld( Entity::Player& player )
{ {
// try // try
@ -589,3 +597,65 @@ bool Sapphire::Scripting::ScriptMgr::onSaveData( Sapphire::Entity::Player& playe
return false; return false;
} }
bool Sapphire::Scripting::ScriptMgr::onPublicContentInit( PublicContentPtr instance )
{
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
if( script )
{
script->onInit( *instance );
return true;
}
return false;
}
bool Sapphire::Scripting::ScriptMgr::onPublicContentUpdate( PublicContentPtr instance, uint64_t tickCount )
{
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
if( script )
{
script->onUpdate( *instance, tickCount );
return true;
}
return false;
}
bool Sapphire::Scripting::ScriptMgr::onPublicContentPlayerZoneIn( PublicContentPtr instance, Entity::Player& player )
{
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
if( script )
{
script->onPlayerZoneIn( *instance, player );
return true;
}
return false;
}
bool Sapphire::Scripting::ScriptMgr::onPublicContentLeaveTerritory( PublicContentPtr instance, Entity::Player& player )
{
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
if( script )
{
script->onLeaveTerritory( *instance, player );
return true;
}
return false;
}
bool Sapphire::Scripting::ScriptMgr::onPublicContentEnterTerritory( PublicContentPtr instance, Entity::Player& player,
uint32_t eventId, uint16_t param1, uint16_t param2 )
{
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
if( script )
{
script->onEnterTerritory( *instance, player, eventId, param1, param2 );
return true;
}
return false;
}

View file

@ -52,6 +52,8 @@ namespace Sapphire::Scripting
*/ */
void watchDirectories(); void watchDirectories();
void onDebug( uint32_t id, Entity::Player& player, uint32_t param );
void onPlayerFirstEnterWorld( Entity::Player& player ); void onPlayerFirstEnterWorld( Entity::Player& player );
bool onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ); bool onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId );
@ -120,6 +122,16 @@ namespace Sapphire::Scripting
bool onSaveData( Entity::Player& player, const Common::EventSaveData& data ); bool onSaveData( Entity::Player& player, const Common::EventSaveData& data );
bool onPublicContentInit( PublicContentPtr instance );
bool onPublicContentUpdate( PublicContentPtr instance, uint64_t tickCount );
bool onPublicContentPlayerZoneIn( PublicContentPtr instance, Entity::Player& player );
bool onPublicContentLeaveTerritory( PublicContentPtr instance, Entity::Player& player );
bool onPublicContentEnterTerritory( PublicContentPtr instance, Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 );
bool loadDir( const std::string& dirname, std::set< std::string >& files, const std::string& ext ); bool loadDir( const std::string& dirname, std::set< std::string >& files, const std::string& ext );
NativeScriptMgr& getNativeScriptHandler(); NativeScriptMgr& getNativeScriptHandler();

View file

@ -310,6 +310,8 @@ void Sapphire::InstanceContent::onRegisterEObj( Entity::EventObjectPtr object )
m_eventObjectMap[ object->getName() ] = object; m_eventObjectMap[ object->getName() ] = object;
if( object->getObjectId() == 2000182 ) // start if( object->getObjectId() == 2000182 ) // start
m_pEntranceEObj = object; m_pEntranceEObj = object;
if( object->getName() == "Entrance" )
m_pEntranceEObj = object;
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto objData = exdData.get< Sapphire::Data::EObj >( object->getObjectId() ); auto objData = exdData.get< Sapphire::Data::EObj >( object->getObjectId() );

View file

@ -0,0 +1,261 @@
#include <Common.h>
#include <Logging/Logger.h>
#include <Util/Util.h>
#include <Util/UtilMath.h>
#include <Exd/ExdDataGenerated.h>
#include <Network/CommonActorControl.h>
#include <Service.h>
#include "Actor/Player.h"
#include "Actor/EventObject.h"
#include "Event/Director.h"
#include "Event/EventDefs.h"
#include "Event/EventHandler.h"
#include "Script/ScriptMgr.h"
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "PublicContent.h"
using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
using namespace Sapphire::Network::ActorControl;
Sapphire::PublicContent::PublicContent( std::shared_ptr< Sapphire::Data::PublicContent > pConfiguration,
uint16_t territoryType,
uint32_t guId,
const std::string& internalName,
const std::string& contentName,
uint32_t contentId ) :
Territory( static_cast< uint16_t >( territoryType ), guId, internalName, contentName ),
Director( Event::Director::PublicContent, contentId ),
m_Configuration( pConfiguration ),
m_ContentId( contentId )
{
}
bool Sapphire::PublicContent::init()
{
if( !Territory::init() )
return false;
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onPublicContentInit( getAsPublicContent() );
return true;
}
Sapphire::PublicContent::~PublicContent()
{
}
uint32_t Sapphire::PublicContent::getContentId() const
{
return m_ContentId;
}
Sapphire::Data::ExdDataGenerated::PublicContentPtr Sapphire::PublicContent::getConfiguration() const
{
return m_Configuration;
}
void Sapphire::PublicContent::onPlayerZoneIn( Entity::Player& player )
{
Logger::debug( "PublicContent::onPlayerZoneIn: Territory#{0}|{1}, Entity#{2}", getGuId(), getTerritoryTypeId(), player.getId() );
sendDirectorInit( player );
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onPublicContentPlayerZoneIn( getAsPublicContent(), player );
}
void Sapphire::PublicContent::onLeaveTerritory( Entity::Player& player )
{
Logger::debug( "PublicContent::onLeaveTerritory: Territory#{0}|{1}, Entity#{2}", getGuId(), getTerritoryTypeId(), player.getId() );
clearDirector( player );
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onPublicContentLeaveTerritory( getAsPublicContent(), player );
}
void Sapphire::PublicContent::onUpdate( uint64_t tickCount )
{
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onPublicContentUpdate( getAsPublicContent(), tickCount );
}
void Sapphire::PublicContent::onFinishLoading( Entity::Player& player )
{
sendDirectorInit( player );
}
void Sapphire::PublicContent::onInitDirector( Entity::Player& player )
{
sendDirectorVars( player );
player.setDirectorInitialized( true );
}
void Sapphire::PublicContent::onDirectorSync( Entity::Player& player )
{
player.queuePacket( makeActorControlSelf( player.getId(), DirectorUpdate, 0x00110001, 0x80000000, 1 ) );
}
void Sapphire::PublicContent::onBeforePlayerZoneIn( Sapphire::Entity::Player& player )
{
if( m_pEntranceEObj != nullptr )
{
player.setRot( PI );
player.setPos( m_pEntranceEObj->getPos() );
}
else
{
player.setRot( PI );
player.setPos( { 0.f, 0.f, 0.f } );
}
player.resetObjSpawnIndex();
}
void Sapphire::PublicContent::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 )
{
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onPublicContentEnterTerritory( getAsPublicContent(), player, eventId, param1, param2 );
}
void Sapphire::PublicContent::onRegisterEObj( Entity::EventObjectPtr object )
{
if( object->getName() != "none" )
m_eventObjectMap[ object->getName() ] = object;
if( object->getObjectId() == 2000182 ) // start
m_pEntranceEObj = object;
if( object->getName() == "Entrance" )
m_pEntranceEObj = object;
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto objData = exdData.get< Sapphire::Data::EObj >( object->getObjectId() );
if( objData )
m_eventIdToObjectMap[ objData->data ] = object;
else
Logger::error( "PublicContent::onRegisterEObj Territory " +
m_internalName + ": No EObj data found for EObj with ID: " +
std::to_string( object->getObjectId() ) );
}
void Sapphire::PublicContent::clearDirector( Entity::Player& player )
{
sendDirectorClear( player );
player.setDirectorInitialized( false );
}
void Sapphire::PublicContent::onTalk( Sapphire::Entity::Player& player, uint32_t eventId, uint64_t actorId )
{
auto it = m_eventIdToObjectMap.find( eventId );
if( it == m_eventIdToObjectMap.end() )
return;
if( auto onTalk = it->second->getOnTalkHandler() )
onTalk( player, it->second, getAsPublicContent(), actorId );
else
player.sendDebug( "No onTalk handler found for interactable eobj with EObjID#{0}, eventId#{1} ",
it->second->getObjectId(), eventId );
}
void Sapphire::PublicContent::setVar( uint8_t index, uint8_t value )
{
if( index > 19 )
return;
switch( index )
{
case 0:
setDirectorUI8AL( value );
break;
case 1:
setDirectorUI8AH( value );
break;
case 2:
setDirectorUI8BL( value );
break;
case 3:
setDirectorUI8BH( value );
break;
case 4:
setDirectorUI8CL( value );
break;
case 5:
setDirectorUI8CH( value );
break;
case 6:
setDirectorUI8DL( value );
break;
case 7:
setDirectorUI8DH( value );
break;
case 8:
setDirectorUI8EL( value );
break;
case 9:
setDirectorUI8EH( value );
break;
case 10:
setDirectorUI8FL( value );
break;
case 11:
setDirectorUI8FH( value );
break;
case 12:
setDirectorUI8GL( value );
break;
case 13:
setDirectorUI8GH( value );
break;
case 14:
setDirectorUI8HL( value );
break;
case 15:
setDirectorUI8HH( value );
break;
case 16:
setDirectorUI8IL( value );
break;
case 17:
setDirectorUI8IH( value );
break;
case 18:
setDirectorUI8JL( value );
break;
case 19:
setDirectorUI8JH( value );
break;
}
// todo: genericise this?
for( const auto& playerIt : m_playerMap )
{
sendDirectorVars( *playerIt.second );
}
}
void Sapphire::PublicContent::setSequence( uint8_t value )
{
setDirectorSequence( value );
for( const auto& playerIt : m_playerMap )
{
sendDirectorVars( *playerIt.second );
}
}
void Sapphire::PublicContent::setBranch( uint8_t value )
{
setDirectorBranch( value );
for( const auto& playerIt : m_playerMap )
{
sendDirectorVars( *playerIt.second );
}
}

View file

@ -0,0 +1,70 @@
#ifndef SAPPHIRE_PUBLICCONTENT_H
#define SAPPHIRE_PUBLICCONTENT_H
#include "Territory.h"
#include "Event/Director.h"
#include "Forwards.h"
namespace Sapphire::Data
{
struct PublicContent;
}
namespace Sapphire
{
class PublicContent : public Event::Director, public Territory
{
public:
PublicContent( std::shared_ptr< Sapphire::Data::PublicContent > pConfiguration,
uint16_t territoryType,
uint32_t guId,
const std::string& internalName,
const std::string& contentName,
uint32_t contentId );
virtual ~PublicContent();
bool init() override;
void onBeforePlayerZoneIn( Entity::Player& player ) override;
void onPlayerZoneIn( Entity::Player& player ) override;
void onLeaveTerritory( Entity::Player& player ) override;
void onUpdate( uint64_t tickCount ) override;
void onFinishLoading( Entity::Player& player ) override;
void onInitDirector( Entity::Player& player ) override;
void onDirectorSync( Entity::Player& player ) override;
void onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override;
void onRegisterEObj( Entity::EventObjectPtr object ) override;
std::shared_ptr< Sapphire::Data::PublicContent > getConfiguration() const;
uint32_t getContentId() const;
void clearDirector( Entity::Player& player );
void onTalk( Entity::Player& player, uint32_t eventId, uint64_t actorId );
void setSequence( uint8_t value );
void setBranch( uint8_t value );
void setVar( uint8_t index, uint8_t value );
private:
std::shared_ptr< Sapphire::Data::PublicContent > m_Configuration;
uint32_t m_ContentId;
Entity::EventObjectPtr m_pEntranceEObj;
std::map< std::string, Entity::EventObjectPtr > m_eventObjectMap;
std::unordered_map< uint32_t, Entity::EventObjectPtr > m_eventIdToObjectMap;
};
}
#endif //SAPPHIRE_PUBLICCONTENT_H

View file

@ -19,6 +19,7 @@
#include "Territory.h" #include "Territory.h"
#include "InstanceContent.h" #include "InstanceContent.h"
#include "QuestBattle.h" #include "QuestBattle.h"
#include "PublicContent.h"
#include "Manager/TerritoryMgr.h" #include "Manager/TerritoryMgr.h"
#include "Navi/NaviProvider.h" #include "Navi/NaviProvider.h"
@ -790,6 +791,11 @@ Sapphire::QuestBattlePtr Sapphire::Territory::getAsQuestBattle()
return std::dynamic_pointer_cast< QuestBattle, Territory >( shared_from_this() ); return std::dynamic_pointer_cast< QuestBattle, Territory >( shared_from_this() );
} }
Sapphire::PublicContentPtr Sapphire::Territory::getAsPublicContent()
{
return std::dynamic_pointer_cast< PublicContent, Territory >( shared_from_this() );
}
uint32_t Sapphire::Territory::getNextEObjId() uint32_t Sapphire::Territory::getNextEObjId()
{ {
return ++m_nextEObjId; return ++m_nextEObjId;

View file

@ -170,6 +170,8 @@ namespace Sapphire
QuestBattlePtr getAsQuestBattle(); QuestBattlePtr getAsQuestBattle();
PublicContentPtr getAsPublicContent();
void updateSpawnPoints(); void updateSpawnPoints();
uint32_t getNextEffectSequence(); uint32_t getNextEffectSequence();