2021-08-30 10:16:05 +02:00
# include <Common.h>
# include <Service.h>
# include <Exd/ExdDataGenerated.h>
# include <Event/EventHandler.h>
# include <Network/CommonActorControl.h>
# include <Network/PacketDef/Zone/ServerZoneDef.h>
# include <Network/PacketWrappers/ActorControlSelfPacket.h>
# include <Util/Util.cpp>
# include <Actor/Player.h>
2021-09-07 16:50:13 +02:00
# include <Script/ScriptMgr.h>
# include <Script/NativeScriptMgr.h>
# include <Territory/InstanceObjectCache.h>
# include <datReader/DatCategories/bg/lgb.h>
2021-08-30 10:16:05 +02:00
# include "MapMgr.h"
# include "TerritoryMgr.h"
using namespace Sapphire : : Event ;
using namespace Sapphire : : Network : : Packets ;
using namespace Sapphire : : Network : : Packets : : Server ;
Sapphire : : World : : Manager : : MapMgr : : MapMgr ( )
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2021-09-07 16:50:13 +02:00
for ( uint32_t questId = 65536 ; auto curQuest = exdData . get < Data : : Quest > ( questId ) ; questId + + )
m_quests . emplace ( questId , curQuest ) ;
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
void Sapphire : : World : : Manager : : MapMgr : : updateAll ( Entity : : Player & player )
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto & objectCache = Common : : Service < Sapphire : : InstanceObjectCache > : : ref ( ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
EventSet mapData ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
auto eventNpcs = objectCache . getAllEventNpc ( player . getZoneId ( ) ) ;
if ( eventNpcs )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
for ( const auto & eventNpc : * eventNpcs )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto eNpc = exdData . get < Data : : ENpcBase > ( eventNpc . second - > data . enpcId ) ;
if ( eNpc )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto eNpcData = eNpc - > eNpcData ;
for ( auto npcData : eNpcData )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( npcData = = 0 )
continue ; // Some npcs have data gaps, so we have to iterate through the entire array
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
EventData eventData ;
eventData . eventId = npcData ;
eventData . levelId = eventNpc . first ;
auto eventHandlerType = static_cast < EventHandler : : EventHandlerType > ( npcData > > 16 ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
switch ( eventHandlerType )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
case EventHandler : : EventHandlerType : : Quest :
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto quest = m_quests [ npcData ] ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( quest - > issuerLocation = = eventNpc . first )
{
insertQuest ( player , npcData , mapData ) ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
break ;
}
case EventHandler : : EventHandlerType : : GuildLeveAssignment :
{
if ( player . isActionLearned ( 5 ) )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto guildLeve = exdData . get < Data : : GuildleveAssignment > ( npcData ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
eventData . iconId = exdData . get < Data : : EventIconType > ( 5 ) - > mapIconAvailable + 1 ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( player . isQuestCompleted ( guildLeve - > quest [ 0 ] ) | |
( ( guildLeve - > typeId = = 2 | | npcData = = 393217 | | npcData = = 393223 | | npcData = = 393225 ) & & // Leve npc locations: Bentbranch / Horizon / Swiftperch
( player . isQuestCompleted ( 220 ) | | player . isQuestCompleted ( 687 ) | | player . isQuestCompleted ( 693 ) ) ) )
{
if ( guildLeve - > typeId = = 2 )
{
if ( player . getGc ( ) ! = 0 )
{
for ( int8_t i = 0 ; i < 3 ; i + + )
{
if ( player . getGcRankArray ( ) [ i ] > = guildLeve - > grandCompanyRank )
{
mapData . insert ( eventData ) ;
break ;
}
}
}
}
else
{
mapData . insert ( eventData ) ;
}
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
}
break ;
}
case EventHandler : : EventHandlerType : : CustomTalk :
{
// Include only the beginner arena icon yet. There a few other ones, that aren't referenced in the game files (Some examples are: The Triple Triad Tournament npc which has multiple icons and the ocean fishing icon)
if ( npcData = = 721223 )
{
auto customTalk = exdData . get < Data : : CustomTalk > ( npcData ) ;
eventData . iconId = customTalk - > iconMap ;
mapData . insert ( eventData ) ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
break ;
}
case EventHandler : : EventHandlerType : : GuildOrderGuide :
{
if ( player . isActionLearned ( 7 ) )
2021-08-30 10:16:05 +02:00
{
eventData . iconId = exdData . get < Data : : EventIconType > ( 6 ) - > mapIconAvailable + 1 ;
2021-09-07 16:50:13 +02:00
mapData . insert ( eventData ) ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
break ;
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
case EventHandler : : EventHandlerType : : TripleTriad :
{
if ( npcData = = 2293771 ) // Triple Triad Master npc for now only
2021-08-30 10:16:05 +02:00
{
eventData . iconId = exdData . get < Data : : EventIconType > ( 7 ) - > mapIconAvailable + 1 ;
2021-09-07 16:50:13 +02:00
mapData . insert ( eventData ) ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
break ;
}
case EventHandler : : EventHandlerType : : PreHandler :
{
//I think this is used in Bozja and Zadnor, need evidence
break ;
}
}
}
}
}
}
auto eventObjs = objectCache . getAllEventObj ( player . getZoneId ( ) ) ;
if ( eventObjs )
{
for ( const auto & eventObj : * eventObjs )
{
auto eObj = exdData . get < Data : : EObj > ( eventObj . second - > data . eobjId ) ;
if ( eObj )
{
auto eObjData = eObj - > data ;
if ( eObjData )
{
EventData eventData ;
eventData . eventId = eObjData ;
eventData . levelId = eventObj . first ;
auto eventHandlerType = static_cast < EventHandler : : EventHandlerType > ( eObjData > > 16 ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( eventHandlerType = = EventHandler : : EventHandlerType : : Quest )
{
auto quest = m_quests [ eObjData ] ;
if ( quest - > issuerLocation = = eventObj . first )
{
insertQuest ( player , eObjData , mapData ) ;
2021-08-30 10:16:05 +02:00
}
}
}
}
}
}
2021-09-07 16:50:13 +02:00
sendPackets ( player , mapData , All ) ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
void Sapphire : : World : : Manager : : MapMgr : : updateQuests ( Entity : : Player & player )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto & objectCache = Common : : Service < Sapphire : : InstanceObjectCache > : : ref ( ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
EventSet mapData ;
auto eventNpcs = objectCache . getAllEventNpc ( player . getZoneId ( ) ) ;
if ( eventNpcs )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
for ( const auto & eventNpc : * eventNpcs )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto eNpcData = exdData . get < Data : : ENpcBase > ( eventNpc . second - > data . enpcId ) - > eNpcData ;
for ( auto npcData : eNpcData )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( npcData = = 0 )
continue ; // Some npcs have data gaps, so we have to iterate through the entire array
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
EventData eventData ;
eventData . eventId = npcData ;
eventData . levelId = eventNpc . first ;
auto eventHandlerType = static_cast < EventHandler : : EventHandlerType > ( npcData > > 16 ) ;
if ( eventHandlerType = = EventHandler : : EventHandlerType : : Quest )
{
auto quest = m_quests [ npcData ] ;
if ( quest - > issuerLocation = = eventNpc . first )
{
insertQuest ( player , npcData , mapData ) ;
}
}
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
}
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
auto eventObjs = objectCache . getAllEventObj ( player . getZoneId ( ) ) ;
if ( eventObjs )
{
for ( const auto & eventObj : * eventObjs )
{
auto eObj = exdData . get < Data : : EObj > ( eventObj . second - > data . eobjId ) ;
if ( eObj )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto eObjData = eObj - > data ;
if ( eObjData )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
EventData eventData ;
eventData . eventId = eObjData ;
eventData . levelId = eventObj . first ;
auto eventHandlerType = static_cast < EventHandler : : EventHandlerType > ( eObjData > > 16 ) ;
if ( eventHandlerType = = EventHandler : : EventHandlerType : : Quest )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto quest = m_quests [ eObjData ] ;
if ( quest - > issuerLocation = = eventObj . first )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
insertQuest ( player , eObjData , mapData ) ;
2021-08-30 10:16:05 +02:00
}
}
}
}
2021-09-07 16:50:13 +02:00
}
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
sendPackets ( player , mapData , Quest ) ;
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
void Sapphire : : World : : Manager : : MapMgr : : insertQuest ( Entity : : Player & player , uint32_t questId , EventSet & mapData )
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
auto & scriptMgr = Common : : Service < Scripting : : ScriptMgr > : : ref ( ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
auto quest = m_quests [ questId ] ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( isQuestVisible ( player , questId , quest ) )
{
auto script = scriptMgr . getNativeScriptHandler ( ) . getScript < Sapphire : : ScriptAPI : : EventScript > ( questId ) ;
// Just don't show quests on map, that aren't implemented yet
if ( script )
{
EventData eventData ;
eventData . eventId = questId ;
2021-09-08 11:25:16 +02:00
auto eventState = script - > getQuestAvailability ( player , questId ) ;
2021-08-30 10:16:05 +02:00
2021-09-08 11:25:16 +02:00
if ( eventState = = Event : : EventHandler : : QuestAvailability : : Available | | eventState = = Event : : EventHandler : : QuestAvailability : : Locked )
2021-08-30 10:16:05 +02:00
{
2021-09-08 11:25:16 +02:00
if ( eventState = = Event : : EventHandler : : QuestAvailability : : Available & & isQuestAvailable ( player , questId , quest ) )
2021-09-07 16:50:13 +02:00
{
eventData . iconId = exdData . get < Data : : EventIconType > ( quest - > eventIconType ) - > mapIconAvailable + 1 + quest - > isRepeatable ;
eventData . levelId = quest - > issuerLocation ;
}
else
{
eventData . iconId = exdData . get < Data : : EventIconType > ( quest - > eventIconType ) - > mapIconInvalid + 1 + quest - > isRepeatable ;
eventData . levelId = quest - > issuerLocation ;
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
mapData . insert ( eventData ) ;
2021-08-30 10:16:05 +02:00
}
}
}
}
2021-09-07 16:50:13 +02:00
bool Sapphire : : World : : Manager : : MapMgr : : isQuestAvailable ( Entity : : Player & player , uint32_t questId , Data : : ExdDataGenerated : : QuestPtr questPtr )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( questPtr - > grandCompany | | questPtr - > grandCompanyRank )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( questPtr - > grandCompany ! = player . getGc ( ) )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( questPtr - > grandCompanyRank > player . getGcRankArray ( ) [ player . getGc ( ) - 1 ] )
return false ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( questPtr - > instanceContentJoin = = 1 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
for ( int32_t i = 0 ; i < 3 ; i + + )
{
if ( questPtr - > instanceContent [ i ] = = 0 )
continue ;
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
return true ;
}
else if ( questPtr - > instanceContentJoin = = 2 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
for ( int32_t i = 0 ; i < 3 ; i + + )
{
if ( questPtr - > instanceContent [ i ] = = 0 )
continue ;
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
}
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( questPtr - > bellStart | | questPtr - > bellEnd )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
uint64_t curEorzeaTime = Util : : getEorzeanTimeStamp ( ) ;
uint32_t convTime = 100 * ( curEorzeaTime / 3600 % 24 ) + curEorzeaTime / 60 % 60 ;
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
if ( questPtr - > bellStart < = questPtr - > bellEnd )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( convTime < questPtr - > bellStart | | convTime > = questPtr - > bellEnd )
2021-08-30 10:16:05 +02:00
return false ;
}
2021-09-07 16:50:13 +02:00
else
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( convTime < questPtr - > bellStart & & convTime > = questPtr - > bellEnd )
2021-08-30 10:16:05 +02:00
return false ;
}
2021-09-07 16:50:13 +02:00
}
auto classJobCategory = & exdData . get < Data : : ClassJobCategory > ( questPtr - > classJobCategory0 ) - > aDV ;
if ( ! classJobCategory [ static_cast < uint8_t > ( player . getClass ( ) ) ] )
return false ;
if ( questPtr - > classJobCategory1 > 1 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
classJobCategory = & exdData . get < Data : : ClassJobCategory > ( questPtr - > classJobCategory1 ) - > aDV ;
if ( ! classJobCategory [ static_cast < uint8_t > ( player . getClass ( ) ) ] )
return false ;
}
2021-08-30 10:16:05 +02:00
2021-09-07 16:50:13 +02:00
return true ;
}
bool Sapphire : : World : : Manager : : MapMgr : : isQuestVisible ( Entity : : Player & player , uint32_t questId , Data : : ExdDataGenerated : : QuestPtr questPtr )
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
if ( ( player . isQuestCompleted ( questId ) & & ( ! questPtr - > isRepeatable & & questId ! = 67114 ) ) | | player . hasQuest ( questId ) )
return false ;
if ( questPtr - > classJobUnlock )
{
if ( questPtr - > classJobUnlockFlag = = 3 )
if ( static_cast < uint8_t > ( player . getClass ( ) ) ! = questPtr - > classJobUnlock )
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
else if ( questPtr - > classJobUnlockFlag = = 4 )
if ( static_cast < uint8_t > ( player . getClass ( ) ) = = questPtr - > classJobUnlock )
return false ;
else
return false ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
// Was this really ever used?
if ( questPtr - > startTown )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( questPtr - > startTown ! = player . getStartTown ( ) )
2021-08-30 10:16:05 +02:00
return false ;
}
2021-09-07 16:50:13 +02:00
if ( Common : : CURRENT_EXPANSION_ID < questPtr - > expansion )
return false ;
if ( questPtr - > mountRequired )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( ! player . hasMount ( questPtr - > mountRequired ) )
2021-08-30 10:16:05 +02:00
return false ;
}
2021-09-07 16:50:13 +02:00
if ( questPtr - > grandCompany )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( questPtr - > grandCompany ! = player . getGc ( ) )
return false ;
2021-08-30 10:16:05 +02:00
}
2021-09-07 16:50:13 +02:00
if ( questPtr - > header ! = 0 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( ! player . isActionLearned ( questPtr - > header ) )
2021-08-30 10:16:05 +02:00
return false ;
}
2021-09-07 16:50:13 +02:00
if ( questPtr - > previousQuestJoin = = 1 )
2021-08-30 10:16:05 +02:00
{
for ( int32_t i = 0 ; i < 3 ; i + + )
{
2021-09-07 16:50:13 +02:00
if ( questPtr - > previousQuest [ i ] = = 0 )
2021-08-30 10:16:05 +02:00
continue ;
2021-09-07 16:50:13 +02:00
if ( ! player . isQuestCompleted ( questPtr - > previousQuest [ i ] ) )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( i = = 0 & & questPtr - > previousQuest0Sequence ! = 0 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( player . getQuestSeq ( questPtr - > previousQuest [ i ] ) < questPtr - > previousQuest0Sequence )
2021-08-30 10:16:05 +02:00
return false ;
}
else
{
return false ;
}
}
}
}
2021-09-07 16:50:13 +02:00
else if ( questPtr - > previousQuestJoin = = 2 )
2021-08-30 10:16:05 +02:00
{
2021-09-11 14:00:04 +02:00
for ( int32_t i = 0 ; i < = 3 ; i + + )
2021-08-30 10:16:05 +02:00
{
2021-09-11 14:00:04 +02:00
if ( i = = 3 )
return false ;
2021-09-07 16:50:13 +02:00
if ( questPtr - > previousQuest [ i ] = = 0 )
2021-08-30 10:16:05 +02:00
continue ;
2021-09-07 16:50:13 +02:00
if ( player . isQuestCompleted ( questPtr - > previousQuest [ i ] ) )
2021-08-30 10:16:05 +02:00
break ;
}
}
2021-09-07 16:50:13 +02:00
if ( questPtr - > questLockJoin = = 1 )
2021-08-30 10:16:05 +02:00
{
2021-09-11 14:00:04 +02:00
for ( int32_t i = 0 ; i < = 2 ; i + + )
2021-08-30 10:16:05 +02:00
{
2021-09-11 14:00:04 +02:00
if ( i = = 2 )
return false ;
2021-09-07 16:50:13 +02:00
if ( questPtr - > questLock [ i ] = = 0 )
2021-08-30 10:16:05 +02:00
continue ;
2021-09-07 16:50:13 +02:00
if ( ! player . isQuestCompleted ( questPtr - > questLock [ i ] ) & & ! player . hasQuest ( questPtr - > questLock [ i ] ) )
2021-08-30 10:16:05 +02:00
break ;
}
}
2021-09-07 16:50:13 +02:00
else if ( questPtr - > questLockJoin = = 2 )
2021-08-30 10:16:05 +02:00
{
for ( int32_t i = 0 ; i < 2 ; i + + )
{
2021-09-07 16:50:13 +02:00
if ( questPtr - > questLock [ i ] = = 0 )
2021-08-30 10:16:05 +02:00
continue ;
2021-09-07 16:50:13 +02:00
if ( player . isQuestCompleted ( questPtr - > questLock [ i ] ) | | player . hasQuest ( questPtr - > questLock [ i ] ) )
2021-08-30 10:16:05 +02:00
return false ;
}
}
2021-09-07 16:50:13 +02:00
if ( questPtr - > festival )
2021-08-30 10:16:05 +02:00
{
auto & territoryMgr = Common : : Service < Manager : : TerritoryMgr > : : ref ( ) ;
auto & festival = territoryMgr . getCurrentFestival ( ) ;
2021-09-07 16:50:13 +02:00
if ( questPtr - > festival ! = festival . first & & questPtr - > festival ! = festival . second )
2021-08-30 10:16:05 +02:00
return false ;
// Don't show festivals with begin state other than 0 yet
2021-09-07 16:50:13 +02:00
if ( questPtr - > festivalBegin ! = 0 )
2021-08-30 10:16:05 +02:00
return false ;
}
2021-09-07 16:50:13 +02:00
if ( ( questPtr - > type & 1 ) = = 0 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto classJobCategory = & exdData . get < Data : : ClassJobCategory > ( questPtr - > classJobCategory0 ) - > aDV ;
2021-08-30 10:16:05 +02:00
for ( int32_t i = 1 ; i < = Common : : CLASSJOB_TOTAL ; i + + )
{
2021-09-07 16:50:13 +02:00
if ( classJobCategory [ i ] )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
if ( player . getLevelForClass ( static_cast < Common : : ClassJob > ( i ) ) > = questPtr - > classJobLevel0 )
2021-08-30 10:16:05 +02:00
break ;
}
if ( i = = Common : : CLASSJOB_TOTAL )
return false ;
}
}
else
{
2021-09-07 16:50:13 +02:00
if ( player . getLevel ( ) < questPtr - > classJobLevel0 )
2021-08-30 10:16:05 +02:00
return false ;
}
for ( int32_t i = 0 ; i < = Common : : CLASSJOB_TOTAL ; i + + )
{
auto classJob = exdData . get < Data : : ClassJob > ( i ) ;
2021-09-07 16:50:13 +02:00
if ( classJob - > relicQuest = = questId )
2021-08-30 10:16:05 +02:00
{
for ( int32_t j = 0 ; i < = Common : : CLASSJOB_TOTAL ; i + + )
{
classJob = exdData . get < Data : : ClassJob > ( i ) ;
if ( player . hasQuest ( classJob - > relicQuest ) )
return false ;
}
break ;
}
}
2021-09-07 16:50:13 +02:00
if ( questPtr - > beastTribe )
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
if ( questPtr - > satisfactionNpc )
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
if ( questPtr - > isHouseRequired )
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
if ( questPtr - > deliveryQuest )
2021-08-30 10:16:05 +02:00
return false ;
2021-09-07 16:50:13 +02:00
if ( player . getQuestSeq ( questId ) = = 0 )
2021-08-30 10:16:05 +02:00
{
2021-09-07 16:50:13 +02:00
auto questAccept = exdData . get < Data : : QuestAcceptAdditionCondition > ( questId ) ;
2021-08-30 10:16:05 +02:00
if ( questAccept )
{
for ( int32_t i = 0 ; i < 2 ; i + + )
{
if ( ( & questAccept - > requirement0 ) [ i ] > = 65536 )
{
if ( ! player . isActionLearned ( 245 ) & & ! player . isQuestCompleted ( ( & questAccept - > requirement0 ) [ i ] ) )
return false ;
}
else
{
if ( ! player . isActionLearned ( ( & questAccept - > requirement0 ) [ i ] ) )
return false ;
}
}
}
}
return true ;
}
2021-09-07 16:50:13 +02:00
bool Sapphire : : World : : Manager : : MapMgr : : isTripleTriadAvailable ( Entity : : Player & player , uint32_t tripleTriadId )
2021-08-30 10:16:05 +02:00
{
auto & exdData = Common : : Service < Data : : ExdDataGenerated > : : ref ( ) ;
2021-09-07 16:50:13 +02:00
auto tripleTriad = exdData . get < Data : : TripleTriad > ( tripleTriadId ) ;
2021-08-30 10:16:05 +02:00
if ( tripleTriad - > previousQuestJoin = = 1 )
{
for ( int32_t i = 0 ; i < 3 ; i + + )
{
if ( tripleTriad - > previousQuest [ i ] = = 0 )
continue ;
if ( ! player . isQuestCompleted ( tripleTriad - > previousQuest [ i ] ) )
return false ;
}
}
else if ( tripleTriad - > previousQuestJoin = = 2 )
{
for ( int32_t i = 0 ; i < 3 ; i + + )
{
if ( tripleTriad - > previousQuest [ i ] = = 0 )
continue ;
if ( player . isQuestCompleted ( tripleTriad - > previousQuest [ i ] ) )
break ;
if ( i = = 2 )
return false ;
}
}
return true ;
}
2021-09-07 16:50:13 +02:00
void Sapphire : : World : : Manager : : MapMgr : : fillPacket ( EventSet & mapData , uint32_t * iconIds , uint32_t * levelIds , uint32_t * eventIds )
2021-08-30 10:16:05 +02:00
{
int32_t i = 0 ;
for ( auto & eventData : mapData )
{
2021-09-07 16:50:13 +02:00
iconIds [ i ] = eventData . iconId ;
levelIds [ i ] = eventData . levelId ;
eventIds [ i ] = eventData . eventId ;
2021-08-30 10:16:05 +02:00
i + + ;
}
}
2021-09-07 16:50:13 +02:00
void Sapphire : : World : : Manager : : MapMgr : : sendPackets ( Entity : : Player & player , EventSet & mapData , UpdateMode updateMode )
2021-08-30 10:16:05 +02:00
{
player . queuePacket ( makeActorControlSelf ( player . getId ( ) , Network : : ActorControl : : BeginMapUpdate , updateMode ) ) ;
if ( mapData . size ( ) < = 2 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
else if ( mapData . size ( ) < = 4 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate4 > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
else if ( mapData . size ( ) < = 8 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate8 > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
else if ( mapData . size ( ) < = 16 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate16 > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
else if ( mapData . size ( ) < = 32 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate32 > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
else if ( mapData . size ( ) < = 64 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate64 > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
else if ( mapData . size ( ) < = 128 )
{
auto mapUpdatePacket = makeZonePacket < FFXIVIpcMapUpdate128 > ( player . getId ( ) ) ;
mapUpdatePacket - > data ( ) . entryCount = mapData . size ( ) ;
fillPacket ( mapData , mapUpdatePacket - > data ( ) . iconIds , mapUpdatePacket - > data ( ) . levelIds , mapUpdatePacket - > data ( ) . eventIds ) ;
player . queuePacket ( mapUpdatePacket ) ;
}
player . queuePacket ( makeActorControlSelf ( player . getId ( ) , Network : : ActorControl : : FinishMapUpdate ) ) ;
}