From 635a393e14e36554e76276a63b95059146d72dbd Mon Sep 17 00:00:00 2001 From: MetricExpansion <> Date: Tue, 3 Nov 2020 00:17:32 -0800 Subject: [PATCH] Added some preliminary work on location detection. --- include/ArmorAddonOverrideService.h | 4 +- src/ArmorAddonOverrideService.cpp | 6 +- src/OutfitSystem.cpp | 84 +++++++++++++++++++ src/papyrus/skyoutsysquicksloteffect.psc | 3 + src/papyrus/skyrimoutfitsystemnativefuncs.psc | 9 +- 5 files changed, 100 insertions(+), 6 deletions(-) diff --git a/include/ArmorAddonOverrideService.h b/include/ArmorAddonOverrideService.h index 0500437..64024f1 100644 --- a/include/ArmorAddonOverrideService.h +++ b/include/ArmorAddonOverrideService.h @@ -73,7 +73,7 @@ class ArmorAddonOverrideService { cobb::istring currentOutfitName = g_noOutfitName; std::unordered_map outfits; // Location-based switching - bool locationBasedAutoswitchEnabled = false; + bool locationBasedAutoSwitchEnabled = false; std::map locationOutfits; // static ArmorAddonOverrideService& GetInstance() { @@ -94,7 +94,7 @@ class ArmorAddonOverrideService { void renameOutfit(const char* oldName, const char* newName); // throws name_conflict if the new name is already taken; can throw bad_name; throws std::out_of_range if the oldName doesn't exist void setOutfit(const char* name); // - void setLocationBasedAutoswitchEnabled(bool) noexcept; + void setLocationBasedAutoSwitchEnabled(bool) noexcept; void setOutfitUsingLocation(LocationType location); void setLocationOutfit(LocationType location, const char* name); void unsetLocationOutfit(LocationType location); diff --git a/src/ArmorAddonOverrideService.cpp b/src/ArmorAddonOverrideService.cpp index b18a1ae..3e64501 100644 --- a/src/ArmorAddonOverrideService.cpp +++ b/src/ArmorAddonOverrideService.cpp @@ -191,12 +191,12 @@ void ArmorAddonOverrideService::setOutfit(const char* name) { } } -void ArmorAddonOverrideService::setLocationBasedAutoswitchEnabled(bool newValue) noexcept { - locationBasedAutoswitchEnabled = newValue; +void ArmorAddonOverrideService::setLocationBasedAutoSwitchEnabled(bool newValue) noexcept { + locationBasedAutoSwitchEnabled = newValue; } void ArmorAddonOverrideService::setOutfitUsingLocation(LocationType location) { - if (locationBasedAutoswitchEnabled) { + if (locationBasedAutoSwitchEnabled) { auto it = locationOutfits.find(location); if (it != locationOutfits.end()) { this->setOutfit(it->second.c_str()); diff --git a/src/OutfitSystem.cpp b/src/OutfitSystem.cpp index d923a20..6c2275c 100644 --- a/src/OutfitSystem.cpp +++ b/src/OutfitSystem.cpp @@ -15,6 +15,9 @@ #include "RE/AI/AIProcess.h" #include "RE/Inventory/InventoryChanges.h" #include "RE/Inventory/InventoryEntryData.h" +#include "RE/FormComponents/TESForm/BGSLocation.h" +#include "RE/FormComponents/TESForm/BGSKeyword/BGSKeyword.h" +#include "RE/Misc/Misc.h" #include "ArmorAddonOverrideService.h" @@ -567,6 +570,51 @@ auto& service = ArmorAddonOverrideService::GetInstance(); service.setOutfit(name.data); } + void SetLocationBasedAutoSwitchEnabled(VMClassRegistry* registry, UInt32 stackId, StaticFunctionTag*, bool) { + + } + bool GetLocationBasedAutoSwitchEnabled(VMClassRegistry* registry, UInt32 stackId, StaticFunctionTag*) { + return false; + } + void SetOutfitUsingLocation(VMClassRegistry* registry, UInt32 stackId, StaticFunctionTag*, BGSLocation* location_skse) { + // Location can be NULL. + std::set keywords; + if (location_skse) { + auto location = (RE::BGSLocation*) location_skse; + std::uint32_t max = location->GetNumKeywords(); + for (std::uint32_t i = 0; i < max; i++) { + RE::BGSKeyword* keyword = location->GetKeywordAt(i).value(); + char message[100]; + _MESSAGE("Location has Keyword %s", keyword->GetFormEditorID()); + sprintf(message, "Location has Keyword %s", keyword->GetFormEditorID()); + RE::DebugNotification(message, nullptr, false); + keywords.insert(keyword->GetFormEditorID()); + } + } + // Location Type Logic + std::string type; + if (keywords.empty()) { + type = "worldcell"; + } else if (keywords.count("LocTypeHabitation")) { + type = "town"; + } else if (keywords.count("LocTypeDungeon")) { + type = "dungeon"; + } else { + type = "worldcell"; + } + char message[100]; + sprintf(message, "This location is a %s.", type.c_str()); + RE::DebugNotification(message, nullptr, false); + } + void SetLocationOutfit(VMClassRegistry* registry, UInt32 stackId, StaticFunctionTag*, UInt32 location, BSFixedString name) { + + } + void UnsetLocationOutfit(VMClassRegistry* registry, UInt32 stackId, StaticFunctionTag*, UInt32 location) { + + } + BSFixedString GetLocationOutfit(VMClassRegistry* registry, UInt32 stackId, StaticFunctionTag*, UInt32 location) { + return ""; + } } @@ -790,5 +838,41 @@ bool OutfitSystem::RegisterPapyrus(VMClassRegistry* registry) { SetSelectedOutfit, registry )); + registry->RegisterFunction(new NativeFunction1( + "SetLocationBasedAutoSwitchEnabled", + "SkyrimOutfitSystemNativeFuncs", + SetLocationBasedAutoSwitchEnabled, + registry + )); + registry->RegisterFunction(new NativeFunction0( + "GetLocationBasedAutoSwitchEnabled", + "SkyrimOutfitSystemNativeFuncs", + GetLocationBasedAutoSwitchEnabled, + registry + )); + registry->RegisterFunction(new NativeFunction1( + "SetOutfitUsingLocation", + "SkyrimOutfitSystemNativeFuncs", + SetOutfitUsingLocation, + registry + )); + registry->RegisterFunction(new NativeFunction2( + "SetLocationOutfit", + "SkyrimOutfitSystemNativeFuncs", + SetLocationOutfit, + registry + )); + registry->RegisterFunction(new NativeFunction1( + "UnsetLocationOutfit", + "SkyrimOutfitSystemNativeFuncs", + UnsetLocationOutfit, + registry + )); + registry->RegisterFunction(new NativeFunction1( + "GetLocationOutfit", + "SkyrimOutfitSystemNativeFuncs", + GetLocationOutfit, + registry + )); return true; } \ No newline at end of file diff --git a/src/papyrus/skyoutsysquicksloteffect.psc b/src/papyrus/skyoutsysquicksloteffect.psc index 344fc4c..d517794 100644 --- a/src/papyrus/skyoutsysquicksloteffect.psc +++ b/src/papyrus/skyoutsysquicksloteffect.psc @@ -1,6 +1,9 @@ Scriptname SkyOutSysQuickslotEffect extends activemagiceffect Event OnEffectStart(Actor akCaster, Actor akTarget) + + SkyrimOutfitSystemNativeFuncs.SetOutfitUsingLocation(akCaster.GetCurrentLocation()) + String[] sLMenuItems = SkyrimOutfitSystemNativeFuncs.ListOutfits(favoritesOnly = true) sLMenuItems = SkyrimOutfitSystemNativeFuncs.NaturalSort_ASCII(sLMenuItems) UIListMenu menu = UIExtensions.GetMenu("UIListMenu") as UIListMenu diff --git a/src/papyrus/skyrimoutfitsystemnativefuncs.psc b/src/papyrus/skyrimoutfitsystemnativefuncs.psc index c0afbf2..5d9ad02 100644 --- a/src/papyrus/skyrimoutfitsystemnativefuncs.psc +++ b/src/papyrus/skyrimoutfitsystemnativefuncs.psc @@ -75,4 +75,11 @@ Bool Function RenameOutfit (String asOutfitName, String asRenameTo) Glo Bool Function OutfitExists (String asOutfitName) Global Native Function OverwriteOutfit (String asOutfitName, Armor[] akArmors) Global Native Function SetEnabled (Bool abEnabled) Global Native - Function SetSelectedOutfit (String asOutfitName) Global Native \ No newline at end of file + Function SetSelectedOutfit (String asOutfitName) Global Native + + Function SetLocationBasedAutoSwitchEnabled (Bool abEnabled) Global Native +Bool Function GetLocationBasedAutoSwitchEnabled () Global Native + Function SetOutfitUsingLocation (Location alLocation) Global Native + Function SetLocationOutfit (Int aiLocationType, String asOutfitName) Global Native + Function UnsetLocationOutfit (Int aiLocationType) Global Native +String Function GetLocationOutfit (Int aiLocationType) Global Native