1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-21 12:17:46 +00:00

Merge pull request #965 from hkAlice/i-need-speed

[3.x] cache eobj/enpc exd; fix server crash on aoe skills; !add unlockall (0xff unlock bitmask);
This commit is contained in:
hkAlice 2024-08-09 20:07:37 -03:00 committed by GitHub
commit 4a46b3dd80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 77 additions and 35 deletions

View file

@ -171,6 +171,7 @@ std::shared_ptr< FFXIVPacketBase > ActionResultBuilder::createActionResultPacket
break; break;
} }
m_actorResultsMap.clear();
return actionResult; return actionResult;
} }
else // use Effect for single target else // use Effect for single target

View file

@ -563,6 +563,11 @@ void Player::setRewardFlag( Common::UnlockEntry unlockId )
Network::Util::Packet::sendActorControlSelf( *this, getId(), SetRewardFlag, unlock, 1 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), SetRewardFlag, unlock, 1 );
} }
void Player::fillRewardFlags()
{
memset( m_unlocks.data(), 0xFF, m_unlocks.size() );
}
void Player::setBorrowAction( uint8_t slot, uint32_t action ) void Player::setBorrowAction( uint8_t slot, uint32_t action )
{ {
if( slot > Common::ARRSIZE_BORROWACTION ) if( slot > Common::ARRSIZE_BORROWACTION )
@ -1815,6 +1820,9 @@ void Player::setFalling( bool state, const Common::FFXIVARR_POSITION3& pos, bool
takeDamage( damage ); takeDamage( damage );
} }
Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), SetFallDamage, damage ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), SetFallDamage, damage );
// todo: this used to work without refreshing the entire UI state
// does 3.x use some sort of fall integrity?
Network::Util::Packet::sendHudParam( *this );
} }
} }
} }

View file

@ -441,6 +441,9 @@ namespace Sapphire::Entity
/*! learn an action / update the unlock bitmask. */ /*! learn an action / update the unlock bitmask. */
void setRewardFlag( Common::UnlockEntry unlockId ); void setRewardFlag( Common::UnlockEntry unlockId );
/*! helper/debug function to fill unlock bitmask */
void fillRewardFlags();
void setBorrowAction( uint8_t slot, uint32_t action ); void setBorrowAction( uint8_t slot, uint32_t action );
BorrowAction& getBorrowAction(); BorrowAction& getBorrowAction();

View file

@ -11,6 +11,7 @@
#include <Database/DatabaseDef.h> #include <Database/DatabaseDef.h>
#include <cmath> #include <cmath>
#include <Network/PacketWrappers/EffectPacket.h> #include <Network/PacketWrappers/EffectPacket.h>
#include <Network/Util/PacketUtil.h>
#include <Service.h> #include <Service.h>
#include "DebugCommand/DebugCommand.h" #include "DebugCommand/DebugCommand.h"
@ -159,6 +160,7 @@ void DebugCommandMgr::help( char* data, Entity::Player& player, std::shared_ptr<
void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command ) void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command )
{ {
auto& server = Sapphire::Common::Service< Sapphire::World::WorldServer >::ref(); auto& server = Sapphire::Common::Service< Sapphire::World::WorldServer >::ref();
auto& playerMgr = Common::Service< PlayerMgr >::ref();
auto& terriMgr = Common::Service< TerritoryMgr >::ref(); auto& terriMgr = Common::Service< TerritoryMgr >::ref();
auto pCurrentZone = terriMgr.getTerritoryByGuId( player.getTerritoryId() ); auto pCurrentZone = terriMgr.getTerritoryByGuId( player.getTerritoryId() );
@ -233,7 +235,8 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr<
else if( subCommand == "discovery_reset" ) else if( subCommand == "discovery_reset" )
{ {
player.resetDiscovery(); player.resetDiscovery();
server.queueForPlayer( player.getCharacterId(), std::make_shared< PlayerSetupPacket >( player ) ); player.setIsLogin( true );
playerMgr.onMoveZone( player );
} }
else if( subCommand == "classjob" ) else if( subCommand == "classjob" )
{ {
@ -385,6 +388,7 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr<
void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command ) void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command )
{ {
auto& terriMgr = Common::Service< TerritoryMgr >::ref(); auto& terriMgr = Common::Service< TerritoryMgr >::ref();
auto& playerMgr = Common::Service< PlayerMgr >::ref();
auto pCurrentZone = terriMgr.getTerritoryByGuId( player.getTerritoryId() ); auto pCurrentZone = terriMgr.getTerritoryByGuId( player.getTerritoryId() );
std::string subCommand; std::string subCommand;
@ -525,6 +529,13 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr<
sscanf( params.c_str(), "%d", &id ); sscanf( params.c_str(), "%d", &id );
player.setRewardFlag( static_cast< Common::UnlockEntry >( id ) ); player.setRewardFlag( static_cast< Common::UnlockEntry >( id ) );
} }
else if( subCommand == "unlockall" )
{
player.fillRewardFlags();
player.setIsLogin( true );
playerMgr.onMoveZone( player );
}
else if( subCommand == "effect" ) else if( subCommand == "effect" )
{ {
uint16_t param1; uint16_t param1;

View file

@ -35,11 +35,24 @@ using namespace Sapphire::World::Manager;
bool MapMgr::loadQuests() bool MapMgr::loadQuests()
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto questList = exdData.getRows< Excel::Quest >(); auto questList = exdData.getRows< Excel::Quest >();
auto eNpcList = exdData.getRows< Excel::ENpcBase >();
auto eObjList = exdData.getRows< Excel::EObj >();
for( auto& [ id, questExdData ] : questList ) for( auto& [ id, questExdData ] : questList )
{ {
m_quests.emplace( id, std::move( questExdData ) ); m_questCacheMap.emplace( id, std::move( questExdData ) );
}
for( auto& [ id, eNpcExdData ] : eNpcList )
{
m_eNpcCacheMap.emplace( id, std::move( eNpcExdData ) );
}
for( auto& [ id, eObjExdData ] : eObjList )
{
m_eObjCacheMap.emplace( id, std::move( eObjExdData ) );
} }
return true; return true;
@ -58,12 +71,12 @@ void MapMgr::updateAll( Entity::Player& player )
for( const auto& eventNpc : *eventNpcs ) for( const auto& eventNpc : *eventNpcs )
{ {
auto eNpc = exdData.getRow< Excel::ENpcBase >( eventNpc.second->data.enpcId ); auto eNpcIt = m_eNpcCacheMap.find( eventNpc.second->data.enpcId );
if( !eNpc ) if( eNpcIt == std::end( m_eNpcCacheMap ) )
continue; continue;
auto eNpcData = eNpc->data().EventHandler; auto eNpcData = eNpcIt->second->data().EventHandler;
for( int npcEvent = 0; npcEvent < 32; npcEvent++ ) for( auto npcEvent = 0; npcEvent < 32; ++npcEvent )
{ {
auto npcData = eNpcData[ npcEvent ].EventHandler; auto npcData = eNpcData[ npcEvent ].EventHandler;
@ -80,7 +93,7 @@ void MapMgr::updateAll( Entity::Player& player )
{ {
case EventHandler::EventHandlerType::Quest: case EventHandler::EventHandlerType::Quest:
{ {
auto& quest = m_quests[ npcData ]->data(); auto& quest = m_questCacheMap[ npcData ]->data();
if( quest.Client == eventNpc.second->data.enpcId ) if( quest.Client == eventNpc.second->data.enpcId )
{ {
@ -102,7 +115,7 @@ void MapMgr::updateAll( Entity::Player& player )
{ {
if( guildLeve.NeedGrandCompanyRank > 0 && player.getGc() != 0 ) if( guildLeve.NeedGrandCompanyRank > 0 && player.getGc() != 0 )
{ {
for( int8_t i = 0; i < 3; i++ ) for( int8_t i = 0; i < 3; ++i )
{ {
if( player.getGcRankArray()[ i ] >= guildLeve.NeedGrandCompanyRank ) if( player.getGcRankArray()[ i ] >= guildLeve.NeedGrandCompanyRank )
{ {
@ -162,11 +175,11 @@ void MapMgr::updateAll( Entity::Player& player )
for( const auto& eventObj : *eventObjs ) for( const auto& eventObj : *eventObjs )
{ {
auto eObj = exdData.getRow< Excel::EObj >( eventObj.second->data.BaseId ); auto eObjIt = m_eObjCacheMap.find( eventObj.second->data.BaseId );
if( !eObj ) if( eObjIt == std::end( m_eObjCacheMap ) )
return; continue;
auto eObjData = eObj->data(); auto eObjData = eObjIt->second->data();
EventData eventData; EventData eventData;
eventData.handlerId = eObjData.EventHandler; eventData.handlerId = eObjData.EventHandler;
eventData.layoutId = eventObj.first; eventData.layoutId = eventObj.first;
@ -175,7 +188,7 @@ void MapMgr::updateAll( Entity::Player& player )
if( eventHandlerType == EventHandler::EventHandlerType::Quest ) if( eventHandlerType == EventHandler::EventHandlerType::Quest )
{ {
auto& quest = m_quests[ eObjData.EventHandler ]->data(); auto& quest = m_questCacheMap[ eObjData.EventHandler ]->data();
if( quest.Client == eventObj.second->data.BaseId ) if( quest.Client == eventObj.second->data.BaseId )
{ {
@ -200,13 +213,13 @@ void MapMgr::updateQuests( Entity::Player& player )
for( const auto& eventNpc : *eventNpcs ) for( const auto& eventNpc : *eventNpcs )
{ {
auto eNpc = exdData.getRow< Excel::ENpcBase >( eventNpc.second->data.enpcId ); auto eNpcIt = m_eNpcCacheMap.find( eventNpc.second->data.enpcId );
if( !eNpc ) if( eNpcIt == std::end( m_eNpcCacheMap ) )
continue; continue;
auto eNpcData = eNpc->data().EventHandler; auto eNpcData = eNpcIt->second->data().EventHandler;
for( int npcEvent = 0; npcEvent < 32; npcEvent++ ) for( auto npcEvent = 0; npcEvent < 32; ++npcEvent )
{ {
auto npcData = eNpcData[ npcEvent ].EventHandler; auto npcData = eNpcData[ npcEvent ].EventHandler;
@ -221,7 +234,7 @@ void MapMgr::updateQuests( Entity::Player& player )
if( eventHandlerType == EventHandler::EventHandlerType::Quest ) if( eventHandlerType == EventHandler::EventHandlerType::Quest )
{ {
auto& quest = m_quests[ npcData ]->data(); auto& quest = m_questCacheMap[ npcData ]->data();
if( quest.Client == eventNpc.second->data.enpcId ) if( quest.Client == eventNpc.second->data.enpcId )
{ {
@ -237,11 +250,11 @@ void MapMgr::updateQuests( Entity::Player& player )
for( const auto& eventObj : *eventObjs ) for( const auto& eventObj : *eventObjs )
{ {
auto eObj = exdData.getRow< Excel::EObj >( eventObj.second->data.BaseId ); auto eObjIt = m_eObjCacheMap.find( eventObj.second->data.BaseId );
if( !eObj ) if( eObjIt == std::end( m_eObjCacheMap ) )
return; continue;
auto eObjData = eObj->data(); auto eObjData = eObjIt->second->data();
EventData eventData; EventData eventData;
eventData.handlerId = eObjData.EventHandler; eventData.handlerId = eObjData.EventHandler;
eventData.layoutId = eventObj.first; eventData.layoutId = eventObj.first;
@ -250,7 +263,7 @@ void MapMgr::updateQuests( Entity::Player& player )
if( eventHandlerType == EventHandler::EventHandlerType::Quest ) if( eventHandlerType == EventHandler::EventHandlerType::Quest )
{ {
auto& quest = m_quests[ eObjData.EventHandler ]->data(); auto& quest = m_questCacheMap[ eObjData.EventHandler ]->data();
if( quest.Client == eventObj.second->data.BaseId ) if( quest.Client == eventObj.second->data.BaseId )
{ {
@ -267,7 +280,7 @@ void MapMgr::insertQuest( Entity::Player& player, uint32_t questId, uint32_t lay
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
auto& quest = m_quests[ questId ]->data(); auto& quest = m_questCacheMap[ questId ]->data();
if( isQuestVisible( player, questId, quest ) ) if( isQuestVisible( player, questId, quest ) )
{ {
@ -307,7 +320,7 @@ bool MapMgr::isQuestAvailable( Entity::Player& player, uint32_t questId, Excel::
if( quest.InstanceContentOperator == 1 ) if( quest.InstanceContentOperator == 1 )
{ {
for( int32_t i = 0; i < 3; i++ ) for( int32_t i = 0; i < 3; ++i )
{ {
if( quest.InstanceContent[ i ] == 0 ) if( quest.InstanceContent[ i ] == 0 )
continue; continue;
@ -319,7 +332,7 @@ bool MapMgr::isQuestAvailable( Entity::Player& player, uint32_t questId, Excel::
} }
else if( quest.InstanceContentOperator == 2 ) else if( quest.InstanceContentOperator == 2 )
{ {
for( int32_t i = 0; i < 3; i++ ) for( int32_t i = 0; i < 3; ++i )
{ {
if( quest.InstanceContent[ i ] == 0 ) if( quest.InstanceContent[ i ] == 0 )
continue; continue;
@ -396,7 +409,7 @@ bool MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Excel::Qu
if( quest.PrevQuestOperator == 1 ) if( quest.PrevQuestOperator == 1 )
{ {
for( int32_t i = 0; i < 3; i++ ) for( auto i = 0; i < 3; ++i )
{ {
if( quest.PrevQuest[ i ] == 0 ) if( quest.PrevQuest[ i ] == 0 )
continue; continue;
@ -419,7 +432,7 @@ bool MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Excel::Qu
} }
else if( quest.PrevQuestOperator == 2 ) else if( quest.PrevQuestOperator == 2 )
{ {
for( int32_t i = 0; i < 3; i++ ) for( auto i = 0; i < 3; ++i )
{ {
if( quest.PrevQuest[ i ] == 0 ) if( quest.PrevQuest[ i ] == 0 )
continue; continue;
@ -434,7 +447,7 @@ bool MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Excel::Qu
if( quest.ExcludeQuestOperator == 1 ) if( quest.ExcludeQuestOperator == 1 )
{ {
for( int32_t i = 0; i < 2; i++ ) for( auto i = 0; i < 2; ++i )
{ {
if( quest.ExcludeQuest[ i ] == 0 ) if( quest.ExcludeQuest[ i ] == 0 )
continue; continue;
@ -448,7 +461,7 @@ bool MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Excel::Qu
} }
else if( quest.ExcludeQuestOperator == 2 ) else if( quest.ExcludeQuestOperator == 2 )
{ {
for( int32_t i = 0; i < 2; i++ ) for( auto i = 0; i < 2; ++i )
{ {
if( quest.ExcludeQuest[ i ] == 0 ) if( quest.ExcludeQuest[ i ] == 0 )
continue; continue;
@ -475,7 +488,7 @@ bool MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Excel::Qu
{ {
auto classJobCategory = exdData.getRow< Excel::ClassJobCategory >( quest.ClassJob )->data().ClassJob; auto classJobCategory = exdData.getRow< Excel::ClassJobCategory >( quest.ClassJob )->data().ClassJob;
for( int32_t i = 1; i <= Common::CLASSJOB_TOTAL; i++ ) for( auto i = 1; i <= Common::CLASSJOB_TOTAL; ++i )
{ {
if( i == Common::CLASSJOB_TOTAL ) if( i == Common::CLASSJOB_TOTAL )
return false; return false;
@ -494,13 +507,14 @@ bool MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Excel::Qu
} }
// TODO: I think this changed in 3.x to be for all relics, more research is needed. // TODO: I think this changed in 3.x to be for all relics, more research is needed.
for( int32_t i = 0; i < Common::CLASSJOB_TOTAL; i++ ) // todo: fix this inner j loop
for( auto i = 0; i < Common::CLASSJOB_TOTAL; ++i )
{ {
auto classJob = exdData.getRow< Excel::ClassJob >( i ); auto classJob = exdData.getRow< Excel::ClassJob >( i );
if( classJob->data().ARRRelicQuestId == questId ) if( classJob->data().ARRRelicQuestId == questId )
{ {
for( int32_t j = 0; i < Common::CLASSJOB_TOTAL; i++ ) for( auto j = 0; i < Common::CLASSJOB_TOTAL; ++i )
{ {
classJob = exdData.getRow< Excel::ClassJob >( i ); classJob = exdData.getRow< Excel::ClassJob >( i );

View file

@ -11,6 +11,8 @@
namespace Sapphire::World::Manager namespace Sapphire::World::Manager
{ {
using QuestMap = std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< Excel::Quest > > >; using QuestMap = std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< Excel::Quest > > >;
using EObjDataCache = std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< Excel::EObj > > >;
using ENpcDataCache = std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< Excel::ENpcBase > > >;
class MapMgr class MapMgr
{ {
@ -64,8 +66,11 @@ namespace Sapphire::World::Manager
}; };
using EventSet = std::multiset< EventData, less >; using EventSet = std::multiset< EventData, less >;
QuestMap m_quests; QuestMap m_questCacheMap;
ENpcDataCache m_eNpcCacheMap;
EObjDataCache m_eObjCacheMap;
void insertQuest( Entity::Player& player, uint32_t questId, uint32_t layoutId, EventSet& mapData ); void insertQuest( Entity::Player& player, uint32_t questId, uint32_t layoutId, EventSet& mapData );

View file

@ -253,7 +253,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
} }
case GmCommand::Kill: case GmCommand::Kill:
{ {
targetActor->getAsChara()->takeDamage( 9999999 ); targetActor->getAsChara()->takeDamage( 0xFFFFFFFF );
PlayerMgr::sendServerNotice( player, "Killed {0}", targetActor->getId()); PlayerMgr::sendServerNotice( player, "Killed {0}", targetActor->getId());
break; break;
} }