2017-08-08 13:53:47 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <vector>
|
2018-03-02 07:22:25 -03:00
|
|
|
#include <time.h>
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Logging/Logger.h>
|
|
|
|
#include <Util/Util.h>
|
|
|
|
#include <Util/UtilMath.h>
|
|
|
|
#include <Network/GamePacketNew.h>
|
|
|
|
#include <Exd/ExdDataGenerated.h>
|
|
|
|
#include <Network/CommonNetwork.h>
|
|
|
|
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
|
|
|
#include <Network/PacketContainer.h>
|
2018-06-23 21:38:04 +02:00
|
|
|
#include <Network/CommonActorControl.h>
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Database/DatabaseDef.h>
|
2018-03-20 20:30:05 +11:00
|
|
|
#include <Network/PacketWrappers/ActorControlPacket143.h>
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "Zone.h"
|
2018-02-23 23:47:21 +01:00
|
|
|
#include "InstanceContent.h"
|
2018-12-01 00:27:16 +11:00
|
|
|
#include "Manager/TerritoryMgr.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Session.h"
|
2018-02-20 22:46:44 +01:00
|
|
|
#include "Actor/Chara.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Actor/Actor.h"
|
2018-09-09 23:56:22 +02:00
|
|
|
#include "Actor/BNpc.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Actor/Player.h"
|
2018-02-28 10:26:03 +01:00
|
|
|
#include "Actor/EventObject.h"
|
2018-12-31 13:54:31 +01:00
|
|
|
#include "Actor/SpawnGroup.h"
|
|
|
|
#include "Actor/SpawnPoint.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/GameConnection.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Script/ScriptMgr.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Session.h"
|
2018-09-09 23:56:22 +02:00
|
|
|
#include "ForwardsZone.h"
|
2018-11-20 21:32:13 +01:00
|
|
|
#include "ServerMgr.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "CellHandler.h"
|
|
|
|
#include "Zone.h"
|
|
|
|
#include "Framework.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
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-12-01 00:27:16 +11:00
|
|
|
using namespace Sapphire::World::Manager;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief
|
|
|
|
*/
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Zone::Zone() :
|
2018-11-05 23:07:39 +01:00
|
|
|
m_territoryTypeId( 0 ),
|
2018-08-29 21:40:59 +02:00
|
|
|
m_guId( 0 ),
|
|
|
|
m_currentWeather( Weather::FairSkies ),
|
|
|
|
m_weatherOverride( Weather::None ),
|
|
|
|
m_lastMobUpdate( 0 ),
|
|
|
|
m_nextEObjId( 0x400D0000 )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-12-02 02:01:41 +01:00
|
|
|
Sapphire::Zone::Zone( uint16_t territoryTypeId, uint32_t guId,
|
2018-12-29 00:53:52 +01:00
|
|
|
const std::string& internalName, const std::string& placeName,
|
|
|
|
FrameworkPtr pFw ) :
|
2018-08-29 21:40:59 +02:00
|
|
|
m_currentWeather( Weather::FairSkies ),
|
2018-12-29 00:53:52 +01:00
|
|
|
m_nextEObjId( 0x400D0000 ),
|
|
|
|
m_pFw( pFw )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
|
2018-08-29 21:40:59 +02:00
|
|
|
m_guId = guId;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-11-05 23:07:39 +01:00
|
|
|
m_territoryTypeId = territoryTypeId;
|
2018-08-29 21:40:59 +02:00
|
|
|
m_internalName = internalName;
|
|
|
|
m_placeName = placeName;
|
|
|
|
m_lastMobUpdate = 0;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
m_weatherOverride = Weather::None;
|
2018-11-29 16:55:48 +01:00
|
|
|
m_territoryTypeInfo = pExdData->get< Sapphire::Data::TerritoryType >( territoryTypeId );
|
2018-02-01 23:32:59 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
loadWeatherRates();
|
2019-01-02 23:40:34 +01:00
|
|
|
loadSpawnGroups();
|
2018-02-14 21:11:23 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
m_currentWeather = getNextWeather();
|
2018-02-14 21:11:23 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::loadWeatherRates()
|
2018-02-14 21:11:23 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !m_territoryTypeInfo )
|
|
|
|
return;
|
2018-02-14 21:11:23 +01:00
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
|
2018-03-06 00:10:36 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint8_t weatherRateId = m_territoryTypeInfo->weatherRate > pExdData->getWeatherRateIdList().size() ?
|
|
|
|
uint8_t{ 0 } : m_territoryTypeInfo->weatherRate;
|
2018-02-01 23:32:59 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint8_t sumPc = 0;
|
|
|
|
auto weatherRateFields = pExdData->m_WeatherRateDat.get_row( weatherRateId );
|
|
|
|
for( size_t i = 0; i < 16; )
|
|
|
|
{
|
2018-10-25 13:38:06 +11:00
|
|
|
int32_t weatherId = std::get< int32_t >( weatherRateFields[ i ] );
|
2018-02-01 23:32:59 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( weatherId == 0 )
|
|
|
|
break;
|
2018-02-01 23:32:59 +01:00
|
|
|
|
2018-10-25 13:38:06 +11:00
|
|
|
sumPc += std::get< uint8_t >( weatherRateFields[ i + 1 ] );
|
2018-08-29 21:40:59 +02:00
|
|
|
m_weatherRateMap[ sumPc ] = weatherId;
|
|
|
|
i += 2;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Zone::~Zone()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Zone::init()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pScriptMgr->onZoneInit( shared_from_this() ) )
|
|
|
|
{
|
|
|
|
// all good
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return true;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::setWeatherOverride( Weather weather )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_weatherOverride = weather;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Weather Sapphire::Zone::getCurrentWeather() const
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_currentWeather;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
const Sapphire::FestivalPair& Sapphire::Zone::getCurrentFestival() const
|
2018-02-03 02:11:29 +11:00
|
|
|
{
|
2018-09-01 20:55:28 +10:00
|
|
|
return m_currentFestival;
|
2018-02-03 02:11:29 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::setCurrentFestival( uint16_t festivalId, uint16_t additionalFestivalId )
|
2018-02-03 02:11:29 +11:00
|
|
|
{
|
2018-09-01 20:55:28 +10:00
|
|
|
m_currentFestival = { festivalId, additionalFestivalId };
|
2018-02-03 02:11:29 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( const auto& playerEntry : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = playerEntry.second;
|
2018-03-20 20:30:05 +11:00
|
|
|
|
2018-09-01 20:55:28 +10:00
|
|
|
auto enableFestival = makeActorControl143( player->getId(), SetFestival, festivalId, additionalFestivalId );
|
2018-08-29 21:40:59 +02:00
|
|
|
playerEntry.second->queuePacket( enableFestival );
|
|
|
|
}
|
2018-03-20 20:30:05 +11:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::loadCellCache()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Weather Sapphire::Zone::getNextWeather()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t unixTime = static_cast< uint32_t >( Util::getTimeSeconds() );
|
|
|
|
// Get Eorzea hour for weather start
|
|
|
|
uint32_t bell = unixTime / 175;
|
|
|
|
// Do the magic 'cause for calculations 16:00 is 0, 00:00 is 8 and 08:00 is 16
|
|
|
|
int32_t increment = ( ( bell + 8 - ( bell % 8 ) ) ) % 24;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// Take Eorzea days since unix epoch
|
|
|
|
uint32_t totalDays = ( unixTime / 4200 );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t calcBase = ( totalDays * 0x64 ) + increment;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t step1 = ( calcBase << 0xB ) ^calcBase;
|
|
|
|
uint32_t step2 = ( step1 >> 8 ) ^step1;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto rate = static_cast< uint8_t >( step2 % 0x64 );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( auto entry : m_weatherRateMap )
|
|
|
|
{
|
|
|
|
uint8_t sRate = entry.first;
|
|
|
|
auto weatherId = static_cast< Weather >( entry.second );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( rate <= sRate )
|
|
|
|
return weatherId;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return Weather::FairSkies;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::pushActor( Entity::ActorPtr pActor )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
float mx = pActor->getPos().x;
|
|
|
|
float my = pActor->getPos().z;
|
|
|
|
uint32_t cx = getPosX( mx );
|
|
|
|
uint32_t cy = getPosY( my );
|
|
|
|
|
|
|
|
Cell* pCell = getCellPtr( cx, cy );
|
|
|
|
if( !pCell )
|
|
|
|
{
|
|
|
|
pCell = create( cx, cy );
|
|
|
|
pCell->init( cx, cy, shared_from_this() );
|
|
|
|
}
|
|
|
|
|
|
|
|
pCell->addActor( pActor );
|
|
|
|
|
|
|
|
pActor->setCell( pCell );
|
|
|
|
|
|
|
|
uint32_t cellX = getPosX( pActor->getPos().x );
|
|
|
|
uint32_t cellY = getPosY( pActor->getPos().z );
|
|
|
|
|
|
|
|
uint32_t endX = cellX <= _sizeX ? cellX + 1 : ( _sizeX - 1 );
|
|
|
|
uint32_t endY = cellY <= _sizeY ? cellY + 1 : ( _sizeY - 1 );
|
|
|
|
uint32_t startX = cellX > 0 ? cellX - 1 : 0;
|
|
|
|
uint32_t startY = cellY > 0 ? cellY - 1 : 0;
|
|
|
|
uint32_t posX, posY;
|
|
|
|
|
|
|
|
for( posX = startX; posX <= endX; ++posX )
|
|
|
|
{
|
|
|
|
for( posY = startY; posY <= endY; ++posY )
|
|
|
|
{
|
|
|
|
pCell = getCellPtr( posX, posY );
|
|
|
|
if( pCell )
|
|
|
|
updateInRangeSet( pActor, pCell );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pActor->isPlayer() )
|
|
|
|
{
|
|
|
|
auto pPlayer = pActor->getAsPlayer();
|
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pServerZone = m_pFw->get< World::ServerMgr >();
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pSession = pServerZone->getSession( pPlayer->getId() );
|
|
|
|
if( pSession )
|
|
|
|
m_sessionSet.insert( pSession );
|
|
|
|
m_playerMap[ pPlayer->getId() ] = pPlayer;
|
|
|
|
updateCellActivity( cx, cy, 2 );
|
|
|
|
}
|
2018-09-09 23:56:22 +02:00
|
|
|
else if( pActor->isBattleNpc() )
|
|
|
|
{
|
|
|
|
auto pBNpc = pActor->getAsBNpc();
|
|
|
|
|
|
|
|
m_bNpcMap[ pBNpc->getId() ] = pBNpc;
|
|
|
|
updateCellActivity( cx, cy, 2 );
|
|
|
|
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::removeActor( Entity::ActorPtr pActor )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
float mx = pActor->getPos().x;
|
|
|
|
float my = pActor->getPos().z;
|
|
|
|
uint32_t cx = getPosX( mx );
|
|
|
|
uint32_t cy = getPosY( my );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
Cell* pCell = getCellPtr( cx, cy );
|
|
|
|
if( pCell && pCell->hasActor( pActor ) )
|
|
|
|
pCell->removeActor( pActor );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pActor->isPlayer() )
|
|
|
|
{
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// If it's a player and he's inside boundaries - update his nearby cells
|
|
|
|
if( pActor->getPos().x <= _maxX && pActor->getPos().x >= _minX &&
|
|
|
|
pActor->getPos().z <= _maxY && pActor->getPos().z >= _minY )
|
|
|
|
{
|
|
|
|
uint32_t x = getPosX( pActor->getPos().x );
|
|
|
|
uint32_t y = getPosY( pActor->getPos().z );
|
|
|
|
updateCellActivity( x, y, 3 );
|
|
|
|
}
|
|
|
|
m_playerMap.erase( pActor->getId() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
onLeaveTerritory( *pActor->getAsPlayer() );
|
2018-02-04 23:35:16 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2018-09-09 23:56:22 +02:00
|
|
|
else if( pActor->isBattleNpc() )
|
|
|
|
{
|
|
|
|
m_bNpcMap.erase( pActor->getId() );
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// remove from lists of other actors
|
|
|
|
pActor->removeFromInRange();
|
|
|
|
pActor->clearInRangeSet();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::queuePacketForRange( Entity::Player& sourcePlayer, uint32_t range,
|
2018-12-02 02:01:41 +01:00
|
|
|
Network::Packets::FFXIVPacketBasePtr pPacketEntry )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pTeriMgr = m_pFw->get< TerritoryMgr >();
|
2018-11-05 23:07:39 +01:00
|
|
|
if( pTeriMgr->isPrivateTerritory( getTerritoryTypeId() ) )
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pServerZone = m_pFw->get< World::ServerMgr >();
|
2018-08-29 21:40:59 +02:00
|
|
|
for( auto entry : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = entry.second;
|
2018-12-02 02:01:41 +01:00
|
|
|
float distance = Util::distance( sourcePlayer.getPos().x, sourcePlayer.getPos().y, sourcePlayer.getPos().z,
|
|
|
|
player->getPos().x, player->getPos().y, player->getPos().z );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
|
|
|
if( ( distance < range ) && sourcePlayer.getId() != player->getId() )
|
|
|
|
{
|
|
|
|
|
|
|
|
auto pSession = pServerZone->getSession( player->getId() );
|
|
|
|
//pPacketEntry->setValAt< uint32_t >( 0x08, player->getId() );
|
|
|
|
if( pSession )
|
|
|
|
pSession->getZoneConnection()->queueOutPacket( pPacketEntry );
|
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::queuePacketForZone( Entity::Player& sourcePlayer,
|
2018-12-02 02:01:41 +01:00
|
|
|
Network::Packets::FFXIVPacketBasePtr pPacketEntry,
|
|
|
|
bool forSelf )
|
2018-11-15 22:30:59 +01:00
|
|
|
{
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pTeriMgr = m_pFw->get< TerritoryMgr >();
|
2018-11-15 22:30:59 +01:00
|
|
|
if( pTeriMgr->isPrivateTerritory( getTerritoryTypeId() ) )
|
|
|
|
return;
|
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pServerZone = m_pFw->get< World::ServerMgr >();
|
2018-11-15 22:30:59 +01:00
|
|
|
for( auto entry : m_playerMap )
|
|
|
|
{
|
|
|
|
auto player = entry.second;
|
|
|
|
if( ( sourcePlayer.getId() != player->getId() ) ||
|
|
|
|
( ( sourcePlayer.getId() == player->getId() ) && forSelf ) )
|
|
|
|
{
|
|
|
|
auto pSession = pServerZone->getSession( player->getId() );
|
|
|
|
if( pSession )
|
|
|
|
pSession->getZoneConnection()->queueOutPacket( pPacketEntry );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint32_t Sapphire::Zone::getTerritoryTypeId() const
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-11-05 23:07:39 +01:00
|
|
|
return m_territoryTypeId;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint32_t Sapphire::Zone::getGuId() const
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_guId;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
const std::string& Sapphire::Zone::getName() const
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_placeName;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
const std::string& Sapphire::Zone::getInternalName() const
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_internalName;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
std::size_t Sapphire::Zone::getPopCount() const
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_playerMap.size();
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Zone::checkWeather()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( m_weatherOverride != Weather::None )
|
|
|
|
{
|
|
|
|
if( m_weatherOverride != m_currentWeather )
|
|
|
|
{
|
|
|
|
m_currentWeather = m_weatherOverride;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto nextWeather = getNextWeather();
|
|
|
|
if( nextWeather != m_currentWeather )
|
|
|
|
{
|
|
|
|
m_currentWeather = nextWeather;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-02-21 12:48:27 +01:00
|
|
|
/*
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::updateBnpcs( int64_t tickCount )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
if( ( tickCount - m_lastMobUpdate ) > 250 )
|
|
|
|
{
|
|
|
|
|
|
|
|
m_lastMobUpdate = tickCount;
|
|
|
|
uint32_t currTime = static_cast< uint32_t >( time( nullptr ) );
|
|
|
|
|
|
|
|
for( auto it3 = m_BattleNpcDeadMap.begin(); it3 != m_BattleNpcDeadMap.end(); ++it3 )
|
|
|
|
{
|
|
|
|
|
|
|
|
Entity::BattleNpcPtr pBNpc = *it3;
|
|
|
|
|
|
|
|
if( ( currTime - pBNpc->getTimeOfDeath() ) > 60 )
|
|
|
|
{
|
|
|
|
|
|
|
|
pBNpc->resetHp();
|
|
|
|
pBNpc->resetMp();
|
|
|
|
pBNpc->resetPos();
|
|
|
|
pushActor( pBNpc );
|
|
|
|
|
|
|
|
m_BattleNpcDeadMap.erase( it3 );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for( auto entry : m_BattleNpcMap )
|
|
|
|
{
|
|
|
|
Entity::BattleNpcPtr pBNpc = entry.second;
|
2018-01-29 18:10:11 +11:00
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
if( !pBNpc )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( !pBNpc->isAlive() && currTime - pBNpc->getTimeOfDeath() > ( 10 ) )
|
|
|
|
{
|
|
|
|
removeActor( pBNpc );
|
|
|
|
m_BattleNpcDeadMap.insert( pBNpc );
|
|
|
|
break;
|
|
|
|
}
|
2018-01-29 18:10:11 +11:00
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
pBNpc->update( tickCount );
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-21 12:48:27 +01:00
|
|
|
*/
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Zone::update( uint32_t currTime )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
int64_t tickCount = Util::getTimeMs();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
//TODO: this should be moved to a updateWeather call and pulled out of updateSessions
|
|
|
|
bool changedWeather = checkWeather();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
updateSessions( changedWeather );
|
|
|
|
//updateBnpcs( tickCount );
|
|
|
|
onUpdate( currTime );
|
2018-02-14 20:44:35 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return true;
|
2018-02-14 20:44:35 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::updateSessions( bool changedWeather )
|
2018-02-14 20:44:35 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto it = m_sessionSet.begin();
|
2018-01-29 18:10:11 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// update sessions in this zone
|
|
|
|
for( ; it != m_sessionSet.end(); )
|
|
|
|
{
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pSession = ( *it );
|
2018-01-29 18:10:11 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pSession )
|
|
|
|
{
|
|
|
|
it = m_sessionSet.erase( it );
|
|
|
|
continue;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pPlayer = pSession->getPlayer();
|
2018-02-21 18:06:52 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// this session is not linked to this area anymore, remove it from zone session list
|
|
|
|
if( ( !pPlayer->getCurrentZone() ) || ( pPlayer->getCurrentZone() != shared_from_this() ) )
|
|
|
|
{
|
|
|
|
removeActor( pSession->getPlayer() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
it = m_sessionSet.erase( it );
|
|
|
|
continue;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( changedWeather )
|
|
|
|
{
|
|
|
|
auto weatherChangePacket = makeZonePacket< FFXIVIpcWeatherChange >( pPlayer->getId() );
|
|
|
|
weatherChangePacket->data().weatherId = static_cast< uint8_t >( m_currentWeather );
|
|
|
|
weatherChangePacket->data().delay = 5.0f;
|
|
|
|
pSession->getPlayer()->queuePacket( weatherChangePacket );
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// perform session duties
|
|
|
|
pSession->update();
|
|
|
|
++it;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Zone::isCellActive( uint32_t x, uint32_t y )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t endX = ( ( x + 1 ) <= _sizeX ) ? x + 1 : ( _sizeX - 1 );
|
|
|
|
uint32_t endY = ( ( y + 1 ) <= _sizeY ) ? y + 1 : ( _sizeY - 1 );
|
|
|
|
uint32_t startX = x > 0 ? x - 1 : 0;
|
|
|
|
uint32_t startY = y > 0 ? y - 1 : 0;
|
|
|
|
uint32_t posX;
|
|
|
|
uint32_t posY;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
Cell* pCell;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( posX = startX; posX <= endX; posX++ )
|
|
|
|
{
|
|
|
|
for( posY = startY; posY <= endY; posY++ )
|
|
|
|
{
|
|
|
|
pCell = getCellPtr( posX, posY );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pCell && ( pCell->hasPlayers() || pCell->isForcedActive() ) )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return false;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::updateCellActivity( uint32_t x, uint32_t y, int32_t radius )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t endX = ( x + radius ) <= _sizeX ? x + radius : ( _sizeX - 1 );
|
|
|
|
uint32_t endY = ( y + radius ) <= _sizeY ? y + radius : ( _sizeY - 1 );
|
|
|
|
uint32_t startX = x - radius > 0 ? x - radius : 0;
|
|
|
|
uint32_t startY = y - radius > 0 ? y - radius : 0;
|
|
|
|
uint32_t posX, posY;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
Cell* pCell;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( posX = startX; posX <= endX; posX++ )
|
|
|
|
{
|
|
|
|
for( posY = startY; posY <= endY; posY++ )
|
|
|
|
{
|
|
|
|
pCell = getCellPtr( posX, posY );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pCell )
|
|
|
|
{
|
|
|
|
if( isCellActive( posX, posY ) )
|
|
|
|
{
|
|
|
|
pCell = create( posX, posY );
|
|
|
|
pCell->init( posX, posY, shared_from_this() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
pCell->setActivity( true );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
assert( !pCell->isLoaded() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
//Cell is now active
|
|
|
|
if( isCellActive( posX, posY ) && !pCell->isActive() )
|
|
|
|
{
|
|
|
|
pCell->setActivity( true );
|
|
|
|
|
|
|
|
if( !pCell->isLoaded() )
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( !isCellActive( posX, posY ) && pCell->isActive() )
|
|
|
|
pCell->setActivity( false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::updateActorPosition( Entity::Actor& actor )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( actor.getCurrentZone() != shared_from_this() )
|
|
|
|
return;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
//actor.checkInRangeActors();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t cellX = getPosX( actor.getPos().x );
|
|
|
|
uint32_t cellY = getPosY( actor.getPos().z );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( cellX >= _sizeX || cellY >= _sizeY )
|
|
|
|
return;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pCell = getCellPtr( cellX, cellY );
|
2018-02-22 18:12:36 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pOldCell = actor.getCellPtr();
|
|
|
|
if( !pCell )
|
|
|
|
{
|
|
|
|
pCell = create( cellX, cellY );
|
|
|
|
pCell->init( cellX, cellY, shared_from_this() );
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// If object moved cell
|
|
|
|
if( pCell != pOldCell )
|
|
|
|
{
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pOldCell )
|
|
|
|
{
|
|
|
|
pOldCell->removeActor( actor.shared_from_this() );
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
pCell->addActor( actor.shared_from_this() );
|
|
|
|
actor.setCell( pCell );
|
|
|
|
pOldCell = pCell;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// if player we need to update cell activity
|
|
|
|
// radius = 2 is used in order to update both
|
|
|
|
// old and new cells
|
|
|
|
if( actor.isPlayer() )
|
|
|
|
{
|
|
|
|
updateCellActivity( cellX, cellY, 2 );
|
|
|
|
if( pOldCell != nullptr )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// only do the second check if theres -/+ 2 difference
|
|
|
|
if( abs( ( int32_t ) cellX - ( int32_t ) pOldCell->m_posX ) > 2 ||
|
|
|
|
abs( ( int32_t ) cellY - ( int32_t ) pOldCell->m_posY ) > 2 )
|
|
|
|
updateCellActivity( pOldCell->m_posX, pOldCell->m_posY, 2 );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// update in range actor set
|
|
|
|
uint32_t endX = cellX <= _sizeX ? cellX + 1 : ( _sizeX - 1 );
|
|
|
|
uint32_t endY = cellY <= _sizeY ? cellY + 1 : ( _sizeY - 1 );
|
|
|
|
uint32_t startX = cellX > 0 ? cellX - 1 : 0;
|
|
|
|
uint32_t startY = cellY > 0 ? cellY - 1 : 0;
|
|
|
|
uint32_t posX, posY;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
for( posX = startX; posX <= endX; ++posX )
|
|
|
|
{
|
|
|
|
for( posY = startY; posY <= endY; ++posY )
|
|
|
|
{
|
|
|
|
pCell = getCellPtr( posX, posY );
|
|
|
|
if( pCell )
|
|
|
|
updateInRangeSet( actor.shared_from_this(), pCell );
|
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pCell == nullptr )
|
|
|
|
return;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-12-29 00:53:52 +01:00
|
|
|
auto pTeriMgr = m_pFw->get< TerritoryMgr >();
|
2018-08-29 21:40:59 +02:00
|
|
|
// TODO: make sure gms can overwrite this. Potentially temporary solution
|
2018-11-05 23:07:39 +01:00
|
|
|
if( pTeriMgr->isPrivateTerritory( getTerritoryTypeId() ) )
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
2018-02-08 15:25:59 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto iter = pCell->m_actors.begin();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
float fRange = 70.0f;
|
|
|
|
int32_t count = 0;
|
|
|
|
while( iter != pCell->m_actors.end() )
|
|
|
|
{
|
|
|
|
auto pCurAct = *iter;
|
|
|
|
++iter;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pCurAct || pCurAct == pActor )
|
|
|
|
continue;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-12-02 02:01:41 +01:00
|
|
|
float distance = Util::distance( pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z,
|
|
|
|
pActor->getPos().x, pActor->getPos().y, pActor->getPos().z );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
bool isInRange = ( fRange == 0.0f || distance <= fRange );
|
|
|
|
bool isInRangeSet = pActor->isInRangeSet( pCurAct );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// Add if range == 0 or distance is withing range.
|
|
|
|
if( isInRange && !isInRangeSet )
|
|
|
|
{
|
2018-02-21 18:06:52 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pActor->isPlayer() && !pActor->getAsPlayer()->isLoadingComplete() )
|
|
|
|
continue;
|
2018-02-21 18:06:52 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( pCurAct->isPlayer() && !pCurAct->getAsPlayer()->isLoadingComplete() )
|
|
|
|
continue;
|
2018-02-21 18:06:52 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
pActor->addInRangeActor( pCurAct );
|
|
|
|
pCurAct->addInRangeActor( pActor );
|
2018-02-21 18:06:52 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// this is a hack to limit actor spawn in one packetset
|
2018-09-09 23:56:22 +02:00
|
|
|
if( count++ > 10 )
|
2018-08-29 21:40:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( !isInRange && isInRangeSet )
|
|
|
|
{
|
|
|
|
pCurAct->removeInRangeActor( *pActor );
|
|
|
|
pActor->removeInRangeActor( *pCurAct );
|
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::onPlayerZoneIn( Entity::Player& player )
|
2018-02-04 23:35:16 +01:00
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::debug(
|
2018-11-05 23:07:39 +01:00
|
|
|
"Zone::onEnterTerritory: Zone#" + std::to_string( getGuId() ) + "|" + std::to_string( getTerritoryTypeId() ) +
|
2018-12-31 13:54:31 +01:00
|
|
|
+ ", Entity#" + std::to_string( player.getId() ) );
|
2018-02-04 23:35:16 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::onLeaveTerritory( Entity::Player& player )
|
2018-02-04 23:35:16 +01:00
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::debug(
|
2018-11-05 23:07:39 +01:00
|
|
|
"Zone::onLeaveTerritory: Zone#" + std::to_string( getGuId() ) + "|" + std::to_string( getTerritoryTypeId() ) +
|
2018-12-31 13:54:31 +01:00
|
|
|
+ ", Entity#" + std::to_string( player.getId() ) );
|
2018-02-04 23:35:16 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::onUpdate( uint32_t currTime )
|
2018-02-04 23:35:16 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::onFinishLoading( Entity::Player& player )
|
2018-02-06 00:01:23 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::onInitDirector( Entity::Player& player )
|
2018-02-06 00:01:23 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::onEnterTerritory( Sapphire::Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 )
|
2018-03-05 22:10:14 +11:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Zone::registerEObj( Entity::EventObjectPtr object )
|
2018-02-10 21:53:16 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !object )
|
|
|
|
return;
|
2018-12-23 03:53:08 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
pushActor( object );
|
2018-02-10 21:53:16 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
m_eventObjects[ object->getId() ] = object;
|
2018-02-10 21:53:16 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
onRegisterEObj( object );
|
2018-02-23 23:47:21 +01:00
|
|
|
|
2018-12-23 03:53:08 +01:00
|
|
|
//Logger::debug( "Registered instance eobj: " + std::to_string( object->getId() ) );
|
2018-02-10 21:53:16 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Entity::EventObjectPtr Sapphire::Zone::getEObj( uint32_t objId )
|
2018-02-10 21:53:16 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto obj = m_eventObjects.find( objId );
|
|
|
|
if( obj == m_eventObjects.end() )
|
|
|
|
return nullptr;
|
2018-02-10 21:53:16 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return obj->second;
|
2018-02-10 21:53:16 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::InstanceContentPtr Sapphire::Zone::getAsInstanceContent()
|
2018-02-23 23:47:21 +01:00
|
|
|
{
|
2018-10-25 12:44:51 +11:00
|
|
|
return std::dynamic_pointer_cast< InstanceContent, Zone >( shared_from_this() );
|
2018-02-23 23:47:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint32_t Sapphire::Zone::getNextEObjId()
|
2018-02-23 23:47:21 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return ++m_nextEObjId;
|
2018-02-23 23:47:21 +01:00
|
|
|
}
|
2018-02-25 01:23:40 +01:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Entity::EventObjectPtr Sapphire::Zone::registerEObj( const std::string& name, uint32_t objectId, uint32_t mapLink,
|
2018-12-02 02:01:41 +01:00
|
|
|
uint8_t state, FFXIVARR_POSITION3 pos, float scale,
|
|
|
|
float rotation )
|
2018-02-25 01:23:40 +01:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto eObj = Entity::make_EventObject( getNextEObjId(), objectId, mapLink, state, pos, rotation, name );
|
|
|
|
eObj->setScale( scale );
|
|
|
|
registerEObj( eObj );
|
2018-02-27 02:13:01 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return eObj;
|
2018-02-25 01:23:40 +01:00
|
|
|
}
|
2018-12-02 21:08:38 +11:00
|
|
|
|
|
|
|
Sapphire::Data::TerritoryTypePtr Sapphire::Zone::getTerritoryTypeInfo() const
|
|
|
|
{
|
|
|
|
return m_territoryTypeInfo;
|
2018-12-31 13:54:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Sapphire::Zone::loadSpawnGroups()
|
|
|
|
{
|
|
|
|
auto pDb = m_pFw->get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
2019-01-04 08:32:47 +01:00
|
|
|
auto res = pDb->query( "SELECT id, bNpcTemplateId, level, maxHp "
|
|
|
|
"FROM spawngroup "
|
2018-12-31 13:54:31 +01:00
|
|
|
"WHERE territoryTypeId = " + std::to_string( getTerritoryTypeId() ) + ";" );
|
|
|
|
|
|
|
|
while( res->next() )
|
|
|
|
{
|
|
|
|
uint32_t id = res->getUInt( 1 );
|
|
|
|
uint32_t templateId = res->getUInt( 2 );
|
|
|
|
uint32_t level = res->getUInt( 3 );
|
|
|
|
uint32_t maxHp = res->getUInt( 4 );
|
|
|
|
|
|
|
|
//Entity::SpawnGroup group;
|
|
|
|
|
|
|
|
Logger::debug( std::to_string( id ) + " " +
|
|
|
|
std::to_string( templateId ) + " " +
|
|
|
|
std::to_string( level ) + " " +
|
|
|
|
std::to_string( maxHp ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|