diff --git a/TheriantrophistControlQuest optimization and graceful degradation.esp b/TheriantrophistControlQuest optimization and graceful degradation.esp new file mode 100644 index 00000000..9ef667e2 Binary files /dev/null and b/TheriantrophistControlQuest optimization and graceful degradation.esp differ diff --git a/scripts/_00e_theriantrophist_alchemycontrol.pex b/scripts/_00e_theriantrophist_alchemycontrol.pex index f0b4198f..e7509653 100644 Binary files a/scripts/_00e_theriantrophist_alchemycontrol.pex and b/scripts/_00e_theriantrophist_alchemycontrol.pex differ diff --git a/source/scripts/_00e_theriantrophist_alchemycontrol.psc b/source/scripts/_00e_theriantrophist_alchemycontrol.psc index 256f8d8c..0f80ad4b 100644 --- a/source/scripts/_00e_theriantrophist_alchemycontrol.psc +++ b/source/scripts/_00e_theriantrophist_alchemycontrol.psc @@ -64,6 +64,8 @@ MagicEffect Property AlchFortifyTwoHanded Auto MagicEffect Property AlchRestoreMagicka Auto MagicEffect Property AlchRestoreStamina Auto +FormList Property _00E_EmptyFormlist Auto + Int Property GreyAlchemist2PotionDurationLimitInSeconds = 180 Autoreadonly Hidden {The potion duration of all werewolf potions is limited to this amount if the player has the first and second perk grey alchemist} Int Property GreyAlchemist1PotionDurationLimitInSeconds = 120 Autoreadonly Hidden @@ -98,10 +100,10 @@ EndProperty bool bDoneDarkBlood = false bool bDoneChymikum = false -int PotionsMixedOnLastTest = 0 ; OBSOLETE AFTER 1.5.3.0. Needed for version update -int criticalSectionProcesses = 0 ; OBSOLETE AFTER 1.5.3.0. Needed for version update +Int curScriptVersion = 0 +Int Property LATEST_SCRIPT_VERSION = 4 AutoReadOnly -FormList Property _00E_EmptyFormlist Auto +bool bHasJContainers = false ;===================================================================================== @@ -116,7 +118,10 @@ Function _UpdatePotion(Potion item, Int count) Bool bIsTheriantrophistPotion = item.HasKeyword(_00E_Theriantrophist_Effect) MagicEffect firstTheriantrophistEffect = None - If bIsTheriantrophistPotion ; FRESHLY BREWN THERIANTROPHIST POTION + If bIsTheriantrophistPotion && EnderalLib.IsDLLLoaded() ; FRESHLY BREWN THERIANTROPHIST POTION + + Debug.Notification("Replacing theriantrophist potion") + PlayerREF.removeItem(item, count, abSilent = true) Bool bRemoveTheriantrophistEffects = False @@ -190,26 +195,37 @@ Function _UpdatePotion(Potion item, Int count) EndIf Potion newPotion = EnderalLib.CreatePotion(newEffects, newMagnitudes, newAreas, newDurations, nNewEffects) - If JFormMap.hasKey(RenamedPotions, newPotion) == False + + If bHasJContainers && JFormMap.hasKey(RenamedPotions, newPotion) == False _RenamePotion(newPotion, newEffects, nNewEffects, bRemoveTheriantrophistEffects) _SetPotionModel(newPotion, firstTheriantrophistEffect, newEffects[0]) EndIf + + GoToState("") ; skip OnItemAdded PlayerREF.addItem(newPotion, count, abSilent = true) + GoToState("InCrafting") If bRemoveTheriantrophistEffects == False _UpdateNQ11(newPotion) EndIf - Else ; COMMON POTION + return + + EndIf + if bHasJContainers && JFormMap.hasKey(RenamedPotions, item) == False ; COMMON POTION _RenamePotion(item, potionEffects, nPotionEffects, True) _SetPotionModel(item, None, potionEffects[0]) - EndIf + if bIsTheriantrophistPotion + _UpdateNQ11(item) + endif + EndFunction Function _RenamePotion(Potion p, MagicEffect[] potionEffects, Int nPotionEffects, Bool bCommonPotion) + Debug.Notification("Renaming potion") String name = "" If bCommonPotion @@ -349,21 +365,93 @@ EndFunction Function _UpdateInventoryFilters() + RemoveAllInventoryEventFilters() + AddInventoryEventFilter(_00E_EmptyFormlist) - Form[] aPotions = JFormMap.allKeysPArray(RenamedPotions) - int i = aPotions.length - while i > 0 - i -= 1 - AddInventoryEventFilter(aPotions[i]) + Int potionNames = RenamedPotions + Form k = JFormMap.nextKey(potionNames, previousKey = None, endKey = None) + while k != None + AddInventoryEventFilter(k) + k = JFormMap.nextKey(potionNames, k, endKey = None) endwhile - aPotions = JFormMap.allKeysPArray(ModelChangedPotions) - i = aPotions.length - while i > 0 - i -= 1 - AddInventoryEventFilter(aPotions[i]) +EndFunction + +Function _RestorePotionAttributes() + Debug.Notification("Restoring potion names") + + Potion k + + Int potionNames = RenamedPotions + k = JFormMap.nextKey(potionNames, previousKey = None, endKey = None) as Potion + while k != None + k.setName(JFormMap.getStr(potionNames, k)) + k = JFormMap.nextKey(potionNames, k, endKey = None) as Potion endwhile + + Int potionModels = ModelChangedPotions + k = JFormMap.nextKey(potionModels, previousKey = None, endKey = None) as Potion + while k != None + k.SetWorldModelPath(JFormMap.getStr(potionModels, k)) + k = JFormMap.nextKey(potionModels, k, endKey = None) as Potion + endwhile + +EndFunction + +Function _InitAchemyControl() + + ;Debug.Notification("AchemyControl init") + + GoToState("") + + int iSKSEVer = SKSE.GetVersion() + + if iSKSEVer < 2 + RemoveAllInventoryEventFilters() + bHasJContainers = false + ;Debug.Notification("SKSE is not loaded") + Debug.Trace("SKSE is not loaded, _00E_Theriantrophist_AlchemyControl is disabled") + return + endif + + bHasJContainers = ( (SKSE.GetPluginVersion("JContainers64") != -1) || (SKSE.GetPluginVersion("JContainersVR") != -1) ) + + if ! bHasJContainers && ! EnderalLib.IsDLLLoaded() + ; Both required components are missing, do not update version and disable everything + RemoveAllInventoryEventFilters() + UnregisterForAllMenus() + Debug.Trace("JContainers and fs.dll are not loaded, _00E_Theriantrophist_AlchemyControl is disabled.") + ;Debug.Notification("JContainers and fs.dll are not loaded") + return + endif + + ; Version update + If curScriptVersion < LATEST_SCRIPT_VERSION + Int oldScriptVersion = curScriptVersion + curScriptVersion = LATEST_SCRIPT_VERSION + + If oldScriptVersion < 4 + ;Debug.Notification("Updating AlchemyControl") + UnregisterForUpdate() + EndIf + EndIf + + ; Re-initialize everything to stay resilient to co-save deletion or corruption + + if bHasJContainers + RegisterForMenu("ContainerMenu") + RegisterForMenu("InventoryMenu") + RegisterForMenu("FavoritesMenu") + ;Debug.Trace("JContainers is loaded, hooking to menus") + else + RemoveAllInventoryEventFilters() + UnregisterForAllMenus() + Debug.Notification("JContainers is not loaded") + Debug.Trace("JContainers is not loaded, renaming and changing potion models is disabled") + endif + + RegisterForMenu("Crafting Menu") EndFunction @@ -378,7 +466,10 @@ Event OnMenuOpen(String MenuName) return endif - GoToState("InInventory") + if bHasJContainers + Debug.Notification("InInventory") + GoToState("InInventory") + endif EndEvent @@ -390,15 +481,18 @@ EndEvent State InCrafting Event OnBeginState() + ;Debug.Notification("RemoveAllInventoryEventFilters") RemoveAllInventoryEventFilters() EndEvent Event OnItemAdded(Form baseItem, int count, ObjectReference itemRef, ObjectReference source) + Debug.Notification("Added " + baseItem.GetName()) + Potion item = baseItem as Potion If item ; Ignore not-custom potions (with FormID not starting with 0xFF) or already registered potions - If (Math.LogicalAnd(item.GetFormID(), 0xFF000000) == 0xFF000000) && JFormMap.hasKey(RenamedPotions, item) == False + If (Math.LogicalAnd(item.GetFormID(), 0xFF000000) == 0xFF000000) && (!bHasJContainers || JFormMap.hasKey(RenamedPotions, item) == False) _UpdatePotion(item, count) EndIf EndIf @@ -406,7 +500,10 @@ State InCrafting EndEvent Event OnEndState() - _UpdateInventoryFilters() + if bHasJContainers && UI.IsMenuOpen("Crafting Menu") == false + Debug.Notification("_UpdateInventoryFilters") + _UpdateInventoryFilters() + endif EndEvent EndState @@ -415,6 +512,7 @@ State InInventory if dest != None return endif + Debug.Notification("Removed " + baseItem.GetName()) ; Probably a potion is consumed Potion item = baseItem as Potion if item @@ -430,49 +528,16 @@ State InInventory EndEvent EndState -Int curScriptVersion = 0 -Int Property LATEST_SCRIPT_VERSION = 4 AutoReadOnly - Event OnInit() curScriptVersion = LATEST_SCRIPT_VERSION - RegisterForMenu("ContainerMenu") - RegisterForMenu("InventoryMenu") - RegisterForMenu("FavoritesMenu") - RegisterForMenu("Crafting Menu") + _InitAchemyControl() EndEvent Event OnPlayerLoadGame() - GoToState("") - - ; Version update - If curScriptVersion < LATEST_SCRIPT_VERSION - Int oldScriptVersion = curScriptVersion - curScriptVersion = LATEST_SCRIPT_VERSION + _InitAchemyControl() - If oldScriptVersion < 4 - UnregisterForUpdate() - RegisterForMenu("ContainerMenu") - RegisterForMenu("InventoryMenu") - RegisterForMenu("FavoritesMenu") - RegisterForMenu("Crafting Menu") - _UpdateInventoryFilters() - EndIf - EndIf - - ; Restore names and models - Potion k - - Int potionNames = RenamedPotions - k = JFormMap.nextKey(potionNames, previousKey = None, endKey = None) as Potion - while k != None - k.setName(JFormMap.getStr(potionNames, k)) - k = JFormMap.nextKey(potionNames, k, endKey = None) as Potion - endwhile - - Int potionModels = ModelChangedPotions - k = JFormMap.nextKey(potionModels, previousKey = None, endKey = None) as Potion - while k != None - k.SetWorldModelPath(JFormMap.getStr(potionModels, k)) - k = JFormMap.nextKey(potionModels, k, endKey = None) as Potion - endwhile + if bHasJContainers + _RestorePotionAttributes() + _UpdateInventoryFilters() + endif EndEvent