2018-01-29 13:05:33 +11:00
|
|
|
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Common.h>
|
|
|
|
#include <Logging/Logger.h>
|
|
|
|
#include <Util/Util.h>
|
|
|
|
#include <Util/UtilMath.h>
|
|
|
|
#include <Exd/ExdDataGenerated.h>
|
2018-06-23 21:38:04 +02:00
|
|
|
#include <Network/CommonActorControl.h>
|
2018-02-07 00:00:48 +01:00
|
|
|
|
|
|
|
#include "Event/Director.h"
|
2018-03-13 20:06:34 +11:00
|
|
|
#include "Event/EventDefs.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Script/ScriptMgr.h"
|
2018-02-04 23:35:16 +01:00
|
|
|
|
|
|
|
#include "Actor/Player.h"
|
2018-02-28 10:26:03 +01:00
|
|
|
#include "Actor/EventObject.h"
|
2018-02-04 23:35:16 +01:00
|
|
|
|
2018-02-06 00:01:23 +01:00
|
|
|
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
|
|
|
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
|
|
|
|
2018-03-06 00:10:36 +01:00
|
|
|
|
2018-02-25 17:23:52 +11:00
|
|
|
#include "Event/EventHandler.h"
|
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "InstanceContent.h"
|
|
|
|
#include "Framework.h"
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
using namespace Sapphire::Common;
|
|
|
|
using namespace Sapphire::Network::Packets;
|
|
|
|
using namespace Sapphire::Network::Packets::Server;
|
|
|
|
using namespace Sapphire::Network::ActorControl;
|
2018-02-06 00:01:23 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::InstanceContent::InstanceContent( std::shared_ptr< Sapphire::Data::InstanceContent > pInstanceConfiguration,
|
2018-12-29 00:53:52 +01:00
|
|
|
uint16_t territoryType,
|
|
|
|
uint32_t guId,
|
|
|
|
const std::string& internalName,
|
|
|
|
const std::string& contentName,
|
|
|
|
uint32_t instanceContentId,
|
|
|
|
FrameworkPtr pFw ) :
|
2019-07-21 22:33:33 +10:00
|
|
|
Territory( static_cast< uint16_t >( territoryType ), guId, internalName, contentName, pFw ),
|
2018-08-29 21:40:59 +02:00
|
|
|
Director( Event::Director::InstanceContent, instanceContentId ),
|
|
|
|
m_instanceConfiguration( pInstanceConfiguration ),
|
|
|
|
m_instanceContentId( instanceContentId ),
|
|
|
|
m_state( Created ),
|
|
|
|
m_pEntranceEObj( nullptr ),
|
|
|
|
m_instanceCommenceTime( 0 ),
|
|
|
|
m_currentBgm( pInstanceConfiguration->bGM )
|
2018-01-29 13:05:33 +11:00
|
|
|
{
|
2018-02-23 23:47:21 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::InstanceContent::init()
|
2018-02-23 23:47:21 +01:00
|
|
|
{
|
2019-07-21 22:33:33 +10:00
|
|
|
if( !Territory::init() )
|
2019-04-19 18:52:55 +10:00
|
|
|
return false;
|
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
2018-08-29 21:40:59 +02:00
|
|
|
pScriptMgr->onInstanceInit( getAsInstanceContent() );
|
2018-02-23 23:47:21 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return true;
|
2018-01-29 13:05:33 +11:00
|
|
|
}
|
|
|
|
|
2018-02-23 23:47:21 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::InstanceContent::~InstanceContent()
|
2018-01-29 13:05:33 +11:00
|
|
|
{
|
|
|
|
|
2018-01-29 19:41:41 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint32_t Sapphire::InstanceContent::getInstanceContentId() const
|
2018-01-29 19:41:41 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_instanceContentId;
|
2018-01-29 19:41:41 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Data::ExdDataGenerated::InstanceContentPtr Sapphire::InstanceContent::getInstanceConfiguration() const
|
2018-01-29 19:41:41 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_instanceConfiguration;
|
2018-01-29 19:41:41 +01:00
|
|
|
}
|
2018-02-04 23:35:16 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onPlayerZoneIn( Entity::Player& player )
|
2018-02-04 23:35:16 +01:00
|
|
|
{
|
2019-07-21 22:33:33 +10:00
|
|
|
Logger::debug( "InstanceContent::onPlayerZoneIn: Territory#{0}|{1}, Entity#{2}",
|
2019-01-04 22:37:01 +11:00
|
|
|
getGuId(), getTerritoryTypeId(), player.getId() );
|
2018-02-06 00:01:23 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// mark player as "bound by duty"
|
|
|
|
player.setStateFlag( PlayerStateFlag::BoundByDuty );
|
2018-02-07 00:00:48 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// if the instance was not started yet, director init is sent on enter event.
|
|
|
|
// else it will be sent on finish loading.
|
|
|
|
if( m_state == Created )
|
|
|
|
sendDirectorInit( player );
|
2018-02-07 00:00:48 +01:00
|
|
|
|
2018-02-04 23:35:16 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onLeaveTerritory( Entity::Player& player )
|
2018-02-04 23:35:16 +01:00
|
|
|
{
|
2019-07-21 22:33:33 +10:00
|
|
|
Logger::debug( "InstanceContent::onLeaveTerritory: Territory#{0}|{1}, Entity#{2}",
|
2019-01-04 22:37:01 +11:00
|
|
|
getGuId(), getTerritoryTypeId(), player.getId() );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-01-13 17:32:43 +01:00
|
|
|
clearDirector( player );
|
2018-02-04 23:35:16 +01:00
|
|
|
}
|
|
|
|
|
2019-04-04 23:29:52 +02:00
|
|
|
void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
|
2018-02-04 23:35:16 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
switch( m_state )
|
|
|
|
{
|
|
|
|
case Created:
|
|
|
|
{
|
2019-04-19 18:52:55 +10:00
|
|
|
if( m_boundPlayerIds.empty() )
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
for( auto playerId : m_boundPlayerIds )
|
2018-02-07 00:00:48 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto it = m_playerMap.find( playerId );
|
|
|
|
if( it == m_playerMap.end() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto player = it->second;
|
|
|
|
if( !player->isLoadingComplete() ||
|
|
|
|
!player->isDirectorInitialized() ||
|
|
|
|
!player->isOnEnterEventDone() ||
|
|
|
|
player->hasStateFlag( PlayerStateFlag::WatchingCutscene ) )
|
|
|
|
return;
|
2018-02-07 00:00:48 +01:00
|
|
|
}
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( m_instanceCommenceTime == 0 )
|
|
|
|
{
|
2019-04-04 23:29:52 +02:00
|
|
|
m_instanceCommenceTime = tickCount + instanceStartDelay;
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-04-04 23:29:52 +02:00
|
|
|
else if( tickCount < m_instanceCommenceTime )
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
2018-02-07 00:00:48 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( const auto& playerIt : m_playerMap )
|
2018-02-07 00:00:48 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pPlayer = playerIt.second;
|
|
|
|
pPlayer->queuePacket( makeActorControl143( pPlayer->getId(), DirectorUpdate,
|
|
|
|
getDirectorId(), 0x40000001,
|
|
|
|
m_instanceConfiguration->timeLimitmin * 60u ) );
|
2018-02-07 00:00:48 +01:00
|
|
|
}
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( m_pEntranceEObj )
|
|
|
|
m_pEntranceEObj->setState( 7 );
|
|
|
|
m_state = DutyInProgress;
|
|
|
|
m_instanceExpireTime = Util::getTimeSeconds() + ( m_instanceConfiguration->timeLimitmin * 60u );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case DutyReset:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DutyInProgress:
|
|
|
|
{
|
2019-04-17 00:10:32 +02:00
|
|
|
updateBNpcs( tickCount );
|
2018-08-29 21:40:59 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-02-07 00:00:48 +01:00
|
|
|
|
2018-03-16 16:56:43 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
case DutyFinished:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
2019-04-04 23:29:52 +02:00
|
|
|
pScriptMgr->onInstanceUpdate( getAsInstanceContent(), tickCount );
|
2019-04-20 15:13:46 +10:00
|
|
|
|
|
|
|
m_lastUpdate = tickCount;
|
2018-02-04 23:35:16 +01:00
|
|
|
}
|
2018-02-06 00:01:23 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onFinishLoading( Entity::Player& player )
|
2018-02-06 00:01:23 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
sendDirectorInit( player );
|
2018-02-06 00:01:23 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onInitDirector( Entity::Player& player )
|
2018-02-06 00:01:23 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
sendDirectorVars( player );
|
|
|
|
player.setDirectorInitialized( true );
|
2018-02-07 00:00:48 +01:00
|
|
|
}
|
2018-02-06 00:01:23 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onDirectorSync( Entity::Player& player )
|
2018-03-05 23:01:55 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
player.queuePacket( makeActorControl143( player.getId(), DirectorUpdate, 0x00110001, 0x80000000, 1 ) );
|
2018-03-05 23:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::setVar( uint8_t index, uint8_t value )
|
2018-02-07 00:00:48 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
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 );
|
|
|
|
}
|
2018-02-23 23:47:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::setSequence( uint8_t value )
|
2018-02-28 22:25:11 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
setDirectorSequence( value );
|
2018-02-28 22:25:11 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( const auto& playerIt : m_playerMap )
|
|
|
|
{
|
|
|
|
sendDirectorVars( *playerIt.second );
|
|
|
|
}
|
2018-02-28 22:25:11 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::setBranch( uint8_t value )
|
2018-02-28 22:25:11 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
setDirectorBranch( value );
|
2018-02-28 22:25:11 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( const auto& playerIt : m_playerMap )
|
|
|
|
{
|
|
|
|
sendDirectorVars( *playerIt.second );
|
|
|
|
}
|
2018-02-28 22:25:11 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::startQte()
|
2018-03-10 00:06:44 +09:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
for( const auto& playerIt : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = playerIt.second;
|
|
|
|
player->queuePacket( makeActorControl143( player->getId(), DirectorUpdate, getDirectorId(), 0x8000000A ) );
|
|
|
|
}
|
2018-03-10 00:06:44 +09:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::startEventCutscene()
|
2018-03-10 00:06:44 +09:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// TODO: lock player movement
|
|
|
|
for( const auto& playerIt : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = playerIt.second;
|
|
|
|
player->queuePacket( makeActorControl143( player->getId(), DirectorUpdate, getDirectorId(), 0x80000008 ) );
|
|
|
|
}
|
2018-03-10 00:06:44 +09:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::endEventCutscene()
|
2018-03-10 00:06:44 +09:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
for( const auto& playerIt : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = playerIt.second;
|
|
|
|
player->queuePacket( makeActorControl143( player->getId(), DirectorUpdate, getDirectorId(), 0x80000009 ) );
|
|
|
|
}
|
2018-03-10 00:06:44 +09:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onRegisterEObj( Entity::EventObjectPtr object )
|
2018-02-23 23:47:21 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( object->getName() != "none" )
|
|
|
|
m_eventObjectMap[ object->getName() ] = object;
|
|
|
|
if( object->getObjectId() == 2000182 ) // start
|
|
|
|
m_pEntranceEObj = object;
|
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
|
2018-11-29 16:55:48 +01:00
|
|
|
auto objData = pExdData->get< Sapphire::Data::EObj >( object->getObjectId() );
|
2018-08-29 21:40:59 +02:00
|
|
|
if( objData )
|
|
|
|
// todo: data should be renamed to eventId
|
|
|
|
m_eventIdToObjectMap[ objData->data ] = object;
|
|
|
|
else
|
2019-07-21 22:33:33 +10:00
|
|
|
Logger::error( "InstanceContent::onRegisterEObj Territory " +
|
2018-12-23 03:53:08 +01:00
|
|
|
m_internalName + ": No EObj data found for EObj with ID: " +
|
|
|
|
std::to_string( object->getObjectId() ) );
|
2018-02-23 23:47:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::InstanceContent::hasPlayerPreviouslySpawned( Entity::Player& player ) const
|
2018-03-13 17:57:52 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto it = m_spawnedPlayers.find( player.getId() );
|
|
|
|
return it != m_spawnedPlayers.end();
|
2018-03-13 17:57:52 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::InstanceContent::InstanceContentState Sapphire::InstanceContent::getState() const
|
2018-03-13 17:57:52 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_state;
|
2018-03-13 17:57:52 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onBeforePlayerZoneIn( Sapphire::Entity::Player& player )
|
2018-02-23 23:47:21 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// remove any players from the instance who aren't bound on zone in
|
|
|
|
if( !isPlayerBound( player.getId() ) )
|
|
|
|
player.exitInstance();
|
|
|
|
|
|
|
|
// if a player has already spawned once inside this instance, don't move them if they happen to zone in again
|
|
|
|
if( !hasPlayerPreviouslySpawned( 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();
|
2018-02-23 23:47:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Entity::EventObjectPtr Sapphire::InstanceContent::getEObjByName( const std::string& name )
|
2018-02-24 00:07:07 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto it = m_eventObjectMap.find( name );
|
|
|
|
if( it == m_eventObjectMap.end() )
|
|
|
|
return nullptr;
|
2018-02-24 00:07:07 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return it->second;
|
2018-02-24 00:07:07 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::onTalk( Sapphire::Entity::Player& player, uint32_t eventId, uint64_t actorId )
|
2018-02-25 17:23:52 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// todo: handle exit (and maybe shortcut?) behaviour here
|
2018-02-27 02:13:01 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto it = m_eventIdToObjectMap.find( eventId );
|
|
|
|
if( it == m_eventIdToObjectMap.end() )
|
|
|
|
return;
|
2018-02-27 02:13:01 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( auto onTalk = it->second->getOnTalkHandler() )
|
|
|
|
onTalk( player, it->second, getAsInstanceContent(), actorId );
|
|
|
|
else
|
2019-01-05 12:32:10 +01:00
|
|
|
player.sendDebug( "No onTalk handler found for interactable eobj with EObjID#{0}, eventId#{1} ",
|
|
|
|
it->second->getObjectId(), eventId );
|
2018-02-25 17:23:52 +11:00
|
|
|
}
|
2018-03-05 22:10:14 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
void
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::InstanceContent::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 )
|
2018-03-05 22:10:14 +11:00
|
|
|
{
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
2018-08-29 21:40:59 +02:00
|
|
|
pScriptMgr->onInstanceEnterTerritory( getAsInstanceContent(), player, eventId, param1, param2 );
|
|
|
|
|
|
|
|
if( !hasPlayerPreviouslySpawned( player ) )
|
|
|
|
{
|
|
|
|
m_spawnedPlayers.insert( player.getId() );
|
|
|
|
player.directorPlayScene( getDirectorId(), 1, NO_DEFAULT_CAMERA | CONDITION_CUTSCENE | SILENT_ENTER_TERRI_ENV |
|
|
|
|
HIDE_HOTBAR | SILENT_ENTER_TERRI_BGM | SILENT_ENTER_TERRI_SE |
|
|
|
|
DISABLE_STEALTH | 0x00100000 | LOCK_HUD | LOCK_HOTBAR |
|
|
|
|
// todo: wtf is 0x00100000
|
2019-07-16 20:10:51 +10:00
|
|
|
DISABLE_CANCEL_EMOTE, 0, 0x9, 0 );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
player.directorPlayScene( getDirectorId(), 2, NO_DEFAULT_CAMERA | HIDE_HOTBAR, 0, 0x9, getCurrentBGM() );
|
2018-03-05 22:10:14 +11:00
|
|
|
}
|
2018-03-15 20:48:35 +11:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::setCurrentBGM( uint16_t bgmIndex )
|
2018-03-15 20:48:35 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_currentBgm = bgmIndex;
|
|
|
|
|
|
|
|
for( const auto& playerIt : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = playerIt.second;
|
|
|
|
// note: retail do send a BGM_MUTE(1) first before any BGM transition, but YOLO in this case.
|
|
|
|
// also do note that this code can't control the bgm granularly. (i.e. per player for WoD submap.) oops.
|
|
|
|
// player->queuePacket( ActorControlPacket143( player->getId(), DirectorUpdate, getDirectorId(), 0x80000001, 1 ) );
|
|
|
|
player->queuePacket(
|
|
|
|
makeActorControl143( player->getId(), DirectorUpdate, getDirectorId(), 0x80000001, bgmIndex ) );
|
|
|
|
}
|
2018-03-15 20:48:35 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::setPlayerBGM( Sapphire::Entity::Player& player, uint16_t bgmId )
|
2018-03-16 16:56:43 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
player.queuePacket( makeActorControl143( player.getId(), DirectorUpdate, getDirectorId(), 0x80000001, bgmId ) );
|
2018-03-16 16:56:43 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint16_t Sapphire::InstanceContent::getCurrentBGM() const
|
2018-03-15 20:48:35 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_currentBgm;
|
2018-03-15 12:24:34 +01:00
|
|
|
}
|
2018-03-15 23:37:21 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::InstanceContent::bindPlayer( uint32_t playerId )
|
2018-03-15 23:37:21 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// if player already bound, return false
|
|
|
|
if( m_boundPlayerIds.count( playerId ) )
|
|
|
|
return false;
|
2018-03-15 23:37:21 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// TODO: do not allow binding of players if instance already has all it can take
|
|
|
|
// if( m_boundPlayerIds.size() >= party restrictions )
|
|
|
|
// return false;
|
2018-03-15 23:37:21 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
m_boundPlayerIds.insert( playerId );
|
|
|
|
return true;
|
2018-03-15 23:37:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::InstanceContent::isPlayerBound( uint32_t playerId ) const
|
2018-03-15 23:37:21 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_boundPlayerIds.count( playerId ) > 0;
|
2018-03-15 23:37:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::InstanceContent::unbindPlayer( uint32_t playerId )
|
2018-03-15 23:37:21 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_boundPlayerIds.erase( playerId );
|
2018-03-16 16:56:43 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto it = m_playerMap.find( playerId );
|
|
|
|
if( it != m_playerMap.end() )
|
|
|
|
it->second->exitInstance();
|
2018-03-15 23:37:21 +01:00
|
|
|
}
|
2019-01-13 17:32:43 +01:00
|
|
|
|
|
|
|
void Sapphire::InstanceContent::clearDirector( Entity::Player& player )
|
|
|
|
{
|
|
|
|
sendDirectorClear( player );
|
|
|
|
|
|
|
|
player.setDirectorInitialized( false );
|
|
|
|
// remove "bound by duty" state
|
|
|
|
player.unsetStateFlag( PlayerStateFlag::BoundByDuty );}
|