diff --git a/README.md b/README.md index a47feebd..56f7d71d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Windows Build Status](https://ci.appveyor.com/api/projects/status/lil7lxa3ty165emm?svg=true)](https://ci.appveyor.com/project/SapphireMordred/Sapphire) -Sapphire is a FINAL FANTASY XIV Server Emulator. This version targets FFXIV v5.58. +Sapphire is a FINAL FANTASY XIV Server Emulator. This version targets FFXIV v6.58 hotfix 2. It is a **research project** to learn how retail servers work and currently not production code; at this time it is **insecure** (use throwaway passwords for accounts) and you should expect a lot of things unimplemented or broken (of course contributions are always welcome). diff --git a/src/common/Common.h b/src/common/Common.h index fcc8d4e9..61a69cc4 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -25,8 +25,8 @@ namespace Sapphire::Common const uint16_t MAX_PLAYER_LEVEL = 90; const uint8_t CURRENT_EXPANSION_ID = 4; - const uint8_t CLASSJOB_TOTAL = 40; - const uint8_t CLASSJOB_SLOTS = 30; + const uint8_t CLASSJOB_TOTAL = 42; + const uint8_t CLASSJOB_SLOTS = 32; const uint8_t TOWN_COUNT = 7; @@ -68,11 +68,20 @@ namespace Sapphire::Common French = 8 }; - enum TellFlags : uint8_t + enum ChatFromType : uint8_t { GmTellMsg = 0x4, }; + enum ChatChannelType : uint16_t + { + CWLinkshellChat = 0x0, + PartyChat = 0x1, + LinkshellChat = 0x2, + FreeCompanyChat = 0x3, + NoviceNetworkChat = 0x4 + }; + enum BNpcType : uint8_t { Friendly = 0, @@ -694,10 +703,10 @@ namespace Sapphire::Common MpGain = 11, TpLoss = 12, TpGain = 13, - GpGain = 14, - ApplyStatusEffectTarget = 15, - ApplyStatusEffectSource = 16, // effect entry on target but buff applies to source, like storm's eye - StatusNoEffect = 20, // shifted one up from 5.18 + //GpGain = 14, + ApplyStatusEffectTarget = 14, // shifted up again 6.x, need to recheck everything I guess + ApplyStatusEffectSource = 15, + StatusNoEffect = 20, /*! * @brief Tells the client that it should show combo indicators on actions. * @@ -705,10 +714,10 @@ namespace Sapphire::Common * @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. + StartActionCombo = 27, + ComboSucceed = 28, Knockback = 33, - Mount = 40, // shifted one down from 5.18 + Mount = 40, VFX = 59, // links to VFX sheet }; @@ -804,6 +813,22 @@ namespace Sapphire::Common InvincibilityIgnoreDamage, }; + enum InviteReplyType : int32_t + { + DENY = 0x0, + ACCEPT = 0x1, + CANCEL = 0x2, + }; + + enum InviteUpdateType : uint8_t + { + NEW_INVITE = 0x01, + INVITE_CANCEL = 0x02, + JOINED_PARTY = 0x03, + ACCEPT_INVITE = 0x04, + REJECT_INVITE = 0x05, + }; + enum PlayerStateFlag : uint8_t { HideUILockChar = 0, // as the name suggests, hides the ui and logs the char... @@ -1340,6 +1365,12 @@ namespace Sapphire::Common GetGil = 9, // p1: gil EmptyCoffer = 11, // seems like no param }; + + enum ItemFlag + { + FlagNone = 0, + FlagHq = 1, + }; } #endif diff --git a/src/common/CommonGen.h b/src/common/CommonGen.h index 01d9d7ca..7d1d012c 100644 --- a/src/common/CommonGen.h +++ b/src/common/CommonGen.h @@ -118,7 +118,15 @@ enum class BaseParam: uint8_t //BeastReputationRank.exd enum class BeastReputationRank: uint8_t { - None = 0, Neutral = 1, Recognized = 2, Friendly = 3, Trusted = 4, Respected = 5, Honored = 6, Sworn = 7, Allied = 8, + None = 0, + Neutral = 1, + Recognized = 2, + Friendly = 3, + Trusted = 4, + Respected = 5, + Honored = 6, + Sworn = 7, + Allied = 8, }; /////////////////////////////////////////////////////////// @@ -190,6 +198,8 @@ enum class ClassJob: uint8_t Dancer = 38, Reaper = 39, Sage = 40, + //Viper = 41, + //Pictomancer = 42, }; /////////////////////////////////////////////////////////// @@ -227,13 +237,22 @@ enum class ContentType: uint8_t UltimateRaids = 28, //5 = 29, VAndCDungeonFinder = 30, + OceanFishing = 31, + TripleTriad = 32, + TheHunt = 33, + Fishing = 34, + GATE = 35, + //6 = 36, }; /////////////////////////////////////////////////////////// //EmoteCategory.exd enum class EmoteCategory: uint8_t { - None = 0, General = 1, Special = 2, Expressions = 3, + None = 0, + General = 1, + Special = 2, + Expressions = 3, //1 = 4, }; @@ -241,14 +260,21 @@ enum class EmoteCategory: uint8_t //ExVersion.exd enum class ExVersion: uint8_t { - ARealmReborn = 0, Heavensward = 1, Stormblood = 2, Shadowbringers = 3, Endwalker = 4, + ARealmReborn = 0, + Heavensward = 1, + Stormblood = 2, + Shadowbringers = 3, + Endwalker = 4, }; /////////////////////////////////////////////////////////// //GrandCompany.exd enum class GrandCompany: uint8_t { - None = 0, Maelstrom = 1, OrderoftheTwinAdder = 2, ImmortalFlames = 3, + None = 0, + Maelstrom = 1, + OrderoftheTwinAdder = 2, + ImmortalFlames = 3, }; /////////////////////////////////////////////////////////// @@ -384,6 +410,8 @@ enum class ItemUICategory: uint8_t DancersArm = 107, ReapersArm = 108, SagesArm = 109, + //VipersArm = 110, + //PictomancersArm = 111, }; /////////////////////////////////////////////////////////// @@ -469,7 +497,7 @@ enum class ItemSearchCategory: uint8_t DarkKnightsArms = 76, MachinistsArms = 77, AstrologiansArms = 78, - AirshipAndSubmersibleComponents = 79, + AirshipSubmersibleComponents = 79, OrchestrionComponents = 80, GardeningItems = 81, Paintings = 82, @@ -481,16 +509,16 @@ enum class ItemSearchCategory: uint8_t ReapersArms = 88, SagesArms = 89, RegistrableMiscellany = 90, - /*1 = 91, - 2 = 92, - 3 = 93, - 4 = 94, - 5 = 95, - 6 = 96, - 7 = 97, - 8 = 98, - 9 = 99, - 10 = 100,*/ + //1 = 91, + //2 = 92, + //3 = 93, + //4 = 94, + //5 = 95, + //6 = 96, + //7 = 97, + //8 = 98, + //9 = 99, + //10 = 100, }; /////////////////////////////////////////////////////////// @@ -551,7 +579,15 @@ enum class OnlineStatus: uint8_t //Race.exd enum class Race: uint8_t { - None = 0, Hyur = 1, Elezen = 2, Lalafell = 3, Miqote = 4, Roegadyn = 5, AuRa = 6, Hrothgar = 7, Viera = 8, + None = 0, + Hyur = 1, + Elezen = 2, + Lalafell = 3, + Miqote = 4, + Roegadyn = 5, + AuRa = 6, + Hrothgar = 7, + Viera = 8, }; /////////////////////////////////////////////////////////// @@ -581,11 +617,18 @@ enum class Tribe: uint8_t //Town.exd enum class Town: uint8_t { - Nowheresville = 0, LimsaLominsa = 1, Gridania = 2, Uldah = 3, Ishgard = 4, //= 5, + Nowheresville = 0, + LimsaLominsa = 1, + Gridania = 2, + Uldah = 3, + Ishgard = 4, + // = 5, //1 = 6, - Kugane = 7, //2 = 8, + Kugane = 7, + //2 = 8, //3 = 9, - Crystarium = 10, //4 = 11, + Crystarium = 10, + //4 = 11, OldSharlayan = 12, //5 = 13, }; @@ -773,6 +816,8 @@ enum class Weather: uint8_t DimensionalDisruption6 = 176, Pandaemonium3 = 177, Pandaemonium4 = 178, + LyricalCatharsis = 179, + Vacuity3 = 180, }; /////////////////////////////////////////////////////////// @@ -792,7 +837,7 @@ enum class HousingAppeal: uint8_t Sanctum = 10, Venue = 11, Florist = 12, - //= 13, + // = 13, Library = 14, PhotoStudio = 15, HauntedHouse = 16, diff --git a/src/common/Database/ZoneDbConnection.cpp b/src/common/Database/ZoneDbConnection.cpp index 773f8cef..a23a1a72 100644 --- a/src/common/Database/ZoneDbConnection.cpp +++ b/src/common/Database/ZoneDbConnection.cpp @@ -241,7 +241,7 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements() CONNECTION_BOTH ); prepareStatement( CHARA_ITEMGLOBAL_UP, - "UPDATE charaglobalitem SET stack = ?, durability = ?, stain = ? WHERE ItemId = ?;", + "UPDATE charaglobalitem SET stack = ?, durability = ?, flags = ?, reservedFlag = ?, stain = ? WHERE ItemId = ?;", CONNECTION_BOTH ); prepareStatement( CHARA_ITEMGLOBAL_DELETE, diff --git a/src/common/Exd/ExdDataGenerated.cpp b/src/common/Exd/ExdDataGenerated.cpp index c4249c1c..304e7988 100644 --- a/src/common/Exd/ExdDataGenerated.cpp +++ b/src/common/Exd/ExdDataGenerated.cpp @@ -318,13 +318,13 @@ Sapphire::Data::Aetheryte::Aetheryte( uint32_t row_id, Sapphire::Data::ExdDataGe level.push_back( exdData->getField< uint32_t >( row, 13 ) ); level.push_back( exdData->getField< uint32_t >( row, 14 ) ); isAetheryte = exdData->getField< bool >( row, 15 ); - aethernetGroup = exdData->getField< uint8_t >( row, 17 ); - invisible = exdData->getField< bool >( row, 18 ); - requiredQuest = exdData->getField< uint32_t >( row, 19 ); - map = exdData->getField< uint16_t >( row, 20 ); - aetherstreamX = exdData->getField< int16_t >( row, 21 ); - aetherstreamY = exdData->getField< int16_t >( row, 22 ); - order = exdData->getField< uint8_t >( row, 23 ); + aethernetGroup = exdData->getField< uint8_t >( row, 18 ); + invisible = exdData->getField< bool >( row, 19 ); + requiredQuest = exdData->getField< uint32_t >( row, 20 ); + map = exdData->getField< uint16_t >( row, 21 ); + aetherstreamX = exdData->getField< int16_t >( row, 22 ); + aetherstreamY = exdData->getField< int16_t >( row, 23 ); + order = exdData->getField< uint8_t >( row, 24 ); } Sapphire::Data::AetheryteSystemDefine::AetheryteSystemDefine( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -968,17 +968,17 @@ Sapphire::Data::BeastTribe::BeastTribe( uint32_t row_id, Sapphire::Data::ExdData icon = exdData->getField< uint32_t >( row, 4 ); maxRank = exdData->getField< uint8_t >( row, 5 ); expansion = exdData->getField< uint8_t >( row, 6 ); - currencyItem = exdData->getField< uint32_t >( row, 7 ); - displayOrder = exdData->getField< uint8_t >( row, 8 ); - name = exdData->getField< std::string >( row, 9 ); - adjective = exdData->getField< int8_t >( row, 10 ); - plural = exdData->getField< std::string >( row, 11 ); - possessivePronoun = exdData->getField< int8_t >( row, 12 ); - startsWithVowel = exdData->getField< int8_t >( row, 13 ); - pronoun = exdData->getField< int8_t >( row, 14 ); - article = exdData->getField< int8_t >( row, 15 ); - dEF = exdData->getField< int8_t >( row, 16 ); - nameRelation = exdData->getField< std::string >( row, 17 ); + currencyItem = exdData->getField< uint32_t >( row, 8 ); + displayOrder = exdData->getField< uint8_t >( row, 9 ); + name = exdData->getField< std::string >( row, 10 ); + adjective = exdData->getField< int8_t >( row, 11 ); + plural = exdData->getField< std::string >( row, 12 ); + possessivePronoun = exdData->getField< int8_t >( row, 13 ); + startsWithVowel = exdData->getField< int8_t >( row, 14 ); + pronoun = exdData->getField< int8_t >( row, 15 ); + article = exdData->getField< int8_t >( row, 16 ); + dEF = exdData->getField< int8_t >( row, 17 ); + nameRelation = exdData->getField< std::string >( row, 18 ); } Sapphire::Data::Behavior::Behavior( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1297,7 +1297,7 @@ Sapphire::Data::BuddySkill::BuddySkill( uint32_t row_id, Sapphire::Data::ExdData Sapphire::Data::Cabinet::Cabinet( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_CabinetDat.get_row( row_id ); - item = exdData->getField< int32_t >( row, 0 ); + item = exdData->getField< uint32_t >( row, 0 ); order = exdData->getField< uint16_t >( row, 1 ); category = exdData->getField< uint8_t >( row, 2 ); } @@ -1306,8 +1306,9 @@ Sapphire::Data::CabinetCategory::CabinetCategory( uint32_t row_id, Sapphire::Dat { auto row = exdData->m_CabinetCategoryDat.get_row( row_id ); menuOrder = exdData->getField< uint8_t >( row, 0 ); - icon = exdData->getField< int32_t >( row, 1 ); - category = exdData->getField< int32_t >( row, 2 ); + hideOrder = exdData->getField< uint8_t >( row, 1 ); + icon = exdData->getField< int32_t >( row, 2 ); + category = exdData->getField< int32_t >( row, 3 ); } Sapphire::Data::Calendar::Calendar( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1399,8 +1400,8 @@ Sapphire::Data::CharaCardBase::CharaCardBase( uint32_t row_id, Sapphire::Data::E image = exdData->getField< int32_t >( row, 0 ); fontColor = exdData->getField< uint8_t >( row, 1 ); unlockCondition = exdData->getField< uint16_t >( row, 5 ); - sortKey = exdData->getField< uint16_t >( row, 6 ); - name = exdData->getField< std::string >( row, 7 ); + sortKey = exdData->getField< uint16_t >( row, 7 ); + name = exdData->getField< std::string >( row, 8 ); } Sapphire::Data::CharaCardDecoration::CharaCardDecoration( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1409,8 +1410,13 @@ Sapphire::Data::CharaCardDecoration::CharaCardDecoration( uint32_t row_id, Sapph category = exdData->getField< uint8_t >( row, 0 ); image = exdData->getField< int32_t >( row, 2 ); unlockCondition = exdData->getField< uint16_t >( row, 4 ); - sortKey = exdData->getField< uint16_t >( row, 5 ); - name = exdData->getField< std::string >( row, 6 ); + sortKey = exdData->getField< uint16_t >( row, 6 ); + name = exdData->getField< std::string >( row, 7 ); +} + +Sapphire::Data::CharaCardDesignCategory::CharaCardDesignCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CharaCardDesignCategoryDat.get_row( row_id ); } Sapphire::Data::CharaCardDesignPreset::CharaCardDesignPreset( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1440,8 +1446,8 @@ Sapphire::Data::CharaCardHeader::CharaCardHeader( uint32_t row_id, Sapphire::Dat bottomImage = exdData->getField< int32_t >( row, 1 ); fontColor = exdData->getField< uint8_t >( row, 2 ); unlockCondition = exdData->getField< uint16_t >( row, 6 ); - sortKey = exdData->getField< uint8_t >( row, 7 ); - name = exdData->getField< std::string >( row, 8 ); + sortKey = exdData->getField< uint8_t >( row, 8 ); + name = exdData->getField< std::string >( row, 9 ); } Sapphire::Data::CharaCardPlayStyle::CharaCardPlayStyle( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -2351,6 +2357,11 @@ Sapphire::Data::ContentFinderConditionTransient::ContentFinderConditionTransient description = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::ContentFinderParamTable::ContentFinderParamTable( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_ContentFinderParamTableDat.get_row( row_id, subRow ); +} + Sapphire::Data::ContentGauge::ContentGauge( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ContentGaugeDat.get_row( row_id ); @@ -2376,6 +2387,11 @@ Sapphire::Data::ContentMemberType::ContentMemberType( uint32_t row_id, Sapphire: rangedPerParty = exdData->getField< uint8_t >( row, 13 ); } +Sapphire::Data::ContentNpc::ContentNpc( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_ContentNpcDat.get_row( row_id ); +} + Sapphire::Data::ContentNpcTalk::ContentNpcTalk( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ContentNpcTalkDat.get_row( row_id ); @@ -2409,16 +2425,16 @@ Sapphire::Data::ContentRoulette::ContentRoulette( uint32_t row_id, Sapphire::Dat isPvP = exdData->getField< bool >( row, 10 ); requiredLevel = exdData->getField< uint8_t >( row, 11 ); itemLevelRequired = exdData->getField< uint16_t >( row, 13 ); - icon = exdData->getField< uint32_t >( row, 15 ); - contentRouletteRoleBonus = exdData->getField< uint8_t >( row, 16 ); - rewardTomeA = exdData->getField< uint16_t >( row, 17 ); - rewardTomeB = exdData->getField< uint16_t >( row, 18 ); - rewardTomeC = exdData->getField< uint16_t >( row, 19 ); - sortKey = exdData->getField< uint8_t >( row, 23 ); - contentMemberType = exdData->getField< uint8_t >( row, 25 ); - requireAllDuties = exdData->getField< bool >( row, 36 ); - contentRouletteOpenRule = exdData->getField< uint8_t >( row, 38 ); - instanceContent = exdData->getField< uint16_t >( row, 39 ); + icon = exdData->getField< uint32_t >( row, 16 ); + contentRouletteRoleBonus = exdData->getField< uint8_t >( row, 17 ); + rewardTomeA = exdData->getField< uint16_t >( row, 18 ); + rewardTomeB = exdData->getField< uint16_t >( row, 19 ); + rewardTomeC = exdData->getField< uint16_t >( row, 20 ); + sortKey = exdData->getField< uint8_t >( row, 24 ); + contentMemberType = exdData->getField< uint8_t >( row, 26 ); + requireAllDuties = exdData->getField< bool >( row, 37 ); + contentRouletteOpenRule = exdData->getField< uint8_t >( row, 39 ); + instanceContent = exdData->getField< uint16_t >( row, 40 ); } Sapphire::Data::ContentRouletteOpenRule::ContentRouletteOpenRule( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -2456,16 +2472,16 @@ Sapphire::Data::ContentsNote::ContentsNote( uint32_t row_id, Sapphire::Data::Exd Sapphire::Data::ContentsTutorial::ContentsTutorial( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ContentsTutorialDat.get_row( row_id ); - name = exdData->getField< std::string >( row, 0 ); - description = exdData->getField< std::string >( row, 1 ); + page.push_back( exdData->getField< int32_t >( row, 0 ) ); + page.push_back( exdData->getField< int32_t >( row, 1 ) ); page.push_back( exdData->getField< int32_t >( row, 2 ) ); page.push_back( exdData->getField< int32_t >( row, 3 ) ); page.push_back( exdData->getField< int32_t >( row, 4 ) ); page.push_back( exdData->getField< int32_t >( row, 5 ) ); page.push_back( exdData->getField< int32_t >( row, 6 ) ); page.push_back( exdData->getField< int32_t >( row, 7 ) ); - page.push_back( exdData->getField< int32_t >( row, 8 ) ); - page.push_back( exdData->getField< int32_t >( row, 9 ) ); + name = exdData->getField< std::string >( row, 8 ); + description = exdData->getField< std::string >( row, 9 ); } Sapphire::Data::ContentsTutorialPage::ContentsTutorialPage( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -2596,6 +2612,41 @@ Sapphire::Data::CreditListText::CreditListText( uint32_t row_id, Sapphire::Data: name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::CSBonusContent::CSBonusContent( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusContentDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusContentIdentifier::CSBonusContentIdentifier( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusContentIdentifierDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusContentType::CSBonusContentType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusContentTypeDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusMission::CSBonusMission( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusMissionDat.get_row( row_id, subRow ); +} + +Sapphire::Data::CSBonusMissionType::CSBonusMissionType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusMissionTypeDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusSeason::CSBonusSeason( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusSeasonDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusTextData::CSBonusTextData( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusTextDataDat.get_row( row_id ); +} + Sapphire::Data::CustomTalk::CustomTalk( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_CustomTalkDat.get_row( row_id ); @@ -3347,6 +3398,12 @@ Sapphire::Data::EurekaAethernet::EurekaAethernet( uint32_t row_id, Sapphire::Dat location = exdData->getField< uint16_t >( row, 0 ); } +Sapphire::Data::EurekaDungeonPortal::EurekaDungeonPortal( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_EurekaDungeonPortalDat.get_row( row_id, subRow ); + levelId = exdData->getField< uint32_t >( row, 0 ); +} + Sapphire::Data::EurekaGrowData::EurekaGrowData( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_EurekaGrowDataDat.get_row( row_id ); @@ -3479,7 +3536,7 @@ Sapphire::Data::EventIconPriority::EventIconPriority( uint32_t row_id, Sapphire: Sapphire::Data::EventIconPriorityPair::EventIconPriorityPair( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_EventIconPriorityPairDat.get_row( row_id ); - icon1 = exdData->getField< uint32_t >( row, 0 ); + icon = exdData->getField< uint32_t >( row, 0 ); } Sapphire::Data::EventIconType::EventIconType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -3841,6 +3898,16 @@ Sapphire::Data::Festival::Festival( uint32_t row_id, Sapphire::Data::ExdDataGene name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::FGSAddon::FGSAddon( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_FGSAddonDat.get_row( row_id ); +} + +Sapphire::Data::FGSStageUI::FGSStageUI( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_FGSStageUIDat.get_row( row_id ); +} + Sapphire::Data::FieldMarker::FieldMarker( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_FieldMarkerDat.get_row( row_id ); @@ -3920,12 +3987,12 @@ Sapphire::Data::FishParameter::FishParameter( uint32_t row_id, Sapphire::Data::E item = exdData->getField< int32_t >( row, 1 ); gatheringItemLevel = exdData->getField< uint16_t >( row, 2 ); oceanStars = exdData->getField< uint8_t >( row, 3 ); - isHidden = exdData->getField< bool >( row, 4 ); - fishingRecordType = exdData->getField< uint8_t >( row, 5 ); - fishingSpot = exdData->getField< uint16_t >( row, 6 ); - gatheringSubCategory = exdData->getField< uint16_t >( row, 7 ); - isInLog = exdData->getField< bool >( row, 8 ); - achievementCredit = exdData->getField< uint32_t >( row, 9 ); + isHidden = exdData->getField< bool >( row, 5 ); + fishingRecordType = exdData->getField< uint8_t >( row, 6 ); + fishingSpot = exdData->getField< uint16_t >( row, 7 ); + gatheringSubCategory = exdData->getField< uint16_t >( row, 8 ); + isInLog = exdData->getField< bool >( row, 9 ); + achievementCredit = exdData->getField< uint32_t >( row, 10 ); } Sapphire::Data::FittingShop::FittingShop( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -4765,6 +4832,11 @@ Sapphire::Data::GFateRideShooting::GFateRideShooting( uint32_t row_id, Sapphire: contentEntry = exdData->getField< uint32_t >( row, 0 ); } +Sapphire::Data::GFateType::GFateType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_GFateTypeDat.get_row( row_id ); +} + Sapphire::Data::GilShop::GilShop( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_GilShopDat.get_row( row_id ); @@ -4799,7 +4871,7 @@ Sapphire::Data::GimmickJump::GimmickJump( uint32_t row_id, Sapphire::Data::ExdDa { auto row = exdData->m_GimmickJumpDat.get_row( row_id ); fallDamage = exdData->getField< uint16_t >( row, 0 ); - height = exdData->getField< int8_t >( row, 1 ); + height = exdData->getField< uint16_t >( row, 1 ); loopMotion = exdData->getField< uint32_t >( row, 2 ); endMotion = exdData->getField< uint32_t >( row, 3 ); startClient = exdData->getField< bool >( row, 4 ); @@ -4912,9 +4984,11 @@ Sapphire::Data::GuildleveAssignment::GuildleveAssignment( uint32_t row_id, Sapph { auto row = exdData->m_GuildleveAssignmentDat.get_row( row_id ); type = exdData->getField< std::string >( row, 0 ); + typeId = exdData->getField< uint8_t >( row, 1 ); assignmentTalk = exdData->getField< uint32_t >( row, 2 ); quest.push_back( exdData->getField< uint32_t >( row, 3 ) ); quest.push_back( exdData->getField< uint32_t >( row, 4 ) ); + grandCompanyRank = exdData->getField< uint8_t >( row, 10 ); } Sapphire::Data::GuildleveAssignmentCategory::GuildleveAssignmentCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -5031,7 +5105,6 @@ Sapphire::Data::HousingFurniture::HousingFurniture( uint32_t row_id, Sapphire::D customTalk = exdData->getField< uint32_t >( row, 6 ); item = exdData->getField< uint32_t >( row, 7 ); destroyOnRemoval = exdData->getField< bool >( row, 8 ); - tooltip = exdData->getField< bool >( row, 9 ); } Sapphire::Data::HousingLandSet::HousingLandSet( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -6554,6 +6627,7 @@ Sapphire::Data::Item::Item( uint32_t row_id, Sapphire::Data::ExdDataGenerated* e alwaysCollectable = exdData->getField< bool >( row, 38 ); aetherialReduce = exdData->getField< uint16_t >( row, 39 ); levelEquip = exdData->getField< uint8_t >( row, 40 ); + requiredPvpRank = exdData->getField< uint8_t >( row, 41 ); equipRestriction = exdData->getField< uint8_t >( row, 42 ); classJobCategory = exdData->getField< uint8_t >( row, 43 ); grandCompany = exdData->getField< uint8_t >( row, 44 ); @@ -6577,6 +6651,11 @@ Sapphire::Data::Item::Item( uint32_t row_id, Sapphire::Data::ExdDataGenerated* e isPvP = exdData->getField< bool >( row, 88 ); subStatCategory = exdData->getField< uint8_t >( row, 89 ); isGlamourous = exdData->getField< bool >( row, 90 ); + for( int i = 0; i < 6; ++i ) + { + param[i].baseparam = exdData->getField< uint8_t >( row, 59 + i * 2 ); + param[i].value = exdData->getField< int16_t >( row, 60 + i * 2 ); + } } Sapphire::Data::ItemAction::ItemAction( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -6808,6 +6887,11 @@ Sapphire::Data::JournalSection::JournalSection( uint32_t row_id, Sapphire::Data: name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::KineDriverOffGroup::KineDriverOffGroup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_KineDriverOffGroupDat.get_row( row_id ); +} + Sapphire::Data::Knockback::Knockback( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_KnockbackDat.get_row( row_id ); @@ -7295,11 +7379,18 @@ Sapphire::Data::MinionSkillType::MinionSkillType( uint32_t row_id, Sapphire::Dat name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::MirageStoreSetItem::MirageStoreSetItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_MirageStoreSetItemDat.get_row( row_id ); +} + Sapphire::Data::MJIAnimals::MJIAnimals( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIAnimalsDat.get_row( row_id ); bNpcBase = exdData->getField< uint32_t >( row, 0 ); size = exdData->getField< uint8_t >( row, 1 ); + rarity = exdData->getField< uint8_t >( row, 2 ); + sort = exdData->getField< uint8_t >( row, 3 ); reward.push_back( exdData->getField< uint32_t >( row, 4 ) ); reward.push_back( exdData->getField< uint32_t >( row, 5 ) ); icon = exdData->getField< int32_t >( row, 6 ); @@ -7435,6 +7526,16 @@ Sapphire::Data::MJICraftworksPopularity::MJICraftworksPopularity( uint32_t row_i popularity.push_back( exdData->getField< uint8_t >( row, 78 ) ); popularity.push_back( exdData->getField< uint8_t >( row, 79 ) ); popularity.push_back( exdData->getField< uint8_t >( row, 80 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 81 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 82 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 83 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 84 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 85 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 86 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 87 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 88 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 89 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 90 ) ); } Sapphire::Data::MJICraftworksPopularityType::MJICraftworksPopularityType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7472,7 +7573,11 @@ Sapphire::Data::MJICropSeed::MJICropSeed( uint32_t row_id, Sapphire::Data::ExdDa Sapphire::Data::MJIDisposalShopItem::MJIDisposalShopItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIDisposalShopItemDat.get_row( row_id ); + item = exdData->getField< uint8_t >( row, 0 ); + currency = exdData->getField< uint8_t >( row, 1 ); + count = exdData->getField< uint16_t >( row, 2 ); category = exdData->getField< uint8_t >( row, 3 ); + sort = exdData->getField< uint8_t >( row, 4 ); } Sapphire::Data::MJIDisposalShopUICategory::MJIDisposalShopUICategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7509,9 +7614,11 @@ Sapphire::Data::MJIGatheringItem::MJIGatheringItem( uint32_t row_id, Sapphire::D auto row = exdData->m_MJIGatheringItemDat.get_row( row_id ); item = exdData->getField< uint32_t >( row, 0 ); sort = exdData->getField< uint8_t >( row, 1 ); + tool = exdData->getField< uint8_t >( row, 2 ); x = exdData->getField< int16_t >( row, 3 ); y = exdData->getField< int16_t >( row, 4 ); radius = exdData->getField< uint16_t >( row, 5 ); + map = exdData->getField< uint8_t >( row, 6 ); } Sapphire::Data::MJIGatheringObject::MJIGatheringObject( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7525,6 +7632,7 @@ Sapphire::Data::MJIGatheringObject::MJIGatheringObject( uint32_t row_id, Sapphir Sapphire::Data::MJIGatheringTool::MJIGatheringTool( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIGatheringToolDat.get_row( row_id ); + item = exdData->getField< uint8_t >( row, 0 ); } Sapphire::Data::MJIHudMode::MJIHudMode( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7548,41 +7656,45 @@ Sapphire::Data::MJIItemPouch::MJIItemPouch( uint32_t row_id, Sapphire::Data::Exd item = exdData->getField< uint32_t >( row, 0 ); category = exdData->getField< int32_t >( row, 1 ); crop = exdData->getField< uint8_t >( row, 2 ); + sort = exdData->getField< uint8_t >( row, 3 ); } Sapphire::Data::MJIKeyItem::MJIKeyItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIKeyItemDat.get_row( row_id ); item = exdData->getField< int32_t >( row, 0 ); + sort = exdData->getField< uint8_t >( row, 1 ); } Sapphire::Data::MJILandmark::MJILandmark( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJILandmarkDat.get_row( row_id ); sGB0 = exdData->getField< uint16_t >( row, 3 ); - sGB1 = exdData->getField< uint16_t >( row, 5 ); - sGB2 = exdData->getField< uint16_t >( row, 7 ); - sGB3 = exdData->getField< uint16_t >( row, 9 ); - sGB4 = exdData->getField< uint16_t >( row, 11 ); - material.push_back( exdData->getField< uint16_t >( row, 18 ) ); - material.push_back( exdData->getField< uint16_t >( row, 19 ) ); + sGB1 = exdData->getField< uint16_t >( row, 4 ); + sGB2 = exdData->getField< uint16_t >( row, 5 ); + sGB3 = exdData->getField< uint16_t >( row, 7 ); + sGB4 = exdData->getField< uint16_t >( row, 9 ); + sGB5 = exdData->getField< uint16_t >( row, 11 ); + sGB6 = exdData->getField< uint16_t >( row, 13 ); material.push_back( exdData->getField< uint16_t >( row, 20 ) ); material.push_back( exdData->getField< uint16_t >( row, 21 ) ); material.push_back( exdData->getField< uint16_t >( row, 22 ) ); - amount.push_back( exdData->getField< uint8_t >( row, 23 ) ); - amount.push_back( exdData->getField< uint8_t >( row, 24 ) ); + material.push_back( exdData->getField< uint16_t >( row, 23 ) ); + material.push_back( exdData->getField< uint16_t >( row, 24 ) ); amount.push_back( exdData->getField< uint8_t >( row, 25 ) ); amount.push_back( exdData->getField< uint8_t >( row, 26 ) ); amount.push_back( exdData->getField< uint8_t >( row, 27 ) ); - name = exdData->getField< uint32_t >( row, 28 ); - icon = exdData->getField< uint32_t >( row, 30 ); + amount.push_back( exdData->getField< uint8_t >( row, 28 ) ); + amount.push_back( exdData->getField< uint8_t >( row, 29 ) ); + name = exdData->getField< uint32_t >( row, 30 ); + icon = exdData->getField< uint32_t >( row, 32 ); } Sapphire::Data::MJILandmarkPlace::MJILandmarkPlace( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJILandmarkPlaceDat.get_row( row_id ); name = exdData->getField< uint32_t >( row, 1 ); - sGB = exdData->getField< uint32_t >( row, 2 ); + sGB = exdData->getField< uint32_t >( row, 3 ); } Sapphire::Data::MJILivelyActor::MJILivelyActor( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7613,6 +7725,11 @@ Sapphire::Data::MJIName::MJIName( uint32_t row_id, Sapphire::Data::ExdDataGenera article = exdData->getField< int8_t >( row, 7 ); } +Sapphire::Data::MJINekomimiRequest::MJINekomimiRequest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_MJINekomimiRequestDat.get_row( row_id ); +} + Sapphire::Data::MJIProgress::MJIProgress( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIProgressDat.get_row( row_id ); @@ -8041,6 +8158,21 @@ Sapphire::Data::NotoriousMonster::NotoriousMonster( uint32_t row_id, Sapphire::D bNpcName = exdData->getField< uint32_t >( row, 2 ); } +Sapphire::Data::NotoriousMonsterTerritory::NotoriousMonsterTerritory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_NotoriousMonsterTerritoryDat.get_row( row_id ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 0 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 1 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 2 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 3 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 4 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 5 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 6 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 7 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 8 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 9 ) ); +} + Sapphire::Data::NpcEquip::NpcEquip( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_NpcEquipDat.get_row( row_id ); @@ -8574,10 +8706,13 @@ Sapphire::Data::Quest::Quest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* previousQuest.push_back( exdData->getField< uint32_t >( row, 9 ) ); previousQuest0Sequence = exdData->getField< uint8_t >( row, 10 ); previousQuest.push_back( exdData->getField< uint32_t >( row, 11 ) ); + previousQuest.push_back( exdData->getField< uint32_t >( row, 12 ) ); questLockJoin = exdData->getField< uint8_t >( row, 13 ); questLock.push_back( exdData->getField< uint32_t >( row, 14 ) ); questLock.push_back( exdData->getField< uint32_t >( row, 15 ) ); header = exdData->getField< uint16_t >( row, 16 ); + startTown = exdData->getField< uint8_t >( row, 17 ); + classJobUnlockFlag = exdData->getField< uint8_t >( row, 18 ); classJobUnlock = exdData->getField< uint8_t >( row, 19 ); grandCompany = exdData->getField< uint8_t >( row, 20 ); grandCompanyRank = exdData->getField< uint8_t >( row, 21 ); @@ -10370,6 +10505,9 @@ Sapphire::Data::QuestEventAreaEntranceInfo::QuestEventAreaEntranceInfo( uint32_t Sapphire::Data::QuestLinkMarker::QuestLinkMarker( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_QuestLinkMarkerDat.get_row( row_id, subRow ); + sourceMap = exdData->getField< uint32_t >( row, 0 ); + level = exdData->getField< uint32_t >( row, 1 ); + targetMap = exdData->getField< uint32_t >( row, 2 ); } Sapphire::Data::QuestLinkMarkerIcon::QuestLinkMarkerIcon( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -11233,9 +11371,9 @@ Sapphire::Data::SpearfishingItem::SpearfishingItem( uint32_t row_id, Sapphire::D description = exdData->getField< std::string >( row, 0 ); item = exdData->getField< int32_t >( row, 1 ); gatheringItemLevel = exdData->getField< uint16_t >( row, 2 ); - fishingRecordType = exdData->getField< uint8_t >( row, 4 ); - territoryType = exdData->getField< uint16_t >( row, 5 ); - isVisible = exdData->getField< bool >( row, 7 ); + fishingRecordType = exdData->getField< uint8_t >( row, 5 ); + territoryType = exdData->getField< uint16_t >( row, 6 ); + isVisible = exdData->getField< bool >( row, 8 ); } Sapphire::Data::SpearfishingNotebook::SpearfishingNotebook( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -11327,130 +11465,130 @@ Sapphire::Data::SpecialShop::SpecialShop( uint32_t row_id, Sapphire::Data::ExdDa questItem.push_back( exdData->getField< int32_t >( row, 1258 ) ); questItem.push_back( exdData->getField< int32_t >( row, 1259 ) ); questItem.push_back( exdData->getField< int32_t >( row, 1260 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1441 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1442 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1443 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1444 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1445 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1446 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1447 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1448 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1449 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1450 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1451 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1452 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1453 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1454 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1455 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1456 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1457 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1458 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1459 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1460 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1461 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1462 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1463 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1464 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1465 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1466 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1467 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1468 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1469 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1470 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1471 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1472 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1473 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1474 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1475 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1476 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1477 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1478 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1479 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1480 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1481 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1482 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1483 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1484 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1485 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1486 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1487 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1488 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1489 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1490 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1491 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1492 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1493 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1494 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1495 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1496 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1497 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1498 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1499 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1500 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1561 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1562 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1563 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1564 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1565 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1566 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1567 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1568 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1569 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1570 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1571 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1572 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1573 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1574 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1575 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1576 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1577 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1578 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1579 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1580 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1581 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1582 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1583 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1584 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1585 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1586 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1587 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1588 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1589 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1590 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1591 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1592 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1593 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1594 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1595 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1596 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1597 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1598 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1599 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1600 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1601 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1602 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1603 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1604 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1605 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1606 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1607 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1608 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1609 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1610 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1611 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1612 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1613 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1614 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1615 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1616 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1617 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1618 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1619 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1620 ) ); - useCurrencyType = exdData->getField< uint8_t >( row, 1621 ); - questUnlock = exdData->getField< uint32_t >( row, 1622 ); - completeText = exdData->getField< int32_t >( row, 1623 ); - notCompleteText = exdData->getField< int32_t >( row, 1624 ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1741 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1742 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1743 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1744 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1745 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1746 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1747 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1748 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1749 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1750 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1751 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1752 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1753 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1754 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1755 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1756 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1757 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1758 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1759 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1760 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1761 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1762 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1763 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1764 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1765 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1766 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1767 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1768 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1769 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1770 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1771 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1772 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1773 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1774 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1775 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1776 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1777 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1778 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1779 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1780 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1781 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1782 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1783 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1784 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1785 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1786 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1787 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1788 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1789 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1790 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1791 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1792 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1793 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1794 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1795 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1796 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1797 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1798 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1799 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1800 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1981 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1982 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1983 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1984 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1985 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1986 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1987 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1988 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1989 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1990 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1991 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1992 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1993 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1994 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1995 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1996 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1997 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1998 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1999 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2000 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2001 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2002 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2003 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2004 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2005 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2006 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2007 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2008 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2009 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2010 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2011 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2012 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2013 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2014 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2015 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2016 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2017 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2018 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2019 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2020 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2021 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2022 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2023 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2024 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2025 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2026 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2027 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2028 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2029 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2030 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2031 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2032 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2033 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2034 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2035 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2036 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2037 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2038 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2039 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2040 ) ); + useCurrencyType = exdData->getField< uint8_t >( row, 2041 ); + questUnlock = exdData->getField< uint32_t >( row, 2042 ); + completeText = exdData->getField< int32_t >( row, 2043 ); + notCompleteText = exdData->getField< int32_t >( row, 2044 ); } Sapphire::Data::SpecialShopItemCategory::SpecialShopItemCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -13495,6 +13633,7 @@ Sapphire::Data::TerritoryType::TerritoryType( uint32_t row_id, Sapphire::Data::E isPvpZone = exdData->getField< bool >( row, 28 ); exVersion = exdData->getField< uint8_t >( row, 29 ); mountSpeed = exdData->getField< uint8_t >( row, 33 ); + notoriousMonsterTerritory = exdData->getField< uint16_t >( row, 42 ); } Sapphire::Data::TerritoryTypeTelepo::TerritoryTypeTelepo( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -13873,6 +14012,11 @@ Sapphire::Data::UIConst::UIConst( uint32_t row_id, Sapphire::Data::ExdDataGenera auto row = exdData->m_UIConstDat.get_row( row_id ); } +Sapphire::Data::UILevelLookup::UILevelLookup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_UILevelLookupDat.get_row( row_id ); +} + Sapphire::Data::VaseFlower::VaseFlower( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_VaseFlowerDat.get_row( row_id ); @@ -13952,7 +14096,7 @@ Sapphire::Data::WarpCondition::WarpCondition( uint32_t row_id, Sapphire::Data::E completeParam = exdData->getField< uint8_t >( row, 1 ); requiredQuest1 = exdData->getField< uint32_t >( row, 2 ); requiredQuest2 = exdData->getField< uint32_t >( row, 3 ); - dRequiredQuest3 = exdData->getField< uint32_t >( row, 4 ); + requiredQuest3 = exdData->getField< uint32_t >( row, 4 ); requiredQuest4 = exdData->getField< uint32_t >( row, 5 ); questReward = exdData->getField< uint16_t >( row, 6 ); classLevel = exdData->getField< uint16_t >( row, 7 ); @@ -14300,6 +14444,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_ChannelingDat = setupDatAccess( "Channeling", xiv::exd::Language::none ); m_CharaCardBaseDat = setupDatAccess( "CharaCardBase", xiv::exd::Language::en ); m_CharaCardDecorationDat = setupDatAccess( "CharaCardDecoration", xiv::exd::Language::en ); + m_CharaCardDesignCategoryDat = setupDatAccess( "CharaCardDesignCategory", xiv::exd::Language::en ); m_CharaCardDesignPresetDat = setupDatAccess( "CharaCardDesignPreset", xiv::exd::Language::en ); m_CharaCardDesignTypeDat = setupDatAccess( "CharaCardDesignType", xiv::exd::Language::none ); m_CharaCardHeaderDat = setupDatAccess( "CharaCardHeader", xiv::exd::Language::en ); @@ -14353,9 +14498,11 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_ContentExActionDat = setupDatAccess( "ContentExAction", xiv::exd::Language::none ); m_ContentFinderConditionDat = setupDatAccess( "ContentFinderCondition", xiv::exd::Language::en ); m_ContentFinderConditionTransientDat = setupDatAccess( "ContentFinderConditionTransient", xiv::exd::Language::en ); + m_ContentFinderParamTableDat = setupDatAccess( "ContentFinderParamTable", xiv::exd::Language::none ); m_ContentGaugeDat = setupDatAccess( "ContentGauge", xiv::exd::Language::en ); m_ContentGaugeColorDat = setupDatAccess( "ContentGaugeColor", xiv::exd::Language::none ); m_ContentMemberTypeDat = setupDatAccess( "ContentMemberType", xiv::exd::Language::none ); + m_ContentNpcDat = setupDatAccess( "ContentNpc", xiv::exd::Language::none ); m_ContentNpcTalkDat = setupDatAccess( "ContentNpcTalk", xiv::exd::Language::none ); m_ContentRandomSelectDat = setupDatAccess( "ContentRandomSelect", xiv::exd::Language::none ); m_ContentRouletteDat = setupDatAccess( "ContentRoulette", xiv::exd::Language::en ); @@ -14377,6 +14524,13 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_CreditCastDat = setupDatAccess( "CreditCast", xiv::exd::Language::en ); m_CreditListDat = setupDatAccess( "CreditList", xiv::exd::Language::none ); m_CreditListTextDat = setupDatAccess( "CreditListText", xiv::exd::Language::en ); + m_CSBonusContentDat = setupDatAccess( "CSBonusContent", xiv::exd::Language::none ); + m_CSBonusContentIdentifierDat = setupDatAccess( "CSBonusContentIdentifier", xiv::exd::Language::none ); + m_CSBonusContentTypeDat = setupDatAccess( "CSBonusContentType", xiv::exd::Language::none ); + m_CSBonusMissionDat = setupDatAccess( "CSBonusMission", xiv::exd::Language::none ); + m_CSBonusMissionTypeDat = setupDatAccess( "CSBonusMissionType", xiv::exd::Language::none ); + m_CSBonusSeasonDat = setupDatAccess( "CSBonusSeason", xiv::exd::Language::none ); + m_CSBonusTextDataDat = setupDatAccess( "CSBonusTextData", xiv::exd::Language::en ); m_CustomTalkDat = setupDatAccess( "CustomTalk", xiv::exd::Language::en ); m_CustomTalkDefineClientDat = setupDatAccess( "CustomTalkDefineClient", xiv::exd::Language::none ); m_CustomTalkNestHandlersDat = setupDatAccess( "CustomTalkNestHandlers", xiv::exd::Language::none ); @@ -14437,6 +14591,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_EquipSlotCategoryDat = setupDatAccess( "EquipSlotCategory", xiv::exd::Language::none ); m_EurekaAetherItemDat = setupDatAccess( "EurekaAetherItem", xiv::exd::Language::en ); m_EurekaAethernetDat = setupDatAccess( "EurekaAethernet", xiv::exd::Language::none ); + m_EurekaDungeonPortalDat = setupDatAccess( "EurekaDungeonPortal", xiv::exd::Language::none ); m_EurekaGrowDataDat = setupDatAccess( "EurekaGrowData", xiv::exd::Language::none ); m_EurekaLogosMixerProbabilityDat = setupDatAccess( "EurekaLogosMixerProbability", xiv::exd::Language::none ); m_EurekaMagiaActionDat = setupDatAccess( "EurekaMagiaAction", xiv::exd::Language::none ); @@ -14479,6 +14634,8 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_FCReputationDat = setupDatAccess( "FCReputation", xiv::exd::Language::en ); m_FCRightsDat = setupDatAccess( "FCRights", xiv::exd::Language::en ); m_FestivalDat = setupDatAccess( "Festival", xiv::exd::Language::none ); + m_FGSAddonDat = setupDatAccess( "FGSAddon", xiv::exd::Language::en ); + m_FGSStageUIDat = setupDatAccess( "FGSStageUI", xiv::exd::Language::none ); m_FieldMarkerDat = setupDatAccess( "FieldMarker", xiv::exd::Language::en ); m_FishingBaitParameterDat = setupDatAccess( "FishingBaitParameter", xiv::exd::Language::none ); m_FishingNoteInfoDat = setupDatAccess( "FishingNoteInfo", xiv::exd::Language::none ); @@ -14540,6 +14697,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_GFateClimbing2ContentDat = setupDatAccess( "GFateClimbing2Content", xiv::exd::Language::none ); m_GFateClimbing2TotemTypeDat = setupDatAccess( "GFateClimbing2TotemType", xiv::exd::Language::none ); m_GFateRideShootingDat = setupDatAccess( "GFateRideShooting", xiv::exd::Language::none ); + m_GFateTypeDat = setupDatAccess( "GFateType", xiv::exd::Language::none ); m_GilShopDat = setupDatAccess( "GilShop", xiv::exd::Language::en ); m_GilShopItemDat = setupDatAccess( "GilShopItem", xiv::exd::Language::none ); m_GimmickAccessorDat = setupDatAccess( "GimmickAccessor", xiv::exd::Language::none ); @@ -14639,6 +14797,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_JournalCategoryDat = setupDatAccess( "JournalCategory", xiv::exd::Language::en ); m_JournalGenreDat = setupDatAccess( "JournalGenre", xiv::exd::Language::en ); m_JournalSectionDat = setupDatAccess( "JournalSection", xiv::exd::Language::en ); + m_KineDriverOffGroupDat = setupDatAccess( "KineDriverOffGroup", xiv::exd::Language::none ); m_KnockbackDat = setupDatAccess( "Knockback", xiv::exd::Language::none ); m_LegacyQuestDat = setupDatAccess( "LegacyQuest", xiv::exd::Language::en ); m_LeveDat = setupDatAccess( "Leve", xiv::exd::Language::en ); @@ -14688,6 +14847,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_MinionRaceDat = setupDatAccess( "MinionRace", xiv::exd::Language::en ); m_MinionRulesDat = setupDatAccess( "MinionRules", xiv::exd::Language::en ); m_MinionSkillTypeDat = setupDatAccess( "MinionSkillType", xiv::exd::Language::en ); + m_MirageStoreSetItemDat = setupDatAccess( "MirageStoreSetItem", xiv::exd::Language::none ); m_MJIAnimalsDat = setupDatAccess( "MJIAnimals", xiv::exd::Language::none ); m_MJIBuildingDat = setupDatAccess( "MJIBuilding", xiv::exd::Language::none ); m_MJIBuildingPlaceDat = setupDatAccess( "MJIBuildingPlace", xiv::exd::Language::none ); @@ -14717,6 +14877,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_MJILivelyActorDat = setupDatAccess( "MJILivelyActor", xiv::exd::Language::none ); m_MJIMinionPopAreasDat = setupDatAccess( "MJIMinionPopAreas", xiv::exd::Language::none ); m_MJINameDat = setupDatAccess( "MJIName", xiv::exd::Language::en ); + m_MJINekomimiRequestDat = setupDatAccess( "MJINekomimiRequest", xiv::exd::Language::none ); m_MJIProgressDat = setupDatAccess( "MJIProgress", xiv::exd::Language::en ); m_MJIRankDat = setupDatAccess( "MJIRank", xiv::exd::Language::none ); m_MJIRecipeDat = setupDatAccess( "MJIRecipe", xiv::exd::Language::none ); @@ -14760,6 +14921,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_NotebookDivisionDat = setupDatAccess( "NotebookDivision", xiv::exd::Language::en ); m_NotebookDivisionCategoryDat = setupDatAccess( "NotebookDivisionCategory", xiv::exd::Language::en ); m_NotoriousMonsterDat = setupDatAccess( "NotoriousMonster", xiv::exd::Language::none ); + m_NotoriousMonsterTerritoryDat = setupDatAccess( "NotoriousMonsterTerritory", xiv::exd::Language::none ); m_NpcEquipDat = setupDatAccess( "NpcEquip", xiv::exd::Language::none ); m_NpcYellDat = setupDatAccess( "NpcYell", xiv::exd::Language::en ); m_OmenDat = setupDatAccess( "Omen", xiv::exd::Language::none ); @@ -14949,6 +15111,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_UDS_PropertyDat = setupDatAccess( "UDS_Property", xiv::exd::Language::none ); m_UIColorDat = setupDatAccess( "UIColor", xiv::exd::Language::none ); m_UIConstDat = setupDatAccess( "UIConst", xiv::exd::Language::none ); + m_UILevelLookupDat = setupDatAccess( "UILevelLookup", xiv::exd::Language::none ); m_VaseFlowerDat = setupDatAccess( "VaseFlower", xiv::exd::Language::none ); m_VFXDat = setupDatAccess( "VFX", xiv::exd::Language::none ); m_VVDDataDat = setupDatAccess( "VVDData", xiv::exd::Language::none ); diff --git a/src/common/Exd/ExdDataGenerated.h b/src/common/Exd/ExdDataGenerated.h index c25f70cc..c5eb2062 100644 --- a/src/common/Exd/ExdDataGenerated.h +++ b/src/common/Exd/ExdDataGenerated.h @@ -134,6 +134,7 @@ struct Carry; struct Channeling; struct CharaCardBase; struct CharaCardDecoration; +struct CharaCardDesignCategory; struct CharaCardDesignPreset; struct CharaCardDesignType; struct CharaCardHeader; @@ -187,9 +188,11 @@ struct ContentEventItem; struct ContentExAction; struct ContentFinderCondition; struct ContentFinderConditionTransient; +struct ContentFinderParamTable; struct ContentGauge; struct ContentGaugeColor; struct ContentMemberType; +struct ContentNpc; struct ContentNpcTalk; struct ContentRandomSelect; struct ContentRoulette; @@ -211,6 +214,13 @@ struct CreditBackImage; struct CreditCast; struct CreditList; struct CreditListText; +struct CSBonusContent; +struct CSBonusContentIdentifier; +struct CSBonusContentType; +struct CSBonusMission; +struct CSBonusMissionType; +struct CSBonusSeason; +struct CSBonusTextData; struct CustomTalk; struct CustomTalkDefineClient; struct CustomTalkNestHandlers; @@ -271,6 +281,7 @@ struct EquipRaceCategory; struct EquipSlotCategory; struct EurekaAetherItem; struct EurekaAethernet; +struct EurekaDungeonPortal; struct EurekaGrowData; struct EurekaLogosMixerProbability; struct EurekaMagiaAction; @@ -313,6 +324,8 @@ struct FCRank; struct FCReputation; struct FCRights; struct Festival; +struct FGSAddon; +struct FGSStageUI; struct FieldMarker; struct FishingBaitParameter; struct FishingNoteInfo; @@ -374,6 +387,7 @@ struct GFateClimbing2; struct GFateClimbing2Content; struct GFateClimbing2TotemType; struct GFateRideShooting; +struct GFateType; struct GilShop; struct GilShopItem; struct GimmickAccessor; @@ -473,6 +487,7 @@ struct JobHudManualPriority; struct JournalCategory; struct JournalGenre; struct JournalSection; +struct KineDriverOffGroup; struct Knockback; struct LegacyQuest; struct Leve; @@ -522,6 +537,7 @@ struct MiniGameTurnBreakStatus; struct MinionRace; struct MinionRules; struct MinionSkillType; +struct MirageStoreSetItem; struct MJIAnimals; struct MJIBuilding; struct MJIBuildingPlace; @@ -551,6 +567,7 @@ struct MJILandmarkPlace; struct MJILivelyActor; struct MJIMinionPopAreas; struct MJIName; +struct MJINekomimiRequest; struct MJIProgress; struct MJIRank; struct MJIRecipe; @@ -594,6 +611,7 @@ struct MYCWarResultNotebook; struct NotebookDivision; struct NotebookDivisionCategory; struct NotoriousMonster; +struct NotoriousMonsterTerritory; struct NpcEquip; struct NpcYell; struct Omen; @@ -783,6 +801,7 @@ struct UDS_Event; struct UDS_Property; struct UIColor; struct UIConst; +struct UILevelLookup; struct VaseFlower; struct VFX; struct VVDData; @@ -2060,7 +2079,7 @@ struct BuddySkill struct Cabinet { - int32_t item; + uint32_t item; uint16_t order; uint8_t category; @@ -2070,6 +2089,7 @@ struct Cabinet struct CabinetCategory { uint8_t menuOrder; + uint8_t hideOrder; int32_t icon; int32_t category; @@ -2122,6 +2142,12 @@ struct CharaCardDecoration CharaCardDecoration( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct CharaCardDesignCategory +{ + + CharaCardDesignCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct CharaCardDesignPreset { uint16_t basePlate; @@ -2801,6 +2827,12 @@ struct ContentFinderConditionTransient ContentFinderConditionTransient( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct ContentFinderParamTable +{ + + ContentFinderParamTable( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct ContentGauge { std::string name; @@ -2829,6 +2861,12 @@ struct ContentMemberType ContentMemberType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct ContentNpc +{ + + ContentNpc( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct ContentNpcTalk { int32_t type; @@ -2907,9 +2945,9 @@ struct ContentsNote struct ContentsTutorial { + std::vector< int32_t > page; std::string name; std::string description; - std::vector< int32_t > page; ContentsTutorial( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -3051,6 +3089,48 @@ struct CreditListText CreditListText( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct CSBonusContent +{ + + CSBonusContent( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusContentIdentifier +{ + + CSBonusContentIdentifier( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusContentType +{ + + CSBonusContentType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusMission +{ + + CSBonusMission( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusMissionType +{ + + CSBonusMissionType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusSeason +{ + + CSBonusSeason( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusTextData +{ + + CSBonusTextData( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct CustomTalk { uint32_t iconActor; @@ -3708,6 +3788,13 @@ struct EurekaAethernet EurekaAethernet( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct EurekaDungeonPortal +{ + uint32_t levelId; + + EurekaDungeonPortal( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct EurekaGrowData { uint16_t baseResistance; @@ -3783,7 +3870,7 @@ struct EventIconPriority struct EventIconPriorityPair { - uint32_t icon1; + uint32_t icon; EventIconPriorityPair( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -4104,6 +4191,18 @@ struct Festival Festival( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct FGSAddon +{ + + FGSAddon( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct FGSStageUI +{ + + FGSStageUI( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct FieldMarker { int32_t vFX; @@ -4698,6 +4797,12 @@ struct GFateRideShooting GFateRideShooting( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct GFateType +{ + + GFateType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct GilShop { std::string name; @@ -4733,7 +4838,7 @@ struct GimmickAccessor struct GimmickJump { uint16_t fallDamage; - int8_t height; + uint16_t height; uint32_t loopMotion; uint32_t endMotion; bool startClient; @@ -4978,7 +5083,6 @@ struct HousingFurniture uint32_t customTalk; uint32_t item; bool destroyOnRemoval; - bool tooltip; HousingFurniture( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -5466,6 +5570,7 @@ struct Item bool alwaysCollectable; uint16_t aetherialReduce; uint8_t levelEquip; + uint8_t requiredPvpRank; uint8_t equipRestriction; uint8_t classJobCategory; uint8_t grandCompany; @@ -5730,6 +5835,12 @@ struct JournalSection JournalSection( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct KineDriverOffGroup +{ + + KineDriverOffGroup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct Knockback { uint8_t distance; @@ -6167,10 +6278,18 @@ struct MinionSkillType MinionSkillType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct MirageStoreSetItem +{ + + MirageStoreSetItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct MJIAnimals { uint32_t bNpcBase; uint8_t size; + uint8_t rarity; + uint8_t sort; std::vector< uint32_t > reward; int32_t icon; @@ -6264,7 +6383,11 @@ struct MJICropSeed struct MJIDisposalShopItem { + uint8_t item; + uint8_t currency; + uint16_t count; uint8_t category; + uint8_t sort; MJIDisposalShopItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6307,9 +6430,11 @@ struct MJIGatheringItem { uint32_t item; uint8_t sort; + uint8_t tool; int16_t x; int16_t y; uint16_t radius; + uint8_t map; MJIGatheringItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6325,6 +6450,7 @@ struct MJIGatheringObject struct MJIGatheringTool { + uint8_t item; MJIGatheringTool( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6351,6 +6477,7 @@ struct MJIItemPouch uint32_t item; int32_t category; uint8_t crop; + uint8_t sort; MJIItemPouch( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6358,6 +6485,7 @@ struct MJIItemPouch struct MJIKeyItem { int32_t item; + uint8_t sort; MJIKeyItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6369,6 +6497,8 @@ struct MJILandmark uint16_t sGB2; uint16_t sGB3; uint16_t sGB4; + uint16_t sGB5; + uint16_t sGB6; std::vector< uint16_t > material; std::vector< uint8_t > amount; uint32_t name; @@ -6416,6 +6546,12 @@ struct MJIName MJIName( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct MJINekomimiRequest +{ + + MJINekomimiRequest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct MJIProgress { std::string vision; @@ -6872,6 +7008,13 @@ struct NotoriousMonster NotoriousMonster( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct NotoriousMonsterTerritory +{ + std::vector< uint16_t > notoriousMonsters; + + NotoriousMonsterTerritory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct NpcEquip { uint64_t modelMainHand; @@ -7554,6 +7697,9 @@ struct QuestEventAreaEntranceInfo struct QuestLinkMarker { + uint32_t sourceMap; + uint32_t level; + uint32_t targetMap; QuestLinkMarker( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -8490,6 +8636,7 @@ struct TerritoryType bool isPvpZone; uint8_t exVersion; uint8_t mountSpeed; + uint16_t notoriousMonsterTerritory; TerritoryType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -8866,6 +9013,12 @@ struct UIConst UIConst( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct UILevelLookup +{ + + UILevelLookup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct VaseFlower { uint32_t item; @@ -8941,7 +9094,7 @@ struct WarpCondition uint8_t completeParam; uint32_t requiredQuest1; uint32_t requiredQuest2; - uint32_t dRequiredQuest3; + uint32_t requiredQuest3; uint32_t requiredQuest4; uint16_t questReward; uint16_t classLevel; @@ -9290,6 +9443,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_ChannelingDat; xiv::exd::Exd m_CharaCardBaseDat; xiv::exd::Exd m_CharaCardDecorationDat; + xiv::exd::Exd m_CharaCardDesignCategoryDat; xiv::exd::Exd m_CharaCardDesignPresetDat; xiv::exd::Exd m_CharaCardDesignTypeDat; xiv::exd::Exd m_CharaCardHeaderDat; @@ -9343,9 +9497,11 @@ struct ZoneSharedGroup xiv::exd::Exd m_ContentExActionDat; xiv::exd::Exd m_ContentFinderConditionDat; xiv::exd::Exd m_ContentFinderConditionTransientDat; + xiv::exd::Exd m_ContentFinderParamTableDat; xiv::exd::Exd m_ContentGaugeDat; xiv::exd::Exd m_ContentGaugeColorDat; xiv::exd::Exd m_ContentMemberTypeDat; + xiv::exd::Exd m_ContentNpcDat; xiv::exd::Exd m_ContentNpcTalkDat; xiv::exd::Exd m_ContentRandomSelectDat; xiv::exd::Exd m_ContentRouletteDat; @@ -9367,6 +9523,13 @@ struct ZoneSharedGroup xiv::exd::Exd m_CreditCastDat; xiv::exd::Exd m_CreditListDat; xiv::exd::Exd m_CreditListTextDat; + xiv::exd::Exd m_CSBonusContentDat; + xiv::exd::Exd m_CSBonusContentIdentifierDat; + xiv::exd::Exd m_CSBonusContentTypeDat; + xiv::exd::Exd m_CSBonusMissionDat; + xiv::exd::Exd m_CSBonusMissionTypeDat; + xiv::exd::Exd m_CSBonusSeasonDat; + xiv::exd::Exd m_CSBonusTextDataDat; xiv::exd::Exd m_CustomTalkDat; xiv::exd::Exd m_CustomTalkDefineClientDat; xiv::exd::Exd m_CustomTalkNestHandlersDat; @@ -9427,6 +9590,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_EquipSlotCategoryDat; xiv::exd::Exd m_EurekaAetherItemDat; xiv::exd::Exd m_EurekaAethernetDat; + xiv::exd::Exd m_EurekaDungeonPortalDat; xiv::exd::Exd m_EurekaGrowDataDat; xiv::exd::Exd m_EurekaLogosMixerProbabilityDat; xiv::exd::Exd m_EurekaMagiaActionDat; @@ -9469,6 +9633,8 @@ struct ZoneSharedGroup xiv::exd::Exd m_FCReputationDat; xiv::exd::Exd m_FCRightsDat; xiv::exd::Exd m_FestivalDat; + xiv::exd::Exd m_FGSAddonDat; + xiv::exd::Exd m_FGSStageUIDat; xiv::exd::Exd m_FieldMarkerDat; xiv::exd::Exd m_FishingBaitParameterDat; xiv::exd::Exd m_FishingNoteInfoDat; @@ -9530,6 +9696,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_GFateClimbing2ContentDat; xiv::exd::Exd m_GFateClimbing2TotemTypeDat; xiv::exd::Exd m_GFateRideShootingDat; + xiv::exd::Exd m_GFateTypeDat; xiv::exd::Exd m_GilShopDat; xiv::exd::Exd m_GilShopItemDat; xiv::exd::Exd m_GimmickAccessorDat; @@ -9629,6 +9796,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_JournalCategoryDat; xiv::exd::Exd m_JournalGenreDat; xiv::exd::Exd m_JournalSectionDat; + xiv::exd::Exd m_KineDriverOffGroupDat; xiv::exd::Exd m_KnockbackDat; xiv::exd::Exd m_LegacyQuestDat; xiv::exd::Exd m_LeveDat; @@ -9678,6 +9846,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_MinionRaceDat; xiv::exd::Exd m_MinionRulesDat; xiv::exd::Exd m_MinionSkillTypeDat; + xiv::exd::Exd m_MirageStoreSetItemDat; xiv::exd::Exd m_MJIAnimalsDat; xiv::exd::Exd m_MJIBuildingDat; xiv::exd::Exd m_MJIBuildingPlaceDat; @@ -9707,6 +9876,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_MJILivelyActorDat; xiv::exd::Exd m_MJIMinionPopAreasDat; xiv::exd::Exd m_MJINameDat; + xiv::exd::Exd m_MJINekomimiRequestDat; xiv::exd::Exd m_MJIProgressDat; xiv::exd::Exd m_MJIRankDat; xiv::exd::Exd m_MJIRecipeDat; @@ -9750,6 +9920,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_NotebookDivisionDat; xiv::exd::Exd m_NotebookDivisionCategoryDat; xiv::exd::Exd m_NotoriousMonsterDat; + xiv::exd::Exd m_NotoriousMonsterTerritoryDat; xiv::exd::Exd m_NpcEquipDat; xiv::exd::Exd m_NpcYellDat; xiv::exd::Exd m_OmenDat; @@ -9939,6 +10110,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_UDS_PropertyDat; xiv::exd::Exd m_UIColorDat; xiv::exd::Exd m_UIConstDat; + xiv::exd::Exd m_UILevelLookupDat; xiv::exd::Exd m_VaseFlowerDat; xiv::exd::Exd m_VFXDat; xiv::exd::Exd m_VVDDataDat; @@ -10081,6 +10253,7 @@ struct ZoneSharedGroup using ChannelingPtr = std::shared_ptr< Channeling >; using CharaCardBasePtr = std::shared_ptr< CharaCardBase >; using CharaCardDecorationPtr = std::shared_ptr< CharaCardDecoration >; + using CharaCardDesignCategoryPtr = std::shared_ptr< CharaCardDesignCategory >; using CharaCardDesignPresetPtr = std::shared_ptr< CharaCardDesignPreset >; using CharaCardDesignTypePtr = std::shared_ptr< CharaCardDesignType >; using CharaCardHeaderPtr = std::shared_ptr< CharaCardHeader >; @@ -10134,9 +10307,11 @@ struct ZoneSharedGroup using ContentExActionPtr = std::shared_ptr< ContentExAction >; using ContentFinderConditionPtr = std::shared_ptr< ContentFinderCondition >; using ContentFinderConditionTransientPtr = std::shared_ptr< ContentFinderConditionTransient >; + using ContentFinderParamTablePtr = std::shared_ptr< ContentFinderParamTable >; using ContentGaugePtr = std::shared_ptr< ContentGauge >; using ContentGaugeColorPtr = std::shared_ptr< ContentGaugeColor >; using ContentMemberTypePtr = std::shared_ptr< ContentMemberType >; + using ContentNpcPtr = std::shared_ptr< ContentNpc >; using ContentNpcTalkPtr = std::shared_ptr< ContentNpcTalk >; using ContentRandomSelectPtr = std::shared_ptr< ContentRandomSelect >; using ContentRoulettePtr = std::shared_ptr< ContentRoulette >; @@ -10158,6 +10333,13 @@ struct ZoneSharedGroup using CreditCastPtr = std::shared_ptr< CreditCast >; using CreditListPtr = std::shared_ptr< CreditList >; using CreditListTextPtr = std::shared_ptr< CreditListText >; + using CSBonusContentPtr = std::shared_ptr< CSBonusContent >; + using CSBonusContentIdentifierPtr = std::shared_ptr< CSBonusContentIdentifier >; + using CSBonusContentTypePtr = std::shared_ptr< CSBonusContentType >; + using CSBonusMissionPtr = std::shared_ptr< CSBonusMission >; + using CSBonusMissionTypePtr = std::shared_ptr< CSBonusMissionType >; + using CSBonusSeasonPtr = std::shared_ptr< CSBonusSeason >; + using CSBonusTextDataPtr = std::shared_ptr< CSBonusTextData >; using CustomTalkPtr = std::shared_ptr< CustomTalk >; using CustomTalkDefineClientPtr = std::shared_ptr< CustomTalkDefineClient >; using CustomTalkNestHandlersPtr = std::shared_ptr< CustomTalkNestHandlers >; @@ -10218,6 +10400,7 @@ struct ZoneSharedGroup using EquipSlotCategoryPtr = std::shared_ptr< EquipSlotCategory >; using EurekaAetherItemPtr = std::shared_ptr< EurekaAetherItem >; using EurekaAethernetPtr = std::shared_ptr< EurekaAethernet >; + using EurekaDungeonPortalPtr = std::shared_ptr< EurekaDungeonPortal >; using EurekaGrowDataPtr = std::shared_ptr< EurekaGrowData >; using EurekaLogosMixerProbabilityPtr = std::shared_ptr< EurekaLogosMixerProbability >; using EurekaMagiaActionPtr = std::shared_ptr< EurekaMagiaAction >; @@ -10260,6 +10443,8 @@ struct ZoneSharedGroup using FCReputationPtr = std::shared_ptr< FCReputation >; using FCRightsPtr = std::shared_ptr< FCRights >; using FestivalPtr = std::shared_ptr< Festival >; + using FGSAddonPtr = std::shared_ptr< FGSAddon >; + using FGSStageUIPtr = std::shared_ptr< FGSStageUI >; using FieldMarkerPtr = std::shared_ptr< FieldMarker >; using FishingBaitParameterPtr = std::shared_ptr< FishingBaitParameter >; using FishingNoteInfoPtr = std::shared_ptr< FishingNoteInfo >; @@ -10321,6 +10506,7 @@ struct ZoneSharedGroup using GFateClimbing2ContentPtr = std::shared_ptr< GFateClimbing2Content >; using GFateClimbing2TotemTypePtr = std::shared_ptr< GFateClimbing2TotemType >; using GFateRideShootingPtr = std::shared_ptr< GFateRideShooting >; + using GFateTypePtr = std::shared_ptr< GFateType >; using GilShopPtr = std::shared_ptr< GilShop >; using GilShopItemPtr = std::shared_ptr< GilShopItem >; using GimmickAccessorPtr = std::shared_ptr< GimmickAccessor >; @@ -10420,6 +10606,7 @@ struct ZoneSharedGroup using JournalCategoryPtr = std::shared_ptr< JournalCategory >; using JournalGenrePtr = std::shared_ptr< JournalGenre >; using JournalSectionPtr = std::shared_ptr< JournalSection >; + using KineDriverOffGroupPtr = std::shared_ptr< KineDriverOffGroup >; using KnockbackPtr = std::shared_ptr< Knockback >; using LegacyQuestPtr = std::shared_ptr< LegacyQuest >; using LevePtr = std::shared_ptr< Leve >; @@ -10469,6 +10656,7 @@ struct ZoneSharedGroup using MinionRacePtr = std::shared_ptr< MinionRace >; using MinionRulesPtr = std::shared_ptr< MinionRules >; using MinionSkillTypePtr = std::shared_ptr< MinionSkillType >; + using MirageStoreSetItemPtr = std::shared_ptr< MirageStoreSetItem >; using MJIAnimalsPtr = std::shared_ptr< MJIAnimals >; using MJIBuildingPtr = std::shared_ptr< MJIBuilding >; using MJIBuildingPlacePtr = std::shared_ptr< MJIBuildingPlace >; @@ -10498,6 +10686,7 @@ struct ZoneSharedGroup using MJILivelyActorPtr = std::shared_ptr< MJILivelyActor >; using MJIMinionPopAreasPtr = std::shared_ptr< MJIMinionPopAreas >; using MJINamePtr = std::shared_ptr< MJIName >; + using MJINekomimiRequestPtr = std::shared_ptr< MJINekomimiRequest >; using MJIProgressPtr = std::shared_ptr< MJIProgress >; using MJIRankPtr = std::shared_ptr< MJIRank >; using MJIRecipePtr = std::shared_ptr< MJIRecipe >; @@ -10541,6 +10730,7 @@ struct ZoneSharedGroup using NotebookDivisionPtr = std::shared_ptr< NotebookDivision >; using NotebookDivisionCategoryPtr = std::shared_ptr< NotebookDivisionCategory >; using NotoriousMonsterPtr = std::shared_ptr< NotoriousMonster >; + using NotoriousMonsterTerritoryPtr = std::shared_ptr< NotoriousMonsterTerritory >; using NpcEquipPtr = std::shared_ptr< NpcEquip >; using NpcYellPtr = std::shared_ptr< NpcYell >; using OmenPtr = std::shared_ptr< Omen >; @@ -10730,6 +10920,7 @@ struct ZoneSharedGroup using UDS_PropertyPtr = std::shared_ptr< UDS_Property >; using UIColorPtr = std::shared_ptr< UIColor >; using UIConstPtr = std::shared_ptr< UIConst >; + using UILevelLookupPtr = std::shared_ptr< UILevelLookup >; using VaseFlowerPtr = std::shared_ptr< VaseFlower >; using VFXPtr = std::shared_ptr< VFX >; using VVDDataPtr = std::shared_ptr< VVDData >; @@ -10872,6 +11063,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_ChannelingIdList; std::set< uint32_t > m_CharaCardBaseIdList; std::set< uint32_t > m_CharaCardDecorationIdList; + std::set< uint32_t > m_CharaCardDesignCategoryIdList; std::set< uint32_t > m_CharaCardDesignPresetIdList; std::set< uint32_t > m_CharaCardDesignTypeIdList; std::set< uint32_t > m_CharaCardHeaderIdList; @@ -10925,9 +11117,11 @@ struct ZoneSharedGroup std::set< uint32_t > m_ContentExActionIdList; std::set< uint32_t > m_ContentFinderConditionIdList; std::set< uint32_t > m_ContentFinderConditionTransientIdList; + std::set< uint32_t > m_ContentFinderParamTableIdList; std::set< uint32_t > m_ContentGaugeIdList; std::set< uint32_t > m_ContentGaugeColorIdList; std::set< uint32_t > m_ContentMemberTypeIdList; + std::set< uint32_t > m_ContentNpcIdList; std::set< uint32_t > m_ContentNpcTalkIdList; std::set< uint32_t > m_ContentRandomSelectIdList; std::set< uint32_t > m_ContentRouletteIdList; @@ -10949,6 +11143,13 @@ struct ZoneSharedGroup std::set< uint32_t > m_CreditCastIdList; std::set< uint32_t > m_CreditListIdList; std::set< uint32_t > m_CreditListTextIdList; + std::set< uint32_t > m_CSBonusContentIdList; + std::set< uint32_t > m_CSBonusContentIdentifierIdList; + std::set< uint32_t > m_CSBonusContentTypeIdList; + std::set< uint32_t > m_CSBonusMissionIdList; + std::set< uint32_t > m_CSBonusMissionTypeIdList; + std::set< uint32_t > m_CSBonusSeasonIdList; + std::set< uint32_t > m_CSBonusTextDataIdList; std::set< uint32_t > m_CustomTalkIdList; std::set< uint32_t > m_CustomTalkDefineClientIdList; std::set< uint32_t > m_CustomTalkNestHandlersIdList; @@ -11009,6 +11210,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_EquipSlotCategoryIdList; std::set< uint32_t > m_EurekaAetherItemIdList; std::set< uint32_t > m_EurekaAethernetIdList; + std::set< uint32_t > m_EurekaDungeonPortalIdList; std::set< uint32_t > m_EurekaGrowDataIdList; std::set< uint32_t > m_EurekaLogosMixerProbabilityIdList; std::set< uint32_t > m_EurekaMagiaActionIdList; @@ -11051,6 +11253,8 @@ struct ZoneSharedGroup std::set< uint32_t > m_FCReputationIdList; std::set< uint32_t > m_FCRightsIdList; std::set< uint32_t > m_FestivalIdList; + std::set< uint32_t > m_FGSAddonIdList; + std::set< uint32_t > m_FGSStageUIIdList; std::set< uint32_t > m_FieldMarkerIdList; std::set< uint32_t > m_FishingBaitParameterIdList; std::set< uint32_t > m_FishingNoteInfoIdList; @@ -11112,6 +11316,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_GFateClimbing2ContentIdList; std::set< uint32_t > m_GFateClimbing2TotemTypeIdList; std::set< uint32_t > m_GFateRideShootingIdList; + std::set< uint32_t > m_GFateTypeIdList; std::set< uint32_t > m_GilShopIdList; std::set< uint32_t > m_GilShopItemIdList; std::set< uint32_t > m_GimmickAccessorIdList; @@ -11211,6 +11416,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_JournalCategoryIdList; std::set< uint32_t > m_JournalGenreIdList; std::set< uint32_t > m_JournalSectionIdList; + std::set< uint32_t > m_KineDriverOffGroupIdList; std::set< uint32_t > m_KnockbackIdList; std::set< uint32_t > m_LegacyQuestIdList; std::set< uint32_t > m_LeveIdList; @@ -11260,6 +11466,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_MinionRaceIdList; std::set< uint32_t > m_MinionRulesIdList; std::set< uint32_t > m_MinionSkillTypeIdList; + std::set< uint32_t > m_MirageStoreSetItemIdList; std::set< uint32_t > m_MJIAnimalsIdList; std::set< uint32_t > m_MJIBuildingIdList; std::set< uint32_t > m_MJIBuildingPlaceIdList; @@ -11289,6 +11496,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_MJILivelyActorIdList; std::set< uint32_t > m_MJIMinionPopAreasIdList; std::set< uint32_t > m_MJINameIdList; + std::set< uint32_t > m_MJINekomimiRequestIdList; std::set< uint32_t > m_MJIProgressIdList; std::set< uint32_t > m_MJIRankIdList; std::set< uint32_t > m_MJIRecipeIdList; @@ -11332,6 +11540,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_NotebookDivisionIdList; std::set< uint32_t > m_NotebookDivisionCategoryIdList; std::set< uint32_t > m_NotoriousMonsterIdList; + std::set< uint32_t > m_NotoriousMonsterTerritoryIdList; std::set< uint32_t > m_NpcEquipIdList; std::set< uint32_t > m_NpcYellIdList; std::set< uint32_t > m_OmenIdList; @@ -11521,6 +11730,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_UDS_PropertyIdList; std::set< uint32_t > m_UIColorIdList; std::set< uint32_t > m_UIConstIdList; + std::set< uint32_t > m_UILevelLookupIdList; std::set< uint32_t > m_VaseFlowerIdList; std::set< uint32_t > m_VFXIdList; std::set< uint32_t > m_VVDDataIdList; @@ -12223,6 +12433,12 @@ const std::set< uint32_t >& getCharaCardDecorationIdList() loadIdList( m_CharaCardDecorationDat, m_CharaCardDecorationIdList ); return m_CharaCardDecorationIdList; } +const std::set< uint32_t >& getCharaCardDesignCategoryIdList() +{ + if( m_CharaCardDesignCategoryIdList.size() == 0 ) + loadIdList( m_CharaCardDesignCategoryDat, m_CharaCardDesignCategoryIdList ); + return m_CharaCardDesignCategoryIdList; +} const std::set< uint32_t >& getCharaCardDesignPresetIdList() { if( m_CharaCardDesignPresetIdList.size() == 0 ) @@ -12541,6 +12757,12 @@ const std::set< uint32_t >& getContentFinderConditionTransientIdList() loadIdList( m_ContentFinderConditionTransientDat, m_ContentFinderConditionTransientIdList ); return m_ContentFinderConditionTransientIdList; } +const std::set< uint32_t >& getContentFinderParamTableIdList() +{ + if( m_ContentFinderParamTableIdList.size() == 0 ) + loadIdList( m_ContentFinderParamTableDat, m_ContentFinderParamTableIdList ); + return m_ContentFinderParamTableIdList; +} const std::set< uint32_t >& getContentGaugeIdList() { if( m_ContentGaugeIdList.size() == 0 ) @@ -12559,6 +12781,12 @@ const std::set< uint32_t >& getContentMemberTypeIdList() loadIdList( m_ContentMemberTypeDat, m_ContentMemberTypeIdList ); return m_ContentMemberTypeIdList; } +const std::set< uint32_t >& getContentNpcIdList() +{ + if( m_ContentNpcIdList.size() == 0 ) + loadIdList( m_ContentNpcDat, m_ContentNpcIdList ); + return m_ContentNpcIdList; +} const std::set< uint32_t >& getContentNpcTalkIdList() { if( m_ContentNpcTalkIdList.size() == 0 ) @@ -12685,6 +12913,48 @@ const std::set< uint32_t >& getCreditListTextIdList() loadIdList( m_CreditListTextDat, m_CreditListTextIdList ); return m_CreditListTextIdList; } +const std::set< uint32_t >& getCSBonusContentIdList() +{ + if( m_CSBonusContentIdList.size() == 0 ) + loadIdList( m_CSBonusContentDat, m_CSBonusContentIdList ); + return m_CSBonusContentIdList; +} +const std::set< uint32_t >& getCSBonusContentIdentifierIdList() +{ + if( m_CSBonusContentIdentifierIdList.size() == 0 ) + loadIdList( m_CSBonusContentIdentifierDat, m_CSBonusContentIdentifierIdList ); + return m_CSBonusContentIdentifierIdList; +} +const std::set< uint32_t >& getCSBonusContentTypeIdList() +{ + if( m_CSBonusContentTypeIdList.size() == 0 ) + loadIdList( m_CSBonusContentTypeDat, m_CSBonusContentTypeIdList ); + return m_CSBonusContentTypeIdList; +} +const std::set< uint32_t >& getCSBonusMissionIdList() +{ + if( m_CSBonusMissionIdList.size() == 0 ) + loadIdList( m_CSBonusMissionDat, m_CSBonusMissionIdList ); + return m_CSBonusMissionIdList; +} +const std::set< uint32_t >& getCSBonusMissionTypeIdList() +{ + if( m_CSBonusMissionTypeIdList.size() == 0 ) + loadIdList( m_CSBonusMissionTypeDat, m_CSBonusMissionTypeIdList ); + return m_CSBonusMissionTypeIdList; +} +const std::set< uint32_t >& getCSBonusSeasonIdList() +{ + if( m_CSBonusSeasonIdList.size() == 0 ) + loadIdList( m_CSBonusSeasonDat, m_CSBonusSeasonIdList ); + return m_CSBonusSeasonIdList; +} +const std::set< uint32_t >& getCSBonusTextDataIdList() +{ + if( m_CSBonusTextDataIdList.size() == 0 ) + loadIdList( m_CSBonusTextDataDat, m_CSBonusTextDataIdList ); + return m_CSBonusTextDataIdList; +} const std::set< uint32_t >& getCustomTalkIdList() { if( m_CustomTalkIdList.size() == 0 ) @@ -13045,6 +13315,12 @@ const std::set< uint32_t >& getEurekaAethernetIdList() loadIdList( m_EurekaAethernetDat, m_EurekaAethernetIdList ); return m_EurekaAethernetIdList; } +const std::set< uint32_t >& getEurekaDungeonPortalIdList() +{ + if( m_EurekaDungeonPortalIdList.size() == 0 ) + loadIdList( m_EurekaDungeonPortalDat, m_EurekaDungeonPortalIdList ); + return m_EurekaDungeonPortalIdList; +} const std::set< uint32_t >& getEurekaGrowDataIdList() { if( m_EurekaGrowDataIdList.size() == 0 ) @@ -13297,6 +13573,18 @@ const std::set< uint32_t >& getFestivalIdList() loadIdList( m_FestivalDat, m_FestivalIdList ); return m_FestivalIdList; } +const std::set< uint32_t >& getFGSAddonIdList() +{ + if( m_FGSAddonIdList.size() == 0 ) + loadIdList( m_FGSAddonDat, m_FGSAddonIdList ); + return m_FGSAddonIdList; +} +const std::set< uint32_t >& getFGSStageUIIdList() +{ + if( m_FGSStageUIIdList.size() == 0 ) + loadIdList( m_FGSStageUIDat, m_FGSStageUIIdList ); + return m_FGSStageUIIdList; +} const std::set< uint32_t >& getFieldMarkerIdList() { if( m_FieldMarkerIdList.size() == 0 ) @@ -13663,6 +13951,12 @@ const std::set< uint32_t >& getGFateRideShootingIdList() loadIdList( m_GFateRideShootingDat, m_GFateRideShootingIdList ); return m_GFateRideShootingIdList; } +const std::set< uint32_t >& getGFateTypeIdList() +{ + if( m_GFateTypeIdList.size() == 0 ) + loadIdList( m_GFateTypeDat, m_GFateTypeIdList ); + return m_GFateTypeIdList; +} const std::set< uint32_t >& getGilShopIdList() { if( m_GilShopIdList.size() == 0 ) @@ -14257,6 +14551,12 @@ const std::set< uint32_t >& getJournalSectionIdList() loadIdList( m_JournalSectionDat, m_JournalSectionIdList ); return m_JournalSectionIdList; } +const std::set< uint32_t >& getKineDriverOffGroupIdList() +{ + if( m_KineDriverOffGroupIdList.size() == 0 ) + loadIdList( m_KineDriverOffGroupDat, m_KineDriverOffGroupIdList ); + return m_KineDriverOffGroupIdList; +} const std::set< uint32_t >& getKnockbackIdList() { if( m_KnockbackIdList.size() == 0 ) @@ -14551,6 +14851,12 @@ const std::set< uint32_t >& getMinionSkillTypeIdList() loadIdList( m_MinionSkillTypeDat, m_MinionSkillTypeIdList ); return m_MinionSkillTypeIdList; } +const std::set< uint32_t >& getMirageStoreSetItemIdList() +{ + if( m_MirageStoreSetItemIdList.size() == 0 ) + loadIdList( m_MirageStoreSetItemDat, m_MirageStoreSetItemIdList ); + return m_MirageStoreSetItemIdList; +} const std::set< uint32_t >& getMJIAnimalsIdList() { if( m_MJIAnimalsIdList.size() == 0 ) @@ -14725,6 +15031,12 @@ const std::set< uint32_t >& getMJINameIdList() loadIdList( m_MJINameDat, m_MJINameIdList ); return m_MJINameIdList; } +const std::set< uint32_t >& getMJINekomimiRequestIdList() +{ + if( m_MJINekomimiRequestIdList.size() == 0 ) + loadIdList( m_MJINekomimiRequestDat, m_MJINekomimiRequestIdList ); + return m_MJINekomimiRequestIdList; +} const std::set< uint32_t >& getMJIProgressIdList() { if( m_MJIProgressIdList.size() == 0 ) @@ -14983,6 +15295,12 @@ const std::set< uint32_t >& getNotoriousMonsterIdList() loadIdList( m_NotoriousMonsterDat, m_NotoriousMonsterIdList ); return m_NotoriousMonsterIdList; } +const std::set< uint32_t >& getNotoriousMonsterTerritoryIdList() +{ + if( m_NotoriousMonsterTerritoryIdList.size() == 0 ) + loadIdList( m_NotoriousMonsterTerritoryDat, m_NotoriousMonsterTerritoryIdList ); + return m_NotoriousMonsterTerritoryIdList; +} const std::set< uint32_t >& getNpcEquipIdList() { if( m_NpcEquipIdList.size() == 0 ) @@ -16117,6 +16435,12 @@ const std::set< uint32_t >& getUIConstIdList() loadIdList( m_UIConstDat, m_UIConstIdList ); return m_UIConstIdList; } +const std::set< uint32_t >& getUILevelLookupIdList() +{ + if( m_UILevelLookupIdList.size() == 0 ) + loadIdList( m_UILevelLookupDat, m_UILevelLookupIdList ); + return m_UILevelLookupIdList; +} const std::set< uint32_t >& getVaseFlowerIdList() { if( m_VaseFlowerIdList.size() == 0 ) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 14bda64b..76f1c510 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -381,26 +381,28 @@ namespace Sapphire::Network::ActorControl SetTitleReq = 0x12E, TitleList = 0x12F, - UpdatedSeenHowTos = 0x133, - CutscenePlayed = 0x134, // param1 = cutscene id + UpdatedSeenHowTos = 0x132, + CutscenePlayed = 0x134, // p1 = cutscene id AllotAttribute = 0x135, - ClearFieldMarkers = 0x13A, - CameraMode = 0x13B, // param11, 1 = enable, 0 = disable + //ClearFieldMarkers = 0x13A, + CameraMode = 0x13A, // p1 (only read lowest byte), 1 = enable, 0 = disable CharaNameReq = 0x13D, // requests character name by content id HuntingLogDetails = 0x194, Timers = 0x1AB, - DyeItem = 0x1B0, // updated 5.21 + DyeItem = 0x1B1, // updated 6.58 hotfix 2 RequestChocoboInventory = 0x1C4, EmoteReq = 0x1F4, + EmoteWithWarp = 0x1F5, EmoteCancel = 0x1F6, PersistentEmoteCancel = 0x1F7, + EmoteCancelWithWarp = 0x1F8, /*! - * param2 = pose ID + * p2 = pose ID * 0 = idle pose 0 (just standing) * 1 = idle pose 1 * 2-4 = idle poses 2-4 @@ -430,9 +432,9 @@ namespace Sapphire::Network::ActorControl AchievementCritReq = 0x3E8, AchievementList = 0x3E9, - SetEstateLightingLevel = 0x40B, // param1 = light level 0 - 5 maps to UI val 5-0 + SetEstateLightingLevel = 0x40B, // p1 = light level 0 - 5 maps to UI val 5-0 RequestHousingBuildPreset = 0x44C, - RequestEstateExteriorRemodel = 0x044D, // param11 = land id + RequestEstateExteriorRemodel = 0x044D, // p1 = land id RequestEstateInteriorRemodel = 0x44E, RequestEstateHallRemoval = 0x44F, RequestBuildPreset = 0x450, // no idea what this is, it gets sent with BuildPresetHandler and has the plot id in param1 diff --git a/src/common/Network/PacketDef/Chat/ServerChatDef.h b/src/common/Network/PacketDef/Chat/ServerChatDef.h index a91004b7..e74006cb 100644 --- a/src/common/Network/PacketDef/Chat/ServerChatDef.h +++ b/src/common/Network/PacketDef/Chat/ServerChatDef.h @@ -20,6 +20,19 @@ struct FFXIVIpcTell : FFXIVIpcBasePacket< Tell > char msg[1029]; }; +struct FFXIVIpcChannelChat : FFXIVIpcBasePacket< ChannelChat > +{ + uint64_t channelId; + uint64_t contentId; + uint32_t charaId; + uint8_t type; + uint8_t unknown1; + uint8_t unknown2; + char name[32]; + char message[1024]; + uint8_t padding; +}; + /** * Structural representation of the packet sent by the server as response * to a failed tell because of unavailable target player diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index c8954b51..ee7d3ce8 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -42,81 +42,80 @@ enum ClientLobbyIpcType : enum ServerZoneIpcType : uint16_t { - Ping = 0x378, // updated 6.48 - Init = 0x2ac, // updated 6.48 + Ping = 0x1D9, // updated 6.58 hotfix 2 + Init = 0x12A, // updated 6.58 hotfix 2 - ActorFreeSpawn = 0x112, // updated 6.48 + ActorFreeSpawn = 0x195, // updated 6.58 hotfix 2 - InitZone = 0x71, // updated 6.48 - PrepareZoning = 0x188, // updated 6.48 + InitZone = 0x02D1, // updated 6.58 hotfix 2 + PrepareZoning = 0x0124, // updated 6.58 hotfix 2 - EffectResult = 0x2a3, // updated 6.48 - EffectResultBasic = 0xfa, // updated 6.48 + EffectResult = 0x0336, // updated 6.58 hotfix 2 + EffectResultBasic = 0x023A, // updated 6.58 hotfix 2 - ActorControl = 0xd4, // updated 6.48 - ActorControlTarget = 0xef, // updated 6.48 - ActorControlSelf = 0x3c1, // updated 6.48 - ActorCast = 0xc8, // updated 6.48 - ActorSetPos = 0x32c, // updated 6.48 - ActorMove = 0x1aa, // updated 6.48 - ActorGauge = 0x2a4, // updated 6.48 + ActorControl = 0x0148, // updated 6.58 hotfix 2 + ActorControlTarget = 0x032C, // updated 6.58 hotfix 2 + ActorControlSelf = 0x025D, // updated 6.58 hotfix 2 + ActorCast = 0x01BB, // updated 6.58 hotfix 2 + ActorSetPos = 0x029D, // updated 6.58 hotfix 2 + ActorMove = 0x011C, // updated 6.58 hotfix 2 + ActorGauge = 0x03B3, // updated 6.58 hotfix 2 /*! * @brief Used when resting */ - UpdateHpMpTp = 0x1fb, // updated 6.48 - UpdateClassInfo = 0x3e3, // updated 6.48 + UpdateHpMpTp = 0x007D, // updated 6.58 hotfix 2 + UpdateClassInfo = 0x0172, // updated 6.58 hotfix 2 /////////////////////////////////////////////////// ChatBanned = 0xF06B, - Playtime = 0x313, // updated 6.48 - Logout = 0x116, // updated 6.48 - CFNotify = 0x69, // updated 6.48 - CFMemberStatus = 0x0079, - CFDutyInfo = 0x1be, // updated 6.48 + Playtime = 0x03DE, // updated 6.58 hotfix 2 + Logout = 0x0378, // updated 6.58 hotfix 2 + CFNotify = 0x0279, // updated 6.58 hotfix 2 + CFMemberStatus = 0x21F, // updated 6.58 hotfix 2? + CFDutyInfo = 0x2E8, // updated 6.58 hotfix 2? CFPlayerInNeed = 0xF07F, - CFPreferredRole = 0x160, // updated 6.48 - CFCancel = 0x1bb, // updated 6.48 + CFPreferredRole = 0x282, // updated 6.58 hotfix 2 + CFCancel = 0x384, // updated 6.58 hotfix 2 + CFUnk = 0x196, // updated 6.58 hotfix 2 SocialRequestError = 0xF0AD, CFRegistered = 0x029F, // updated 5.58h - SocialRequestResponse = 0x373, // updated 6.48 - SocialMessage = 0x03CB, // updated 5.58h - SocialMessage2 = 0x01D7, // updated 5.58h + SocialInviteResponse = 0x322, // updated 6.58 hotfix 2 + SocialInviteUpdate = 0x01C1, // updated 6.58 hotfix 2 + SocialInviteResult = 0x031B, // updated 6.58 hotfix 2 CancelAllianceForming = 0xF0C6, // updated 4.2 - LogMessage = 0x316, // updated 6.48 + LogMessage = 0x19C, // updated 6.58 hotfix 2? - Chat = 0x2d7, // updated 6.48 - PartyChat = 0x0065, + Chat = 0x0325, // updated 6.58 hotfix 2 WorldVisitList = 0xF0FE, // added 4.5 - SocialList = 0xb1, // updated 6.48 + SocialList = 0x1F2, // updated 6.58 hotfix 2 - ExamineSearchInfo = 0x357, // updated 6.48 - UpdateSearchInfo = 0x115, // updated 6.48 - InitSearchInfo = 0x70, // updated 6.48 - ExamineSearchComment = 0x199, // updated 6.48 + ExamineSearchInfo = 0x014A, // updated 6.58 hotfix 2 + UpdateSearchInfo = 0x00CF, // updated 6.58 hotfix 2 + InitSearchInfo = 0x329, // updated 6.58 hotfix 2 + ExamineSearchComment = 0x244, // updated 6.58 hotfix 2? - ServerNoticeShort = 0x0333, // updated 5.58h - ServerNotice = 0x2b1, // updated 6.48 - SystemLogMessage = 0x3c8, // updated 6.48 - SetOnlineStatus = 0x17a, // updated 6.48 + ServerNoticeShort = 0xF333, // updated 5.58h + ServerNotice = 0x33B, // updated 6.58 hotfix 2 + SetOnlineStatus = 0x285, // updated 6.58 hotfix 2 - CountdownInitiate = 0x399, // updated 6.48 - CountdownCancel = 0x342, // updated 6.48 + CountdownInitiate = 0x376, // updated 6.58 hotfix 2 + CountdownCancel = 0x2B7, // updated 6.58 hotfix 2 PlayerAddedToBlacklist = 0xe2, // updated 6.48 - PlayerRemovedFromBlacklist = 0xd0, // updated 6.48 - BlackList = 0x233, // updated 6.48 + PlayerRemovedFromBlacklist = 0x201, // updated 6.58 hotfix 2? + BlackList = 0x38A, // updated 6.58 hotfix 2 - LinkshellList = 0x1f8, // updated 6.48 - CrossWorldLinkshellList = 0x3cc, // updated 6.48 - FellowshipList = 0x1c5, // updated 6.48 + LinkshellList = 0x2B2, // updated 6.58 hotfix 2 + CrossWorldLinkshellList = 0x3D5, // updated 6.58 hotfix 2 + FellowshipList = 0x373, // updated 6.58 hotfix 2 - MailDeleteRequest = 0x1b6, // updated 6.48 + MailDeleteRequest = 0x168, // updated 6.58 hotfix 2? // 12D - 137 - constant gap between 4.5x -> 5.0 ReqMoogleMailList = 0xF138, // updated 5.0 @@ -125,183 +124,183 @@ enum ServerZoneIpcType : MarketTaxRates = 0x01F8, // updated 5.35h - MarketBoardSearchResult = 0x3d6, // updated 6.48 - MarketBoardItemListingCount = 0x306, // updated 6.48 - MarketBoardItemListingHistory = 0x2f4, // updated 6.48 - MarketBoardItemListing = 0x1db, // updated 6.48 - MarketBoardPurchase = 0x1f0, // updated 6.48 - ItemMarketBoardInfo = 0x11b, // updated 6.48 + MarketBoardSearchResult = 0x0161, // updated 6.58 hotfix 2 + MarketBoardItemListingCount = 0x0286, // updated 6.58 hotfix 2 + MarketBoardItemListingHistory = 0x0229, // updated 6.58 hotfix 2 + MarketBoardItemListing = 0x03E3, // updated 6.58 hotfix 2 + MarketBoardPurchase = 0x0143, // updated 6.58 hotfix 2 + ItemMarketBoardInfo = 0x01BC, // updated 6.58 hotfix 2 CharaFreeCompanyTag = 0x013B, // updated 4.5 FreeCompanyBoardMsg = 0x03DB, // updated 5.58h - FreeCompanyInfo = 0x30f, // updated 6.48 - FreeCompanyDialog = 0x1b4, // updated 6.48 + FreeCompanyInfo = 0x02D5, // updated 6.58 hotfix 2 + FreeCompanyDialog = 0x029F, // updated 6.58 hotfix 2 ExamineFreeCompanyInfo = 0x158, // updated 6.48 FreeCompanyUpdateShortMessage = 0xF157, // added 5.0 - StatusEffectList = 0x1dd, // updated 6.48 - EurekaStatusEffectList = 0x192, // updated 6.48 - BossStatusEffectList = 0x2cb, // updated 6.48 - StatusEffectList2 = 0x166, // updated 6.48 - StatusEffectList3 = 0x31f, // updated 6.48 - Effect = 0x354, // updated 6.48 - AoeEffect8 = 0x18f, // updated 6.48 - AoeEffect16 = 0x38f, // updated 6.48 - AoeEffect24 = 0xd1, // updated 6.48 - AoeEffect32 = 0x340, // updated 6.48 - PersistantEffect = 0x31f, // updated 6.48 + StatusEffectList = 0x0383, // updated 6.58 hotfix 2 + EurekaStatusEffectList = 0x3A8, // updated 6.58 hotfix 2 + BossStatusEffectList = 0x28C, // updated 6.58 hotfix 2 + StatusEffectList2 = 0x0369, // updated 6.58 hotfix 2 + StatusEffectList3 = 0x0163, // updated 6.58 hotfix 2 + Effect = 0x037D, // updated 6.58 hotfix 2 + AoeEffect8 = 0x0F4, // updated 6.58 hotfix 2 + AoeEffect16 = 0x121, // updated 6.58 hotfix 2 + AoeEffect24 = 0x2E3, // updated 6.58 hotfix 2 + AoeEffect32 = 0x1FB, // updated 6.58 hotfix 2 + PersistantEffect = 0x163, // updated 6.58 hotfix 2 - PlaceFieldMarker = 0x194, // updated 6.48 - PlaceFieldMarkerPreset = 0x221, // updated 6.48 + PlaceFieldMarker = 0x02E4, // updated 6.58 hotfix 2 + PlaceFieldMarkerPreset = 0x030A, // updated 6.58 hotfix 2 - GCAffiliation = 0x280, // updated 6.48 + GCAffiliation = 0x35D, // updated 6.58 hotfix 2 - PlayerSpawn = 0x10e, // updated 6.48 - NpcSpawn = 0x91, // updated 6.48 - NpcSpawn2 = 0x2b6, // updated 6.48 + PlayerSpawn = 0x039C, // updated 6.58 hotfix 2 + NpcSpawn = 0x00A7, // updated 6.58 hotfix 2 + NpcSpawn2 = 0x338, // updated 6.58 hotfix 2? SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 - PartyList = 0x16f, // updated 6.48 - PartyMessage = 0x336, // updated 6.48 - HateRank = 0x33f, // updated 6.48 - HateList = 0x356, // updated 6.48 - ObjectSpawn = 0x190, // updated 6.48 - ObjectDespawn = 0xd2, // updated 6.48 + PartyList = 0x164, // updated 6.58 hotfix 2 + PartyUpdate = 0x2D8, // updated 6.58 hotfix 2 + HateRank = 0x2A7, // updated 6.58 hotfix 2 + HateList = 0x26B, // updated 6.58 hotfix 2 + ObjectSpawn = 0x03B8, // updated 6.58 hotfix 2 + ObjectDespawn = 0x1D8, // updated 6.58 hotfix 2 SilentSetClassJob = 0xF18E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything - PlayerSetup = 0x20e, // updated 6.48 - PlayerStats = 0x2f3, // updated 6.48 - ActorOwner = 0x20e, // updated 6.48 - PlayerStateFlags = 0x2ed, // updated 6.48 - PlayerClassInfo = 0xfb, // updated 6.48 + PlayerSetup = 0x035F, // updated 6.58 hotfix 2 + PlayerStats = 0x034F, // updated 6.58 hotfix 2 + ActorOwner = 0x2c3, // updated 6.58 hotfix 2 + PlayerStateFlags = 0x1B6, // updated 6.58 hotfix 2 + PlayerClassInfo = 0x238, // updated 6.58 hotfix 2 PlayerUpdateLook = 0xa8, // updated 6.48 - CharaVisualEffect = 0x2fc, // updated 6.48 + CharaVisualEffect = 0x0C1, // updated 6.58 hotfix 2 - ModelEquip = 0x82, // updated 6.48 - Examine = 0x200, // updated 6.48 - CharaNameReq = 0x267, // updated 6.48 + ModelEquip = 0x27D, // updated 6.58 hotfix 2 + Examine = 0x02C0, // updated 6.58 hotfix 2 + CharaNameReq = 0x33C, // updated 6.58 hotfix 2? // nb: see #565 on github UpdateRetainerItemSalePrice = 0xF19F, // updated 5.0 RetainerSaleHistory = 0x23d, // updated 6.48 - RetainerInformation = 0x2fe, // updated 6.48 + RetainerInformation = 0x00ED, // updated 6.58 hotfix 2 SetLevelSync = 0x1186, // not updated for 4.4, not sure what it is anymore - ItemInfo = 0x3a4, // updated 6.48 - ContainerInfo = 0x208, // updated 6.48 - InventoryTransactionFinish = 0x298, // updated 6.48 - InventoryTransaction = 0x3db, // updated 6.48 - CurrencyCrystalInfo = 0x389, // updated 6.48 + ItemInfo = 0x02F0, // updated 6.58 hotfix 2 + ContainerInfo = 0x0069, // updated 6.58 hotfix 2 + InventoryTransactionFinish = 0x009C, // updated 6.58 hotfix 2 + InventoryTransaction = 0x02BD, // updated 6.58 hotfix 2 + CurrencyCrystalInfo = 0x02DE, // updated 6.58 hotfix 2 - InventoryActionAck = 0x134, // updated 6.48 - UpdateInventorySlot = 0xa4, // updated 6.48 + InventoryActionAck = 0x00DD, // updated 6.58 hotfix 2 + UpdateInventorySlot = 0x034D, // updated 6.58 hotfix 2 - HuntingLogEntry = 0xb9, // updated 6.48 + HuntingLogEntry = 0x388, // updated 6.58 hotfix 2 - EventPlay = 0x2db, // updated 6.48 - EventPlay4 = 0xe8, // updated 6.48 - EventPlay8 = 0xfe, // updated 6.48 - EventPlay16 = 0x8f, // updated 6.48 - EventPlay32 = 0x374, // updated 6.48 - EventPlay64 = 0x27f, // updated 6.48 - EventPlay128 = 0x365, // updated 6.48 - EventPlay255 = 0xdb, // updated 6.48 - EventStart = 0x2be, // updated 6.48 - EventFinish = 0x289, // updated 6.48 + EventPlay = 0x0155, // updated 6.58 hotfix 2 + EventPlay4 = 0x00D0, // updated 6.58 hotfix 2 + EventPlay8 = 0x022B, // updated 6.58 hotfix 2 + EventPlay16 = 0x00D2, // updated 6.58 hotfix 2 + EventPlay32 = 0x02CF, // updated 6.58 hotfix 2 + EventPlay64 = 0x01D4, // updated 6.58 hotfix 2 + EventPlay128 = 0x039F, // updated 6.58 hotfix 2 + EventPlay255 = 0x0073, // updated 6.58 hotfix 2 + EventStart = 0x0146, // updated 6.58 hotfix 2 + EventFinish = 0x0339, // updated 6.58 hotfix 2 - EventContinue = 0xd9, // updated 6.48 + EventReturn = 0x1F3, // updated 6.58 hotfix 2 EventLinkshell = 0x1169, - QuestActiveList = 0x108, // updated 6.48 - QuestUpdate = 0x2f0, // updated 6.48 - QuestCompleteList = 0x17f, // updated 6.48 + QuestActiveList = 0x247, // updated 6.58 hotfix 2 + QuestUpdate = 0x1A4, // updated 6.58 hotfix 2 + QuestCompleteList = 0x352, // updated 6.58 hotfix 2 - QuestFinish = 0xf4, // updated 6.48 - MSQTrackerComplete = 0x20a, // updated 6.48 + QuestFinish = 0x2BB, // updated 6.58 hotfix 2 + MSQTrackerComplete = 0x1A9, // updated 6.58 hotfix 2 MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474 - QuestMessage = 0x0220, // updated 5.58h + QuestMessage = 0x06B, // updated 6.58 hotfix 2 - QuestTracker = 0x2ec, // updated 6.48 + QuestTracker = 0x27C, // updated 6.58 hotfix 2 - Mount = 0x242, // updated 6.48 + Mount = 0x09F, // updated 6.58 hotfix 2 - DirectorVars = 0x114, // updated 6.48 - SomeDirectorUnk1 = 0x0084, // updated 5.18 - SomeDirectorUnk2 = 0xF0C1, // updated 5.18 - SomeDirectorUnk4 = 0x03DD, // updated 5.58h - SomeDirectorUnk8 = 0x028A, // updated 5.18 - SomeDirectorUnk16 = 0x028C, // updated 5.18 - DirectorPopUp = 0x03DF, // updated 5.58h - DirectorPopUp4 = 0x019B, // updated 5.58h - DirectorPopUp8 = 0x0271, // updated 5.58h + DirectorVars = 0x3A6, // updated 6.58 hotfix 2 + DirectorMsg1 = 0xF084, // updated 5.18 + DirectorMsg2 = 0xF0C1, // updated 5.18 + DirectorMsg4 = 0x3A9, // updated 6.58 hotfix 2 + DirectorMsg8 = 0xF28A, // updated 5.18 + DirectorMsg16 = 0xF28C, // updated 5.18 + DirectorPopUp2 = 0x300, // updated 6.58 hotfix 2 + DirectorPopUp4 = 0xF19B, // updated 5.58h + DirectorPopUp8 = 0xF271, // updated 5.58h CFAvailableContents = 0xF1FD, // updated 4.2 - WeatherChange = 0x21c, // updated 6.48 - PlayerTitleList = 0x17c, // updated 6.48 - Discovery = 0x14f, // updated 6.48 + WeatherChange = 0x021D, // updated 6.58 hotfix 2 + PlayerTitleList = 0x1FF, // updated 6.58 hotfix 2? + Discovery = 0x11E, // updated 6.58 hotfix 2 - EorzeaTimeOffset = 0x1a2, // updated 6.48 + EorzeaTimeOffset = 0x398, // updated 6.58 hotfix 2? - EquipDisplayFlags = 0x24e, // updated 6.48 + EquipDisplayFlags = 0x33A, // updated 6.58 hotfix 2 MiniCactpotInit = 0x0286, // added 5.31 - ShopMessage = 0x0287, // updated 5.58h - LootMessage = 0x219, // updated 6.48 - ResultDialog = 0x21f, // updated 6.48 - DesynthResult = 0x296, // updated 6.48 + ShopMessage = 0x016F, // updated 6.58 hotfix 2 + LootMessage = 0x265, // updated 6.58 hotfix 2 + ResultDialog = 0x0362, // updated 6.58 hotfix 2 + DesynthResult = 0x007F, // updated 6.58 hotfix 2 /// Housing ////////////////////////////////////// - LandSetInitialize = 0x228, // updated 6.48 - LandUpdate = 0x26c, // updated 6.48 - LandAvailability = 0x258, // updated 6.48 - YardObjectSpawn = 0x2c0, // updated 6.48 - HousingIndoorInitialize = 0x24f, // updated 6.48 - LandPriceUpdate = 0x94, // updated 6.48 - LandInfoSign = 0x330, // updated 6.48 - LandRename = 0x255, // updated 6.48 - HousingEstateGreeting = 0x253, // updated 6.48 - HousingUpdateLandFlagsSlot = 0x3a1, // updated 6.48 - HousingLandFlags = 0x197, // updated 6.48 - HousingShowEstateGuestAccess = 0x2f2, // updated 6.48 + LandSetInitialize = 0x1C9, // updated 6.58 hotfix 2 + LandUpdate = 0x1AB, // updated 6.58 hotfix 2? + LandAvailability = 0x236, // updated 6.58 hotfix 2 + YardObjectSpawn = 0x0D1, // updated 6.58 hotfix 2? + HousingIndoorInitialize = 0x084, // updated 6.58 hotfix 2? + LandPriceUpdate = 0x0F1, // updated 6.58 hotfix 2 + LandInfoSign = 0x15F, // updated 6.58 hotfix 2 + LandRename = 0x09B, // updated 6.58 hotfix 2? + HousingEstateGreeting = 0x298, // updated 6.58 hotfix 2? + HousingUpdateLandFlagsSlot = 0x151, // updated 6.58 hotfix 2? + HousingLandFlags = 0x330, // updated 6.58 hotfix 2 + HousingShowEstateGuestAccess = 0x0E6, // updated 6.58 hotfix 2? - HousingObjectInitialize = 0x39e, // updated 6.48 - HousingInternalObjectSpawn = 0x31c, // updated 6.48 + HousingObjectInitialize = 0x1AA, // updated 6.58 hotfix 2 + HousingInternalObjectSpawn = 0x2D7, // updated 6.58 hotfix 2? - HousingWardInfo = 0x395, // updated 6.48 + HousingWardInfo = 0x327, // updated 6.58 hotfix 2? HousingObjectMove = 0x21b, // updated 6.48 - HousingObjectDye = 0x2a6, // updated 6.48 + HousingObjectDye = 0x333, // updated 6.58 hotfix 2? - SharedEstateSettingsResponse = 0x2d1, // updated 6.48 + SharedEstateSettingsResponse = 0x25B, // updated 6.58 hotfix 2? - LandUpdateHouseName = 0x98, // updated 6.48 - LandSetMap = 0x366, // updated 6.48 + LandUpdateHouseName = 0x0B5, // updated 6.58 hotfix 2? + LandSetMap = 0x32B, // updated 6.58 hotfix 2 - CeremonySetActorAppearance = 0x3be, // updated 6.48 + CeremonySetActorAppearance = 0x140, // updated 6.58 hotfix 2? ////////////////////////////////////////////////// DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui - PerformNote = 0x12a, // updated 6.48 + PerformNote = 0x266, // updated 6.58 hotfix 2? DutyGauge = 0x02E5, // updated 5.58h // daily quest info -> without them sent, login will take longer... - DailyQuests = 0x90, // updated 6.48 - DailyQuestRepeatFlags = 0x382, // updated 6.48 + DailyQuests = 0x2EF, // updated 6.58 hotfix 2 + DailyQuestRepeatFlags = 0x134, // updated 6.58 hotfix 2 - MapUpdate = 0xa3, // updated 6.48 - MapUpdate4 = 0x345, // updated 6.48 - MapUpdate8 = 0x10c, // updated 6.48 - MapUpdate16 = 0x360, // updated 6.48 - MapUpdate32 = 0x1b1, // updated 6.48 - MapUpdate64 = 0x325, // updated 6.48 - MapUpdate128 = 0x9c, // updated 6.48 + MapUpdate = 0x0FF, // updated 6.58 hotfix 2 + MapUpdate4 = 0x345, // updated 6.58 hotfix 2 + MapUpdate8 = 0x114, // updated 6.58 hotfix 2 + MapUpdate16 = 0x2CE, // updated 6.58 hotfix 2 + MapUpdate32 = 0x205, // updated 6.58 hotfix 2 + MapUpdate64 = 0x1FC, // updated 6.58 hotfix 2 + MapUpdate128 = 0x158, // updated 6.58 hotfix 2 /// Doman Mahjong ////////////////////////////////////// MahjongOpenGui = 0x02A4, // only available in mahjong instance @@ -316,19 +315,19 @@ enum ServerZoneIpcType : MahjongEndGame = 0x02C6, // finished oorasu(all-last) round; shows a result screen. /// Airship & Submarine ////////////////////////////////////// - AirshipTimers = 0x34f, // updated 6.48 - AirshipStatus = 0x16b, // updated 6.48 - AirshipStatusList = 0x2e4, // updated 6.48 - AirshipExplorationResult = 0x359, // updated 6.48 + AirshipTimers = 0x0123, // updated 6.58 hotfix 2 + AirshipStatus = 0x0291, // updated 6.58 hotfix 2 + AirshipStatusList = 0x023B, // updated 6.58 hotfix 2 + AirshipExplorationResult = 0x01BD, // updated 6.58 hotfix 2 - SubmarineTimers = 0x3af, // updated 6.48 - SubmarineProgressionStatus = 0x152, // updated 6.48 - SubmarineStatusList = 0xc4, // updated 6.48 - SubmarineExplorationResult = 0x376, // updated 6.48 + SubmarineTimers = 0x0185, // updated 6.58 hotfix 2 + SubmarineProgressionStatus = 0x02DD, // updated 6.58 hotfix 2 + SubmarineStatusList = 0x03E2, // updated 6.58 hotfix 2 + SubmarineExplorationResult = 0x02AA, // updated 6.58 hotfix 2 - EnvironmentControl = 0x137, // updated 6.48 - RSVData = 0x212, // updated 6.48 - IslandWorkshopSupplyDemand = 0xf9, // updated 6.48 + EnvironmentControl = 0x02FC, // updated 6.58 hotfix 2 + RSVData = 0x065, // updated 6.58 hotfix 2? + IslandWorkshopSupplyDemand = 0x013C, // updated 6.58 hotfix 2 }; /** @@ -337,50 +336,50 @@ enum ServerZoneIpcType : enum ClientZoneIpcType : uint16_t { - PingHandler = 0x238, // updated 6.48 - InitHandler = 0x3b6, // updated 6.48 + PingHandler = 0x2AE, // updated 6.58 hotfix 2 + InitHandler = 0x1CE, // updated 6.58 hotfix 2 - FinishLoadingHandler = 0x2ac, // updated 6.48 + FinishLoadingHandler = 0x12A, // updated 6.58 hotfix 2 - CFCommenceHandler = 0x0381, // updated 5.58h + CFCommenceHandler = 0x0242, // updated 6.58 hotfix 2 CFCancelHandler = 0x02B2, // updated 5.58h - CFRegisterDuty = 0x01BD, // updated 5.58h + CFRegisterDuty = 0x0312, // updated 6.58 hotfix 2 CFRegisterRoulette = 0x037A, // updated 5.58h - PlayTimeHandler = 0x02B7, // updated 5.58h - LogoutHandler = 0x1ad, // updated 6.48 + PlayTimeHandler = 0x0378, // updated 6.58 hotfix 2 + LogoutHandler = 0x384, // updated 6.58 hotfix 2 CancelLogout = 0x01e3, // updated 6.31h CFDutyInfoHandler = 0xF078, // updated 4.2 - SocialReqSendHandler = 0x00D7, // updated 5.58h - SocialResponseHandler = 0x023B, // updated 5.58h + SocialInviteHandler = 0x00F5, // updated 6.58 hotfix 2 + SocialReplyHandler = 0x0160, // updated 6.58 hotfix 2 CreateCrossWorldLS = 0x9999, // updated 5.58h - ChatHandler = 0x1df, // updated 6.48 - PartyChatHandler = 0x0065, PartySetLeaderHandler = 0x036C, // updated 5.58h - LeavePartyHandler = 0x019D, // updated 5.58h - KickPartyMemberHandler = 0x0262, // updated 5.58h - DisbandPartyHandler = 0x0276, // updated 5.58h + ChatHandler = 0x246, // updated 6.58 hotfix 2 + PartyChangeLeaderHandler = 0x0E4, // updated 6.58 hotfix 2 + PartyLeaveHandler = 0x0373, // updated 6.58 hotfix 2 + PartyKickHandler = 0x013F, // updated 6.58 hotfix 2 + PartyDisbandHandler = 0x03BF, // updated 6.58 hotfix 2 - SocialListHandler = 0x206, // updated 6.40 - SetSearchInfoHandler = 0x230, // updated 6.48 - ReqSearchInfoHandler = 0x03b0, // updated 6.31h + SocialListHandler = 0x10B, // updated 6.58 hotfix 2 + SetSearchInfoHandler = 0x01A0, // updated 6.58 hotfix 2 + ReqSearchInfoHandler = 0x0235, // updated 6.58 hotfix 2 ReqExamineSearchCommentHandler = 0x00E7, // updated 5.0 ReqRemovePlayerFromBlacklist = 0x00B4, // updated 5.58h - BlackListHandler = 0x153, // updated 6.48 + BlackListHandler = 0x284, // updated 6.58 hotfix 2 PlayerSearchHandler = 0x037D, // updated 5.58h - LinkshellListHandler = 0x03B6, // updated 5.58h + LinkshellListHandler = 0x0302, // updated 6.58 hotfix 2 MarketBoardRequestItemListingInfo = 0x00F4, // updated 5.58h MarketBoardRequestItemListings = 0x0122, // updated 5.58h MarketBoardSearch = 0x0082, // updated 5.58h - MarketBoardPurchaseHandler = 0x15b, // updated 6.48 + MarketBoardPurchaseHandler = 0x0322, // updated 6.58 hotfix 2 ReqExamineFcInfo = 0xF37B, // updated 5.58h (prepended F. Conflicts with FinishLoadingHandler 6.38) - FcInfoReqHandler = 0x9999, // unknown + FcInfoReqHandler = 0x33B, // updated 6.58 hotfix 2 FreeCompanyUpdateShortMessageHandler = 0x0123, // added 5.0 @@ -388,57 +387,57 @@ enum ClientZoneIpcType : ReqJoinNoviceNetwork = 0x0129, // updated 4.2 - ReqCountdownInitiate = 0x03e1, // updated 6.31h - ReqCountdownCancel = 0x023a, // updated 6.31h + ReqCountdownInitiate = 0x03E3, // updated 6.58 hotfix 2 + ReqCountdownCancel = 0xF23a, // updated 6.31h - ZoneLineHandler = 0x34e, // updated 6.48 - ClientTrigger = 0x186, // updated 6.48 - DiscoveryHandler = 0x038B, // updated 5.58h + ZoneLineHandler = 0x326, // updated 6.58 hotfix 2 + ClientTrigger = 0x035C, // updated 6.58 hotfix 2 + ClientTriggerEnvironment = 0x0295, // updated 6.58 hotfix 2 + DiscoveryHandler = 0x0129, // updated 6.58 hotfix 2 - SkillHandler = 0xa7, // updated 6.48 - GMCommand1 = 0x2f9, // updated 6.48 - GMCommand2 = 0x299, // updated 6.48 - AoESkillHandler = 0x65, // updated 6.48 + SkillHandler = 0x07C, // updated 6.58 hotfix 2 + GMCommand1 = 0x152, // updated 6.58 hotfix 2 + GMCommand2 = 0x306, // updated 6.58 hotfix 2 + AoESkillHandler = 0x0FC, // updated 6.58 hotfix 2 - UpdatePositionHandler = 0x3b5, // updated 6.48 + UpdatePositionHandler = 0x0256, // updated 6.58 hotfix 2 - InventoryModifyHandler = 0x2da, // updated 6.48 + InventoryModifyHandler = 0x023E, // updated 6.58 hotfix 2 - InventoryEquipRecommendedItems = 0x01C9, // updated 5.58h + InventoryEquipRecommendedItems = 0x355, // updated 6.58 hotfix 2 - ReqPlaceHousingItem = 0x02D4, // updated 5.58h - BuildPresetHandler = 0x0223, // updated 5.58h + ReqPlaceHousingItem = 0x032D, // updated 6.58 hotfix 2 + BuildPresetHandler = 0x0D9, // updated 6.58 hotfix 2 - TalkEventHandler = 0x1a8, // updated 6.48 - EmoteEventHandler = 0x00B0, // updated 5.58h - WithinRangeEventHandler = 0x1b9, // updated 6.48 - OutOfRangeEventHandler = 0x263, // updated 6.48 - EnterTeriEventHandler = 0x370, // updated 6.48 - ShopEventHandler = 0x0384, // updated 5.58h - ReturnEventHandler = 0xef, // updated 6.48 - TradeReturnEventHandler = 0x1fb, // updated 6.48 - TradeReturnEventHandler2 = 0x354, // updated 6.48 - EventYield2Handler = 0x021D, // updated 5.58h + TalkEventHandler = 0x23A, // updated 6.58 hotfix 2 + SayEventHandler = 0x25D, // updated 6.58 hotfix 2 + EmoteEventHandler = 0x1B5, // updated 6.58 hotfix 2 + WithinRangeEventHandler = 0x38E, // updated 6.58 hotfix 2 + OutOfRangeEventHandler = 0x200, // updated 6.58 hotfix 2 + EnterTeriEventHandler = 0x105, // updated 6.58 hotfix 2 + ShopEventHandler = 0x0148, // updated 6.58 hotfix 2 + ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 + TradeReturnEventHandler = 0x166, // updated 6.58 hotfix 2 + TradeReturnEventHandler2 = 0x37D, // updated 6.58 hotfix 2 + EventYield2Handler = 0x0273, // updated 6.58 hotfix 2 EventYield16Handler = 0x0207, // updated 5.58h LinkshellEventHandler = 0x9999, // unknown LinkshellEventHandler1 = 0x9999, // unknown - ReqEquipDisplayFlagsChange = 0x03BC, // updated 6.30h + ReqEquipDisplayFlagsChange = 0x0150, // updated 6.58 hotfix 2 - LandRenameHandler = 0x028E, // updated 5.58h - HousingUpdateHouseGreeting = 0x0343, // updated 5.58h - HousingUpdateObjectPosition = 0x9999, // unknown - HousingEditExterior = 0x027B, // updated 5.58h - HousingEditInterior = 0x02E3, // updated 5.58h + LandRenameHandler = 0x03B7, // updated 6.58 hotfix 2 + HousingUpdateHouseGreeting = 0x03A7, // updated 6.58 hotfix 2 + HousingUpdateObjectPosition = 0x0157, // updated 6.58 hotfix 2 + HousingEditExterior = 0x028C, // updated 6.58 hotfix 2 + HousingEditInterior = 0x0336, // updated 6.58 hotfix 2 SetSharedEstateSettings = 0x00D2, // updated 5.58h - UpdatePositionInstance = 0xa5, // updated 6.48 + UpdatePositionInstance = 0x0227, // updated 6.58 hotfix 2 PerformNoteHandler = 0x0243, // updated 5.58h - - WorldInteractionHandler = 0x0274, // updated 5.58h Dive = 0x018C, // updated 6.30h }; @@ -451,6 +450,7 @@ enum ServerChatIpcType : uint16_t { Tell = 0x0064, // updated for sb + ChannelChat = 0x0065, PublicContentTell = 0xF0FB, // added 4.5, this is used when receiving a /tell in PublicContent instances such as Eureka or Bozja (prepended F conflicts with TradeReturnEventHandler 6.38) TellErrNotFound = 0x0066, @@ -464,6 +464,7 @@ enum ClientChatIpcType : uint16_t { TellReq = 0x0064, + ChannelChatReq = 0x0065, PublicContentTellReq = 0x0326, // updated 5.35 hotfix, this is used when sending a /tell in PublicContent instances such as Eureka or Bozja }; diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index f15ca0bf..7590b8e4 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -37,12 +37,11 @@ struct FFXIVIpcClientTrigger : { /* 0000 */ uint16_t commandId; /* 0002 */ uint8_t unk_2[2]; - /* 0004 */ uint32_t param11; - /* 0008 */ uint32_t param12; - /* 000C */ uint32_t param2; - /* 0010 */ uint32_t param4; // todo: really? - /* 0014 */ uint32_t param5; - /* 0018 */ uint64_t param3; + /* 0004 */ uint32_t param1; + /* 0008 */ uint32_t param2; + /* 000C */ uint32_t param3; + /* 0010 */ uint32_t param4; + /* 0014 */ Common::FFXIVARR_POSITION3 position; }; struct FFXIVIpcUpdatePosition : @@ -161,6 +160,13 @@ struct FFXIVIpcEventHandlerTalk : /* 0008 */ uint32_t eventId; }; +struct FFXIVIpcEventHandlerSay : + FFXIVIpcBasePacket< SayEventHandler > +{ + /* 0000 */ uint64_t actorId; + /* 0008 */ uint32_t eventId; +}; + struct FFXIVIpcPingHandler : FFXIVIpcBasePacket< PingHandler > { @@ -207,10 +213,10 @@ struct FFXIVIpcChatHandler : /* 001A */ char message[1012]; }; -struct FFXIVIpcPartyChatHandler : - FFXIVIpcBasePacket< ChatHandler > +struct FFXIVIpcChannelChatHandler : + FFXIVIpcBasePacket< ChannelChatReq > { - uint64_t unknown; + uint64_t channelId; char message[1024]; }; @@ -351,19 +357,8 @@ struct FFXIVIpcFreeCompanyUpdateShortMessageHandler : uint16_t unknown2; }; -struct FFXIVIpcWorldInteractionHandler : - FFXIVIpcBasePacket< WorldInteractionHandler > -{ - uint32_t action; - uint32_t param1; - uint32_t param2; - uint32_t param3; - uint32_t param4; - Common::FFXIVARR_POSITION3 position; -}; - -struct FFXIVIpcSocialReqSendHandler : - FFXIVIpcBasePacket< SocialReqSendHandler > +struct FFXIVIpcSocialInviteHandler : + FFXIVIpcBasePacket< SocialInviteHandler > { uint64_t unknown; uint8_t p1; @@ -373,8 +368,8 @@ struct FFXIVIpcSocialReqSendHandler : uint8_t padding[5]; }; -struct FFXIVIpcSocialResponseHandler : - FFXIVIpcBasePacket< SocialResponseHandler > +struct FFXIVIpcSocialReplyHandler : + FFXIVIpcBasePacket< SocialReplyHandler > { uint64_t contentId; uint8_t p1; @@ -384,8 +379,8 @@ struct FFXIVIpcSocialResponseHandler : uint32_t unknown; }; -struct FFXIVIpcPartySetLeaderHandler : - FFXIVIpcBasePacket< PartySetLeaderHandler > +struct FFXIVIpcPartyChangeLeaderHandler : + FFXIVIpcBasePacket< PartyChangeLeaderHandler > { uint64_t contentId; uint8_t p1; @@ -394,14 +389,14 @@ struct FFXIVIpcPartySetLeaderHandler : uint8_t padding[6]; }; -struct FFXIVIpcLeavePartyHandler : - FFXIVIpcBasePacket< LeavePartyHandler > +struct FFXIVIpcPartyLeaveHandler : + FFXIVIpcBasePacket< PartyLeaveHandler > { uint64_t empty; }; -struct FFXIVIpcKickPartyMemberHander : - FFXIVIpcBasePacket< KickPartyMemberHandler > +struct FFXIVIpcPartyKickHandler : + FFXIVIpcBasePacket< PartyKickHandler > { uint64_t contentId; uint8_t p1; @@ -410,8 +405,8 @@ struct FFXIVIpcKickPartyMemberHander : uint8_t padding[6]; }; -struct FFXIVIpcDisbandPartyHandler : - FFXIVIpcBasePacket< DisbandPartyHandler > +struct FFXIVIpcPartyDisbandHandler : + FFXIVIpcBasePacket< PartyDisbandHandler > { uint64_t empty; }; diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 590354af..ea7cbad2 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -47,19 +47,6 @@ namespace Sapphire::Network::Packets::Server uint8_t unknown[12]; //possibly padding? }; - struct FFXIVIpcPartyChat : FFXIVIpcBasePacket< PartyChat > - { - uint64_t unknown; - uint64_t contentId; - uint32_t charaId; - uint8_t u1; - uint8_t u2; - uint8_t u3; - char name[32]; - char message[1024]; - uint8_t padding; - }; - struct FFXIVIpcChatBanned : FFXIVIpcBasePacket< ChatBanned > { uint8_t padding[4]; // I was not sure reinterpreting ZST is valid behavior in C++. @@ -107,6 +94,7 @@ namespace Sapphire::Network::Packets::Server struct PlayerEntry { uint64_t contentId; + uint64_t unknown; uint8_t bytes[12]; uint16_t zoneId; uint16_t zoneId1; @@ -116,10 +104,10 @@ namespace Sapphire::Network::Packets::Server uint8_t padding; uint8_t level; uint8_t padding1; - uint16_t padding2; - uint8_t one; + uint8_t unknown2[8]; char name[0x20]; - char fcTag[9]; + char fcTag[6]; + uint8_t padding2[6]; }; struct FFXIVIpcSocialList : FFXIVIpcBasePacket< SocialList > @@ -456,8 +444,8 @@ namespace Sapphire::Network::Packets::Server */ struct FFXIVIpcEffectResult : FFXIVIpcBasePacket< EffectResult > { - uint32_t globalSequence; uint32_t unknown1; + uint32_t globalSequence; uint32_t actor_id; uint32_t current_hp; uint32_t max_hp; @@ -479,6 +467,7 @@ namespace Sapphire::Network::Packets::Server uint32_t sourceActorId; } statusEntries[4]; + uint32_t padding; }; /** @@ -553,11 +542,11 @@ namespace Sapphire::Network::Packets::Server */ uint32_t sequence; - float animationLockTime; // maybe? doesn't seem to do anything + float animationLockTime; uint32_t someTargetId; // always 0x0E000000? /*! - * @brief The cast sequence from the originating player. Should only be sent to the source, 0 for every other player. + * @brief The cast sequence from the originating player. * * This needs to match the sequence sent from the player in the action start packet otherwise you'll cancel the * initial animation and start a new one once the packet arrives. @@ -574,7 +563,7 @@ namespace Sapphire::Network::Packets::Server uint16_t padding_22[3]; - uint8_t effects[65]; + uint8_t effects[64]; uint16_t padding_6A[3]; @@ -679,39 +668,42 @@ namespace Sapphire::Network::Packets::Server uint16_t fateID; uint16_t mPCurr; uint16_t mPMax; - uint16_t unk; // == 0 + uint16_t unk; uint16_t modelChara; uint16_t rotation; uint16_t currentMount; uint16_t activeMinion; uint8_t u23; uint8_t u24; + uint8_t u25; + uint8_t u26; uint8_t spawnIndex; uint8_t state; uint8_t persistentEmote; uint8_t modelType; uint8_t subtype; uint8_t voice; - uint16_t u25c; uint8_t enemyType; + uint8_t u27; uint8_t level; uint8_t classJob; - uint8_t u26d; - uint16_t u27a; + uint8_t u28; + uint8_t u29; + uint8_t u30; uint8_t mountHead; uint8_t mountBody; uint8_t mountFeet; uint8_t mountColor; uint8_t scale; uint8_t elementData[6]; - uint8_t unknown5_5; Common::StatusEffect effect[30]; Common::FFXIVARR_POSITION3 pos; uint32_t models[10]; + uint8_t unknown6_58[10]; char name[32]; uint8_t look[26]; char fcTag[6]; - uint32_t unk30[2]; + uint8_t padding[6]; }; /** @@ -762,28 +754,31 @@ namespace Sapphire::Network::Packets::Server uint16_t activeMinion; uint8_t u23; uint8_t u24; + uint8_t u6_58a; + uint8_t u6_58b; uint8_t spawnIndex; uint8_t state; uint8_t persistantEmote; uint8_t modelType; uint8_t subtype; uint8_t voice; - uint16_t u25c; + uint8_t u25c; uint8_t enemyType; uint8_t level; uint8_t classJob; - uint8_t u26d; - uint16_t u27a; + uint8_t u26; + uint8_t u27; + uint8_t u28; uint8_t mountHead; uint8_t mountBody; uint8_t mountFeet; uint8_t mountColor; uint8_t scale; uint8_t elemental[6]; - uint8_t unknown5_5; Common::StatusEffect effect[30]; Common::FFXIVARR_POSITION3 pos; uint32_t models[10]; + uint8_t unknown6_58[10]; char name[32]; uint8_t look[26]; char fcTag[6]; @@ -792,7 +787,7 @@ namespace Sapphire::Network::Packets::Server uint8_t bNPCPartSlot; uint8_t unk32; uint16_t unk33; - uint32_t unk34[2]; + uint16_t unk34; }; /** @@ -950,13 +945,14 @@ namespace Sapphire::Network::Packets::Server /** * Structural representation of the packet sent by the server to initialize * the client UI upon initial connection. + * + * verified = at correct offset, if the next field is not verified it may have an incorrect size */ struct FFXIVIpcPlayerSetup : FFXIVIpcBasePacket< PlayerSetup > { - // plain C types for a bit until the packet is actually fixed. - // makes conversion between different editors easier. - uint64_t contentId; + uint64_t contentId; // verified uint64_t crest; + uint64_t unknown10; uint32_t charId; uint32_t restedExp; uint32_t companionCurrentExp; @@ -977,105 +973,77 @@ namespace Sapphire::Network::Packets::Server uint16_t unknown50; uint16_t unknownPvp52[4]; uint16_t pvpSeriesExp; - uint16_t playerCommendations; - uint16_t unknown5C; - uint16_t unknown5E; - uint16_t pvpFrontlineWeeklyCampaigns; - uint16_t enhancedAnimaGlassProgress; + uint16_t playerCommendations; // verified uint16_t unknown64[8]; uint16_t pvpRivalWingsTotalMatches; uint16_t pvpRivalWingsTotalVictories; uint16_t pvpRivalWingsWeeklyMatches; uint16_t pvpRivalWingsWeeklyVictories; - uint8_t maxLevel; - uint8_t expansion; + uint8_t maxLevel; // verified + uint8_t expansion; // verified uint8_t unknown76; uint8_t unknown77; uint8_t unknown78; - uint8_t race; - uint8_t tribe; - uint8_t gender; - uint8_t currentJob; - uint8_t currentClass; - uint8_t deity; - uint8_t namedayMonth; - uint8_t namedayDay; - uint8_t cityState; - uint8_t homepoint; - uint8_t unknown83; - uint8_t petHotBar; - uint8_t companionRank; - uint8_t companionStars; - uint8_t companionSp; - uint8_t companionUnk86; - uint8_t companionColor; + uint8_t race; // verified + uint8_t tribe; // verified + uint8_t gender; // verified + uint8_t currentJob; // verified + uint8_t currentClass; // verified + uint8_t deity; // verified + uint8_t namedayMonth; // verified + uint8_t namedayDay; // verified + uint8_t cityState; // verified + uint8_t homepoint; // verified + uint8_t unknown8D[3]; + uint8_t companionRank; // verified + uint8_t companionStars; // verified + uint8_t companionSp; // verified + uint8_t companionUnk93; + uint8_t companionColor; // verified uint8_t companionFavFeed; - uint8_t favAetheryteCount; - uint8_t unknown8C[4]; - uint8_t hasRelicBook; - uint8_t relicBookId; + uint8_t favAetheryteCount; // verified + uint8_t unknown97[5]; uint8_t sightseeing21To80Unlock; uint8_t sightseeingHeavenswardUnlock; - uint8_t unknown94[2]; - uint8_t craftingMasterMask; - uint8_t unknown97[9]; - uint8_t unknownA0[3]; - uint8_t pvpSeriesLevel; - uint8_t pvpMalmstonesClaimed; - uint8_t lastSeasonMalmstonesEarned; - uint8_t lastSeasonMalmstonesClaimed; - uint8_t unknownA7[7]; - uint32_t exp[30]; + uint8_t unknown9E[26]; + uint32_t exp[32]; // verified uint32_t pvpTotalExp; uint32_t unknownPvp124; uint32_t pvpExp; uint32_t pvpFrontlineOverallRanks[3]; uint32_t unknown138; - uint16_t levels[30]; - uint16_t unknown178[8]; - uint16_t fishingRecordsFishId[33]; - uint16_t fishingRecordsFishLength[33]; - uint16_t beastExp[17]; - uint16_t unknown21C[6]; - uint16_t pvpFrontlineWeeklyRanks[3]; - uint16_t unknownMask22C[8]; - uint8_t companionName[21]; - uint8_t companionDefRank; - uint8_t companionAttRank; - uint8_t companionHealRank; + uint16_t levels[32]; // verified + uint8_t unknown194[218]; + char companionName[21]; // verified + uint8_t companionDefRank; // verified + uint8_t companionAttRank; // verified + uint8_t companionHealRank; // verified uint8_t mountGuideMask[33]; uint8_t ornamentMask[4]; - uint8_t unknown281[16]; - char name[32]; + uint8_t unknown281[23]; + char name[32]; // verified uint8_t unknown293[16]; - uint8_t unknown2A3; + uint8_t unknown2A3[16]; uint8_t unlockBitmask[64]; uint8_t aetheryte[26]; - uint16_t favoriteAetheryteIds[4]; + uint16_t favoriteAetheryteIds[4]; // verified uint16_t freeAetheryteId; uint16_t psPlusFreeAetheryteId; - uint8_t discovery[472]; - uint8_t howto[36]; + uint8_t discovery[480]; // verified + uint8_t howto[36]; // verified uint8_t unknown554[4]; uint8_t minions[60]; uint8_t chocoboTaxiMask[12]; - uint8_t watchedCutscenes[154]; + uint8_t watchedCutscenes[159]; uint8_t companionBardingMask[12]; - uint8_t unknownMask64E[23]; - uint8_t companionEquippedHead; - uint8_t companionEquippedBody; - uint8_t companionEquippedLegs; - uint8_t fishingGuideMask[161]; - uint8_t fishingSpotVisited[38]; - uint8_t unknown694[34]; - uint8_t unknown6B6[7]; - uint8_t unknownPvp6BD[3]; - uint8_t beastRank[17]; - uint8_t unknownPvp6CE[12]; - uint8_t pose[7]; + uint8_t companionEquippedHead; // verified + uint8_t companionEquippedBody; // verified + uint8_t companionEquippedLegs; // verified + uint8_t unknownMask[287]; + uint8_t pose[7]; // verified uint8_t unknown6DF[3]; uint8_t challengeLogComplete[13]; - uint8_t secretRecipeBookMask[10]; + uint8_t secretRecipeBookMask[12]; uint8_t unknownMask6F7[29]; uint8_t relicCompletion[12]; uint8_t sightseeingMask[37]; @@ -1087,26 +1055,20 @@ namespace Sapphire::Network::Packets::Server uint8_t unknown7E6[49]; uint8_t regionalFolkloreMask[6]; uint8_t orchestrionMask[87]; - uint8_t hallOfNoviceCompletion[3]; + uint8_t hallOfNoviceCompletion[3]; // verified uint8_t animaCompletion[11]; - uint8_t unknown85E[16]; - uint8_t unknown86E[4]; - uint8_t unknown872[18]; - uint8_t unknown880; - uint8_t unlockedRaids[28]; - uint8_t unlockedDungeons[18]; - uint8_t unlockedGuildhests[10]; - uint8_t unlockedTrials[12]; + uint8_t unknown85E[41]; + uint8_t unlockedRaids[28]; // verified + uint8_t unlockedDungeons[18]; // verified + uint8_t unlockedGuildhests[10]; // verified + uint8_t unlockedTrials[12]; // verified uint8_t unlockedPvp[5]; - uint8_t clearedRaids[28]; - uint8_t clearedDungeons[18]; - uint8_t clearedGuildhests[10]; - uint8_t clearedTrials[12]; + uint8_t clearedRaids[28]; // verified + uint8_t clearedDungeons[18]; // verified + uint8_t clearedGuildhests[10]; // verified + uint8_t clearedTrials[12]; // verified uint8_t clearedPvp[5]; - uint8_t unknown948[6]; - uint8_t unknown94C[2]; - uint8_t unknown94E[2]; - uint8_t unknownA06[2]; + uint8_t unknown948[15]; }; @@ -1185,7 +1147,6 @@ namespace Sapphire::Network::Packets::Server uint8_t isSpecialist; uint16_t syncedLevel; // Locks actions, equipment, prob more. Player's current level (synced). uint16_t classLevel; // Locks roles, prob more. Player's actual unsynced level. - uint32_t roleActions[10]; }; /** @@ -1647,15 +1608,12 @@ namespace Sapphire::Network::Packets::Server */ struct FFXIVIpcCFNotify : FFXIVIpcBasePacket< CFNotify > { - uint32_t state1; // 3 = cancelled, 4 = duty ready - uint32_t state2; // if state1 == 3, state2 is cancelled reason + uint32_t state1; + uint32_t unknown[5]; - uint32_t param1; // usually classJobId - uint32_t param2; // usually flag - uint32_t param3; // usually languages, sometimes join in progress timestamp - - uint16_t param4; // usually roulette id + uint32_t unknown_one; uint16_t contents[5]; + uint16_t padding; }; /** @@ -1831,23 +1789,19 @@ namespace Sapphire::Network::Packets::Server uint16_t u28; }; - struct FFXIVIpcDirectorPopUp : FFXIVIpcBasePacket< DirectorPopUp > + struct FFXIVIpcDirectorPopUp2 : FFXIVIpcBasePacket< DirectorPopUp2 > { uint32_t directorId; uint16_t pad1[2]; uint64_t sourceActorId; - /*! - * 2 = green text in log - */ - uint8_t flags; - uint8_t pad2[3]; - uint32_t bNPCName; uint32_t textId; uint32_t popupTimeMs; - uint32_t param[6]; + uint32_t bNPCName; + uint8_t flags; // 2 = green text in log + uint8_t pad2[3]; + uint32_t param[2]; }; - struct FFXIVIpcActorGauge : FFXIVIpcBasePacket< ActorGauge > { uint8_t classJobId; @@ -2161,10 +2115,20 @@ namespace Sapphire::Network::Packets::Server struct FFXIVIpcCFCancel : FFXIVIpcBasePacket< CFCancel > { + uint64_t unknown1; uint32_t cancelReason; uint32_t unknown2; }; + // used to clear CF state, otherwise the UI stays locked and cannot queue again. + struct FFXIVIpcCFUnk : FFXIVIpcBasePacket< CFUnk > + { + uint16_t cfConditionId; + uint16_t unknown1; + uint32_t five; + uint32_t unknown2[2]; + }; + struct FFXIVIpcShopMessage : FFXIVIpcBasePacket< ShopMessage > { uint32_t shopId; @@ -2190,21 +2154,22 @@ namespace Sapphire::Network::Packets::Server uint32_t param7; }; - struct FFXIVIpcSocialMessage : FFXIVIpcBasePacket< SocialMessage > + struct FFXIVIpcSocialInviteUpdate : FFXIVIpcBasePacket< SocialInviteUpdate > { uint64_t contentId; + uint64_t unknown; uint32_t expireTime; uint8_t p1; uint8_t p2; uint8_t socialType; uint8_t padding; uint8_t type; - uint8_t unknown4; + uint8_t gender; char name[32]; uint8_t padding2[6]; }; - struct FFXIVIpcSocialMessage2 : FFXIVIpcBasePacket< SocialMessage2 > + struct FFXIVIpcSocialInviteResult : FFXIVIpcBasePacket< SocialInviteResult > { uint64_t contentId; uint32_t unknown3; @@ -2215,40 +2180,43 @@ namespace Sapphire::Network::Packets::Server char name[32]; }; - struct FFXIVIpcSocialRequestResponse : FFXIVIpcBasePacket< SocialRequestResponse > + struct FFXIVIpcSocialInviteResponse : FFXIVIpcBasePacket< SocialInviteResponse > { uint64_t contentId; uint32_t unknown3; - uint8_t u1AlwaysOne; + uint8_t socialType; uint8_t response; - uint8_t u2AlwaysOne; + uint8_t gender; char name[32]; uint8_t padding; }; + struct PartyMember + { + char name[32]; + uint64_t unknown2; + uint64_t contentId; + uint32_t charaId; + uint32_t u1; // 3.x ParentEntityId? + uint32_t u2; // 3.x PetEntityId? + uint32_t hp; + uint32_t maxHp; + uint16_t mp; + uint16_t maxMp; + uint16_t u3; + uint16_t zoneId; + uint8_t gposeSelectable; // 3.x Valid? + uint8_t classId; + uint8_t u5; // 3.x ObjType? + uint8_t level; + uint8_t isLevelSync; + uint8_t unknown[7]; + Common::StatusEffect effect[30]; + }; + struct FFXIVIpcPartyList : FFXIVIpcBasePacket< PartyList > { - struct - { - char name[32]; - uint64_t contentId; - uint32_t charaId; - uint32_t u1; - uint32_t u2; - uint32_t hp; - uint32_t maxHp; - uint16_t mp; - uint16_t maxMp; - uint16_t u3; - uint16_t zoneId; - uint8_t gposeSelectable; - uint8_t classId; - uint8_t u5; - uint8_t level; - uint8_t isLevelSync; - uint8_t unknown[7]; - Common::StatusEffect effect[30]; - } member[8]; + PartyMember member[8]; uint64_t partyId; uint64_t channelId; uint8_t leaderIndex; @@ -2257,20 +2225,20 @@ namespace Sapphire::Network::Packets::Server uint32_t padding2; }; - struct FFXIVIpcPartyMessage : FFXIVIpcBasePacket< PartyMessage > + struct FFXIVIpcPartyUpdate : FFXIVIpcBasePacket< PartyUpdate > { - uint64_t leaderContentId; - uint64_t memberContentId; - uint8_t u1; - uint8_t u2; - uint16_t type; - uint8_t partySize; // ? - char leaderName[32]; - char memberName[32]; + uint64_t executeContentId; + uint64_t targetContentId; + uint8_t executeGender; + uint8_t targetGender; + uint16_t updateStatus; + uint8_t partySize; + char executeName[32]; + char targetName[32]; uint8_t padding[3]; }; - struct FFXIVIpcEventContinue : FFXIVIpcBasePacket< EventContinue > + struct FFXIVIpcEventReturn : FFXIVIpcBasePacket< EventReturn > { uint32_t eventId; uint16_t scene; @@ -2278,7 +2246,7 @@ namespace Sapphire::Network::Packets::Server uint64_t unknown2; }; - struct FFXIVDirectorUnk4 : FFXIVIpcBasePacket< SomeDirectorUnk4 > + struct FFXIVDirectorMsg4 : FFXIVIpcBasePacket< DirectorMsg4 > { uint32_t param[4]; uint64_t unknown; diff --git a/src/scripts/quest/ManSea001.cpp b/src/scripts/quest/ManSea001.cpp index ddad3d00..cef649f1 100644 --- a/src/scripts/quest/ManSea001.cpp +++ b/src/scripts/quest/ManSea001.cpp @@ -74,21 +74,25 @@ private: void Scene00005( Entity::Player& player ) { - player.playSceneChain( getId(), 5, HIDE_HOTBAR, bindScene( &ManSea001::Scene00006 ) ); + player.playScene( getId(), 5, HIDE_HOTBAR, + [ & ]( Entity::Player& player, const Event::SceneResult& result ) + { + if( result.param2 == 1 ) + { + Scene00006( player ); + } + } ); } void Scene00006( Entity::Player& player ) { player.playScene( getId(), 6, INVIS_OTHER_PC, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - if( result.param2 == 1 ) - { - player.updateQuest( getId(), SEQ_FINISH ); - player.prepareZoning( player.getZoneId(), true, 1, 0 ); - player.changePosition( 9, 40, 14, 2 ); - } - } ); + [ & ]( Entity::Player& player, const Event::SceneResult& result ) + { + player.updateQuest( getId(), SEQ_FINISH ); + player.prepareZoning( player.getZoneId(), true, 1, 0 ); + player.changePosition( 9, 40, 14, 2 ); + } ); } void Scene00007( Entity::Player& player ) diff --git a/src/world/Action/EventItemAction.cpp b/src/world/Action/EventItemAction.cpp index f833c420..ab201aac 100644 --- a/src/world/Action/EventItemAction.cpp +++ b/src/world/Action/EventItemAction.cpp @@ -67,4 +67,6 @@ void EventItemAction::execute() void EventItemAction::start() { m_startTime = Common::Util::getTimeMs(); + if( !hasCastTime() ) + execute(); } diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index bd3d8271..a06ecdb1 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -535,6 +535,7 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf auto statusEffectAdd = makeZonePacket< FFXIVIpcEffectResult >( getId() ); + statusEffectAdd->data().unknown1 = 1; statusEffectAdd->data().globalSequence = getCurrentTerritory()->getNextEffectSequence(); statusEffectAdd->data().actor_id = pEffect->getTargetActorId(); statusEffectAdd->data().current_hp = getHp(); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 7ecb39a0..73ec81bf 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -85,6 +85,7 @@ Sapphire::Entity::Player::Player() : m_onEnterEventDone( false ), m_falling( false ), m_pQueuedAction( nullptr ), + m_partyId( 0 ), m_cfNotifiedContent( 0 ) { m_id = 0; @@ -134,7 +135,8 @@ uint32_t Sapphire::Entity::Player::getMaxHp() uint32_t Sapphire::Entity::Player::getMaxMp() { - return m_baseStats.max_mp; + //return m_baseStats.max_mp; + return 10000; } uint16_t Sapphire::Entity::Player::getZoneId() const @@ -236,6 +238,10 @@ Sapphire::Common::OnlineStatus Sapphire::Entity::Player::getOnlineStatus() const void Sapphire::Entity::Player::setOnlineStatusMask( uint64_t status ) { m_onlineStatus = status; + sendToInRangeSet( makeActorControl( getId(), SetStatusIcon, static_cast< uint8_t >( getOnlineStatus() ) ), true ); + auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( getId() ); + statusPacket->data().onlineStatusFlags = status; + queuePacket( statusPacket ); } uint64_t Sapphire::Entity::Player::getOnlineStatusMask() const @@ -243,6 +249,47 @@ uint64_t Sapphire::Entity::Player::getOnlineStatusMask() const return m_onlineStatus; } +void Sapphire::Entity::Player::addOnlineStatus( OnlineStatus status ) +{ + uint64_t statusValue = 1ull << static_cast< uint8_t >( status ); + uint64_t newFlags = getOnlineStatusMask() | statusValue; + + setOnlineStatusMask( newFlags ); +} + +void Sapphire::Entity::Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status ) +{ + uint64_t newFlags = getOnlineStatusMask(); + for( const auto& state : status ) + { + uint64_t statusValue = 1ull << static_cast< uint8_t >( state ); + newFlags |= statusValue; + } + + setOnlineStatusMask( newFlags ); +} + +void Sapphire::Entity::Player::removeOnlineStatus( OnlineStatus status ) +{ + uint64_t statusValue = 1ull << static_cast< uint8_t >( status ); + uint64_t newFlags = getOnlineStatusMask(); + newFlags &= ~statusValue; + + setOnlineStatusMask( newFlags ); +} + +void Sapphire::Entity::Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& status ) +{ + uint64_t newFlags = getOnlineStatusMask(); + for( const auto& state : status ) + { + uint64_t statusValue = 1ull << static_cast< uint8_t >( state ); + newFlags &= ~statusValue; + } + + setOnlineStatusMask( newFlags ); +} + void Sapphire::Entity::Player::prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime, uint16_t animation, uint8_t param4, uint8_t param7, uint8_t unknown ) { auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( getId() ); @@ -420,6 +467,16 @@ void Sapphire::Entity::Player::forceZoneing( uint32_t zoneId ) //performZoning( zoneId, Common::ZoneingType::None, getPos() ); } +void Sapphire::Entity::Player::forceZoneing( uint32_t zoneId, FFXIVARR_POSITION3 pos, float rot, bool showZoneName ) +{ + if( zoneId == 0 ) + { + zoneId = getCurrentTerritory()->getTerritoryTypeId(); + } + m_queuedZoneing = std::make_shared< QueuedZoning >( zoneId, pos, Util::getTimeMs(), rot ); + prepareZoning( showZoneName ? zoneId : 0, true, 1, 0 ); +} + void Sapphire::Entity::Player::returnToHomepoint() { setZoningType( Common::ZoneingType::Return ); @@ -467,10 +524,14 @@ bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance ) // zoning within the same zone won't cause the prev data to be overwritten if( instance->getTerritoryTypeId() != m_territoryTypeId ) { - m_prevPos = m_pos; - m_prevRot = m_rot; - m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); - m_prevTerritoryId = getTerritoryId(); + // never returning to a BeforeTrialDung zone. + if( currentZone->getTerritoryTypeInfo()->territoryIntendedUse != Sapphire::World::Manager::TerritoryMgr::TerritoryIntendedUse::BeforeTrialDung ) + { + m_prevPos = m_pos; + m_prevRot = m_rot; + m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); + m_prevTerritoryId = getTerritoryId(); + } } return teriMgr.movePlayer( instance, getAsPlayer() ); @@ -488,10 +549,14 @@ bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance, Common::FFXIV // zoning within the same zone won't cause the prev data to be overwritten if( instance->getTerritoryTypeId() != m_territoryTypeId ) { - m_prevPos = m_pos; - m_prevRot = m_rot; - m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); - m_prevTerritoryId = getTerritoryId(); + // never returning to a BeforeTrialDung zone. + if( currentZone->getTerritoryTypeInfo()->territoryIntendedUse != Sapphire::World::Manager::TerritoryMgr::TerritoryIntendedUse::BeforeTrialDung ) + { + m_prevPos = m_pos; + m_prevRot = m_rot; + m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); + m_prevTerritoryId = getTerritoryId(); + } } m_pos = pos; @@ -513,16 +578,22 @@ bool Sapphire::Entity::Player::exitInstance() { auto& teriMgr = Common::Service< TerritoryMgr >::ref(); - auto d = getCurrentTerritory()->getAsDirector(); + auto d = getCurrentTerritory()->getAsInstanceContent(); if( d && d->getContentFinderConditionId() > 0 ) { - auto p = makeZonePacket< FFXIVDirectorUnk4 >( getId() ); + // shows correct name when leaving dungeon + auto p = makeZonePacket< FFXIVDirectorMsg4 >( getId() ); p->data().param[0] = d->getDirectorId(); p->data().param[1] = 1534; p->data().param[2] = 1; - p->data().param[3] = d->getContentFinderConditionId(); + p->data().param[3] = d->getContentId(); queuePacket( p ); + auto p2 = makeZonePacket< FFXIVIpcCFUnk >( getId() ); + p2->data().cfConditionId = d->getContentFinderConditionId(); + p2->data().five = 5; + queuePacket( p2 ); + prepareZoning( 0, 1, 1, 0, 0, 1, 9 ); } @@ -637,9 +708,9 @@ void Sapphire::Entity::Player::discover( int16_t map_id, int16_t sub_id ) } if( info->discoveryArrayByte ) - offset = 5 + 2 * info->discoveryIndex; + offset = 2 * info->discoveryIndex; else - offset = 325 + 4 * info->discoveryIndex; + offset = 320 + 4 * info->discoveryIndex; int32_t index = offset + sub_id / 8; uint8_t bitIndex = sub_id % 8; @@ -1080,7 +1151,6 @@ bool Sapphire::Entity::Player::hasStateFlag( Common::PlayerStateFlag flag ) cons void Sapphire::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) { - auto prevOnlineStatus = getOnlineStatus(); int32_t iFlag = static_cast< uint32_t >( flag ); uint16_t index; @@ -1089,13 +1159,6 @@ void Sapphire::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) m_stateFlags[ index ] |= value; sendStateFlags(); - - auto newOnlineStatus = getOnlineStatus(); - - if( prevOnlineStatus != newOnlineStatus ) - sendToInRangeSet( makeActorControl( getId(), SetStatusIcon, - static_cast< uint8_t >( getOnlineStatus() ) ), true ); - } void Sapphire::Entity::Player::setStateFlags( std::vector< Common::PlayerStateFlag > flags ) @@ -1116,8 +1179,6 @@ void Sapphire::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) if( !hasStateFlag( flag ) ) return; - auto prevOnlineStatus = getOnlineStatus(); - int32_t iFlag = static_cast< uint32_t >( flag ); uint16_t index; @@ -1126,11 +1187,6 @@ void Sapphire::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) m_stateFlags[ index ] ^= value; sendStateFlags(); - - auto newOnlineStatus = getOnlineStatus(); - - if( prevOnlineStatus != newOnlineStatus ) - sendToInRangeSet( makeActorControl( getId(), SetStatusIcon, static_cast< uint8_t >( getOnlineStatus() ) ), true ); } void Sapphire::Entity::Player::update( uint64_t tickCount ) @@ -1356,6 +1412,14 @@ void Sapphire::Entity::Player::queuePacket( Network::Packets::FFXIVPacketBasePtr } +void Sapphire::Entity::Player::queuePacket( std::vector< Network::Packets::FFXIVPacketBasePtr > packets ) +{ + for( auto& packet : packets ) + { + queuePacket( packet ); + } +} + void Sapphire::Entity::Player::queueChatPacket( Network::Packets::FFXIVPacketBasePtr pPacket ) { auto& serverMgr = Common::Service< World::ServerMgr >::ref(); @@ -1974,10 +2038,10 @@ void Sapphire::Entity::Player::finishZoning() } } -void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent ) +void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint16_t rotation ) { sendToInRangeSet( makeActorControlTarget( getId(), ActorControlType::Emote, - emoteId, 0, isSilent ? 1 : 0, 0, targetId ) ); + emoteId, 0, isSilent ? 1 : 0, rotation, targetId ) ); } void Sapphire::Entity::Player::emoteInterrupt() @@ -2334,6 +2398,16 @@ bool Sapphire::Entity::Player::checkAction() return true; } +uint64_t Sapphire::Entity::Player::getPartyId() const +{ + return m_partyId; +} + +void Sapphire::Entity::Player::setPartyId( uint64_t partyId ) +{ + m_partyId = partyId; +} + std::vector< Sapphire::Entity::ShopBuyBackEntry >& Sapphire::Entity::Player::getBuyBackListForShop( uint32_t shopId ) { return m_shopBuyBackMap[ shopId ]; diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 2e36ba69..d0a94913 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -340,7 +340,7 @@ namespace Sapphire::Entity void equipSoulCrystal( ItemPtr pItem, bool updateClass ); /*! unequip a soul crystal, returning to the base class*/ - void unequipSoulCrystal( ItemPtr pItem ); + void unequipSoulCrystal(); /*! get player ilvl */ uint16_t getItemLevel() const; @@ -512,6 +512,7 @@ namespace Sapphire::Entity uint32_t getTerritoryTypeId() const; void forceZoneing( uint32_t zoneId ); + void forceZoneing( uint32_t zoneId, Sapphire::Common::FFXIVARR_POSITION3 pos, float rot, bool showZoneName ); /*! return player to preset homepoint */ void returnToHomepoint(); @@ -543,6 +544,11 @@ namespace Sapphire::Entity /*! returns the current online status */ uint64_t getOnlineStatusMask() const; + void addOnlineStatus( Common::OnlineStatus status ); + void addOnlineStatus( const std::vector< Common::OnlineStatus >& status ); + void removeOnlineStatus( Common::OnlineStatus status ); + void removeOnlineStatus( const std::vector< Common::OnlineStatus >& status ); + /*! perform a teleport of a specified type ( teleport,return,aethernet ) */ void teleport( uint16_t aetheryteId, uint8_t type = 1 ); @@ -769,6 +775,7 @@ namespace Sapphire::Entity /*! queue a packet for the player */ void queuePacket( Network::Packets::FFXIVPacketBasePtr pPacket ); + void queuePacket( std::vector< Network::Packets::FFXIVPacketBasePtr > packets ); /*! queue a char connection packet for the player */ void queueChatPacket( Network::Packets::FFXIVPacketBasePtr pPacket ); @@ -785,7 +792,7 @@ namespace Sapphire::Entity /*! return true if the player is marked for zoning */ bool isMarkedForZoning() const; - void emote( uint32_t emoteId, uint64_t targetId, bool isSilent ); + void emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint16_t rotation = 0 ); void emoteInterrupt(); @@ -1028,6 +1035,9 @@ namespace Sapphire::Entity void updateHuntingLog( uint16_t id ); + uint64_t getPartyId() const; + void setPartyId( uint64_t partyId ); + World::SessionPtr getSession(); uint64_t m_lastMoveTime; @@ -1097,21 +1107,21 @@ namespace Sapphire::Entity uint16_t m_activeTitle; uint8_t m_titleList[48]; - uint8_t m_howTo[35]; - uint8_t m_minions[56]; - uint8_t m_mountGuide[29]; + uint8_t m_howTo[36]; + uint8_t m_minions[60]; + uint8_t m_mountGuide[33]; uint8_t m_homePoint; uint8_t m_startTown; uint16_t m_townWarpFstFlags; uint8_t m_questCompleteFlags[487]; - uint8_t m_discovery[464]; + uint8_t m_discovery[480]; uint32_t m_playTime; uint16_t m_classArray[ Common::CLASSJOB_SLOTS ]; uint32_t m_expArray[ Common::CLASSJOB_SLOTS ]; - uint8_t m_aetheryte[21]; + uint8_t m_aetheryte[26]; uint8_t m_unlocks[64]; - uint8_t m_orchestrion[64]; + uint8_t m_orchestrion[87]; uint8_t m_openingSequence; @@ -1181,6 +1191,8 @@ namespace Sapphire::Entity Common::Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator; Common::Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; + uint64_t m_partyId; + std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries; std::unordered_map< uint32_t, std::vector< ShopBuyBackEntry > > m_shopBuyBackMap; }; diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index b3bedbb0..c818244a 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -148,9 +148,9 @@ void Sapphire::Entity::Player::equipSoulCrystal( ItemPtr pItem, bool updateJob ) void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapphire::ItemPtr& pItem, bool updateClass ) { - uint64_t model = pItem->getModelId1(); - uint64_t model2 = pItem->getModelId2(); - uint64_t stain = pItem->getStain(); + uint64_t model = pItem ? pItem->getModelId1() : 0; + uint64_t model2 = pItem ? pItem->getModelId2() : 0; + uint64_t stain = pItem ? pItem->getStain() : 0; switch( equipSlotId ) { @@ -172,7 +172,10 @@ void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapp break; case SoulCrystal: - equipSoulCrystal( pItem, updateClass ); + if( pItem ) + equipSoulCrystal( pItem, updateClass ); + else + unequipSoulCrystal(); break; case Waist: @@ -265,15 +268,12 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite if( sendUpdate ) { + updateModels( equipSlotId, nullptr, true ); sendModel(); - m_itemLevel = calculateEquippedGearItemLevel(); sendItemLevel(); } - if ( equipSlotId == SoulCrystal ) - unequipSoulCrystal( pItem ); - auto baseParams = pItem->getBaseParams(); for( auto i = 0; i < 6; ++i ) { @@ -293,7 +293,7 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite } } -void Sapphire::Entity::Player::unequipSoulCrystal( ItemPtr pItem ) +void Sapphire::Entity::Player::unequipSoulCrystal() { auto& exdData = Common::Service< Sapphire::Data::ExdDataGenerated >::ref(); @@ -547,38 +547,6 @@ void Sapphire::Entity::Player::writeInventory( InventoryType type ) db.execute( query ); } -void Sapphire::Entity::Player::updateItemDb( Sapphire::ItemPtr pItem ) const -{ - if( pItem->getUId() == 0 ) - writeItemDb( pItem ); - - auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); - auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); - - // todo: add more fields - stmt->setInt( 1, pItem->getStackSize() ); - stmt->setInt( 2, pItem->getDurability() ); - stmt->setInt( 3, pItem->getStain() ); - - stmt->setInt64( 4, pItem->getUId() ); - - db.directExecute( stmt ); -} - -void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const -{ - if( item->getUId() == 0 ) - return; - - auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); - auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); - - stmt->setInt64( 1, item->getUId() ); - - db.directExecute( stmt ); -} - - bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity ) { return true; @@ -748,7 +716,19 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); if( tmpItem == nullptr ) + { + sendUrgent( "trying to move EMPTY item from [container{}, slot{}] to [container{}, slot{}], potential client desync, no action is performed.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); return; + } + + if( auto target = m_storageMap[ toInventoryId ]->getItem( toSlot ) ) + { + sendUrgent( "trying to move item from [container{}, slot{}] to NON-EMPTY [container{}, slot{}], potential client desync, swapItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + swapItem( fromInventoryId, fromSlotId, toInventoryId, toSlot, sendUpdate ); + return; + } itemMap[ fromSlotId ].reset(); @@ -885,8 +865,28 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot ); auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); - if( fromItem == nullptr || toItem == nullptr ) + if( fromItem == nullptr && toItem == nullptr ) + { + sendUrgent( "trying to swap TWO EMPTY ITEMS from [container{}, slot{}] to [container{}, slot{}], potential client desync, no action is performed.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); return; + } + + if( fromItem != nullptr && toItem == nullptr ) + { + sendUrgent( "trying to swap item from [container{}, slot{}] to EMPTY [container{}, slot{}], potential client desync, moveItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + moveItem( fromInventoryId, fromSlotId, toInventoryId, toSlot, sendUpdate ); + return; + } + + if( fromItem == nullptr && toItem != nullptr ) + { + sendUrgent( "trying to swap EMPTY item from [container{}, slot{}] to [container{}, slot{}], potential client desync, moveItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + moveItem( toInventoryId, toSlot, fromInventoryId, fromSlotId, sendUpdate ); // we are moving the non-empty toSlot back to fromSlot. + return; + } // An item is being moved from bag0-3 to equippment, meaning // the swapped out item will be placed in the matching armory. diff --git a/src/world/Actor/PlayerSql.cpp b/src/world/Actor/PlayerSql.cpp index bd3fe3d3..4b0bb68b 100644 --- a/src/world/Actor/PlayerSql.cpp +++ b/src/world/Actor/PlayerSql.cpp @@ -650,10 +650,13 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); uint8_t flags = 0; + if( pItem->isHq() ) + flags |= Common::ItemFlag::FlagHq; pItem->setUId( itemMgr.getNextUId() ); - std::string sql = "INSERT INTO charaglobalitem ( CharacterId, itemId, catalogId, stack, flags ) VALUES ( " + + std::string sql = "INSERT INTO charaglobalitem ( CharacterId, itemId, reservedFlag, catalogId, stack, flags ) VALUES ( " + std::to_string( getId() ) + ", " + std::to_string( pItem->getUId() ) + ", " + + std::to_string( pItem->getReservedFlag() ) + ", " + std::to_string( pItem->getId() ) + ", " + std::to_string( pItem->getStackSize() ) + ", " + std::to_string( flags ) + ");"; @@ -661,6 +664,46 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const } } +void Sapphire::Entity::Player::updateItemDb( Sapphire::ItemPtr pItem ) const +{ + if( pItem->getUId() == 0 ) + { + writeItemDb( pItem ); + return; + } + + uint8_t flags = 0; + if( pItem->isHq() ) + flags |= Common::ItemFlag::FlagHq; + + auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); + auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); + + // todo: add more fields + stmt->setInt( 1, pItem->getStackSize() ); + stmt->setInt( 2, pItem->getDurability() ); + stmt->setInt( 3, flags ); + stmt->setInt( 4, pItem->getReservedFlag() ); + stmt->setInt( 5, pItem->getStain() ); + + stmt->setInt64( 6, pItem->getUId() ); + + db.directExecute( stmt ); +} + +void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const +{ + if( item->getUId() == 0 ) + return; + + auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); + auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); + + stmt->setInt64( 1, item->getUId() ); + + db.directExecute( stmt ); +} + bool Sapphire::Entity::Player::loadInventory() { auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); diff --git a/src/world/Manager/ChatChannelMgr.cpp b/src/world/Manager/ChatChannelMgr.cpp new file mode 100644 index 00000000..1fd0e50c --- /dev/null +++ b/src/world/Manager/ChatChannelMgr.cpp @@ -0,0 +1,144 @@ +#include +#include +#include + +#include "ChatChannelMgr.h" + +#include "Actor/Player.h" +#include "ServerMgr.h" +#include "Session.h" +#include "Network/GameConnection.h" + +using namespace Sapphire; +using namespace Sapphire::Network; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::World::Manager; + +const uint64_t ChatChannelMgr::createChatChannel( Common::ChatChannelType type ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + + // get next id for new channel + + uint32_t cNo = m_lastChatNo; + + m_lastChatNo++; + + uint16_t chatType = static_cast< uint16_t >( type ); + uint16_t worldId = server.getWorldId(); + + Data::ChatChannel cId; + + cId.data.ChannelNo = cNo; + cId.data.ChannelType = type; + cId.data.WorldId = worldId; + + // create our new chat channel + + Data::ChatChannelMembers newChatChannel = {}; + + m_channels[ cId.ChannelID ] = newChatChannel; + + Logger::debug( "Chat channel ID " + + std::to_string( cId.ChannelID ) + + " created" + ); + + return cId.ChannelID; +} + +void ChatChannelMgr::addToChannel( uint64_t channelId, Entity::Player& player ) +{ + if( !isChannelValid( channelId ) ) + { + // channel id is invalid + + Logger::warn( "Attempted to add player " + + std::to_string( player.getId() ) + + " to invalid channel ID " + + std::to_string( channelId ) + ); + + return; + } + + auto& channelMembers = m_channels[ channelId ]; + auto id = player.getId(); + + if( std::find( channelMembers.begin(), channelMembers.end(), id ) == channelMembers.end() ) + m_channels[ channelId ].emplace_back( id ); +} + +void ChatChannelMgr::removeFromChannel( uint64_t channelId, Entity::Player& player ) +{ + if( !isChannelValid( channelId ) ) + { + // channel id is invalid + + Logger::warn( "Attempted to remove player " + + std::to_string( player.getId() ) + + " from invalid channel ID " + + std::to_string( channelId ) + ); + + return; + } + + auto& channelMembers = m_channels[ channelId ]; + auto id = player.getId(); + + auto it = std::find( channelMembers.begin(), channelMembers.end(), id ); + if( it != channelMembers.end() ) + channelMembers.erase( it ); +} + +void ChatChannelMgr::sendMessageToChannel( uint64_t channelId, Entity::Player& sender, const std::string& message ) +{ + if( !isChannelValid( channelId ) ) + { + // channel id is invalid + + Logger::warn( "Attempted to send message from player " + + std::to_string( sender.getId() ) + + " to invalid channel ID " + + std::to_string( channelId ) + ); + + return; + } + + auto& channelMembers = m_channels[ channelId ]; + + auto& server = Common::Service< World::ServerMgr >::ref(); + + // send message to all players in chat channel + for( const auto id : channelMembers ) + { + // skip sender from getting their own message + if( id == sender.getId() ) + continue; + + auto pPlayer = server.getSession( id )->getPlayer(); + + // check if player is online to recv message + if( !pPlayer/*->isConnected()*/ ) + continue; + + // prepare message packet, associating message and sender info with channel data + auto chatToChannelPacket = std::make_shared< Packets::Server::ChannelChatPacket >( *pPlayer, sender, channelId, message ); + pPlayer->queueChatPacket( chatToChannelPacket ); + } +} + +bool ChatChannelMgr::isChannelValid( uint64_t channelId ) const +{ + return !( m_channels.find( channelId ) == m_channels.end() ); +} + +const Data::ChatChannelMembers& ChatChannelMgr::getChatChannel( uint64_t channelId ) +{ + bool channelValid = isChannelValid( channelId ); + assert( channelValid ); + + return m_channels[ channelId ]; +} \ No newline at end of file diff --git a/src/world/Manager/ChatChannelMgr.h b/src/world/Manager/ChatChannelMgr.h new file mode 100644 index 00000000..16dec38e --- /dev/null +++ b/src/world/Manager/ChatChannelMgr.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include "ForwardsZone.h" + +namespace Sapphire::Data +{ + using ChatChannelMembers = std::vector< uint32_t >; + + union ChatChannel + { + uint64_t ChannelID; + + struct ChannelData { + uint32_t ChannelNo; + uint16_t ChannelType; + uint16_t WorldId; + } data; + }; +} + +namespace Sapphire::World::Manager +{ + class ChatChannelMgr + { + public: + ChatChannelMgr() = default; + ~ChatChannelMgr() = default; + + const uint64_t createChatChannel( Common::ChatChannelType type ); + + void addToChannel( uint64_t channelId, Entity::Player& player ); + void removeFromChannel( uint64_t channelId, Entity::Player& player ); + + void sendMessageToChannel( uint64_t channelId, Entity::Player& sender, const std::string& message ); + + bool isChannelValid( uint64_t channelId ) const; + const Data::ChatChannelMembers& getChatChannel( uint64_t channelId ); + + private: + std::map< uint64_t, Data::ChatChannelMembers > m_channels; + uint32_t m_lastChatNo = 0x1000; + }; +} \ No newline at end of file diff --git a/src/world/Manager/ItemMgr.cpp b/src/world/Manager/ItemMgr.cpp index c8331dac..01d2b03c 100644 --- a/src/world/Manager/ItemMgr.cpp +++ b/src/world/Manager/ItemMgr.cpp @@ -132,15 +132,16 @@ Sapphire::ItemPtr Sapphire::World::Manager::ItemMgr::loadItem( uint64_t uId ) try { auto itemInfo = exdData.get< Sapphire::Data::Item >( itemRes->getUInt( 1 ) ); - bool isHq = itemRes->getUInt( 3 ) == 1; + bool isHq = itemRes->getUInt( 5 ) & Common::ItemFlag::FlagHq; ItemPtr pItem = make_Item( uId, itemRes->getUInt( 1 ), isHq ); pItem->setStackSize( itemRes->getUInt( 2 ) ); - pItem->setStain( itemRes->getUInt16( 13 ) ); + pItem->setReservedFlag( itemRes->getUInt( 3 ) ); pItem->setDurability( itemRes->getInt16( 6 ) ); + pItem->setStain( itemRes->getUInt16( 13 ) ); return pItem; } diff --git a/src/world/Manager/PartyMgr.cpp b/src/world/Manager/PartyMgr.cpp new file mode 100644 index 00000000..4d00bfe1 --- /dev/null +++ b/src/world/Manager/PartyMgr.cpp @@ -0,0 +1,439 @@ +#include +#include +#include +#include + +#include +#include + +#include "Network/GameConnection.h" + +#include "PartyMgr.h" +#include "ServerMgr.h" +#include "ChatChannelMgr.h" +#include "PlayerMgr.h" + +#include "Session.h" + +#include "Actor/Player.h" + +#include "Network/PacketWrappers/PartyUpdatePacket.h" + +using namespace Sapphire; +using namespace Sapphire::World::Manager; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::Server; + +void PartyMgr::onJoin( Entity::Player& joiner, Entity::Player& inviter ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto& ccMgr = Common::Service< World::Manager::ChatChannelMgr >::ref(); + + auto& inviteePlayer = joiner; + auto& invitingPlayer = inviter; + + if( inviteePlayer.getPartyId() != 0 ) + { + Logger::error( "Player#{} already in a party, cannot be invited!!", inviteePlayer.getId() ); + return; + } + + uint64_t partyId; + // if there is no party yet, one has to be created + PartyPtr party; + if( inviteePlayer.getPartyId() == 0 && invitingPlayer.getPartyId() == 0 ) + { + partyId = createParty(); + party = getParty( partyId ); + assert( party ); + + inviteePlayer.setPartyId( partyId ); + inviteePlayer.addOnlineStatus( Common::OnlineStatus::PartyMember ); + invitingPlayer.setPartyId( partyId ); + invitingPlayer.addOnlineStatus( Common::OnlineStatus::PartyLeader ); + + ccMgr.addToChannel( party->ChatChannel, invitingPlayer ); + ccMgr.addToChannel( party->ChatChannel, inviteePlayer ); + + party->MemberId.push_back( invitingPlayer.getId() ); + party->MemberId.push_back( inviteePlayer.getId() ); + party->PartyCount = 2; + party->LeaderId = invitingPlayer.getId(); + } + else if( inviteePlayer.getPartyId() == 0 ) + { + partyId = invitingPlayer.getPartyId(); + party = getParty( partyId ); + + inviteePlayer.setPartyId( partyId ); + inviteePlayer.addOnlineStatus( Common::OnlineStatus::PartyMember ); + + ccMgr.addToChannel( party->ChatChannel, inviteePlayer ); + + party->MemberId.push_back( inviteePlayer.getId() ); + party->PartyCount++; + } + + auto pcUpdateParty = makePartyUpdate( invitingPlayer, inviteePlayer, UpdateStatus::JOINED, party->PartyCount ); + auto members = getPartyMembers( *party ); + sendPartyUpdate( *party ); + for( const auto& member : members ) + { + member->queuePacket( pcUpdateParty ); + } +} + +void PartyMgr::onLeave( Sapphire::Entity::Player &leavingPlayer ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + + auto party = getParty( leavingPlayer.getPartyId() ); + assert( party ); + + auto leadingPlayer = getPartyLeader( *party ); + assert( leadingPlayer ); + + if( !leadingPlayer ) + return; + + if( party->PartyCount == 2 ) + { + onDisband( *leadingPlayer ); + } + else + { + auto members = getPartyMembers( *party ); + removeMember( *party, leavingPlayer.getAsPlayer() ); + + uint32_t newLeaderId = 0; + for( const auto& member : members ) + { + if( member->getId() == leavingPlayer.getId() ) + { + member->removeOnlineStatus( { Common::OnlineStatus::PartyMember, + Common::OnlineStatus::PartyLeader } ); + + leavingPlayer.queuePacket( makeZonePacket< FFXIVIpcPartyList >( leavingPlayer.getId() ) ); + member->queuePacket( makePartyUpdate( leadingPlayer, nullptr, UpdateStatus::KICK_SELF, party->PartyCount ) ); + } + else + { + if( leavingPlayer.getId() == party->LeaderId ) + { + newLeaderId = party->MemberId[ 0 ]; + auto pPlayer = server.getSession( newLeaderId )->getPlayer(); + if( !pPlayer /*|| !pPlayer->isConnected() */) + continue; + pPlayer->addOnlineStatus( Common::OnlineStatus::PartyLeader ); + member->queuePacket( makePartyUpdate( leavingPlayer.getAsPlayer(), pPlayer, UpdateStatus::LEAVELEADER_LEAVED_MEMBER, party->PartyCount ) ); + } + else + { + member->queuePacket( makePartyUpdate( leavingPlayer.getAsPlayer(), nullptr, UpdateStatus::LEAVE_MEMBER, party->PartyCount ) ); + + } + } + } + if( newLeaderId != 0 ) + party->LeaderId = newLeaderId; + party->PartyCount--; + sendPartyUpdate( *party ); + } +} + +void PartyMgr::onDisband( Entity::Player& disbandingPlayer ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto party = getParty( disbandingPlayer.getPartyId() ); + assert( party ); + + auto members = getPartyMembers( *party ); + for( const auto& member : members ) + { + removeMember( *party, member ); + member->removeOnlineStatus( { Common::OnlineStatus::PartyMember, Common::OnlineStatus::PartyLeader } ); + member->queuePacket( { makePartyUpdate( disbandingPlayer, disbandingPlayer, UpdateStatus::DISBAND, party->PartyCount ), makeZonePacket< FFXIVIpcPartyList >( member->getId() ) } ); + } + + removeParty( party->PartyID ); +} + +void PartyMgr::onMoveZone( Sapphire::Entity::Player &movingPlayer ) +{ + if( movingPlayer.getPartyId() == 0 ) + { + movingPlayer.queuePacket( makeZonePacket< FFXIVIpcPartyList >( movingPlayer.getId() ) ); + return; + } + auto party = getParty( movingPlayer.getPartyId() ); + assert( party ); + sendPartyUpdate( *party ); +} + +void PartyMgr::onMemberDisconnect( Entity::Player& disconnectingPlayer ) +{ + if( disconnectingPlayer.getPartyId() == 0 ) + return; + + auto& server = Common::Service< World::ServerMgr >::ref(); + auto party = getParty( disconnectingPlayer.getPartyId() ); + assert( party ); + auto members = getPartyMembers( *party ); + auto pLeader = getPartyLeader( *party ); + + bool anyMembersOnline = false; + + for( const auto& member : members ) + { + if( member/*->isConnected()*/ ) + { + anyMembersOnline = true; + break; + } + } + + // if there are no party members online, destroy the party + if( !anyMembersOnline ) + return onDisband( *pLeader ); + + for( const auto& member : members ) + { + // TODO: 2nd argument here makes it automatically send passing leadership message + member->queuePacket( { makePartyUpdate( disconnectingPlayer, UpdateStatus::OFFLINE_MEMBER, party->PartyCount ), makeZonePacket< FFXIVIpcPartyList >( member->getId() ) } ); + } + + sendPartyUpdate( *party ); +} + +void PartyMgr::onMemberRejoin( Entity::Player& joiningPlayer ) +{ + auto party = getParty( joiningPlayer.getPartyId() ); + assert( party ); + + // TODO: do we need a party update here? move zone handler already handles it +} + +void PartyMgr::onKick( const std::string& kickPlayerName, Entity::Player& leader ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto party = getParty( leader.getPartyId() ); + assert( party ); + auto pLeader = getPartyLeader( *party ); + auto members = getPartyMembers( *party ); + auto pKickedPlayer = server.getSession( kickPlayerName )->getPlayer(); + if( !pKickedPlayer ) + { + Logger::error( "Target player for kicking not found (\"{t}\")", kickPlayerName ); + return; + } + + if( party->PartyCount == 2 ) + { + onDisband( *pLeader ); + } + else + { + for( const auto &member: members ) + { + if( kickPlayerName == member->getName() ) + { + removeMember( *party, member ); + member->removeOnlineStatus( Common::OnlineStatus::PartyMember ); + + member->queuePacket( { makePartyUpdate( *pLeader, *member, UpdateStatus::KICK_SELF, party->PartyCount ), + makeZonePacket< FFXIVIpcPartyList >( member->getId() ) } ); + } + else + { + member->queuePacket( makePartyUpdate( *pKickedPlayer, UpdateStatus::KICK_MEMBER, party->PartyCount ) ); + } + } + party->PartyCount--; + sendPartyUpdate( *party ); + } +} + +void PartyMgr::onChangeLeader( const std::string& newLeaderName, Entity::Player& oldLeader ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto party = getParty( oldLeader.getPartyId() ); + + auto pNewLeader = server.getSession( newLeaderName )->getPlayer(); + + if( !pNewLeader ) + { + Logger::error( "Target player for new leader not found (\"{t}\")", newLeaderName ); + return; + } + + for( auto memberId : party->MemberId ) + { + if( memberId == pNewLeader->getId() ) + { + pNewLeader->addOnlineStatus( Common::OnlineStatus::PartyLeader ); + // this is not ideal, probably better to have a function which can add + // and remove at the same time so packets are only triggered once + oldLeader.addOnlineStatus( Common::OnlineStatus::PartyMember ); + oldLeader.removeOnlineStatus( Common::OnlineStatus::PartyLeader ); + + party->LeaderId = pNewLeader->getId(); + break; + } + } + + auto members = getPartyMembers( *party ); + for( auto& member : members ) + { + auto pcUpdateParty = makePartyUpdate( oldLeader.getAsPlayer(), pNewLeader, UpdateStatus::CHANGELEADER, party->PartyCount ); + member->queuePacket( pcUpdateParty ); + } + + sendPartyUpdate( *party ); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +uint64_t PartyMgr::createParty() +{ + auto& chatChannelMgr = Common::Service< ChatChannelMgr >::ref(); + auto party = std::make_shared< Party >(); + party->PartyID = getNextPartyId(); + party->ChatChannel = chatChannelMgr.createChatChannel( Common::ChatChannelType::PartyChat ); + m_partyIdMap[ party->PartyID ] = party; + return party->PartyID; +} + +uint64_t PartyMgr::getNextPartyId() +{ + return ++m_maxPartyId; +} + +PartyPtr PartyMgr::getParty( uint64_t partyId ) +{ + auto it = m_partyIdMap.find( partyId ); + if( it != m_partyIdMap.end() ) + return it->second; + + return nullptr; +} + +std::vector< Entity::PlayerPtr > PartyMgr::getPartyMembers( Party& party ) +{ + std::vector< Entity::PlayerPtr > members; + + auto& server = Common::Service< World::ServerMgr >::ref(); + for( auto& memberId : party.MemberId ) + { + if( memberId == 0 ) + continue; + + auto pPlayer = server.getSession( memberId )->getPlayer(); + + members.push_back( pPlayer ); + } + return members; +} + +Entity::PlayerPtr PartyMgr::getPartyLeader( Party& party ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + + if( party.LeaderId == 0 ) + return nullptr; + + auto pLeader = server.getSession( party.LeaderId )->getPlayer(); + + return pLeader; +} + +void PartyMgr::sendPartyUpdate( Party& party ) +{ + auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); + auto partyMembers = getPartyMembers( party ); + std::vector< PartyMember > entries; + auto& server = Common::Service< World::ServerMgr >::ref(); + + for( const auto& member : partyMembers ) + { + auto classJob = exdData.get< Data::ClassJob >( static_cast< uint8_t >( member->getClass() ) ); + if( !classJob ) + continue; + + PartyMember memberEntry{}; + + memberEntry./*ParentEntityId*/u1 = Common::INVALID_GAME_OBJECT_ID; + memberEntry./*PetEntityId*/u2 = Common::INVALID_GAME_OBJECT_ID; + memberEntry.hp = member->getHp(); + memberEntry.maxHp = member->getMaxHp(); + memberEntry.mp = member->getMp(); + memberEntry.maxMp = member->getMaxMp(); + memberEntry.classId = static_cast< uint8_t >( member->getClass() ); + memberEntry.level = member->getLevel(); + //memberEntry.ObjType = 4; // 1 PC, 2 Buddy ?? + memberEntry.zoneId = member->getTerritoryTypeId(); + memberEntry./*Valid*/gposeSelectable = 1; + //memberEntry.Tp = member->getTp(); + //memberEntry.Role = classJob->role; + + entries.push_back( memberEntry ); + } + + for( const auto& pMember : partyMembers ) + { + size_t idx = 0; + + auto updatePartyPacket = makeZonePacket< FFXIVIpcPartyList >( partyMembers[ 0 ]->getId() ); + auto& data = updatePartyPacket->data(); + data.partyId = party.PartyID; + data.leaderIndex = getPartyLeaderIndex( party ); + data.channelId = party.ChatChannel; + data.partySize = party.PartyCount; + + for( const auto& member : partyMembers ) + { + bool isConnected = /*member->isConnected()*/true; + // if player is online and in the same zone as current member in party, display more data in partylist + bool hasInfo = isConnected && member->getTerritoryTypeId() == pMember->getTerritoryTypeId(); + + if( hasInfo ) + { + data.member[ idx ] = entries[ idx ]; + } + + data.member[ idx ].contentId = member->getContentId(); + data.member[ idx ].charaId = member->getId(); + strcpy( data.member[ idx ].name, member->getName().c_str() ); + + idx++; + } + + pMember->queuePacket( updatePartyPacket ); + } +} + +void PartyMgr::removeParty( uint64_t partyId ) +{ + m_partyIdMap.erase( partyId ); +} + +int8_t PartyMgr::getPartyLeaderIndex( const Party &party ) +{ + size_t idx = 0; + for( const auto& memberId : party.MemberId ) + { + if( memberId == party.LeaderId ) + return static_cast< int8_t >( idx ); + idx++; + } + return -1; +} + +void PartyMgr::removeMember( Party &party, const Entity::PlayerPtr& pMember ) +{ + auto& ccMgr = Common::Service< World::Manager::ChatChannelMgr >::ref(); + pMember->setPartyId( 0 ); + ccMgr.removeFromChannel( party.ChatChannel, *pMember ); + party.MemberId.erase( std::remove( party.MemberId.begin(), party.MemberId.end(), pMember->getId() ), party.MemberId.end() ); +} diff --git a/src/world/Manager/PartyMgr.h b/src/world/Manager/PartyMgr.h new file mode 100644 index 00000000..7548b35f --- /dev/null +++ b/src/world/Manager/PartyMgr.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Sapphire::World::Manager +{ + + enum UpdateStatus : int32_t + { + NONE_8 = 0x0, + JOINED = 0x1, + CHANGELEADER = 0x2, + DISBAND = 0x3, + KICK_MEMBER = 0x4, + KICK_SELF = 0x5, + LEAVE_MEMBER = 0x6, + LEAVE_SELF = 0x7, + MOVEZONE = 0x8, + MOVETERRITORY = 0x9, + OFFLINE_MEMBER = 0xA, + RECOVERY_MEMBER = 0xB, + LEAVELEADER_LEAVED_MEMBER = 0xC, + LEAVELEADER_LEAVED_SELF = 0xD, + ADDMEMBER_BUDDY = 0xE, + REMOVEMEMBER_BUDDY = 0xF, + SENDREADYCHECK = 0x10, + REPLYREADYCHECK = 0x11, + }; + + struct Party + { + std::vector< uint32_t > MemberId; + uint64_t PartyID; + uint64_t ChatChannel; + uint32_t LeaderId; + uint8_t PartyCount; + }; + + using PartyPtr = std::shared_ptr< Party >; + + class PartyMgr + { + public: + PartyMgr() = default; + + /// Perform required actions for events + void onJoin( Entity::Player& joiner, Entity::Player& inviter ); + void onLeave( Entity::Player& leavingPlayer ); + void onMoveZone( Entity::Player& movingPlayer ); + void onDisband( Entity::Player& disbandingPlayer ); + void onKick( const std::string& kickPlayerName, Entity::Player& leader ); + void onChangeLeader( const std::string& newLeaderName, Entity::Player& oldLeader ); + + void onMemberDisconnect( Entity::Player& disconnectingPlayer ); + void onMemberRejoin( Entity::Player& joiningPlayer ); + + void onJoinBuddy( Entity::Player& buddyOwner, Party& party ); + void onLeaveBuddy( Entity::Player& buddyOwner, Party& party ); + void onStartReadyCheck( Entity::Player& startingPlayer, Party& party ); + void onReplyReadyCheck( Entity::Player& replyingPlayer, Party& party ); + + /////////////////////////// + PartyPtr getParty( uint64_t partyId ); + + private: + // arbitrary start range for party ids + uint64_t m_maxPartyId = 0x0000044000000000; + + uint64_t createParty(); + void removeParty( uint64_t partyId ); + uint64_t getNextPartyId(); + std::unordered_map< uint64_t, PartyPtr > m_partyIdMap; + + static void sendPartyUpdate( Party& party ); + static void removeMember( Party& party, const Entity::PlayerPtr& pMember ); + static std::vector< Entity::PlayerPtr > getPartyMembers( Party& party ); + static Entity::PlayerPtr getPartyLeader( Party& party ); + + static int8_t getPartyLeaderIndex( const Party& party ); + + }; + +} diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 8b4703f6..bf20bcae 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -6,6 +6,7 @@ #include #include +#include "Manager/PartyMgr.h" #include "Actor/Player.h" @@ -759,6 +760,9 @@ bool Sapphire::World::Manager::TerritoryMgr::movePlayer( TerritoryPtr pZone, Sap pPlayer->sendZonePackets(); + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + partyMgr.onMoveZone( *pPlayer ); + return true; } diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 4601816f..6d0d8f58 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -15,7 +15,7 @@ using namespace Sapphire::Math; using namespace Sapphire::Entity; -const int levelTable[81][6] = +const int levelTable[91][6] = { // MAIN,SUB,DIV,HP,ELMT,THREAT { 1, 1, 1, 1, 1, 1 }, @@ -102,6 +102,16 @@ const int levelTable[81][6] = { 330, 376, 3034, 3600, 295, 466 }, { 335, 378, 3164, 3600, 295, 466 }, { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, }; std::random_device CalcStats::dev; diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index ef9be721..c2afcd0e 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -70,7 +70,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::ReqExamineFcInfo, "ReqExamineFcInfo", &GameConnection::reqExamineFcInfo ); setZoneHandler( ClientZoneIpcType::ZoneLineHandler, "ZoneLineHandler", &GameConnection::zoneLineHandler ); setZoneHandler( ClientZoneIpcType::ClientTrigger, "ClientTrigger", &GameConnection::clientTriggerHandler ); - + setZoneHandler( ClientZoneIpcType::ClientTriggerEnvironment, "ClientTriggerEnvironment", &GameConnection::clientTriggerHandler ); setZoneHandler( ClientZoneIpcType::DiscoveryHandler, "DiscoveryHandler", &GameConnection::discoveryHandler ); setZoneHandler( ClientZoneIpcType::SkillHandler, "ActionHandler", &GameConnection::actionHandler ); @@ -96,6 +96,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::HousingEditInterior, "HousingEditInterior", &GameConnection::housingEditInterior ); setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk ); + setZoneHandler( ClientZoneIpcType::SayEventHandler, "EventHandlerSay", &GameConnection::eventHandlerSay ); setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote ); setZoneHandler( ClientZoneIpcType::WithinRangeEventHandler, "EventHandlerWithinRange", &GameConnection::eventHandlerWithinRange ); @@ -137,13 +138,20 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemListings, "MarketBoardRequestItemListings", &GameConnection::marketBoardRequestItemListings ); - setZoneHandler( ClientZoneIpcType::WorldInteractionHandler, "WorldInteractionHandler", &GameConnection::worldInteractionhandler ); setZoneHandler( ClientZoneIpcType::Dive, "Dive", &GameConnection::diveHandler ); setZoneHandler( ClientZoneIpcType::InventoryEquipRecommendedItems, "InventoryEquipRecommendedItemsHandler", &GameConnection::inventoryEquipRecommendedItemsHandler ); setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler ); + setChatHandler( ClientChatIpcType::ChannelChatReq, "ChannelChatReq", &GameConnection::channelChatHandler ); + setZoneHandler( ClientZoneIpcType::SocialInviteHandler, "SocialInviteHandler", &GameConnection::socialInviteHandler ); + setZoneHandler( ClientZoneIpcType::SocialReplyHandler, "SocialReplyHandler", &GameConnection::socialReplyHandler ); + + setZoneHandler( ClientZoneIpcType::PartyLeaveHandler, "PartyLeaveHandler", &GameConnection::partyLeaveHandler ); + setZoneHandler( ClientZoneIpcType::PartyDisbandHandler, "PartyDisbandHandler", &GameConnection::partyDisbandHandler ); + setZoneHandler( ClientZoneIpcType::PartyKickHandler, "PartyKickHandler", &GameConnection::partyKickHandler ); + setZoneHandler( ClientZoneIpcType::PartyChangeLeaderHandler, "PartyChangeLeaderHandler", &GameConnection::partyChangeLeaderHandler ); } Sapphire::Network::GameConnection::~GameConnection() = default; diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index c8ff3e97..b11c62b7 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -133,6 +133,8 @@ namespace Sapphire::Network DECLARE_HANDLER( eventHandlerTalk ); + DECLARE_HANDLER( eventHandlerSay ); + DECLARE_HANDLER( eventHandlerEmote ); DECLARE_HANDLER( eventHandlerWithinRange ); @@ -179,6 +181,8 @@ namespace Sapphire::Network DECLARE_HANDLER( tellHandler ); + DECLARE_HANDLER( channelChatHandler ); + DECLARE_HANDLER( reqPlaceHousingItem ); DECLARE_HANDLER( reqMoveHousingItem ); @@ -200,6 +204,14 @@ namespace Sapphire::Network DECLARE_HANDLER( eventYieldHandler ); DECLARE_HANDLER( inventoryEquipRecommendedItemsHandler ); + + DECLARE_HANDLER( socialInviteHandler ); + DECLARE_HANDLER( socialReplyHandler ); + + DECLARE_HANDLER( partyLeaveHandler ); + DECLARE_HANDLER( partyDisbandHandler ); + DECLARE_HANDLER( partyKickHandler ); + DECLARE_HANDLER( partyChangeLeaderHandler ); }; } diff --git a/src/world/Network/Handlers/CFHandlers.cpp b/src/world/Network/Handlers/CFHandlers.cpp index 9778d37c..ca281f92 100644 --- a/src/world/Network/Handlers/CFHandlers.cpp +++ b/src/world/Network/Handlers/CFHandlers.cpp @@ -46,7 +46,7 @@ void Sapphire::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_ Packets::FFXIVARR_PACKET_RAW copy = inPacket; std::vector< uint16_t > selectedContent; - for( uint32_t offset = 0x1E; offset <= 0x26; offset += 0x2 ) + for( uint32_t offset = 0x2A; offset <= 0x32; offset += 0x2 ) { auto id = *reinterpret_cast< uint16_t* >( ©.data[ offset ] ); if( id == 0 ) @@ -64,9 +64,9 @@ void Sapphire::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_ player.sendDebug( "Duty register request for contentFinderConditionId#{0}", contentFinderConditionId ); player.m_cfNotifiedContent = contentFinderConditionId; auto notify = makeZonePacket< FFXIVIpcCFNotify >( player.getId() ); - notify->data().state1 = 8195; - notify->data().param3 = 1; - notify->data().param4 = contentFinderConditionId; + notify->data().state1 = 3; + notify->data().unknown_one = 1; + notify->data().contents[ 0 ] = contentFinderConditionId; player.queuePacket( notify ); } diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index 25dd4efb..8c60c233 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -8,8 +8,12 @@ #include #include +#include +#include + #include "Territory/Territory.h" #include "Territory/ZonePosition.h" +#include #include "Manager/HousingMgr.h" #include "Network/GameConnection.h" @@ -70,16 +74,15 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket ); const auto commandId = packet.data().commandId; - const auto param1 = *reinterpret_cast< const uint64_t* >( &packet.data().param11 ); - const auto param11 = packet.data().param11; - const auto param12 = packet.data().param12; - const auto param2 = packet.data().param2; - const auto param3 = packet.data().param3; - const auto param4 = packet.data().param4; - const auto param5 = packet.data().param5; + const auto p1u64 = *reinterpret_cast< const uint64_t* >( &packet.data().param1 ); + const auto p1 = packet.data().param1; + const auto p2 = packet.data().param2; + const auto p3 = packet.data().param3; + const auto p4 = packet.data().param4; + const auto pos = packet.data().position; - Logger::debug( "[{0}] Incoming action: {1:X} ( p1:{2:X} p2:{3:X} p3:{4:X} )", - m_pSession->getId(), commandId, param1, param2, param3 ); + Logger::debug( "[{0}] Type: {1:X} (p1u64:{2:X} p1:{3} p2:{4} p3:{5} p4:{6} x:{7} y:{8} z:{9}", + m_pSession->getId(), commandId, p1u64, p1, p2, p3, p4, pos.x, pos.y, pos.z ); //Logger::Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString()); @@ -87,7 +90,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { case ClientTriggerType::ToggleSheathe: // Toggle sheathe { - if( param11 == 1 ) + if( p1 == 1 ) player.setStance( Common::Stance::Active ); else { @@ -95,13 +98,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX player.setAutoattack( false ); } - player.sendToInRangeSet( makeActorControl( player.getId(), 0, param11, 1 ) ); + player.sendToInRangeSet( makeActorControl( player.getId(), 0, p1, 1 ) ); break; } case ClientTriggerType::ToggleAutoAttack: // Toggle auto-attack { - if( param11 == 1 ) + if( p1 == 1 ) { player.setAutoattack( true ); player.setStance( Common::Stance::Active ); @@ -110,15 +113,15 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX player.setAutoattack( false ); // 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 ) ); + player.queuePacket( makeActorControl( player.getId(), 1, p1, 1 ) ); + //player.sendToInRangeSet( makeActorControl( player.getId(), 1, p1, 1 ) ); break; } case ClientTriggerType::ChangeTarget: // Change target { - uint64_t targetId = param1; + uint64_t targetId = p1u64; player.changeTarget( targetId ); break; } @@ -129,7 +132,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::SpawnCompanionReq: { - player.spawnCompanion( static_cast< uint16_t >( param1 ) ); + player.spawnCompanion( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::DespawnCompanionReq: @@ -140,7 +143,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd - player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) ); + player.removeSingleStatusEffectById( static_cast< uint32_t >( p1 ) ); break; } case ClientTriggerType::CastCancel: // Cancel cast @@ -151,7 +154,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::Examine: { - uint32_t targetId = param11; + uint32_t targetId = p1u64; examineHandler( player, targetId ); break; } @@ -161,7 +164,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::SetTitleReq: // Set player title { - player.setTitle( static_cast< uint16_t >( param1 ) ); + player.setTitle( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::TitleList: // Get title list @@ -171,13 +174,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen { - uint32_t howToId = param11; + uint32_t howToId = p1; player.updateHowtosSeen( howToId ); break; } case ClientTriggerType::CharaNameReq: { - uint64_t targetContentId = param1; + uint64_t targetContentId = p1u64; // todo: look up player by content id /* auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() ); @@ -192,10 +195,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX break; } case ClientTriggerType::EmoteReq: // emote + case ClientTriggerType::EmoteWithWarp: { uint64_t targetId = player.getTargetId(); - uint32_t emoteId = param11; - bool isSilent = param2 == 1; + uint32_t emoteId = p1; + bool isSilent = p3 == 1; auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); auto emoteData = exdData.get< Data::Emote >( emoteId ); @@ -203,7 +207,23 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX if( !emoteData ) return; - player.emote( emoteId, targetId, isSilent ); + if( commandId == ClientTriggerType::EmoteWithWarp ) + { + player.setPos( packet.data().position ); + player.setRot( Util::floatFromUInt16Rot( static_cast< uint16_t >( p4 ) ) ); + if( player.hasInRangeActor() ) + { + auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setpos->data().r16 = static_cast< uint16_t >( p4 ); + setpos->data().waitForLoad = 18; + setpos->data().x = packet.data().position.x; + setpos->data().y = packet.data().position.y; + setpos->data().z = packet.data().position.z; + player.sendToInRangeSet( setpos, false ); + } + } + + player.emote( emoteId, targetId, isSilent, commandId == ClientTriggerType::EmoteWithWarp ? static_cast< uint16_t >( p4 ) : 0 ); bool isPersistent = emoteData->emoteMode != 0; @@ -213,10 +233,6 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX player.setAutoattack( false ); player.setPersistentEmote( emoteData->emoteMode ); player.setStatus( Common::ActorStatus::EmoteMode ); - - player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::SetStatus, - static_cast< uint8_t >( Common::ActorStatus::EmoteMode ), - emoteData->hasCancelEmote ? 1 : 0 ), true ); } if( emoteData->drawsWeapon ) @@ -226,38 +242,52 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX break; } - case ClientTriggerType::EmoteCancel: // emote - { - player.emoteInterrupt(); - break; - } + case ClientTriggerType::EmoteCancel: // emote cancel case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote + case ClientTriggerType::EmoteCancelWithWarp: { - player.setPersistentEmote( 0 ); + if( commandId == ClientTriggerType::EmoteCancelWithWarp ) + { + player.setPos( packet.data().position ); + if( player.hasInRangeActor() ) + { + auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setpos->data().r16 = p2; + setpos->data().waitForLoad = 18; + setpos->data().x = packet.data().position.x; + setpos->data().y = packet.data().position.y; + setpos->data().z = packet.data().position.z; + player.sendToInRangeSet( setpos, false ); + } + } player.emoteInterrupt(); - player.setStatus( Common::ActorStatus::Idle ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); - player.sendToInRangeSet( pSetStatusPacket ); + if( player.getPersistentEmote() ) + { + player.setPersistentEmote( 0 ); + player.setStatus( Common::ActorStatus::Idle ); + auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); + player.sendToInRangeSet( pSetStatusPacket ); + } break; } case ClientTriggerType::PoseChange: // change pose case ClientTriggerType::PoseReapply: // reapply pose { - player.setPose( static_cast< uint8_t >( param12 ) ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 ); + player.setPose( static_cast< uint8_t >( p2 ) ); + auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, p1, p2 ); player.sendToInRangeSet( pSetStatusPacket, true ); break; } case ClientTriggerType::PoseCancel: // cancel pose { - player.setPose( static_cast< uint8_t >( param12 ) ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 ); + player.setPose( static_cast< uint8_t >( p2 ) ); + auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, p1, p2 ); player.sendToInRangeSet( pSetStatusPacket, false ); break; } case ClientTriggerType::Return: // return dead / accept raise { - switch( static_cast < ResurrectType >( param1 ) ) + switch( static_cast < ResurrectType >( p1 ) ) { case ResurrectType::RaiseSpell: // todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet) @@ -280,16 +310,16 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX case ClientTriggerType::Teleport: // Teleport { - player.teleportQuery( static_cast< uint16_t >( param11 ) ); + player.teleportQuery( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::DyeItem: // Dye item { - // param11 = item to dye container - // param12 = item to dye slot - // param2 = dye bag container - // param4 = dye bag slot - player.setDyeingInfo( param11, param12, param2, param4 ); + // p1 = item to dye container + // p2 = item to dye slot + // p3 = dye bag container + // p4 = dye bag slot + player.setDyeingInfo( p1, p2, p3, p4 ); break; } case ClientTriggerType::DirectorInitFinish: // Director init finish @@ -315,7 +345,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::AbandonQuest: { - player.removeQuest( static_cast< uint16_t >( param1 ) ); + player.removeQuest( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::RequestHousingBuildPreset: @@ -325,9 +355,9 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX if (!hZone) return; - player.setActiveLand( static_cast< uint8_t >( param11 ), hZone->getWardNum() ); + player.setActiveLand( static_cast< uint8_t >( p1 ), hZone->getWardNum() ); - auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, param11 ); + auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, p1 ); player.queuePacket( pShowBuildPresetUIPacket ); break; @@ -336,7 +366,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.sendLandSignFree( player, ident ); break; @@ -345,7 +375,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12, false ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2, false ); housingMgr.sendLandSignOwned( player, ident ); break; @@ -354,7 +384,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - housingMgr.sendWardLandInfo( player, static_cast< uint8_t >( param12 ), static_cast< uint8_t >( param11 ) ); + housingMgr.sendWardLandInfo( player, static_cast< uint8_t >( p2 ), static_cast< uint8_t >( p1 ) ); break; } @@ -362,7 +392,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto plot = static_cast< uint8_t >( param12 & 0xFF ); + auto plot = static_cast< uint8_t >( p2 & 0xFF ); housingMgr.relinquishLand( player, plot ); break; @@ -371,7 +401,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.requestEstateRename( player, ident ); break; @@ -380,7 +410,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.requestEstateEditGreeting( player, ident ); break; @@ -389,7 +419,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.requestEstateEditGuestAccess( player, ident ); break; @@ -397,13 +427,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX case ClientTriggerType::RequestHousingItemUI: { // close ui - if( param11 == 1 ) + if( p1 == 1 ) break; - // param12 is 0 when inside a house + // p2 is 0 when inside a house - uint8_t ward = ( param12 >> 16 ) & 0xFF; - uint8_t plot = ( param12 & 0xFF ); + uint8_t ward = ( p2 >> 16 ) & 0xFF; + uint8_t plot = ( p2 & 0xFF ); auto pShowHousingItemUIPacket = makeActorControl( player.getId(), ShowHousingItemUI, 0, plot ); player.queuePacket( pShowHousingItemUIPacket ); @@ -416,19 +446,19 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.sendEstateGreeting( player, ident ); break; } case ClientTriggerType::RequestLandInventory: { - uint8_t plot = ( param12 & 0xFF ); + uint8_t plot = ( p2 & 0xFF ); auto& housingMgr = Common::Service< HousingMgr >::ref(); uint16_t inventoryType = Common::InventoryType::HousingExteriorPlacedItems; - if( param2 == 1 ) + if( p3 == 1 ) inventoryType = Common::InventoryType::HousingExteriorStoreroom; housingMgr.sendEstateInventory( player, inventoryType, plot ); @@ -439,10 +469,10 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - // param1 = 1 - storeroom - // param1 = 0 - placed items + // p1 = 1 - storeroom + // p1 = 0 - placed items - if( param1 == 1 ) + if( p1 == 1 ) housingMgr.sendInternalEstateInventoryBatch( player, true ); else housingMgr.sendInternalEstateInventoryBatch( player ); @@ -453,11 +483,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto slot = param4 & 0xFF; - auto sendToStoreroom = ( param4 >> 16 ) != 0; + auto slot = p4 & 0xFF; + auto sendToStoreroom = ( p4 >> 16 ) != 0; //player, plot, containerId, slot, sendToStoreroom - housingMgr.reqRemoveHousingItem( player, static_cast< uint16_t >( param12 ), static_cast< uint16_t >( param2 ), static_cast< uint8_t >( slot ), sendToStoreroom ); + housingMgr.reqRemoveHousingItem( player, static_cast< uint16_t >( p2 ), static_cast< uint16_t >( p3 ), static_cast< uint8_t >( slot ), sendToStoreroom ); break; } @@ -465,7 +495,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - housingMgr.reqEstateExteriorRemodel( player, static_cast< uint16_t >( param11 ) ); + housingMgr.reqEstateExteriorRemodel( player, static_cast< uint16_t >( p1 ) ); break; } @@ -481,16 +511,16 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - housingMgr.removeHouse( player, static_cast< uint16_t >( param11 ) ); + housingMgr.removeHouse( player, static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::UpdateEstateGuestAccess: { - auto canTeleport = ( param2 & 0xFF ) == 1; - auto unk1 = ( param2 >> 8 & 0xFF ) == 1; // todo: related to fc? or unused? - auto privateEstateAccess = ( param2 >> 16 & 0xFF ) == 1; - auto unk = ( param2 >> 24 & 0xFF ) == 1; // todo: related to fc? or unused? + auto canTeleport = ( p3 & 0xFF ) == 1; + auto unk1 = ( p3 >> 8 & 0xFF ) == 1; // todo: related to fc? or unused? + auto privateEstateAccess = ( p3 >> 16 & 0xFF ) == 1; + auto unk = ( p3 >> 24 & 0xFF ) == 1; // todo: related to fc? or unused? player.sendDebug( "can teleport: {0}, unk: {1}, privateEstateAccess: {2}, unk: {3}", canTeleport, unk1, privateEstateAccess, unk ); @@ -498,36 +528,34 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::RequestEventBattle: { - auto packet = makeActorControlSelf( player.getId(), ActorControl::EventBattleDialog, 0, param12, param2 ); + auto packet = makeActorControlSelf( player.getId(), ActorControl::EventBattleDialog, 0, p2, p3 ); player.queuePacket( packet ); - - player.sendDebug( "event battle p1: {0}, p11: {1}, p12: {2}, p2: {3}, p3: {4}, p4: {5}, p5: {6}", param1, param11, param12, param2, param3, param4, param5 ); break; } case ClientTriggerType::CutscenePlayed: { - player.sendDebug( "cutscene: {}", param1 ); + player.sendDebug( "cutscene: {}", p1 ); break; } case ClientTriggerType::OpenPerformInstrumentUI: { - //param11 = instrument, 0 = end - player.sendDebug( "perform: {}", param11 ); - if( param11 == 0 ) + //p1 = instrument, 0 = end + player.sendDebug( "perform: {}", p1 ); + if( p1 == 0 ) { player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 1, 0, 0, 0 ), true ); player.unsetStateFlag( PlayerStateFlag::Performing ); } else { - player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, param11, 0, 0 ), true ); + player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, p1, 0, 0 ), true ); player.setStateFlag( PlayerStateFlag::Performing ); } break; } case ClientTriggerType::CameraMode: { - if( param11 == 1 ) + if( ( p1 & 0xFF ) == 1 ) { player.setOnlineStatusMask( player.getOnlineStatusMask() | 0x0000000000040000 ); } @@ -537,6 +565,64 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } break; } + case 0x25E: // coming out from water (no 3.x name) + case 0xD1: // underwater town portal (3.x NEWBIE_TELEPO_INQUIRY) + { + auto p = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() ); + p->data().targetZone = player.getCurrentTerritory()->getTerritoryTypeId(); + p->data().param4 = commandId == 0xD1 ? 14 : 227; + p->data().hideChar = commandId == 0xD1 ? 2 : 1; + p->data().fadeOut = commandId == 0xD1 ? 24 : 25; + p->data().fadeOutTime = 1; + p->data().unknown = commandId == 0xD1 ? 4 : 6; + auto x = pos.x; + auto y = pos.y; + auto z = pos.z; + auto rot = player.getRot(); + if( commandId == 0xD1 ) + { + auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); + auto exit = instanceObjectCache.getExitRange( p->data().targetZone, p1 ); + if( exit ) + { + player.sendDebug( "exitRange {0} found!", p1 ); + auto destZone = exit->data.destTerritoryType; + if( destZone == 0 ) + destZone = p->data().targetZone; + else + p->data().targetZone = destZone; + auto pop = instanceObjectCache.getPopRange( destZone, exit->data.destInstanceObjectId ); + if( pop ) + { + player.sendDebug( "popRange {0} found!", exit->data.destInstanceObjectId ); + x = pop->header.transform.translation.x; + y = pop->header.transform.translation.y; + z = pop->header.transform.translation.z; + //rot = pop->header.transform.rotation.y; all x/y/z not correct, maybe we don't need it since we have to be facing the portal anyway? + } + else + { + player.sendUrgent( "popRange {0} not found in {1}!", exit->data.destInstanceObjectId, destZone ); + } + } + else + { + player.sendUrgent( "exitRange {0} not found in {1}!", p1, p->data().targetZone ); + } + } + player.queuePacket( p ); + player.setPos( x, y, z, true ); + player.setRot( rot ); + auto setPos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setPos->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() ); + setPos->data().x = x; + setPos->data().y = y; + setPos->data().z = z; + setPos->data().waitForLoad = commandId == 0xD1 ? 24 : 25; + setPos->data().unknown1 = 0; + player.queuePacket( setPos ); // this packet needs a delay of 0.8 second to wait for the client finishing its water animation otherwise it looks odd. + 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 893ae18f..978e6e53 100644 --- a/src/world/Network/Handlers/EventHandlers.cpp +++ b/src/world/Network/Handlers/EventHandlers.cpp @@ -80,6 +80,32 @@ void Sapphire::Network::GameConnection::eventHandlerTalk( const Packets::FFXIVAR } +void Sapphire::Network::GameConnection::eventHandlerSay( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); + auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); + auto& eventMgr = Common::Service< World::Manager::EventMgr >::ref(); + + const auto packet = ZoneChannelPacket< Client::FFXIVIpcEventHandlerSay >( inPacket ); + + const auto actorId = packet.data().actorId; + const auto eventId = packet.data().eventId; + + std::string eventName = "onSay"; + std::string objName = eventMgr.getEventName( eventId ); + + player.sendDebug( "Chara: {0} -> {1} \neventId: {2} ({3:08X})", actorId, + eventMgr.mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ), eventId, eventId ); + + player.sendDebug( "Calling: {0}.{1}", objName, eventName ); + + player.eventStart( actorId, eventId, Event::EventHandler::Say, 0, 0 ); + + scriptMgr.onSay( player, actorId, eventId ); + + player.checkEvent( eventId ); +} + void Sapphire::Network::GameConnection::eventHandlerEmote( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { @@ -320,7 +346,7 @@ void Sapphire::Network::GameConnection::eventYieldHandler( const Packets::FFXIVA scriptMgr.onEventYield( player, eventId, scene, param ); - auto response = makeZonePacket< FFXIVIpcEventContinue >( player.getId() ); + auto response = makeZonePacket< FFXIVIpcEventReturn >( player.getId() ); response->data().eventId = eventId; response->data().scene = scene; player.queuePacket( response ); diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index af3b5335..5a4265c7 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -256,19 +256,12 @@ void Sapphire::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACK { targetPlayer->setOnlineStatusMask( param1 ); - auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() ); - statusPacket->data().onlineStatusFlags = param1; - queueOutPacket( statusPacket ); - auto searchInfoPacket = makeZonePacket< FFXIVIpcSetSearchInfo >( player.getId() ); searchInfoPacket->data().onlineStatusFlags = param1; searchInfoPacket->data().selectRegion = targetPlayer->getSearchSelectRegion(); strcpy( searchInfoPacket->data().searchMessage, targetPlayer->getSearchMessage() ); targetPlayer->queuePacket( searchInfoPacket ); - targetPlayer->sendToInRangeSet( makeActorControl( player.getId(), SetStatusIcon, - static_cast< uint8_t >( player.getOnlineStatus() ) ), - true ); player.sendNotice( "Icon for {0} was set to {1}", targetPlayer->getName(), param1 ); break; } diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 97ab09ab..f0a5c5fc 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -47,6 +47,8 @@ #include "Manager/HousingMgr.h" #include "Manager/RNGMgr.h" #include "Manager/ItemMgr.h" +#include "Manager/PartyMgr.h" +#include "Manager/ChatChannelMgr.h" #include "Action/Action.h" #include "Inventory/Item.h" @@ -91,18 +93,12 @@ void Sapphire::Network::GameConnection::setSearchInfoHandler( const Packets::FFX // mark player as new adventurer player.setNewAdventurer( true ); - auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() ); - statusPacket->data().onlineStatusFlags = status; - queueOutPacket( statusPacket ); - auto searchInfoPacket = makeZonePacket< FFXIVIpcSetSearchInfo >( player.getId() ); searchInfoPacket->data().onlineStatusFlags = status; searchInfoPacket->data().selectRegion = player.getSearchSelectRegion(); strcpy( searchInfoPacket->data().searchMessage, player.getSearchMessage() ); queueOutPacket( searchInfoPacket ); - player.sendToInRangeSet( makeActorControl( player.getId(), SetStatusIcon, - static_cast< uint8_t >( player.getOnlineStatus() ) ), true ); } void Sapphire::Network::GameConnection::reqSearchInfoHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, @@ -444,31 +440,56 @@ void Sapphire::Network::GameConnection::socialListHandler( const Packets::FFXIVA int32_t entrysizes = sizeof( listPacket->data().entries ); memset( listPacket->data().entries, 0, sizeof( listPacket->data().entries ) ); - listPacket->data().entries[ 0 ].bytes[ 2 ] = player.getCurrentTerritory()->getTerritoryTypeId(); - listPacket->data().entries[ 0 ].bytes[ 3 ] = 0x80; - listPacket->data().entries[ 0 ].bytes[ 4 ] = 0x02; - listPacket->data().entries[ 0 ].bytes[ 6 ] = 0x3B; - listPacket->data().entries[ 0 ].bytes[ 11 ] = 0x10; - listPacket->data().entries[ 0 ].classJob = static_cast< uint8_t >( player.getClass() ); - listPacket->data().entries[ 0 ].contentId = player.getContentId(); - listPacket->data().entries[ 0 ].level = player.getLevel(); - listPacket->data().entries[ 0 ].zoneId = player.getCurrentTerritory()->getTerritoryTypeId(); - listPacket->data().entries[ 0 ].zoneId1 = 0x0100; - // TODO: no idea what this does - //listPacket.data().entries[0].one = 1; + auto fillEntryAt = [ &listPacket ]( int i, Entity::PlayerPtr nextPlayer, bool isLeader ) + { + //listPacket->data().entries[ i ].bytes[ 2 ] = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); + //listPacket->data().entries[ i ].bytes[ 3 ] = 0x80; + //listPacket->data().entries[ i ].bytes[ 4 ] = 0x02; + //listPacket->data().entries[ i ].bytes[ 6 ] = 0x3B; + listPacket->data().entries[ i ].bytes[ 8 ] = isLeader; + listPacket->data().entries[ i ].bytes[ 11 ] = 0x10; + listPacket->data().entries[ i ].classJob = static_cast< uint8_t >( nextPlayer->getClass() ); + listPacket->data().entries[ i ].contentId = nextPlayer->getContentId(); + listPacket->data().entries[ i ].level = nextPlayer->getLevel(); + listPacket->data().entries[ i ].zoneId = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); + listPacket->data().entries[ i ].zoneId1 = 0x0100; - memcpy( listPacket->data().entries[ 0 ].name, player.getName().c_str(), strlen( player.getName().c_str() ) ); + memcpy( listPacket->data().entries[ i ].name, nextPlayer->getName().c_str(), strlen( nextPlayer->getName().c_str() ) ); - // GC icon - listPacket->data().entries[ 0 ].bytes1[ 0 ] = 2; - // client language J = 0, E = 1, D = 2, F = 3 - listPacket->data().entries[ 0 ].bytes1[ 1 ] = 1; - // user language settings flag J = 1, E = 2, D = 4, F = 8 - listPacket->data().entries[ 0 ].bytes1[ 2 ] = 1 + 2; - listPacket->data().entries[ 0 ].onlineStatusMask = player.getOnlineStatusMask(); + // GC icon + listPacket->data().entries[ i ].bytes1[ 0 ] = 2; + // client language J = 0, E = 1, D = 2, F = 3 + listPacket->data().entries[ i ].bytes1[ 1 ] = 1; + // user language settings flag J = 1, E = 2, D = 4, F = 8 + listPacket->data().entries[ i ].bytes1[ 2 ] = 1 + 2 + 4 + 8; + listPacket->data().entries[ i ].onlineStatusMask = nextPlayer->getOnlineStatusMask(); + }; + auto nextPlayer = player.getAsPlayer(); + fillEntryAt( 0, nextPlayer, false ); + if( player.getPartyId() != 0 ) + { + // fill party members + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + auto& server = Common::Service< World::ServerMgr >::ref(); + auto pParty = partyMgr.getParty( player.getPartyId() ); + assert( pParty ); + + int i = 1; + for( auto id : pParty->MemberId ) + { + nextPlayer = server.getSession( id )->getPlayer(); + if( nextPlayer->getId() == player.getId() ) + { + // data already in entry 0, only change the leader flag + listPacket->data().entries[ 0 ].bytes[ 8 ] = pParty->LeaderId == id; + continue; + } + fillEntryAt( i, nextPlayer, pParty->LeaderId == id ); + i++; + } + } queueOutPacket( listPacket ); - } else if( type == 2 ) { // friend list @@ -604,12 +625,24 @@ void Sapphire::Network::GameConnection::tellHandler( const Packets::FFXIVARR_PAC if( player.isActingAsGm() ) { - tellPacket->data().flags |= TellFlags::GmTellMsg; + tellPacket->data().flags |= ChatFromType::GmTellMsg; } pTargetPlayer->queueChatPacket( tellPacket ); } +void Sapphire::Network::GameConnection::channelChatHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto packet = ChatChannelPacket< Client::FFXIVIpcChannelChatHandler >( inPacket ); + auto& data = packet.data(); + + auto& chatChannelMgr = Common::Service< ChatChannelMgr >::ref(); + + std::string message = std::string( data.message ); + + chatChannelMgr.sendMessageToChannel( data.channelId, player, message ); +} + void Sapphire::Network::GameConnection::performNoteHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { @@ -772,139 +805,6 @@ void Sapphire::Network::GameConnection::marketBoardRequestItemListings( const Pa marketMgr.requestItemListings( player, packet.data().itemCatalogId ); } -void Sapphire::Network::GameConnection::worldInteractionhandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, - Entity::Player& player ) -{ - const auto packet = ZoneChannelPacket< Client::FFXIVIpcWorldInteractionHandler >( inPacket ); - auto action = packet.data().action; - player.sendDebug( "WorldInteraction {}", action ); - switch( action ) - { - case 0x1F5: // emote - { - auto emote = packet.data().param1; - if( emote == 0x32 || emote == 0x33 ) // "/sit" - { - auto param4 = packet.data().param4; - auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); - auto emoteData = exdData.get< Data::Emote >( emote ); - - if( !emoteData ) - break; - - player.setPos( packet.data().position ); - player.setRot( Util::floatFromUInt16Rot( param4 ) ); - if( emote == 0x32 && player.hasInRangeActor() ) - { - auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setpos->data().r16 = param4; - setpos->data().waitForLoad = 18; - setpos->data().x = packet.data().position.x; - setpos->data().y = packet.data().position.y; - setpos->data().z = packet.data().position.z; - player.sendToInRangeSet( setpos, false ); - } - player.sendToInRangeSet( makeActorControlTarget( player.getId(), ActorControl::ActorControlType::Emote, emote, 0, 0, param4, 0xE0000000 ), true ); - - if( emote == 0x32 && emoteData->emoteMode != 0 ) - { - player.setStance( Common::Stance::Passive ); - player.setAutoattack( false ); - player.setPersistentEmote( emoteData->emoteMode ); - player.setStatus( Common::ActorStatus::EmoteMode ); - } - } - break; - } - case 0x1F8: - { - if( player.getPersistentEmote() > 0 ) - { - auto param2 = packet.data().param2; - - player.setPos( packet.data().position ); - if( player.hasInRangeActor() ) - { - auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setpos->data().r16 = param2; - setpos->data().waitForLoad = 18; - setpos->data().x = packet.data().position.x; - setpos->data().y = packet.data().position.y; - setpos->data().z = packet.data().position.z; - player.sendToInRangeSet( setpos, false ); - } - - player.setPersistentEmote( 0 ); - player.emoteInterrupt(); - player.setStatus( Common::ActorStatus::Idle ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); - player.sendToInRangeSet( pSetStatusPacket ); - } - break; - } - case 0x25E: // coming out from water - case 0xD1: // underwater town portal - { - auto p = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() ); - p->data().targetZone = player.getCurrentTerritory()->getTerritoryTypeId(); - p->data().param4 = action == 0xD1 ? 14 : 227; - p->data().hideChar = action == 0xD1 ? 2 : 1; - p->data().fadeOut = action == 0xD1 ? 24 : 25; - p->data().fadeOutTime = 1; - p->data().unknown = action == 0xD1 ? 4 : 6; - auto x = packet.data().position.x; - auto y = packet.data().position.y; - auto z = packet.data().position.z; - auto rot = player.getRot(); - if( action == 0xD1 ) - { - auto exitRange = packet.data().param1; - - auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); - auto exit = instanceObjectCache.getExitRange( p->data().targetZone, exitRange ); - if( exit ) - { - player.sendDebug( "exitRange {0} found!", exitRange ); - auto destZone = exit->data.destTerritoryType; - if( destZone == 0 ) - destZone = p->data().targetZone; - else - p->data().targetZone = destZone; - auto pop = instanceObjectCache.getPopRange( destZone, exit->data.destInstanceObjectId ); - if( pop ) - { - player.sendDebug( "popRange {0} found!", exit->data.destInstanceObjectId ); - x = pop->header.transform.translation.x; - y = pop->header.transform.translation.y; - z = pop->header.transform.translation.z; - //rot = pop->header.transform.rotation.y; all x/y/z not correct, maybe we don't need it since we have to be facing the portal anyway? - } - else - { - player.sendUrgent( "popRange {0} not found in {1}!", exit->data.destInstanceObjectId, destZone ); - } - } - else - { - player.sendUrgent( "exitRange {0} not found in {1}!", exitRange, p->data().targetZone ); - } - } - player.queuePacket( p ); - player.setPos( x, y, z, true ); - player.setRot( rot ); - auto setPos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setPos->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() ); - setPos->data().x = x; - setPos->data().y = y; - setPos->data().z = z; - setPos->data().waitForLoad = action == 0xD1 ? 24 : 25; - setPos->data().unknown1 = 0; - player.queuePacket( setPos ); // this packet needs a delay of 0.8 second to wait for the client finishing its water animation otherwise it looks odd. - break; - } - } -} - void Sapphire::Network::GameConnection::diveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { const auto packetIn = ZoneChannelPacket< Client::FFXIVIpcDive >( inPacket ); diff --git a/src/world/Network/Handlers/PartyHandlers.cpp b/src/world/Network/Handlers/PartyHandlers.cpp new file mode 100644 index 00000000..80208996 --- /dev/null +++ b/src/world/Network/Handlers/PartyHandlers.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +#include +#include +#include + +#include "Manager/PartyMgr.h" + +#include "Network/GameConnection.h" + +#include "Session.h" +#include "Actor/Player.h" + +using namespace Sapphire::Common; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::World::Manager; + + +void Sapphire::Network::GameConnection::partyLeaveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onLeave( player ); + +} + +void Sapphire::Network::GameConnection::partyDisbandHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onDisband( player ); + +} + +void Sapphire::Network::GameConnection::partyKickHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + const auto packet = ZoneChannelPacket< Client::FFXIVIpcPartyKickHandler >( inPacket ); + const auto& data = packet.data(); + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onKick( std::string( data.name ), player ); + +} + +void Sapphire::Network::GameConnection::partyChangeLeaderHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + const auto packet = ZoneChannelPacket< Client::FFXIVIpcPartyChangeLeaderHandler >( inPacket ); + const auto& data = packet.data(); + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onChangeLeader( std::string( data.name ), player ); + +} diff --git a/src/world/Network/PacketWrappers/ChannelChatPacket.h b/src/world/Network/PacketWrappers/ChannelChatPacket.h new file mode 100644 index 00000000..8542ef1e --- /dev/null +++ b/src/world/Network/PacketWrappers/ChannelChatPacket.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Forwards.h" +#include "Actor/Player.h" +#include +#include + +namespace Sapphire::Network::Packets::Server +{ + + /** + * @brief The Chat packet. + */ + class ChannelChatPacket : public ChatChannelPacket< FFXIVIpcChannelChat > + { + public: + ChannelChatPacket( Entity::Player& target, + Entity::Player& sender, + uint64_t channelId, + const std::string& msg ) : + ChatChannelPacket< FFXIVIpcChannelChat >( target.getId(), target.getId() ) + { + initialize( sender, channelId, msg ); + }; + + private: + void initialize( Entity::Player& sender, uint64_t channelId, const std::string& msg ) + { + strcpy( m_data.message, msg.c_str() ); + strcpy( m_data.name, sender.getName().c_str() ); + + m_data.channelId = channelId; + + m_data.contentId = sender.getContentId(); + m_data.charaId = sender.getId(); + + m_data.type = 0; + }; + }; + +} \ No newline at end of file diff --git a/src/world/Network/PacketWrappers/InviteHandlers.cpp b/src/world/Network/PacketWrappers/InviteHandlers.cpp new file mode 100644 index 00000000..97f3d41f --- /dev/null +++ b/src/world/Network/PacketWrappers/InviteHandlers.cpp @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "Network/GameConnection.h" +#include "Session.h" + +#include "Territory/Territory.h" + +#include "Network/PacketWrappers/PlayerSetupPacket.h" + +//#include "Manager/FriendListMgr.h" +#include "Manager/PartyMgr.h" +#include "Manager/PlayerMgr.h" +//#include "Manager/FreeCompanyMgr.h" + +#include "Action/Action.h" + +#include "ServerMgr.h" +#include "Forwards.h" + +using namespace Sapphire::Common; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::Server; +using namespace Sapphire::Network::Packets::Client; +using namespace Sapphire::World::Manager; + + +void Sapphire::Network::GameConnection::socialInviteHandler( const FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto packet = ZoneChannelPacket< Client::FFXIVIpcSocialInviteHandler >( inPacket ); + + player.sendDebug( "Auth Type#{0}", packet.data().socialType ); + player.sendDebug( "Target Name: {0}", packet.data().name ); + + std::string name( packet.data().name ); + + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto& server = Common::Service< Sapphire::World::ServerMgr >::ref(); + auto pTargetPlayer = server.getSession( name )->getPlayer(); + + if( !pTargetPlayer ) + return; + + switch( packet.data().socialType ) + { + case 1: + { + auto inviteResultPacket = makeZonePacket< Server::FFXIVIpcSocialInviteResult >( player.getId() ); + auto& data = inviteResultPacket->data(); + data.contentId = pTargetPlayer->getContentId(); + data.p1 = packet.data().p1; + data.p2 = packet.data().p2; + data.socialType = packet.data().socialType; + strcpy( data.name, packet.data().name ); + player.queuePacket( inviteResultPacket ); + + auto inviteUpdatePacket = makeZonePacket< Server::FFXIVIpcSocialInviteUpdate >( pTargetPlayer->getId() ); + inviteUpdatePacket->data().contentId = player.getContentId(); + inviteUpdatePacket->data().expireTime = Common::Util::getTimeSeconds() + 30; + inviteUpdatePacket->data().p1 = packet.data().p1; + inviteUpdatePacket->data().p2 = packet.data().p2; + inviteUpdatePacket->data().socialType = packet.data().socialType; + inviteUpdatePacket->data().type = 1; + inviteUpdatePacket->data().gender = player.getGender(); + strcpy( inviteUpdatePacket->data().name, player.getName().c_str() ); + pTargetPlayer->queuePacket( inviteUpdatePacket ); + + break; + } + } +} + +void Sapphire::Network::GameConnection::socialReplyHandler( const FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto packet = ZoneChannelPacket< Client::FFXIVIpcSocialReplyHandler >( inPacket ); + const auto& data = packet.data(); + + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto& server = Common::Service< Sapphire::World::ServerMgr >::ref(); + auto pPlayer = server.getSession( data.contentId )->getPlayer(); + + if( !pPlayer ) + return; + + auto inviteReplyPacket = makeZonePacket< Server::FFXIVIpcSocialInviteResponse >( player.getId() ); + auto& inviteReplyData = inviteReplyPacket->data(); + inviteReplyData.response = data.response; + + switch( data.socialType ) + { + case 1: + { + auto& partyMgr = Common::Service< PartyMgr >::ref(); + + if( data.response == InviteReplyType::ACCEPT ) + { + partyMgr.onJoin( player, *pPlayer ); + } + + auto inviteUpPacket = makeZonePacket< Server::FFXIVIpcSocialInviteUpdate >( pPlayer->getId() ); + inviteUpPacket->data().contentId = player.getContentId(); + inviteUpPacket->data().expireTime = Common::Util::getTimeSeconds() + 30; + inviteUpPacket->data().p1 = packet.data().p1; + inviteUpPacket->data().p2 = packet.data().p2; + inviteUpPacket->data().socialType = packet.data().socialType; + inviteUpPacket->data().type = data.response == InviteReplyType::ACCEPT ? InviteUpdateType::ACCEPT_INVITE : InviteUpdateType::REJECT_INVITE; + strcpy( inviteUpPacket->data().name, player.getName().c_str() ); + pPlayer->queuePacket( inviteUpPacket ); + + inviteReplyData.contentId == pPlayer->getContentId(); + inviteReplyData.socialType = data.socialType; + inviteReplyData.gender = pPlayer->getGender(); + strcpy( inviteReplyData.name, pPlayer->getName().c_str() ); + player.queuePacket( inviteReplyPacket ); + + break; + } + } +} diff --git a/src/world/Network/PacketWrappers/PartyUpdatePacket.h b/src/world/Network/PacketWrappers/PartyUpdatePacket.h new file mode 100644 index 00000000..71899f01 --- /dev/null +++ b/src/world/Network/PacketWrappers/PartyUpdatePacket.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include "Actor/Player.h" +#include "Forwards.h" + +namespace Sapphire::Network::Packets::Server +{ + class PartyUpdatePacket : public ZoneChannelPacket< FFXIVIpcPartyUpdate > + { + public: + PartyUpdatePacket( Entity::Player& executePlayer, Entity::Player& targetPlayer, uint8_t updateStatus, uint8_t count ) : + ZoneChannelPacket< FFXIVIpcPartyUpdate >( executePlayer.getId(), executePlayer.getId() ) + { + initialize( executePlayer, targetPlayer, updateStatus, count ); + }; + + PartyUpdatePacket( Entity::Player& executePlayer, uint8_t updateStatus, uint8_t count ) : + ZoneChannelPacket< FFXIVIpcPartyUpdate >( executePlayer.getId(), executePlayer.getId() ) + { + initialize( executePlayer, updateStatus, count ); + }; + + PartyUpdatePacket( const Entity::PlayerPtr& executePlayer, const Entity::PlayerPtr& targetPlayer, uint8_t updateStatus, uint8_t count ) : + ZoneChannelPacket< FFXIVIpcPartyUpdate >( executePlayer->getId(), executePlayer->getId() ) + { + initialize( executePlayer, targetPlayer, updateStatus, count ); + }; + + private: + void initialize( Entity::Player& executePlayer, Entity::Player& targetPlayer, uint8_t updateStatus, uint8_t partySize ) + { + m_data.executeContentId = executePlayer.getContentId(); + m_data.targetContentId = targetPlayer.getContentId(); + m_data.executeGender = executePlayer.getGender(); + m_data.targetGender = targetPlayer.getGender(); + m_data.updateStatus = updateStatus; + m_data.partySize = partySize; + strcpy( m_data.executeName, executePlayer.getName().c_str() ); + strcpy( m_data.targetName, targetPlayer.getName().c_str() ); + }; + + void initialize( Entity::Player& executePlayer, uint8_t updateStatus, uint8_t partySize ) + { + m_data.executeContentId = executePlayer.getContentId(); + m_data.targetContentId = 0; + m_data.executeGender = executePlayer.getGender(); + m_data.targetGender = 0; + m_data.updateStatus = updateStatus; + m_data.partySize = partySize; + strcpy( m_data.targetName, executePlayer.getName().c_str() ); + }; + + void initialize( const Entity::PlayerPtr& executePlayer, const Entity::PlayerPtr& targetPlayer, uint8_t updateStatus, uint8_t partySize ) + { + if( targetPlayer ) + { + m_data.targetContentId = targetPlayer->getContentId(); + m_data.targetGender = targetPlayer->getGender(); + strcpy( m_data.targetName, targetPlayer->getName().c_str() ); + } + + if( executePlayer ) + { + m_data.executeContentId = executePlayer->getContentId(); + m_data.executeGender = executePlayer->getGender(); + strcpy( m_data.executeName, executePlayer->getName().c_str() ); + } + + m_data.updateStatus = updateStatus; + m_data.partySize = partySize; + + }; + + }; + + template< typename... Args > + std::shared_ptr< PartyUpdatePacket > makePartyUpdate( Args... args ) + { + return std::make_shared< PartyUpdatePacket >( args... ); + } + +} diff --git a/src/world/Network/PacketWrappers/PlayerSetupPacket.h b/src/world/Network/PacketWrappers/PlayerSetupPacket.h index 52b52dba..17ddcddb 100644 --- a/src/world/Network/PacketWrappers/PlayerSetupPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSetupPacket.h @@ -45,7 +45,6 @@ namespace Sapphire::Network::Packets::Server //m_data.gcRank = GCRank::None; m_data.homepoint = player.getHomepoint(); - m_data.pose[0] = player.getPose(); memset( &m_data.name[ 0 ], 0, sizeof( m_data.name ) ); strcpy( &m_data.name[ 0 ], player.getName().c_str() ); @@ -69,29 +68,27 @@ namespace Sapphire::Network::Packets::Server memcpy( m_data.howto, player.getHowToArray(), sizeof( m_data.howto ) ); - // possibly max level or current level m_data.maxLevel = Common::MAX_PLAYER_LEVEL; m_data.expansion = Common::CURRENT_EXPANSION_ID; - // df stuff - // todo: actually do this properly - // m_data.unknown70[4] = 1; // enable df + // unlock mounts + memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask ) ); - // enable all raids/guildhests/dungeons + // uncomment to unlock everything or choose options below + //memset( &m_data.unknown293[ 0 ], 0xFF, reinterpret_cast< uint64_t >( &m_data.unknown85E[ 40 ] ) - reinterpret_cast< uint64_t >( &m_data.unknown293[ 0 ] ) + 1 ); + + m_data.pose[0] = player.getPose(); + memset( &m_data.pose[ 1 ], 0, sizeof( m_data.pose ) - 1 ); + + // custom unlock options memset( m_data.unlockedDungeons, 0xFF, sizeof( m_data.unlockedDungeons ) ); memset( m_data.unlockedGuildhests, 0xFF, sizeof( m_data.unlockedGuildhests ) ); memset( m_data.unlockedPvp, 0xFF, sizeof( m_data.unlockedPvp ) ); memset( m_data.unlockedRaids, 0xFF, sizeof( m_data.unlockedRaids ) ); memset( m_data.unlockedTrials, 0xFF, sizeof( m_data.unlockedTrials ) ); - - // uncomment to enable custom unlocks - - // everything - //memset( &m_data.unknownOword[ 0 ], 0xFF, reinterpret_cast< uint64_t >( &m_data.unknown5_55c ) - reinterpret_cast< uint64_t >( &m_data.unknownOword[ 0 ] ) ); - // or select options below //memset( m_data.unlockBitmask, 0xFF, sizeof( m_data.unlockBitmask ) ); - //memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask ) ); //memset( m_data.minions, 0xFF, sizeof( m_data.minions ) ); + //memset( m_data.discovery, 0xFF, sizeof( m_data.discovery ) ); }; }; diff --git a/src/world/Script/NativeScriptApi.cpp b/src/world/Script/NativeScriptApi.cpp index 1702e733..acf1bfc4 100644 --- a/src/world/Script/NativeScriptApi.cpp +++ b/src/world/Script/NativeScriptApi.cpp @@ -99,6 +99,10 @@ namespace Sapphire::ScriptAPI { } + void EventScript::onSay( uint32_t eventId, Entity::Player& player, uint64_t actorId ) + { + } + void EventScript::onBNpcKill( uint32_t nameId, Entity::Player& player ) { } diff --git a/src/world/Script/NativeScriptApi.h b/src/world/Script/NativeScriptApi.h index 315bdad2..a843e6e4 100644 --- a/src/world/Script/NativeScriptApi.h +++ b/src/world/Script/NativeScriptApi.h @@ -150,6 +150,8 @@ namespace Sapphire::ScriptAPI virtual void onTalk( uint32_t eventId, Sapphire::Entity::Player& player, uint64_t actorId ); + virtual void onSay( uint32_t eventId, Sapphire::Entity::Player& player, uint64_t actorId ); + virtual void onBNpcKill( uint32_t nameId, Sapphire::Entity::Player& player ); virtual void onEmote( uint64_t actorId, uint32_t eventId, uint32_t emoteId, Sapphire::Entity::Player& player ); diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index 718c72be..efb0c0cf 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -192,6 +192,17 @@ bool Sapphire::Scripting::ScriptMgr::onTalk( Entity::Player& player, uint64_t ac } } +bool Sapphire::Scripting::ScriptMgr::onSay( Entity::Player& player, uint64_t actorId, uint32_t eventId ) +{ + auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( eventId ); + if( script ) + { + script->onSay( eventId, player, actorId ); + return true; + } + return false; +} + bool Sapphire::Scripting::ScriptMgr::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) { diff --git a/src/world/Script/ScriptMgr.h b/src/world/Script/ScriptMgr.h index b0a5cb5f..97f0b841 100644 --- a/src/world/Script/ScriptMgr.h +++ b/src/world/Script/ScriptMgr.h @@ -56,6 +56,8 @@ namespace Sapphire::Scripting bool onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ); + bool onSay( Entity::Player& player, uint64_t actorId, uint32_t eventId ); + bool onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ); bool onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ); diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index c600b0d6..dde311d3 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -42,6 +42,8 @@ #include "Manager/NaviMgr.h" #include "Manager/ActionMgr.h" #include "Manager/MapMgr.h" +#include "Manager/ChatChannelMgr.h" +#include "Manager/PartyMgr.h" #include "Territory/InstanceObjectCache.h" @@ -153,6 +155,9 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) } Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::set( pDb ); + auto pChatChannelMgr = std::make_shared< Manager::ChatChannelMgr >(); + Common::Service< Manager::ChatChannelMgr >::set( pChatChannelMgr ); + Logger::info( "LinkshellMgr: Caching linkshells" ); auto pLsMgr = std::make_shared< Manager::LinkshellMgr >(); if( !pLsMgr->loadLinkshells() ) @@ -227,6 +232,7 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) auto pEventMgr = std::make_shared< Manager::EventMgr >(); auto pItemMgr = std::make_shared< Manager::ItemMgr >(); auto pRNGMgr = std::make_shared< Manager::RNGMgr >(); + auto pPartyMgr = std::make_shared< Manager::PartyMgr >(); Common::Service< DebugCommandMgr >::set( pDebugCom ); Common::Service< Manager::PlayerMgr >::set( pPlayerMgr ); @@ -235,6 +241,7 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) Common::Service< Manager::EventMgr >::set( pEventMgr ); Common::Service< Manager::ItemMgr >::set( pItemMgr ); Common::Service< Manager::RNGMgr >::set( pRNGMgr ); + Common::Service< Manager::PartyMgr >::set( pPartyMgr ); Logger::info( "World server running on {0}:{1}", m_ip, m_port ); @@ -320,6 +327,7 @@ void Sapphire::World::ServerMgr::mainLoop() { Logger::info( "[{0}] Session removal", it->second->getId() ); it = m_sessionMapById.erase( it ); + removeSession( pPlayer->getContentId() ); removeSession( pPlayer->getName() ); continue; } @@ -334,6 +342,7 @@ void Sapphire::World::ServerMgr::mainLoop() // if( it->second.unique() ) { it = m_sessionMapById.erase( it ); + removeSession( pPlayer->getContentId() ); removeSession( pPlayer->getName() ); } } @@ -372,17 +381,13 @@ bool Sapphire::World::ServerMgr::createSession( uint32_t sessionId ) return false; } + m_sessionMapByContentId[ newSession->getPlayer()->getContentId() ] = newSession; m_sessionMapByName[ newSession->getPlayer()->getName() ] = newSession; return true; } -void Sapphire::World::ServerMgr::removeSession( uint32_t sessionId ) -{ - m_sessionMapById.erase( sessionId ); -} - Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( uint32_t id ) { //std::lock_guard lock( m_sessionMutex ); @@ -394,6 +399,16 @@ Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( uint32_t id return nullptr; } +Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( uint64_t contentId ) +{ + auto it = m_sessionMapByContentId.find( contentId ); + + if( it != m_sessionMapByContentId.end() ) + return ( it->second ); + + return nullptr; +} + Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( const std::string& playerName ) { //std::lock_guard lock( m_sessionMutex ); @@ -406,6 +421,16 @@ Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( const std::s return nullptr; } +void Sapphire::World::ServerMgr::removeSession( uint32_t sessionId ) +{ + m_sessionMapById.erase( sessionId ); +} + +void Sapphire::World::ServerMgr::removeSession( uint64_t contentId ) +{ + m_sessionMapByContentId.erase( contentId ); +} + void Sapphire::World::ServerMgr::removeSession( const std::string& playerName ) { m_sessionMapByName.erase( playerName ); diff --git a/src/world/ServerMgr.h b/src/world/ServerMgr.h index 1add030a..1de5b977 100644 --- a/src/world/ServerMgr.h +++ b/src/world/ServerMgr.h @@ -24,10 +24,8 @@ namespace Sapphire::World bool createSession( uint32_t sessionId ); - void removeSession( uint32_t sessionId ); - void removeSession( const std::string& playerName ); - World::SessionPtr getSession( uint32_t id ); + World::SessionPtr getSession( uint64_t contentId ); World::SessionPtr getSession( const std::string& playerName ); size_t getSessionCount() const; @@ -66,11 +64,15 @@ namespace Sapphire::World Sapphire::Common::Config::WorldConfig m_config; std::map< uint32_t, SessionPtr > m_sessionMapById; + std::map< uint64_t, SessionPtr > m_sessionMapByContentId; std::map< std::string, SessionPtr > m_sessionMapByName; std::map< uint32_t, std::string > m_playerNameMapById; std::map< uint32_t, uint32_t > m_zones; std::map< std::string, Entity::BNpcTemplatePtr > m_bNpcTemplateMap; + void removeSession( uint32_t sessionId ); + void removeSession( uint64_t contentId ); + void removeSession( const std::string& playerName ); }; } diff --git a/src/world/Session.cpp b/src/world/Session.cpp index b446f293..5a2562cc 100644 --- a/src/world/Session.cpp +++ b/src/world/Session.cpp @@ -8,6 +8,9 @@ #include "Network/GameConnection.h" #include "Actor/Player.h" +#include "Service.h" +#include "Manager/PartyMgr.h" + #include "Session.h" namespace fs = std::filesystem; @@ -73,6 +76,12 @@ void Sapphire::World::Session::close() if( m_pPlayer ) { m_pPlayer->clearBuyBackMap(); + if( m_pPlayer->getPartyId() != 0 ) + { + // offline player is removed from party for now; + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + partyMgr.onLeave( *m_pPlayer ); + } // do one last update to db m_pPlayer->updateSql(); // reset the zone, so the zone handler knows to remove the actor