diff --git a/src/common/Common.h b/src/common/Common.h index d8e7618c..5f27478d 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -4,1268 +4,825 @@ #include #include +#include #include "CommonGen.h" -#include "Vector3.h" // +--------------------------------------------------------------------------- // The following enumerations are structures to require their type be included. -// They are also defined within the Sapphire::Common namespace to avoid collisions. +// They are also defined within the Core::Common namespace to avoid collisions. // +--------------------------------------------------------------------------- -namespace Sapphire::Common -{ +namespace Core { +namespace Common { - // 99 is the last spawn id that seems to spawn any actor - const uint8_t MAX_DISPLAYED_ACTORS = 99; - const uint8_t MAX_DISPLAYED_EOBJS = 40; + // 99 is the last spawn id that seems to spawn any actor + const uint8_t MAX_DISPLAYED_ACTORS = 99; - const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000; - const uint64_t INVALID_GAME_OBJECT_ID64 = 0xE0000000; + const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000; - const uint16_t MAX_PLAYER_LEVEL = 80; - const uint8_t CURRENT_EXPANSION_ID = 3; + struct FFXIVARR_POSITION3 + { + float x; + float y; + float z; + }; - const uint8_t CLASSJOB_TOTAL = 38; - const uint8_t CLASSJOB_SLOTS = 28; + enum EquipSlot : uint8_t + { + MainHand = 0, + OffHand = 1, + Head = 2, + Body = 3, + Hands = 4, + Waist = 5, + Legs = 6, + Feet = 7, + Neck = 8, + Ear = 9, + Wrist = 10, + Ring1 = 11, + Ring2 = 12, + SoulCrystal = 13, + }; - const uint8_t TOWN_COUNT = 6; + enum InventoryType : uint16_t + { + Bag0 = 0, + Bag1 = 1, + Bag2 = 2, + Bag3 = 3, - /*! - * @brief The maximum length (in ms) of a combo before it is canceled/voided. - * - * The client has a combo timer of about 12 seconds, with a 0.5 second grace on top for latency considerations. + GearSet0 = 1000, + GearSet1 = 1001, + + Currency = 2000, + Crystal = 2001, + //UNKNOWN_0 = 2003, + KeyItem = 2004, + DamagedGear = 2007, + //UNKNOWN_1 = 2008, + + ArmoryOff = 3200, + ArmoryHead = 3201, + ArmoryBody = 3202, + ArmoryHand = 3203, + ArmoryWaist = 3204, + ArmoryLegs = 3205, + ArmoryFeet = 3206, + ArmotyNeck = 3207, + ArmoryEar = 3208, + ArmoryWrist = 3209, + ArmoryRing = 3300, + + ArmorySoulCrystal = 3400, + ArmoryMain = 3500, + + RetainerBag0 = 10000, + RetainerBag1 = 10001, + RetainerBag2 = 10002, + RetainerBag3 = 10003, + RetainerBag4 = 10004, + RetainerBag5 = 10005, + RetainerBag6 = 10006, + RetainerEquippedGear = 11000, + RetainerGil = 12000, + RetainerCrystal = 12001, + RetainerMarket = 12002, + + FreeCompanyBag0 = 20000, + FreeCompanyBag1 = 20001, + FreeCompanyBag2 = 20002, + FreeCompanyGil = 22000, + FreeCompanyCrystal = 22001 + }; + + + enum struct ZoneingType : uint8_t + { + None = 1, + Teleport = 2, + Return = 3, + ReturnDead = 4, + FadeIn = 5, + }; + + enum struct ResurrectType : uint8_t + { + None = 0, + RaiseSpell = 5, + Return = 8 + }; + + enum Gender : uint8_t + { + Male = 0, + Female = 1, + }; + + + + enum struct GCRank : uint8_t + { + None = 0, + PrivateThirdClass = 1, + PrivateSecondClass = 2, + PrivateFirstClass = 3, + Corporal = 4, + SergeantThirdClass = 5, + SergeantSecondClass = 6, + SergeantFirstClass = 7, + ChiefSergeant = 8, + SecondLieutenant = 9, + FirstLieutenant = 10, + Captain = 11, + SecondCommander = 12, + FirstCommander = 13, + HighCommander = 14, + RearMarshal = 15, + ViceMarshal = 16, + Marshal = 17, + GrandMarshal = 18, + Champion = 19, + }; + + /** + * Structural representation of the packet sent by the server + * Send the entire StatusEffect list */ - const uint16_t MAX_COMBO_LENGTH = 12500; + struct StatusEffect + { + uint16_t effect_id; + uint16_t unknown1; + float duration; + uint32_t sourceActorId; + }; - struct FFXIVARR_POSITION3_U16 - { - uint16_t x; - uint16_t y; - uint16_t z; - }; + enum RegionType : uint8_t + { + normal, + instance, + }; - struct ActiveLand - { - uint8_t ward; - uint8_t plot; - }; + enum TerritoryIntendedUseType : uint8_t //ToDo: Add The Rest of The Territory Types and Have Better Names For Them + { + Town = 0, + OpenWorld = 1, + Inn = 2, + Dungeon = 3, + JailArea = 5, + OpeningArea = 6, + BeforeTrialDung = 7, + AllianceRaid = 8, + OpenWorldInstanceBattle = 9, + Trial = 10, + HousingArea = 13, + HousingPrivateArea = 14, + MSQPrivateArea = 15, + Raids = 16, + RaidFights = 17, + ChocoboTutorial = 21, + Wedding = 22, + BeginnerTutorial = 27, + PalaceOfTheDead = 31, + }; - enum InventoryOperation : uint16_t - { - Discard = 0x013C, - Move = 0x013D, - Swap = 0x013E, - Split = 0x013F, - Merge = 0x0141, - }; + enum CharaLook : uint8_t + { + Race = 0x00, + Gender = 0x01, + Tribe = 0x04, + Height = 0x03, + ModelType = 0x02, // Au Ra: changes horns/tails, everything else: seems to drastically change appearance (flip between two sets, odd/even numbers). sometimes retains hairstyle and other features + FaceType = 0x05, + HairStyle = 0x06, + HasHighlights = 0x07, // negative to enable, positive to disable + SkinColor = 0x08, + EyeColor = 0x09, // color of character's right eye + HairColor = 0x0A, // main color + HairColor2 = 0x0B, // highlights color + FaceFeatures = 0x0C, // seems to be a toggle, (-odd and +even for large face covering), opposite for small + FaceFeaturesColor = 0x0D, + Eyebrows = 0x0E, + EyeColor2 = 0x0F, // color of character's left eye + EyeShape = 0x10, + NoseShape = 0x11, + JawShape = 0x12, + LipStyle = 0x13, // lip colour depth and shape (negative values around -120 darker/more noticeable, positive no colour) + LipColor = 0x14, + RaceFeatureSize = 0x15, + RaceFeatureType = 0x16, // negative or out of range tail shapes for race result in no tail (e.g. Au Ra has max of 4 tail shapes), incorrect value can crash client + BustSize = 0x17, // char creator allows up to max of 100, i set to 127 cause who wouldnt but no visible difference + Facepaint = 0x18, + FacepaintColor = 0x19, - enum ClientLanguage : uint8_t - { - Japanese = 1, - English = 2, - German = 4, - French = 8 - }; + }; - enum TellFlags : uint8_t - { - GmTellMsg = 0x4, - }; + enum MoveType : uint16_t + { + Run = 0x00, + Walk = 0x02, + Strafe = 0x04, + Jump = 0x100, + Fall = 0x400, + Land = 0x200, + }; - enum BNpcType : uint8_t - { - Friendly = 0, - Enemy = 4, - }; - - enum ObjKind : uint8_t - { - None = 0x00, - Player = 0x01, - BattleNpc = 0x02, - EventNpc = 0x03, - Treasure = 0x04, - Aetheryte = 0x05, - GatheringPoint = 0x06, - EventObj = 0x07, - MountType = 0x08, - Companion = 0x09, // this probably actually means minion - Retainer = 0x0A, - Area = 0x0B, - Housing = 0x0C, - Cutscene = 0x0D, - CardStand = 0x0E, - }; - - enum Stance : uint8_t - { - Passive = 0, - Active = 1, - }; - - enum class DisplayFlags : uint16_t - { - ActiveStance = 0x001, - Invisible = 0x020, - HideHead = 0x040, - HideWeapon = 0x080, - Faded = 0x100, - Visor = 0x800, - }; - - enum struct ActorStatus : uint8_t - { - Idle = 0x01, - Dead = 0x02, - Sitting = 0x03, - Mounted = 0x04, - Crafting = 0x05, - Gathering = 0x06, - Melding = 0x07, - SMachine = 0x08, - Carry = 0x09, - EmoteMode = 0x0B - }; - - enum GearSetSlot : uint8_t - { - MainHand = 0, - OffHand = 1, - Head = 2, - Body = 3, - Hands = 4, - Waist = 5, - Legs = 6, - Feet = 7, - Ear = 8, - Neck = 9, - Wrist = 10, - Ring1 = 11, - Ring2 = 12, - SoulCrystal = 13, - }; - - enum GearModelSlot : int8_t - { - ModelInvalid = -1, - ModelHead = 0, - ModelBody = 1, - ModelHands = 2, - ModelLegs = 3, - ModelFeet = 4, - ModelEar = 5, - ModelNeck = 6, - ModelWrist = 7, - ModelRing1 = 8, - ModelRing2 = 9 - }; - - enum class EquipSlotCategory : uint8_t - { - // main slots - - CharaMainHand = 0, - CharaOffHand = 1, - CharaHead = 2, - CharaBody = 3, - CharaHands = 4, - CharaWaist = 5, - CharaLegs = 6, - CharaFeet = 7, - CharaEars = 8, - CharaNeck = 9, - CharaWrist = 10, - CharaRing = 11, - CharaSoulCrystal = 12, - - /* following slots not seem to exist any more. - when multi-slot gear is moved into equipment slot, normal slot listed above is used. - client will move any incompatible gears into armory but no InventoryModifiyHandler is sent. - server need to move those silently in order to sync with client. - */ - - /*! Cannot equip gear to offhand slot */ - //MainTwoHandedWeapon = 13, - /*! Can be equipped in either main or offhand slot */ - //MainOrOffHand = 14, // unused - /*! Cannot equip gear to head */ - //BodyDisallowHead = 15, - /*! Cannot equip gear to hands, legs and feet slots */ - //BodyDisallowHandsLegsFeet = 16, - /*! Cannot equip gear to feet slot */ - //LegsDisallowFeet = 18, - /*! Cannot equp gear to head, hands, legs, feet slots */ - //BodyDisallowAll = 19, - /*! Cannot equip gear to hands slot */ - //BodyDisallowHands = 20, - /*! Cannot equip gear to legs & feet slots */ - //BodyDisallowLegsFeet = 21, - }; - - enum InventoryType : uint16_t - { - Bag0 = 0, - Bag1 = 1, - Bag2 = 2, - Bag3 = 3, - - GearSet0 = 1000, - GearSet1 = 1001, - - Currency = 2000, - Crystal = 2001, - //UNKNOWN_0 = 2003, - KeyItem = 2004, - HandIn = 2005, - DamagedGear = 2007, - //UNKNOWN_1 = 2008, - // Temporary inventory that is used for the "trade" window - TradeInventory = 2009, - - ArmoryOff = 3200, - ArmoryHead = 3201, - ArmoryBody = 3202, - ArmoryHand = 3203, - ArmoryWaist = 3204, - ArmoryLegs = 3205, - ArmoryFeet = 3206, - ArmoryEar = 3207, - ArmoryNeck = 3208, - ArmoryWrist = 3209, - ArmoryRing = 3300, - - ArmorySoulCrystal = 3400, - ArmoryMain = 3500, - - SaddleBag0 = 4000, - SaddleBag1 = 4001, - // These are the ones you get when paying for premium companion app - PremiumSaddleBag0 = 4100, - PremiumSaddleBag1 = 4101, - - RetainerBag0 = 10000, - RetainerBag1 = 10001, - RetainerBag2 = 10002, - RetainerBag3 = 10003, - RetainerBag4 = 10004, - RetainerBag5 = 10005, - RetainerBag6 = 10006, - RetainerEquippedGear = 11000, - RetainerGil = 12000, - RetainerCrystal = 12001, - RetainerMarket = 12002, - - FreeCompanyBag0 = 20000, - FreeCompanyBag1 = 20001, - FreeCompanyBag2 = 20002, - FreeCompanyGil = 22000, - FreeCompanyCrystal = 22001, - - // housing interior containers - HousingInteriorAppearance = 25002, - - // 50 in each container max, 400 slots max - HousingInteriorPlacedItems1 = 25003, - HousingInteriorPlacedItems2 = 25004, - HousingInteriorPlacedItems3 = 25005, - HousingInteriorPlacedItems4 = 25006, - HousingInteriorPlacedItems5 = 25007, - HousingInteriorPlacedItems6 = 25008, - HousingInteriorPlacedItems7 = 25009, - HousingInteriorPlacedItems8 = 25010, - - // 50 max per container, 400 slots max - // slot limit increased 'temporarily' for relocation for all estates - // see: https://na.finalfantasyxiv.com/lodestone/topics/detail/d781e0d538428aef93b8bed4b50dd62c3c50fc74 - HousingInteriorStoreroom1 = 27001, - HousingInteriorStoreroom2 = 27002, - HousingInteriorStoreroom3 = 27003, - HousingInteriorStoreroom4 = 27004, - HousingInteriorStoreroom5 = 27005, - HousingInteriorStoreroom6 = 27006, - HousingInteriorStoreroom7 = 27007, - HousingInteriorStoreroom8 = 27008, - - - // housing exterior containers - HousingExteriorAppearance = 25000, - HousingExteriorPlacedItems = 25001, - HousingExteriorStoreroom = 27000, - - - }; - - struct HuntingLogEntry - { - uint8_t rank; - uint8_t entries[10][4]; - }; - - enum class UnlockEntry : uint16_t - { - Return = 1, - Teleport = 4, - GearSets = 6, - HuntingLog = 21, - }; - - enum ContainerType : uint16_t - { - Unknown = 0, - Bag = 1, - GearSet = 2, - CurrencyCrystal = 3, - Armory = 4 - }; - - - enum CurrencyType : uint8_t - { - Gil = 0x01, - StormSeal = 0x02, - SerpentSeal = 0x03, - FlameSeal = 0x04, - TomestonePhilo = 0x05, - TomestoneMytho = 0x06, - WolfMark = 0x07, - TomestoneSold = 0x08, - AlliedSeal = 0x09, - TomestonePoet = 0x0A, - Mgp = 0x0B, - TomestoneLaw = 0x0C, - TomestoneEso = 0x0D, - TomestoneLore = 0x0E - }; - - enum CrystalType : uint8_t - { - FireShard = 0x01, - IceShard = 0x02, - WindShard = 0x03, - EarthShard = 0x04, - LightningShard = 0x05, - WaterShard = 0x06, - - FireCrystal = 0x07, - IceCrystal = 0x08, - WindCrystal = 0x09, - EarthCrystal = 0x0A, - LightningCrystal = 0x0B, - WaterCrystal = 0x0C, - - FireCluster = 0x0D, - IceCluster = 0x0E, - WindCluster = 0x0F, - EarthCluster = 0x10, - LightningCluster = 0x11, - WaterCluster = 0x12 - }; - - enum struct ZoneingType : uint8_t - { - None = 1, - Teleport = 2, - Return = 3, - ReturnDead = 4, - FadeIn = 5, - }; - - enum struct ResurrectType : uint8_t - { - None = 0, - RaiseSpell = 5, - Return = 8 - }; - - enum Gender : uint8_t - { - Male = 0, - Female = 1, - }; - - - enum struct GCRank : uint8_t - { - None = 0, - PrivateThirdClass = 1, - PrivateSecondClass = 2, - PrivateFirstClass = 3, - Corporal = 4, - SergeantThirdClass = 5, - SergeantSecondClass = 6, - SergeantFirstClass = 7, - ChiefSergeant = 8, - SecondLieutenant = 9, - FirstLieutenant = 10, - Captain = 11, - SecondCommander = 12, - FirstCommander = 13, - HighCommander = 14, - RearMarshal = 15, - ViceMarshal = 16, - Marshal = 17, - GrandMarshal = 18, - Champion = 19, - }; - - /** - * Structural representation of the packet sent by the server - * Send the entire StatusEffect list - */ - struct StatusEffect - { - uint16_t effect_id; - uint16_t param; - float duration; - uint32_t sourceActorId; - }; - - enum CharaLook : uint8_t - { - Race = 0x00, - Gender = 0x01, - Tribe = 0x04, - Height = 0x03, - ModelType = 0x02, // Au Ra: changes horns/tails, everything else: seems to drastically change appearance (flip between two sets, odd/even numbers). sometimes retains hairstyle and other features - FaceType = 0x05, - HairStyle = 0x06, - HasHighlights = 0x07, // negative to enable, positive to disable - SkinColor = 0x08, - EyeColor = 0x09, // color of character's right eye - HairColor = 0x0A, // main color - HairColor2 = 0x0B, // highlights color - FaceFeatures = 0x0C, // seems to be a toggle, (-odd and +even for large face covering), opposite for small - FaceFeaturesColor = 0x0D, - Eyebrows = 0x0E, - EyeColor2 = 0x0F, // color of character's left eye - EyeShape = 0x10, - NoseShape = 0x11, - JawShape = 0x12, - LipStyle = 0x13, // lip colour depth and shape (negative values around -120 darker/more noticeable, positive no colour) - LipColor = 0x14, - RaceFeatureSize = 0x15, - RaceFeatureType = 0x16, // negative or out of range tail shapes for race result in no tail (e.g. Au Ra has max of 4 tail shapes), incorrect value can crash client - BustSize = 0x17, // char creator allows up to max of 100, i set to 127 cause who wouldnt but no visible difference - Facepaint = 0x18, - FacepaintColor = 0x19, - - }; - - enum MoveType : uint8_t - { - Running = 0x00, - Walking = 0x02, - Strafing = 0x04, - Jumping = 0x10, - }; - - enum MoveState : uint8_t - { - No = 0x00, - LeaveCollision = 0x01, - EnterCollision = 0x02, - StartFalling = 0x04, - }; - - enum MoveSpeed : uint8_t - { - Walk = 24, - Run = 60, - }; - - struct QuestActive - { - QuestActive() - { - c.questId = 0; - c.sequence = 0; - c.flags = 0; - c.UI8A = 0; - c.UI8B = 0; - c.UI8C = 0; - c.UI8D = 0; - c.UI8E = 0; - c.UI8F = 0; - c.padding = 0; - c.padding1 = 0; - } - - - union - { - struct + struct QuestActive + { + QuestActive() { - uint16_t questId; - uint8_t sequence; - uint8_t flags; - uint8_t padding; - uint8_t BitFlag48; - uint8_t BitFlag40; - uint8_t BitFlag32; - uint8_t BitFlag24; - uint8_t BitFlag16; - uint8_t BitFlag8; - uint8_t padding1; - } a; + c.questId = 0; + c.sequence = 0; + c.flags = 0; + c.UI8A = 0; + c.UI8B = 0; + c.UI8C = 0; + c.UI8D = 0; + c.UI8E = 0; + c.UI8F = 0; + c.padding = 0; + } - struct + + union { - uint16_t questId; - uint8_t sequence; - uint8_t flags; - uint8_t padding; - uint8_t UI8AL : 4; - uint8_t UI8AH : 4; - uint8_t UI8BL : 4; - uint8_t UI8BH : 4; - uint8_t UI8CL : 4; - uint8_t UI8CH : 4; - uint8_t UI8DL : 4; - uint8_t UI8DH : 4; - uint8_t UI8EL : 4; - uint8_t UI8EH : 4; - uint8_t UI8FL : 4; - uint8_t UI8FH : 4; - uint8_t padding1; - } b; + struct + { + uint16_t questId; + uint8_t sequence; + uint8_t flags; + uint8_t padding; + uint8_t BitFlag48; + uint8_t BitFlag40; + uint8_t BitFlag32; + uint8_t BitFlag24; + uint8_t BitFlag16; + uint8_t BitFlag8; + uint8_t padding1; + } a; - struct - { - uint16_t questId; - uint8_t sequence; - uint8_t flags; - uint8_t padding; - uint8_t UI8A; - uint8_t UI8B; - uint8_t UI8C; - uint8_t UI8D; - uint8_t UI8E; - uint8_t UI8F; - uint8_t padding1; - } c; + struct + { + uint16_t questId; + uint8_t sequence; + uint8_t flags; + uint8_t padding; + uint8_t UI8AL : 4; + uint8_t UI8AH : 4; + uint8_t UI8BL : 4; + uint8_t UI8BH : 4; + uint8_t UI8CL : 4; + uint8_t UI8CH : 4; + uint8_t UI8DL : 4; + uint8_t UI8DH : 4; + uint8_t UI8EL : 4; + uint8_t UI8EH : 4; + uint8_t UI8FL : 4; + uint8_t UI8FH : 4; + uint8_t padding1; + } b; - //struct - //{ - // uint16_t questId; - // uint8_t sequence; - // uint8_t flags; - // uint8_t padding; - // uint16_t UI16A; - // uint16_t UI16B; - // uint16_t UI16C; - // uint8_t padding1; - //} d; + struct + { + uint16_t questId; + uint8_t sequence; + uint8_t flags; + uint8_t padding; + uint8_t UI8A; + uint8_t UI8B; + uint8_t UI8C; + uint8_t UI8D; + uint8_t UI8E; + uint8_t UI8F; + uint8_t padding1; + } c; - //struct - //{ - // uint8_t padding; - // uint32_t UI32A; - // uint16_t padding2; - //} e; - }; + //struct + //{ + // uint16_t questId; + // uint8_t sequence; + // uint8_t flags; + // uint8_t padding; + // uint16_t UI16A; + // uint16_t UI16B; + // uint16_t UI16C; + // uint8_t padding1; + //} d; + + //struct + //{ + // uint8_t padding; + // uint32_t UI32A; + // uint16_t padding2; + //} e; + }; - }; + }; - enum FieldMarkerStatus : uint32_t - { - A = 0x1, - B = 0x2, - C = 0x4, - D = 0x8, - One = 0x10, - Two = 0x20, - Three = 0x40, - Four = 0x80 - }; - // TODO: consolidate these two into one since FieldMarkerStatus == 1 << FieldMarkerId? - enum class FieldMarkerId : uint8_t - { - A, - B, - C, - D, - One, - Two, - Three, - Four - }; + enum EventType : uint16_t + { + Quest = 0x0001, + Warp = 0x0002, + Shop = 0x0004, + Aetheryte = 0x0005, + GuildLeveAssignment = 0x0006, + DefaultTalk = 0x0009, + CustomTalk = 0x000B, + CompanyLeveOfficer = 0x000C, + CraftLeve = 0x000E, + GimmickAccessor = 0x000F, + GimmickBill = 0x0010, + GimmickRect = 0x0011, + ChocoboTaxiStand = 0x0012, + Opening = 0x0013, + ExitRange = 0x0014, + GCShop = 0x0016, + GuildOrderGuide = 0x0017, + GuildOrderOfficer = 0x0018, + ContentNpc = 0x0019, + Story = 0x001A, + SpecialShop = 0x001B, + BahamutGuide = 0x001C, + FcTalk = 0x001F, + }; - enum struct ActionAspect : uint8_t - { - None = 0, // Doesn't imply unaspected - Fire = 1, - Ice = 2, - Wind = 3, - Stone = 4, - Lightning = 5, - Water = 6, - Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical - }; + enum struct ActionAspect : uint8_t + { + None = 0, // Doesn't imply unaspected + Fire = 1, + Ice = 2, + Wind = 3, + Stone = 4, + Lightning = 5, + Water = 6, + Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical + }; - enum class ActionPrimaryCostType : uint8_t - { - None = 0, // ? - MagicPoints = 3, - TacticsPoints = 5, - StatusEffect = 10, - WARGauge = 22, - DRKGauge = 25, - // AetherflowStack = 30, - // Status = 32, - SAMKenki = 39, - SAMSen = 40, - PLDGauge = 41, - GNBAmmo = 55, - WHMBloodLily = 56, - WHMLily = 57, - SAMMeditation = 63, - // RDMGaugeBoth = 74, - //// RDMGaugeBlack = 75, // not right? - // DRGGauge3Eyes = 76, - }; + enum class ActionType : int8_t + { + WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)? + Unknown_0 = 0, + Slashing = 1, + Piercing = 2, + Blunt = 3, + Unknown_4 = 4, + Magical = 5, + Darkness = 6, + Unknown_7 = 7, + LimitBreak = 8, + }; - enum class AttackType : int8_t - { - //WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)? - Physical = -1, // seems to be the case - Unknown_0 = 0, - Slashing = 1, - Piercing = 2, - Blunt = 3, - Unknown_4 = 4, - Magical = 5, - Darkness = 6, - Unknown_7 = 7, - LimitBreak = 8, - }; + enum ActionEffectType : uint8_t + { + Nothing = 0, + Miss = 1, + FullResist = 2, + Damage = 3, + Heal = 4, + BlockedDamage = 5, + ParriedDamage = 6, + Invulnerable = 7, + NoEffectText = 8, + Unknown_0 = 9, + MpLoss = 10, + MpGain = 11, + TpLoss = 12, + TpGain = 13, + GpGain = 14, + Mount = 38 + }; - enum ActionEffectType : uint8_t - { - Nothing = 0, - Miss = 1, - FullResist = 2, - Damage = 3, - Heal = 4, - BlockedDamage = 5, - ParriedDamage = 6, - Invulnerable = 7, - NoEffectText = 8, - Unknown_0 = 9, - MpLoss = 10, - 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 - /*! - * @brief Tells the client that it should show combo indicators on actions. - * - * @param flags Required to be 128, doesn't show combo rings on hotbars otherwise - * @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo - */ - StartActionCombo = 27, // shifted one up from 5.18 - ComboSucceed = 28, // shifted one up from 5.18, on retail this is not seen anymore, still working though. - Knockback = 33, - Mount = 40, // shifted one down from 5.18 - VFX = 59, // links to VFX sheet - }; + enum class ActionHitSeverityType : uint8_t + { + NormalDamage = 0, + CritHeal = 0, + CritDamage = 1, + NormalHeal = 1, + DirectHitDamage = 2, + CritDirectHitDamage = 3 + }; - enum class ActionHitSeverityType : uint8_t - { - NormalDamage = 0, - NormalHeal = 0, - CritDamage = 1, - CritHeal = 1, - DirectHitDamage = 2, - CritDirectHitDamage = 3 - }; + enum class ActionCollisionType : uint8_t + { + None, + SingleTarget, + Circle, + Cone, + Box, + Unknown, + Unknown2, + PersistentArea, // for when you set aoe like asylum + Unknown3 + }; - enum class ActionEffectResultFlag : uint8_t - { - None = 0, - Absorbed = 0x04, - ExtendedValue = 0x40, - EffectOnSource = 0x80, - Reflected = 0xA0, - }; + enum HandleActionType : uint8_t + { + Event, + Spell, + Teleport + }; - enum ItemActionType : uint16_t - { - ItemActionVFX = 852, - ItemActionVFX2 = 944, - }; + enum HandleSkillType : uint8_t + { + StdDamage, + StdHeal, + StdDot, + }; - enum ActionEffectDisplayType : uint8_t - { - HideActionName = 0, - ShowActionName = 1, - ShowItemName = 2, - }; + enum InvincibilityType : uint8_t + { + InvincibilityNone, + InvincibilityRefill, + InvincibilityStayAlive, + }; - struct EffectEntry - { - Common::ActionEffectType effectType; - uint8_t param0; - uint8_t param1; - /*! - * @brief Shows an additional percentage in the battle log - * - * Has no effect on what is shown and stored in value - */ - uint8_t param2; - uint8_t extendedValueHighestByte; - uint8_t flags; - int16_t value; - }; + enum struct PlayerStateFlag : uint8_t + { + SomeFlag, + NoCombat, + Combat, + Casting, + StatusAffliction, + StatusAffliction1, + Occupied, + Occupied1, + Occupied2, + Occupied3, - enum class ActionCollisionType : uint8_t - { - None, - SingleTarget, - Circle, - Cone, - Box, - Unknown, - Unknown2, - PersistentArea, // for when you set aoe like asylum - Unknown3 - }; + BoundByDuty, + Occupied4, + DuelingArea, + TradeOpen, + Occupied5, + HandlingItems, + Crafting, + PreparingToCraft, + Gathering, + Fishing, - enum class ActionInterruptType : uint8_t - { - None, - RegularInterrupt, - DamageInterrupt, - }; + BeingRaised, + BetweenAreas, + Stealthed, + InnRoom, + Jumping, + AutoRun, + Occupied6, + BetweenAreas1, + SystemError, + LoggingOut, - enum HandleActionType : uint8_t - { - Event, - Spell, - Teleport - }; + InvalidLocation, + WaitingForDuty, + BoundByDuty1, + Mounting, + WatchingCutscene, + WaitingForDutyFinder, + CreatingCharacter, + Jumping1, + PvpDisplay, + StatusAfflication2, - enum HandleSkillType : uint8_t - { - StdDamage, - StdHeal, - StdDot, - }; + Mounting1, + CarryingItem, + UsingPartyFinder, + HousingFunctions, + Transformed, + FreeTrail, + BeingMoved, + Mounting2, + StatusAffliction3, + StatusAffliction4, - enum InvincibilityType : uint8_t - { - InvincibilityNone, - InvincibilityRefill, - InvincibilityStayAlive, - InvincibilityIgnoreDamage, - }; + RegisteringRaceOrMatch, + WaitingForRaceOrMatch, + WaitingForTripleTriadMatch, + InFlight, + WatchingCutscene1, + DeepDungeon, + Swimming, + Diving, + RegisteringTripleTriad, + WaitingTripleTriad, + InCrossWorldParty - enum PlayerStateFlag : uint8_t - { - HideUILockChar = 0, // as the name suggests, hides the ui and logs the char... - InCombat = 1, // in Combat, locks gearchange/return/teleport - Casting = 2, - InNpcEvent = 7, // when talking to an npc, locks ui giving "occupied" message + }; - InNpcEvent1 = 10, // Sent together with InNpcEvent, when waiting for input? just a guess... + enum struct FateStatus : uint8_t + { + Active = 2, + Inactive = 4, + Preparing = 7, + Completed = 8, + }; - BetweenAreas = 24, - BoundByDuty = 28, - WatchingCutscene = 50, // this is actually just a dummy, this id is different + enum ActorControlType : uint16_t + { + ToggleWeapon = 0x01, + SetStatus = 0x02, + CastStart = 0x03, + ToggleAggro = 0x04, + ClassJobChange = 0x05, + DefeatMsg = 0x06, + GainExpMsg = 0x07, + LevelUpEffect = 0x0A, - }; + ExpChainMsg = 0x0C, + HpSetStat = 0x0D, + DeathAnimation = 0x0E, + CastInterrupt = 0x0F, - enum struct FateStatus : uint8_t - { - Active = 2, - Inactive = 4, - Preparing = 7, - Completed = 8, - }; + ActionStart = 0x11, - enum struct ChatType : uint16_t - { - LogKindError, - ServerDebug, - ServerUrgent, - ServerNotice, - Unused4, - Unused5, - Unused6, - Unused7, - Unused8, - Unused9, - Say, - Shout, - Tell, - TellReceive, - Party, - Alliance, - LS1, - LS2, - LS3, - LS4, - LS5, - LS6, - LS7, - LS8, - FreeCompany, - Unused25, - Unused26, - NoviceNetwork, - CustomEmote, - StandardEmote, - Yell, - Unknown31, - PartyUnk2, - Unused33, - Unused34, - Unused35, - Unused36, - Unused37, - Unused38, - Unused39, - Unused40, - BattleDamage, - BattleFailed, - BattleActions, - BattleItems, - BattleHealing, - BattleBeneficial, - BattleDetrimental, - BattleUnk48, - BattleUnk49, - Unused50, - Unused51, - Unused52, - Unused53, - Unused54, - Unused55, - Echo, - SystemMessage, - SystemErrorMessage, - BattleSystem, - GatheringSystem, - NPCMessage, - LootMessage, - Unused63, - CharProgress, - Loot, - Crafting, - Gathering, - NPCAnnouncement, - FCAnnouncement, - FCLogin, - RetainerSale, - PartySearch, - PCSign, - DiceRoll, - NoviceNetworkNotice, - Unknown76, - Unused77, - Unused78, - Unused79, - GMTell, - GMSay, - GMShout, - GMYell, - GMParty, - GMFreeCompany, - GMLS1, - GMLS2, - GMLS3, - GMLS4, - GMLS5, - GMLS6, - GMLS7, - GMLS8, - GMNoviceNetwork, - Unused95, - Unused96, - Unused97, - Unused98, - Unused99, - Unused100 - }; + StatusEffectGain = 0x14, + StatusEffectLose = 0x15, - enum EquipDisplayFlags : uint8_t - { - HideNothing = 0x0, - HideHead = 0x1, - HideWeapon = 0x2, - HideLegacyMark = 0x4, + HPFloatingText = 0x17, + UpdateRestedExp = 0x018, + Unk2 = 0x19, - StoreNewItemsInArmouryChest = 0x10, - StoreCraftedItemsInInventory = 0x20, + Flee = 0x1B, - Visor = 0x40, - }; + Unk3 = 0x20, // Animation related? - enum SkillType : uint8_t - { - Normal = 0x1, - ItemAction = 0x2, - MountSkill = 0xD, - }; + CombatIndicationShow = 0x22, - enum HouseExteriorSlot - { - HousePermit, - ExteriorRoof, - ExteriorWall, - ExteriorWindow, - ExteriorDoor, - ExteriorRoofDecoration, - ExteriorWallDecoration, - ExteriorPlacard, - ExteriorFence - }; + SpawnEffect = 0x25, + ToggleInvisible = 0x26, - enum HouseInteriorSlot - { - InteriorWall, - InteriorFloor, - InteriorLight, - InteriorWall_Attic, - InteriorFloor_Attic, - InteriorLight_Attic, - InteriorWall_Basement, - InteriorFloor_Basement, - InteriorLight_Basement, - InteriorLight_Mansion - }; + ToggleActionUnlock = 0x29, - enum HouseTagSlot - { - MainTag, - SubTag1, - SubTag2 - }; + UpdateUiExp = 0x2B, + DmgTakenMsg = 0x2D, - enum LandFlagsSlot - { - FreeCompany, - Private, - Apartment, - SharedHouse1, - SharedHouse2 - }; + SetTarget = 0x32, + ToggleNameHidden = 0x36, - enum class LandType : uint8_t - { - none = 0, - FreeCompany = 1, - Private = 2, - }; + LimitbreakStart = 0x47, + LimitbreakPartyStart = 0x48, + BubbleText = 0x49, - enum LandFlags : uint32_t - { - EstateBuilt = 0x1, - HasAetheryte = 0x2, - UNKNOWN_1 = 0x4, - UNKNOWN_2 = 0x8, - UNKNOWN_3 = 0x10, - }; + DamageEffect = 0x50, + RaiseAnimation = 0x51, + TreasureScreenMsg = 0x57, + SetOwnerId = 0x59, + ItemRepairMsg = 0x5C, - struct LandIdent - { - int16_t landId; //00 - int16_t wardNum; //02 - int16_t territoryTypeId; //04 - int16_t worldId; //06 - }; + LeveStartAnim = 0x66, + LeveStartError = 0x67, + PlayerNameGrayout = 0x6A, - struct LandFlagSet - { - LandIdent landIdent; - uint32_t landFlags; //08 - uint32_t unkown1; //12 - }; + ItemObtainMsg = 0x75, + DutyQuestScreenMsg = 0x7B, - struct HousingObject - { - uint32_t itemId; - uint32_t padding; // was itemrotation + unknown/pad, looks unused now - float rotation; - Common::FFXIVARR_POSITION3 pos; - }; + ItemObtainIcon = 0x84, + FateItemFailMsg = 0x85, + ItemFailMsg = 0x86, + ActionLearnMsg1 = 0x87, - enum HouseSize : uint8_t - { - Cottage, - House, - Mansion - }; + FreeEventPos = 0x8A, - enum HouseStatus : uint8_t - { - none, - ForSale, - Sold, - PrivateEstate, - FreeCompanyEstate, - }; + UnlockAetherCurrentMsg = 0xA4, - enum HouseIconAdd : uint8_t - { - heart = 0x06 - }; + RemoveName = 0xA8, - enum WardlandFlags : uint8_t - { - IsEstateOwned = 1, - IsPublicEstate = 2, - HasEstateGreeting = 4, - EstateFlagUnknown = 8, - IsFreeCompanyEstate = 16, - }; + ScreenFadeOut = 0xAA, - struct PlayerTeleportQuery - { - uint16_t targetAetheryte; - uint16_t cost; - }; + ZoneIn = 0xC8, + ZoneInDefaultPos = 0xC9, - enum LevelTableEntry : uint8_t - { - MAIN, - SUB, - DIV, - HP, - ELMT, - THREAT - }; + TeleportStart = 0xCB, - enum CastType : uint8_t - { - SingleTarget = 1, - CircularAOE = 2, - Type3 = 3, // another single target? no idea how to call it - RectangularAOE = 4, - CircularAoEPlaced = 7 - }; + TeleportDone = 0xCD, + TeleportDoneFadeOut = 0xCE, + DespawnZoneScreenMsg = 0xCF, - enum class Role : uint8_t - { - None, - Tank, - Healer, - RangedPhysical, - RangedMagical, - Melee, - Crafter, - Gatherer - }; + InstanceSelectDlg = 0xD2, + ActorDespawnEffect = 0xD4, - enum class AstCardType : uint8_t - { - None = 0, - Balance = 1, - Bole = 2, - Arrow = 3, - Spear = 4, - Ewer = 5, - Spire = 6, - Lord = 0x70, - Lady = 0x80, - }; + CompanionUnlock = 0xFD, + ObtainBarding = 0xFE, + EquipBarding = 0xFF, - enum class AstSealType : uint8_t - { - None = 0, - Sun = 1, - Moon = 2, - Celestrial = 3, - }; + CompanionMsg1 = 0x102, + CompanionMsg2 = 0x103, + ShowPetHotbar = 0x104, - enum class DrgState : uint8_t - { - None = 0, - BloodOfTheDragon = 1, - LifeOfTheDragon = 2, - }; + ActionLearnMsg = 0x109, + ActorFadeOut = 0x10A, + ActorFadeIn = 0x10B, + WithdrawMsg = 0x10C, + OrderMinion = 0x10D, + ToggleMinion = 0x10E, + LearnMinion = 0x10F, + ActorFateOut1 = 0x110, - enum class SamSen : uint8_t - { - None = 0, - Setsu = 1, - Getsu = 2, - Ka = 4, - }; + Emote = 0x122, - enum class SchDismissedFairy : uint8_t - { - None = 0, - Eos = 6, - Selene = 7, - }; + SetPose = 0x127, - enum class SmnPet : uint8_t - { - None = 0, - Ifrit = 3, - Titan = 4, - Garuda = 5, - }; + CraftingUnk = 0x12C, - enum class SmnPetGlam : uint8_t - { - None = 0, - Emerald = 1, - Topaz = 2, - Ruby = 3, - }; + GatheringSenseMsg = 0x130, + PartyMsg = 0x131, + GatheringSenseMsg1 = 0x132, - enum class BrdSong : uint8_t - { - Mage = 5, - Army = 0x0A, - Wanderer = 0x0F, - }; + GatheringSenseMsg2 = 0x138, - union JobGauge - { - struct - { - uint8_t gauge_data[15]; - } _raw; + FishingMsg = 0x140, - struct - { - uint32_t unused; - AstCardType card; - AstSealType seals[3]; - } ast; - struct - { - uint16_t timeUntilNextPolyglot; - uint16_t elementTimer; - uint8_t elementStance; - uint8_t umbralhearts; - uint8_t polyglotStacks; - uint8_t enochainState; - } blm; - struct - { - uint16_t songTimer; - uint8_t songStacks; - uint8_t unused; - BrdSong song; - } brd; - struct - { - uint8_t feathers; - uint8_t esprit; - uint8_t stepOrder[4]; - uint8_t completeSteps; - } dnc; - struct - { - uint16_t dragonTimer; - DrgState dragonState; - uint8_t eyes; - } drg; - struct - { - uint8_t blood; - uint8_t unused; - uint16_t darksideTimer; - uint8_t darkArts; - uint8_t unused2; - uint16_t shadowTimer; - } drk; - struct - { - uint8_t ammo; - uint8_t unused; - uint16_t maxTimerDuration; - uint8_t ammoComboStep; - } gnb; - struct - { - uint16_t overheatTimer; - uint16_t robotTimer; - uint8_t heat; - uint8_t battery; - uint8_t lastRobotBatteryPower; - uint8_t activeTimerFlag; - } mch; - struct - { - uint8_t greasedLightningTimer; - uint8_t unused; - uint8_t greasedLightningStacks; - uint8_t chakra; - uint8_t greasedLightningTimerFreezed; - } mnk; - struct - { - uint32_t hutonTimer; - uint8_t tenChiJinMudrasUsed; - uint8_t ninki; - uint8_t hutonManualCasts; - } nin; - struct - { - uint8_t oathGauge; - } pld; - struct - { - uint8_t whiteGauge; - uint8_t blackGauge; - } rdm; - struct - { - uint16_t unused; - uint8_t unused2; - uint8_t kenki; - uint8_t meditationStacks; - SamSen sen; - } sam; - struct - { - uint16_t unused; - uint8_t aetherflowStacks; - uint8_t fairyGauge; - uint16_t seraphTimer; - SchDismissedFairy dismissedFairy; - } sch; - struct - { - uint16_t timer; - SmnPet returnSummon; - SmnPetGlam petGlam; - uint8_t stacks; - } smn; + FishingBaitMsg = 0x145, - struct - { - uint8_t beastGauge; - } war; - struct - { - uint16_t unused; - uint16_t lilyTimer; - uint8_t lilies; - uint8_t bloodLilies; - } whm; - }; + FishingReachMsg = 0x147, + FishingFailMsg = 0x148, - enum class LootMessageType : uint8_t - { - GetItem1 = 1, // p1: actorId, p4: itemId (HQ: itemId + 1,000,000 lol), p5: amount - GetItem2 = 3, // p1: actorId, p2: itemId, p3: amount, seems like same thing as GetItem1 but different param position. - FailedToGetLootNoFreeInventorySlot = 5, // p1: actorId - LootRolled = 7, // p1: actorId, p2: itemId, p3: amount - GetGil = 9, // p1: gil - EmptyCoffer = 11, // seems like no param - }; + MateriaConvertMsg = 0x15E, + MeldSuccessMsg = 0x15F, + MeldFailMsg = 0x160, + MeldModeToggle = 0x161, - using PlayerStateFlagList = std::vector< PlayerStateFlag >; + AetherRestoreMsg = 0x163, -} + DyeMsg = 0x168, + + ToggleCrestMsg = 0x16A, + ToggleBulkCrestMsg = 0x16B, + MateriaRemoveMsg = 0x16C, + GlamourCastMsg = 0x16D, + GlamourRemoveMsg = 0x16E, + + RelicInfuseMsg = 0x179, + + AetherReductionDlg = 0x17D, + + Unk6 = 0x19C, + + SetTitle = 0x1F4, + + SetStatusIcon = 0x1F8, + + SetHomepoint = 0x1FB, + SetFavorite = 0x1FC, + LearnTeleport = 0x1FD, + + ArmoryErrorMsg = 0x201, + + AchievementPopup = 0x203, + + Unk7 = 0x205, // LogMessage? + AchievementMsg = 0x206, + + SetItemLevel = 0x209, + + ChallengeEntryCompleteMsg = 0x20B, + ChallengeEntryUnlockMsg = 0x20C, + + GilTrailMsg = 0x211, + + SetMaxGearSets = 0x230, + + SetCharaGearParamUI = 0x260, + + GearSetEquipMsg = 0x321, + + ToggleOrchestrionUnlock = 0x396, + Dismount = 0x3a0 + }; + + enum struct ChatType : uint16_t + { + LogKindError, + ServerDebug, + ServerUrgent, + ServerNotice, + Unused4, + Unused5, + Unused6, + Unused7, + Unused8, + Unused9, + Say, + Shout, + Tell, + TellReceive, + Party, + Alliance, + LS1, + LS2, + LS3, + LS4, + LS5, + LS6, + LS7, + LS8, + FreeCompany, + Unused25, + Unused26, + NoviceNetwork, + CustomEmote, + StandardEmote, + Yell, + Unknown31, + PartyUnk2, + Unused33, + Unused34, + Unused35, + Unused36, + Unused37, + Unused38, + Unused39, + Unused40, + BattleDamage, + BattleFailed, + BattleActions, + BattleItems, + BattleHealing, + BattleBeneficial, + BattleDetrimental, + BattleUnk48, + BattleUnk49, + Unused50, + Unused51, + Unused52, + Unused53, + Unused54, + Unused55, + Echo, + SystemMessage, + SystemErrorMessage, + BattleSystem, + GatheringSystem, + NPCMessage, + LootMessage, + Unused63, + CharProgress, + Loot, + Crafting, + Gathering, + NPCAnnouncement, + FCAnnouncement, + FCLogin, + RetainerSale, + PartySearch, + PCSign, + DiceRoll, + NoviceNetworkNotice, + Unknown76, + Unused77, + Unused78, + Unused79, + GMTell, + GMSay, + GMShout, + GMYell, + GMParty, + GMFreeCompany, + GMLS1, + GMLS2, + GMLS3, + GMLS4, + GMLS5, + GMLS6, + GMLS7, + GMLS8, + GMNoviceNetwork, + Unused95, + Unused96, + Unused97, + Unused98, + Unused99, + Unused100 + }; + + enum EquipDisplayFlags : uint8_t + { + HideNothing = 0x0, + HideHead = 0x1, + HideWeapon = 0x2, + LegacyMark = 0x4, + + Visor = 0x40, + }; + + enum SkillType : uint8_t + { + Normal = 0x1, + MountSkill = 0xD, + }; + + /*! ModelType as found in eventsystemdefine.exd */ + enum ModelType : uint8_t + { + Human = 1, + DemiHuman = 2, + Monster = 3, + SharedGroup = 4, + Parts = 5 + }; + + typedef std::vector< PlayerStateFlag > PlayerStateFlagList; + +} /* Common */ +} /* Core */ #endif diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index e21d1427..a4d6e1c2 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -7,1637 +7,1183 @@ #ifndef _CORE_NETWORK_PACKETS_ZONE_SERVER_IPC_H #define _CORE_NETWORK_PACKETS_ZONE_SERVER_IPC_H -#include -#include +#include +#include -namespace Sapphire::Network::Packets::Server +namespace Core { +namespace Network { +namespace Packets { +namespace Server { + +/** +* Structural representation of the packet sent by the server as response +* to a ping packet +*/ +struct FFXIVIpcPing : FFXIVIpcBasePacket { + /* 0000 */ uint64_t timeInMilliseconds; + /* 0008 */ uint8_t unknown_8[0x38]; +}; - /** - * Structural representation of the packet sent by the server as response - * to a ping packet - */ - struct FFXIVIpcPing : FFXIVIpcBasePacket< Ping > - { - /* 0000 */ uint64_t timeInMilliseconds; - /* 0008 */ uint8_t unknown_8[0x38]; - }; +/** +* Structural representation of the packet sent by the server as response +* to a ping packet +*/ +struct FFXIVIpcInit : FFXIVIpcBasePacket +{ + uint64_t unknown; + uint32_t charId; + uint32_t unknown1; +}; - /** - * Structural representation of the packet sent by the server as response - * to a ping packet - */ - struct FFXIVIpcInit : FFXIVIpcBasePacket< Init > - { - uint64_t unknown; - uint32_t charId; - uint32_t unknown1; - }; +/** +* Structural representation of the packet sent by the server +* carrying chat messages +*/ +struct FFXIVIpcChat : FFXIVIpcBasePacket +{ + /* 0000 */ uint8_t padding[14]; //Maybe this is SubCode, or some kind of talker ID... + Common::ChatType chatType; + char name[32]; + char msg[1012]; +}; - /** - * Structural representation of the packet sent by the server - * carrying chat messages - */ - struct FFXIVIpcChat : FFXIVIpcBasePacket< Chat > - { - /* 0000 */ uint8_t padding[14]; //Maybe this is SubCode, or some kind of talker ID... - Common::ChatType chatType; - char name[32]; - char msg[1012]; - }; +struct FFXIVIpcChatBanned : FFXIVIpcBasePacket +{ + uint8_t padding[4]; // I was not sure reinterpreting ZST is valid behavior in C++. + // client doesn't care about the data (zero sized) for this opcode anyway. +}; - 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; - }; +/** +* Structural representation of the packet sent by the server +* carrying chat messages +*/ +struct FFXIVIpcLogout : FFXIVIpcBasePacket +{ + uint32_t flags1; + uint32_t flags2; +}; - struct FFXIVIpcChatBanned : FFXIVIpcBasePacket< ChatBanned > - { - uint8_t padding[4]; // I was not sure reinterpreting ZST is valid behavior in C++. - // client doesn't care about the data (zero sized) for this opcode anyway. - }; - - /** - * Structural representation of the packet sent by the server - * to show a list of worlds for world visit - */ - struct FFXIVIpcWorldVisitList : FFXIVIpcBasePacket< WorldVisitList > - { - struct worldEntry - { - uint16_t id; // this is the id of the world from lobby - uint16_t status; // 1 = available (this is what retail sends) | 2+ = unavailable (this will need to be checked with retail if it's exactly 2 or not since it does not actually lock the option) - } world[16]; - }; - - /** - * Structural representation of the packet sent by the server - * carrying chat messages - */ - struct FFXIVIpcLogout : FFXIVIpcBasePacket< Logout > - { - uint32_t flags1; - uint32_t flags2; - }; - - /** - * Structural representation of the packet sent by the server - * sent to show the play time - */ - struct FFXIVIpcPlayTime : FFXIVIpcBasePacket< Playtime > - { - uint32_t playTimeInMinutes; - uint32_t padding; - }; +/** +* Structural representation of the packet sent by the server +* sent to show the play time +*/ +struct FFXIVIpcPlayTime : FFXIVIpcBasePacket +{ + uint32_t playTimeInMinutes; + uint32_t padding; +}; - /** - * Structural representation of the packet sent by the server - * with a list of players ( party list | friend list | search results ) - */ - struct PlayerEntry - { - uint64_t contentId; - uint8_t bytes[12]; - uint16_t zoneId; - uint16_t zoneId1; - char bytes1[8]; - uint64_t onlineStatusMask; - uint8_t classJob; - uint8_t padding; - uint8_t level; - uint8_t padding1; - uint16_t padding2; - uint8_t one; - char name[0x20]; - char fcTag[9]; - }; +/** +* Structural representation of the packet sent by the server +* with a list of players ( party list | friend list | search results ) +*/ +struct PlayerEntry { + uint64_t contentId; + uint8_t bytes[12]; + uint16_t zoneId; + uint16_t zoneId1; + char bytes1[8]; + uint64_t onlineStatusMask; + uint8_t classJob; + uint8_t padding; + uint8_t level; + uint8_t padding1; + uint16_t padding2; + uint8_t one; + char name[0x20]; + char fcTag[9]; +}; - struct FFXIVIpcSocialList : FFXIVIpcBasePacket< SocialList > - { - uint32_t padding; - uint32_t padding1; - uint32_t padding2; - uint8_t type; - uint8_t sequence; - uint16_t padding3; +struct FFXIVIpcSocialList : FFXIVIpcBasePacket +{ + uint32_t padding; + uint32_t padding1; + uint32_t padding2; + uint8_t type; + uint8_t sequence; + uint16_t padding3; - PlayerEntry entries[10]; - }; + PlayerEntry entries[10]; +}; - struct FFXIVIpcExamineSearchInfo : FFXIVIpcBasePacket< ExamineSearchInfo > - { - uint32_t unknown; - uint16_t unknown1; - uint16_t unknown2; - char padding[16]; - uint32_t unknown3; - uint16_t unknown4; - uint16_t unknown5; - uint16_t unknown6; - uint8_t worldId; - char searchMessage[193]; - char fcName[24]; - uint8_t unknown7; - uint16_t padding1; - struct ClassJobEntry - { - uint16_t id; - uint16_t level; - } levelEntries[Common::CLASSJOB_TOTAL]; - }; - struct FFXIVIpcSetSearchInfo : FFXIVIpcBasePacket< UpdateSearchInfo > - { - uint64_t onlineStatusFlags; - uint64_t unknown; - uint32_t unknown1; - uint8_t padding; - uint8_t selectRegion; - char searchMessage[193]; - uint8_t padding2; - }; +struct FFXIVIpcSetSearchInfo : FFXIVIpcBasePacket +{ + uint64_t onlineStatusFlags; + uint64_t unknown; + uint32_t unknown1; + uint8_t padding; + uint8_t selectRegion; + char searchMessage[193]; + uint8_t padding2; +}; - struct FFXIVIpcInitSearchInfo : FFXIVIpcBasePacket< InitSearchInfo > - { - uint64_t onlineStatusFlags; - uint64_t unknown; - uint8_t unknown1; - uint8_t selectRegion; - char searchMessage[193]; - char padding[5]; - }; +struct FFXIVIpcInitSearchInfo : FFXIVIpcBasePacket +{ + uint64_t onlineStatusFlags; + uint64_t unknown; + uint8_t unknown1; + uint8_t selectRegion; + char searchMessage[193]; + char padding[5]; +}; - struct FFXIVIpcExamineSearchComment : FFXIVIpcBasePacket< ExamineSearchComment > - { - uint32_t charId; - // packet only has 196 bytes after the charid - // likely utf8 - char searchComment[195]; - char padding; - }; - - /** - * Structural representation of the packet sent by the server - * to display a server notice message - */ - struct FFXIVIpcServerNoticeShort : FFXIVIpcBasePacket< ServerNoticeShort > - { - // these are actually display flags - /* 0000 */ uint8_t padding; - // 0 = chat log - // 2 = nothing - // 4 = on screen message - // 5 = on screen message + chat log - char message[538]; - }; - - /** - * Structural representation of the packet sent by the server - * to display a server notice message - */ - struct FFXIVIpcServerNotice : FFXIVIpcBasePacket< ServerNotice > - { - // these are actually display flags - /* 0000 */ uint8_t padding; - // 0 = chat log - // 2 = nothing - // 4 = on screen message - // 5 = on screen message + chat log - char message[775]; - }; +/** +* Structural representation of the packet sent by the server +* to display a server notice message +*/ +struct FFXIVIpcServerNotice : FFXIVIpcBasePacket +{ + /* 0000 */ uint8_t padding; + char message[307]; +}; - struct FFXIVIpcSetOnlineStatus : FFXIVIpcBasePacket< SetOnlineStatus > - { - uint64_t onlineStatusFlags; - }; +struct FFXIVIpcSetOnlineStatus : FFXIVIpcBasePacket +{ + uint64_t onlineStatusFlags; +}; - struct FFXIVIpcBlackList : FFXIVIpcBasePacket< BlackList > - { - struct BlEntry - { +struct FFXIVIpcBlackList : FFXIVIpcBasePacket +{ + struct BlEntry + { uint64_t contentId; char name[32]; - } entry[20]; - uint8_t padding; - uint8_t padding1; - uint16_t sequence; - uint32_t padding2; - }; + } entry[20]; + uint8_t padding; + uint8_t padding1; + uint16_t sequence; + uint32_t padding2; +}; - struct FFXIVIpcLogMessage : FFXIVIpcBasePacket< LogMessage > - { - uint32_t field_0; - uint32_t field_4; - uint32_t field_8; - uint32_t field_12; - uint32_t category; - uint32_t logMessage; - uint8_t field_24; - uint8_t field_25; - uint8_t field_26[32]; - uint32_t field_58; - }; +struct FFXIVIpcLogMessage : FFXIVIpcBasePacket +{ + uint32_t field_0; + uint32_t field_4; + uint32_t field_8; + uint32_t field_12; + uint32_t category; + uint32_t logMessage; + uint8_t field_24; + uint8_t field_25; + uint8_t field_26[32]; + uint32_t field_58; +}; - struct FFXIVIpcLinkshellList : FFXIVIpcBasePacket< LinkshellList > - { - struct LsEntry - { +struct FFXIVIpcLinkshellList : FFXIVIpcBasePacket +{ + struct LsEntry + { uint64_t lsId; uint64_t unknownId; uint8_t unknown; uint8_t rank; uint16_t padding; uint8_t lsName[20]; - uint8_t unk[16]; - } entry[8]; - }; + } entry[8]; +}; - /** - * Structural representation of the packet sent by the server - * to send a list of mail the player has - */ - struct FFXIVIpcReqMoogleMailList : FFXIVIpcBasePacket< ReqMoogleMailList > - { - struct letterEntry - { - char unk[0x8]; - uint32_t timeStamp; // The time the mail was sent (this also seems to be used as a Id) - char unk1[0x30]; // This should be items, gil, etc for the letter - uint8_t read; // 0 = false | 1 = true - uint8_t type; // 0 = Friends | 1 = Rewards | 2 = GM - uint8_t unk2; - char senderName[0x20]; // The name of the sender - char summary[0x3C]; // The start of the full letter text - char padding2[0x5]; - } letter[5]; - char unk3[0x08]; - }; +struct FFXIVIpcStatusEffectList : FFXIVIpcBasePacket +{ + uint8_t classId; + uint8_t classId1; + uint16_t level; + uint32_t current_hp; + uint32_t max_hp; + uint16_t current_mp; + uint16_t max_mp; + uint16_t currentTp; + uint16_t unknown1; + Common::StatusEffect effect[30]; + uint32_t padding; +}; - /** - * Structural representation of the packet sent by the server - * to show the mail delivery notification - */ - struct FFXIVIpcMailLetterNotification : FFXIVIpcBasePacket< MailLetterNotification > - { - uint32_t sendbackCount; // The amount of letters sent back since you ran out of room (moogle dialog changes based on this) - uint16_t friendLetters; // The amount of letters in the friends section of the letterbox - uint16_t unreadCount; // The amount of unreads in the letterbox (this is the number that shows up) - uint16_t rewardLetters; // The amount of letters in the rewards section of the letterbox - uint8_t isGmLetter; // Makes the letter notification flash red - uint8_t isSupportDesk; // After setting this to 1 we can no longer update mail notifications (more research needed on the support desk) - char unk2[0x4]; // This has probs something to do with the support desk (inquiry id?) - }; +struct FFXIVGCAffiliation : FFXIVIpcBasePacket +{ + uint8_t gcId; + uint8_t gcRank[3]; +}; - struct FFFXIVIpcMarketTaxRates : FFXIVIpcBasePacket< MarketTaxRates > - { - // Same handler as MiniCactpotInit - uint32_t type; - uint16_t category; - uint8_t unknown1; - uint8_t unknown2; - uint32_t taxRate[Common::TOWN_COUNT]; // In the order of Common::Town - uint64_t unknown3; - }; +/** +* Structural representation of the packet sent by the server +* add a status effect +*/ +struct FFXIVIpcAddStatusEffect : FFXIVIpcBasePacket +{ + uint32_t unknown; + uint32_t actor_id; + uint8_t unknown1; + uint8_t unknown2; + uint16_t padding1; + uint32_t current_hp; + uint16_t current_mp; + uint16_t current_tp; + uint32_t max_hp; + uint16_t max_mp; + uint16_t max_something; + uint8_t effect_index; // which position do i display this + uint8_t unknown3; + uint16_t effect_id; + uint16_t param; + uint16_t unknown5; // Sort this out (old right half of power/param property) + float duration; + uint32_t actor_id1; + uint8_t unknown4[52]; +}; - struct FFFXIVIpcMarketBoardItemListingCount : FFXIVIpcBasePacket< MarketBoardItemListingCount > - { - uint32_t itemCatalogId; - uint32_t unknown1; // does some shit if nonzero - uint16_t requestId; - uint16_t quantity; // high/low u8s read separately? - uint32_t unknown3; - }; +/** +* Structural representation of the packet sent by the server +* to update certain player details / status +*/ +struct FFXIVIpcActorControl142 : FFXIVIpcBasePacket +{ + /* 0000 */ uint16_t category; + /* 0002 */ uint16_t padding; + /* 0004 */ uint32_t param1; + /* 0008 */ uint32_t param2; + /* 000C */ uint32_t param3; + /* 0010 */ uint32_t param4; + /* 0014 */ uint32_t padding1; +}; - struct FFXIVIpcMarketBoardItemListing : FFXIVIpcBasePacket< MarketBoardItemListing > - { - struct ItemListing // 152 bytes each - { - uint64_t listingId; - uint64_t retainerId; - uint64_t retainerOwnerId; - uint64_t artisanId; - uint32_t pricePerUnit; - uint32_t totalTax; - uint32_t itemQuantity; - uint32_t itemId; - uint16_t lastReviewTime; - uint16_t containerId; - uint32_t slotId; - uint16_t durability; - uint16_t spiritBond; - /** - * auto materiaId = (i & 0xFF0) >> 4; - * auto index = i & 0xF; - * auto leftover = i >> 8; - */ - uint16_t materiaValue[5]; - uint16_t padding1; - uint32_t padding2; - char retainerName[32]; - char playerName[32]; - bool hq; - uint8_t materiaCount; - uint8_t onMannequin; - Common::Town marketCity; - uint16_t dyeId; - uint16_t padding3; - uint32_t padding4; - } listing[10]; // Multiple packets are sent if there are more than 10 search results. - uint8_t listingIndexEnd; - uint8_t listingIndexStart; - uint16_t requestId; - char padding7[16]; - uint8_t unknown13; - uint16_t padding8; - uint8_t unknown14; - uint64_t padding9; - uint32_t unknown15; - uint32_t padding10; - }; +/** +* Structural representation of the packet sent by the server +* to update certain player details / status +*/ +struct FFXIVIpcActorControl143 : FFXIVIpcBasePacket +{ + /* 0000 */ uint16_t category; + /* 0002 */ uint16_t padding; + /* 0004 */ uint32_t param1; + /* 0008 */ uint32_t param2; + /* 000C */ uint32_t param3; + /* 0010 */ uint32_t param4; + /* 0014 */ uint32_t param5; + /* 0018 */ uint32_t param6; + /* 0018 */ uint32_t padding1; +}; - struct FFXIVIpcMarketBoardItemListingHistory : FFXIVIpcBasePacket< MarketBoardItemListingHistory > - { - uint32_t itemCatalogId; - uint32_t itemCatalogId2; +/** +* Structural representation of the packet sent by the server +* to update certain player details / status +*/ +struct FFXIVIpcActorControl144 : FFXIVIpcBasePacket +{ + /* 0000 */ uint16_t category; + /* 0002 */ uint16_t padding; + /* 0004 */ uint32_t param1; + /* 0008 */ uint32_t param2; + /* 000C */ uint32_t param3; + /* 0010 */ uint32_t param4; + /* 0014 */ uint32_t padding1; + /* 0018 */ uint64_t targetId; +}; - struct MarketListing - { - uint32_t salePrice; - uint32_t purchaseTime; - uint32_t quantity; - uint8_t isHq; - uint8_t padding; - uint8_t onMannequin; - - char buyerName[33]; - - uint32_t itemCatalogId; - } listing[20]; - }; - - struct FFXIVIpcMarketBoardSearchResult : FFXIVIpcBasePacket< MarketBoardSearchResult > - { - struct MarketBoardItem - { - uint32_t itemCatalogId; - uint16_t quantity; - uint16_t demand; - } items[20]; - - uint32_t itemIndexEnd; - uint32_t padding1; - uint32_t itemIndexStart; - uint32_t requestId; - }; - - struct FFXIVIpcExamineFreeCompanyInfo : FFXIVIpcBasePacket< ExamineFreeCompanyInfo > - { - char unknown[0x20]; // likely fc allegiance/icon/housing info etc - uint32_t charId; - uint32_t fcTimeCreated; - char unknown2[0x10]; - uint16_t unknown3; - char fcName[0x14]; // 20 char limit - uint16_t padding; - char fcTag[0x05]; // 5 char tag limit - uint16_t padding2; // null terminator? - char fcLeader[0x20]; // leader name (32 bytes) - char fcSlogan[192]; // source: https://ffxiv.gamerescape.com/wiki/Free_Company (packet cap confirms this size also) - char padding3; // null terminator? - char fcEstateProfile[20]; // todo: size needs confirmation - uint32_t padding4; - }; - - struct FFXIVIpcFreeCompanyUpdateShortMessage : FFXIVIpcBasePacket< FreeCompanyUpdateShortMessage > - { - uint32_t unknown; - uint16_t unknown1; - uint16_t unknown2; - uint32_t unknown3; - uint32_t unknown5; - char shortMessage[104]; - }; - - struct FFXIVIpcStatusEffectList : FFXIVIpcBasePacket< StatusEffectList > - { - uint8_t classId; - uint8_t level1; - uint16_t level; - uint32_t current_hp; - uint32_t max_hp; - uint16_t current_mp; - uint16_t max_mp; - uint8_t shieldPercentage; - uint8_t unknown1; - uint16_t unknown2; - Common::StatusEffect effect[30]; - uint32_t padding; - }; - - struct FFXIVGCAffiliation : FFXIVIpcBasePacket< GCAffiliation > - { - uint8_t gcId; - uint8_t gcRank[3]; - }; - - /** - * Structural representation of the packet sent by the server - * add a status effect - */ - struct FFXIVIpcEffectResult : FFXIVIpcBasePacket< EffectResult > - { - uint32_t globalSequence; - uint32_t actor_id; - uint32_t current_hp; - uint32_t max_hp; - uint16_t current_mp; - uint8_t unknown1; - uint8_t classId; - uint8_t shieldPercentage; - uint8_t entryCount; - uint16_t unknown2; - - struct StatusEntry - { - uint8_t index; // which position do i display this - uint8_t unknown3; - uint16_t id; - uint16_t param; - uint16_t unknown4; // Sort this out (old right half of power/param property) - float duration; - uint32_t sourceActorId; - } statusEntries[4]; - - }; - - /** - * Structural representation of the packet sent by the server - * to update certain player details / status - */ - struct FFXIVIpcActorControl : FFXIVIpcBasePacket< ActorControl > - { - /* 0000 */ uint16_t category; - /* 0002 */ uint16_t padding; - /* 0004 */ uint32_t param1; - /* 0008 */ uint32_t param2; - /* 000C */ uint32_t param3; - /* 0010 */ uint32_t param4; - /* 0014 */ uint32_t padding1; - }; - - /** - * Structural representation of the packet sent by the server - * to update certain player details / status - */ - struct FFXIVIpcActorControlSelf : FFXIVIpcBasePacket< ActorControlSelf > - { - /* 0000 */ uint16_t category; - /* 0002 */ uint16_t padding; - /* 0004 */ uint32_t param1; - /* 0008 */ uint32_t param2; - /* 000C */ uint32_t param3; - /* 0010 */ uint32_t param4; - /* 0014 */ uint32_t param5; - /* 0018 */ uint32_t param6; - /* 0018 */ uint32_t padding1; - }; - - /** - * Structural representation of the packet sent by the server - * to update certain player details / status - */ - struct FFXIVIpcActorControlTarget : FFXIVIpcBasePacket< ActorControlTarget > - { - /* 0000 */ uint16_t category; - /* 0002 */ uint16_t padding; - /* 0004 */ uint32_t param1; - /* 0008 */ uint32_t param2; - /* 000C */ uint32_t param3; - /* 0010 */ uint32_t param4; - /* 0014 */ uint32_t padding1; - /* 0018 */ uint64_t targetId; - }; - - /** - * Structural representation of the packet sent by the server - * to update HP / MP / TP - */ - struct FFXIVIpcUpdateHpMpTp : FFXIVIpcBasePacket< UpdateHpMpTp > - { - /* 0000 */ uint32_t hp; - /* 0004 */ uint16_t mp; - /* 0006 */ uint16_t tp; - /* 0008 */ uint16_t gp; - /* 0010 */ uint16_t unknown_10; - /* 0012 */ uint32_t unknown_12; - }; - - struct FFXIVIpcEffect : FFXIVIpcBasePacket< Effect > - { - uint64_t animationTargetId; // who the animation targets - - uint32_t actionId; // what the casting player casts, shown in battle log/ui - /*! - * @brief Zone sequence for the effect. Used to link effects that are split across multiple packets as one - */ - uint32_t sequence; - - float animationLockTime; // maybe? doesn't seem to do anything - 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. - * - * 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. - */ - uint16_t sourceSequence; - uint16_t rotation; - uint16_t actionAnimationId; // the animation that is played by the casting character - uint8_t variation; // variation in the animation - Common::ActionEffectDisplayType effectDisplayType; - - uint8_t unknown20; // is read by handler, runs code which gets the LODWORD of animationLockTime (wtf?) - uint8_t effectCount; // ignores effects if 0, otherwise parses all of them - uint16_t padding_21; - - uint16_t padding_22[3]; - - uint8_t effects[8*8]; - - uint16_t padding_6A[3]; - - uint32_t effectTargetId; // who the effect targets - uint32_t effectFlags; // nonzero = effects do nothing, no battle log, no ui text - only shows animations - - uint32_t padding_78; - }; - - template< int size > - struct FFXIVIpcAoeEffect - { - uint64_t animationTargetId; // who the animation targets - - uint32_t actionId; // what the casting player casts, shown in battle log/ui - uint32_t globalSequence; // seems to only increment on retail? - - float animationLockTime; // maybe? doesn't seem to do anything - uint32_t someTargetId; // always 00 00 00 E0, 0x0E000000 is the internal def for INVALID TARGET ID - - uint16_t sourceSequence; // if 0, always shows animation, otherwise hides it. counts up by 1 for each animation skipped on a caster - uint16_t rotation; - uint16_t actionAnimationId; // the animation that is played by the casting character - uint8_t variation; // variation in the animation - Common::ActionEffectDisplayType effectDisplayType; - - uint8_t unknown20; // is read by handler, runs code which gets the LODWORD of animationLockTime (wtf?) - uint8_t effectCount; // ignores effects if 0, otherwise parses all of them - uint16_t padding_21[3]; - uint16_t padding; - - struct - { - Common::EffectEntry entries[8]; - } effects[size]; - - uint16_t padding_6A[3]; - - uint64_t effectTargetId[size]; - uint16_t unkFlag[3]; // all 0x7FFF - uint16_t unk[3]; - }; - - struct FFXIVIpcAoeEffect8 : - FFXIVIpcBasePacket< AoeEffect8 >, FFXIVIpcAoeEffect< 8 > - { - }; - struct FFXIVIpcAoeEffect16 : - FFXIVIpcBasePacket< AoeEffect16 >, FFXIVIpcAoeEffect< 16 > - { - }; - struct FFXIVIpcAoeEffect24 : - FFXIVIpcBasePacket< AoeEffect24 >, FFXIVIpcAoeEffect< 24 > - { - }; - struct FFXIVIpcAoeEffect32 : - FFXIVIpcBasePacket< AoeEffect32 >, FFXIVIpcAoeEffect< 32 > - { - }; +/** +* Structural representation of the packet sent by the server +* to update HP / MP / TP +*/ +struct FFXIVIpcUpdateHpMpTp : FFXIVIpcBasePacket +{ + /* 0000 */ uint32_t hp; + /* 0004 */ uint16_t mp; + /* 0006 */ uint16_t tp; + /* 0008 */ uint32_t unknown_8; + /* 000C */ uint32_t unknown_12; +}; - /** - * Structural representation of the packet sent by the server - * to spawn an actor - */ - struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket< PlayerSpawn > - { - uint16_t title; - uint16_t u1b; - uint16_t currentWorldId; - uint16_t homeWorldId; +/** +* Structural representation of the packet sent by the server +* for battle actions +*/ +struct effectEntry +{ + Common::ActionEffectType effectType; + Common::ActionHitSeverityType hitSeverity; + uint8_t unknown_3; + int8_t bonusPercent; + int16_t value; + uint8_t valueMultiplier; // This multiplies whatever value is in the 'value' param by 10. Possibly a workaround for big numbers + uint8_t unknown_6; +}; - uint8_t gmRank; - uint8_t u3c; - uint8_t u4; - uint8_t onlineStatus; - - uint8_t pose; - uint8_t u5a; - uint8_t u5b; - uint8_t u5c; - - uint64_t targetId; - uint32_t u6; - uint32_t u7; - uint64_t mainWeaponModel; - uint64_t secWeaponModel; - uint64_t craftToolModel; - - uint32_t u14; - uint32_t u15; - uint32_t bNPCBase; - uint32_t bNPCName; - uint32_t u18; - uint32_t u19; - uint32_t directorId; - uint32_t ownerId; - uint32_t u22; - uint32_t hPMax; - uint32_t hPCurr; - uint32_t displayFlags; - uint16_t fateID; - uint16_t mPCurr; - uint16_t mPMax; - uint16_t unk; // == 0 - uint16_t modelChara; - uint16_t rotation; - uint16_t activeMinion; - 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 level; - uint8_t classJob; - uint8_t u26d; - uint16_t u27a; - uint8_t currentMount; - uint8_t mountHead; - uint8_t mountBody; - uint8_t mountFeet; - uint8_t mountColor; - uint8_t scale; - - //uint32_t elementalLevel; one of these two field changed to 16bit - //uint32_t element; - uint8_t elementData[6]; - - Common::StatusEffect effect[30]; - Common::FFXIVARR_POSITION3 pos; - uint32_t models[10]; - char name[32]; - uint8_t look[26]; - char fcTag[6]; - uint32_t unk30; - }; - - /** - * Structural representation of the packet sent by the server - * to spawn an actor - */ - struct FFXIVIpcNpcSpawn : FFXIVIpcBasePacket< NpcSpawn > - { - uint32_t gimmickId; // needs to be existing in the map, mob will snap to it - uint8_t u2b; - uint8_t u2ab; - uint8_t gmRank; - uint8_t u3b; - - uint8_t aggressionMode; // 1 passive, 2 aggressive - uint8_t onlineStatus; - uint8_t u3c; - uint8_t pose; - - uint32_t u4; - - uint64_t targetId; - uint32_t u6; - uint32_t u7; - uint64_t mainWeaponModel; - uint64_t secWeaponModel; - uint64_t craftToolModel; - - uint32_t u14; - uint32_t u15; - uint32_t bNPCBase; - uint32_t bNPCName; - uint32_t levelId; - uint32_t u19; - uint32_t directorId; - uint32_t spawnerId; - uint32_t parentActorId; - uint32_t hPMax; - uint32_t hPCurr; - uint32_t displayFlags; - uint16_t fateID; - uint16_t mPCurr; - uint16_t unknown1; // 0 - uint16_t unknown2; // 0 or pretty big numbers > 30000 - uint16_t modelChara; - uint16_t rotation; - uint16_t activeMinion; - uint8_t spawnIndex; - uint8_t state; - uint8_t persistantEmote; - uint8_t modelType; - uint8_t subtype; - uint8_t voice; - uint16_t u25c; - uint8_t enemyType; - uint8_t level; - uint8_t classJob; - uint8_t u26d; - uint16_t u27a; - uint8_t currentMount; - uint8_t mountHead; - uint8_t mountBody; - uint8_t mountFeet; - uint8_t mountColor; - uint8_t scale; - uint16_t elementalLevel; // Eureka - uint16_t element; // Eureka - Common::StatusEffect effect[30]; - Common::FFXIVARR_POSITION3 pos; - uint32_t models[10]; - char name[32]; - uint8_t look[26]; - char fcTag[6]; - uint32_t unk30; - uint32_t unk31; - uint8_t bNPCPartSlot; - uint8_t unk32; - uint16_t unk33; - uint32_t unk34; - }; - - /** - * Structural representation of the packet sent by the server - * to show player movement - */ - struct FFXIVIpcActorFreeSpawn : FFXIVIpcBasePacket< ActorFreeSpawn > - { - uint32_t spawnId; - uint32_t actorId; - }; - - /** - * Structural representation of the packet sent by the server - * to show player movement - */ - struct FFXIVIpcActorMove : FFXIVIpcBasePacket< ActorMove > - { - /* 0000 */ uint8_t headRotation; - /* 0001 */ uint8_t rotation; - /* 0002 */ uint8_t animationType; - /* 0003 */ uint8_t animationState; - /* 0004 */ uint8_t animationSpeed; - /* 0005 */ uint8_t unknownRotation; - /* 0006 */ uint16_t posX; - /* 0008 */ uint16_t posY; - /* 000a */ uint16_t posZ; - /* 000C */ uint32_t unknown_12; - }; - - /** - * Structural representation of the packet sent by the server - * to set an actors position - */ - struct FFXIVIpcActorSetPos : FFXIVIpcBasePacket< ActorSetPos > - { - uint16_t r16; - uint8_t waitForLoad; - uint8_t unknown1; - uint32_t unknown2; - float x; - float y; - float z; - uint32_t unknown3; - - }; +struct FFXIVIpcEffect : FFXIVIpcBasePacket +{ + uint32_t targetId; + uint32_t unknown_1; + uint32_t actionAnimationId; + uint32_t unknown_2; + uint32_t unknown_5; + uint32_t unknown_6; + uint32_t effectTargetId; + uint16_t rotation; + uint16_t actionTextId; + uint8_t unknown_61; + uint8_t unknown_62; + uint8_t unknown_10; + uint8_t numEffects; + uint32_t u11; + effectEntry effects[8]; + uint32_t effectTarget; + uint64_t unknown_8; +}; - /** - * Structural representation of the packet sent by the server - * to start an actors casting - */ - struct FFXIVIpcActorCast : FFXIVIpcBasePacket< ActorCast > - { - uint16_t action_id; - Common::SkillType skillType; - uint8_t unknown; - uint32_t unknown_1; // action id or mount id - float cast_time; - uint32_t target_id; - uint16_t rotation; - uint16_t flag; // 1 = interruptible blinking cast bar - uint32_t unknown_2; - uint16_t posX; - uint16_t posY; - uint16_t posZ; - uint16_t unknown_3; - }; +/** +* Structural representation of the packet sent by the server +* to spawn an actor +*/ +struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket +{ + uint16_t title; + uint16_t u1b; + uint8_t u2b; + uint8_t u2ab; + uint8_t gmRank; + uint8_t onlineStatus; - struct FFXIVIpcHateList : FFXIVIpcBasePacket< HateList > - { - uint32_t numEntries; - struct - { + uint8_t u3a; + uint8_t u3b; + uint8_t u3c; + uint8_t pose; + + uint32_t u4; + + uint64_t targetId; + uint32_t u6; + uint32_t u7; + uint64_t mainWeaponModel; + uint64_t secWeaponModel; + uint64_t craftToolModel; + + uint32_t u14; + uint32_t u15; + uint32_t bNPCBase; + uint32_t bNPCName; + uint32_t u18; + uint32_t u19; + uint32_t directorId; + uint32_t ownerId; + uint32_t u22; + uint32_t hPMax; + uint32_t hPCurr; + uint32_t displayFlags; + uint16_t fateID; + uint16_t mPCurr; + uint16_t tPCurr; + uint16_t mPMax; + uint16_t tPMax; + uint16_t modelChara; + uint16_t rotation; + uint16_t activeMinion; + uint8_t spawnIndex; + uint8_t state; + uint8_t persistantEmote; + uint8_t type; + uint8_t subtype; + uint8_t voice; + uint16_t u25c; + uint8_t enemyType; + uint8_t level; + uint8_t classJob; + uint8_t u26d; + uint16_t u27a; + uint8_t currentMount; + uint8_t mountHead; + uint8_t mountBody; + uint8_t mountFeet; + uint8_t mountColor; + uint8_t scale; + uint32_t u29b; + Common::StatusEffect effect[30]; + Common::FFXIVARR_POSITION3 pos; + uint32_t models[10]; + char name[32]; + uint8_t look[26]; + char fcTag[6]; + uint32_t unk30; +}; + +/** +* Structural representation of the packet sent by the server +* to spawn an actor +*/ +struct FFXIVIpcNpcSpawn : FFXIVIpcBasePacket +{ + uint16_t title; + uint16_t u1b; + uint16_t u2a; + uint16_t u2b; + + uint8_t pose; + uint8_t u3b; + uint8_t u3c; + uint8_t u3d; + + uint32_t u4; + + uint64_t targetId; + uint32_t u6; + uint32_t u7; + + uint64_t mainWeaponModel; + uint64_t secWeaponModel; + uint64_t craftToolModel; + + uint32_t u14; + uint32_t u15; + uint32_t bNPCBase; + uint32_t bNPCName; + uint32_t u18; + uint32_t u19; + uint32_t u20; + uint32_t u21; + uint32_t u22; + + uint32_t hPCurr; + uint32_t hPMax; + uint32_t displayFlags; + uint16_t fateID; + uint16_t mPCurr; + uint16_t tPCurr; + uint16_t mPMax; + + uint16_t unk21a; + uint16_t modelChara; + uint16_t rotation; + uint16_t unk22b; + uint8_t spawnIndex; + uint8_t state; // ActorState + uint8_t u24a; + uint8_t type; // 1 for player, 2 for NPC, else furniture; + uint8_t subtype; // 4 for players, 2 for pet, 3 for companion, 5 for mob, 7 for minion + uint8_t u25b; + uint16_t u25c; + + uint8_t enemyType; // 0 for friendly, anything else is an enemy + uint8_t level; + uint8_t classJob; + uint8_t u26d; + + uint16_t u27a; + + uint8_t currentMount; + uint8_t mountHead; + uint8_t mountBody; + uint8_t mountFeet; + uint16_t mountColor; + + uint32_t u29b; + Common::StatusEffect effect[30]; + Common::FFXIVARR_POSITION3 pos; + uint32_t models[10]; + char name[32]; + uint8_t look[26]; + char fcTag[6]; + uint32_t unk30; +}; + +/** +* Structural representation of the packet sent by the server +* to show player movement +*/ +struct FFXIVIpcActorFreeSpawn : FFXIVIpcBasePacket +{ + uint32_t spawnId; + uint32_t actorId; +}; + +/** +* Structural representation of the packet sent by the server +* to show player movement +*/ +struct FFXIVIpcActorMove : FFXIVIpcBasePacket +{ + /* 0000 */ uint8_t rotation; + /* 0001 */ uint8_t unknown_1; + /* 0002 */ uint8_t unknown_2; + /* 0003 */ uint8_t unknown_3; + /* 0004 */ uint16_t unknown_4; + /* 0006 */ uint16_t posX; + /* 0008 */ uint16_t posY; + /* 000a */ uint16_t posZ; + /* 000C */ uint32_t unknown_12; +}; + +/** +* Structural representation of the packet sent by the server +* to set an actors position +*/ +struct FFXIVIpcActorSetPos : FFXIVIpcBasePacket +{ + uint16_t r16; + uint8_t waitForLoad; + uint8_t unknown1; + uint32_t unknown2; + float x; + float y; + float z; + uint32_t unknown3; + +}; + + + +/** +* Structural representation of the packet sent by the server +* to start an actors casting +*/ +struct FFXIVIpcActorCast : FFXIVIpcBasePacket +{ + uint16_t action_id; + Common::SkillType skillType; + uint8_t unknown; + uint32_t unknown_1; // Also action id + float cast_time; + uint32_t target_id; + float rotation; // In radians + uint32_t unknown_2; + uint16_t posX; + uint16_t posY; + uint16_t posZ; + uint16_t unknown_3; +}; + +struct FFXIVIpcHateList : FFXIVIpcBasePacket +{ + uint32_t numEntries; + struct LsEntry + { uint32_t actorId; uint8_t hatePercent; uint8_t unknown; uint16_t padding; - } entry[32]; - uint32_t padding; - }; + } entry[32]; + uint32_t padding; +}; - struct FFXIVIpcHateRank : FFXIVIpcBasePacket< HateRank > - { - uint32_t numEntries; - struct - { - uint32_t actorId; - uint32_t hateAmount; - } entry[32]; - uint32_t padding; - }; +struct FFXIVIpcUpdateClassInfo : FFXIVIpcBasePacket +{ + uint8_t classId; + uint8_t classId1; + uint16_t level; + uint32_t nextLevelIndex; + uint32_t currentExp; + uint32_t restedExp; +}; - struct FFXIVIpcUpdateClassInfo : FFXIVIpcBasePacket< UpdateClassInfo > - { - uint8_t classId; - uint8_t level1; - uint16_t level; - uint32_t nextLevelIndex; - uint32_t currentExp; - uint32_t restedExp; - }; +/** + * Structural representation of the packet sent by the server + * to send the titles available to the player + */ +struct FFXIVIpcPlayerTitleList : FFXIVIpcBasePacket +{ + uint8_t titleList[48]; +}; - /** - * Structural representation of the packet sent by the server - * to send the titles available to the player - */ - struct FFXIVIpcPlayerTitleList : FFXIVIpcBasePacket< PlayerTitleList > - { - uint8_t titleList[48]; - }; - - /** - * Structural representation of the packet sent by the server - * to initialize a zone for the player - */ - struct FFXIVIpcInitZone : FFXIVIpcBasePacket< InitZone > - { - uint16_t serverId; - uint16_t zoneId; - uint16_t unknown1; - uint16_t contentfinderConditionId; - uint32_t unknown3; - uint32_t unknown4; - uint8_t weatherId; - uint8_t bitmask; - uint8_t bitmask1; - // bitmask1 findings - //0 = unknown ( 7B F8 69 ) - //1 = show playguide window ( 7B 69 ) - //2 = unknown ( 7B 69 ) - //4 = disables record ready check ( 7B DF DF F8 F0 E4 110 (all sorts of social packets) ) - //8 = hide server icon ( 7B 69 ) - //16 = enable flight ( 7B F8 69 ) - //32 = unknown ( 7B F8 69 ) - //64 = unknown ( 7B F8 69 ) - //128 = shows message "You are now in the instanced area XX A. - //Current instance can be confirmed at any time using the /instance text command." ( 7B F8 69 ) - - uint8_t unknown5; - uint32_t unknown8; - uint16_t festivalId; - uint16_t additionalFestivalId; - uint32_t unknown9; - uint32_t unknown10; - uint32_t unknown11; - uint32_t unknown12[4]; - uint32_t unknown13[3]; - Common::FFXIVARR_POSITION3 pos; - uint32_t unknown14[3]; - uint32_t unknown15; - }; +/** +* Structural representation of the packet sent by the server +* to initialize a zone for the player +*/ +struct FFXIVIpcInitZone : FFXIVIpcBasePacket +{ + uint16_t serverId; + uint16_t zoneId; + uint16_t unknown1; + uint16_t unknown2; + uint32_t unknown3; + uint32_t unknown4; + uint8_t weatherId; + uint8_t bitmask; + uint16_t unknown5; + uint16_t unknown6; + uint16_t unknown7; + uint32_t unknown8; + Common::FFXIVARR_POSITION3 pos; +}; - /** - * Structural representation of the packet sent by the server to initialize - * the client UI upon initial connection. - */ - 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; - unsigned int unknown8; - unsigned int unknownC; - unsigned int charId; - unsigned int restedExp; - unsigned int companionCurrentExp; - unsigned int unknown1C; - unsigned int fishCaught; - unsigned int useBaitCatalogId; - unsigned int unknown28; - unsigned short unknownPvp2C; - unsigned short unknown3; - unsigned int pvpFrontlineOverallCampaigns; - unsigned int unknownTimestamp34; - unsigned int unknownTimestamp38; - unsigned int unknown3C; - unsigned int unknown40; - unsigned int unknown44; - float companionTimePassed; - unsigned int unknown4C; - unsigned short unknown50; - unsigned short unknownPvp52[4]; - unsigned short playerCommendations; - unsigned short unknown5C; - unsigned short unknown5E; - unsigned short pvpFrontlineWeeklyCampaigns; - unsigned short enhancedAnimaGlassProgress; - unsigned short unknown64[4]; - unsigned short pvpRivalWingsTotalMatches; - unsigned short pvpRivalWingsTotalVictories; - unsigned short pvpRivalWingsWeeklyMatches; - unsigned short pvpRivalWingsWeeklyVictories; - unsigned char maxLevel; - unsigned char expansion; - unsigned char unknown76; - unsigned char unknown77; - unsigned char very_unknown; - unsigned char race; - unsigned char tribe; - unsigned char gender; - unsigned char currentJob; - unsigned char currentClass; - unsigned char deity; - unsigned char namedayMonth; - unsigned char namedayDay; - unsigned char cityState; - unsigned char homepoint; - unsigned char unknown82; - unsigned char petHotBar; - unsigned char companionRank; - unsigned char companionStars; - unsigned char companionSp; - unsigned char companionUnk86; - unsigned char companionColor; - unsigned char companionFavoFeed; - unsigned char unknown89; - unsigned char unknown8A[4]; - unsigned char hasRelicBook; - unsigned char relicBookId; - unsigned char unknown90[4]; - unsigned char craftingMasterMask; - unsigned char unknown95[9]; - unsigned char unknown9F[2]; - unsigned char unknownA1[6]; - unsigned int exp[Common::CLASSJOB_SLOTS]; - unsigned int unknown108; - unsigned int pvpTotalExp; - unsigned int unknownPvp110; - unsigned int pvpExp; - unsigned int pvpFrontlineOverallRanks[3]; - unsigned short levels[Common::CLASSJOB_SLOTS]; - /* - unsigned short unknown15C[9]; - unsigned short u1; - unsigned short u2; - unsigned short unknown112[23]; - unsigned short fishingRecordsFish[26]; - unsigned short beastExp[11]; - unsigned short unknown1EA[5]; - unsigned short pvpFrontlineWeeklyRanks[3]; - unsigned short unknownMask1FA[4]; - unsigned char companionName[21]; - unsigned char companionDefRank; - unsigned char companionAttRank; - unsigned char companionHealRank; - unsigned char u19[8]; - unsigned char mountGuideMask[22]; - unsigned char u19_2; - */ - unsigned char unknown5_3a[176]; - unsigned char companionName[21]; - unsigned char companionDefRank; - unsigned char companionAttRank; - unsigned char companionHealRank; - unsigned char mountGuideMask[23]; - unsigned char maybeReservedMountSlots; - //== - char name[32]; - unsigned char unknownOword[16]; - unsigned char unknownOw; - unsigned char unlockBitmask[64]; - unsigned char aetheryte[21]; - unsigned char discovery[445]; - unsigned char howto[34]; - unsigned char minions[51]; - unsigned char chocoboTaxiMask[10]; - unsigned char watchedCutscenes[131]; - unsigned char companionBardingMask[10]; - unsigned char companionEquippedHead; - unsigned char companionEquippedBody; - unsigned char companionEquippedLegs; - /* - unsigned char unknown52A[4]; - unsigned char unknownMask52E[11]; - unsigned char fishingGuideMask[105]; - unsigned char fishingSpotVisited[31]; - unsigned char unknown59A[27]; - unsigned char unknown5A9[7]; - unsigned char beastRank[11]; - unsigned char unknownPvp5AB[11]; - unsigned char unknown5B9[5]; - */ - unsigned char unknown5_3c[234]; - //== - unsigned char pose; - /* - unsigned char unknown5B91; - unsigned char challengeLogComplete[9]; - unsigned char weaponPose; - unsigned char unknownMask673[10]; - unsigned char unknownMask5DD[28]; - unsigned char relicCompletion[12]; - unsigned char sightseeingMask[26]; - unsigned char huntingMarkMask[55]; - unsigned char tripleTriadCards[32]; - unsigned char u12[11]; - unsigned char u13; - unsigned char aetherCurrentMask[22]; - unsigned char u10[3]; - */ - unsigned char unknown5_3d[292]; - //== - unsigned char orchestrionMask[40]; - unsigned char hallOfNoviceCompletion[3]; - unsigned char animaCompletion[11]; - unsigned char unknown5_3e[33]; - unsigned char unlockedRaids[28]; - unsigned char unlockedDungeons[18]; - unsigned char unlockedGuildhests[10]; - unsigned char unlockedTrials[9]; // 5.35 trial:pvp either 9:5 or 8:6 not confirmed - unsigned char unlockedPvp[5]; - unsigned char clearedRaids[28]; - unsigned char clearedDungeons[18]; - unsigned char clearedGuildhests[10]; - unsigned char clearedTrials[9]; - unsigned char clearedPvp[5]; - /* - unsigned short fishingRecordsFishWeight[26]; - unsigned int exploratoryMissionNextTimestamp; - unsigned char pvpLevel; - */ - unsigned char padding2[8]; - //== - }; +/** +* Structural representation of the packet sent by the server to initialize +* the client UI upon initial connection. +*/ +struct FFXIVIpcInitUI : FFXIVIpcBasePacket +{ + uint64_t contentId; + uint32_t unknown8; + uint32_t unknownC; + uint32_t charId; + uint32_t restedExp; + uint16_t unknown18; + uint8_t maxLevel; + uint8_t expansion; + 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 unknown26; + uint8_t petHotBar; + uint8_t companionRank; + uint8_t companionStars; + uint8_t companionSp; + uint8_t companionUnk1; + uint8_t companionColor; + uint8_t companionFavoFeed; + uint16_t companionUnk2; + float companionTimePassed; + uint32_t companionCurrentExp; + uint32_t unknown38; + uint32_t unknown3C; + uint32_t fishCaught; + uint32_t useBaitCatalogId; + uint16_t pvpWolfFoldMatches; + uint16_t pvpWolfFoldVictories; + uint16_t pvpWolfFoldWeeklyMatches; + uint16_t pvpWolfFoldWeeklyVictories; + uint16_t pvpStats[6]; + uint16_t playerCommendations; + uint16_t pvpStats1; + uint32_t frontlineCampaigns; + uint16_t frontlineCampaignsWeekly; + uint8_t currentRelic; + uint8_t currentBook; + uint8_t masterCrafterMask; + uint8_t unknown69; + uint8_t unknown6A; + uint8_t unknown6B; + uint32_t unknown6C; + uint8_t unknown70[61]; + uint8_t preNamePadding; + char name[32]; + uint8_t unknownOword[16]; + uint8_t unknownDE[2]; + uint16_t levels[25]; + uint16_t levelsPadding; + uint32_t exp[25]; + uint8_t unlockBitmask[64]; + uint8_t aetheryte[16]; + uint8_t discovery[420]; + uint8_t howto[33]; + uint8_t minions[35]; + uint8_t chocoboTaxiMask[8]; + uint8_t contentClearMask[105]; + uint8_t contentClearPadding; + uint16_t unknown422[8]; + uint8_t companionBardingMask[8]; + uint8_t companionEquippedHead; + uint8_t companionEquippedBody; + uint8_t companionEquippedFeet; + uint8_t companion_fields[15]; + uint8_t companion_name[21]; + uint8_t companionDefRank; + uint8_t companionAttRank; + uint8_t companionHealRank; + uint8_t mountGuideMask[14]; + uint8_t fishingGuideMask[89]; + uint8_t fishingSpotVisited[25]; + uint16_t fishingRecordsFish[26]; + uint16_t fishingRecordsFishWeight[26]; + uint8_t unknownMask4[15]; + uint8_t unknownMask4Padding; + uint8_t unknown55C[19]; + uint8_t rankAmalJaa; + uint8_t rankSylph; + uint8_t rankKobold; + uint8_t rankSahagin; + uint8_t rankIxal; + uint8_t rankVanu; + uint8_t rankVath; + uint8_t rankMoogle; + uint8_t rankKojin; + uint16_t expAmalJaa; + uint16_t expSylph; + uint16_t expKobold; + uint16_t expSahagin; + uint16_t expIxal; + uint16_t expVanu; + uint16_t expVath; + uint16_t expMoogle; + uint16_t expKojin; + uint8_t unknown58A[10]; + uint16_t unknown594[5]; + uint8_t unknownMask59E[5]; + uint8_t unknown5A3[16]; + uint8_t unknownMask5B3[28]; + uint8_t unknown_03411; + uint32_t unknownDword5D0; + uint8_t relicBookCompletion[12]; + uint8_t sightseeingMask[26]; + uint16_t unknown_XXX; + uint32_t pvpFrontlineOverall1st; + uint32_t pvpFrontlineOverall2nd; + uint32_t pvpFrontlineOverall3rd; + uint16_t pvpFrontlineWeekly1st; + uint16_t pvpFrontlineWeekly2nd; + uint16_t pvpFrontlineWeekly3rd; + uint8_t unknown60E; + uint8_t unknown60F[32]; + uint8_t unknown62F[22]; + uint8_t tripleTriadCards[27]; + uint8_t unknown660[11]; + uint8_t unknownMask66B[22]; + uint8_t unknown681[3]; + uint8_t orchestrionMask[40]; + uint8_t hallOfNoviceCompleteMask[3]; + uint8_t unknownMask6AF[11]; + uint8_t unknownMask6BA[16]; + uint8_t unknown6CA[13]; + uint8_t unlockedRaids[28]; + uint8_t unlockedDungeons[18]; + uint8_t unlockedGuildhests[10]; + uint8_t unlockedTrails[7]; + uint8_t unlockedPvp[5]; + uint8_t unknownMask71B[28]; + uint8_t unknownMask737[18]; + uint8_t unknown749[23]; +}; + +/** +* Structural representation of the packet sent by the server +* to set a players stats +*/ +struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket +{ + uint32_t strength; + uint32_t dexterity; + uint32_t vitality; + uint32_t intelligence; + uint32_t mind; + uint32_t piety; + uint32_t hp; + uint32_t mp; + uint32_t tp; + uint32_t unknown; + uint32_t unknown_1; + uint32_t unknown_2; + uint32_t tenacity; + uint32_t attack; + uint32_t defense; + uint32_t accuracy; + uint32_t spellSpeed; + uint32_t magicDefense; + uint32_t criticalHitRate; + uint32_t resistanceSlashing; + uint32_t resistancePiercing; + uint32_t resistanceBlunt; + uint32_t attackMagicPotency; + uint32_t healingMagicPotency; + uint32_t fire; + uint32_t ice; + uint32_t wind; + uint32_t earth; + uint32_t lightning; + uint32_t water; + uint32_t determination; + uint32_t skillSpeed; + uint32_t spellSpeed1; + uint32_t spellSpeedMod; + uint32_t unknown_6; + uint32_t craftsmanship; + uint32_t control; + uint32_t gathering; + uint32_t perception; + uint32_t resistanceSlow; + uint32_t resistanceSilence; + uint32_t resistanceBlind; + uint32_t resistancePoison; + uint32_t resistanceStun; + uint32_t resistanceSleep; + uint32_t resistanceBind; + uint32_t resistanceHeavy; + uint32_t unknown_7[9]; // possibly level sync stats. +}; + +/** +* Structural representation of the packet sent by the server +* to set an actors current owner +*/ +struct FFXIVIpcActorOwner : FFXIVIpcBasePacket +{ + uint8_t type; + uint8_t padding[7]; + uint32_t actorId; + uint32_t actorId2; +}; + +/** +* Structural representation of the packet sent by the server +* to set a players state +*/ +struct FFXIVIpcPlayerStateFlags : FFXIVIpcBasePacket +{ + /* 0000 */ uint16_t padding; + /* 0002 */ uint8_t flags[7]; + /* 0009 */ uint8_t padding1[3]; + /* 000C */ uint32_t padding2; + +}; + +/** +* Structural representation of the packet sent by the server +* containing current class information +*/ +struct FFXIVIpcPlayerClassInfo : FFXIVIpcBasePacket +{ + uint16_t classId; + uint8_t unknown; + uint8_t isSpecialist; + uint16_t level; // Locks actions, equipment, prob more + uint16_t level1; // Locks roles, prob more + uint32_t roleActions[10]; +}; + +/** +* Structural representation of the packet sent by the server +* to update a players appearance +*/ +struct FFXIVIpcModelEquip : FFXIVIpcBasePacket +{ + /* 0000 */ uint64_t mainWeapon; + /* 0008 */ uint64_t offWeapon; + /* 0010 */ uint32_t padding1; + /* 0014 */ uint32_t models[10]; + /* 003C */ uint32_t padding2; +}; + +/** +* Structural representation of the packet sent by the server +* to update a players appearance +*/ +struct FFXIVIpcItemInfo : FFXIVIpcBasePacket +{ + uint32_t sequence; + uint32_t unknown; + uint16_t containerId; + uint16_t slot; + uint32_t quantity; + uint32_t catalogId; + uint32_t reservedFlag; + uint64_t signatureId; + uint8_t hqFlag; + uint8_t unknown2; + uint16_t condition; + uint16_t spiritBond; + uint16_t color; + uint32_t glamourCatalogId; + uint16_t materia1; + uint16_t materia2; + uint16_t materia3; + uint16_t materia4; + uint16_t materia5; + uint8_t buffer1; + uint8_t buffer2; + uint8_t buffer3; + uint8_t buffer4; + uint8_t buffer5; + uint8_t padding; + uint32_t unknown10; +}; + +/** +* Structural representation of the packet sent by the server +* to update a players appearance +*/ +struct FFXIVIpcContainerInfo : FFXIVIpcBasePacket +{ + uint32_t sequence; + uint32_t numItems; + uint32_t containerId; + uint32_t unknown; +}; + +/** +* Structural representation of the packet sent by the server +* to update a players appearance +*/ +struct FFXIVIpcCurrencyCrystalInfo : FFXIVIpcBasePacket +{ + uint32_t sequence; + uint16_t containerId; + uint16_t slot; + uint32_t quantity; + uint32_t unknown; + uint32_t catalogId; + uint32_t unknown1; + uint32_t unknown2; + uint32_t unknown3; +}; + +struct FFXIVIpcInventoryTransactionFinish : FFXIVIpcBasePacket +{ + uint32_t transactionId; + uint32_t transactionId1; + uint64_t padding; +}; + +struct FFXIVIpcInventoryTransaction : FFXIVIpcBasePacket +{ + uint32_t transactionId; + uint8_t type; + uint8_t padding; + uint16_t padding1; + uint32_t ownerId; + uint32_t storageId; + uint16_t slotId; + uint16_t padding2; + uint32_t stackSize; + uint32_t catalogId; + uint32_t someActorId; + int32_t targetStorageId; + uint32_t padding3[3]; +}; - /** - * Structural representation of the packet sent by the server - * to set a players stats - */ - struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket< PlayerStats > - { - // order comes from baseparam order column - uint32_t strength; - uint32_t dexterity; - uint32_t vitality; - uint32_t intelligence; - uint32_t mind; - uint32_t piety; - uint32_t hp; - uint32_t mp; - uint32_t tp; - uint32_t gp; - uint32_t cp; - uint32_t delay; - uint32_t tenacity; - uint32_t attackPower; - uint32_t defense; - uint32_t directHitRate; - uint32_t evasion; - uint32_t magicDefense; - uint32_t criticalHit; - uint32_t attackMagicPotency; - uint32_t healingMagicPotency; - uint32_t elementalBonus; - uint32_t determination; - uint32_t skillSpeed; - uint32_t spellSpeed; - uint32_t haste; - uint32_t craftsmanship; - uint32_t control; - uint32_t gathering; - uint32_t perception; - - // todo: what is here? - uint32_t unknown[26]; - }; - - /** - * Structural representation of the packet sent by the server - * to set an actors current owner - */ - struct FFXIVIpcActorOwner : FFXIVIpcBasePacket< ActorOwner > - { - uint8_t type; - uint8_t padding[7]; - uint32_t actorId; - uint32_t actorId2; - }; - - /** - * Structural representation of the packet sent by the server - * to set a players state - */ - struct FFXIVIpcPlayerStateFlags : FFXIVIpcBasePacket< PlayerStateFlags > - { - uint8_t flags[12]; - uint32_t padding; - }; - - /** - * Structural representation of the packet sent by the server - * containing current class information - */ - struct FFXIVIpcPlayerClassInfo : FFXIVIpcBasePacket< PlayerClassInfo > - { - uint16_t classId; - uint8_t unknown; - 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]; - }; - - /** - * Structural representation of the packet sent by the server - * to update a players appearance - */ - struct FFXIVIpcModelEquip : FFXIVIpcBasePacket< ModelEquip > - { - /* 0000 */ uint64_t mainWeapon; - /* 0008 */ uint64_t offWeapon; - /* 0010 */ uint8_t unk1; - /* 0011 */ uint8_t classJobId; - /* 0012 */ uint8_t level; - /* 0013 */ uint8_t unk2; - /* 0014 */ uint32_t models[10]; - /* 003C */ uint32_t padding2; - }; - - struct FFXIVIpcExamine : FFXIVIpcBasePacket< Examine > - { - uint8_t unkFlag1; - uint8_t unkFlag2; - char classJob; - char level; - uint16_t padding; - uint16_t titleId; - char grandCompany; - char grandCompanyRank; - - char unknown[6]; - uint32_t u6_fromPSpawn; - uint32_t u7_fromPSpawn; - char padding1[8]; - uint64_t mainWeaponModel; - uint64_t secWeaponModel; - uint8_t unknown2; - uint16_t worldId; - char unknown3[12]; - struct ItemData - { - uint32_t catalogId; - uint32_t appearanceCatalogId; - uint64_t crafterId; - uint8_t quality; - uint8_t stain; - uint8_t unknown[2]; - struct Materia - { - uint16_t materiaId; - uint16_t tier; - } materia[5]; - } entries[14]; - char name[32]; - char padding2; - char unk3[16]; - char look[26]; - char padding3[5]; - uint32_t models[10]; - char unknown4[200]; - }; - - struct FFXIVIpcCharaNameReq : FFXIVIpcBasePacket< CharaNameReq > - { - uint64_t contentId; - char name[32]; - }; - - /** - * Structural representation of the packet sent by the server - * to update a players appearance - */ - struct FFXIVIpcItemInfo : FFXIVIpcBasePacket< ItemInfo > - { - uint32_t containerSequence; - uint32_t unknown; - uint16_t containerId; - uint16_t slot; - uint32_t quantity; - uint32_t catalogId; - uint32_t reservedFlag; - uint64_t signatureId; - uint8_t hqFlag; - uint8_t unknown2; - uint16_t condition; - uint16_t spiritBond; - uint16_t stain; - uint32_t glamourCatalogId; - uint16_t materia1; - uint16_t materia2; - uint16_t materia3; - uint16_t materia4; - uint16_t materia5; - uint8_t buffer1; - uint8_t buffer2; - uint8_t buffer3; - uint8_t buffer4; - uint8_t buffer5; - uint8_t padding; - uint32_t unknown10; - }; - - /** - * Structural representation of the packet sent by the server - * to update a players appearance - */ - struct FFXIVIpcContainerInfo : FFXIVIpcBasePacket< ContainerInfo > - { - uint32_t containerSequence; - uint32_t numItems; - uint32_t containerId; - uint32_t unknown; - }; - - /** - * Structural representation of the packet sent by the server - * to update a players appearance - */ - struct FFXIVIpcCurrencyCrystalInfo : FFXIVIpcBasePacket< CurrencyCrystalInfo > - { - uint32_t containerSequence; - uint16_t containerId; - uint16_t slot; - uint32_t quantity; - uint32_t unknown; - uint32_t catalogId; - uint32_t unknown1; - uint32_t unknown2; - uint32_t unknown3; - }; - - struct FFXIVIpcInventoryTransactionFinish : FFXIVIpcBasePacket< InventoryTransactionFinish > - { - uint32_t sequenceId; - uint32_t sequenceId1; - uint64_t padding; - }; - - struct FFXIVIpcInventoryTransaction : FFXIVIpcBasePacket< InventoryTransaction > - { - uint32_t sequence; - uint16_t type; - uint16_t padding1; - uint32_t ownerId; - uint32_t storageId; - uint16_t slotId; - uint16_t padding2; - uint32_t stackSize; - uint32_t catalogId; - uint32_t someActorId; - int32_t targetStorageId; - uint32_t padding3[3]; - }; +struct FFXIVIpcInventoryActionAck : FFXIVIpcBasePacket +{ + uint32_t sequence; + uint16_t type; + uint16_t padding; + uint32_t padding1; + uint32_t padding2; +}; - struct FFXIVIpcInventoryActionAck : FFXIVIpcBasePacket< InventoryActionAck > - { - uint32_t sequence; - uint16_t type; - uint16_t padding; - uint32_t padding1; - uint32_t padding2; - }; +/** +* Structural representation of the packet sent by the server +* to update a slot in the inventory +*/ +struct FFXIVIpcUpdateInventorySlot : FFXIVIpcBasePacket +{ + uint32_t sequence; + uint32_t unknown; + uint16_t containerId; + uint16_t slot; + uint32_t quantity; + uint32_t catalogId; + uint32_t reservedFlag; + uint64_t signatureId; + uint16_t hqFlag; + uint16_t condition; + uint16_t spiritBond; + uint16_t color; + uint32_t glamourCatalogId; + uint16_t materia1; + uint16_t materia2; + uint16_t materia3; + uint16_t materia4; + uint16_t materia5; + uint8_t buffer1; + uint8_t buffer2; + uint8_t buffer3; + uint8_t buffer4; + uint8_t buffer5; + uint8_t padding; + uint32_t unknown10; +}; + +/** +* Structural representation of the packet sent by the server +* to start an event, not actually playing it, but registering +*/ +struct FFXIVIpcEventStart : FFXIVIpcBasePacket +{ + /* 0000 */ uint64_t actorId; + /* 0008 */ uint32_t eventId; + /* 000C */ uint8_t param1; + /* 000D */ uint8_t param2; + /* 000E */ uint16_t padding; + /* 0010 */ uint32_t param3; + /* 0014 */ uint32_t padding1; +}; - /** - * Structural representation of the packet sent by the server - * to update a slot in the inventory - */ - struct FFXIVIpcUpdateInventorySlot : FFXIVIpcBasePacket< UpdateInventorySlot > - { - uint32_t sequence; - uint32_t unknown; - uint16_t containerId; - uint16_t slot; - uint32_t quantity; - uint32_t catalogId; - uint32_t reservedFlag; - uint64_t signatureId; - uint16_t hqFlag; - uint16_t condition; - uint16_t spiritBond; - uint16_t color; - uint32_t glamourCatalogId; - uint16_t materia1; - uint16_t materia2; - uint16_t materia3; - uint16_t materia4; - uint16_t materia5; - uint8_t buffer1; - uint8_t buffer2; - uint8_t buffer3; - uint8_t buffer4; - uint8_t buffer5; - uint8_t padding; - uint32_t unknown10; - }; +/** +* Structural representation of the packet sent by the server +* to play an event +*/ +struct FFXIVIpcEventPlay : FFXIVIpcBasePacket +{ + uint64_t actorId; + uint32_t eventId; + uint16_t scene; + uint16_t padding; + uint32_t flags; + uint32_t param3; + uint8_t param4; + uint8_t padding1[3]; + uint32_t param5; + uint8_t unknown[8]; +}; - /** - * Structural representation of the packet sent by the server - * to start an event, not actually playing it, but registering - */ - struct FFXIVIpcEventStart : FFXIVIpcBasePacket< EventStart > - { - /* 0000 */ uint64_t actorId; - /* 0008 */ uint32_t eventId; - /* 000C */ uint8_t param1; - /* 000D */ uint8_t param2; - /* 000E */ uint16_t padding; - /* 0010 */ uint32_t param3; - /* 0014 */ uint32_t padding1; - }; - - /** - * Structural representation of the packet sent by the server - * to fill a huntin log entry - */ - struct FFXIVIpcHuntingLogEntry : FFXIVIpcBasePacket< HuntingLogEntry > - { - int32_t u0; // -1 for all normal classes - uint8_t rank; // starting from 0 - uint8_t index; // classes and gcs - uint8_t entries[10][4]; - uint16_t pad; - uint64_t completeFlags; // 4 bit for each potential entry and the 5th bit for completion of the section - uint64_t pad1; - }; - - /** - * Structural representation of the packet sent by the server - * to play an event - */ - struct FFXIVIpcEventPlay : FFXIVIpcBasePacket< EventPlay > - { - uint64_t actorId; - uint32_t eventId; - uint16_t scene; - uint16_t padding; - uint32_t flags; - uint32_t param3; - uint8_t param4; - uint8_t padding1[3]; - uint32_t param5; - uint8_t unknown[8]; - }; - - template< int ArgCount > - struct FFXIVIpcEventPlayN - { - uint64_t actorId; - uint32_t eventId; - uint16_t scene; - uint16_t padding; - uint32_t sceneFlags; - uint32_t unknown; - uint8_t paramSize; - uint8_t padding2[3]; - uint32_t params[ArgCount]; - }; - - /** - * Structural representation of the packet sent by the server - * to play an event - */ - struct FFXIVIpcDirectorPlayScene : FFXIVIpcBasePacket< EventPlay32 > - { - uint64_t actorId; - uint32_t eventId; - uint16_t scene; - uint16_t padding; - uint32_t flags; - uint32_t param3; - uint8_t param4; - uint8_t padding1[3]; - uint32_t param5; - uint8_t unknown8[0x08]; - uint8_t unknown[0x38]; - }; - - /** - * Structural representation of the packet sent by the server - * to finish an event - */ - struct FFXIVIpcEventFinish : FFXIVIpcBasePacket< EventFinish > - { - /* 0000 */ uint32_t eventId; - /* 0004 */ uint8_t param1; - /* 0005 */ uint8_t param2; - /* 0006 */ uint16_t padding; - /* 0008 */ uint32_t param3; - /* 000C */ uint32_t padding1; - }; - - struct FFXIVIpcEventPlay255 : - FFXIVIpcBasePacket< EventPlay255 >, - FFXIVIpcEventPlayN< 255 > - { - }; +/** +* Structural representation of the packet sent by the server +* to finish an event +*/ +struct FFXIVIpcEventFinish : FFXIVIpcBasePacket +{ + /* 0000 */ uint32_t eventId; + /* 0004 */ uint8_t param1; + /* 0005 */ uint8_t param2; + /* 0006 */ uint16_t padding; + /* 0008 */ uint32_t param3; + /* 000C */ uint32_t padding1; +}; - /** - * Structural representation of the packet sent by the server - * to respond to a linkshell creation event - */ - struct FFXIVIpcEventLinkshell : FFXIVIpcBasePacket< EventLinkshell > - { - uint32_t eventId; - uint8_t scene; - uint8_t param1; - uint8_t param2; - uint8_t param3; - uint32_t unknown1; - uint32_t unknown2; - uint32_t unknown3; - uint32_t unknown4; - }; +/** +* Structural representation of the packet sent by the server +* to respond to a linkshell creation event +*/ +struct FFXIVIpcEventLinkshell : FFXIVIpcBasePacket +{ + uint32_t eventId; + uint8_t scene; + uint8_t param1; + uint8_t param2; + uint8_t param3; + uint32_t unknown1; + uint32_t unknown2; + uint32_t unknown3; + uint32_t unknown4; +}; - /** - * Structural representation of the packet sent by the server - * to send the active quests - */ - struct FFXIVIpcQuestActiveList : FFXIVIpcBasePacket< QuestActiveList > - { - Common::QuestActive activeQuests[30]; - }; +/** +* Structural representation of the packet sent by the server +* to send the active quests +*/ +struct FFXIVIpcQuestActiveList : FFXIVIpcBasePacket +{ + Common::QuestActive activeQuests[30]; +}; - /** - * Structural representation of the packet sent by the server - * to send update a quest slot - */ - struct FFXIVIpcQuestUpdate : FFXIVIpcBasePacket< QuestUpdate > - { - uint16_t slot; - uint16_t padding; - Common::QuestActive questInfo; - }; +/** +* Structural representation of the packet sent by the server +* to send update a quest slot +*/ +struct FFXIVIpcQuestUpdate : FFXIVIpcBasePacket +{ + uint16_t slot; + uint16_t padding; + Common::QuestActive questInfo; +}; - /** - * Structural representation of the packet sent by the server - * to send the completed quests mask - */ - struct FFXIVIpcQuestCompleteList : FFXIVIpcBasePacket< QuestCompleteList > - { - uint8_t questCompleteMask[487]; - uint8_t unknownCompleteMask[73]; - }; +/** +* Structural representation of the packet sent by the server +* to send the completed quests mask +*/ +struct FFXIVIpcQuestCompleteList : FFXIVIpcBasePacket +{ + /* 0000 */ uint8_t questCompleteMask[200]; +}; - /** - * Structural representation of the packet sent by the server - * to finish a quest - */ - struct FFXIVIpcQuestFinish : FFXIVIpcBasePacket< QuestFinish > - { - uint16_t questId; - uint8_t flag1; - uint8_t flag2; - uint32_t padding; - }; +/** +* Structural representation of the packet sent by the server +* to finish a quest +*/ +struct FFXIVIpcQuestFinish : FFXIVIpcBasePacket +{ + uint16_t questId; + uint8_t flag1; + uint8_t flag2; + uint32_t padding; +}; - /** - * Structural representation of the packet sent by the server - * to send a quest message - * type 0 default - * type 1 icon - * type 5 status - */ - struct FFXIVIpcQuestMessage : FFXIVIpcBasePacket< QuestMessage > - { - /* 0000 */ uint32_t questId; - /* 0000 */ uint8_t msgId; - /* 0000 */ uint8_t type; - /* 0000 */ uint16_t padding1; - /* 0000 */ uint32_t var1; - /* 0000 */ uint32_t var2; - }; +/** +* Structural representation of the packet sent by the server +* to send a quest message +* type 0 default +* type 1 icon +* type 5 status +*/ +struct FFXIVIpcQuestMessage : FFXIVIpcBasePacket +{ + /* 0000 */ uint32_t questId; + /* 0000 */ uint8_t msgId; + /* 0000 */ uint8_t type; + /* 0000 */ uint16_t padding1; + /* 0000 */ uint32_t var1; + /* 0000 */ uint32_t var2; +}; - struct FFXIVIpcQuestTracker : FFXIVIpcBasePacket< QuestTracker > - { - struct TrackerEntry - { +struct FFXIVIpcQuestTracker : FFXIVIpcBasePacket +{ + struct TrackerEntry + { uint8_t active; uint8_t questIndex; - } entry[5]; - uint16_t padding[3]; - }; + } entry[5]; + uint16_t padding[3]; +}; - struct FFXIVIpcWeatherChange : FFXIVIpcBasePacket< WeatherChange > - { - uint32_t weatherId; - float delay; - }; +struct FFXIVIpcWeatherChange : FFXIVIpcBasePacket +{ + uint32_t weatherId; + float delay; +}; - /** - * Structural representation of the packet sent by the server - * to send a unveil a map - */ - struct FFXIVIpcDiscovery : FFXIVIpcBasePacket< Discovery > - { - /* 0000 */ uint32_t mapPartId; - /* 0004 */ uint32_t mapId; - }; +/** +* Structural representation of the packet sent by the server +* to send a unviel a map +*/ +struct FFXIVIpcDiscovery : FFXIVIpcBasePacket +{ + /* 0000 */ uint32_t map_part_id; + /* 0004 */ uint32_t map_id; +}; - /** - * UNKOWN TYPE - */ - struct FFXIVARR_IPC_UNK322 : FFXIVIpcBasePacket< DailyQuestRepeatFlags > - { - /* 0000 */ uint8_t unk[8]; - }; - /** - * UNKOWN TYPE - */ - struct FFXIVARR_IPC_UNK320 : FFXIVIpcBasePacket< DailyQuests > - { - /* 0000 */ uint8_t unk[0x38]; - }; +/** +* UNKOWN TYPE +*/ +struct FFXIVARR_IPC_UNK322 : FFXIVIpcBasePacket +{ + /* 0000 */ uint8_t unk[8]; +}; - /** - * Structural representation of the packet sent by the server - * prepare zoning, showing screenmessage - */ - struct FFXIVIpcPrepareZoning : FFXIVIpcBasePacket< PrepareZoning > - { - uint32_t logMessage; - uint16_t targetZone; - uint16_t animation; - uint8_t param4; - uint8_t hideChar; - uint8_t fadeOut; - uint8_t param7; - uint8_t fadeOutTime; - uint8_t unknown; // this changes whether or not the destination zone's name displays during the loading screen. Seems to always be 9 (=hidden) when going to an instance and certain zones, 0 otherwise. - uint16_t padding; - }; +/** +* UNKOWN TYPE +*/ +struct FFXIVARR_IPC_UNK320 : FFXIVIpcBasePacket +{ + /* 0000 */ uint8_t unk[32]; +}; - /** - * Structural representation of the packet sent by the server - * to trigger content finder events - * - * See https://gist.github.com/Minoost/c35843c4c8a7a931f31fdaac9bce64c2 - */ - struct FFXIVIpcCFNotify : FFXIVIpcBasePacket< CFNotify > - { +/** +* Structural representation of the packet sent by the server +* prepare zoning, showing screenmessage +*/ +struct FFXIVIpcPrepareZoning : FFXIVIpcBasePacket +{ + uint32_t logMessage; + uint16_t targetZone; + uint16_t animation; + uint8_t param4; + uint8_t hideChar; + uint8_t fadeOut; + uint8_t param7; + uint8_t fadeOutTime; + uint8_t unknown; + uint16_t padding; +}; + +/** +* Structural representation of the packet sent by the server +* to trigger content finder events +* +* See https://gist.github.com/Minoost/c35843c4c8a7a931f31fdaac9bce64c2 +*/ +struct FFXIVIpcCFNotify : FFXIVIpcBasePacket +{ uint32_t state1; // 3 = cancelled, 4 = duty ready uint32_t state2; // if state1 == 3, state2 is cancelled reason @@ -1647,597 +1193,103 @@ namespace Sapphire::Network::Packets::Server uint16_t param4; // usually roulette id uint16_t contents[5]; - }; +}; - /** - * Structural representation of the packet sent by the server - * to update contents available in duty finder or raid finder - * - * Do note that this packet has to come early in login phase (around initui packet) - * or it won't be applied until you reconnect - */ - struct FFXIVIpcCFAvailableContents : FFXIVIpcBasePacket< CFAvailableContents > - { +/** +* Structural representation of the packet sent by the server +* to update contents available in duty finder or raid finder +* +* Do note that this packet has to come early in login phase (around initui packet) +* or it won't be applied until you reconnect +*/ +struct FFXIVIpcCFAvailableContents : FFXIVIpcBasePacket +{ uint8_t contents[0x48]; - }; +}; - /** - * Structural representation of the packet sent by the server - * to update adventure in needs in duty roulette - */ - struct FFXIVIpcCFPlayerInNeed : FFXIVIpcBasePacket< CFPlayerInNeed > - { +/** +* Structural representation of the packet sent by the server +* to update adventure in needs in duty roulette +*/ +struct FFXIVIpcCFPlayerInNeed : FFXIVIpcBasePacket +{ // Ordered by roulette id uint8_t inNeeds[0x10]; - }; +}; - /** - * Structural representation of the packet sent by the server - * to update duty info in general - */ - struct FFXIVIpcCFDutyInfo : FFXIVIpcBasePacket< CFDutyInfo > - { +/** +* Structural representation of the packet sent by the server +* to update duty info in general +*/ +struct FFXIVIpcCFDutyInfo : FFXIVIpcBasePacket +{ uint8_t penaltyTime; uint8_t unknown[7]; - }; +}; - struct FFXIVIpcCFRegisterDuty : FFXIVIpcBasePacket< CFRegisterDuty > - { +struct FFXIVIpcCFRegisterDuty : FFXIVIpcBasePacket +{ uint32_t unknown0; // 0x301 uint8_t rouletteId; // if it's a daily roulette uint8_t unknown1; // 0xDB uint16_t contentId; - }; +}; - struct FFXIVIpcCFMemberStatus : FFXIVIpcBasePacket< CFMemberStatus > - { - uint16_t contentId; - uint16_t unknown1; - uint8_t status; - uint8_t currentTank; - uint8_t currentDps; - uint8_t currentHealer; - uint8_t estimatedTime; - uint8_t unknown2[3]; - uint32_t unknown3; - }; +struct FFXIVIpcCFMemberStatus : FFXIVIpcBasePacket +{ + uint16_t contentId; + uint16_t unknown1; + uint8_t status; + uint8_t currentTank; + uint8_t currentDps; + uint8_t currentHealer; + uint8_t estimatedTime; + uint8_t unknown2[3]; + uint32_t unknown3; +}; - struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket< EorzeaTimeOffset > - { - uint64_t timestamp; - }; +struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket +{ + uint64_t timestamp; +}; - /** - * Structural representation of the packet sent by the server - * to set the gear show/hide status of a character - */ - struct FFXIVIpcEquipDisplayFlags : FFXIVIpcBasePacket< EquipDisplayFlags > - { - uint8_t bitmask; - }; +/** +* Structural representation of the packet sent by the server +* to set the gear show/hide status of a character +*/ +struct FFXIVIpcEquipDisplayFlags : FFXIVIpcBasePacket +{ + uint8_t bitmask; +}; - struct FFXIVIpcMiniCactPotInit : FFXIVIpcBasePacket< MiniCactpotInit > - { - /* - * Looks like this shares a handler with MarketTaxRates and a few - * other packets, so these first fields are most likely discriminators - * or other metadata for the handler itself. - */ - uint32_t type; - uint16_t category; - uint8_t unknown1; - uint8_t unknown2; - /* - * Always 18 for this packet, incidentally the number of payouts plus 1. - * Used similarly for MarketTaxRates => for (auto i = 0; i <= indexEnd; i++) {} - */ - uint8_t indexEnd; - uint8_t unknown3; - uint16_t padding1; - /* - * On clicking a number, the client sends a ClientTrigger (DirectorSync) with an unknown - * param2, param5; param1 session, param3 column, param4 row; zero param6, and the server - * replies with an ActorControlSelf (DirectorUpdate) with an unknown param2; param1 session, - * param3 column, param4 row, param5 digit; zero param6. After a line is selected, - * the server replies with 9 DirectorUpdate packets, in order (column, row), containing every - * number on the board (why tho). Finally, one last DirectorUpdate is sent with parameters - * param1 session, param3 payout index; unknown param2, param4; zero param5, param6. - */ - uint32_t column; // zero-based - uint32_t row; - uint32_t firstDigit; - uint32_t payouts[19]; // In in-game display order - uint32_t unknown4; - /* - * All of the below fields seem to be gibberish, and change completely between - * draws and characters. - */ - uint32_t unknown5; - uint32_t unknown6; - uint32_t unknown7; - uint32_t unknown8; - uint16_t unknown9; - uint16_t unknown10; - uint32_t unknown11; - uint64_t unknown12; - }; - - /** - * Structural representation of the packet sent by the server - * to place/remove field marker presets - */ - struct FFXIVIpcPlaceFieldMarkerPreset : FFXIVIpcBasePacket< PlaceFieldMarkerPreset > - { - /*! which fieldmarks to show */ - Common::FieldMarkerStatus status; - /*! A coordinates would be (float)Xints[0]/1000.0, (float)Yints[0]/1000.0, (float)Zints[0]/1000.0 */ - uint32_t Xints[8]; - uint32_t Yints[8]; - uint32_t Zints[8]; - }; - - /** - * Structural representation of the packet sent by the server - * to place/remove a field marker - */ - struct FFXIVIpcPlaceFieldMarker : FFXIVIpcBasePacket< PlaceFieldMarker > - { - Common::FieldMarkerId markerId; - uint8_t status; - uint8_t pad[2]; - uint32_t Xint; - uint32_t Yint; - uint32_t Zint; - }; - - /** - * Structural representation of the packet sent by the server - * to mount a player - */ - struct FFXIVIpcMount : FFXIVIpcBasePacket< Mount > - { - uint32_t id; - uint32_t padding[3]; - }; - - /** - * Structural representation of the packet sent by the server - * to mount a player - */ - struct FFXIVIpcDirectorVars : FFXIVIpcBasePacket< DirectorVars > - { - /*! DirectorType | ContentId */ - uint32_t m_directorId; - /*! currect sequence */ - uint8_t m_sequence; - /*! current branch */ - uint8_t m_branch; - /*! raw storage for flags/vars */ - uint8_t m_unionData[10]; - /*! unknown */ - uint16_t u20; - uint16_t u22; - uint16_t u24; - uint16_t u28; - }; - - struct FFXIVIpcDirectorPopUp : FFXIVIpcBasePacket< DirectorPopUp > - { - 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 pad3[4]; - }; +/** +* Structural representation of the packet sent by the server +* to mount a player +*/ +struct FFXIVIpcMount : FFXIVIpcBasePacket +{ + uint32_t id; +}; - struct FFXIVIpcActorGauge : FFXIVIpcBasePacket< ActorGauge > - { - uint8_t classJobId; - uint8_t data[15]; // depends on classJobId - }; +struct FFXIVIpcActorGauge : FFXIVIpcBasePacket +{ + uint8_t classJobId; + uint8_t data[15]; // depends on classJobId +}; - struct FFXIVIpcPerformNote : FFXIVIpcBasePacket< PerformNote > - { - uint8_t data[32]; - }; - - struct FFXIVIpcHousingUpdateLandFlagsSlot : FFXIVIpcBasePacket< HousingUpdateLandFlagsSlot > - { - uint32_t type; - uint32_t unknown; - Common::LandFlagSet flagSet; - }; - - struct FFXIVIpcHousingLandFlags : FFXIVIpcBasePacket< HousingLandFlags > - { - Common::LandFlagSet freeCompanyHouse; // 00 - uint64_t unkown1; - Common::LandFlagSet privateHouse; // 24 - uint64_t unkown2; - Common::LandFlagSet apartment; // 48 - uint64_t unkown3; - Common::LandFlagSet sharedHouse[2]; //72 - uint64_t unkown4; - Common::LandFlagSet unkownHouse; - uint64_t unkown5; - }; - - //Structs - struct LandStruct - { - uint8_t plotSize; //0 - uint8_t houseState; // 2 - uint8_t flags; // bit1 -> hasPublicAccess; bit2 -> isPersonalHouse - uint8_t iconAddIcon; // 6 - uint32_t fcId; //8 - uint32_t fcIcon;// 12 - uint32_t fcIconColor; // 16 - uint16_t housePart[ 8 ]; // 34 - uint8_t houseColour[ 8 ]; // 36 - }; - - struct FFXIVIpcLandUpdate : FFXIVIpcBasePacket< LandUpdate > - { - Common::LandIdent landIdent; - LandStruct land; - }; - - struct FFXIVIpcLandPriceUpdate : FFXIVIpcBasePacket< LandPriceUpdate > - { - uint32_t price; - uint32_t timeLeft; - }; - - struct FFXIVIpcLandInfoSign : FFXIVIpcBasePacket< LandInfoSign > - { - Common::LandIdent landIdent; - uint64_t ownerId; // ither contentId or fcId - uint32_t unknow1; - uint8_t houseIconAdd; - uint8_t houseSize; - uint8_t houseType; - char estateName[23]; - char estateGreeting[193]; - char ownerName[31]; - char fcTag[7]; - uint8_t tag[3]; - }; - - struct FFXIVIpcLandRename : FFXIVIpcBasePacket< LandRename > - { - Common::LandIdent landIdent; - char houseName[20]; - uint32_t padding; - }; - - struct FFXIVIpcLandUpdateHouseName : FFXIVIpcBasePacket< LandUpdateHouseName > - { - uint32_t unknown[3]; - char houseName[20]; - uint32_t unknown2[2]; - }; - - struct FFXIVIpcLandSetMap : FFXIVIpcBasePacket< LandSetMap > - { - uint8_t u1; - uint8_t subdivision; - uint8_t u3; - struct - { - uint8_t status; - uint8_t size; - uint8_t isPrivate; - } landInfo[ 30 ]; - uint8_t padding[ 3 ]; - }; - - struct FFXIVIpcLandSetInitialize : FFXIVIpcBasePacket< LandSetInitialize > - { - Common::LandIdent landIdent; - uint8_t unknown1; - uint8_t subInstance; // (default : 1/2) - uint8_t unknown3; - uint8_t unknown4; - uint8_t unknown5; - uint8_t unknown6; - uint8_t unknown7; - uint8_t unknown8; - LandStruct land[ 30 ]; - }; - - struct FFXIVIpcYardObjectSpawn : FFXIVIpcBasePacket< YardObjectSpawn > - { - uint8_t landId; - uint8_t objectArray; - uint16_t unknown1; - Common::HousingObject object; - }; - - struct FFXIVIpcHousingObjectMove : FFXIVIpcBasePacket< HousingObjectMove > - { - uint16_t itemRotation; - uint8_t objectArray; - uint8_t landId; - Common::FFXIVARR_POSITION3 pos; - uint16_t unknown1; - uint16_t unknown2; - uint16_t unknown3; - }; - - struct FFXIVIpcHousingObjectInitialize : FFXIVIpcBasePacket< HousingObjectInitialize > - { - Common::LandIdent landIdent; - /*! - * when this is 2, actrl 0x400 will hide the additional quarters door - * if it's any other value, it will stay there regardless - */ - int8_t u1; //Outdoor -1 / Indoor 0 - probably indicator - uint8_t packetNum; - uint8_t packetTotal; - uint8_t u2; //Outdoor 0 / Indoor 100(?) - Common::HousingObject object[100]; - uint32_t unknown4; //unused - }; - - struct FFXIVIpcHousingInternalObjectSpawn : FFXIVIpcBasePacket< HousingInternalObjectSpawn > - { - uint16_t containerId; - uint8_t containerOffset; - uint8_t pad1; - - Common::HousingObject object; - }; - - struct FFXIVIpcHousingIndoorInitialize : FFXIVIpcBasePacket< HousingIndoorInitialize > - { - uint16_t u1; - uint16_t u2; - uint16_t u3; - uint16_t u4; - uint32_t indoorItems[10]; - }; +struct FFXIVIpcPerformNote : FFXIVIpcBasePacket +{ + uint8_t data[32]; +}; - struct FFXIVIpcHousingWardInfo : FFXIVIpcBasePacket< HousingWardInfo > - { - Common::LandIdent landIdent; +} /* Server */ +} /* Packets */ +} /* Network */ +} /* Core */ - struct HouseInfoEntry - { - uint32_t housePrice; - uint8_t infoFlags; - Common::HousingAppeal houseAppeal[3]; - char estateOwnerName[32]; - } houseInfoEntry[60]; - }; - struct FFXIVIpcHousingEstateGreeting : FFXIVIpcBasePacket< HousingEstateGreeting > - { - Common::LandIdent landIdent; - char message[200]; - }; - - struct FFXIVIpcHousingShowEstateGuestAccess : FFXIVIpcBasePacket< HousingShowEstateGuestAccess > - { - uint32_t unknown[2]; - Common::LandIdent ident; - }; - - /** - * Structural representation of the packet sent by the server - * to show the current shared estate settings - */ - struct FFXIVIpcSharedEstateSettingsResponse : FFXIVIpcBasePacket< SharedEstateSettingsResponse > - { - struct playerEntry - { - uint64_t contentId; - uint8_t permissions; - char name[0x20]; - char padding[0x7]; - } entry[3]; - }; - - struct FFXIVIpcMSQTrackerProgress : FFXIVIpcBasePacket< MSQTrackerProgress > - { - uint32_t id; - uint32_t padding; - }; - - struct FFXIVIpcMSQTrackerComplete : FFXIVIpcBasePacket< MSQTrackerComplete > - { - uint32_t id; - uint32_t padding1; - uint64_t padding2; - uint64_t padding3; - uint64_t padding4; // last 4 bytes is uint32_t but who cares - }; - - struct FFXIVIpcObjectSpawn : FFXIVIpcBasePacket< ObjectSpawn > - { - uint8_t spawnIndex; - uint8_t objKind; - uint8_t state; - uint8_t unknown3; - uint32_t objId; - uint32_t actorId; - uint32_t levelId; - uint32_t unknown10; - uint32_t someActorId14; - uint32_t gimmickId; - float scale; - int16_t unknown20a; - uint16_t rotation; - int16_t unknown24a; - int16_t unknown24b; - uint16_t flag; - int16_t unknown28c; - uint32_t housingLink; - Common::FFXIVARR_POSITION3 position; - int16_t unknown3C; - int16_t unknown3E; - }; - - struct FFXIVIpcObjectDespawn : FFXIVIpcBasePacket< ObjectDespawn > - { - uint8_t spawnIndex; - uint8_t padding[7]; - }; - - struct FFXIVIpcDuelChallenge : FFXIVIpcBasePacket< DuelChallenge > - { - uint8_t otherClassJobId; - uint8_t otherLevel; // class job level - uint8_t challengeByYou; // 0 if the other challenges you, 1 if you challenges the other. - uint8_t otherItemLevel; - - uint32_t otherActorId; - - char otherName[32]; - }; - - struct FFXIVIpcRetainerInformation : FFXIVIpcBasePacket< RetainerInformation > - { - uint8_t unknown0[8]; - uint64_t retainerId; - uint8_t hireOrder; - uint8_t itemCount; - uint8_t unknown5[2]; - uint32_t gil; - uint8_t sellingCount; - uint8_t cityId; - uint8_t classJob; - uint8_t level; - uint8_t unknown11[4]; - uint32_t retainerTask; - uint32_t retainerTaskComplete; - uint8_t unknown14; - char retainerName[20]; - }; - - struct FFXIVIpcCharaVisualEffect : FFXIVIpcBasePacket< CharaVisualEffect > - { - uint32_t id; - uint32_t padding; - }; - - struct FFXIVIpcCFCancel : FFXIVIpcBasePacket< CFCancel > - { - uint32_t cancelReason; - uint32_t unknown2; - }; - - struct FFXIVIpcShopMessage : FFXIVIpcBasePacket< ShopMessage > - { - uint32_t shopId; - uint32_t msgType; - uint32_t unknown2; - uint32_t itemId; - uint32_t amount; - uint32_t price; - uint32_t unknown6; - uint32_t unknown7; - }; - - struct FFXIVIpcLootMessage : FFXIVIpcBasePacket< LootMessage > - { - Common::LootMessageType msgType; - uint8_t padding[3]; - uint32_t param1; - uint32_t param2; - uint32_t param3; - uint32_t param4; - uint32_t param5; - uint32_t param6; - uint32_t param7; - }; - - struct FFXIVIpcSocialMessage : FFXIVIpcBasePacket< SocialMessage > - { - uint64_t contentId; - uint32_t expireTime; - uint8_t p1; - uint8_t p2; - uint8_t socialType; - uint8_t padding; - uint8_t type; - uint8_t unknown4; - char name[32]; - uint8_t padding2[6]; - }; - - struct FFXIVIpcSocialMessage2 : FFXIVIpcBasePacket< SocialMessage2 > - { - uint64_t contentId; - uint32_t unknown3; - uint8_t p1; - uint8_t p2; - uint8_t socialType; - uint8_t padding; - char name[32]; - }; - - struct FFXIVIpcSocialRequestResponse : FFXIVIpcBasePacket< SocialRequestResponse > - { - uint64_t contentId; - uint32_t unknown3; - uint8_t u1AlwaysOne; - uint8_t response; - uint8_t u2AlwaysOne; - char name[32]; - uint8_t padding; - }; - - 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 otherData[368]; - } member[8]; - uint64_t someContentId1; - uint64_t someContentId2; - uint8_t leaderIndex; - uint8_t partySize; - uint16_t padding1; - uint32_t padding2; - }; - - struct FFXIVIpcPartyMessage : FFXIVIpcBasePacket< PartyMessage > - { - uint64_t leaderContentId; - uint64_t memberContentId; - uint8_t u1; - uint8_t u2; - uint16_t type; - uint8_t partySize; // ? - char leaderName[32]; - char memberName[32]; - uint8_t padding[3]; - }; -} #endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/ diff --git a/src/servers/sapphire_api/Forwards.h b/src/servers/sapphire_api/Forwards.h new file mode 100644 index 00000000..bdffff9f --- /dev/null +++ b/src/servers/sapphire_api/Forwards.h @@ -0,0 +1,102 @@ +#ifndef _FORWARDS_H +#define _FORWARDS_H + +#include + +namespace Core +{ + + class Cell; + class Zone; + class Item; + class ItemContainer; + class Inventory; + class Session; + class XMLConfig; + class ZonePosition; + + typedef boost::shared_ptr ZonePtr; + typedef boost::shared_ptr ItemPtr; + typedef boost::shared_ptr ItemContainerPtr; + typedef boost::shared_ptr InventoryPtr; + typedef boost::shared_ptr SessionPtr; + typedef boost::shared_ptr XMLConfigPtr; + typedef boost::shared_ptr ZonePositionPtr; + + namespace StatusEffect + { + class StatusEffect; + class StatusEffectContainer; + + typedef boost::shared_ptr StatusEffectPtr; + typedef boost::shared_ptr StatusEffectContainerPtr; + } + + namespace Entity + { + class Actor; + class Player; + class BattleNpc; + + typedef boost::shared_ptr ActorPtr; + typedef boost::shared_ptr PlayerPtr; + typedef boost::shared_ptr BattleNpcPtr; + } + + namespace Event + { + class EventHandler; + + typedef boost::shared_ptr EventPtr; + } + + namespace Action + { + class Action; + class ActionTeleport; + class EventAction; + + typedef boost::shared_ptr ActionPtr; + typedef boost::shared_ptr ActionTeleportPtr; + typedef boost::shared_ptr EventActionPtr; + } + + + namespace Network + { + class Hive; + class Acceptor; + class Connection; + class WorldConnection; + class SessionConnection; + class ZoneConnection; + + typedef boost::shared_ptr HivePtr; + typedef boost::shared_ptr AcceptorPtr; + typedef boost::shared_ptr ConnectionPtr; + typedef boost::shared_ptr WorldConnectionPtr; + typedef boost::shared_ptr ZoneConnectionPtr; + typedef boost::shared_ptr SessionConnectionPtr; + + namespace Packets + { + class GamePacket; + + + typedef boost::shared_ptr GamePacketPtr; + + + } + } + + namespace Scripting + { + typedef std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t, uint16_t ) > EventReturnCallback; + } + + typedef std::function< void( Entity::Player&, uint32_t, uint64_t ) > ActionCallback; + +} + + +#endif diff --git a/src/servers/sapphire_zone/Action/EventAction.cpp b/src/servers/sapphire_zone/Action/EventAction.cpp new file mode 100644 index 00000000..0aa85bfc --- /dev/null +++ b/src/servers/sapphire_zone/Action/EventAction.cpp @@ -0,0 +1,138 @@ +#include +#include +#include + +#include "EventAction.h" +#include "Network/PacketWrappers/ActorControlPacket142.h" +#include "Network/PacketWrappers/ActorControlPacket143.h" +#include "Actor/Player.h" +#include "Event/EventHandler.h" + +extern Core::Logger g_log; +extern Core::Data::ExdData g_exdData; + +using namespace Core::Common; +using namespace Core::Network; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +Core::Action::EventAction::EventAction() +{ + m_handleActionType = HandleActionType::Event; +} + +Core::Action::EventAction::EventAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action, + ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional ) +{ + m_additional = additional; + m_handleActionType = HandleActionType::Event; + m_eventId = eventId; + m_id = action; + m_castTime = g_exdData.m_EventActionInfoMap[action].castTime; // TODO: Add security checks. + m_onActionFinishClb = finishRef; + m_onActionInterruptClb = interruptRef; + m_pSource = pActor; + m_bInterrupt = false; +} + +Core::Action::EventAction::~EventAction() +{ + +} + +void Core::Action::EventAction::onStart() +{ + if( !m_pSource ) + return; + + m_startTime = Util::getTimeMs(); + + auto control = ActorControlPacket142( m_pSource->getId(), Common::ActorControlType::CastStart, + 1, m_id, 0x4000004E ); + + if( m_pSource->isPlayer() ) + { + m_pSource->sendToInRangeSet( control, true ); + m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::SomeFlag ); + m_pSource->getAsPlayer()->sendStateFlags(); + } + else + m_pSource->sendToInRangeSet( control ); +} + +void Core::Action::EventAction::onFinish() +{ + if( !m_pSource ) + return; + + try + { + auto pEvent = m_pSource->getAsPlayer()->getEvent( m_eventId ); + + pEvent->setPlayedScene( false ); + + if( m_onActionFinishClb ) + m_onActionFinishClb( *m_pSource->getAsPlayer(), m_eventId, m_additional ); + + auto control = ActorControlPacket142( m_pSource->getId(), Common::ActorControlType::CastStart, 0, m_id ); + + if( !pEvent->hasPlayedScene() ) + m_pSource->getAsPlayer()->eventFinish( m_eventId, 1 ); + else + pEvent->setPlayedScene( false ); + + if( m_pSource->isPlayer() ) + { + m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::SomeFlag ); + m_pSource->getAsPlayer()->sendStateFlags(); + m_pSource->sendToInRangeSet( control, true ); + } + else + m_pSource->sendToInRangeSet( control ); + } + catch( std::exception& e ) + { + g_log.error( e.what() ); + } + +} + +void Core::Action::EventAction::onInterrupt() +{ + if( !m_pSource ) + return; + + try + { + + auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, + 0x219, 0x04, m_id ); + + if( m_pSource->isPlayer() ) + { + auto control1 = ActorControlPacket143( m_pSource->getId(), ActorControlType::FreeEventPos, m_eventId ); + + m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat ); + m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); + m_pSource->getAsPlayer()->sendStateFlags(); + m_pSource->sendToInRangeSet( control ); + m_pSource->sendToInRangeSet( control1 ); + + m_pSource->getAsPlayer()->queuePacket( control1 ); + m_pSource->getAsPlayer()->queuePacket( control ); + m_pSource->getAsPlayer()->eventFinish( m_eventId, 1 ); + + } + else + m_pSource->sendToInRangeSet( control ); + + if( m_onActionInterruptClb ) + m_onActionInterruptClb( *m_pSource->getAsPlayer(), m_eventId, m_additional ); + + } + catch( std::exception& e ) + { + g_log.error( e.what() ); + } + +} diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp new file mode 100644 index 00000000..eecd4f2c --- /dev/null +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -0,0 +1,1598 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Session.h" +#include "Player.h" +#include "BattleNpc.h" + +#include "Zone/ZoneMgr.h" +#include "Zone/Zone.h" + +#include "ServerZone.h" + +#include "Network/GameConnection.h" +#include "Network/PacketWrappers/ActorControlPacket142.h" +#include "Network/PacketWrappers/ActorControlPacket143.h" +#include "Network/PacketWrappers/InitUIPacket.h" +#include "Network/PacketWrappers/ServerNoticePacket.h" +#include "Network/PacketWrappers/ChatPacket.h" +#include "Network/PacketWrappers/ModelEquipPacket.h" +#include "Network/PacketWrappers/UpdateHpMpTpPacket.h" +#include "Network/PacketWrappers/PlayerStateFlagsPacket.h" +#include "Network/PacketWrappers/PlayerSpawnPacket.h" + +#include "Script/ScriptManager.h" + +#include "Inventory/Item.h" + +#include "Inventory/Inventory.h" +#include "Event/EventHandler.h" +#include "Action/Action.h" +#include "Action/EventAction.h" +#include "Action/EventItemAction.h" +#include "Zone/ZonePosition.h" +#include "Math/CalcStats.h" +#include "Math/CalcBattle.h" +#include + +extern Core::Logger g_log; +extern Core::ServerZone g_serverZone; +extern Core::ZoneMgr g_zoneMgr; +extern Core::Data::ExdData g_exdData; +extern Core::Scripting::ScriptManager g_scriptMgr; + +using namespace Core::Common; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +// player constructor +Core::Entity::Player::Player() : + Actor(), + m_lastWrite( 0 ), + m_lastPing( 0 ), + m_bIsLogin( false ), + m_contentId( 0 ), + m_modelMainWeapon( 0 ), + m_modelSubWeapon( 0 ), + m_homePoint( 0 ), + m_startTown( 0 ), + m_townWarpFstFlags( 0 ), + m_playTime( 0 ), + m_bInCombat( false ), + m_bLoadingComplete( false ), + m_bMarkedForZoning( false ), + m_zoningType( Common::ZoneingType::None ), + m_bAutoattack( false ), + m_markedForRemoval( false ), + m_mount( 0 ) +{ + m_id = 0; + m_objKind = ObjKind::Player; + m_currentStance = Stance::Passive; + m_onlineStatus = 0; + m_queuedZoneing = nullptr; + m_status = ActorStatus::Idle; + m_invincibilityType = InvincibilityType::InvincibilityNone; + + memset( m_questTracking, 0, sizeof( m_questTracking ) ); + memset( m_name, 0, sizeof( m_name ) ); + memset( m_stateFlags, 0, sizeof( m_stateFlags ) ); + memset( m_searchMessage, 0, sizeof( m_searchMessage ) ); + memset( m_classArray, 0, sizeof( m_classArray ) ); + memset( m_expArray, 0, sizeof( m_expArray ) ); +} + +Core::Entity::Player::~Player() +{ + g_log.debug( "PlayerObj destroyed" ); +} + +// TODO: add a proper calculation based on race / job / level / gear +uint32_t Core::Entity::Player::getMaxHp() +{ + return m_baseStats.max_hp; +} + +uint32_t Core::Entity::Player::getMaxMp() +{ + return m_baseStats.max_mp; +} + +uint16_t Core::Entity::Player::getZoneId() const +{ + return m_zoneId; +} + +uint8_t Core::Entity::Player::getGmRank() const +{ + return m_gmRank; +} + +void Core::Entity::Player::setGmRank( uint8_t rank ) +{ + m_gmRank = rank; +} + +uint8_t Core::Entity::Player::getMode() const +{ + return m_mode; +} + +void Core::Entity::Player::setMode( uint8_t mode ) +{ + m_mode = mode; +} + +uint8_t Core::Entity::Player::getStartTown() const +{ + return m_startTown; +} + +void Core::Entity::Player::setMarkedForRemoval() +{ + m_markedForRemoval = true; +} + +bool Core::Entity::Player::isMarkedForRemoval() const +{ + return m_markedForRemoval; +} + +Core::Common::OnlineStatus Core::Entity::Player::getOnlineStatus() +{ + uint64_t newMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::NewAdventurer ); + uint64_t afkMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::AwayfromKeyboard ); + uint64_t busyMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::Busy ); + uint64_t dcMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::Disconnected ); + uint64_t meldMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::LookingtoMeldMateria ); + uint64_t ptMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::LookingforParty ); + uint64_t rpMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::Roleplaying ); + + OnlineStatus status = OnlineStatus::Online; + + //if( hasStateFlag( Common::PlayerStateFlag::NewAdventurer ) ) + if( m_onlineStatus & newMask ) + status = OnlineStatus::NewAdventurer; + + if( m_onlineStatus & afkMask ) + status = OnlineStatus::AwayfromKeyboard; + + if( m_onlineStatus & busyMask ) + status = OnlineStatus::Busy; + + if( m_onlineStatus & dcMask ) + status = OnlineStatus::Disconnected; + + if( m_onlineStatus & meldMask ) + status = OnlineStatus::LookingtoMeldMateria; + + if( m_onlineStatus & ptMask ) + status = OnlineStatus::LookingforParty; + + if( m_onlineStatus & rpMask ) + status = OnlineStatus::Roleplaying; + + if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) || hasStateFlag( PlayerStateFlag::WatchingCutscene1 ) ) + status = OnlineStatus::ViewingCutscene; + + // TODO: add all the logic for returning the proper online status, there probably is a better way for this alltogether + return status; +} + +void Core::Entity::Player::setOnlineStatusMask( uint64_t status ) +{ + m_onlineStatus = status; +} + +uint64_t Core::Entity::Player::getOnlineStatusMask() const +{ + return m_onlineStatus; +} + +void Core::Entity::Player::prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime, uint16_t animation ) +{ + ZoneChannelPacket< FFXIVIpcPrepareZoning > preparePacket( getId() ); + preparePacket.data().targetZone = targetZone; + preparePacket.data().fadeOutTime = fadeOutTime; + preparePacket.data().animation = animation; + preparePacket.data().fadeOut = static_cast< uint8_t >( fadeOut ? 1 : 0 ); + queuePacket( preparePacket ); +} + +void Core::Entity::Player::calculateStats() +{ + uint8_t tribe = getLookAt( Common::CharaLook::Tribe ); + uint8_t level = getLevel(); + uint8_t job = static_cast< uint8_t >( getClass() ); + + auto classInfoIt = g_exdData.m_classJobInfoMap.find( job ); + auto tribeInfoIt = g_exdData.m_tribeInfoMap.find( tribe ); + auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( level ); + + if( tribeInfoIt == g_exdData.m_tribeInfoMap.end() || + classInfoIt == g_exdData.m_classJobInfoMap.end() || + paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() ) + return; + + auto tribeInfo = tribeInfoIt->second; + auto classInfo = classInfoIt->second; + auto paramGrowthInfo = paramGrowthInfoIt->second; + + // TODO: put formula somewhere else... + float base = Math::CalcStats::calculateBaseStat( getAsPlayer() ); + + m_baseStats.str = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_str ) / 100 ) + tribeInfo.mod_str ); + m_baseStats.dex = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_dex ) / 100 ) + tribeInfo.mod_dex ); + m_baseStats.vit = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_vit ) / 100 ) + tribeInfo.mod_vit ); + m_baseStats.inte = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_int ) / 100 ) + tribeInfo.mod_int ); + m_baseStats.mnd = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_mnd ) / 100 ) + tribeInfo.mod_mnd ); + m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_pie ) / 100 ) + tribeInfo.mod_pie ); + + m_baseStats.skillSpeed = paramGrowthInfo.base_secondary; + m_baseStats.spellSpeed = paramGrowthInfo.base_secondary; + m_baseStats.accuracy = paramGrowthInfo.base_secondary; + m_baseStats.critHitRate = paramGrowthInfo.base_secondary; + m_baseStats.attackPotMagic = paramGrowthInfo.base_secondary; + m_baseStats.healingPotMagic = paramGrowthInfo.base_secondary; + m_baseStats.tenacity = paramGrowthInfo.base_secondary; + + m_baseStats.max_mp = Math::CalcStats::calculateMaxMp( getAsPlayer() ); + + m_baseStats.max_hp = Math::CalcStats::calculateMaxHp( getAsPlayer() ); + + if( m_mp > m_baseStats.max_mp ) + m_mp = m_baseStats.max_mp; + + if( m_hp > m_baseStats.max_hp ) + m_hp = m_baseStats.max_hp; + + + m_baseStats.determination = static_cast< uint32_t >( base ); + +} + + +void Core::Entity::Player::setAutoattack(bool mode) +{ + m_bAutoattack = mode; + m_lastAttack = Util::getTimeMs(); +} + +bool Core::Entity::Player::isAutoattackOn() const +{ + return m_bAutoattack; +} + +void Core::Entity::Player::sendStats() +{ + ZoneChannelPacket< FFXIVIpcPlayerStats > statPacket( getId() ); + statPacket.data().strength = m_baseStats.str; + statPacket.data().dexterity = m_baseStats.dex; + statPacket.data().vitality = m_baseStats.vit; + statPacket.data().intelligence = m_baseStats.inte; + statPacket.data().mind = m_baseStats.mnd; + statPacket.data().piety = m_baseStats.pie; + statPacket.data().determination = m_baseStats.determination; + statPacket.data().hp = m_baseStats.max_hp; + statPacket.data().mp = m_baseStats.max_mp; + statPacket.data().accuracy = m_baseStats.accuracy; + statPacket.data().attack = m_baseStats.attack; + statPacket.data().attackMagicPotency = m_baseStats.attackPotMagic; + statPacket.data().healingMagicPotency = m_baseStats.healingPotMagic; + statPacket.data().skillSpeed = m_baseStats.skillSpeed; + statPacket.data().spellSpeed = m_baseStats.spellSpeed; + statPacket.data().spellSpeed1 = m_baseStats.spellSpeed; + statPacket.data().spellSpeedMod = 100; + + statPacket.data().criticalHitRate = m_baseStats.spellSpeed; + statPacket.data().defense = m_baseStats.spellSpeed; + statPacket.data().magicDefense = m_baseStats.spellSpeed; + statPacket.data().attack = m_baseStats.spellSpeed; + + queuePacket( statPacket ); +} + +void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) +{ + auto data = g_exdData.getAetheryteInfo( aetheryteId ); + + if( data == nullptr ) + { + return; + } + + setStateFlag( PlayerStateFlag::BetweenAreas ); + sendStateFlags(); + + auto z_pos = g_zoneMgr.getZonePosition( data->levelId ); + + Common::FFXIVARR_POSITION3 pos; + pos.x = 0; + pos.y = 0; + pos.z = 0; + float rot = 0; + + if( z_pos != nullptr ) + { + pos = z_pos->getTargetPosition(); + rot = z_pos->getTargetRotation(); + } + + sendDebug( "Teleport: " + data->placename + " " + data->placename_aethernet + + "(" + std::to_string( data->levelId ) + ")" ); + + // TODO: this should be simplified and a type created in server_common/common.h. + if( type == 1 ) // teleport + { + prepareZoning( data->target_zone, true, 1, 112 ); + sendToInRangeSet( ActorControlPacket142( getId(), ActorDespawnEffect, 0x04 ) ); + setZoningType( Common::ZoneingType::Teleport ); + } + else if( type == 2 ) // aethernet + { + prepareZoning( data->target_zone, true, 1, 112 ); + sendToInRangeSet( ActorControlPacket142( getId(), ActorDespawnEffect, 0x04 ) ); + setZoningType( Common::ZoneingType::Teleport ); + } + else if( type == 3 ) // return + { + prepareZoning( data->target_zone, true, 1, 111 ); + sendToInRangeSet( ActorControlPacket142( getId(), ActorDespawnEffect, 0x03 ) ); + setZoningType( Common::ZoneingType::Return ); + } + + m_queuedZoneing = boost::make_shared< QueuedZoning >( data->target_zone, pos, Util::getTimeMs(), rot ); + + +} + +void Core::Entity::Player::forceZoneing( uint32_t zoneId ) +{ + m_queuedZoneing = boost::make_shared< QueuedZoning >( zoneId, getPos(), Util::getTimeMs(), 0.f ); + //performZoning( zoneId, Common::ZoneingType::None, getPos() ); +} + +void Core::Entity::Player::returnToHomepoint() +{ + setZoningType( Common::ZoneingType::Return ); + teleport( getHomepoint(), 3 ); +} + +void Core::Entity::Player::setZone( uint32_t zoneId ) +{ + auto pPlayer = getAsPlayer(); + + auto pZone = g_zoneMgr.getZone( zoneId ); + + + if( !pZone /*|| ( ( pZone == m_pCurrentZone ) && m_lastPing )*/ ) + { + g_log.error( "Zone " + std::to_string( zoneId ) + " not found on this server." ); + return; + } + + m_zoneId = zoneId; + + // mark character as zoning in progress + setLoadingComplete( false ); + + if( m_lastPing != 0 ) + m_pCurrentZone->removeActor( shared_from_this() ); + + m_pCurrentZone = pZone; + m_pCurrentZone->pushActor( shared_from_this() ); + + ZoneChannelPacket< FFXIVIpcInit > initPacket( getId() ); + initPacket.data().charId = getId(); + queuePacket( initPacket ); + + sendInventory(); + + if( isLogin() ) + { + queuePacket(ActorControlPacket143( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) ); + } + + // set flags, will be reset automatically by zoning ( only on client side though ) + pPlayer->setStateFlag( PlayerStateFlag::BetweenAreas ); + pPlayer->setStateFlag( PlayerStateFlag::BetweenAreas1 ); + pPlayer->sendStateFlags(); + + pPlayer->sendStats(); + + // only initialize the UI if the player in fact just logged in. + if( isLogin() ) + { + ZoneChannelPacket< FFXIVIpcCFAvailableContents > contentFinderList( getId() ); + for( auto i = 0; i < sizeof( contentFinderList.data().contents ); i++ ) + { + // unlock all contents for now + contentFinderList.data().contents[i] = 0xFF; + } + queuePacket( contentFinderList ); + + Server::InitUIPacket initUIPacket( *pPlayer ); + queuePacket( initUIPacket ); + + ZoneChannelPacket< FFXIVIpcPlayerClassInfo > classInfoPacket( getId() ); + classInfoPacket.data().classId = static_cast< uint8_t >( getClass() ); + classInfoPacket.data().unknown = 1; + classInfoPacket.data().level = getLevel(); + classInfoPacket.data().level1 = getLevel(); + queuePacket( classInfoPacket ); + + ZoneChannelPacket< FFXIVGCAffiliation > gcAffPacket( getId() ); + gcAffPacket.data().gcId = m_gc; + gcAffPacket.data().gcRank[0] = m_gcRank[0]; + gcAffPacket.data().gcRank[1] = m_gcRank[1]; + gcAffPacket.data().gcRank[2] = m_gcRank[2]; + queuePacket( gcAffPacket ); + + m_itemLevel = getInventory()->calculateEquippedGearItemLevel(); + sendItemLevel(); + } + + ZoneChannelPacket< FFXIVIpcInitZone > initZonePacket( getId() ); + initZonePacket.data().zoneId = getCurrentZone()->getLayoutId(); + initZonePacket.data().weatherId = static_cast< uint8_t >( getCurrentZone()->getCurrentWeather() ); + initZonePacket.data().bitmask = 0x1; + initZonePacket.data().unknown5 = 0x2A; + initZonePacket.data().pos.x = getPos().x; + initZonePacket.data().pos.y = getPos().y; + initZonePacket.data().pos.z = getPos().z; + queuePacket( initZonePacket ); + + if( isLogin() ) + { + ZoneChannelPacket< FFXIVARR_IPC_UNK322 > unk322( getId() ); + queuePacket( unk322 ); + + ZoneChannelPacket< FFXIVARR_IPC_UNK320 > unk320( getId() ); + queuePacket( unk320 ); + } + + if( getLastPing() == 0 ) + sendQuestInfo(); + + m_bMarkedForZoning = false; +} + +uint32_t Core::Entity::Player::getPlayTime() const +{ + return m_playTime; +} + +uint8_t Core::Entity::Player::getRace() const +{ + return getLookAt( CharaLook::Race ); +} + +uint8_t Core::Entity::Player::getGender() const +{ + return getLookAt( CharaLook::Gender ); +} + +void Core::Entity::Player::initSpawnIdQueue() +{ + while( !m_freeSpawnIdQueue.empty() ) + { + m_freeSpawnIdQueue.pop(); + } + + for( int32_t i = 1; i < MAX_DISPLAYED_ACTORS; i++ ) + { + m_freeSpawnIdQueue.push( i ); + } +} + +uint8_t Core::Entity::Player::getSpawnIdForActorId( uint32_t actorId ) +{ + if( m_freeSpawnIdQueue.empty() ) + return 0; + + uint8_t spawnId = m_freeSpawnIdQueue.front(); + m_freeSpawnIdQueue.pop(); + m_playerIdToSpawnIdMap[actorId] = spawnId; + return spawnId; +} + +void Core::Entity::Player::assignSpawnIdToPlayerId( uint32_t actorId, uint8_t spawnId ) +{ + m_playerIdToSpawnIdMap[actorId] = spawnId; +} + +void Core::Entity::Player::registerAetheryte( uint8_t aetheryteId ) +{ + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( aetheryteId, value, index ); + + m_aetheryte[index] |= value; + queuePacket( ActorControlPacket143( getId(), LearnTeleport, aetheryteId, 1 ) ); + +} + +bool Core::Entity::Player::isAetheryteRegistered( uint8_t aetheryteId ) const +{ + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( aetheryteId, value, index ); + + return ( m_aetheryte[index] & value ) != 0; +} + +uint8_t * Core::Entity::Player::getDiscoveryBitmask() +{ + return m_discovery; +} + +void Core::Entity::Player::discover( int16_t map_id, int16_t sub_id ) +{ + // map.exd field 12 -> index in one of the two discovery sections, if field 15 is false, need to use 2nd section + // section 1 starts at 4 - 2 bytes each + + // section to starts at 320 - 4 bytes long + + int32_t offset = 4; + + auto info = g_exdData.m_zoneInfoMap[getCurrentZone()->getId()]; + if( info.is_two_byte ) + offset = 4 + 2 * info.discovery_index; + else + offset = 324 + 4 * info.discovery_index; + + int32_t index = offset + sub_id / 8; + uint8_t bitIndex = sub_id % 8; + + uint8_t value = 1 << bitIndex; + + m_discovery[index] |= value; + + uint16_t level = getLevel(); + + uint32_t exp = ( g_exdData.m_paramGrowthInfoMap[level].needed_exp * 5 / 100 ); + + gainExp( exp ); + + + +} + +bool Core::Entity::Player::isNewAdventurer() const +{ + return m_bNewAdventurer; +} + +void Core::Entity::Player::setNewAdventurer( bool state ) +{ + //if( !state ) + //{ + // unsetStateFlag( PlayerStateFlag::NewAdventurer ); + //} + //else + //{ + // setStateFlag( PlayerStateFlag::NewAdventurer ); + //} + sendStateFlags(); + m_bNewAdventurer = state; +} + +void Core::Entity::Player::resetDiscovery() +{ + memset( m_discovery, 0, sizeof( m_discovery ) ); +} + +void Core::Entity::Player::changePosition( float x, float y, float z, float o ) +{ + Common::FFXIVARR_POSITION3 pos; + pos.x = x; + pos.y = y; + pos.z = z; + m_queuedZoneing = boost::make_shared( getZoneId(), pos, Util::getTimeMs(), o ); +} + +void Core::Entity::Player::learnAction( uint8_t actionId ) +{ + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( actionId, value, index ); + + m_unlocks[index] |= value; + + queuePacket( ActorControlPacket143( getId(), ToggleActionUnlock, actionId, 1 ) ); +} + +void Core::Entity::Player::learnSong( uint8_t songId, uint32_t itemId ) +{ + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( songId, value, index ); + + m_orchestrion[index] |= value; + + queuePacket( ActorControlPacket143( getId(), ToggleOrchestrionUnlock, songId, 1, itemId ) ); +} + +bool Core::Entity::Player::isActionLearned( uint8_t actionId ) const +{ + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( actionId, value, index ); + + return ( m_unlocks[index] & value ) != 0; +} + +void Core::Entity::Player::gainExp( uint32_t amount ) +{ + uint32_t currentExp = getExp(); + + uint16_t level = getLevel(); + + uint32_t neededExpToLevel = g_exdData.m_paramGrowthInfoMap[level].needed_exp; + + uint32_t neededExpToLevelplus1 = g_exdData.m_paramGrowthInfoMap[level + 1].needed_exp; + + queuePacket( ActorControlPacket143( getId(), GainExpMsg, static_cast< uint8_t >( getClass() ), amount ) ); + + if( level >= 70 ) // temporary fix for leveling over levelcap + { + queuePacket( ActorControlPacket143( getId(), UpdateUiExp, static_cast< uint8_t >( getClass() ), amount ) ); + return; + } + + if( ( currentExp + amount ) >= neededExpToLevel ) + { + // levelup + amount = ( currentExp + amount - neededExpToLevel ) > neededExpToLevelplus1 ? + neededExpToLevelplus1 - 1 : + ( currentExp + amount - neededExpToLevel ); + setExp( amount ); + gainLevel(); + queuePacket( ActorControlPacket143( getId(), UpdateUiExp, static_cast< uint8_t >( getClass() ), amount ) ); + + } + else + { + queuePacket( ActorControlPacket143( getId(), UpdateUiExp, static_cast< uint8_t >( getClass() ), currentExp + amount ) ); + setExp( currentExp + amount ); + } + + sendStatusUpdate(); +} + +void Core::Entity::Player::gainLevel() +{ + setLevel( getLevel() + 1 ); + + calculateStats(); + sendStats(); + sendStatusUpdate(); + + m_hp = getMaxHp(); + m_mp = getMaxMp(); + + ZoneChannelPacket< FFXIVIpcStatusEffectList > effectListPacket( getId() ); + effectListPacket.data().classId = static_cast< uint8_t > ( getClass() ); + effectListPacket.data().classId1 = static_cast< uint8_t > ( getClass() ); + effectListPacket.data().level = getLevel(); + effectListPacket.data().current_hp = getMaxHp(); + effectListPacket.data().current_mp = getMaxMp(); + effectListPacket.data().currentTp = 1000; + effectListPacket.data().max_hp = getMaxHp(); + effectListPacket.data().max_mp = getMaxMp(); + sendToInRangeSet( effectListPacket, true ); + + sendToInRangeSet( ActorControlPacket142( getId(), LevelUpEffect, static_cast< uint8_t >( getClass() ), + getLevel(), getLevel() - 1 ), true ); + + + ZoneChannelPacket< FFXIVIpcUpdateClassInfo > classInfoPacket( getId() ); + classInfoPacket.data().classId = static_cast< uint8_t > ( getClass() ); + classInfoPacket.data().classId1 = static_cast< uint8_t > ( getClass() ); + classInfoPacket.data().level = getLevel(); + classInfoPacket.data().nextLevelIndex = getLevel(); + classInfoPacket.data().currentExp = getExp(); + queuePacket( classInfoPacket ); + +} + +void Core::Entity::Player::unlock() +{ + queuePacket( PlayerStateFlagsPacket( *getAsPlayer(), PlayerStateFlagList{} ) ); +} + +void Core::Entity::Player::sendStatusUpdate( bool toSelf ) +{ + // CGamePacket* pPE = new CGamePacket(0x140, 0x0128, getId(), getId()); + + //pPE->setInt8At(0x20, static_cast(getClass())); + + // pPE->setInt8At(0x21, getLevel()); + // pPE->setInt8At(0x22, getLevel()); + + // // current exp + // pPE->setInt32At(0x28, getExp()); + + // // rested exp + // //pPE->setInt32At(0x2C, m_hp); + + // pPE->setInt32At(0x24, m_hp); + // pPE->setInt32At(0x28, getMaxHp()); + // pPE->setInt16At(0x2C, m_mp); + // pPE->setInt16At(0x2E, getMaxMp()); + // pPE->setInt16At(0x30, m_tp); + + // sendToInRangeSet(pPE, toSelf); + + sendToInRangeSet( UpdateHpMpTpPacket( shared_from_this() ), true ); + +} + +uint8_t Core::Entity::Player::getLevel() const +{ + uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( getClass() )].exp_idx; + return static_cast< uint8_t >( m_classArray[classJobIndex] ); +} + +uint8_t Core::Entity::Player::getLevelForClass( Common::ClassJob pClass ) const +{ + uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( pClass )].exp_idx; + return static_cast< uint8_t >( m_classArray[classJobIndex] ); +} + +uint32_t Core::Entity::Player::getExp() const +{ + uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( getClass() )].exp_idx; + return m_expArray[classJobIndex]; +} + +void Core::Entity::Player::setExp( uint32_t amount ) +{ + uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( getClass() )].exp_idx; + m_expArray[classJobIndex] = amount; +} + +bool Core::Entity::Player::isInCombat() const +{ + return m_bInCombat; +} + +void Core::Entity::Player::setInCombat( bool mode ) +{ + //m_lastAttack = GetTickCount(); + m_bInCombat = mode; +} + +void Core::Entity::Player::setClassJob( Common::ClassJob classJob ) +{ + m_class = classJob; + uint8_t level = getLevel(); + + if( getHp() > getMaxHp() ) + m_hp = getMaxHp(); + + if( getMp() > getMaxMp() ) + m_mp = getMaxMp(); + + m_tp = 0; + + ZoneChannelPacket< FFXIVIpcPlayerClassInfo > classInfoPacket( getId() ); + classInfoPacket.data().classId = static_cast< uint8_t >( getClass() ); + classInfoPacket.data().level = getLevel(); + queuePacket( classInfoPacket ); + + sendToInRangeSet( ActorControlPacket142( getId(), ClassJobChange, 0x04 ), true ); + + sendStatusUpdate( true ); +} + +void Core::Entity::Player::setLevel( uint8_t level ) +{ + uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( static_cast< uint8_t >( getClass() ) )].exp_idx; + m_classArray[classJobIndex] = level; +} + +void Core::Entity::Player::setLevelForClass( uint8_t level, Common::ClassJob classjob ) +{ + uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( classjob )].exp_idx; + + if( m_classArray[classJobIndex] == 0 ) + insertDbClass( classJobIndex ); + + m_classArray[classJobIndex] = level; +} + +void Core::Entity::Player::sendModel() +{ + ModelEquipPacket modelEquip( *getAsPlayer() ); + sendToInRangeSet( modelEquip, true ); +} + +uint32_t Core::Entity::Player::getModelForSlot( Inventory::EquipSlot slot ) +{ + return m_modelEquip[slot]; +} + +void Core::Entity::Player::setModelForSlot( Inventory::EquipSlot slot, uint32_t val ) +{ + m_modelEquip[slot] = val; +} + +uint64_t Core::Entity::Player::getModelMainWeapon() const +{ + return m_modelMainWeapon; +} + +uint64_t Core::Entity::Player::getModelSubWeapon() const +{ + return m_modelSubWeapon; +} + +uint64_t Core::Entity::Player::getModelSystemWeapon() const +{ + return m_modelSystemWeapon; +} + +int8_t Core::Entity::Player::getAetheryteMaskAt( uint8_t index ) const +{ + if( index > sizeof( m_aetheryte ) ) + return 0; + return m_aetheryte[index]; +} + +uint8_t Core::Entity::Player::getBirthDay() const +{ + return m_birthDay; +} + +uint8_t Core::Entity::Player::getBirthMonth() const +{ + return m_birthMonth; +} + +uint8_t Core::Entity::Player::getGuardianDeity() const +{ + return m_guardianDeity; +} + +uint8_t Core::Entity::Player::getLookAt( uint8_t index ) const +{ + return m_customize[index]; +} + +void Core::Entity::Player::setLookAt( uint8_t index, uint8_t value ) +{ + m_customize[index] = value; +} + +// spawn this player for pTarget +void Core::Entity::Player::spawn( Entity::PlayerPtr pTarget ) +{ + g_log.debug( "[" + std::to_string( pTarget->getId() ) + "] Spawning " + + getName() + " for " + + pTarget->getName() ); + + PlayerSpawnPacket spawnActor( *getAsPlayer(), *pTarget ); + pTarget->queuePacket( spawnActor ); +} + +// despawn +void Core::Entity::Player::despawn( Entity::ActorPtr pTarget ) +{ + auto pPlayer = pTarget->getAsPlayer(); + + pPlayer->freePlayerSpawnId( getId() ); + + pPlayer->queuePacket( ActorControlPacket143( getId(), DespawnZoneScreenMsg, 0x04, getId(), 0x01 ) ); +} + +Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId ) +{ + ActorPtr targetActor; + auto inRange = getInRangeActors( true ); + for( auto actor : inRange ) + { + if( actor->getId() == targetId ) + targetActor = actor; + } + return targetActor; +} + +void Core::Entity::Player::setLastPing( uint32_t ping ) +{ + m_lastPing = ping; +} + +uint32_t Core::Entity::Player::getLastPing() const +{ + return m_lastPing; +} + +void Core::Entity::Player::setVoiceId( uint8_t voiceId ) +{ + m_voice = voiceId; +} + +void Core::Entity::Player::setGc( uint8_t gc ) +{ + m_gc = gc; + + ZoneChannelPacket< FFXIVGCAffiliation > gcAffPacket( getId() ); + gcAffPacket.data().gcId = m_gc; + gcAffPacket.data().gcRank[0] = m_gcRank[0]; + gcAffPacket.data().gcRank[1] = m_gcRank[1]; + gcAffPacket.data().gcRank[2] = m_gcRank[2]; + queuePacket( gcAffPacket ); +} + +void Core::Entity::Player::setGcRankAt( uint8_t index, uint8_t rank ) +{ + m_gcRank[index] = rank; + + ZoneChannelPacket< FFXIVGCAffiliation > gcAffPacket( getId() ); + gcAffPacket.data().gcId = m_gc; + gcAffPacket.data().gcRank[0] = m_gcRank[0]; + gcAffPacket.data().gcRank[1] = m_gcRank[1]; + gcAffPacket.data().gcRank[2] = m_gcRank[2]; + queuePacket( gcAffPacket ); +} + +const uint8_t* Core::Entity::Player::getStateFlags() const +{ + return m_stateFlags; +} + +bool Core::Entity::Player::actionHasCastTime( uint32_t actionId ) //TODO: Add logic for special cases +{ + auto actionInfoPtr = g_exdData.getActionInfo( actionId ); + if( actionInfoPtr->is_instant ) + return false; + + return actionInfoPtr->cast_time != 0; + +} + +bool Core::Entity::Player::hasStateFlag( Common::PlayerStateFlag flag ) const +{ + int32_t iFlag = static_cast< uint32_t >( flag ); + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( iFlag, value, index ); + + return ( m_stateFlags[index] & value ) != 0; +} + +void Core::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) +{ + int32_t iFlag = static_cast< uint32_t >( flag ); + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( iFlag, value, index ); + + m_stateFlags[index] |= value; + +} + +void Core::Entity::Player::setStateFlags( std::vector< Common::PlayerStateFlag > flags ) +{ + for( const auto& flag : flags ) + { + int iFlag = static_cast< uint32_t >( flag ); + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( iFlag, value, index ); + + m_stateFlags[index] |= value; + } +} + +void Core::Entity::Player::sendStateFlags() +{ + queuePacket( PlayerStateFlagsPacket( *getAsPlayer() ) ); +} + +void Core::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) +{ + if( !hasStateFlag( flag ) ) + return; + + int32_t iFlag = static_cast< uint32_t >( flag ); + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( iFlag, value, index ); + + m_stateFlags[index] ^= value; + +} + +void Core::Entity::Player::update( int64_t currTime ) +{ + + // a zoning is pending, lets do it + if( m_queuedZoneing && ( currTime - m_queuedZoneing->m_queueTime ) > 800 ) + { + Common::FFXIVARR_POSITION3 targetPos = m_queuedZoneing->m_targetPosition; + if( getCurrentZone()->getId() != m_queuedZoneing->m_targetZone ) + { + performZoning( m_queuedZoneing->m_targetZone, targetPos, m_queuedZoneing->m_targetRotation); + } + else + { + ZoneChannelPacket< FFXIVIpcActorSetPos > setActorPosPacket( getId() ); + setActorPosPacket.data().r16 = Math::Util::floatToUInt16Rot( m_queuedZoneing->m_targetRotation ); + setActorPosPacket.data().waitForLoad = 0x04; + setActorPosPacket.data().x = targetPos.x; + setActorPosPacket.data().y = targetPos.y; + setActorPosPacket.data().z = targetPos.z; + sendToInRangeSet( setActorPosPacket, true ); + setPosition( targetPos ); + } + m_queuedZoneing.reset(); + return; + } + + if( m_hp <= 0 && m_status != ActorStatus::Dead ) + die(); + + if( !isAlive() ) + return; + + updateStatusEffects(); + + m_lastUpdate = currTime; + + if( !checkAction() ) + { + if( m_targetId && m_currentStance == Entity::Actor::Stance::Active && isAutoattackOn() ) + { + auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::MainHand ); + + // @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need... + for( auto actor : m_inRangeActors ) + { + if( actor->getId() == m_targetId && actor->isAlive() && mainWeap ) + { + // default autoattack range + // TODO make this dependant on bnpc size + uint32_t range = 7; + + // default autoattack range for ranged classes + if( getClass() == ClassJob::Machinist || + getClass() == ClassJob::Bard || + getClass() == ClassJob::Archer ) + range = 25; + + + if( Math::Util::distance(getPos().x, getPos().y, getPos().z, + actor->getPos().x, actor->getPos().y, actor->getPos().z) <= range ) + { + + if( ( currTime - m_lastAttack ) > mainWeap->getDelay() ) + { + m_lastAttack = currTime; + autoAttack( actor ); + } + + } + } + } + } + } + + if( ( currTime - m_lastTickTime ) > 3000 ) + { + // add 3 seconds to total play time + m_playTime += 3; + m_lastTickTime = currTime; + onTick(); + } +} + +void Core::Entity::Player::onMobKill( uint16_t nameId ) +{ + g_scriptMgr.onMobKill( *getAsPlayer(), nameId ); +} + +void Core::Entity::Player::freePlayerSpawnId( uint32_t actorId ) +{ + uint8_t spawnId = m_playerIdToSpawnIdMap[actorId]; + m_playerIdToSpawnIdMap.erase( actorId ); + m_freeSpawnIdQueue.push( spawnId ); + + ZoneChannelPacket< FFXIVIpcActorFreeSpawn > freeActorSpawnPacket( getId() ); + freeActorSpawnPacket.data().actorId = actorId; + freeActorSpawnPacket.data().spawnId = spawnId; + queuePacket( freeActorSpawnPacket ); + +} + +uint8_t * Core::Entity::Player::getAetheryteArray() +{ + return m_aetheryte; +} + +/*! set homepoint */ +void Core::Entity::Player::setHomepoint( uint8_t aetheryteId ) +{ + m_homePoint = aetheryteId; + + queuePacket( ActorControlPacket143( getId(), SetHomepoint, aetheryteId ) ); +} + +/*! get homepoint */ +uint8_t Core::Entity::Player::getHomepoint() const +{ + return m_homePoint; +} + +uint16_t* Core::Entity::Player::getClassArray() +{ + return m_classArray; +} + +const uint16_t* Core::Entity::Player::getClassArray() const +{ + return m_classArray; +} + +const uint8_t* Core::Entity::Player::getLookArray() const +{ + return m_customize; +} + +const uint32_t* Core::Entity::Player::getModelArray() const +{ + return m_modelEquip; +} + +uint32_t* Core::Entity::Player::getExpArray() +{ + return m_expArray; +} + +const uint32_t* Core::Entity::Player::getExpArray() const +{ + return m_expArray; +} + +uint8_t* Core::Entity::Player::getHowToArray() +{ + return m_howTo; +} + +const uint8_t* Core::Entity::Player::getHowToArray() const +{ + return m_howTo; +} + +const uint8_t* Core::Entity::Player::getUnlockBitmask() const +{ + return m_unlocks; +} + +const uint8_t* Core::Entity::Player::getOrchestrionBitmask() const +{ + return m_orchestrion; +} + +const uint8_t* Core::Entity::Player::getMountGuideBitmask() const +{ + return m_mountGuide; +} + +uint64_t Core::Entity::Player::getContentId() const +{ + return m_contentId; +} + +uint8_t Core::Entity::Player::getVoiceId() const +{ + return m_voice; +} + +uint8_t Core::Entity::Player::getGc() const +{ + return m_gc; +} + +const uint8_t* Core::Entity::Player::getGcRankArray() const +{ + return m_gcRank; +} + +void Core::Entity::Player::queuePacket( Network::Packets::GamePacketPtr pPacket ) +{ + auto pSession = g_serverZone.getSession( m_id ); + + if( !pSession ) + return; + + auto pZoneCon = pSession->getZoneConnection(); + + if( pZoneCon ) + pZoneCon->queueOutPacket( pPacket ); + +} + +void Core::Entity::Player::queueChatPacket( Network::Packets::GamePacketPtr pPacket ) +{ + auto pSession = g_serverZone.getSession( m_id ); + + if( !pSession ) + return; + + auto pChatCon = pSession->getChatConnection(); + + if( pChatCon ) + pChatCon->queueOutPacket( pPacket ); +} + +bool Core::Entity::Player::isLoadingComplete() const +{ + return m_bLoadingComplete; +} + +void Core::Entity::Player::setLoadingComplete( bool bComplete ) +{ + m_bLoadingComplete = bComplete; +} + +void Core::Entity::Player::performZoning( uint16_t zoneId, const Common::FFXIVARR_POSITION3 &pos, float rotation ) +{ + m_pos = pos; + m_zoneId = zoneId; + m_bMarkedForZoning = true; + setRotation( rotation ); + setZone( zoneId ); +} + +bool Core::Entity::Player::isMarkedForZoning() const +{ + return m_bMarkedForZoning; +} + +ZoneingType Core::Entity::Player::getZoningType() const +{ + return m_zoningType; +} + +void Core::Entity::Player::setZoningType( Common::ZoneingType zoneingType ) +{ + m_zoningType = zoneingType; +} + +void Core::Entity::Player::setSearchInfo( uint8_t selectRegion, uint8_t selectClass, const char* searchMessage ) +{ + m_searchSelectRegion = selectRegion; + m_searchSelectClass = selectClass; + memset( &m_searchMessage[0], 0, sizeof( searchMessage ) ); + strcpy( &m_searchMessage[0], searchMessage ); +} + +const char* Core::Entity::Player::getSearchMessage() const +{ + return &m_searchMessage[0]; +} + +uint8_t Core::Entity::Player::getSearchSelectRegion() const +{ + return m_searchSelectRegion; +} + +uint8_t Core::Entity::Player::getSearchSelectClass() const +{ + return m_searchSelectClass; +} + +void Core::Entity::Player::sendNotice( const std::string& message ) //Purple Text +{ + queuePacket( ServerNoticePacket( getId(), message ) ); +} + +void Core::Entity::Player::sendUrgent( const std::string& message ) //Red Text +{ + queuePacket( ChatPacket( *getAsPlayer(), ChatType::ServerUrgent, message ) ); +} + +void Core::Entity::Player::sendDebug( const std::string& message ) //Grey Text +{ + queuePacket( ChatPacket( *getAsPlayer(), ChatType::ServerDebug, message ) ); +} + +void Core::Entity::Player::updateHowtosSeen( uint32_t howToId ) +{ + uint8_t index = howToId / 8; + uint8_t bitIndex = howToId % 8; + + uint8_t value = 1 << bitIndex; + + m_howTo[index] |= value; +} + + +void Core::Entity::Player::onMobAggro( BattleNpcPtr pBNpc ) +{ + hateListAdd( pBNpc ); + + queuePacket( ActorControlPacket142( getId(), ToggleAggro, 1 ) ); +} + +void Core::Entity::Player::onMobDeaggro( BattleNpcPtr pBNpc ) +{ + hateListRemove( pBNpc ); + + if( m_actorIdTohateSlotMap.empty() ) + queuePacket( ActorControlPacket142( getId(), ToggleAggro ) ); +} + +void Core::Entity::Player::hateListAdd( BattleNpcPtr pBNpc ) + +{ + if( m_freeHateSlotQueue.empty() ) + return; + uint8_t hateId = m_freeHateSlotQueue.front(); + m_freeHateSlotQueue.pop(); + m_actorIdTohateSlotMap[pBNpc->getId()] = hateId; + sendHateList(); + +} + +void Core::Entity::Player::hateListRemove( BattleNpcPtr pBNpc ) +{ + + auto it = m_actorIdTohateSlotMap.begin(); + for( ; it != m_actorIdTohateSlotMap.end(); ++it ) + { + if( it->first == pBNpc->getId() ) + { + uint8_t hateSlot = it->second; + m_freeHateSlotQueue.push( hateSlot ); + m_actorIdTohateSlotMap.erase( it ); + sendHateList(); + + return; + } + } +} + +bool Core::Entity::Player::hateListHasMob( BattleNpcPtr pBNpc ) +{ + + auto it = m_actorIdTohateSlotMap.begin(); + for( ; it != m_actorIdTohateSlotMap.end(); ++it ) + { + if( it->first == pBNpc->getId() ) + return true; + } + return false; +} + +void Core::Entity::Player::initHateSlotQueue() +{ + m_freeHateSlotQueue = std::queue< uint8_t >(); + for( int32_t i = 1; i < 26; i++ ) + m_freeHateSlotQueue.push( i ); +} + +void Core::Entity::Player::sendHateList() +{ + ZoneChannelPacket< FFXIVIpcHateList > hateListPacket( getId() ); + hateListPacket.data().numEntries = m_actorIdTohateSlotMap.size(); + auto it = m_actorIdTohateSlotMap.begin(); + for( int32_t i = 0; it != m_actorIdTohateSlotMap.end(); ++it, i++ ) + { + hateListPacket.data().entry[i].actorId = it->first; + hateListPacket.data().entry[i].hatePercent = 100; + } + queuePacket( hateListPacket ); +} + +bool Core::Entity::Player::isLogin() const +{ + return m_bIsLogin; +} + +void Core::Entity::Player::setIsLogin( bool bIsLogin ) +{ + m_bIsLogin = bIsLogin; +} + +uint8_t* Core::Entity::Player::getTitleList() +{ + return m_titleList; +} + +uint16_t Core::Entity::Player::getTitle() const +{ + return m_activeTitle; +} + +void Core::Entity::Player::addTitle( uint16_t titleId ) +{ + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( titleId, value, index ); + + m_titleList[index] |= value; +} + +void Core::Entity::Player::setTitle( uint16_t titleId ) +{ + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( titleId, value, index ); + + if ( ( m_titleList[index] & value ) == 0 ) // Player doesn't have title - bail + return; + + m_activeTitle = titleId; + + sendToInRangeSet( ActorControlPacket142( getId(), SetTitle, titleId ), true ); +} + +void Core::Entity::Player::setEquipDisplayFlags( uint8_t state ) +{ + m_equipDisplayFlags = state; + ZoneChannelPacket< FFXIVIpcEquipDisplayFlags > paramPacket( getId() ); + paramPacket.data().bitmask = m_equipDisplayFlags; + sendToInRangeSet( paramPacket, true ); +} + +uint8_t Core::Entity::Player::getEquipDisplayFlags() const +{ + return m_equipDisplayFlags; +} + +void Core::Entity::Player::mount( uint32_t id ) +{ + m_mount = id; + sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Mounted )), true ); + sendToInRangeSet( ActorControlPacket143( getId(), 0x39e, 12 ), true ); //? + + ZoneChannelPacket< FFXIVIpcMount > mountPacket( getId() ); + mountPacket.data().id = id; + sendToInRangeSet( mountPacket, true ); +} + +void Core::Entity::Player::dismount() +{ + sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, + static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle )), true ); + sendToInRangeSet( ActorControlPacket143( getId(), ActorControlType::Dismount, 1 ), true ); + m_mount = 0; +} + +uint8_t Core::Entity::Player::getCurrentMount() const +{ + return m_mount; +} + +void Core::Entity::Player::autoAttack( ActorPtr pTarget ) +{ + + auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, + Inventory::EquipSlot::MainHand ); + + pTarget->onActionHostile( shared_from_this() ); + //uint64_t tick = Util::getTimeMs(); + //srand(static_cast< uint32_t >(tick)); + + uint32_t damage = static_cast< uint32_t >( mainWeap->getAutoAttackDmg() ); + uint32_t variation = 0 + rand() % 3; + + if( getClass() == ClassJob::Machinist || + getClass() == ClassJob::Bard || + getClass() == ClassJob::Archer ) + { + ZoneChannelPacket< FFXIVIpcEffect > effectPacket(getId()); + effectPacket.data().targetId = pTarget->getId(); + effectPacket.data().actionAnimationId = 8; + // effectPacket.data().unknown_2 = variation; + effectPacket.data().numEffects = 1; + effectPacket.data().unknown_61 = 1; + effectPacket.data().unknown_62 = 1; + effectPacket.data().actionTextId = 8; + effectPacket.data().rotation = Math::Util::floatToUInt16Rot(getRotation()); + effectPacket.data().effectTargetId = pTarget->getId(); + effectPacket.data().effectTarget = pTarget->getId(); + effectPacket.data().effects[0].value = damage; + effectPacket.data().effects[0].effectType = Common::ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = Common::ActionHitSeverityType::NormalDamage; + effectPacket.data().effects[0].unknown_3 = 7; + + sendToInRangeSet(effectPacket, true); + } + else + { + + ZoneChannelPacket< FFXIVIpcEffect > effectPacket(getId()); + effectPacket.data().targetId = pTarget->getId(); + effectPacket.data().actionAnimationId = 7; + // effectPacket.data().unknown_2 = variation; + effectPacket.data().numEffects = 1; + effectPacket.data().unknown_61 = 1; + effectPacket.data().unknown_62 = 1; + effectPacket.data().actionTextId = 7; + effectPacket.data().rotation = Math::Util::floatToUInt16Rot(getRotation()); + effectPacket.data().effectTarget = pTarget->getId(); + effectPacket.data().effects[0].value = damage; + effectPacket.data().effects[0].effectType = Common::ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = Common::ActionHitSeverityType::NormalDamage; + effectPacket.data().effects[0].unknown_3 = 71; + + sendToInRangeSet(effectPacket, true); + } + + pTarget->takeDamage(damage); + +} + + +///////////////////////////// +// Content Finder +///////////////////////////// +uint32_t Core::Entity::Player::getCFPenaltyTimestamp() const +{ + return m_cfPenaltyUntil; +} + +void Core::Entity::Player::setCFPenaltyTimestamp( uint32_t timestamp ) +{ + m_cfPenaltyUntil = timestamp; +} + +uint32_t Core::Entity::Player::getCFPenaltyMinutes() const +{ + auto currentTimestamp = Core::Util::getTimeSeconds(); + auto endTimestamp = getCFPenaltyTimestamp(); + + // check if penalty timestamp already passed current time + if( currentTimestamp > endTimestamp ) + return 0; + + auto deltaTime = endTimestamp - currentTimestamp; + return static_cast< uint32_t > ( ceil( static_cast< float > (deltaTime) / 60 ) ); +} + +void Core::Entity::Player::setCFPenaltyMinutes( uint32_t minutes ) +{ + auto currentTimestamp = Core::Util::getTimeSeconds(); + setCFPenaltyTimestamp( static_cast< uint32_t >( currentTimestamp + minutes * 60 ) ); +} + +uint8_t Core::Entity::Player::getOpeningSequence() const +{ + return m_openingSequence; +} + +void Core::Entity::Player::setOpeningSequence( uint8_t seq ) +{ + m_openingSequence = seq; +} + +uint16_t Core::Entity::Player::getItemLevel() const +{ + return m_itemLevel; +} + +/// Tells client to offset their eorzean time by given timestamp. +void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp ) +{ + // TODO: maybe change to persistent? + ZoneChannelPacket< FFXIVIpcEorzeaTimeOffset > packet ( getId() ); + packet.data().timestamp = timestamp; + + // Send to single player + queuePacket( packet ); +} diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h new file mode 100644 index 00000000..03e00b15 --- /dev/null +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -0,0 +1,652 @@ +#ifndef _PLAYER_H +#define _PLAYER_H + +#include "Forwards.h" + +#include + +#include "Actor.h" +#include "Inventory/Inventory.h" +#include "Event/EventHandler.h" +#include +#include + +namespace Core { + +namespace Entity { + +struct QueuedZoning +{ + uint16_t m_targetZone; + Common::FFXIVARR_POSITION3 m_targetPosition; + float m_targetRotation; + uint64_t m_queueTime; + + QueuedZoning( uint16_t targetZone, const Common::FFXIVARR_POSITION3& targetPosition, uint64_t queuedTime, float targetRotation ) + : m_targetZone( targetZone ) + , m_targetPosition( targetPosition ) + , m_queueTime( queuedTime ) + , m_targetRotation( targetRotation ) {} +}; + +/** Class representing the Player +* Inheriting from Actor +* +*/ +class Player : public Actor +{ +public: + /*! Contructor */ + Player(); + + /*! Destructor */ + ~Player(); + + void autoAttack( ActorPtr pTarget ) override; + + // EventHandlers + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! start an event action */ + void eventActionStart( uint32_t eventId, uint32_t action, ActionCallback finishCallback, ActionCallback interruptCallback, uint64_t additional ); + /*! start an event item action */ + void eventItemActionStart( uint32_t eventId, uint32_t action, ActionCallback finishCallback, ActionCallback interruptCallback, uint64_t additional ); + /*! start/register a normal event */ + void eventStart( uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventParam, uint8_t eventParam1, uint32_t eventParam2 ); + /*! play a subevent */ + void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2, uint32_t eventParam3 ); + /*! play a subevent */ + void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, + uint32_t eventParam2, uint32_t eventParam3, Event::EventHandler::SceneReturnCallback eventReturnCallback ); + /*! play a subevent */ + void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, + uint32_t eventParam2, uint32_t eventParam3, uint32_t eventParam4, + Event::EventHandler::SceneReturnCallback eventReturnCallback ); + /*! play a subevent */ + void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, + Event::EventHandler::SceneReturnCallback eventReturnCallback ); + /*! play a subevent */ + void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags ); + /*! finish / unregister an event */ + void eventFinish( uint32_t eventId, uint32_t freePlayer ); + /*! add an event to the event array */ + void addEvent( Event::EventHandlerPtr pEvent ); + /*! retrieve an event from the event array */ + Event::EventHandlerPtr getEvent( uint32_t eventId ); + /*! get number of active events */ + size_t getEventCount(); + /*! remove an event from the event array */ + void removeEvent( uint32_t eventId ); + /*! return the eventlist */ + std::map< uint32_t, Event::EventHandlerPtr >& eventList(); + + void checkEvent( uint32_t eventId ); + + + + // Events + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! Event to be called when zoning process gets triggered */ + void onZoneStart(); + /*! Event to be called when zoning process is finished */ + void onZoneDone(); + /*! Event to be called on login */ + void onLogin(); + /*! Event to be called on update tick */ + void onTick() override; + /*! Event to be called upon player death */ + void onDeath() override; + /*! Event called on every session iteration */ + void update( int64_t currTime ) override; + /*! Event to be called upon Bnpc kill */ + void onMobKill( uint16_t nameId ); + + + // Quest + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! load data for currently active quests */ + bool loadActiveQuests(); + /*! update quest ( register it as active quest if new ) */ + void updateQuest( uint16_t questId, uint8_t sequence ); + /*! return true if quest is currently active */ + bool hasQuest( uint16_t questId ); + /*! return the current quest sequence */ + uint8_t getQuestSeq( uint16_t questId ); + /*! send the quest tracker packet */ + void sendQuestTracker(); + /*! set quest tracker flag for a specified slot */ + void setQuestTracker( uint16_t index, int16_t flag ); + /*! return the index of a given quest in the players quest list */ + int8_t getQuestIndex( uint16_t questId ); + /*! finish a given quest */ + void finishQuest( uint16_t questId ); + /*! finish a given quest */ + void unfinishQuest( uint16_t questId ); + /*! remove a given quest */ + void removeQuest( uint16_t questId ); + /*! add a quest to the completed quests mask */ + void updateQuestsCompleted( uint32_t questId ); + /*! remove a quest from the completed quest mask */ + void removeQuestsCompleted( uint32_t questId ); + /*! get the curent opening sequence */ + uint8_t getOpeningSequence() const; + /*! set te current opening sequence */ + void setOpeningSequence( uint8_t seq ); + + bool giveQuestRewards( uint32_t questId, uint32_t optionalChoice ); + + boost::shared_ptr< Common::QuestActive > getQuestActive( uint16_t index ); + + uint8_t getQuestUI8A( uint16_t questId ); + uint8_t getQuestUI8B( uint16_t questId ); + uint8_t getQuestUI8C( uint16_t questId ); + uint8_t getQuestUI8D( uint16_t questId ); + uint8_t getQuestUI8E( uint16_t questId ); + uint8_t getQuestUI8F( uint16_t questId ); + uint8_t getQuestUI8AH( uint16_t questId ); + uint8_t getQuestUI8BH( uint16_t questId ); + uint8_t getQuestUI8CH( uint16_t questId ); + uint8_t getQuestUI8DH( uint16_t questId ); + uint8_t getQuestUI8EH( uint16_t questId ); + uint8_t getQuestUI8FH( uint16_t questId ); + uint8_t getQuestUI8AL( uint16_t questId ); + uint8_t getQuestUI8BL( uint16_t questId ); + uint8_t getQuestUI8CL( uint16_t questId ); + uint8_t getQuestUI8DL( uint16_t questId ); + uint8_t getQuestUI8EL( uint16_t questId ); + uint8_t getQuestUI8FL( uint16_t questId ); + uint16_t getQuestUI16A( uint16_t questId ); + uint16_t getQuestUI16B( uint16_t questId ); + uint16_t getQuestUI16C( uint16_t questId ); + uint32_t getQuestUI32A( uint16_t questId ); + + uint8_t getQuestBitFlag8( uint16_t questId ); + uint8_t getQuestBitFlag16( uint16_t questId ); + uint8_t getQuestBitFlag24( uint16_t questId ); + uint8_t getQuestBitFlag32( uint16_t questId ); + uint8_t getQuestBitFlag40( uint16_t questId ); + uint8_t getQuestBitFlag48( uint16_t questId ); + + + void setQuestUI8A( uint16_t questId, uint8_t val ); + void setQuestUI8B( uint16_t questId, uint8_t val ); + void setQuestUI8C( uint16_t questId, uint8_t val ); + void setQuestUI8D( uint16_t questId, uint8_t val ); + void setQuestUI8E( uint16_t questId, uint8_t val ); + void setQuestUI8F( uint16_t questId, uint8_t val ); + void setQuestUI8AH( uint16_t questId, uint8_t val ); + void setQuestUI8BH( uint16_t questId, uint8_t val ); + void setQuestUI8CH( uint16_t questId, uint8_t val ); + void setQuestUI8DH( uint16_t questId, uint8_t val ); + void setQuestUI8EH( uint16_t questId, uint8_t val ); + void setQuestUI8FH( uint16_t questId, uint8_t val ); + void setQuestUI8AL( uint16_t questId, uint8_t val ); + void setQuestUI8BL( uint16_t questId, uint8_t val ); + void setQuestUI8CL( uint16_t questId, uint8_t val ); + void setQuestUI8DL( uint16_t questId, uint8_t val ); + void setQuestUI8EL( uint16_t questId, uint8_t val ); + void setQuestUI8FL( uint16_t questId, uint8_t val ); + void setQuestUI16A( uint16_t questId, uint16_t val ); + void setQuestUI16B( uint16_t questId, uint16_t val ); + void setQuestUI16C( uint16_t questId, uint16_t val ); + void setQuestUI32A( uint16_t questId, uint32_t val ); + + void setQuestBitFlag8( uint16_t questId, uint8_t val ); + void setQuestBitFlag16( uint16_t questId, uint8_t val ); + void setQuestBitFlag24( uint16_t questId, uint8_t val ); + void setQuestBitFlag32( uint16_t questId, uint8_t val ); + void setQuestBitFlag40( uint16_t questId, uint8_t val ); + void setQuestBitFlag48( uint16_t questId, uint8_t val ); + + // Inventory / Item / Currency + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! add an item to the first free slot in one of the 4 main containers */ + bool tryAddItem( uint16_t catalogId, uint32_t quantity ); + /*! add an item to a given container */ + bool addItem( uint16_t containerId, uint16_t catalogId, uint32_t quantity ); + /*! equip an item to a specified slot */ + void equipItem( Inventory::EquipSlot equipSlotId, ItemPtr pItem, bool sendModel ); + /*! remove an item from an equipment slot */ + void unequipItem( Inventory::EquipSlot equipSlotId, ItemPtr pItem ); + /*! equip a weapon, possibly forcing a job change */ + void equipWeapon( ItemPtr pItem ); + /*! get player ilvl */ + uint16_t getItemLevel() const; + /*! send player ilvl */ + void sendItemLevel(); + /*! get a const pointer to the inventory object */ + InventoryPtr getInventory() const; + /*! get the current main hand model */ + uint64_t getModelMainWeapon() const; + /*! get the current off hand model */ + uint64_t getModelSubWeapon() const; + /*! get the current system hand model */ + uint64_t getModelSystemWeapon() const; + /*! return a const pointer to the model array */ + const uint32_t* getModelArray() const; + /*! return the equipment model in a specified equipment slot */ + uint32_t getModelForSlot( Inventory::EquipSlot slot ); + /*! set the equipment model in a specified equipment slot */ + void setModelForSlot( Inventory::EquipSlot slot, uint32_t val ); + /*! return the current amount of currency of type */ + uint32_t getCurrency( uint8_t type ) const; + /*! add amount to the currency of type */ + void addCurrency( uint8_t type, uint32_t amount ); + /*! remove amount from the currency of type */ + void removeCurrency( uint8_t type, uint32_t amount ); + /*! return the current amount of crystals of type */ + uint32_t getCrystal( uint8_t type ) const; + /*! add amount to the crystals of type */ + void addCrystal( uint8_t type, uint32_t amount ); + /*! remove amount from the crystals of type */ + void removeCrystal( uint8_t type, uint32_t amount ); + + // Class / Job / Exp + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! returns the level of the currently active class / job */ + uint8_t getLevel() const override; + /*! returns the level of the provided class / job */ + uint8_t getLevelForClass( Common::ClassJob pClass ) const; + /*! returns the exp of the currently active class / job */ + uint32_t getExp() const; + /*! sets the exp of the currently active class / job */ + void setExp( uint32_t amount ); + /*! adds exp to the currently active class / job */ + void gainExp( uint32_t amount ); + /*! gain a level on the currently active class / job */ + void gainLevel(); + /*! set level on the currently active class / job to given level */ + void setLevel( uint8_t level ); + /*! set level on the provided class / job to given level */ + void setLevelForClass( uint8_t level, Common::ClassJob classjob ); + /*! change class or job to given class / job */ + void setClassJob( Common::ClassJob classJob ); + /*! returns a pointer to the class array */ + uint16_t* getClassArray(); + /*! returns a const pointer to the class array */ + const uint16_t* getClassArray() const; + /*! returns a pointer to the exp array */ + uint32_t* getExpArray(); + /*! returns a const pointer to the exp array */ + const uint32_t* getExpArray() const; + + // Base Look / Stats / Params + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! return the birth day */ + uint8_t getBirthDay() const; + /*! return the birth month */ + uint8_t getBirthMonth() const; + /*! return the guardian diety Id */ + uint8_t getGuardianDeity() const; + /*! get look at specified index */ + uint8_t getLookAt( uint8_t index ) const; + /*! return the race */ + uint8_t getRace() const; + /*! return gender 0 male, 1 female */ + uint8_t getGender() const; + /*! return the id of the home town */ + uint8_t getStartTown() const; + /*! return the voice id */ + uint8_t getVoiceId() const; + /*! return the grand company */ + uint8_t getGc() const; + /*! return the grand company rank */ + const uint8_t* getGcRankArray() const; + /*! set look at index */ + void setLookAt( uint8_t index, uint8_t value ); + /*! set the voice Id */ + void setVoiceId( uint8_t voiceId ); + /*! set the grand company */ + void setGc( uint8_t gc ); + /*! set the grand company rank */ + void setGcRankAt( uint8_t index, uint8_t rank ); + /*! return a const pointer to the look array */ + const uint8_t* getLookArray() const; + /*! returns true if the player is currently in combat */ + bool isInCombat() const; + /*! sets players combat state */ + void setInCombat( bool mode ); + /*! return current online status depending on current state / activity */ + Common::OnlineStatus getOnlineStatus(); + /*! sets the players zone, initiating a zoning process */ + void setZone( uint32_t zoneId ); + + void forceZoneing( uint32_t zoneId ); + /*! return player to preset homepoint */ + void returnToHomepoint(); + /*! change position, sends update too */ + void changePosition( float x, float y, float z, float o ); + /*! return the contentId */ + uint64_t getContentId() const; + /*! return max hp */ + uint32_t getMaxHp(); + /*! return max mp */ + uint32_t getMaxMp(); + /*! return a players total play time */ + uint32_t getPlayTime() const; + /*! return true if the player has "new adventurere" status */ + bool isNewAdventurer() const; + /*! change the players "new adventurere" status */ + void setNewAdventurer( bool state ); + /*! sets the list of current online status */ + void setOnlineStatusMask( uint64_t status ); + /*! returns the current online status */ + uint64_t getOnlineStatusMask() const; + /*! perform a teleport of a specified type ( teleport,return,aethernet ) */ + void teleport( uint16_t aetheryteId, uint8_t type = 1 ); + /*! prepares zoning / fades out the screen */ + void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadoutTime = 0, uint16_t animation = 0 ); + /*! get player's title list (available titles) */ + uint8_t* getTitleList(); + /*! get player's active title */ + uint16_t getTitle() const; + /*! add title to player title list */ + void addTitle( uint16_t titleId ); + /*! change player's active title */ + void setTitle( uint16_t titleId ); + /*! change gear param state */ + void setEquipDisplayFlags( uint8_t state ); + /*! get gear param state */ + uint8_t getEquipDisplayFlags() const; + /*! mount the specified mount and send the packets */ + void mount( uint32_t id ); + /*! dismount the current mount and send the packets */ + void dismount(); + /*! get the current mount */ + uint8_t getCurrentMount() const; + + void calculateStats() override; + void sendStats(); + + + // Aetheryte / Action / Attribute bitmasks + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! register aetheryte aetheryteId and send update */ + void registerAetheryte( uint8_t aetheryteId ); + /*! check if aetheryte is already registered */ + bool isAetheryteRegistered( uint8_t aetheryteId ) const; + /*! return a const pointer to the aetheryte unlock bitmask array */ + int8_t getAetheryteMaskAt( uint8_t index ) const; + /*! return a pointer to the aetheryte unlock bitmask array */ + uint8_t* getAetheryteArray(); + /*! set homepoint */ + void setHomepoint( uint8_t aetheryteId ); + /*! get homepoint */ + uint8_t getHomepoint() const; + /*! discover subarea subid fo map map_id, also send udpate packet */ + void discover( int16_t map_id, int16_t sub_id ); + /*! return a pointer to the discovery bitmask array */ + uint8_t* getDiscoveryBitmask(); + /*! helper/debug function to reset all discovered areas */ + void resetDiscovery(); + /*! get a pointer to the howto bitmask array */ + uint8_t* getHowToArray(); + /*! get a const pointer to the howto bitmask array */ + const uint8_t* getHowToArray() const; + /*! update bitmask for how-to's seen */ + void updateHowtosSeen( uint32_t howToId ); + /*! learn an action / update the unlock bitmask. */ + void learnAction( uint8_t actionId ); + /*! learn a song / update the unlock bitmask. */ + void learnSong( uint8_t songId, uint32_t itemId ); + /*! check if an action is already unlocked in the bitmask. */ + bool isActionLearned( uint8_t actionId ) const; + /*! return a const pointer to the unlock bitmask array */ + const uint8_t* getUnlockBitmask() const; + /*! return a const pointer to the orchestrion bitmask array */ + const uint8_t* getOrchestrionBitmask() const; + /*! return a const pointer to the mount guide bitmask array */ + const uint8_t* getMountGuideBitmask() const; + + + // Spawn handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! initialize the spawnId queue */ + void initSpawnIdQueue(); + /*! get the spawn id mapped to a specific actorId */ + uint8_t getSpawnIdForActorId( uint32_t actorId ); + /*! assigns the given spawnId to the actor */ + void assignSpawnIdToPlayerId( uint32_t actorId, uint8_t spawnId ); + /*! frees the spawnId assigned to the given actor */ + void freePlayerSpawnId( uint32_t actorId ); + /*! send spawn packets to pTarget */ + void spawn( PlayerPtr pTarget ) override; + /*! send despawn packets to pTarget */ + void despawn( ActorPtr pTarget ) override; + + // Player State Handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /* return a const pointer to the state flag array */ + const uint8_t* getStateFlags() const; + /* set a specified state flag */ + void setStateFlag( Common::PlayerStateFlag flag ); + /* set a specified state flag */ + void setStateFlags( std::vector< Common::PlayerStateFlag > flags ); + /* check if a specified flag is set */ + bool hasStateFlag( Common::PlayerStateFlag flag ) const; + /* reset a specified flag */ + void unsetStateFlag( Common::PlayerStateFlag flag ); + /* helper function, send an empty state flag update */ + void unlock(); + + // Player Session Handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! return the userlevel */ + uint8_t getUserLevel() const; + /*! set timestamp for last received ping */ + void setLastPing( uint32_t ping ); + /*! get timestamp of last received ping */ + uint32_t getLastPing() const; + + // Player Database Handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! generate the update sql based on update flags */ + void updateSql(); + /*! load player from db, by id */ + bool load( uint32_t charId, SessionPtr pSession ); + /*! load active class data */ + bool loadClassData(); + /*! load search info */ + bool loadSearchInfo(); + + // Player Network Handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! send current models ( equipment ) */ + void sendModel(); + /*! send active state flags */ + void sendStateFlags(); + /*! send status update */ + void sendStatusUpdate( bool toSelf = true ) override; + /*! send the entire inventory sequence */ + void sendInventory() const; + /*! send active quest list */ + void sendQuestInfo(); + /*! send a quest specific message */ + void sendQuestMessage( uint32_t questId, int8_t msgId, uint8_t type, uint32_t var1, uint32_t var2 ); + /*! queue a packet for the player */ + void queuePacket( Network::Packets::GamePacketPtr pPacket ); + /*! queue a char connection packet for the player */ + void queueChatPacket( Network::Packets::GamePacketPtr pPacket ); + /*! returns true if loading is complete ( 0x69 has been received ) */ + bool isLoadingComplete() const; + /*! set the loading complete bool */ + void setLoadingComplete( bool bComplete ); + /*! mark this player for zoning, notify worldserver */ + void performZoning(uint16_t zoneId, const Common::FFXIVARR_POSITION3& pos, float rotation); + /*! return true if the player is marked for zoning */ + bool isMarkedForZoning() const; + + Common::ZoneingType getZoningType() const; + void setZoningType( Common::ZoneingType zoneingType ); + + void setSearchInfo( uint8_t selectRegion, uint8_t selectClass, const char* searchMessage ); + const char* getSearchMessage() const; + uint8_t getSearchSelectRegion() const; + uint8_t getSearchSelectClass() const; + + void sendNotice( const std::string& message ); + void sendUrgent( const std::string& message ); + void sendDebug( const std::string& message ); + + // Player Battle Handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + void onMobAggro( BattleNpcPtr pBNpc ); + void onMobDeaggro( BattleNpcPtr pBNpc ); + + void initHateSlotQueue(); + void hateListAdd( BattleNpcPtr pBNpc ); + void hateListRemove( BattleNpcPtr pBNpc ); + + bool hateListHasMob( BattleNpcPtr pBNpc ); + + void sendHateList(); + + bool actionHasCastTime( uint32_t actionId ); + + Core::Entity::ActorPtr lookupTargetById( uint64_t targetId ); + + bool isLogin() const; + void setIsLogin( bool bIsLogin ); + + uint16_t getZoneId() const; + + uint8_t getGmRank() const; + void setGmRank( uint8_t rank ); + + uint8_t getMode() const; + void setMode( uint8_t mode ); + + void setAutoattack( bool mode ); + bool isAutoattackOn() const; + + // Content Finder handling + ////////////////////////////////////////////////////////////////////////////////////////////////////// + /*! Get an unix time when the player can register into content finder again. */ + uint32_t getCFPenaltyTimestamp() const; + + /*! Set an unix time when the player can register into content finder again. */ + void setCFPenaltyTimestamp( uint32_t timestamp ); + + uint32_t getCFPenaltyMinutes() const; + void setCFPenaltyMinutes( uint32_t minutes ); + + void setEorzeaTimeOffset( uint64_t timestamp ); + + // Database + void updateDbAllQuests() const; + void deleteQuest( uint16_t questId ) const; + void insertQuest( uint16_t questId, uint8_t index, uint8_t seq ) const; + void updateDbSearchInfo() const; + void updateDbClass() const; + void insertDbClass( const uint8_t classJobIndex ) const; + + void setMarkedForRemoval(); + bool isMarkedForRemoval() const; + +private: + uint32_t m_lastWrite; + uint32_t m_lastPing; + + bool m_bIsLogin; + + uint64_t m_contentId; // This id will be the name of the folder for character settings in "My Games" + + uint8_t m_mode; + + bool m_markedForRemoval; + +private: + + uint8_t m_voice; + + uint64_t m_modelMainWeapon; + uint64_t m_modelSubWeapon; + uint64_t m_modelSystemWeapon; + + uint32_t m_modelEquip[10]; + + bool m_bNewGame; + + uint8_t m_guardianDeity; + uint8_t m_birthDay; + uint8_t m_birthMonth; + + struct RetainerInfo + { + uint32_t retainerId; + char retainerName[32]; + uint32_t createUnixTime; + bool isActive; + bool isRename; + uint8_t status; + } m_retainerInfo[8]; + + uint16_t m_activeTitle; + uint8_t m_titleList[48]; + uint8_t m_howTo[33]; + uint8_t m_minions[35]; + uint8_t m_mountGuide[14]; + uint8_t m_homePoint; + uint8_t m_startTown; + uint16_t m_townWarpFstFlags; + uint8_t m_questCompleteFlags[200]; + uint8_t m_discovery[420]; + uint32_t m_playTime; + + uint16_t m_classArray[25]; + uint32_t m_expArray[25]; + uint8_t m_aetheryte[16]; + uint8_t m_unlocks[64]; + uint8_t m_orchestrion[40]; + + uint8_t m_openingSequence; + + uint16_t m_itemLevel; + InventoryPtr m_pInventory; + + std::map< uint32_t, Event::EventHandlerPtr > m_eventMap; + std::map< uint32_t, uint8_t > m_playerIdToSpawnIdMap; // maps player to spawn id + std::queue< uint8_t > m_freeSpawnIdQueue; // queue with spawn ids free to be assigned + std::queue< uint8_t > m_freeHateSlotQueue; // queue with "hate slots" free to be assigned + std::map< uint32_t, uint8_t > m_actorIdTohateSlotMap; + + std::map< uint32_t, uint8_t > m_questIdToQuestIdx; // quest mapping, quest id to quest container index + std::map< uint8_t, uint32_t > m_questIdxToQuestId; // quest mapping, quest container index to questId + boost::shared_ptr< Common::QuestActive > m_activeQuests[30]; + int16_t m_questTracking[5]; + + uint8_t m_stateFlags[7]; + uint8_t m_gmRank; + uint16_t zoneId; + + uint8_t m_equipDisplayFlags; + + bool m_bInCombat; + bool m_bLoadingComplete; + bool m_bAutoattack; + + Common::ZoneingType m_zoningType; + + bool m_bMarkedForZoning; + bool m_bNewAdventurer; + uint64_t m_onlineStatus; + boost::shared_ptr< QueuedZoning > m_queuedZoneing; + + // search info + char m_searchMessage[193]; // searchmessage to show in profile + uint8_t m_searchSelectRegion; // regions selected to show up in profile + uint8_t m_searchSelectClass; // class selected to show up in profile + + // gc info + uint8_t m_gc; + uint8_t m_gcRank[3]; + + // content finder info + uint32_t m_cfPenaltyUntil; // unix time + + uint8_t m_mount; +}; + +} +} + +#endif diff --git a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp new file mode 100644 index 00000000..b1ec4f57 --- /dev/null +++ b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp @@ -0,0 +1,361 @@ +#include +#include +#include +#include +#include + +#include "Player.h" + +#include "Zone/Zone.h" + +#include "Forwards.h" + +#include "Network/GameConnection.h" +#include "Network/PacketWrappers/ActorControlPacket142.h" +#include "Network/PacketWrappers/InitUIPacket.h" +#include "Network/PacketWrappers/ServerNoticePacket.h" +#include "Network/PacketWrappers/EventStartPacket.h" +#include "Network/PacketWrappers/EventPlayPacket.h" +#include "Network/PacketWrappers/EventFinishPacket.h" + +#include "Action/EventAction.h" +#include "Action/EventItemAction.h" + +#include "Event/EventHandler.h" +#include "Event/EventHandler.h" +#include "ServerZone.h" + +extern Core::Logger g_log; +extern Core::ServerZone g_serverZone; + +using namespace Core::Common; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +void Core::Entity::Player::addEvent( Event::EventHandlerPtr pEvent ) +{ + m_eventMap[pEvent->getId()] = pEvent; +} + +std::map< uint32_t, Core::Event::EventHandlerPtr >& Core::Entity::Player::eventList() +{ + return m_eventMap; +} + +Core::Event::EventHandlerPtr Core::Entity::Player::getEvent( uint32_t eventId ) +{ + auto it = m_eventMap.find( eventId ); + if( it != m_eventMap.end() ) + return it->second; + + return Event::EventHandlerPtr( nullptr ); +} + +size_t Core::Entity::Player::getEventCount() +{ + return m_eventMap.size(); +} + +void Core::Entity::Player::removeEvent( uint32_t eventId ) +{ + auto it = m_eventMap.find( eventId ); + if( it != m_eventMap.end() ) + { + auto tmpEvent = it->second; + m_eventMap.erase( it ); + } +} + +void Core::Entity::Player::checkEvent( uint32_t eventId ) +{ + auto pEvent = getEvent( eventId ); + + if( pEvent && !pEvent->hasPlayedScene() ) + eventFinish( eventId, 1 ); +} + + +void Core::Entity::Player::eventStart( uint64_t actorId, uint32_t eventId, + Event::EventHandler::EventType eventType, uint8_t eventParam1, + uint32_t eventParam2 ) +{ + Event::EventHandlerPtr newEvent( new Event::EventHandler( actorId, eventId, eventType, eventParam2 ) ); + addEvent( newEvent ); + + setStateFlag( PlayerStateFlag::Occupied2 ); + sendStateFlags(); + + EventStartPacket eventStart( getId(), actorId, eventId, eventType, eventParam1, eventParam2 ); + + queuePacket( eventStart ); + +} + +void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, + uint32_t flags, uint32_t eventParam2, + uint32_t eventParam3 ) +{ + eventPlay( eventId, scene, flags, eventParam2, eventParam3, nullptr ); +} + +void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, + uint32_t flags, Event::EventHandler::SceneReturnCallback eventCallback ) +{ + eventPlay( eventId, scene, flags, 0, 0, eventCallback ); +} + +void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags ) +{ + eventPlay( eventId, scene, flags, 0, 0, nullptr ); +} + +void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, + uint32_t flags, uint32_t eventParam2, + uint32_t eventParam3, Event::EventHandler::SceneReturnCallback eventCallback ) +{ + if( flags & 0x02 ) + { + setStateFlag( PlayerStateFlag::WatchingCutscene ); + sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, + static_cast< uint8_t >( getOnlineStatus() ) ), true ); + } + + auto pEvent = getEvent( eventId ); + if( !pEvent && getEventCount() ) + { + // We're trying to play a nested event, need to start it first. + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); + pEvent = getEvent( eventId ); + } + else if( !pEvent ) + { + g_log.error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" ); + return; + } + + pEvent->setPlayedScene( true ); + pEvent->setEventReturnCallback( eventCallback ); + EventPlayPacket eventPlay( getId(), pEvent->getActorId(), pEvent->getId(), + scene, flags, eventParam2, eventParam3 ); + + queuePacket( eventPlay ); +} + +void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, + uint32_t flags, uint32_t eventParam2, + uint32_t eventParam3, uint32_t eventParam4, Event::EventHandler::SceneReturnCallback eventCallback ) +{ + if( flags & 0x02 ) + { + setStateFlag( PlayerStateFlag::WatchingCutscene ); + sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, + static_cast< uint8_t >( getOnlineStatus() ) ), true ); + } + + auto pEvent = getEvent( eventId ); + if( !pEvent && getEventCount() ) + { + // We're trying to play a nested event, need to start it first. + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); + pEvent = getEvent( eventId ); + } + else if( !pEvent ) + { + g_log.error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" ); + return; + } + + pEvent->setPlayedScene( true ); + pEvent->setEventReturnCallback( eventCallback ); + EventPlayPacket eventPlay( getId(), pEvent->getActorId(), pEvent->getId(), + scene, flags, eventParam2, eventParam3, eventParam4 ); + + queuePacket( eventPlay ); +} + +void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer ) +{ + auto pEvent = getEvent( eventId ); + + if( !pEvent ) + { + g_log.error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" ); + return; + } + + if( getEventCount() > 1 && pEvent->getEventType() != Event::EventHandler::Nest ) + { + // this is the parent of a nested event, we can't finish it until the parent finishes + return; + } + + switch( pEvent->getEventType() ) + { + case Event::EventHandler::Nest: + { + queuePacket( EventFinishPacket( getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam3() ) ); + removeEvent( pEvent->getId() ); + + auto events = eventList(); + + for( auto it : events ) + { + + if( it.second->hasPlayedScene() == false ) + { + // TODO: not happy with this, this is also prone to break wit more than one remaining event in there + queuePacket( EventFinishPacket( getId(), it.second->getId(), it.second->getEventType(), it.second->getEventParam3() ) ); + removeEvent( it.second->getId() ); + } + } + + break; + } + default: + { + queuePacket( EventFinishPacket( getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam3() ) ); + break; + } + } + + if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) ) + { + unsetStateFlag( PlayerStateFlag::WatchingCutscene ); + sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, + static_cast< uint8_t >( getOnlineStatus() ) ), true ); + } + + removeEvent( pEvent->getId() ); + + if( freePlayer == 1 ) + { + unsetStateFlag( PlayerStateFlag::Occupied2 ); + sendStateFlags(); + } +} + +void Core::Entity::Player::eventActionStart( uint32_t eventId, + uint32_t action, + ActionCallback finishCallback, + ActionCallback interruptCallback, + uint64_t additional ) +{ + Action::ActionPtr pEventAction( new Action::EventAction( shared_from_this(), eventId, action, + finishCallback, interruptCallback, additional ) ); + + setCurrentAction( pEventAction ); + auto pEvent = getEvent( eventId ); + + if( !pEvent && getEventCount() ) + { + // We're trying to play a nested event, need to start it first. + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); + pEvent = getEvent( eventId ); + } + else if( !pEvent ) + { + g_log.error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" ); + return; + } + + if( pEvent ) + pEvent->setPlayedScene( true ); + pEventAction->onStart(); +} + + +void Core::Entity::Player::eventItemActionStart( uint32_t eventId, + uint32_t action, + ActionCallback finishCallback, + ActionCallback interruptCallback, + uint64_t additional ) +{ + Action::ActionPtr pEventItemAction( new Action::EventItemAction( shared_from_this(), eventId, action, + finishCallback, interruptCallback, additional ) ); + + setCurrentAction( pEventItemAction ); + + pEventItemAction->onStart(); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Core::Entity::Player::onLogin() +{ + for( auto& child : g_serverZone.getConfig()->getChild( "Settings.Parameters.MotDArray" ) ) + { + sendNotice( child.second.data() ); + } +} + +void Core::Entity::Player::onZoneStart() +{ + +} + +void Core::Entity::Player::onZoneDone() +{ + +} + +void Core::Entity::Player::onDeath() +{ + +} + + +// TODO: slightly ugly here and way too static. Needs too be done properly +void Core::Entity::Player::onTick() +{ + + bool sendUpdate = false; + + if( !isAlive() || !isLoadingComplete() ) + return; + + uint32_t addHp = static_cast< uint32_t >( getMaxHp() * 0.1f + 1 ); + uint32_t addMp = static_cast< uint32_t >( getMaxMp() * 0.06f + 1 ); + uint32_t addTp = 100; + + if( !m_actorIdTohateSlotMap.empty() ) + { + addHp = static_cast< uint32_t >( getMaxHp() * 0.01f + 1 ); + addMp = static_cast< uint32_t >( getMaxMp() * 0.02f + 1 ); + addTp = 60; + } + + if( m_hp < getMaxHp() ) + { + + if( m_hp + addHp < getMaxHp() ) + m_hp += addHp; + else + m_hp = getMaxHp(); + + sendUpdate = true; + } + + if( m_mp < getMaxMp() ) + { + + if( m_mp + addMp < getMaxMp() ) + m_mp += addMp; + else + m_mp = getMaxMp(); + + sendUpdate = true; + } + + if( m_tp < 1000 ) + { + if( m_tp + addTp < 1000 ) + m_tp += addTp; + else + m_tp = 1000; + + sendUpdate = true; + } + + if( sendUpdate ) + sendStatusUpdate(); +} diff --git a/src/servers/sapphire_zone/Event/EventHelper.cpp b/src/servers/sapphire_zone/Event/EventHelper.cpp new file mode 100644 index 00000000..6438ab6f --- /dev/null +++ b/src/servers/sapphire_zone/Event/EventHelper.cpp @@ -0,0 +1,72 @@ +#include "EventHelper.h" +#include "EventHandler.h" +#include +#include + +extern Core::Data::ExdData g_exdData; + +using namespace Core::Common; + +std::string Core::Event::getEventName( uint32_t eventId ) +{ + uint16_t eventType = eventId >> 16; + + auto unknown = std::string{ "unknown" }; + + switch( eventType ) + { + case EventType::Quest: + { + auto questInfo = g_exdData.getQuestInfo( eventId ); + if( !questInfo ) + return unknown + "Quest"; + + std::string name = questInfo->name_intern; + std::size_t pos = name.find_first_of( "_" ); + + return questInfo->name_intern.substr( 0, pos ); + } + case EventType::CustomTalk: + { + auto customTalkInfo = g_exdData.getCustomTalkInfo( eventId ); + if( !customTalkInfo ) + return unknown + "CustomTalk"; + + std::string name = customTalkInfo->name_intern; + std::size_t pos = name.find_first_of( "_" ); + + return customTalkInfo->name_intern.substr( 0, pos ); + } + case EventType::Opening: + { + auto openingInfo = g_exdData.getOpeningInfo( eventId ); + if( openingInfo ) + return openingInfo->name; + return unknown + "Opening"; + } + case EventType::Aetheryte: + { + auto aetherInfo = g_exdData.getAetheryteInfo( eventId & 0xFFFF ); + if( aetherInfo->isAetheryte ) + return "Aetheryte"; + return "Aethernet"; + } + case EventType::Warp: + { + return "ChocoboTaxi"; + } + default: + { + return unknown; + } + } +} + +uint32_t Core::Event::mapEventActorToRealActor( uint32_t eventActorId ) +{ + auto levelInfo = g_exdData.getLevelInfo( eventActorId ); + if( levelInfo ) + return levelInfo->actor_id; + + return 0; +} diff --git a/src/servers/sapphire_zone/Forwards.h b/src/servers/sapphire_zone/Forwards.h new file mode 100644 index 00000000..40fcc5c0 --- /dev/null +++ b/src/servers/sapphire_zone/Forwards.h @@ -0,0 +1,81 @@ +#ifndef _FORWARDS_H +#define _FORWARDS_H + +#include +#include + +#define TYPE_FORWARD( x ) \ +class x; \ +typedef boost::shared_ptr< x > x ## Ptr; \ +typedef std::vector< x > x ## PtrList; + +namespace Core +{ + TYPE_FORWARD( Cell ); + TYPE_FORWARD( Zone ); + TYPE_FORWARD( Item ); + TYPE_FORWARD( ItemContainer ); + TYPE_FORWARD( Inventory ); + TYPE_FORWARD( Session ); + TYPE_FORWARD( XMLConfig ); + TYPE_FORWARD( ZonePosition ) + + namespace StatusEffect + { + TYPE_FORWARD( StatusEffect ); + TYPE_FORWARD( StatusEffectContainer ); + } + + namespace Entity + { + TYPE_FORWARD( Actor ); + TYPE_FORWARD( Player ); + TYPE_FORWARD( BattleNpc ); + TYPE_FORWARD( BattleNpcTemplate ); + } + + namespace Event + { + TYPE_FORWARD( EventHandler ); + } + + namespace Action + { + TYPE_FORWARD( Action ); + TYPE_FORWARD( ActionTeleport ); + TYPE_FORWARD( ActionCast ); + TYPE_FORWARD( ActionMount ); + TYPE_FORWARD( EventAction ); + } + + namespace Network + { + TYPE_FORWARD( Hive ); + TYPE_FORWARD( Acceptor ); + TYPE_FORWARD( Connection ); + TYPE_FORWARD( GameConnection ); + TYPE_FORWARD( SessionConnection ); + TYPE_FORWARD( CustomMsgClientConnection ); + + namespace Packets + { + TYPE_FORWARD( GamePacket ); + } + } + + namespace ContentFinder + { + TYPE_FORWARD( ContentFinder ); + } + + namespace Scripting + { + class NativeScriptManager; + } + + typedef std::function< void( Entity::Player&, uint32_t, uint64_t ) > ActionCallback; + +} + + +#endif diff --git a/src/servers/sapphire_zone/Script/ScriptManager.cpp b/src/servers/sapphire_zone/Script/ScriptManager.cpp new file mode 100644 index 00000000..3073c2e5 --- /dev/null +++ b/src/servers/sapphire_zone/Script/ScriptManager.cpp @@ -0,0 +1,483 @@ +#include +#include +#include + +#include "NativeScriptManager.h" + +#include "Zone/Zone.h" +#include "Actor/Player.h" +#include "Actor/BattleNpc.h" +#include "ServerZone.h" +#include "Event/EventHandler.h" +#include "Event/EventHelper.h" +#include "StatusEffect/StatusEffect.h" +#include "Network/PacketWrappers/ServerNoticePacket.h" +#include "Script/ScriptManager.h" + +#include +#include +#include +#include +#include + + +// enable the ambiguity fix for every platform to avoid #define nonsense +#define WIN_AMBIGUITY_FIX +#include + +extern Core::Logger g_log; +extern Core::Data::ExdData g_exdData; +extern Core::ServerZone g_serverZone; + +Core::Scripting::ScriptManager::ScriptManager() : + m_firstScriptChangeNotificiation( false ) +{ + m_nativeScriptManager = createNativeScriptMgr(); +} + +Core::Scripting::ScriptManager::~ScriptManager() +{ + Watchdog::unwatchAll(); +} + +void Core::Scripting::ScriptManager::update() +{ + m_nativeScriptManager->processLoadQueue(); +} + +bool Core::Scripting::ScriptManager::init() +{ + std::set< std::string > files; + + loadDir( g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.Path", "./compiledscripts/" ), + files, m_nativeScriptManager->getModuleExtension() ); + + uint32_t scriptsFound = 0; + uint32_t scriptsLoaded = 0; + + for( auto itr = files.begin(); itr != files.end(); ++itr ) + { + auto& path = *itr; + + scriptsFound++; + + if( m_nativeScriptManager->loadScript( path ) ) + scriptsLoaded++; + } + + g_log.info( "ScriptManager: Loaded " + std::to_string( scriptsLoaded ) + "/" + std::to_string( scriptsFound ) + " scripts successfully" ); + + watchDirectories(); + + return true; +} + +void Core::Scripting::ScriptManager::watchDirectories() +{ + Watchdog::watchMany( g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.Path", "./compiledscripts/" ) + "*" + m_nativeScriptManager->getModuleExtension(), + [ this ]( const std::vector< ci::fs::path >& paths ) + { + if( !m_firstScriptChangeNotificiation ) + { + // for whatever reason, the first time this runs, it detects every file as changed + // so we're always going to ignore the first notification + m_firstScriptChangeNotificiation = true; + return; + } + + for( auto path : paths ) + { + if( m_nativeScriptManager->isModuleLoaded( path.stem().string() ) ) + { + g_log.debug( "Reloading changed script: " + path.stem().string() ); + + m_nativeScriptManager->queueScriptReload( path.stem( ).string( )); + } + else + { + g_log.debug( "Loading new script: " + path.stem().string() ); + + m_nativeScriptManager->loadScript( path.string() ); + } + } + }); +} + +void Core::Scripting::ScriptManager::loadDir( const std::string& dirname, std::set &files, const std::string& ext ) +{ + + g_log.info( "ScriptEngine: loading scripts from " + dirname ); + + boost::filesystem::path targetDir( dirname ); + + boost::filesystem::directory_iterator iter( targetDir ); + boost::filesystem::directory_iterator eod; + + BOOST_FOREACH( boost::filesystem::path const& i, make_pair( iter, eod ) ) + { + if( is_regular_file( i ) && boost::filesystem::extension( i.string() ) == ext ) + { + files.insert( i.string() ); + } + } +} + +void Core::Scripting::ScriptManager::onPlayerFirstEnterWorld( Entity::Player& player ) +{ +// try +// { +// std::string test = m_onFirstEnterWorld( player ); +// } +// catch( const std::exception &e ) +// { +// std::string what = e.what(); +// g_log.Log( LoggingSeverity::error, what ); +// } +} + +bool Core::Scripting::ScriptManager::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, + uint32_t bnpcNameId, uint32_t modelId, std::string aiName ) +{ + return g_serverZone.registerBnpcTemplate( templateName, bnpcBaseId, bnpcNameId, modelId, aiName ); +} + +bool Core::Scripting::ScriptManager::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ) +{ + std::string eventName = "onTalk"; + std::string objName = Event::getEventName( eventId ); + + player.sendDebug( "Actor: " + + std::to_string( actorId ) + " -> " + + std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) + + " \neventId: " + + std::to_string( eventId ) + + " (0x" + boost::str( boost::format( "%|08X|" ) + % static_cast< uint64_t >( eventId & 0xFFFFFFF ) ) + ")" ); + + uint16_t eventType = eventId >> 16; + uint32_t scriptId = eventId; + + // aethernet/aetherytes need to be handled separately + if( eventType == Common::EventType::Aetheryte ) + { + auto aetherInfo = g_exdData.getAetheryteInfo( eventId & 0xFFFF ); + scriptId = EVENTSCRIPT_AETHERYTE_ID; + if( !aetherInfo->isAetheryte ) + scriptId = EVENTSCRIPT_AETHERNET_ID; + } + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, scriptId ); + if( script ) + { + player.sendDebug( "Calling: " + objName + "." + eventName ); + + player.eventStart( actorId, eventId, Event::EventHandler::Talk, 0, 0 ); + + script->onTalk( eventId, player, actorId ); + + player.checkEvent( eventId ); + } + else + { + if ( eventType == Common::EventType::Quest ) + { + auto questInfo = g_exdData.getQuestInfo( eventId ); + if ( questInfo ) + { + player.sendUrgent( "Quest not implemented: " + questInfo->name + " (" + questInfo->name_intern + ")" ); + + } + } + + return false; + } + + return true; +} + +bool Core::Scripting::ScriptManager::onEnterTerritory( Entity::Player& player, uint32_t eventId, + uint16_t param1, uint16_t param2 ) +{ + std::string eventName = "onEnterTerritory"; + std::string objName = Event::getEventName( eventId ); + + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + if( script ) + { + player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() ); + + script->onEnterZone( player, eventId, param1, param2 ); + + player.checkEvent( eventId ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1, + float x, float y, float z ) +{ + + std::string eventName = "onWithinRange"; + std::string objName = Event::getEventName( eventId ); + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) + " p1: " + std::to_string( param1 ) ); + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + if( script ) + { + player.eventStart( player.getId(), eventId, Event::EventHandler::WithinRange, 1, param1 ); + + script->onWithinRange( player, eventId, param1, x, y, z ); + + player.checkEvent( eventId ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onOutsideRange( Entity::Player& player, uint32_t eventId, uint32_t param1, + float x, float y, float z ) +{ + std::string eventName = "onOutsideRange"; + std::string objName = Event::getEventName( eventId ); + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + if( script ) + { + player.eventStart( player.getId(), eventId, Event::EventHandler::WithinRange, 1, param1 ); + + script->onOutsideRange( player, eventId, param1, x, y, z ); + + player.checkEvent( eventId ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onEmote( Entity::Player& player, uint64_t actorId, + uint32_t eventId, uint8_t emoteId ) +{ + std::string eventName = "onEmote"; + std::string objName = Event::getEventName( eventId ); + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + if( script ) + { + player.sendDebug( "Calling: " + objName + "." + eventName ); + + player.eventStart( actorId, eventId, Event::EventHandler::Emote, 0, emoteId ); + + script->onEmote( actorId, eventId, emoteId, player ); + + player.checkEvent( eventId ); + } + else + { + uint16_t eventType = eventId >> 16; + + if( eventType == Common::EventType::Quest ) + { + auto questInfo = g_exdData.getQuestInfo( eventId ); + if( questInfo ) + { + player.sendUrgent( "Quest not implemented: " + questInfo->name ); + return false; + } + } + return false; + } + + return true; +} + +bool Core::Scripting::ScriptManager::onEventHandlerReturn( Entity::Player& player, uint32_t eventId, + uint16_t subEvent, uint16_t param1, uint16_t param2, + uint16_t param3 ) +{ + + player.sendDebug( "eventId: " + + std::to_string( eventId ) + + " ( 0x" + boost::str( boost::format( "%|08X|" ) % ( uint64_t ) ( eventId & 0xFFFFFFF ) ) + " ) " + + " scene: " + std::to_string( subEvent ) + + " p1: " + std::to_string( param1 ) + + " p2: " + std::to_string( param2 ) + + " p3: " + std::to_string( param3 ) ); + + try + { + auto pEvent = player.getEvent( eventId ); + if( pEvent ) + { + pEvent->setPlayedScene( false ); + // try to retrieve a stored callback + auto eventCallback = pEvent->getEventReturnCallback(); + // if there is one, proceed to call it + if( eventCallback ) + { + eventCallback( player, eventId, param1, param2, param3 ); + if( !pEvent->hasPlayedScene() ) + player.eventFinish( eventId, 1 ); + else + pEvent->setPlayedScene( false ); + } + // else, finish the event. + else + player.eventFinish( eventId, 1 ); + } + } + catch( std::exception& e ) + { + player.sendNotice( e.what() ); + return false; + } + + return true; +} + +bool Core::Scripting::ScriptManager::onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId, + uint16_t subEvent, uint16_t param, uint32_t catalogId ) +{ + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + if( script ) + { + script->onEventHandlerTradeReturn( player, eventId, subEvent, param, catalogId ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onEventItem( Entity::Player& player, uint32_t eventItemId, + uint32_t eventId, uint32_t castTime, uint64_t targetId ) +{ + std::string eventName = "onEventItem"; + std::string objName = Event::getEventName( eventId ); + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + if( script ) + { + player.eventStart( targetId, eventId, Event::EventHandler::Item, 0, 0 ); + + script->onEventItem( player, eventItemId, eventId, castTime, targetId ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onMobKill( Entity::Player& player, uint16_t nameId ) +{ + std::string eventName = "onBnpcKill_" + std::to_string( nameId ); + + + // loop through all active quests and try to call available onMobKill callbacks + for( size_t i = 0; i < 30; i++ ) + { + auto activeQuests = player.getQuestActive( static_cast< uint16_t >( i ) ); + if( !activeQuests ) + continue; + + uint16_t questId = activeQuests->c.questId; + + auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, questId ); + if( script ) + { + std::string objName = Event::getEventName( 0x00010000 | questId ); + + player.sendDebug("Calling: " + objName + "." + eventName); + + script->onNpcKill( nameId, player ); + } + } + + return true; +} + +bool Core::Scripting::ScriptManager::onCastFinish( Entity::Player& player, Entity::ActorPtr pTarget, uint32_t actionId ) +{ + auto script = m_nativeScriptManager->getScript< ActionScript >( ScriptType::ScriptedAction, actionId ); + + if( script ) + script->onCastFinish( player, *pTarget ); + + return true; +} + +bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId ) +{ + auto script = m_nativeScriptManager->getScript< StatusEffectScript >( ScriptType::ScriptedStatusEffect, effectId ); + + if( script ) + { + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendDebug( "Calling status receive for statusid: " + std::to_string( effectId ) ); + + script->onApply( *pActor ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect ) +{ + auto script = m_nativeScriptManager->getScript< StatusEffectScript >( ScriptType::ScriptedStatusEffect, effect.getId() ); + if( script ) + { + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + std::to_string( effect.getId() ) ); + + script->onTick( *pActor ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId ) +{ + auto script = m_nativeScriptManager->getScript< StatusEffectScript >( ScriptType::ScriptedStatusEffect, effectId ); + if( script ) + { + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendDebug( "Calling status timeout for statusid: " + std::to_string( effectId ) ); + + script->onExpire( *pActor ); + + return true; + } + + return false; +} + +bool Core::Scripting::ScriptManager::onZoneInit( ZonePtr pZone ) +{ + auto script = m_nativeScriptManager->getScript< ZoneScript >( ScriptType::ScriptedZone, pZone->getId() ); + if( script ) + { + script->onZoneInit(); + + return true; + } + + return false; +} + +Scripting::NativeScriptManager& Core::Scripting::ScriptManager::getNativeScriptHandler() +{ + return *m_nativeScriptManager; +} diff --git a/src/world/Event/Director.cpp b/src/world/Event/Director.cpp index 864bf0e3..79e7142b 100644 --- a/src/world/Event/Director.cpp +++ b/src/world/Event/Director.cpp @@ -1,197 +1 @@ #include "Director.h" - -#include -#include -#include - -#include "Actor/Player.h" - -#include "Network/PacketWrappers/ActorControlPacket.h" -#include "Network/PacketWrappers/ActorControlSelfPacket.h" -#include - - -using namespace Sapphire::Common; -using namespace Sapphire::Network::Packets; -using namespace Sapphire::Network::Packets::Server; -using namespace Sapphire::Network::ActorControl; - -Sapphire::Event::Director::Director( Sapphire::Event::Director::DirectorType type, uint16_t contentId ) : - m_contentId( contentId ), - m_type( type ), - m_directorId( ( static_cast< uint32_t >( type ) << 16 ) | contentId ), - m_sequence( 1 ), - m_branch( 0 ), - m_elapsedTime( 0 ) -{ - memset( m_unionData.arrData, 0, sizeof( m_unionData ) ); -} - -uint32_t Sapphire::Event::Director::getDirectorId() const -{ - return m_directorId; -} - -uint16_t Sapphire::Event::Director::getContentId() const -{ - return m_contentId; -} - -uint8_t Sapphire::Event::Director::getSequence() const -{ - return m_sequence; -} - -void Sapphire::Event::Director::sendDirectorClear( Sapphire::Entity::Player& player ) const -{ - player.queuePacket( makeActorControlSelf( player.getId(), DirectorClear, m_directorId ) ); -} - -void Sapphire::Event::Director::sendDirectorVars( Sapphire::Entity::Player& player ) const -{ - auto varPacket = makeZonePacket< FFXIVIpcDirectorVars >( player.getId() ); - varPacket->data().m_directorId = getDirectorId(); - varPacket->data().m_sequence = getSequence(); - varPacket->data().m_branch = 0; - memcpy( varPacket->data().m_unionData, m_unionData.arrData, sizeof( varPacket->data().m_unionData ) ); - player.queuePacket( varPacket ); -} - -void Sapphire::Event::Director::sendDirectorInit( Sapphire::Entity::Player& player ) const -{ - Logger::debug( "DirectorID#{}, QuestBattleID#{}", m_directorId, m_contentId ); - player.queuePacket( makeActorControlSelf( player.getId(), DirectorInit, m_directorId, m_contentId ) ); -} - -Sapphire::Event::Director::DirectorType Sapphire::Event::Director::getType() const -{ - return m_type; -} - -uint8_t Sapphire::Event::Director::getBranch() const -{ - return m_branch; -} - -void Sapphire::Event::Director::setDirectorUI8AL( uint8_t value ) -{ - m_unionData.ui8lh.UI8AL = value; -} - -void Sapphire::Event::Director::setDirectorUI8AH( uint8_t value ) -{ - m_unionData.ui8lh.UI8AH = value; -} - -void Sapphire::Event::Director::setDirectorUI8BL( uint8_t value ) -{ - m_unionData.ui8lh.UI8BL = value; -} - -void Sapphire::Event::Director::setDirectorUI8BH( uint8_t value ) -{ - m_unionData.ui8lh.UI8BH = value; -} - -void Sapphire::Event::Director::setDirectorUI8CL( uint8_t value ) -{ - m_unionData.ui8lh.UI8CL = value; -} - -void Sapphire::Event::Director::setDirectorUI8CH( uint8_t value ) -{ - m_unionData.ui8lh.UI8CH = value; -} - -void Sapphire::Event::Director::setDirectorUI8DL( uint8_t value ) -{ - m_unionData.ui8lh.UI8DL = value; -} - -void Sapphire::Event::Director::setDirectorUI8DH( uint8_t value ) -{ - m_unionData.ui8lh.UI8DH = value; -} - -void Sapphire::Event::Director::setDirectorUI8EL( uint8_t value ) -{ - m_unionData.ui8lh.UI8EL = value; -} - -void Sapphire::Event::Director::setDirectorUI8EH( uint8_t value ) -{ - m_unionData.ui8lh.UI8EH = value; -} - -void Sapphire::Event::Director::setDirectorUI8FL( uint8_t value ) -{ - m_unionData.ui8lh.UI8FL = value; -} - -void Sapphire::Event::Director::setDirectorUI8FH( uint8_t value ) -{ - m_unionData.ui8lh.UI8FH = value; -} - -void Sapphire::Event::Director::setDirectorUI8GL( uint8_t value ) -{ - m_unionData.ui8lh.UI8GL = value; -} - -void Sapphire::Event::Director::setDirectorUI8GH( uint8_t value ) -{ - m_unionData.ui8lh.UI8GH = value; -} - -void Sapphire::Event::Director::setDirectorUI8HL( uint8_t value ) -{ - m_unionData.ui8lh.UI8HL = value; -} - -void Sapphire::Event::Director::setDirectorUI8HH( uint8_t value ) -{ - m_unionData.ui8lh.UI8HH = value; -} - -void Sapphire::Event::Director::setDirectorUI8IL( uint8_t value ) -{ - m_unionData.ui8lh.UI8IL = value; -} - -void Sapphire::Event::Director::setDirectorUI8IH( uint8_t value ) -{ - m_unionData.ui8lh.UI8IH = value; -} - -void Sapphire::Event::Director::setDirectorUI8JL( uint8_t value ) -{ - m_unionData.ui8lh.UI8JL = value; -} - -void Sapphire::Event::Director::setDirectorUI8JH( uint8_t value ) -{ - m_unionData.ui8lh.UI8JH = value; -} - -void Sapphire::Event::Director::setDirectorBranch( uint8_t value ) -{ - m_branch = value; -} - -void Sapphire::Event::Director::setDirectorSequence( uint8_t value ) -{ - m_sequence = value; -} - -void Sapphire::Event::Director::setCustomVar( uint32_t varId, uint32_t value ) -{ - m_customVarMap[ varId ] = value; -} - -uint32_t Sapphire::Event::Director::getCustomVar( uint32_t varId ) -{ - auto it = m_customVarMap.find( varId ); - if( it != m_customVarMap.end() ) - return it->second; - return 0; -} \ No newline at end of file diff --git a/src/world/Event/Director.h b/src/world/Event/Director.h index 38970984..11af59fe 100644 --- a/src/world/Event/Director.h +++ b/src/world/Event/Director.h @@ -1,192 +1,45 @@ #ifndef SAPPHIRE_DIRECTOR_H #define SAPPHIRE_DIRECTOR_H -#include +#include -#include "ForwardsZone.h" +#include "Forwards.h" -namespace Sapphire::Event +namespace Core { +namespace Event { + +/*! +\class Director +\brief Base class for all Directors implements sequence and variables + +\author Mordred +*/ + +class Director { +private: + /*! Id of the director */ + uint32_t m_id; - /*! - \class Director - \brief Base class for all Directors implements sequence and variables + /*! currect sequence */ + uint8_t m_sequence; - */ + /*! current branch */ + uint8_t m_branch; - class Director - { + /*! raw storage for flags/vars */ + uint8_t m_unionData[10]; - public: - enum DirectorType - { - BattleLeve = 0x8001, - GatheringLeve = 0x8002, - InstanceContent = 0x8003, // used for dungeons/raids - PublicContent = 0x8004, - QuestBattle = 0x8006, - CompanyLeve = 0x8007, - TreasureHunt = 0x8009, - GoldSaucer = 0x800A, - CompanyCraftDirector = 0x800B, - DpsChallange = 0x800D, - Fate = 0x801A - }; +public: + uint8_t getId() const; + uint8_t getSequence() const; - enum DirectorState - { - Created, - DutyReset, - DutyInProgress, - DutyFinished, - DutyFailed - }; +}; - Director( DirectorType type, uint16_t contentId ); - - uint32_t getDirectorId() const; - - uint16_t getContentId() const; - - DirectorType getType() const; - - uint8_t getSequence() const; - - uint8_t getBranch() const; - - void sendDirectorInit( Entity::Player& player ) const; - - void sendDirectorClear( Entity::Player& player ) const; - - void sendDirectorVars( Entity::Player& player ) const; - - void setDirectorUI8AL( uint8_t value ); - - void setDirectorUI8AH( uint8_t value ); - - void setDirectorUI8BL( uint8_t value ); - - void setDirectorUI8BH( uint8_t value ); - - void setDirectorUI8CL( uint8_t value ); - - void setDirectorUI8CH( uint8_t value ); - - void setDirectorUI8DL( uint8_t value ); - - void setDirectorUI8DH( uint8_t value ); - - void setDirectorUI8EL( uint8_t value ); - - void setDirectorUI8EH( uint8_t value ); - - void setDirectorUI8FL( uint8_t value ); - - void setDirectorUI8FH( uint8_t value ); - - void setDirectorUI8GL( uint8_t value ); - - void setDirectorUI8GH( uint8_t value ); - - void setDirectorUI8HL( uint8_t value ); - - void setDirectorUI8HH( uint8_t value ); - - void setDirectorUI8IL( uint8_t value ); - - void setDirectorUI8IH( uint8_t value ); - - void setDirectorUI8JL( uint8_t value ); - - void setDirectorUI8JH( uint8_t value ); - - void setDirectorSequence( uint8_t value ); - - void setDirectorBranch( uint8_t value ); - - void setCustomVar( uint32_t varId, uint32_t value ); - uint32_t getCustomVar( uint32_t varId ); - - private: - /*! Id of the content of the director */ - uint16_t m_contentId; - - /*! DirectorType | ContentId */ - uint32_t m_directorId; - - /*! currect sequence */ - uint8_t m_sequence; - - /*! current branch */ - uint8_t m_branch; - - union - { - struct UI8LH - { - uint8_t UI8AL : 4; - uint8_t UI8AH : 4; - uint8_t UI8BL : 4; - uint8_t UI8BH : 4; - uint8_t UI8CL : 4; - uint8_t UI8CH : 4; - uint8_t UI8DL : 4; - uint8_t UI8DH : 4; - uint8_t UI8EL : 4; - uint8_t UI8EH : 4; - uint8_t UI8FL : 4; - uint8_t UI8FH : 4; - uint8_t UI8GL : 4; - uint8_t UI8GH : 4; - uint8_t UI8HL : 4; - uint8_t UI8HH : 4; - uint8_t UI8IL : 4; - uint8_t UI8IH : 4; - uint8_t UI8JL : 4; - uint8_t UI8JH : 4; - } ui8lh; - - struct UI8 - { - uint8_t UI8A; - uint8_t UI8B; - uint8_t UI8C; - uint8_t UI8D; - uint8_t UI8E; - uint8_t UI8F; - uint8_t UI8G; - uint8_t UI8H; - uint8_t UI8I; - uint8_t UI8J; - } ui8; - - struct FLAGS - { - uint8_t flags80; - uint8_t flags72; - uint8_t flags64; - uint8_t flags56; - uint8_t flags48; - uint8_t flags40; - uint8_t flags32; - uint8_t flags24; - uint8_t flags16; - uint8_t flags8; - } flags; - - /*! raw storage for flags/vars */ - uint8_t arrData[10]; - } m_unionData; - - /*! type of the director */ - DirectorType m_type; - - uint32_t m_elapsedTime; - - std::unordered_map< uint32_t, uint32_t > m_customVarMap; - - }; } +} + + #endif //SAPPHIRE_DIRECTOR_H diff --git a/src/world/Event/EventHandler.cpp b/src/world/Event/EventHandler.cpp index 81c66836..f863c6e3 100644 --- a/src/world/Event/EventHandler.cpp +++ b/src/world/Event/EventHandler.cpp @@ -1,95 +1,65 @@ #include "EventHandler.h" -Sapphire::Event::EventHandler::EventHandler( uint64_t actorId, uint32_t eventId, - EventType eventType, uint32_t eventParam ) : - m_actorId( actorId ), - m_eventId( eventId ), - m_eventType( eventType ), - m_playedScene( false ) +Core::Event::EventHandler::EventHandler( uint64_t actorId, uint32_t eventId, EventType eventType, uint32_t eventParam3 ) : + m_actorId( actorId ), + m_eventId( eventId ), + m_eventType( eventType ), + m_playedScene( false ) { - m_entryId = static_cast< uint16_t >( eventId ); - m_type = static_cast< uint16_t >( eventId >> 16 ); - m_eventParam = eventParam; - m_returnCallback = nullptr; + m_entryId = static_cast< uint16_t >( eventId ); + m_type = static_cast< uint16_t >( eventId >> 16 ); + + m_eventParam3 = eventParam3; + + m_callback = nullptr; } -uint64_t Sapphire::Event::EventHandler::getActorId() const +uint64_t Core::Event::EventHandler::getActorId() const { - return m_actorId; + return m_actorId; } -uint32_t Sapphire::Event::EventHandler::getId() const +uint32_t Core::Event::EventHandler::getId() const { - return m_eventId; + return m_eventId; } -uint8_t Sapphire::Event::EventHandler::getEventType() const +uint8_t Core::Event::EventHandler::getEventType() const { - return m_eventType; + return m_eventType; } -uint16_t Sapphire::Event::EventHandler::getType() const +uint16_t Core::Event::EventHandler::getType() const { - return m_type; + return m_type; } -uint16_t Sapphire::Event::EventHandler::getEntryId() const +uint16_t Core::Event::EventHandler::getEntryId() const { - return m_entryId; + return m_entryId; } -uint32_t Sapphire::Event::EventHandler::getEventParam() const +uint32_t Core::Event::EventHandler::getEventParam3() const { - return m_eventParam; + return m_eventParam3; } -Sapphire::Event::EventHandler::SceneReturnCallback Sapphire::Event::EventHandler::getEventReturnCallback() const +Core::Event::EventHandler::SceneReturnCallback Core::Event::EventHandler::getEventReturnCallback() const { - return m_returnCallback; + return m_callback; } -void Sapphire::Event::EventHandler::setEventReturnCallback( SceneReturnCallback callback ) +void Core::Event::EventHandler::setEventReturnCallback( SceneReturnCallback callback ) { - m_returnCallback = callback; + m_callback = callback; } -Sapphire::Event::EventHandler::SceneChainCallback Sapphire::Event::EventHandler::getSceneChainCallback() const +bool Core::Event::EventHandler::hasPlayedScene() const { - return m_chainCallback; + return m_playedScene; } -void Sapphire::Event::EventHandler::setSceneChainCallback( Sapphire::Event::EventHandler::SceneChainCallback callback ) +void Core::Event::EventHandler::setPlayedScene( bool playedScene ) { - m_chainCallback = callback; + m_playedScene = playedScene; } - -Sapphire::Event::EventHandler::EventFinishCallback Sapphire::Event::EventHandler::getEventFinishCallback() const -{ - return m_finishCallback; -} - -void Sapphire::Event::EventHandler::setEventFinishCallback( EventFinishCallback callback ) -{ - m_finishCallback = callback; -} - -bool Sapphire::Event::EventHandler::hasPlayedScene() const -{ - return m_playedScene; -} - -void Sapphire::Event::EventHandler::setPlayedScene( bool playedScene ) -{ - m_playedScene = playedScene; -} - -bool Sapphire::Event::EventHandler::hasNestedEvent() const -{ - return m_pNestedEvent != nullptr; -} - -void Sapphire::Event::EventHandler::removeNestedEvent() -{ - m_pNestedEvent.reset(); -} - diff --git a/src/world/Event/EventHandler.h b/src/world/Event/EventHandler.h index 9bec90a4..5720d6f9 100644 --- a/src/world/Event/EventHandler.h +++ b/src/world/Event/EventHandler.h @@ -1,142 +1,106 @@ #ifndef _EVENT_H #define _EVENT_H -#include "ForwardsZone.h" +#include "../Forwards.h" -namespace Sapphire::Event -{ +namespace Core { + namespace Event { - struct SceneResult - { - uint64_t actorId; - uint32_t eventId; - uint16_t param1; - uint16_t param2; - uint16_t param3; - uint16_t param4; - }; + class EventHandler + { + public: + enum EventType : uint8_t + { + Talk = 1, + Emote = 2, + DistanceBelow = 3, + DistanceOver = 4, + BattleReward = 5, + Craft = 6, + Nest = 7, + Item = 8, + Drop = 9, + WithinRange = 10, + OutsideRange = 11, + GameStart = 12, + GameProgress = 13, + EnterTerritory = 15, + GameComeBack = 17, + ActionResult = 18, + MateriaCraft = 19, + Fishing = 20, + UI = 21, + Housing = 22, + Say = 23, + TableGame = 24, + }; - class EventHandler - { - public: - enum EventType : uint8_t - { - Talk = 1, - Emote = 2, - DistanceBelow = 3, - DistanceOver = 4, - BattleReward = 5, - Craft = 6, - Nest = 7, - Item = 8, - Drop = 9, - WithinRange = 10, - OutsideRange = 11, - GameStart = 12, - GameProgress = 13, - EnterTerritory = 15, - GameComeBack = 17, - ActionResult = 18, - MateriaCraft = 19, - Fishing = 20, - UI = 21, - Housing = 22, - Say = 23, - TableGame = 24, - }; + enum EventHandlerType : uint16_t + { + Quest = 0x0001, + Warp = 0x0002, + Shop = 0x0004, + Aetheryte = 0x0005, + GuildLeveAssignment = 0x0006, + DefaultTalk = 0x0009, + CustomTalk = 0x000B, + CompanyLeveOfficer = 0x000C, + CraftLeve = 0x000E, + GimmickAccessor = 0x000F, + GimmickBill = 0x0010, + GimmickRect = 0x0011, + ChocoboTaxiStand = 0x0012, + Opening = 0x0013, + ExitRange = 0x0014, + GCShop = 0x0016, + GuildOrderGuide = 0x0017, + GuildOrderOfficer = 0x0018, + ContentNpc = 0x0019, + Story = 0x001A, + SpecialShop = 0x001B, + BahamutGuide = 0x001C, + FcTalk = 0x001F, + }; - enum class EventHandlerType : uint16_t - { - Quest = 0x0001, - Warp = 0x0002, - GatheringPoint = 0x0003, // Came up in the client with "Begin" unsure that means - Shop = 0x0004, - Aetheryte = 0x0005, - GuildLeveAssignment = 0x0006, - DefaultTalk = 0x0009, - Craft = 0x000A, - CustomTalk = 0x000B, - CompanyLeveOfficer = 0x000C, - Array = 0x000D, - CraftLeve = 0x000E, - GimmickAccessor = 0x000F, - GimmickBill = 0x0010, - GimmickRect = 0x0011, - ChocoboTaxiStand = 0x0012, - Opening = 0x0013, - ExitRange = 0x0014, - Fishing = 0x0015, - GCShop = 0x0016, - GuildOrderGuide = 0x0017, - GuildOrderOfficer = 0x0018, - ContentNpc = 0x0019, - Story = 0x001A, - SpecialShop = 0x001B, - BahamutGuide = 0x001C, - InstanceContentGuide = 0x001D, - HousingAethernet = 0x001E, - FcTalk = 0x001F, - Adventure = 0x0021, - DailyQuestSupply = 0x0022, - ICDirector = 0x8003, - QuestBattleDirector = 0x8006, - }; + using SceneReturnCallback = std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t ) > ; - using SceneReturnCallback = std::function< void( Entity::Player&, const SceneResult& ) >; - using SceneChainCallback = std::function< void( Entity::Player& ) >; - using EventFinishCallback = std::function< void( Entity::Player&, uint64_t ) >; + EventHandler( uint64_t actorId, uint32_t eventId, EventType eventType, uint32_t eventParam3 ); - EventHandler( uint64_t actorId, uint32_t eventId, EventType eventType, uint32_t eventParam ); + ~EventHandler() {} - ~EventHandler() - { - } + uint64_t getActorId() const; - uint64_t getActorId() const; + uint32_t getId() const; - uint32_t getId() const; + uint16_t getType() const; - uint16_t getType() const; + uint16_t getEntryId() const; - uint16_t getEntryId() const; + uint8_t getEventType() const; - uint8_t getEventType() const; + uint32_t getEventParam3() const; - uint32_t getEventParam() const; + bool hasPlayedScene() const; - bool hasPlayedScene() const; + void setPlayedScene( bool playedScene ); - void setPlayedScene( bool playedScene ); + SceneReturnCallback getEventReturnCallback() const; - SceneReturnCallback getEventReturnCallback() const; + void setEventReturnCallback( SceneReturnCallback callback ); - void setEventReturnCallback( SceneReturnCallback callback ); - SceneChainCallback getSceneChainCallback() const; - void setSceneChainCallback( SceneChainCallback callback ); - - EventFinishCallback getEventFinishCallback() const; - - void setEventFinishCallback( EventFinishCallback callback ); - - bool hasNestedEvent() const; - - void removeNestedEvent(); - - protected: - uint64_t m_actorId; - uint32_t m_eventId; - uint16_t m_entryId; - uint16_t m_type; - uint8_t m_eventType; - uint32_t m_eventParam; - EventHandlerPtr m_pNestedEvent; - bool m_playedScene; - SceneReturnCallback m_returnCallback; - SceneChainCallback m_chainCallback; - EventFinishCallback m_finishCallback; - }; + protected: + uint64_t m_actorId; + uint32_t m_eventId; + uint16_t m_entryId; + uint16_t m_type; + uint8_t m_eventType; + uint32_t m_eventParam3; + bool m_playedScene; + SceneReturnCallback m_callback; + }; + } } #endif