From 14860047b66f2b5db967a19514f319b26513ec17 Mon Sep 17 00:00:00 2001 From: collett Date: Sun, 5 Feb 2023 19:37:17 +0900 Subject: [PATCH] First batch of 5.58 updates: - Common defs, ActorControls and packet updates (more to come later). - Haste added to chara base stats for later use. - Acquiring HQ items support (HQ status not yet saved to db, need table modification). - Event item support. - Load more default zones. - Quest related debug commands. --- src/common/Common.h | 56 ++++++++++++ src/common/Network/CommonActorControl.h | 2 +- .../Network/PacketDef/Zone/ClientZoneDef.h | 4 +- .../Network/PacketDef/Zone/ServerZoneDef.h | 10 ++- .../quest/subquest/gridania/SubFst008.cpp | 2 +- src/world/Action/EventItemAction.cpp | 70 +++++++++++++++ src/world/Action/EventItemAction.h | 34 ++++++++ src/world/Actor/BNpc.cpp | 1 + src/world/Actor/Chara.cpp | 8 +- src/world/Actor/Chara.h | 1 + src/world/Actor/Player.cpp | 5 +- src/world/Actor/PlayerInventory.cpp | 7 ++ src/world/Actor/PlayerQuest.cpp | 9 +- src/world/ForwardsZone.h | 1 + src/world/Manager/ActionMgr.cpp | 16 ++++ src/world/Manager/ActionMgr.h | 5 ++ src/world/Manager/DebugCommandMgr.cpp | 86 +++++++++++++++++++ src/world/Manager/TerritoryMgr.cpp | 57 ++++++------ src/world/Manager/TerritoryMgr.h | 2 + src/world/Network/Handlers/ActionHandler.cpp | 8 ++ .../Network/Handlers/ClientTriggerHandler.cpp | 16 +++- src/world/Network/Handlers/EventHandlers.cpp | 17 ++-- 22 files changed, 373 insertions(+), 44 deletions(-) create mode 100644 src/world/Action/EventItemAction.cpp create mode 100644 src/world/Action/EventItemAction.h diff --git a/src/common/Common.h b/src/common/Common.h index 8f9c258b..e6cf7371 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -78,6 +78,60 @@ namespace Sapphire::Common Enemy = 4, }; + enum ActorKind : int32_t + { + ACTOR_KIND_PC = 0x0, + ACTOR_KIND_NPC = 0x1, + ACTOR_KIND_RETAINER = 0x2, + ACTOR_KIND_BATTLE = 0x3, + ACTOR_KIND_BATTLE_FRIEND = 0x4, + ACTOR_KIND_OBJECT = 0x5, + ACTOR_KIND_TREASURE = 0x6, + ACTOR_KIND_GATHERING = 0x7, + ACTOR_KIND_MAX = 0x8, + }; + + enum ObjectType : int32_t + { + OBJECT_TYPE_CAMERA = 0x0, + OBJECT_TYPE_CAMERA_MAYA = 0x1, + OBJECT_TYPE_LIGHT = 0x2, + OBJECT_TYPE_PLAYER = 0x3, + OBJECT_TYPE_WEAPON = 0x4, + OBJECT_TYPE_MONSTER = 0x5, + OBJECT_TYPE_TERRAIN = 0x6, + OBJECT_TYPE_BG_OBJECT = 0x7, + OBJECT_TYPE_ENV_LOCATION = 0x8, + OBJECT_TYPE_ENV_SPACE = 0x9, + OBJECT_TYPE_VFX_OBJECT = 0xA, + OBJECT_TYPE_COUNT_MAX = 0xB, + }; + + enum WarpType : uint8_t + { + WARP_TYPE_NON = 0x0, + WARP_TYPE_NORMAL = 0x1, + WARP_TYPE_NORMAL_POS = 0x2, + WARP_TYPE_EXIT_RANGE = 0x3, + WARP_TYPE_TELEPO = 0x4, + WARP_TYPE_REISE = 0x5, + WARP_TYPE_ = 0x6, + WARP_TYPE_DESION = 0x7, + WARP_TYPE_HOME_POINT = 0x8, + WARP_TYPE_RENTAL_CHOCOBO = 0x9, + WARP_TYPE_CHOCOBO_TAXI = 0xA, + WARP_TYPE_INSTANCE_CONTENT = 0xB, + WARP_TYPE_REJECT = 0xC, + WARP_TYPE_CONTENT_END_RETURN = 0xD, + WARP_TYPE_TOWN_TRANSLATE = 0xE, + WARP_TYPE_GM = 0xF, + WARP_TYPE_LOGIN = 0x10, + WARP_TYPE_LAYER_SET = 0x11, + WARP_TYPE_EMOTE = 0x12, + WARP_TYPE_HOUSING_TELEPO = 0x13, + WARP_TYPE_DEBUG = 0x14, + }; + enum ObjKind : uint8_t { None = 0x00, @@ -649,6 +703,7 @@ namespace Sapphire::Common * @param flags Required to be 128, doesn't show combo rings on hotbars otherwise * @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo */ + Provoke = 24, StartActionCombo = 27, // shifted one up from 5.18 ComboSucceed = 28, // shifted one up from 5.18, on retail this is not seen anymore, still working though. Knockback = 33, @@ -893,6 +948,7 @@ namespace Sapphire::Common { Normal = 0x1, ItemAction = 0x2, + EventItem = 0x3, MountSkill = 0xD, }; diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index c713148c..b1e397c4 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -382,7 +382,7 @@ namespace Sapphire::Network::ActorControl AllotAttribute = 0x135, ClearFieldMarkers = 0x13A, - CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable + CameraMode = 0x13B, // param11, 1 = enable, 0 = disable CharaNameReq = 0x13D, // requests character name by content id HuntingLogDetails = 0x194, diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 5efe9771..3755e800 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -452,7 +452,7 @@ struct FFXIVIpcEventYieldHandler : uint32_t eventId; uint16_t scene; uint16_t padding; - uint64_t unknown; + uint32_t params[2]; }; struct FFXIVIpcEventYield16Handler : @@ -468,7 +468,7 @@ struct FFXIVIpcCFCommenceHandler : FFXIVIpcBasePacket< CFCommenceHandler > { uint8_t param; - uint8_t dummy[7]; + uint8_t padding[7]; }; } diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 74b980a1..62a6d5ca 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -753,8 +753,8 @@ namespace Sapphire::Network::Packets::Server uint16_t unknown1; uint16_t unknown2; uint16_t modelChara; - uint16_t currentMount; uint16_t rotation; + uint16_t currentMount; uint16_t activeMinion; uint8_t spawnIndex; uint8_t state; @@ -2230,10 +2230,12 @@ namespace Sapphire::Network::Packets::Server uint8_t classId; uint8_t u5; uint8_t level; - uint8_t otherData[368]; + uint8_t isLevelSync; + uint8_t unknown[7]; + Common::StatusEffect effect[30]; } member[8]; - uint64_t someContentId1; - uint64_t someContentId2; + uint64_t partyId; + uint64_t channelId; uint8_t leaderIndex; uint8_t partySize; uint16_t padding1; diff --git a/src/scripts/quest/subquest/gridania/SubFst008.cpp b/src/scripts/quest/subquest/gridania/SubFst008.cpp index ad00c64c..fb556914 100644 --- a/src/scripts/quest/subquest/gridania/SubFst008.cpp +++ b/src/scripts/quest/subquest/gridania/SubFst008.cpp @@ -123,7 +123,7 @@ private: { if( result.param2 == 1 ) { - if( player.giveQuestRewards( getId(), 0 ) ) + if( player.giveQuestRewards( getId(), result.param3 ) ) { player.setQuestUI8BH( getId(), result.param3 ); player.finishQuest( getId() ); diff --git a/src/world/Action/EventItemAction.cpp b/src/world/Action/EventItemAction.cpp new file mode 100644 index 00000000..f833c420 --- /dev/null +++ b/src/world/Action/EventItemAction.cpp @@ -0,0 +1,70 @@ +#include "EventItemAction.h" + +#include +#include + +#include "Manager/PlayerMgr.h" +#include "Manager/EventMgr.h" + +#include "Script/ScriptMgr.h" +#include +#include +#include "Network/PacketWrappers/ActorControlPacket.h" +#include "Network/PacketWrappers/ActorControlSelfPacket.h" +#include "Network/PacketWrappers/ActorControlTargetPacket.h" +#include +#include + +using namespace Sapphire; +using namespace Sapphire::Common; +using namespace Sapphire::Network; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::Server; +using namespace Sapphire::Network::ActorControl; +using namespace Sapphire::World; +using namespace Sapphire::World::Action; + +EventItemAction::EventItemAction( Sapphire::Entity::CharaPtr source, uint32_t eventItemId, + Data::EventItemPtr eventItemActionData, + uint32_t sequence, uint64_t targetId ) : + m_eventItemAction( std::move( eventItemActionData ) ) +{ + m_id = eventItemId; + m_eventItem = eventItemId; + m_pSource = std::move( source ); + m_sequence = sequence; + m_targetId = targetId; + m_interruptType = Common::ActionInterruptType::None; + //m_actionKind = Common::SkillType::EventItem; +} + +bool EventItemAction::init() +{ + auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); + auto actionInfoPtr = exdData.get< Data::Action >( m_eventItemAction->action ); + + m_castTimeMs = static_cast< uint32_t >( m_eventItemAction->castTime * 1000 ); + m_recastTimeMs = static_cast< uint32_t >( actionInfoPtr->recast100ms * 100 ); + m_cooldownGroup = actionInfoPtr->cooldownGroup; + m_id = m_eventItemAction->action; + return true; +} + +void EventItemAction::execute() +{ + auto player = getSourceChara()->getAsPlayer(); + if( !player ) + return; + + auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); + auto& eventMgr = Common::Service< World::Manager::EventMgr >::ref(); + + player->eventStart( m_targetId, m_eventItemAction->quest, Event::EventHandler::ActionResult, 0, 0 ); + scriptMgr.onEventItem( *player, m_eventItem, m_eventItemAction->quest, m_castTimeMs, m_targetId ); + player->checkEvent( m_eventItemAction->quest ); +} + +void EventItemAction::start() +{ + m_startTime = Common::Util::getTimeMs(); +} diff --git a/src/world/Action/EventItemAction.h b/src/world/Action/EventItemAction.h new file mode 100644 index 00000000..8c76fcbc --- /dev/null +++ b/src/world/Action/EventItemAction.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Action.h" +#include + +namespace Sapphire::Data +{ + struct EventItem; + using EventItemPtr = std::shared_ptr< EventItem >; +} + +namespace Sapphire::World::Action +{ + class EventItemAction : public Action + { + public: + EventItemAction( Entity::CharaPtr source, uint32_t eventItemId, Data::EventItemPtr itemActionData, + uint32_t sequence, uint64_t targetId ); + + virtual ~EventItemAction() = default; + + bool init(); + + void execute() override; + + void start() override; + + + private: + Data::EventItemPtr m_eventItemAction; + uint32_t m_eventItem; + uint32_t m_sequence; + }; +} \ No newline at end of file diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 09b96793..e324c187 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -732,6 +732,7 @@ void Sapphire::Entity::BNpc::calculateStats() m_baseStats.pie = static_cast< uint32_t >( base ); m_baseStats.skillSpeed = static_cast< uint32_t >( paramGrowthInfo->baseSpeed ); m_baseStats.spellSpeed = static_cast< uint32_t >( paramGrowthInfo->baseSpeed ); + m_baseStats.haste = 100; m_baseStats.accuracy = static_cast< uint32_t >( paramGrowthInfo->baseSpeed ); m_baseStats.critHitRate = static_cast< uint32_t >( paramGrowthInfo->baseSpeed ); m_baseStats.attackPotMagic = static_cast< uint32_t >( paramGrowthInfo->baseSpeed ); diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index c62c268c..1c9d6be5 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -529,8 +529,8 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf if( nextSlot == -1 ) return; - pEffect->applyStatus(); m_statusEffectMap[ nextSlot ] = pEffect; + pEffect->applyStatus(); auto statusEffectAdd = makeZonePacket< FFXIVIpcEffectResult >( getId() ); @@ -867,6 +867,12 @@ uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam base break; } + case Common::BaseParam::Haste: + { + value = m_baseStats.haste; + break; + } + case Common::BaseParam::CriticalHit: { value = m_baseStats.critHitRate; diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index a6aee7c0..b200be4c 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -48,6 +48,7 @@ namespace Sapphire::Entity uint32_t healingPotMagic = 0; uint32_t determination = 0; uint32_t skillSpeed = 0; + uint32_t haste = 0; uint32_t resistSlow = 0; uint32_t resistSilence = 0; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 1ef07103..48ce94ef 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -287,6 +287,7 @@ void Sapphire::Entity::Player::calculateStats() m_baseStats.pie = static_cast< uint32_t >( base ); m_baseStats.skillSpeed = paramGrowthInfo->baseSpeed; m_baseStats.spellSpeed = paramGrowthInfo->baseSpeed; + m_baseStats.haste = 100; m_baseStats.accuracy = paramGrowthInfo->baseSpeed; m_baseStats.critHitRate = paramGrowthInfo->baseSpeed; m_baseStats.attackPotMagic = paramGrowthInfo->baseSpeed; @@ -339,7 +340,7 @@ void Sapphire::Entity::Player::sendStats() statPacket->data().healingMagicPotency = getStatValue( Common::BaseParam::HealingMagicPotency ); statPacket->data().skillSpeed = getStatValue( Common::BaseParam::SkillSpeed ); statPacket->data().spellSpeed = getStatValue( Common::BaseParam::SpellSpeed ); - statPacket->data().haste = 100; + statPacket->data().haste = getStatValue( Common::BaseParam::Haste ); statPacket->data().criticalHit = getStatValue( Common::BaseParam::CriticalHit ); statPacket->data().defense = getStatValue( Common::BaseParam::Defense ); statPacket->data().magicDefense = getStatValue( Common::BaseParam::MagicDefense ); @@ -1183,7 +1184,7 @@ void Sapphire::Entity::Player::update( uint64_t tickCount ) actor->getPos().x, actor->getPos().y, actor->getPos().z ) <= range ) { - if( ( tickCount - m_lastAttack ) > mainWeap->getDelay() ) + if( ( tickCount - m_lastAttack ) > ( static_cast< float >( mainWeap->getDelay() ) * ( getStatValue( Common::BaseParam::Haste ) / 100.0f ) ) ) { m_lastAttack = tickCount; autoAttack( actor->getAsChara() ); diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index 5ead207c..b9fe5488 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -704,7 +704,14 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_ { if( catalogId == 0 ) return nullptr; + if( catalogId > 1000000 ) + { + catalogId -= 1000000; + isHq = true; + } auto item = createTempItem( catalogId, quantity ); + if( !item ) + return false; item->setHq( isHq ); return addItem( item, silent, canMerge, sendLootMessage ); } diff --git a/src/world/Actor/PlayerQuest.cpp b/src/world/Actor/PlayerQuest.cpp index 7029c64e..a650432a 100644 --- a/src/world/Actor/PlayerQuest.cpp +++ b/src/world/Actor/PlayerQuest.cpp @@ -1091,6 +1091,13 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti } } + auto isHq = false; + if( optionalChoice > 1000000 ) + { + optionalChoice -= 1000000; + isHq = true; + } + if( optionalItemCount > 0 ) { for( uint32_t i = 0; i < optionalItemCount; i++ ) @@ -1098,7 +1105,7 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti auto itemId = questInfo->itemReward1.at( i ); if( itemId > 0 && itemId == optionalChoice ) { - addItem( itemId, questInfo->itemCountReward1.at( i ), false, false, true, true ); + addItem( itemId, questInfo->itemCountReward1.at( i ), isHq, false, true, true ); break; } } diff --git a/src/world/ForwardsZone.h b/src/world/ForwardsZone.h index 4592c320..33e33fb6 100644 --- a/src/world/ForwardsZone.h +++ b/src/world/ForwardsZone.h @@ -87,6 +87,7 @@ namespace World::Action TYPE_FORWARD( Action ); TYPE_FORWARD( EventAction ); TYPE_FORWARD( ItemAction ); +TYPE_FORWARD( EventItemAction ); TYPE_FORWARD( MountAction ); TYPE_FORWARD( EffectBuilder ); TYPE_FORWARD( EffectResult ); diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index 22280a1a..b7800562 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -2,6 +2,7 @@ #include "Action/Action.h" #include "Action/ItemAction.h" +#include "Action/EventItemAction.h" #include "Action/MountAction.h" #include "Script/ScriptMgr.h" #include "Actor/Player.h" @@ -72,6 +73,20 @@ void World::Manager::ActionMgr::handleItemAction( Sapphire::Entity::Player& play action->start(); } +void World::Manager::ActionMgr::handleEventItemAction( Sapphire::Entity::Player& player, uint32_t itemId, Data::EventItemPtr itemActionData, uint32_t sequence, uint64_t targetId ) +{ + auto action = Action::make_EventItemAction( player.getAsChara(), itemId, itemActionData, sequence, targetId ); + if( !action->init() ) + return; + if( itemActionData->castTime ) + { + player.setCurrentAction( action ); + } + + action->start(); +} + + void World::Manager::ActionMgr::handleMountAction( Entity::Player& player, uint16_t mountId, Data::ActionPtr actionData, uint64_t targetId, uint16_t sequence ) @@ -94,6 +109,7 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player, { if( !currentAction->preCheck() ) { + player.sendDebug( "preCheck failed" ); // forcefully interrupt the action and reset the cooldown currentAction->interrupt(); return; diff --git a/src/world/Manager/ActionMgr.h b/src/world/Manager/ActionMgr.h index af58dc1d..5dc0a7bc 100644 --- a/src/world/Manager/ActionMgr.h +++ b/src/world/Manager/ActionMgr.h @@ -10,6 +10,9 @@ namespace Sapphire::Data struct ItemAction; using ItemActionPtr = std::shared_ptr< ItemAction >; + + struct EventItem; + using EventItemPtr = std::shared_ptr< EventItem >; } namespace Sapphire::World::Manager @@ -28,6 +31,8 @@ namespace Sapphire::World::Manager void handleItemAction( Entity::Player& player, uint32_t itemId, Data::ItemActionPtr itemActionData, uint16_t itemSourceSlot, uint16_t itemSourceContainer ); + void handleEventItemAction( Entity::Player& player, uint32_t itemId, Data::EventItemPtr itemActionData, uint32_t sequence, uint64_t targetId ); + void handleMountAction( Entity::Player& player, uint16_t mountId, Data::ActionPtr actionData, uint64_t targetId, uint16_t sequence ); diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 5daafd7f..135d0f6f 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -16,6 +16,9 @@ #include "DebugCommand/DebugCommand.h" #include "DebugCommandMgr.h" +#include +#include + #include "Network/PacketWrappers/ServerNoticePacket.h" #include "Network/PacketWrappers/ActorControlPacket.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h" @@ -33,6 +36,7 @@ #include "Territory/InstanceContent.h" #include "Territory/QuestBattle.h" #include "Territory/PublicContent.h" +#include "Territory/InstanceObjectCache.h" #include "Manager/TerritoryMgr.h" #include "Event/EventDefs.h" @@ -304,6 +308,76 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player& { terriMgr.disableCurrentFestival(); } + else if( subCommand == "QuestVar" ) + { + uint16_t questId; + uint8_t index; + uint8_t value; + sscanf( params.c_str(), "%hu %hhu %hhu", &questId, &index, &value ); + switch( index ) + { + case 1: + { + player.setQuestUI8AH( questId, value ); + break; + } + case 2: + { + player.setQuestUI8AL( questId, value ); + break; + } + case 3: + { + player.setQuestUI8BH( questId, value ); + break; + } + case 4: + { + player.setQuestUI8BL( questId, value ); + break; + } + case 5: + { + player.setQuestUI8CH( questId, value ); + break; + } + case 6: + { + player.setQuestUI8CL( questId, value ); + break; + } + case 7: + { + player.setQuestUI8DH( questId, value ); + break; + } + case 8: + { + player.setQuestUI8DL( questId, value ); + break; + } + case 9: + { + player.setQuestUI8EH( questId, value ); + break; + } + case 10: + { + player.setQuestUI8EL( questId, value ); + break; + } + case 11: + { + player.setQuestUI8FH( questId, value ); + break; + } + case 12: + { + player.setQuestUI8FL( questId, value ); + break; + } + } + } else if( subCommand == "BitFlag" ) { uint16_t questId; @@ -604,6 +678,18 @@ void Sapphire::World::Manager::DebugCommandMgr::get( char* data, Entity::Player& instance->getBranch() ); } } + else if( ( subCommand == "poprange" ) ) + { + uint32_t id, param; + sscanf( params.c_str(), "%u", &id ); + + auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); + auto pPopRange = instanceObjectCache.getPopRange( player.getCurrentTerritory()->getTerritoryTypeId(), id ); + if( pPopRange ) + { + player.sendNotice( "x:{}, y:{}, z:{}", pPopRange->header.transform.translation.x, pPopRange->header.transform.translation.y, pPopRange->header.transform.translation.z ); + } + } else { player.sendUrgent( "{0} is not a valid GET command.", subCommand ); diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 9df18782..eda3260f 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -104,15 +104,21 @@ bool Sapphire::World::Manager::TerritoryMgr::isInstanceContentTerritory( uint32_ auto intendedUse = pTeri->territoryIntendedUse; return intendedUse == TerritoryIntendedUse::AllianceRaid || - intendedUse == TerritoryIntendedUse::BeforeTrialDung || - intendedUse == TerritoryIntendedUse::Trial || - intendedUse == TerritoryIntendedUse::Dungeon || - intendedUse == TerritoryIntendedUse::OpenWorldInstanceBattle || - intendedUse == TerritoryIntendedUse::PalaceOfTheDead || - intendedUse == TerritoryIntendedUse::RaidFights || - intendedUse == TerritoryIntendedUse::Raids || - intendedUse == TerritoryIntendedUse::TreasureMapInstance || - intendedUse == TerritoryIntendedUse::EventTrial; + intendedUse == TerritoryIntendedUse::BeforeTrialDung || + intendedUse == TerritoryIntendedUse::Trial || + intendedUse == TerritoryIntendedUse::Dungeon || + intendedUse == TerritoryIntendedUse::OpenWorldInstanceBattle || + intendedUse == TerritoryIntendedUse::PalaceOfTheDead || + intendedUse == TerritoryIntendedUse::RaidFights || + intendedUse == TerritoryIntendedUse::Raids || + intendedUse == TerritoryIntendedUse::TreasureMapInstance || + intendedUse == TerritoryIntendedUse::EventTrial || + intendedUse == TerritoryIntendedUse::DiademV1 || + intendedUse == TerritoryIntendedUse::DiademV2 || + intendedUse == TerritoryIntendedUse::DiademV3 || + intendedUse == TerritoryIntendedUse::Eureka || + intendedUse == TerritoryIntendedUse::Bozja || + intendedUse == TerritoryIntendedUse::Wedding; } bool Sapphire::World::Manager::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const @@ -123,9 +129,9 @@ bool Sapphire::World::Manager::TerritoryMgr::isPrivateTerritory( uint32_t territ return false; return pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea || - pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn || - pTeri->territoryIntendedUse == TerritoryIntendedUse::JailArea || - pTeri->territoryIntendedUse == TerritoryIntendedUse::MSQPrivateArea; + pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn || + pTeri->territoryIntendedUse == TerritoryIntendedUse::JailArea || + pTeri->territoryIntendedUse == TerritoryIntendedUse::MSQPrivateArea; } bool Sapphire::World::Manager::TerritoryMgr::isInternalEstateTerritory( uint32_t territoryTypeId ) const @@ -146,10 +152,13 @@ bool Sapphire::World::Manager::TerritoryMgr::isDefaultTerritory( uint32_t territ return false; return pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn || - pTeri->territoryIntendedUse == TerritoryIntendedUse::Town || - pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorld || - pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea; - + pTeri->territoryIntendedUse == TerritoryIntendedUse::Town || + pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorld || + pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea || + pTeri->territoryIntendedUse == TerritoryIntendedUse::GoldSaucer || + pTeri->territoryIntendedUse == TerritoryIntendedUse::ChocoboSquare || + pTeri->territoryIntendedUse == TerritoryIntendedUse::MSQPrivateArea || + pTeri->territoryIntendedUse == TerritoryIntendedUse::BeforeTrialDung; } bool Sapphire::World::Manager::TerritoryMgr::isHousingTerritory( uint32_t territoryTypeId ) const @@ -261,9 +270,9 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createTerritoryIn if( !isValidTerritory( territoryTypeId ) ) return nullptr; -// nb: disabled for now because there's not a real reason to have this constraint, makes testing some stuff easier too -// if( isInstanceContentTerritory( territoryTypeId ) ) -// return nullptr; + // nb: disabled for now because there's not a real reason to have this constraint, makes testing some stuff easier too + // if( isInstanceContentTerritory( territoryTypeId ) ) + // return nullptr; auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); auto pTeri = getTerritoryDetail( territoryTypeId ); @@ -327,8 +336,8 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createQuestBattle if( !pQuestInfo ) return nullptr; - if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) ) - return nullptr; + //if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) ) + // return nullptr; auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType ); @@ -361,8 +370,8 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createInstanceCon if( !pInstanceContent ) return nullptr; - if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) ) - return nullptr; + //if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) ) + // return nullptr; auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType ); @@ -670,7 +679,7 @@ void Sapphire::World::Manager::TerritoryMgr::updateTerritoryInstances( uint64_t } Sapphire::World::Manager::TerritoryMgr::InstanceIdList - Sapphire::World::Manager::TerritoryMgr::getInstanceContentIdList( uint16_t instanceContentId ) const +Sapphire::World::Manager::TerritoryMgr::getInstanceContentIdList( uint16_t instanceContentId ) const { std::vector< uint32_t > idList; auto zoneMap = m_instanceContentIdToInstanceMap.find( instanceContentId ); diff --git a/src/world/Manager/TerritoryMgr.h b/src/world/Manager/TerritoryMgr.h index ff9dd285..8cb4dcb2 100644 --- a/src/world/Manager/TerritoryMgr.h +++ b/src/world/Manager/TerritoryMgr.h @@ -48,8 +48,10 @@ namespace Sapphire::World::Manager MSQPrivateArea = 15, Raids = 16, RaidFights = 17, + ChocoboSquare = 19, ChocoboTutorial = 21, Wedding = 22, + GoldSaucer = 23, DiademV1 = 26, BeginnerTutorial = 27, PvPTheFeast = 28, diff --git a/src/world/Network/Handlers/ActionHandler.cpp b/src/world/Network/Handlers/ActionHandler.cpp index cbb412b0..4576a0a8 100644 --- a/src/world/Network/Handlers/ActionHandler.cpp +++ b/src/world/Network/Handlers/ActionHandler.cpp @@ -67,6 +67,14 @@ void Sapphire::Network::GameConnection::actionHandler( const Packets::FFXIVARR_P break; } + case Common::SkillType::EventItem: + { + auto action = exdData.get< Data::EventItem >( actionId ); + assert( action ); + actionMgr.handleEventItemAction( player, actionId, action, sequence, targetId ); + break; + } + case Common::SkillType::MountSkill: { auto action = exdData.get< Data::Action >( 4 ); diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index ef520bdc..25dd4efb 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -109,7 +109,9 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX else player.setAutoattack( false ); - player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) ); + // the client seems to ignore source actor of this packet and always set auto-attack on itself. causing everyone on screen take their weapons out + player.queuePacket( makeActorControl( player.getId(), 1, param11, 1 ) ); + //player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) ); break; } @@ -523,6 +525,18 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } break; } + case ClientTriggerType::CameraMode: + { + if( param11 == 1 ) + { + player.setOnlineStatusMask( player.getOnlineStatusMask() | 0x0000000000040000 ); + } + else + { + player.setOnlineStatusMask( player.getOnlineStatusMask() & 0xFFFFFFFFFFFBFFFF ); + } + break; + } default: { Logger::debug( "[{0}] Unhandled action: {1:04X}", m_pSession->getId(), commandId ); diff --git a/src/world/Network/Handlers/EventHandlers.cpp b/src/world/Network/Handlers/EventHandlers.cpp index 70d28f95..893ae18f 100644 --- a/src/world/Network/Handlers/EventHandlers.cpp +++ b/src/world/Network/Handlers/EventHandlers.cpp @@ -298,17 +298,20 @@ void Sapphire::Network::GameConnection::eventYieldHandler( const Packets::FFXIVA auto pParam = reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 + 8 ] ); std::vector< uint32_t > param; + auto paramSize = 0; switch( opcode ) { - case EventYield16Handler: - { - for( int i = 0; i < 16; i++ ) - { - param.push_back( pParam[ i ] ); - } + case EventYield2Handler: + paramSize = 2; break; - } + case EventYield16Handler: + paramSize = 16; + break; + } + for( int i = 0; i < paramSize; i++ ) + { + param.push_back( pParam[ i ] ); } std::string eventName = "onEventYield";