#pragma once #include #include #include struct Skills { enum Skill : std::uint32_t { kOneHanded = 0, kTwoHanded = 1, kArchery = 2, kBlock = 3, kSmithing = 4, kHeavyArmor = 5, kLightArmor = 6, kPickpocket = 7, kLockpicking = 8, kSneak = 9, kAlchemy = 10, kSpeech = 11, kAlteration = 12, kConjuration = 13, kDestruction = 14, kIllusion = 15, kRestoration = 16, kEnchanting = 17, kTotal }; static const Skill GetSkillFromActorValue(int32_t aActorValue) noexcept { switch (aActorValue) { case ActorValueInfo::kOneHanded: return kOneHanded; case ActorValueInfo::kTwoHanded: return kTwoHanded; case ActorValueInfo::kMarksman: return kArchery; case ActorValueInfo::kBlock: return kBlock; case ActorValueInfo::kSmithing: return kSmithing; case ActorValueInfo::kHeavyArmor: return kHeavyArmor; case ActorValueInfo::kLightArmor: return kLightArmor; case ActorValueInfo::kPickpocket: return kPickpocket; case ActorValueInfo::kLockpicking: return kLockpicking; case ActorValueInfo::kSneak: return kSneak; case ActorValueInfo::kAlchemy: return kAlchemy; case ActorValueInfo::kSpeechcraft: return kSpeech; case ActorValueInfo::kAlteration: return kAlteration; case ActorValueInfo::kConjuration: return kConjuration; case ActorValueInfo::kDestruction: return kDestruction; case ActorValueInfo::kIllusion: return kIllusion; case ActorValueInfo::kRestoration: return kRestoration; case ActorValueInfo::kEnchanting: return kEnchanting; default: return kTotal; } } static const char* GetSkillString(Skill aSkill) noexcept { switch (aSkill) { case kOneHanded: return "One-handed"; case kTwoHanded: return "Two-handed"; case kArchery: return "Archery"; case kBlock: return "Block"; case kSmithing: return "Smithing"; case kHeavyArmor: return "Heavy armor"; case kLightArmor: return "Light armor"; case kPickpocket: return "Pickpocket"; case kLockpicking: return "Lockpicking"; case kSneak: return "Sneak"; case kAlchemy: return "Alchemy"; case kSpeech: return "Speech"; case kAlteration: return "Alteration"; case kConjuration: return "Conjuration"; case kDestruction: return "Destruction"; case kIllusion: return "Illusion"; case kRestoration: return "Restoration"; case kEnchanting: return "Enchanting"; default: return "UNKNOWN"; } } struct SkillData { float level; float xp; float levelThreshold; }; static_assert(sizeof(SkillData) == 0xC); float xp; float levelThreshold; SkillData skills[Skill::kTotal]; uint32_t legendaryLevels[Skill::kTotal]; }; struct TESQuest; struct PlayerCharacter : Actor { static constexpr FormType Type = FormType::Character; static int32_t LastUsedCombatSkill; static PlayerCharacter* Get() noexcept; static void SetGodMode(bool aSet) noexcept; const GameArray& GetTints() const noexcept; // TODO: there's an in game function for this in fallout 4, maybe also for skyrim? void SetDifficulty(const int32_t aDifficulty, bool aForceUpdate = true, bool aExpectGameDataLoaded = true) noexcept; void AddSkillExperience(int32_t aSkill, float aExperience) noexcept; float GetSkillExperience(Skills::Skill aSkill) const noexcept { return (*pSkills)->skills[aSkill].xp; } NiPoint3 RespawnPlayer() noexcept; void PayCrimeGoldToAllFactions() noexcept; void SetWaypoint(NiPoint3* apPosition, TESWorldSpace* apWorldSpace) noexcept; void RemoveWaypoint() noexcept; struct Objective { BSFixedString name; TESQuest* quest; }; struct ObjectiveInstance { Objective* instance; uint64_t instanceCount; }; uint8_t pad1[0x588 - sizeof(Actor)]; GameArray objectives; uint8_t pad588[0x9B0 - 0x598]; Skills** pSkills; uint8_t pad9B8[0xAC8 - 0x9B8]; TESForm* locationForm; uint8_t padAC8[0x28]; int32_t difficulty; uint8_t padAFC[0xB10 - 0xAFC]; GameArray baseTints; GameArray* overlayTints; uint8_t padPlayerEnd[0xBE0 - 0xB30]; }; static_assert(offsetof(PlayerCharacter, objectives) == 0x588); static_assert(offsetof(PlayerCharacter, pSkills) == 0x9B8); static_assert(offsetof(PlayerCharacter, locationForm) == 0xAD0); static_assert(offsetof(PlayerCharacter, baseTints) == 0xB18); static_assert(offsetof(PlayerCharacter, overlayTints) == 0xB30); static_assert(sizeof(PlayerCharacter) == 0xBE8);