ItsAlways710 Posted December 4, 2021 Author Share Posted December 4, 2021 Yeah, not sure where to go with it at this point. The hotkeys were an afterthought, maybe I just abandon them. Recompiled with the script I posted with the added bool and modified OnKeyDown and State and took out any registering of keys that could happen without doing it, COC Riverwood and messed around about 25 mins without going into the MCM or anything, no problems. Went into MCM and exited without touching anything, messed around with using Mod spells and features for about 25 mins, no problem, went into MCM and added one hotkey, 6 mins and the game froze - never even hit the hotkey and was sitting on a mount spinning just to make sure nothing from the Mod was being used. Loaded up the version with no hotkeys on a fully modded game, played around using mod features and stuff for over an hour, no issues. Went back to the minimal build that has the current version with hotkeys, COC Riverwood, went into MCM and assigned a hotkey and then just stood there, didn't touch anything and it froze before it started spinning. Maybe hotkeys just weren't meant to be. Really frustrating though. I feel like I'm SO close LOL. -IA710 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted December 4, 2021 Share Posted December 4, 2021 Post the code as you have it now. One option to consider, rewrite the MCM to utilize its state method (example of that can be seen in my Inventory management mod). The state method puts all events for a given option into a single state. No long lists of ElseIf statements to get lost in when wanting to modify a single option. Plus adding new options gets easier as an existing state can be copied, pasted and then adjusted as needed. Link to comment Share on other sites More sharing options...
ItsAlways710 Posted December 4, 2021 Author Share Posted December 4, 2021 Ok, I'm not giving up - here it is as it sits right now: Scriptname IA710_HandyCrafting_MCM_Script extends SKI_ConfigBase IA710_HandyCraftingScript Property HandyCrafting Auto ;These need to be filled with the formlists and container references. FormList Property IA710_flAllIngredients Auto {Holds all of the ingredients from the other lists.} ObjectReference Property IA710_cIngredientStorageRef Auto {Master container hold all the stored ingredients.} ObjectReference Property IA710_cTemporaryHoldingRef Auto {Container that holds Protected ingredients while the player is crafting.} ObjectReference Property IA710_cCappingChestRef Auto {Container tha holds the Capping ingredients list.} FormList[] Property IngredientsList Auto {Contains all the vanilla ingredient lists} ObjectReference[] Property IngredientContainerRef Auto {The containers for each of the corresponding ingredient lists} ; Miscelaneous properties Message Property IA710_mUninstallMessage Auto {Final instructions to follow to complete uninstallation.} Spell Property IA710_spFortifyCraftingWeight Auto {Used to remove the spell from the player, in case something went wrong.} String Property ThousandsSeperator = "," Auto {The thousands seperator used in formatting the item count numbers. Default: ,} ObjectReference Property IA710_cRetrieveStorageRef Auto {Temprarily Holds list specific ingredients while retrieving them} ObjectReference Property IA710_cBagofHoldingREF Auto {Container Ref that holds Bag of Holding stored items} Spell[] Property HandySpellsList Auto ; Handy Spell List is ; [0] = Handy Store and Retrieve Spell ; [1] = Handy Conjure Ghost Mount Spell ; [2] = Handy Teleport Spell ; [3] = Handy Bag of Holding Spell Actor PlayerRef ; To keep from making repeated calls to Game.GetPlayer() int current_version = 0 Int[] IngrdientEntryID ; ID numbers to access each of the vanilla ingredient lists/containers Int OpenCappingContainerID ; ID number to access the Capping container Int OpenStorageContainerID ; ID number to access the storage container Int StoreAllIngredientsID ; ID number to start the Store All Ingredients function Int IsEnabledID ; ID number to enable/disable Handy Crafting Int EnabledWeightBuffID ; ID number to enable/disable the carry weight buff Int EnableIngredientCappingID ; ID number to enable/disable ingredient Capping Int AlwaysShowMessagesID ; ID number to enable/disable container message always showing Int UninstallHandyCraftingID ; ID number to start uninstalling Handy Crafting Int RefreshListsID ; ID number to start the Refresh All of the Ingredient Lists Int AllowInDungeonsID ; ID number to allow Handy Crafting to work on crafting stations in dungeons/wilderness Int AddStoreIngredientsSpellID ; ID number to add/remove the "Handy Store and Retrieve" spell. Int AddHandyTeleportSpellID ; ID number to add/remove the "Handy Teleport" spell. Int AddHandyGhostMountSpellID ; ID number to add/remove the "Handy Conjure Ghost Mount" spell. Int AddHandyBOHSpellID ; ID number to add/remove the "Handy Bag of Holding" spell. Int RetrieveAllStoredID ; ID Number to Retrieve all items from all storage main and temporay storage, leaves capping, protected and custom added int[] HSKeyDefault int[] HSKeyMap int[] OID_Hotkey int HSLMax ; IngredientEntryID indices are ; 0 = Alchemy ; 1 = Carpetnry ; 2 = Cooking ; 3 = Enchanting ; 4 = Milling ; 5 = Smelting ; 6 = Smithing ; 7 = Tanning ; 8 = Tempering ; 9 = Protected Int Function GetVersion() Return 1 EndFunction String Function GetCustomControl(int keyCode) int idx = 0 while idx < HSLMax if (HSKeyMap[idx] == keyCode) return "Handy Crafting: " + HandySpellsList[idx].GetName() EndIf idx += 1 EndWhile return "" EndFunction String Function FormatNumber(Int aiNumToFormat) String FormattedNumber = aiNumToFormat If aiNumToFormat > 0 If StringUtil.GetLength(FormattedNumber) > 3 FormattedNumber = StringUtil.SubString(FormattedNumber, 0, StringUtil.GetLength(FormattedNumber) - 3) + ThousandsSeperator + StringUtil.SubString(FormattedNumber, StringUtil.GetLength(FormattedNumber) - 3, 3) If StringUtil.GetLength(FormattedNumber) > 7 FormattedNumber = StringUtil.SubString(FormattedNumber, 0, StringUtil.GetLength(FormattedNumber) - 7) + ThousandsSeperator + StringUtil.SubString(FormattedNumber, StringUtil.GetLength(FormattedNumber) - 7, 7) EndIf EndIf Return FormattedNumber Else Return "" EndIf EndFunction ; Closes the MCM and System menus. Brings the player back to game mode. Function CloseMCM() UI.Invoke("Journal Menu", "_root.QuestJournalFader.Menu_mc.ConfigPanelClose") UI.Invoke("Journal Menu", "_root.QuestJournalFader.Menu_mc.CloseMenu") Utility.Wait(0.5) EndFunction ; Refreshes a formlist with it's associated container ; Used to make sure the formlist contains valid objects Function RefreshList(FormList aflIngredientList, ObjectReference aorIngredientContainer) Int idx = aorIngredientContainer.GetNumItems() Form[] ContainerContents = Utility.CreateFormArray(idx) While idx > 0 idx -= 1 ContainerContents[idx] = aorIngredientContainer.GetNthForm(idx) EndWhile aflIngredientList.Revert() aflIngredientList.Addforms(ContainerContents) EndFunction ; Returns the total number of items inside a container Int Function MergeIngredientLists(FormList aflIngredientList) Int idx = IngredientsList.Length Form[] ConvertedFormlist aflIngredientList.Revert() While idx > 0 idx -= 1 ConvertedFormlist = IngredientsList[idx].ToArray() aflIngredientList.AddForms(ConvertedFormlist) EndWhile Return IA710_cIngredientStorageRef.GetItemCount(aflIngredientList) EndFunction event OnVersionUpdate(int version) if (version > current_version) Debug.Trace(self + ": Updating script to version " + version) OnConfigInit() endIf endEvent Event OnConfigInit() ; Pages = new string[3] Pages[0] = "List Maintenance" Pages[1] = "Configuration" Pages[2] = "Uninstall" PlayerRef = Game.GetPlayer() ; To keep from making repeated calls to Game.GetPlayer() IngrdientEntryID = Utility.CreateIntArray(IngredientsList.Length) ; Just in case I decide to add or remove ingredient lists Int idx = IngredientsList.Length - 1 ; Skip adding Protected Ingredients to the large list. Form[] ConvertedFormlist IA710_flAllIngredients.Revert() While idx > 0 idx -= 1 ConvertedFormlist = IngredientsList[idx].ToArray() IA710_flAllIngredients.AddForms(ConvertedFormlist) EndWhile PlayerRef.AddSpell(HandySpellsList[0], abVerbose = False) PlayerRef.AddSpell(HandySpellsList[1], abVerbose = False) PlayerRef.AddSpell(HandySpellsList[2], abVerbose = False) PlayerRef.AddSpell(HandySpellsList[3], abVerbose = False) ; Initialize Hotkey Stuff HSLMax = HandySpellsList.Length OID_Hotkey = Utility.CreateIntArray(HSLMax, 0) int[] tempkeyholding ; Unregister all keys UnregisterForAllKeys() ; Set Key Defaults If (!HSKeyDefault || HSKeyDefault.Length != HSLMax) HSKeyDefault = Utility.CreateIntArray(HSLMax, -1) endif ; if HSKeyMap doesn't exist, initialize it, ; if it already exists but is the wrong length, preserve the values we can, reinit and fill with old values if !HSKeyMap HSKeyMap = Utility.CreateIntArray(HSLMax, -1) elseIf HSKeyMap.Length != HSLMax ; TempKeyHolding = Utility.CreateIntArray(HSLMax, -1) ; idx = HSLMax ; while idx > 0 ; idx -= 1 ; if idx < HSKeyMap.length ; TempKeyHolding[idx] = HSKeyMap[idx] ; else ; TempKeyHolding[idx] = HSKeyDefault[idx] ; endif ; endWhile HSKeyMap = Utility.CreateIntArray(HSLMax, -1) ; HSKeyMap = TempKeyHolding endIf ; Register the hotkeys ; idx = HSLMax ; while idx > 0 ; idx -= 1 ; if HSKeyMap[idx] > 1 ; RegisterForKey(HSKeyMap[idx]) ; endIf ; endwhile current_version = GetVersion() Debug.Notification("Handy Crafting and Spells Initilization Complete") EndEvent Event OnGameReload() Int idx = IngredientsList.Length Form CurrentIngredient Parent.OnGameReload() While idx > 0 idx -= 1 RefreshList(IngredientsList[idx], IngredientContainerRef[idx]) EndWhile idx = IA710_cCappingChestRef.GetNumItems() HandyCrafting.CappedIngredientsNum HandyCrafting.CappedIngredientsRef = Utility.CreateFormArray(idx) HandyCrafting.CappedIngredientsQty = Utility.CreateIntArray(idx) While idx > 0 idx -= 1 CurrentIngredient = IA710_cCappingChestRef.GetNthForm(idx) HandyCrafting.CappedIngredientsRef[idx] = CurrentIngredient HandyCrafting.CappedIngredientsQty[idx] = IA710_cCappingChestRef.GetItemCount(CurrentIngredient) EndWhile EndEvent Event OnConfigOpen() Int idx = IngredientsList.Length - 1 ; Skip adding Protected Ingredients to the large list. Form[] ConvertedFormlist ; Merges all of the ingredient formlists into one large list. ; This is used to quickly store all ingreidents and display how many ingredients are in the storage container. IA710_flAllIngredients.Revert() While idx > 0 idx -= 1 ConvertedFormlist = IngredientsList[idx].ToArray() IA710_flAllIngredients.AddForms(ConvertedFormlist) EndWhile ; Some basic maintenance. PlayerRef.RemoveSpell(IA710_spFortifyCraftingWeight) ; Remove the carry weight buff if the player has it on him/her IA710_cTemporaryHoldingRef.RemoveAllItems(PlayerRef) ; This container should always be empty, but just to be safe IA710_cRetrieveStorageRef.RemoveAllItems(PlayerRef) ; This container should also always be empty, but just to be safe EndEvent Event OnPageReset(String a_Page) If (a_page == "") OnPageReset("List Maintenance") ; Load List Maintenance page ElseIf (a_page == "List Maintenance") SetCursorFillMode (LEFT_TO_RIGHT) SetTitleText("$The_HandyCrafting_Title") Utility.WaitMenuMode(0.1) ; Show all the ingredient lists on the left side of the page, maintenance and options on the right side. ; The two sides are mixed together, so good luck trying to make sense of it. :P - I created several pages and split it -IA710 AddHeaderOption("$Ingredients_Lists") AddHeaderOption("$Maintenance") IngrdientEntryID[0] = AddTextOption("$Alchemy_Ingredients", FormatNumber(IngredientContainerRef[0].GetNumItems())) OpenStorageContainerID = AddTextOption("$Open_Storage_Container", FormatNumber(IA710_cIngredientStorageRef.GetItemCount( IA710_flAllIngredients))) IngrdientEntryID[1] = AddTextOption("$Carpentry_Ingredients", FormatNumber(IngredientContainerRef[1].GetNumItems())) StoreAllIngredientsID = AddTextOption("$Store_All_Ingredients", "") IngrdientEntryID[2] = AddTextOption("$Cooking_Ingredients", FormatNumber(IngredientContainerRef[2].GetNumItems())) RetrieveAllStoredID = AddTextOption("$Retrieve_All_Items", "") SetCursorFillMode (TOP_TO_BOTTOM) IngrdientEntryID[3] = AddTextOption("$Enchanting_Ingredients", FormatNumber(IngredientContainerRef[3].GetNumItems())) IngrdientEntryID[4] = AddTextOption("$Milling_Ingredients", FormatNumber(IngredientContainerRef[4].GetNumItems())) IngrdientEntryID[5] = AddTextOption("$Smelting_Ingredients", FormatNumber(IngredientContainerRef[5].GetNumItems())) IngrdientEntryID[6] = AddTextOption("$Smithing_Ingredients", FormatNumber(IngredientContainerRef[6].GetNumItems())) IngrdientEntryID[7] = AddTextOption("$Tanning_Ingredients", FormatNumber(IngredientContainerRef[7].GetNumItems())) IngrdientEntryID[8] = AddTextOption("$Tempering_Ingredients", FormatNumber(IngredientContainerRef[8].GetNumItems())) IngrdientEntryID[9] = AddTextOption("$Protected_Ingredients", FormatNumber(IngredientContainerRef[9].GetNumItems())) OpenCappingContainerID = AddTextOption("$Capped_Ingredients", FormatNumber(IA710_cCappingChestRef.GetNumItems())) ElseIf (a_page == "Configuration") SetCursorFillMode (LEFT_TO_RIGHT) SetTitleText("$The_HandyCrafting_Title") AddHeaderOption("$Options") AddHeaderOption ("$Add_Spells_Header") IsEnabledID = AddToggleOption("$Enable_HandyCrafting", HandyCrafting.HandyCraftingEnabled) AddStoreIngredientsSpellID = AddToggleOption("$Add_Store_Ingredients_Power", PlayerRef.HasSpell(HandySpellsList[0])) AllowInDungeonsID = AddToggleOption("$Restricted_Mode", !HandyCrafting.AllowInDungeons) AddHandyGhostMountSpellID = AddToggleOption ("$Add_Handy_Mount_Spell", PlayerRef.HasSpell(HandySpellsList[1])) EnableIngredientCappingID = AddToggleOption("$Enable_Capping", HandyCrafting.EnableCapping) AddHandyTeleportSpellID = AddToggleOption("$Add_Handy_Teleport_Spell", PlayerRef.HasSpell(HandySpellsList[2])) EnabledWeightBuffID = AddToggleOption("$Increase_Carry_Weight_while_Crafting", HandyCrafting.CraftingWeightBuffEnabled) AddHandyBOHSpellID = AddToggleOption("$Add_Handy_BOH_Spell", PlayerRef.HasSpell(HandySpellsList[3])) AlwaysShowMessagesID = AddToggleOption("$Always_Show_Messages", HandyCrafting.AlwaysShowMessages) SetCursorFillMode(TOP_TO_BOTTOM) AddEmptyOption() AddHeaderOption("$Add_Handy_Hotkeys") int idx = 0 while (idx < HSLMax) OID_Hotkey[idx] = AddKeyMapOption(HandySpellsList[idx].GetName() + " Hotkey", HSKeyMap[idx]) idx += 1 endwhile ElseIf (a_page == "Uninstall") SetCursorFillMode (TOP_TO_BOTTOM) SetTitleText("$The_HandyCrafting_Title") AddHeaderOption("$Uninstall") UninstallHandyCraftingID = AddTextOption("$Uninstall_HandyCrafting", "") AddEmptyOption() AddHeaderOption("Troubleshooting") RefreshListsID = AddTextOption("Reinitialize and Refresh all lists", "") EndIf EndEvent Event OnOptionHighlight(Int OptionID) If OptionID == IngrdientEntryID[0] SetInfoText("$Alchemy_Description") ElseIf OptionID == IngrdientEntryID[1] SetInfoText("$Carpentry_Description") ElseIf OptionID == IngrdientEntryID[2] SetInfoText("$Cooking_Description") ElseIf OptionID == IngrdientEntryID[3] SetInfoText("$Enchanting_Description") ElseIf OptionID == IngrdientEntryID[4] SetInfoText("$Milling_Description") ElseIf OptionID == IngrdientEntryID[5] SetInfoText("$Smelting_Description") ElseIf OptionID == IngrdientEntryID[6] SetInfoText("$Smithing_Description") ElseIf OptionID == IngrdientEntryID[7] SetInfoText("$Tanning_Description") ElseIf OptionID == IngrdientEntryID[8] SetInfoText("$Tempering_Description") ElseIf OptionID == IngrdientEntryID[9] SetInfoText("$Protected_Description") ElseIf OptionID == OpenCappingContainerID SetInfoText("$Capped_Description") ElseIf OptionID == OpenStorageContainerID SetInfoText("$Open_Storage_Container_Description") ElseIf OptionID == StoreAllIngredientsID SetInfoText("$Store_All_Ingredients_Description") ElseIf OptionID == IsEnabledID SetInfoText("$Enable/Disable_Description") ElseIF OptionID == AllowInDungeonsID SetInfoText("$Restricted_Mode_Description") ElseIf OptionID == EnableIngredientCappingID SetInfoText("$Enable_Capping_Description") ElseIf OptionID == AlwaysShowMessagesID SetInfoText("$Always_Show_Messages_Description") Elseif OptionID == EnabledWeightBuffID SetInfoText("$Enable_Weight_Buff_Description") ElseIf OptionID == UninstallHandyCraftingID SetInfoText("$Uninstall_Description") ElseIf OptionID == AddStoreIngredientsSpellID SetInfoText("$Add_Store_Ingedients_Power_Description") ElseIf OptionID == AddHandyTeleportSpellID SetInfoText("$Add_Handy_Teleport_Spell_Description") ElseIf OptionID == AddHandyGhostMountSpellID SetInfoText("$Add_Handy_Mount_Spell_Description") ElseIf OptionID == AddHandyBOHSpellID SetInfoText("$Add_Handy_BOH_Spell_Description") ElseIf OptionID == RetrieveAllStoredID SetInfoText("$Retrieve_All_Items_Description") Else int idx = 0 while idx < HSLMax If (OptionID == OID_Hotkey[idx]) SetInfoText("$Set_Handy_Hotkey") EndIf idx += 1 EndWhile EndIf EndEvent Event OnOptionDefault(Int OptionID) If OptionID == IsEnabledID HandyCrafting.HandyCraftingEnabled = True SetToggleOptionValue(OptionID, HandyCrafting.HandyCraftingEnabled) ElseIf OptionID == AllowInDungeonsID HandyCrafting.AllowInDungeons = True SetToggleOptionValue(OptionID, !HandyCrafting.AllowInDungeons) ElseIf OptionID == EnabledWeightBuffID HandyCrafting.CraftingWeightBuffEnabled = True SetToggleOptionValue(OptionID, HandyCrafting.CraftingWeightBuffEnabled) ElseIf OptionID == EnableIngredientCappingID HandyCrafting.EnableCapping = True SetToggleOptionValue(OptionID, HandyCrafting.EnableCapping) ElseIf OptionID == AlwaysShowMessagesID HandyCrafting.AlwaysShowMessages = True SetToggleOptionValue(OptionID, HandyCrafting.AlwaysShowMessages) ElseIf OptionID == AddStoreIngredientsSpellID If !PlayerRef.HasSpell(HandySpellsList[0]) PlayerRef.AddSpell(HandySpellsList[0]) EndIf SetToggleOptionValue(AddStoreIngredientsSpellID, True) ElseIf OptionID == AddHandyTeleportSpellID If !PlayerRef.HasSpell(HandySpellsList[2]) PlayerRef.AddSpell(HandySpellsList[2]) EndIf SetToggleOptionValue(AddHandyTeleportSpellID, True) ElseIf OptionID == AddHandyGhostMountSpellID If !PlayerRef.HasSpell(HandySpellsList[1]) PlayerRef.AddSpell(HandySpellsList[1]) EndIf SetToggleOptionValue(AddHandyGhostMountSpellID, True) ElseIf OptionID == AddHandyBOHSpellID If !PlayerRef.HasSpell(HandySpellsList[3]) PlayerRef.AddSpell(HandySpellsList[3]) EndIf SetToggleOptionValue(AddHandyBOHSpellID, True) Else int idx = 0 while idx < HSLMax If (OptionID == OID_Hotkey[idx]) UnregisterForKey(HSKeyMap[idx]) SetKeyMapOptionValue(OptionID, -1) HSKeyMap[idx] = -1 EndIf idx += 1 EndWhile EndIf EndEvent Event OnOptionSelect(Int OptionID) Int idx Form IngredientToCap Int QuantityToCap Form CurrentIngredient If OptionID == UninstallHandyCraftingID ; Handle the uninstall option If ShowMessage("$Confirm_Uninstall") CloseMCM() HandyCrafting.ShutDown() UnregisterForAllKeys() PlayerRef.RemoveSpell(HandySpellsList[2]) PlayerRef.RemoveSpell(HandySpellsList[3]) IA710_cBagofHoldingREF.RemoveAllItems(PlayerRef) PlayerRef.RemoveSpell(HandySpellsList[1]) PlayerRef.RemoveSpell(HandySpellsList[0]) IA710_cRetrieveStorageRef.RemoveAllItems(PlayerRef) IA710_cIngredientStorageRef.RemoveAllItems(PlayerRef) IA710_cTemporaryHoldingRef.RemoveAllItems(PlayerRef) idx = IngredientContainerRef.Length While idx > 0 idx -= 1 IngredientContainerRef[idx].RemoveAllItems() EndWhile IA710_mUninstallMessage.Show() Self.Stop() EndIf ; Handle Troubleshooting ElseIf OptionID == RefreshListsID OnConfigInit() idx = IngredientsList.Length While idx > 0 idx -= 1 RefreshList(IngredientsList[idx], IngredientContainerRef[idx]) EndWhile idx = IA710_cCappingChestRef.GetNumItems() HandyCrafting.CappedIngredientsNum HandyCrafting.CappedIngredientsRef = Utility.CreateFormArray(idx) HandyCrafting.CappedIngredientsQty = Utility.CreateIntArray(idx) While idx > 0 idx -= 1 CurrentIngredient = IA710_cCappingChestRef.GetNthForm(idx) HandyCrafting.CappedIngredientsRef[idx] = CurrentIngredient HandyCrafting.CappedIngredientsQty[idx] = IA710_cCappingChestRef.GetItemCount(CurrentIngredient) EndWhile OnConfigOpen() ShowMessage("Reinitialized MCM and Refreshed all lists.", False) ; Handle the toggled options ElseIf OptionID == IsEnabledID HandyCrafting.HandyCraftingEnabled = !HandyCrafting.HandyCraftingEnabled SetToggleOptionValue(OptionID, HandyCrafting.HandyCraftingEnabled) ElseIf OptionID == AllowInDungeonsID ; Handle the Allow in Dungeons/Wilderness option HandyCrafting.AllowInDungeons = !HandyCrafting.AllowInDungeons SetToggleOptionValue(OptionID, !HandyCrafting.AllowInDungeons) ElseIf OptionID == EnabledWeightBuffID HandyCrafting.CraftingWeightBuffEnabled = !HandyCrafting.CraftingWeightBuffEnabled SetToggleOptionValue(OptionID, HandyCrafting.CraftingWeightBuffEnabled) ElseIf OptionID == EnableIngredientCappingID HandyCrafting.EnableCapping = !HandyCrafting.EnableCapping SetToggleOptionValue(OptionID, HandyCrafting.EnableCapping) ElseIf OptionID == AlwaysShowMessagesID HandyCrafting.AlwaysShowMessages = !HandyCrafting.AlwaysShowMessages SetToggleOptionValue(OptionID, HandyCrafting.AlwaysShowMessages) ElseIf OptionID == AddStoreIngredientsSpellID If !PlayerRef.HasSpell(HandySpellsList[0]) PlayerRef.AddSpell(HandySpellsList[0], abVerbose = False) Else PlayerRef.RemoveSpell(HandySpellsList[0]) IA710_cRetrieveStorageRef.RemoveAllItems(PlayerRef) EndIf SetToggleOptionValue(AddStoreIngredientsSpellID, PlayerRef.HasSpell(HandySpellsList[0])) ElseIf OptionID == AddHandyTeleportSpellID If !PlayerRef.HasSpell(HandySpellsList[2]) PlayerRef.AddSpell(HandySpellsList[2], abVerbose = False) Else PlayerRef.RemoveSpell(HandySpellsList[2]) EndIf SetToggleOptionValue(AddHandyTeleportSpellID, PlayerRef.HasSpell(HandySpellsList[2])) ElseIf OptionID == AddHandyGhostMountSpellID If !PlayerRef.HasSpell(HandySpellsList[1]) PlayerRef.AddSpell(HandySpellsList[1], abVerbose = False) Else PlayerRef.RemoveSpell(HandySpellsList[1]) EndIf SetToggleOptionValue(AddHandyGhostMountSpellID, PlayerRef.HasSpell(HandySpellsList[1])) ElseIf OptionID == AddHandyBOHSpellID If !PlayerRef.HasSpell(HandySpellsList[3]) PlayerRef.AddSpell(HandySpellsList[3], abVerbose = False) Else PlayerRef.RemoveSpell(HandySpellsList[3]) IA710_cBagofHoldingREF.RemoveAllItems(PlayerRef) EndIf SetToggleOptionValue(AddHandyBOHSpellID, PlayerRef.HasSpell(HandySpellsList[3])) ElseIf OptionID == OpenCappingContainerID ; Handle accessing the Capping container CloseMCM() IA710_cCappingChestRef.AddInventoryEventFilter(IA710_flAllIngredients) IA710_cCappingChestRef.Activate(PlayerRef) ElseIf OptionID == OpenStorageContainerID ; Handle accessing the storage container CloseMCM() IA710_cIngredientStorageRef.Activate(PlayerRef) ElseIf OptionID == StoreAllIngredientsID ; Handle the Store All Ingredients option ; Retreive all the items in the storage container IA710_cIngredientStorageRef.RemoveAllItems(PlayerRef) ; Store any Protected ingredients in the temporary container PlayerRef.RemoveItem(IngredientsList[9], PlayerRef.GetItemCount(IngredientsList[9]), abSilent = True, akOtherContainer = IA710_cTemporaryHoldingRef) ; Search through the capped ingredients list for excess ingredients in the player's inventory idx = IA710_cCappingChestRef.GetNumItems() While idx > 0 idx -= 1 IngredientToCap = IA710_cCappingChestRef.GetNthForm(idx) QuantityToCap = PlayerRef.GetItemCount(IngredientToCap) - IA710_cCappingChestRef.GetItemCount(IngredientToCap) ; Set any excess ingredients aside in the temporary holding container If QuantityToCap > 0 PlayerRef.RemoveItem(IngredientToCap, QuantityToCap, abSilent = True, akOtherContainer = IA710_cTemporaryHoldingRef) EndIf EndWhile ; Store all the remaining ingredients PlayerRef.RemoveItem(IA710_flAllIngredients, PlayerRef.GetItemCount(IA710_flAllIngredients), abSilent = True, akOtherContainer = IA710_cIngredientStorageRef) ; Retreive the Protected items from the temporary holding container IA710_cTemporaryHoldingRef.RemoveAllItems(PlayerRef) ShowMessage("$Ingredients_Stored", False) SetTextOptionValue(OpenStorageContainerID, FormatNumber(IA710_cIngredientStorageRef.GetItemCount(IA710_flAllIngredients))) ElseIf OptionID == RetrieveAllStoredID IA710_cBagofHoldingREF.RemoveAllItems(PlayerRef) IA710_cRetrieveStorageRef.RemoveAllItems(PlayerRef) IA710_cIngredientStorageRef.RemoveAllItems(PlayerRef) IA710_cTemporaryHoldingRef.RemoveAllItems(PlayerRef) SetTextOptionValue(OpenStorageContainerID, FormatNumber(IA710_cIngredientStorageRef.GetItemCount(IA710_flAllIngredients))) ShowMessage("$All_Items_Retrieved", False) ; Handle accessing the ingredient containers Else idx = IngredientsList.Length While idx > 0 idx -= 1 If OptionID == IngrdientEntryID[idx] CloseMCM() IngredientContainerRef[idx].Activate(PlayerRef) idx = 0 EndIf EndWhile EndIf EndEvent event OnOptionKeyMapChange(int option, int keyCode, string conflictControl, string conflictName) {Called when a key has been remapped} int idx = 0 while idx < HSLMax If (option == OID_Hotkey[idx]) bool continue = true if (keyCode != 1 && conflictControl != "") string msg if (conflictName != "") msg = "This key is already mapped to:\n\"" + conflictControl + "\"\n(" + conflictName + ")\n\nAre you sure you want to continue?" else msg = "This key is already mapped to:\n\"" + conflictControl + "\"\n\nAre you sure you want to continue?" endIf continue = ShowMessage(msg, true, "$Yes", "$No") endIf If continue UnregisterForKey(HSKeyMap[idx]) if keyCode != 1 RegisterForKey(keyCode) HSKeyMap[idx] = keyCode EndIf SetKeyMapOptionValue(option, keyCode) EndIf EndIf idx += 1 EndWhile endEvent Event OnKeyDown(int keycode) if (keyCode != 1 && SafeProcess() == True) int idx = 0 while idx < HSLMax GoToState("Busy") ; prevent the event from piling up with multiple key presses If (keyCode == HSKeyMap[idx]) ; Debug.Notification("HCaS Casting: " + HandySpellsList[idx].GetName()) HandySpellsList[idx].Cast(PlayerRef) idx = HSLMax ; got what we need - get out GoToState("") ; return to the empty state EndIf idx += 1 endWhile EndIf EndEvent Bool Function SafeProcess() If (!Utility.IsInMenuMode()) \ && (!UI.IsMenuOpen("Dialogue Menu")) \ && (!UI.IsMenuOpen("Console")) \ && (!UI.IsMenuOpen("Crafting Menu")) \ && (!UI.IsMenuOpen("MessageBoxMenu")) \ && (!UI.IsMenuOpen("ContainerMenu")) \ && (!UI.IsTextInputEnabled()) \ && (!PlayerRef.IsOnMount()) ;IsInMenuMode to block when game is paused with menus open ;Dialogue Menu check to block when dialog is open ;Console check to block when console is open - console does not trigger IsInMenuMode and thus needs its own check ;Crafting Menu check to block when crafting menus are open - game is not paused so IsInMenuMode does not work ;MessageBoxMenu check to block when message boxes are open - while they pause the game, they do not trigger IsInMenuMode ;ContainerMenu check to block when containers are accessed - while they pause the game, they do not trigger IsInMenuMode ;IsTextInputEnabled check to block when editable text fields are open ;IsInCombat check to block when combat is going on. ;IsOnMount check to block when riding a horse Return True Else Debug.Notification("Unable to process mod hot key at this time.") Return False EndIf EndFunction State Busy Event OnKeyDown(int keycode) ;do nothing EndEvent EndState I have a lot of stuff in the onconfiginit commented out that I may want to re--enable if we get this working so assigned keys would be preserved on version update, I commented it for the last test to just make sure the variables inited correctly. You are so kind to help me, I can't thank you enough! -IA710 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted December 4, 2021 Share Posted December 4, 2021 I cannot readily see why it would hang up as you are experiencing. I did notice a mistake, in my sample code I put the line to go to the busy state inside the while loop. It should be just before the while statement instead. Link to comment Share on other sites More sharing options...
ItsAlways710 Posted December 5, 2021 Author Share Posted December 5, 2021 Well, I want to thank you for all the help and examples you've given me, I'm better for it, and I can't thank you enough. I'm going to keep messing with it, maybe implement the state method on the MCM script and see how that effects it. I may downgrade AE to 1.5.97 on my laptop and try it on it to rule out something funny with my install on this machine. I'm mid-playthrough on the install on this machine and so have it frozen, maybe it's something peculiar to this machine? I'll let you know if I figure anything out. Thank you! -IA710 Link to comment Share on other sites More sharing options...
Sphered Posted December 5, 2021 Share Posted December 5, 2021 If keys are giving you this much trouble you might consider setting aside a script exactly for all that is key input I posted a template but the registerforkey line had a goof so nvm, but anyway let me know if a template would help Link to comment Share on other sites More sharing options...
ReDragon2013 Posted December 6, 2021 Share Posted December 6, 2021 (edited) IA710 wrote: "Went back to the minimal build that has the current version with hotkeys, COC Riverwood, went into MCM and assigned a hotkey and then just stood there, didn't touch anything and it froze before it started spinning. Maybe hotkeys just weren't meant to be. Really frustrating though." Its importent to understand that Skyrim SE and Skyrim AE require a different version of SKSE64. There are enough threads here in forums on Skyrim Nexus. About your MCM script. Try to avoid redundancy in code to make it better maintanable. Use more functions to compact your event codes. The following script is made for studying, not compiled yet. IA710_HandyCrafting_MCM_Script Scriptname IA710_HandyCrafting_MCM_Script extends SKI_ConfigBase ; https://forums.nexusmods.com/index.php?/topic/10792698-need-help-adding-hotkeys-to-mcm/page-2 IA710_HandyCraftingScript PROPERTY HandyCrafting auto ; pointer to script "IA710_HandyCraftingScript.psc" Message PROPERTY IA710_mUninstallMessage auto ; {Final instructions to follow to complete uninstallation.} Spell PROPERTY IA710_spFortifyCraftingWeight auto ; {Used to remove the spell from the player, in case something went wrong.} Spell[] PROPERTY HandySpellsList auto ; Array with spell lists as follow: ; [0] = Handy Store and Retrieve Spell ; [1] = Handy Conjure Ghost Mount Spell ; [2] = Handy Teleport Spell ; [3] = Handy Bag of Holding Spell ;These need to be filled with the formlists and container references. FormList PROPERTY IA710_flAllIngredients auto ; {Holds all of the ingredients from the other lists.} FormList[] PROPERTY IngredientsList auto ; {Contains all the vanilla ingredient lists} ObjectReference PROPERTY IA710_cIngredientStorageRef auto ; {Master container hold all the stored ingredients.} ObjectReference PROPERTY IA710_cTemporaryHoldingRef auto ; {Container that holds Protected ingredients while the player is crafting.} ObjectReference PROPERTY IA710_cCappingChestRef auto ; {Container tha holds the Capping ingredients list.} ObjectReference PROPERTY IA710_cBagofHoldingREF auto ; {Container Ref that holds Bag of Holding stored items} ObjectReference PROPERTY IA710_cRetrieveStorageRef auto ; {Temprarily Holds list specific ingredients while retrieving them} ObjectReference[] PROPERTY IngredientContainerRef auto ; {The containers for each of the corresponding ingredient lists} String PROPERTY ThousandsSeperator = "," auto ; {The thousands seperator used in formatting the item count numbers. Default: ,} ; ID numbers to Int OpenCappingContainerID ; access the Capping container Int OpenStorageContainerID ; access the storage container Int IsEnabledID ; enable/disable Handy Crafting Int EnabledWeightBuffID ; enable/disable the carry weight buff Int EnableIngredientCappingID ; enable/disable ingredient Capping Int AlwaysShowMessagesID ; enable/disable container message always showing Int AllowInDungeonsID ; allow Handy Crafting to work on crafting stations in dungeons/wilderness Int AddStoreIngredientsSpellID ; add/remove the "Handy Store and Retrieve" spell. Int AddHandyTeleportSpellID ; add/remove the "Handy Teleport" spell. Int AddHandyGhostMountSpellID ; add/remove the "Handy Conjure Ghost Mount" spell. Int AddHandyBOHSpellID ; add/remove the "Handy Bag of Holding" spell. Int RefreshListsID ; start the Refresh All of the Ingredient Lists Int StoreAllIngredientsID ; start the Store All Ingredients function Int UninstallHandyCraftingID ; start uninstalling Handy Crafting Int RetrieveAllStoredID ; retrieve all items from all storage main and temporay storage, leaves capping, protected and custom added Int[] HSKeyDefault Int[] HSKeyMap Int[] OID_Hotkey Int[] IngrdientEntryID ; ID numbers to access each of the vanilla ingredient lists/containers ; IngredientEntryID indices are ; 0 = Alchemy ; 1 = Carpentry ; 2 = Cooking ; 3 = Enchanting ; 4 = Milling ; 5 = Smelting ; 6 = Smithing ; 7 = Tanning ; 8 = Tempering ; 9 = Protected Int HSLMax Int current_version = 0 ;Actor PlayerRef ; to keep from making repeated calls to Game.GetPlayer() ;------------------------ Int FUNCTION GetVersion() ;------------------------ RETURN 1 ENDFUNCTION ;------------------ FUNCTION CloseMCM() ; Closes the MCM and System menus. Brings the player back to game mode. ;------------------ UI.Invoke("Journal Menu", "_root.QuestJournalFader.Menu_mc.ConfigPanelClose") UI.Invoke("Journal Menu", "_root.QuestJournalFader.Menu_mc.CloseMenu") Utility.Wait(0.5) ENDFUNCTION ; -- EVENTs -- 10 + "Busy" EVENT OnVersionUpdate(Int version) ;==================== IF (version > current_version) Debug.Trace(" OnVersionUpdate() - is updating the script to version " +version+ " -- " +self) OnConfigInit() ENDIF ENDEVENT EVENT OnConfigInit() ;================= ; Pages = new string[3] Pages[0] = "List Maintenance" Pages[1] = "Configuration" Pages[2] = "Uninstall" ; Just in case I decide to add or remove ingredient lists IngrdientEntryID = Utility.CreateIntArray( IngredientsList.Length ) myF_Revert() actor player = Game.GetPlayer() player.AddSpell(HandySpellsList[0], abVerbose = False) player.AddSpell(HandySpellsList[1], abVerbose = False) player.AddSpell(HandySpellsList[2], abVerbose = False) player.AddSpell(HandySpellsList[3], abVerbose = False) ; Unregister all keys UnregisterForAllKeys() ; Initialize Hotkey Stuff HSLMax = HandySpellsList.Length OID_Hotkey = Utility.CreateIntArray(HSLMax, 0) ; Set Key Defaults IF (!HSKeyDefault) || (HSLMax != HSKeyDefault.Length) HSKeyDefault = Utility.CreateIntArray(HSLMax, -1) ENDIF ; if HSKeyMap does not exist, initialize it, ; if it already exists but is the wrong length, preserve the values we can, reinit and fill with old values IF ( !HSKeyMap ) HSKeyMap = Utility.CreateIntArray(HSLMax, -1) ELSEIF (HSKeyMap.Length != HSLMax) ;--------- ; int[] tempkeyholding ; TempKeyHolding = Utility.CreateIntArray(HSLMax, -1) ; i = HSLMax ; while i > 0 ; i -= 1 ; if i < HSKeyMap.length ; TempKeyHolding[i] = HSKeyMap[i] ; else ; TempKeyHolding[i] = HSKeyDefault[i] ; endif ; endWhile ; HSKeyMap = TempKeyHolding ;--------- HSKeyMap = Utility.CreateIntArray(HSLMax, -1) ENDIF ; Register the hotkeys ; i = HSLMax ; while i > 0 ; i -= 1 ; if HSKeyMap[i] > 1 ; RegisterForKey(HSKeyMap[i]) ; endIf ; endwhile current_version = GetVersion() Debug.Notification("Handy Crafting and Spells Initilization Complete") ENDEVENT EVENT OnConfigOpen() ;================= ; Merges all of the ingredient formlists into one large list. ; This is used to quickly store all ingredients and display how many ingredients are in the storage container. myF_Revert() ; Some basic maintenance. actor player = Game.GetPlayer() player.RemoveSpell(IA710_spFortifyCraftingWeight) ; Remove the carry weight buff if the player has it on him/her IA710_cTemporaryHoldingRef.RemoveAllItems(player) ; This container should always be empty, but just to be safe IA710_cRetrieveStorageRef.RemoveAllItems(player) ; This container should also always be empty, but just to be safe ENDEVENT EVENT OnGameReload() ;================= parent.OnGameReload() ; see "SKI_ConfigBase.psc" myF_Refresh() ENDEVENT EVENT OnPageReset(String a_Page) ;================ IF (a_page == "") OnPageReset("List Maintenance") RETURN ; - STOP - recursive call with "Maintenance page" ENDIF ;--------------------- IF (a_page == "List Maintenance") SetCursorFillMode (LEFT_TO_RIGHT) SetTitleText("$The_HandyCrafting_Title") Utility.WaitMenuMode(0.1) ; Show all the ingredient lists on the left side of the page, maintenance and options on the right side. ; The two sides are mixed together, so good luck trying to make sense of it. :P - I created several pages and split it -IA710 AddHeaderOption("$Ingredients_Lists") AddHeaderOption("$Maintenance") IngrdientEntryID[0] = AddTextOption("$Alchemy_Ingredients", FormatNumber( IngredientContainerRef[0].GetNumItems() )) OpenStorageContainerID = AddTextOption("$Open_Storage_Container", FormatNumber(IA710_cIngredientStorageRef.GetItemCount( IA710_flAllIngredients ))) IngrdientEntryID[1] = AddTextOption("$Carpentry_Ingredients", FormatNumber(IngredientContainerRef[1].GetNumItems())) StoreAllIngredientsID = AddTextOption("$Store_All_Ingredients", "") IngrdientEntryID[2] = AddTextOption("$Cooking_Ingredients", FormatNumber(IngredientContainerRef[2].GetNumItems())) RetrieveAllStoredID = AddTextOption("$Retrieve_All_Items", "") SetCursorFillMode (TOP_TO_BOTTOM) IngrdientEntryID[3] = AddTextOption("$Enchanting_Ingredients",FormatNumber(IngredientContainerRef[3].GetNumItems())) IngrdientEntryID[4] = AddTextOption("$Milling_Ingredients", FormatNumber(IngredientContainerRef[4].GetNumItems())) IngrdientEntryID[5] = AddTextOption("$Smelting_Ingredients", FormatNumber(IngredientContainerRef[5].GetNumItems())) IngrdientEntryID[6] = AddTextOption("$Smithing_Ingredients", FormatNumber(IngredientContainerRef[6].GetNumItems())) IngrdientEntryID[7] = AddTextOption("$Tanning_Ingredients", FormatNumber(IngredientContainerRef[7].GetNumItems())) IngrdientEntryID[8] = AddTextOption("$Tempering_Ingredients", FormatNumber(IngredientContainerRef[8].GetNumItems())) IngrdientEntryID[9] = AddTextOption("$Protected_Ingredients", FormatNumber(IngredientContainerRef[9].GetNumItems())) OpenCappingContainerID = AddTextOption("$Capped_Ingredients", FormatNumber( IA710_cCappingChestRef.GetNumItems() )) RETURN ; - STOP - ENDIF ;--------------------- IF (a_page == "Configuration") SetCursorFillMode (LEFT_TO_RIGHT) SetTitleText("$The_HandyCrafting_Title") AddHeaderOption("$Options") AddHeaderOption ("$Add_Spells_Header") actor player = Game.GetPlayer() IsEnabledID = AddToggleOption("$Enable_HandyCrafting", HandyCrafting.HandyCraftingEnabled) AddStoreIngredientsSpellID = AddToggleOption("$Add_Store_Ingredients_Power", player.HasSpell(HandySpellsList[0])) AllowInDungeonsID = AddToggleOption("$Restricted_Mode", !HandyCrafting.AllowInDungeons) AddHandyGhostMountSpellID = AddToggleOption("$Add_Handy_Mount_Spell", player.HasSpell(HandySpellsList[1])) EnableIngredientCappingID = AddToggleOption("$Enable_Capping", HandyCrafting.EnableCapping) AddHandyTeleportSpellID = AddToggleOption("$Add_Handy_Teleport_Spell", player.HasSpell(HandySpellsList[2])) EnabledWeightBuffID = AddToggleOption("$Increase_Carry_Weight_while_Crafting", HandyCrafting.CraftingWeightBuffEnabled) AddHandyBOHSpellID = AddToggleOption("$Add_Handy_BOH_Spell", player.HasSpell(HandySpellsList[3])) AlwaysShowMessagesID = AddToggleOption("$Always_Show_Messages", HandyCrafting.AlwaysShowMessages) SetCursorFillMode(TOP_TO_BOTTOM) AddEmptyOption() AddHeaderOption("$Add_Handy_Hotkeys") int i = 0 WHILE (i < HSLMax) OID_Hotkey[i] = AddKeyMapOption(HandySpellsList[i].GetName() + " Hotkey", HSKeyMap[i]) i = i + 1 ENDWHILE RETURN ; - STOP - ENDIF ;--------------------- IF (a_page == "Uninstall") SetCursorFillMode (TOP_TO_BOTTOM) SetTitleText("$The_HandyCrafting_Title") AddHeaderOption("$Uninstall") UninstallHandyCraftingID = AddTextOption("$Uninstall_HandyCrafting", "") AddEmptyOption() AddHeaderOption("Troubleshooting") RefreshListsID = AddTextOption("Reinitialize and Refresh all lists", "") ENDIF ENDEVENT EVENT OnOptionSelect(Int OptionID) ;=================== actor player = Game.GetPlayer() int i IF OptionID == UninstallHandyCraftingID ; Handle the uninstall option IF ShowMessage("$Confirm_Uninstall") CloseMCM() HandyCrafting.ShutDown() UnregisterForAllKeys() player.RemoveSpell(HandySpellsList[3]) player.RemoveSpell(HandySpellsList[2]) player.RemoveSpell(HandySpellsList[1]) player.RemoveSpell(HandySpellsList[0]) IA710_cBagofHoldingREF.RemoveAllItems(player) IA710_cRetrieveStorageRef.RemoveAllItems(player) IA710_cIngredientStorageRef.RemoveAllItems(player) IA710_cTemporaryHoldingRef.RemoveAllItems(player) i = IngredientContainerRef.Length WHILE (i > 0) i = i - 1 IngredientContainerRef[i].RemoveAllItems() ENDWHILE IA710_mUninstallMessage.Show() self.Stop() ; STOP the QUEST ENDIF RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == RefreshListsID ; Handle Troubleshooting OnConfigInit() myF_Refresh() OnConfigOpen() ShowMessage("Reinitialized MCM and Refreshed all lists.", False) RETURN ; - STOP - ENDIF ;--------------------- ; Handle the toggled options IF OptionID == IsEnabledID HandyCrafting.HandyCraftingEnabled = !HandyCrafting.HandyCraftingEnabled SetToggleOptionValue(OptionID, HandyCrafting.HandyCraftingEnabled) RETURN ; - STOP - ENDIF ;--------------------- ; Handle the Allow in Dungeons/Wilderness option IF OptionID == AllowInDungeonsID HandyCrafting.AllowInDungeons = !HandyCrafting.AllowInDungeons SetToggleOptionValue(OptionID, !HandyCrafting.AllowInDungeons) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == EnabledWeightBuffID HandyCrafting.CraftingWeightBuffEnabled = !HandyCrafting.CraftingWeightBuffEnabled SetToggleOptionValue(OptionID, HandyCrafting.CraftingWeightBuffEnabled) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == EnableIngredientCappingID HandyCrafting.EnableCapping = !HandyCrafting.EnableCapping SetToggleOptionValue(OptionID, HandyCrafting.EnableCapping) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AlwaysShowMessagesID HandyCrafting.AlwaysShowMessages = !HandyCrafting.AlwaysShowMessages SetToggleOptionValue(OptionID, HandyCrafting.AlwaysShowMessages) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddStoreIngredientsSpellID myF_SelectSpell(OptionID, 0) ;;; If !layer.HasSpell(HandySpellsList[0]) ;;; player.AddSpell(HandySpellsList[0], abVerbose = False) ;;; Else ;;; player.RemoveSpell(HandySpellsList[0]) ;;; IA710_cRetrieveStorageRef.RemoveAllItems(player) ;;; EndIf ;;; SetToggleOptionValue(OptionID, player.HasSpell(HandySpellsList[0])) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyGhostMountSpellID myF_SelectSpell(OptionID, 1) ;;; If !player.HasSpell(HandySpellsList[1]) ;;; player.AddSpell(HandySpellsList[1], abVerbose = False) ;;; Else ;;; player.RemoveSpell(HandySpellsList[1]) ;;; EndIf ;;; SetToggleOptionValue(OptionID, player.HasSpell(HandySpellsList[1])) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyTeleportSpellID myF_SelectSpell(OptionID, 2) ;;; If !player.HasSpell(HandySpellsList[2]) ;;; player.AddSpell(HandySpellsList[2], abVerbose = False) ;;; Else ;;; player.RemoveSpell(HandySpellsList[2]) ;;; EndIf ;;; SetToggleOptionValue(OptionID, player.HasSpell(HandySpellsList[2])) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyBOHSpellID myF_SelectSpell(OptionID, 3) ;;; If !player.HasSpell(HandySpellsList[3]) ;;; player.AddSpell(HandySpellsList[3], abVerbose = False) ;;; Else ;;; player.RemoveSpell(HandySpellsList[3]) ;;; IA710_cBagofHoldingREF.RemoveAllItems(player) ;;; EndIf ;;; SetToggleOptionValue(OptionID, player.HasSpell(HandySpellsList[3])) RETURN ; - STOP - ENDIF ;--------------------- ; Handle accessing the Capping container IF OptionID == OpenCappingContainerID CloseMCM() IA710_cCappingChestRef.AddInventoryEventFilter(IA710_flAllIngredients) IA710_cCappingChestRef.Activate(player as ObjectReference) RETURN ; - STOP - ENDIF ;--------------------- ; Handle accessing the storage container IF OptionID == OpenStorageContainerID CloseMCM() IA710_cIngredientStorageRef.Activate(player as ObjectReference) RETURN ; - STOP - ENDIF ;--------------------- ; Handle the Store All Ingredients option IF OptionID == StoreAllIngredientsID ; Retreive all the items in the storage container IA710_cIngredientStorageRef.RemoveAllItems(player) ; Store any Protected ingredients in the temporary container player.RemoveItem(IngredientsList[9], player.GetItemCount(IngredientsList[9]), abSilent = True, akOtherContainer = IA710_cTemporaryHoldingRef) ; Search through the capped ingredients list for excess ingredients in the players inventory i = IA710_cCappingChestRef.GetNumItems() WHILE (i > 0) i = i - 1 form fm = IA710_cCappingChestRef.GetNthForm(i) ; fm = IngredientToCap int QuantityToCap = player.GetItemCount(fm) - IA710_cCappingChestRef.GetItemCount(fm) ; Set any excess ingredients aside in the temporary holding container IF (QuantityToCap > 0) player.RemoveItem(fm, QuantityToCap, abSilent = True, akOtherContainer = IA710_cTemporaryHoldingRef) ENDIF ENDWHILE ; Store all the remaining ingredients player.RemoveItem(IA710_flAllIngredients, player.GetItemCount(IA710_flAllIngredients), abSilent = True, akOtherContainer = IA710_cIngredientStorageRef) ; Retreive the Protected items from the temporary holding container IA710_cTemporaryHoldingRef.RemoveAllItems(layer) ShowMessage("$Ingredients_Stored", False) SetTextOptionValue(OpenStorageContainerID, FormatNumber(IA710_cIngredientStorageRef.GetItemCount(IA710_flAllIngredients))) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == RetrieveAllStoredID IA710_cBagofHoldingREF.RemoveAllItems(player) IA710_cRetrieveStorageRef.RemoveAllItems(player) IA710_cIngredientStorageRef.RemoveAllItems(player) IA710_cTemporaryHoldingRef.RemoveAllItems(player) SetTextOptionValue(OpenStorageContainerID, FormatNumber(IA710_cIngredientStorageRef.GetItemCount(IA710_flAllIngredients))) ShowMessage("$All_Items_Retrieved", False) RETURN ; - STOP - ENDIF ;--------------------- ; Handle accessing the ingredient containers i = IngredientsList.Length WHILE (i) i = i - 1 IF (OptionID == IngrdientEntryID[i]) CloseMCM() IngredientContainerRef[i].Activate(player as ObjectReference) i = 0 ENDIF ENDWHILE ENDEVENT ;-------------------------------------------- FUNCTION myF_SelectSpell(Int OptionID, Int i) ;-------------------------------------------- actor player = Game.GetPlayer() bool b = player.HasSpell( HandySpellsList[i] ) IF ( b ) player.RemoveSpell( HandySpellsList[i] ) IF (i == 0) IA710_cRetrieveStorageRef.RemoveAllItems(player) ; option: AddStoreIngredientsSpellID ENDIF IF (i == 3) IA710_cBagofHoldingREF.RemoveAllItems(player) ; option: AddHandyBOHSpellID ENDIF ELSE player.AddSpell(HandySpellsList[i], abVerbose = False) ENDIF SetToggleOptionValue(OptionID, !b) ENDFUNCTION EVENT OnOptionDefault(Int OptionID) ;===================== IF OptionID == IsEnabledID HandyCrafting.HandyCraftingEnabled = TRUE ; TRUE SetToggleOptionValue(OptionID, HandyCrafting.HandyCraftingEnabled) ; enabled RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AllowInDungeonsID HandyCrafting.AllowInDungeons = TRUE ; TRUE SetToggleOptionValue(OptionID, !HandyCrafting.AllowInDungeons) ; opposite here ?? RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == EnabledWeightBuffID HandyCrafting.CraftingWeightBuffEnabled = TRUE ; TRUE SetToggleOptionValue(OptionID, HandyCrafting.CraftingWeightBuffEnabled) ; enabled RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == EnableIngredientCappingID HandyCrafting.EnableCapping = TRUE ; TRUE SetToggleOptionValue(OptionID, HandyCrafting.EnableCapping) ; enable RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AlwaysShowMessagesID HandyCrafting.AlwaysShowMessages = TRUE ; TRUE SetToggleOptionValue(OptionID, HandyCrafting.AlwaysShowMessages) ; always show messages RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddStoreIngredientsSpellID myF_AddSpell(0) ;;; If !PlayerRef.HasSpell(HandySpellsList[0]) ;;; PlayerRef.AddSpell(HandySpellsList[0]) ;;; EndIf SetToggleOptionValue(OptionID, TRUE) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyGhostMountSpellID myF_AddSpell(1) SetToggleOptionValue(OptionID, TRUE) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyTeleportSpellID myF_AddSpell(2) SetToggleOptionValue(OptionID, TRUE) RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyBOHSpellID myF_AddSpell(3) SetToggleOptionValue(OptionID, TRUE) RETURN ; - STOP - ENDIF ;--------------------- int i = 0 WHILE (i < HSLMax) IF (OptionID == OID_Hotkey[i]) UnregisterForKey( HSKeyMap[i] ) SetKeyMapOptionValue(OptionID, -1) HSKeyMap[i] = -1 i = HSLMax ; break loop here *** added by ReDragon *** ENDIF i = i + 1 ENDWHILE ENDEVENT ;--------------------------- FUNCTION myF_AddSpell(Int i) ;--------------------------- actor player = Game.GetPlayer() IF player.HasSpell( HandySpellsList[i] ) RETURN ; - STOP - ENDIF ;--------------------- player.AddSpell( HandySpellsList[i] ) ENDFUNCTION EVENT OnOptionHighlight(Int OptionID) ;====================== IF OptionID == IngrdientEntryID[0] SetInfoText("$Alchemy_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[1] SetInfoText("$Carpentry_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[2] SetInfoText("$Cooking_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[3] SetInfoText("$Enchanting_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[4] SetInfoText("$Milling_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[5] SetInfoText("$Smelting_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[6] SetInfoText("$Smithing_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[7] SetInfoText("$Tanning_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[8] SetInfoText("$Tempering_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IngrdientEntryID[9] SetInfoText("$Protected_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == OpenCappingContainerID SetInfoText("$Capped_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == OpenStorageContainerID SetInfoText("$Open_Storage_Container_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == StoreAllIngredientsID SetInfoText("$Store_All_Ingredients_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == IsEnabledID SetInfoText("$Enable/Disable_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AllowInDungeonsID SetInfoText("$Restricted_Mode_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == EnableIngredientCappingID SetInfoText("$Enable_Capping_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AlwaysShowMessagesID SetInfoText("$Always_Show_Messages_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == EnabledWeightBuffID SetInfoText("$Enable_Weight_Buff_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == UninstallHandyCraftingID SetInfoText("$Uninstall_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddStoreIngredientsSpellID SetInfoText("$Add_Store_Ingedients_Power_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyTeleportSpellID SetInfoText("$Add_Handy_Teleport_Spell_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyGhostMountSpellID SetInfoText("$Add_Handy_Mount_Spell_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == AddHandyBOHSpellID SetInfoText("$Add_Handy_BOH_Spell_Description") RETURN ; - STOP - ENDIF ;--------------------- IF OptionID == RetrieveAllStoredID SetInfoText("$Retrieve_All_Items_Description") RETURN ; - STOP - ENDIF ;--------------------- int i = HSLMax WHILE (i) ; (i != 0) i = i - 1 IF (OptionID == OID_Hotkey[i]) SetInfoText("$Set_Handy_Hotkey") ENDIF ENDWHILE ENDEVENT EVENT OnOptionKeyMapChange(Int option, Int keyCode, String conflictControl, String conflictName) ; {Called when a key has been remapped} ;========================= int i = 0 WHILE (i < HSLMax) IF (option == OID_Hotkey[i]) bool bOK = TRUE ; bOK = continue IF (keyCode != 1) && (conflictControl != "") string s = "This key is already mapped to:\n\"" + conflictControl ; s = msg IF (conflictName == "") s = s + "\"\n\nAre you sure you want to continue?" ELSE s = s + "\"\n(" + conflictName + ")\n\nAre you sure you want to continue?" ENDIF bOK = ShowMessage(s, TRUE, "$Yes", "$No") ENDIF IF ( bOK ) UnregisterForKey( HSKeyMap[i] ) IF (keyCode != 1) RegisterForKey(keyCode) HSKeyMap[i] = keyCode ENDIF SetKeyMapOptionValue(option, keyCode) ENDIF ENDIF i = i + 1 ENDWHILE ENDEVENT ;====================================== State Busy ;========= EVENT OnKeyDown(Int keycode) ENDEVENT ;======= endState EVENT OnKeyDown(Int keycode) ;============== IF (keyCode == 1) RETURN ; - STOP - ENDIF ;--------------------- gotoState("Busy") ; ### STATE ### prevent the event from piling up with multiple keypress myF_Process(keycode) gotoState("") ; ### STATE ### back to normal ENDEVENT ; -- FUNCTIONs -- (2) + (2) + 7 ;-------------------------------- FUNCTION myF_Process(Int keycode) ;-------------------------------- 1 int i IF Utility.IsInMenuMode() i = 1 ; IsInMenuMode to block when game is paused with menus open ELSEIF UI.IsMenuOpen("Dialogue Menu") i = 2 ; Dialogue Menu check to block when dialog is open ELSEIF UI.IsMenuOpen("Console") i = 3 ; Console check to block when console is open - console does not trigger IsInMenuMode and thus needs its own check ELSEIF UI.IsMenuOpen("Crafting Menu") i = 4 ; Crafting Menu check to block when crafting menus are open - game is not paused so IsInMenuMode does not work ELSEIF UI.IsMenuOpen("MessageBoxMenu") i = 5 ; MessageBoxMenu check to block when message boxes are open - while they pause the game, they do not trigger IsInMenuMode ELSEIF UI.IsMenuOpen("ContainerMenu") i = 6 ; ContainerMenu check to block when containers are accessed - while they pause the game, they do not trigger IsInMenuMode ELSEIF UI.IsTextInputEnabled() i = 7 ; IsTextInputEnabled check to block when editable text fields are open ELSEIF Game.GetPlayer().IsOnMount() i = 8 ; IsOnMount check to block when riding a horse ;ELSEIF Game.GetPlayer().IsInCombat() ; i = 9 ; IsInCombat check to block when combat is going on. ENDIF IF (i > 0) Debug.Notification("Unable to process mod hotkey at this time. " +i) RETURN ; - STOP - ENDIF ;--------------------- i = HSKeyMap.Find(keyCode) IF (i < 0) RETURN ; - STOP - key not found! ENDIF ;--------------------- ;; Debug.Notification("HCaS Casting: " + HandySpellsList[i].GetName()) HandySpellsList[i].Cast(Game.GetPlayer() as ObjectReference) ENDFUNCTION ;-------------------------------------------- String FUNCTION GetCustomControl(Int keyCode) ; UnUSED internal ;-------------------------------------------- 2 string s = "" int i = 0 WHILE (i < HSLMax) IF (HSKeyMap[i] == keyCode) s = "Handy Crafting: " + HandySpellsList[i].GetName() i = HSLMax ; abort loop ENDIF i = i + 1 ENDWHILE RETURN s ENDFUNCTION ;---------------------------------------------- String FUNCTION FormatNumber(Int aiNumToFormat) ;---------------------------------------------- 3 string s = "" ; s = FormattedNumber IF (aiNumToFormat <= 0) RETURN s ENDIF ;--------- ; 1000000 -> 1,000,000 > 7 s = aiNumToFormat as String ; 1000 -> 1,000 > 3 int i = StringUtil.GetLength(s) IF (i > 3) s = StringUtil.SubString(s, 0, (i - 3)) +ThousandsSeperator+ StringUtil.SubString(s, (i - 3), 3) i = StringUtil.GetLength(s) IF (i > 7) s = StringUtil.SubString(s, 0, (i - 7)) +ThousandsSeperator+ StringUtil.SubString(s, (i - 7), 7) ENDIF ENDIF RETURN s ENDFUNCTION ;--------------------- FUNCTION myF_Refresh() ;--------------------- 4 int i = IngredientsList.Length WHILE (i > 0) i = i - 1 RefreshList(IngredientsList[i], IngredientContainerRef[i]) ENDWHILE i = IA710_cCappingChestRef.GetNumItems() HandyCrafting.CappedIngredientsNum ; ??? HandyCrafting.CappedIngredientsRef = Utility.CreateFormArray(i) HandyCrafting.CappedIngredientsQty = Utility.CreateIntArray(i) WHILE (i > 0) i = i - 1 form fm = IA710_cCappingChestRef.GetNthForm(i) ; fm = CurrentIngredient HandyCrafting.CappedIngredientsRef[i] = fm HandyCrafting.CappedIngredientsQty[i] = IA710_cCappingChestRef.GetItemCount(fm) ENDWHILE ENDFUNCTION ;--------------------------------------------------------------------------------------- FUNCTION RefreshList(FormList aflIngredientList, ObjectReference aorIngredientContainer) ; helper, see myF_Refresh() ;--------------------------------------------------------------------------------------- 5 ; Refreshes a formlist with its associated container ; Used to make sure the formlist contains valid objects int i = aorIngredientContainer.GetNumItems() form[] a = Utility.CreateFormArray(i) ; a = ContainerContents WHILE (i > 0) i = i - 1 a[i] = aorIngredientContainer.GetNthForm(i) ENDWHILE aflIngredientList.Revert() ; clear formlist entries made by script aflIngredientList.Addforms(a) ; add new entries ENDFUNCTION ;-------------------- FUNCTION myF_Revert() ;-------------------- 6 form[] a ; a = ConvertedFormlist IA710_flAllIngredients.Revert() i = IngredientsList.Length - 1 ; Skip adding Protected Ingredients to the large list. WHILE (i > 0) i = i - 1 a = IngredientsList[i].ToArray() IA710_flAllIngredients.AddForms(a) ENDWHILE ENDFUNCTION ;------------------------------------------------------------ Int FUNCTION MergeIngredientLists(FormList aflIngredientList) ; UnUSED internal ;------------------------------------------------------------ 7 ; Returns the total number of items inside a container form[] a ; a = ConvertedFormlist aflIngredientList.Revert() int i = IngredientsList.Length WHILE (i > 0) i = i - 1 a = IngredientsList[i].ToArray() aflIngredientList.AddForms(a) ENDWHILE i = IA710_cIngredientStorageRef.GetItemCount(aflIngredientList) RETURN i ENDFUNCTION HandyCrafting.CappedIngredientsNum ; ??? Edited December 6, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
ItsAlways710 Posted December 7, 2021 Author Share Posted December 7, 2021 All, I've learned a lot from all of this. I'm going to try several things over the next few weeks, but I have only an hour or two a day at most to spend on it for a while due to some other obligations, but I will post back to this thread as I try things and truly appreciate all your help. Ishra, Sphered I'll try to use the template provided to use states + Ishra's recomendations regarding onconfigclose and onupdate, thank you! ReDragon2013 - Yeah, the AE install is on a different machine and has the correct version of SKSE. Thank you so much for the code sample, I had every intention of tightening it up once I had it working right, but most likely should have done that from the beginning. Your example compiled (with a couple of tweaks), but the issue persists. The HandCrafting.CappedIngreditensNum was leftover from something else and not required. Thank you again. I am starting to think it's an issue with my system and am going to look at that next. Thank you all, I will let you know how it goes! -IA710 Link to comment Share on other sites More sharing options...
ItsAlways710 Posted December 9, 2021 Author Share Posted December 9, 2021 (edited) Ishara, Sphered and ReDragon2013, I am trying to implement everything everyone has suggested (maybe not the best idea, but I like all of your examples), and so have tried to do something like what all of you have described. Switched to MCM 2.0 State based format.Got rid of OnGameReload weird piece, and replaced it with OnPlayerLoadGame event, and moved the OnConfigOpen to OnPlayerLoadGame because that's really where it belonged anyways in an effort to decrease the total number of events.Used/Created more functions (some ReDragon2013 provided, some I did as I was converting it) for obvious reasons. The example below is where I am at on it. It compiles and everything seems to work fine, and I was able to run it longer than before. I know that Ishara recommended to us OnConfigClose to register for a single update and then update everything at one time, but really I'm not positive that would help much with my situation, or what all I would wait to process (maybe just keymaping?). So that's one thing that I will look further at. Ishara, the reference mod you mentioned moved some of the onkeydown stuff to a separate script, should I be considering that too? Here's where I'm at: Scriptname IA710_HandyCrafting_MCM_Script extends SKI_ConfigBase IA710_HandyCraftingScript PROPERTY HandyCrafting auto ; pointer to script "IA710_HandyCraftingScript.psc" Message PROPERTY IA710_mUninstallMessage auto ; {Final instructions to follow to complete uninstallation.} Spell PROPERTY IA710_spFortifyCraftingWeight auto ; {Used to remove the spell from the player, in case something went wrong.} Spell[] PROPERTY HandySpellsList auto ; Array with spell lists as follow: ; [0] = Handy Store and Retrieve Spell ; [1] = Handy Conjure Ghost Mount Spell ; [2] = Handy Teleport Spell ; [3] = Handy Bag of Holding Spell ;These need to be filled with the formlists and container references. FormList PROPERTY IA710_flAllIngredients auto ; {Holds all of the ingredients from the other lists.} FormList[] PROPERTY IngredientsList auto ; {Contains all the vanilla ingredient lists} ; 0 = Alchemy ; 1 = Carpentry ; 2 = Cooking ; 3 = Enchanting ; 4 = Milling ; 5 = Smelting ; 6 = Smithing ; 7 = Tanning ; 8 = Tempering ; 9 = Protected ObjectReference PROPERTY IA710_cIngredientStorageRef auto ; {Master container hold all the stored ingredients.} ObjectReference PROPERTY IA710_cTemporaryHoldingRef auto ; {Container that holds Protected ingredients while the player is crafting.} ObjectReference PROPERTY IA710_cCappingChestRef auto ; {Container tha holds the Capping ingredients list.} ObjectReference PROPERTY IA710_cBagofHoldingREF auto ; {Container Ref that holds Bag of Holding stored items} ObjectReference PROPERTY IA710_cRetrieveStorageRef auto ; {Temprarily Holds list specific ingredients while retrieving them} ObjectReference[] PROPERTY IngredientContainerRef auto ; {The containers for each of the corresponding ingredient lists} String PROPERTY ThousandsSeperator = "," auto ; {The thousands seperator used in formatting the item count numbers. Default: ,} Int[] HSKeyDefault Int[] HSKeyMap Int HSLMax Int current_version = 0 ; actor player = Game.GetPlayer() ;Actor PlayerRef ; to keep from making repeated calls to Game.GetPlayer() ;------------------------ Int FUNCTION GetVersion() ;------------------------ RETURN 1 ENDFUNCTION ;------------------ FUNCTION CloseMCM() ; Closes the MCM and System menus. Brings the player back to game mode. ;------------------ UI.Invoke("Journal Menu", "_root.QuestJournalFader.Menu_mc.ConfigPanelClose") UI.Invoke("Journal Menu", "_root.QuestJournalFader.Menu_mc.CloseMenu") Utility.Wait(0.5) ENDFUNCTION ; -- EVENTs -- 10 + "Busy" EVENT OnVersionUpdate(Int version) ;==================== IF (version > current_version) Debug.Trace(" OnVersionUpdate() - is updating the script to version " +version+ " -- " +self) OnConfigInit() ENDIF ENDEVENT EVENT OnConfigInit() ;================= ; Pages = new string[3] Pages[0] = "List Maintenance" Pages[1] = "Configuration" Pages[2] = "Uninstall" myF_Revert() actor player = Game.GetPlayer() player.AddSpell(HandySpellsList[0], abVerbose = False) player.AddSpell(HandySpellsList[1], abVerbose = False) player.AddSpell(HandySpellsList[2], abVerbose = False) player.AddSpell(HandySpellsList[3], abVerbose = False) ; Unregister all keys UnregisterForAllKeys() ; Initialize Hotkey Stuff HSLMax = HandySpellsList.Length ; Set Key Defaults IF (!HSKeyDefault) || (HSLMax != HSKeyDefault.Length) HSKeyDefault = Utility.CreateIntArray(HSLMax, -1) ENDIF ; if HSKeyMap does not exist, initialize it, ; if it already exists but is the wrong length, preserve the values we can, reinit and fill with old values IF ( !HSKeyMap ) HSKeyMap = Utility.CreateIntArray(HSLMax, -1) ELSEIF (HSKeyMap.Length != HSLMax) ;--------- ; int[] tempkeyholding ; TempKeyHolding = Utility.CreateIntArray(HSLMax, -1) ; i = HSLMax ; while i > 0 ; i -= 1 ; if i < HSKeyMap.length ; TempKeyHolding[i] = HSKeyMap[i] ; else ; TempKeyHolding[i] = HSKeyDefault[i] ; endif ; endWhile ; HSKeyMap = TempKeyHolding ;--------- HSKeyMap = Utility.CreateIntArray(HSLMax, -1) ENDIF ; Register the hotkeys ; i = HSLMax ; while i > 0 ; i -= 1 ; if HSKeyMap[i] > 1 ; RegisterForKey(HSKeyMap[i]) ; endIf ; endwhile current_version = GetVersion() Debug.Notification("Handy Crafting and Spells Initilization Complete") ENDEVENT ;EVENT OnConfigOpen() ;================= ; Merges all of the ingredient formlists into one large list. ; This is used to quickly store all ingredients and display how many ingredients are in the storage container. ; myF_Revert() ; Some basic maintenance. ; actor player = Game.GetPlayer() ; player.RemoveSpell(IA710_spFortifyCraftingWeight) ; Remove the carry weight buff if the player has it on him/her ; IA710_cTemporaryHoldingRef.RemoveAllItems(player) ; This container should always be empty, but just to be safe ; IA710_cRetrieveStorageRef.RemoveAllItems(player) ; This container should also always be empty, but just to be safe ;ENDEVENT EVENT OnPlayerLoadGame() ;================= ; parent.OnGameReload() ; see "SKI_ConfigBase.psc" myF_Refresh() myF_Revert() ; Some basic maintenance. actor player = Game.GetPlayer() player.RemoveSpell(IA710_spFortifyCraftingWeight) ; Remove the carry weight buff if the player has it on him/her IA710_cTemporaryHoldingRef.RemoveAllItems(player) ; This container should always be empty, but just to be safe IA710_cRetrieveStorageRef.RemoveAllItems(player) ; This container should also always be empty, but just to be safe ENDEVENT EVENT OnPageReset(String a_Page) ;================ ;IF (a_page == "") ; OnPageReset("List Maintenance") ; RETURN ; - STOP - recursive call with "Maintenance page" ;ENDIF ;--------------------- IF (a_page == "List Maintenance") SetCursorFillMode (TOP_TO_BOTTOM) SetTitleText("$The_HandyCrafting_Title") Utility.WaitMenuMode(0.1) ; Show all the ingredient lists on the left side of the page, maintenance and options on the right side. AddHeaderOption("$Ingredients_Lists") AddTextOptionST("IngredientEntryIDState" + 0, "$Alchemy_Ingredients", FormatNumber( IngredientContainerRef[0].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 1, "$Carpentry_Ingredients", FormatNumber( IngredientContainerRef[1].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 2, "$Cooking_Ingredients", FormatNumber( IngredientContainerRef[2].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 3, "$Enchanting_Ingredients", FormatNumber( IngredientContainerRef[3].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 4, "$Milling_Ingredients", FormatNumber( IngredientContainerRef[4].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 5, "$Smelting_Ingredients", FormatNumber( IngredientContainerRef[5].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 6, "$Smithing_Ingredients", FormatNumber( IngredientContainerRef[6].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 7, "$Tanning_Ingredients", FormatNumber( IngredientContainerRef[7].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 8, "$Tempering_Ingredients", FormatNumber( IngredientContainerRef[8].GetNumItems() )) AddTextOptionST("IngredientEntryIDState" + 9, "$Protected_Ingredients", FormatNumber( IngredientContainerRef[9].GetNumItems() )) AddTextOptionST("OpenCappingContainerState", "$Capped_Ingredients", FormatNumber( IA710_cCappingChestRef.GetNumItems() )) SetCursorPosition(1) AddHeaderOption("$Maintenance") AddTextOptionST("OpenStorageContainerState", "$Open_Storage_Container", FormatNumber(IA710_cIngredientStorageRef.GetItemCount( IA710_flAllIngredients ))) AddTextOptionST("StoreAllIngredientsState", "$Store_All_Ingredients", "") AddTextOptionST("RetrieveAllStoredState", "$Retrieve_All_Items", "") RETURN ; - STOP - ENDIF ;--------------------- IF (a_page == "Configuration") SetTitleText("$The_HandyCrafting_Title") SetCursorFillMode (TOP_TO_BOTTOM) AddHeaderOption("$Options") actor player = Game.GetPlayer() AddToggleOptionST("HCIsEnabledState", "$Enable_HandyCrafting", HandyCrafting.HandyCraftingEnabled) AddToggleOptionST("AllowInDungeonsState", "$Restricted_Mode", !HandyCrafting.AllowInDungeons) AddToggleOptionST("EnableIngCappingState", "$Enable_Capping", HandyCrafting.EnableCapping) AddToggleOptionST("EnabledWeightBuffState","$Increase_Carry_Weight_while_Crafting", HandyCrafting.CraftingWeightBuffEnabled) AddToggleOptionST("AlwaysShowMessagesState", "$Always_Show_Messages", HandyCrafting.AlwaysShowMessages) SetCursorPosition(1) AddHeaderOption ("$Add_Spells_Header") AddToggleOptionST("AddStoreSpellState", "$Add_Store_Ingredients_Power", player.HasSpell(HandySpellsList[0])) AddToggleOptionST("AddMountSpellState", "$Add_Handy_Mount_Spell", player.HasSpell(HandySpellsList[1])) AddToggleOptionST("AddTeleportSpellState", "$Add_Handy_Teleport_Spell", player.HasSpell(HandySpellsList[2])) AddToggleOptionST("AddBOHSpellState", "$Add_Handy_BOH_Spell", player.HasSpell(HandySpellsList[3])) AddEmptyOption() AddHeaderOption("$Add_Handy_Hotkeys") int i = 0 WHILE (i < HSLMax) AddKeyMapOptionST("HSKeyState" + i, HandySpellsList[i].GetName() + " Hotkey", HSKeyMap[i]) i = i + 1 ENDWHILE RETURN ; - STOP - ENDIF ;--------------------- IF (a_page == "Uninstall") SetCursorFillMode (TOP_TO_BOTTOM) SetTitleText("$The_HandyCrafting_Title") AddHeaderOption("$Uninstall") AddTextOptionST("UninstallState", "$Uninstall_HandyCrafting", "") AddEmptyOption() AddHeaderOption("Troubleshooting") AddTextOptionST("RefreshListsState", "Reinitialize and Refresh all lists", "") RETURN ENDIF ENDEVENT ;-------------------------------------------- FUNCTION myF_SelectSpell(Int i) ;-------------------------------------------- actor player = Game.GetPlayer() bool b = player.HasSpell( HandySpellsList[i] ) IF ( b ) player.RemoveSpell( HandySpellsList[i] ) IF (i == 0) IA710_cRetrieveStorageRef.RemoveAllItems(player) ; option: AddStoreSpellState ENDIF IF (i == 3) IA710_cBagofHoldingREF.RemoveAllItems(player) ; option: AddBOHSpellState ENDIF ELSE player.AddSpell(HandySpellsList[i], abVerbose = False) ENDIF ENDFUNCTION ;--------------------------- FUNCTION myF_AddSpell(Int i) ;--------------------------- actor player = Game.GetPlayer() IF player.HasSpell( HandySpellsList[i] ) RETURN ; - STOP - ENDIF ;--------------------- player.AddSpell( HandySpellsList[i] ) ENDFUNCTION FUNCTION myF_OnOptionKeyMapChange(Int option, Int keyCode, String conflictControl, String conflictName) ; {Called when a key has been remapped} ;========================= bool bOK = TRUE ; bOK = continue IF (keyCode != 1) && (conflictControl != "") string s = "This key is already mapped to:\n\"" + conflictControl ; s = msg IF (conflictName == "") s = s + "\"\n\nAre you sure you want to continue?" ELSE s = s + "\"\n(" + conflictName + ")\n\nAre you sure you want to continue?" ENDIF bOK = ShowMessage(s, TRUE, "$Yes", "$No") ENDIF IF ( bOK ) UnregisterForKey( HSKeyMap[option] ) IF (keyCode != 1) RegisterForKey(keyCode) HSKeyMap[option] = keyCode ENDIF SetKeyMapOptionValueST(keyCode, False, "HSKeyState" + option) ENDIF ENDFUNCTION ;====================================== State Busy ;========= EVENT OnKeyDown(Int keycode) ENDEVENT ;======= endState EVENT OnKeyDown(Int keycode) ;============== IF (keyCode == 1) RETURN ; - STOP - ENDIF ;--------------------- gotoState("Busy") ; ### STATE ### prevent the event from piling up with multiple keypress myF_Process(keycode) gotoState("") ; ### STATE ### back to normal ENDEVENT ; -- FUNCTIONs -- (2) + (2) + 7 ;-------------------------------- FUNCTION myF_Process(Int keycode) ;-------------------------------- 1 int i IF Utility.IsInMenuMode() i = 1 ; IsInMenuMode to block when game is paused with menus open ELSEIF UI.IsMenuOpen("Dialogue Menu") i = 2 ; Dialogue Menu check to block when dialog is open ELSEIF UI.IsMenuOpen("Console") i = 3 ; Console check to block when console is open - console does not trigger IsInMenuMode and thus needs its own check ELSEIF UI.IsMenuOpen("Crafting Menu") i = 4 ; Crafting Menu check to block when crafting menus are open - game is not paused so IsInMenuMode does not work ELSEIF UI.IsMenuOpen("MessageBoxMenu") i = 5 ; MessageBoxMenu check to block when message boxes are open - while they pause the game, they do not trigger IsInMenuMode ELSEIF UI.IsMenuOpen("ContainerMenu") i = 6 ; ContainerMenu check to block when containers are accessed - while they pause the game, they do not trigger IsInMenuMode ELSEIF UI.IsTextInputEnabled() i = 7 ; IsTextInputEnabled check to block when editable text fields are open ELSEIF Game.GetPlayer().IsOnMount() i = 8 ; IsOnMount check to block when riding a horse ;ELSEIF Game.GetPlayer().IsInCombat() ; i = 9 ; IsInCombat check to block when combat is going on. ENDIF IF (i > 0) Debug.Notification("Unable to process Handy hotkey at this time. " +i) RETURN ; - STOP - ENDIF ;--------------------- i = HSKeyMap.Find(keyCode) IF (i < 0) RETURN ; - STOP - key not found! ENDIF ;--------------------- ;; Debug.Notification("HCaS Casting: " + HandySpellsList[i].GetName()) HandySpellsList[i].Cast(Game.GetPlayer() as ObjectReference) ENDFUNCTION ;-------------------------------------------- String FUNCTION GetCustomControl(Int keyCode) ; UnUSED internal ;-------------------------------------------- 2 string s = "" int i = 0 WHILE (i < HSLMax) IF (HSKeyMap[i] == keyCode) s = "Handy Crafting: " + HandySpellsList[i].GetName() i = HSLMax ; abort loop ENDIF i = i + 1 ENDWHILE RETURN s ENDFUNCTION ;---------------------------------------------- String FUNCTION FormatNumber(Int aiNumToFormat) ;---------------------------------------------- 3 string s = "" ; s = FormattedNumber IF (aiNumToFormat <= 0) RETURN s ENDIF ;--------- ; 1000000 -> 1,000,000 > 7 s = aiNumToFormat as String ; 1000 -> 1,000 > 3 int i = StringUtil.GetLength(s) IF (i > 3) s = StringUtil.SubString(s, 0, (i - 3)) +ThousandsSeperator+ StringUtil.SubString(s, (i - 3), 3) i = StringUtil.GetLength(s) IF (i > 7) s = StringUtil.SubString(s, 0, (i - 7)) +ThousandsSeperator+ StringUtil.SubString(s, (i - 7), 7) ENDIF ENDIF RETURN s ENDFUNCTION ;--------------------- FUNCTION myF_Refresh() ;--------------------- 4 int i = IngredientsList.Length WHILE (i > 0) i = i - 1 RefreshList(IngredientsList[i], IngredientContainerRef[i]) ENDWHILE i = IA710_cCappingChestRef.GetNumItems() HandyCrafting.CappedIngredientsNum ; ??? HandyCrafting.CappedIngredientsRef = Utility.CreateFormArray(i) HandyCrafting.CappedIngredientsQty = Utility.CreateIntArray(i) WHILE (i > 0) i = i - 1 form fm = IA710_cCappingChestRef.GetNthForm(i) ; fm = CurrentIngredient HandyCrafting.CappedIngredientsRef[i] = fm HandyCrafting.CappedIngredientsQty[i] = IA710_cCappingChestRef.GetItemCount(fm) ENDWHILE ENDFUNCTION ;--------------------------------------------------------------------------------------- FUNCTION RefreshList(FormList aflIngredientList, ObjectReference aorIngredientContainer) ; helper, see myF_Refresh() ;--------------------------------------------------------------------------------------- 5 ; Refreshes a formlist with its associated container ; Used to make sure the formlist contains valid objects int i = aorIngredientContainer.GetNumItems() form[] a = Utility.CreateFormArray(i) ; a = ContainerContents WHILE (i > 0) i = i - 1 a[i] = aorIngredientContainer.GetNthForm(i) ENDWHILE aflIngredientList.Revert() ; clear formlist entries made by script aflIngredientList.Addforms(a) ; add new entries ENDFUNCTION ;-------------------- FUNCTION myF_Revert() ;-------------------- 6 form[] a ; a = ConvertedFormlist IA710_flAllIngredients.Revert() int i = IngredientsList.Length - 1 ; Skip adding Protected Ingredients to the large list. WHILE (i > 0) i = i - 1 a = IngredientsList[i].ToArray() IA710_flAllIngredients.AddForms(a) ENDWHILE ENDFUNCTION ;------------------------------------------------------------ Int FUNCTION MergeIngredientLists(FormList aflIngredientList) ; UnUSED internal ;------------------------------------------------------------ 7 ; Returns the total number of items inside a container form[] a ; a = ConvertedFormlist aflIngredientList.Revert() int i = IngredientsList.Length WHILE (i > 0) i = i - 1 a = IngredientsList[i].ToArray() aflIngredientList.AddForms(a) ENDWHILE i = IA710_cIngredientStorageRef.GetItemCount(aflIngredientList) RETURN i ENDFUNCTION STATE IngredientEntryIDState0 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[0].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Alchemy_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState1 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[1].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Carpentry_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState2 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[2].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Cooking_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState3 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[3].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Enchanting_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState4 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[4].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Milling_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState5 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[5].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Smelting_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState6 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[6].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Smithing_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState7 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[7].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Tanning_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState8 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[8].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Tempering_Description") ENDEVENT ENDSTATE STATE IngredientEntryIDState9 EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IngredientContainerRef[9].Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Protected_Description") ENDEVENT ENDSTATE STATE OpenCappingContainerState EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IA710_cCappingChestRef.AddInventoryEventFilter(IA710_flAllIngredients) IA710_cCappingChestRef.Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Capped_Description") ENDEVENT ENDSTATE STATE OpenStorageContainerState EVENT OnSelectST() actor player = Game.GetPlayer() CloseMCM() IA710_cIngredientStorageRef.Activate(player as ObjectReference) ENDEVENT EVENT OnHighlightST() SetInfoText("$Open_Storage_Container_Description") ENDEVENT ENDSTATE STATE StoreAllIngredientsState EVENT OnSelectST() actor player = Game.GetPlayer() IA710_cIngredientStorageRef.RemoveAllItems(player) ; Store any Protected ingredients in the temporary container player.RemoveItem(IngredientsList[9], player.GetItemCount(IngredientsList[9]), abSilent = True, akOtherContainer = IA710_cTemporaryHoldingRef) ; Search through the capped ingredients list for excess ingredients in the players inventory int i = IA710_cCappingChestRef.GetNumItems() WHILE (i > 0) i = i - 1 form fm = IA710_cCappingChestRef.GetNthForm(i) ; fm = IngredientToCap int QuantityToCap = player.GetItemCount(fm) - IA710_cCappingChestRef.GetItemCount(fm) ; Set any excess ingredients aside in the temporary holding container IF (QuantityToCap > 0) player.RemoveItem(fm, QuantityToCap, abSilent = True, akOtherContainer = IA710_cTemporaryHoldingRef) ENDIF ENDWHILE ; Store all the remaining ingredients player.RemoveItem(IA710_flAllIngredients, player.GetItemCount(IA710_flAllIngredients), abSilent = True, akOtherContainer = IA710_cIngredientStorageRef) ; Retreive the Protected items from the temporary holding container IA710_cTemporaryHoldingRef.RemoveAllItems(player) ShowMessage("$Ingredients_Stored", False) SetTextOptionValueST(FormatNumber(IA710_cIngredientStorageRef.GetItemCount(IA710_flAllIngredients)), False, "OpenStorageContainerState") ENDEVENT EVENT OnHighlightST() SetInfoText("$Store_All_Ingredients_Description") ENDEVENT ENDSTATE STATE RetrieveAllStoredState EVENT OnSelectST() actor player = Game.GetPlayer() IA710_cBagofHoldingREF.RemoveAllItems(player) IA710_cRetrieveStorageRef.RemoveAllItems(player) IA710_cIngredientStorageRef.RemoveAllItems(player) IA710_cTemporaryHoldingRef.RemoveAllItems(player) SetTextOptionValueST(FormatNumber(IA710_cIngredientStorageRef.GetItemCount(IA710_flAllIngredients)), False, "OpenStorageContainerState") ShowMessage("$All_Items_Retrieved", False) ENDEVENT EVENT OnHighlightST() SetInfoText("$Retrieve_All_Items_Description") ENDEVENT ENDSTATE STATE HCIsEnabledState EVENT OnSelectST() HandyCrafting.HandyCraftingEnabled = !HandyCrafting.HandyCraftingEnabled SetToggleOptionValueST(HandyCrafting.HandyCraftingEnabled) ENDEVENT EVENT OnDefaultST() HandyCrafting.HandyCraftingEnabled = TRUE ; TRUE SetToggleOptionValueST(HandyCrafting.HandyCraftingEnabled) ; enabled ENDEVENT EVENT OnHighlightST() SetInfoText("$WeightlessInfo") ENDEVENT ENDSTATE STATE AllowInDungeonsState EVENT OnSelectST() HandyCrafting.AllowInDungeons = !HandyCrafting.AllowInDungeons SetToggleOptionValueST(!HandyCrafting.AllowInDungeons) ENDEVENT EVENT OnDefaultST() HandyCrafting.AllowInDungeons = TRUE ; TRUE SetToggleOptionValueST(!HandyCrafting.AllowInDungeons) ; opposite here ENDEVENT EVENT OnHighlightST() SetInfoText("$Restricted_Mode_Description") ENDEVENT ENDSTATE STATE EnableIngCappingState EVENT OnSelectST() HandyCrafting.EnableCapping = !HandyCrafting.EnableCapping SetToggleOptionValueST(HandyCrafting.EnableCapping) ENDEVENT EVENT OnDefaultST() HandyCrafting.EnableCapping = TRUE ; TRUE SetToggleOptionValueST(HandyCrafting.EnableCapping) ; enable ENDEVENT EVENT OnHighlightST() SetInfoText("$Enable_Capping_Description") ENDEVENT ENDSTATE STATE EnabledWeightBuffState EVENT OnSelectST() HandyCrafting.CraftingWeightBuffEnabled = !HandyCrafting.CraftingWeightBuffEnabled SetToggleOptionValueST(HandyCrafting.CraftingWeightBuffEnabled) ENDEVENT EVENT OnDefaultST() HandyCrafting.CraftingWeightBuffEnabled = TRUE ; TRUE SetToggleOptionValueST(HandyCrafting.CraftingWeightBuffEnabled) ; enabled ENDEVENT EVENT OnHighlightST() SetInfoText("$Enable_Weight_Buff_Description") ENDEVENT ENDSTATE STATE AlwaysShowMessagesState EVENT OnSelectST() HandyCrafting.AlwaysShowMessages = !HandyCrafting.AlwaysShowMessages SetToggleOptionValueST(HandyCrafting.AlwaysShowMessages) ENDEVENT EVENT OnDefaultST() HandyCrafting.AlwaysShowMessages = TRUE ; TRUE SetToggleOptionValueST(HandyCrafting.AlwaysShowMessages) ; always show messages ENDEVENT EVENT OnHighlightST() SetInfoText("$Always_Show_Messages_Description") ENDEVENT ENDSTATE STATE AddStoreSpellState EVENT OnSelectST() actor player = Game.GetPlayer() myF_SelectSpell(0) SetToggleOptionValueST(player.HasSpell(HandySpellsList[0])) ENDEVENT EVENT OnDefaultST() myF_AddSpell(0) SetToggleOptionValueST(True) ENDEVENT EVENT OnHighlightST() SetInfoText("$Add_Store_Ingedients_Power_Description") ENDEVENT ENDSTATE STATE AddMountSpellState EVENT OnSelectST() actor player = Game.GetPlayer() myF_SelectSpell(1) SetToggleOptionValueST(player.HasSpell(HandySpellsList[1])) ENDEVENT EVENT OnDefaultST() myF_AddSpell(1) SetToggleOptionValueST(True) ENDEVENT EVENT OnHighlightST() SetInfoText("$Add_Handy_Mount_Spell_Description") ENDEVENT ENDSTATE STATE AddTeleportSpellState EVENT OnSelectST() actor player = Game.GetPlayer() myF_SelectSpell(2) SetToggleOptionValueST(player.HasSpell(HandySpellsList[2])) ENDEVENT EVENT OnDefaultST() myF_AddSpell(2) SetToggleOptionValueST(True) ENDEVENT EVENT OnHighlightST() SetInfoText("$Add_Handy_Teleport_Spell_Description") ENDEVENT ENDSTATE STATE AddBOHSpellState EVENT OnSelectST() actor player = Game.GetPlayer() myF_SelectSpell(3) SetToggleOptionValueST(player.HasSpell(HandySpellsList[3])) ENDEVENT EVENT OnDefaultST() myF_AddSpell(3) SetToggleOptionValueST(True) ENDEVENT EVENT OnHighlightST() SetInfoText("$Add_Handy_BOH_Spell_Description") ENDEVENT ENDSTATE STATE HSKeyState0 EVENT OnKeyMapChangeST(Int keyCode, String conflictControl, String conflictName) myF_OnOptionKeyMapChange(0, keycode, conflictControl, conflictName) ENDEVENT EVENT OnDefaultST() UnregisterForKey(HSKeyMap[0]) HSKeyMap[0] = HSKeyDefault[0] SetKeyMapOptionValueST(-1) ENDEVENT EVENT OnHighlightST() SetInfoText("$Set_Handy_Hotkey") ENDEVENT ENDSTATE STATE HSKeyState1 EVENT OnKeyMapChangeST(Int keyCode, String conflictControl, String conflictName) myF_OnOptionKeyMapChange(1, keycode, conflictControl, conflictName) ENDEVENT EVENT OnDefaultST() UnregisterForKey(HSKeyMap[1]) HSKeyMap[1] = HSKeyDefault[1] SetKeyMapOptionValueST(-1) ENDEVENT EVENT OnHighlightST() SetInfoText("$Set_Handy_Hotkey") ENDEVENT ENDSTATE STATE HSKeyState2 EVENT OnKeyMapChangeST(Int keyCode, String conflictControl, String conflictName) myF_OnOptionKeyMapChange(2, keycode, conflictControl, conflictName) ENDEVENT EVENT OnDefaultST() UnregisterForKey(HSKeyMap[2]) HSKeyMap[2] = HSKeyDefault[2] SetKeyMapOptionValueST(-1) ENDEVENT EVENT OnHighlightST() SetInfoText("$Set_Handy_Hotkey") ENDEVENT ENDSTATE STATE HSKeyState3 EVENT OnKeyMapChangeST(Int keyCode, String conflictControl, String conflictName) myF_OnOptionKeyMapChange(3, keycode, conflictControl, conflictName) ENDEVENT EVENT OnDefaultST() UnregisterForKey(HSKeyMap[3]) HSKeyMap[3] = HSKeyDefault[3] SetKeyMapOptionValueST(-1) ENDEVENT EVENT OnHighlightST() SetInfoText("$Set_Handy_Hotkey") ENDEVENT ENDSTATE STATE UninstallState EVENT OnSelectST() IF ShowMessage("$Confirm_Uninstall") actor player = Game.GetPlayer() CloseMCM() HandyCrafting.ShutDown() UnregisterForAllKeys() player.RemoveSpell(HandySpellsList[3]) player.RemoveSpell(HandySpellsList[2]) player.RemoveSpell(HandySpellsList[1]) player.RemoveSpell(HandySpellsList[0]) IA710_cBagofHoldingREF.RemoveAllItems(player) IA710_cRetrieveStorageRef.RemoveAllItems(player) IA710_cIngredientStorageRef.RemoveAllItems(player) IA710_cTemporaryHoldingRef.RemoveAllItems(player) int i = IngredientContainerRef.Length WHILE (i > 0) i = i - 1 IngredientContainerRef[i].RemoveAllItems() ENDWHILE IA710_mUninstallMessage.Show() self.Stop() ; STOP the QUEST ENDIF ENDEVENT EVENT OnHighlightST() SetInfoText("$Uninstall_Description") ENDEVENT ENDSTATE STATE RefreshListsState EVENT OnSelectST() OnConfigInit() myF_Refresh() myF_Revert() ShowMessage("Reinitialized MCM and Refreshed all lists.", False) ENDEVENT EVENT OnHighlightST() SetInfoText("Selecting this option will reinitialize the MCM and refresh all lists") ENDEVENT ENDSTATE Still a WIP, but please let me know of any issues you notice. Once again, I can't thank you all enough. -IA710 EDIT - removed an errant " for readability from code Edited December 9, 2021 by ItsAlways710 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted December 10, 2021 Share Posted December 10, 2021 OnPlayerLoadGame event can only be ran on a player alias script. It will not function on any other script even though it will compile. If you wish to use this event, you'll need to set up a player alias and then you could, if you wish, shift the OnKeyDown event to that script as well. You could use a global variable for the key value and update it that way. It would also be useful to use an SKSE mod event to tell the player alias script to unregister and register for the key each time the player might update it in the MCM (example of that also in the mod I previously mentioned). Most of what your MCM is doing doesn't need to be put off until the end because the original author devised a way to force close the MCM. However, it is something to keep in mind. Especially if you end up doing an MCM where an option is intended to start a quest. Quests won't start until the menu is closed and from personal experience an option that starts a quest while in the MCM will cause the next mod's MCM menu to hang up. Link to comment Share on other sites More sharing options...
Recommended Posts