Kalambre Posted August 28, 2018 Share Posted August 28, 2018 Hi, this question is for MCM experts. I need a list of toggle options to validate all armor slots (slot 30 to slot 60) in the MCM, so I'm trying to use arrays to avoid tons of states, I think I know how to do it using the old method, but I prefer to use state-based method if possible because my MCM uses states for all other options. A bool value for each slot is stored in a json file, so I need to get this value, show it in MCM, change value if needed, and save changes in json file. I've tried this code: Bool[] SlotTrigger SlotTrigger = new Bool[61] ;This is the array for slot values Int SlotIndex = 30 String SlotsFile ;This is the json file path While SlotIndex < 61 SlotTrigger[SlotIndex] = JSONUtil.GetIntValue(SlotsFile, "boolslot" + SlotIndex) ArmorSlot = ("Slot" + SlotIndex) AddToggleOptionST("ArmorSlot"+SlotIndex, "Armor Slot " + SlotIndex, SlotTrigger[SlotIndex]) SlotIndex += 1 EndWhile Well, toggle options for all slot are shown in the MCM and bool values are correct, but I don't know how to connect this to OnSelectST() or OnDefaultST() events in order to change values. Thanks in advance. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted August 28, 2018 Share Posted August 28, 2018 I did something similar. I've not released it publicly yet. I should. I keep forgetting to double check that it works still and let others convert it to SSE for their personal use. At any rate, I have multiple containers with the same choices and I used a combination of global variable formlists and internal arrays to keep track of choices. I even allow for saving and restoring the selections via FISS. Breaking down just one of those... This is the state used just to toggle one container to be used or not. State ToggleState0 Event OnSelectST() Int index = 0 If (cbc0 < ComponentBehave.length - 2) cbc0 += 1 Else cbc0 = 0 EndIf ComponentChoice[index] = cbc0 SetTextOptionValueST(ComponentBehave[cbc0]) If ComponentChoice[index] != 0 SetOptionFlagsST(OPTION_FLAG_NONE, false, "AutoSortState"+index) SetOptionFlagsST(OPTION_FLAG_NONE, false, "Weightless"+index) SetOptionFlagsST(OPTION_FLAG_NONE, false, "MerchExcl"+index) Else AutoStoreChoice[index] = 0 SetTextOptionValueST(AutoStoreBehave[0], false, "AutoSortState"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "AutoSortState"+index) WeightlesActive[index] = false SetToggleOptionValueST(WeightlesActive[index],false,"Weightless"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "Weightless"+index) MerchExclActive[index] = false SetToggleOptionValueST(MerchExclActive[index],false,"MerchExcl"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "MerchExcl"+index) RedoItemsActive[index] = false SetToggleOptionValueST(RedoItemsActive[index],false,"RedoItems"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "RedoItems"+index) EndIf EndEvent Event OnDefaultST() Int index = 0 ComponentChoice[index] = 0 SetTextOptionValueST(ComponentBehave[0]) AutoStoreChoice[index] = 0 SetTextOptionValueST(AutoStoreBehave[0], false, "AutoSortState"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "AutoSortState"+index) WeightlesActive[index] = false SetToggleOptionValueST(WeightlesActive[index],false,"Weightless"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "Weightless"+index) MerchExclActive[index] = false SetToggleOptionValueST(MerchExclActive[index],false,"MerchExcl"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "MerchExcl"+index) RedoItemsActive[index] = false SetToggleOptionValueST(RedoItemsActive[index],false,"RedoItems"+index) SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "RedoItems"+index) EndEvent Event OnHighlightST() SetInfoText("$AlchToggleInfo") EndEvent EndState This is where I save all the options in the preset: import FISSFactory State SavePreset Event OnSelectST() PresetSave = !PresetSave SetToggleOptionValueST(PresetSave) ShowMessage("$SavingPrest") FISSInterface fiss = FISSFactory.getFISS() If fiss fiss.beginSave("IMS_MCM_Preset.xml","Inventory Management System") Int ix = 0 While ix < ComponentChoice.Length fiss.saveInt("abim_IMS_ComponentChoice"+ix,ComponentChoice[ix]) fiss.saveInt("abim_IMS_AutoStoreChoice"+ix,AutoStoreChoice[ix]) fiss.saveBool("abim_IMS_WeightlesActive"+ix,WeightlesActive[ix]) fiss.saveBool("abim_IMS_MerchExclActive"+ix,MerchExclActive[ix]) ix += 1 EndWhile Int ixA = 0 While ixA < ArrowArrayIndex.Length fiss.saveInt("abim_IMS_ArrowArrayIndex"+ixA,ArrowArrayIndex[ixA]) ixA += 1 EndWhile Int ixB = 0 While ixB < BoltArrayIndex.Length fiss.saveInt("abim_IMS_BoltArrayIndex"+ixB,BoltArrayIndex[ixB]) ixB += 1 EndWhile String SaveResult = fiss.endSave() If SaveResult != "" ShowMessage("$Error saving file") Else ShowMessage("$Success saving file") EndIf EndIf PresetSave = !PresetSave SetToggleOptionValueST(PresetSave) EndEvent Event OnDefaultST() PresetSave = false EndEvent Event OnHighlightST() If FissActive == true SetInfoText("$SavePresetInfo") EndIf EndEvent EndState This is where I retrieve all the options in the preset State LoadPreset Event OnSelectST() PresetLoad = !PresetLoad SetToggleOptionValueST(PresetLoad) If PresetLoad == true ShowMessage("$LoadingPreset") FISSInterface fiss = FISSFactory.getFISS() If fiss fiss.beginLoad("IMS_MCM_Preset.xml") Int ix = 0 While ix < ComponentChoice.Length ComponentChoice[ix] = fiss.loadInt("abim_IMS_ComponentChoice"+ix) AutoStoreChoice[ix] = fiss.loadInt("abim_IMS_AutoStoreChoice"+ix) WeightlesActive[ix] = fiss.loadBool("abim_IMS_WeightlesActive"+ix) MerchExclActive[ix] = fiss.loadBool("abim_IMS_MerchExclActive"+ix) ix += 1 EndWhile Int ixA = 0 While ixA < ArrowArrayIndex.Length ArrowArrayIndex[ixA] = fiss.loadInt("abim_IMS_ArrowArrayIndex"+ixA) ArrowIndex[ixA] = 0 If ArrowArrayIndex[ixA] >= 0 ArrowIndex[ixA] = ArrowArrayIndex[ixA] EndIf ixA += 1 EndWhile Int ixB = 0 While ixB < BoltArrayIndex.Length BoltArrayIndex[ixB] = fiss.loadInt("abim_IMS_BoltArrayIndex"+ixB) BoltIndex[ixB] = 0 If BoltArrayIndex[ixB] >= 0 BoltIndex[ixB] = BoltArrayIndex[ixB] EndIf ixB += 1 EndWhile String LoadResult = fiss.endLoad() If LoadResult != "" ShowMessage("$Error reading file") Else ShowMessage("$Success reading file") asc0 = AutoStoreChoice[0] asc1 = AutoStoreChoice[1] asc2 = AutoStoreChoice[2] asc3 = AutoStoreChoice[3] asc4 = AutoStoreChoice[4] asc5 = AutoStoreChoice[5] asc6 = AutoStoreChoice[6] asc7 = AutoStoreChoice[7] asc8 = AutoStoreChoice[8] asc9 = AutoStoreChoice[9] asc10 = AutoStoreChoice[10] asc11 = AutoStoreChoice[11] asc12 = AutoStoreChoice[12] asc13 = AutoStoreChoice[13] asc14 = AutoStoreChoice[14] asc15 = AutoStoreChoice[15] asc16 = AutoStoreChoice[16] cbc0 = ComponentChoice[0] cbc1 = ComponentChoice[1] cbc2 = ComponentChoice[2] cbc3 = ComponentChoice[3] cbc4 = ComponentChoice[4] cbc5 = ComponentChoice[5] cbc6 = ComponentChoice[6] cbc7 = ComponentChoice[7] cbc8 = ComponentChoice[8] cbc9 = ComponentChoice[9] cbc10 = ComponentChoice[10] cbc11 = ComponentChoice[11] cbc12 = ComponentChoice[12] cbc13 = ComponentChoice[13] cbc14 = ComponentChoice[14] cbc15 = ComponentChoice[15] cbc16 = ComponentChoice[16] EndIf EndIf EndIf PresetLoad = !PresetLoad SetToggleOptionValueST(PresetLoad) EndEvent Event OnDefaultST() PresetLoad = false EndEvent Event OnHighlightST() If FissActive == true SetInfoText("$LoadPresetInfo") EndIf EndEvent EndState The relevant section of the OnPageReset for the container referenced above. AddHeaderOption("$Alchemy Supplies") AddTextOptionST("ToggleState"+0, "$Use Alchemy Supplies", ComponentBehave[cbc0]) If ComponentChoice[0] == 0 AddTextOptionST("AutoSortState"+0,"$Auto-Store", AutoStoreBehave[asc0],OPTION_FLAG_DISABLED) AddToggleOptionST("Weightless"+0,"$Weightless", WeightlesActive[0],OPTION_FLAG_DISABLED) AddToggleOptionST("MerchExcl"+0,"$MerchExcl", MerchExclActive[0],OPTION_FLAG_DISABLED) AddToggleOptionST("RedoItems"+0,"$RedoItems", RedoItemsActive[0],OPTION_FLAG_DISABLED) Else AddTextOptionST("AutoSortState"+0,"$Auto-Store", AutoStoreBehave[asc0],OPTION_FLAG_NONE) AddToggleOptionST("Weightless"+0,"$Weightless", WeightlesActive[0],OPTION_FLAG_NONE) AddToggleOptionST("MerchExcl"+0,"$MerchExcl", MerchExclActive[0],OPTION_FLAG_NONE) If AutoStoreChoice[0] != 0 AddToggleOptionST("RedoItems"+0,"$RedoItems", RedoItemsActive[0],OPTION_FLAG_NONE) Else AddToggleOptionST("RedoItems"+0,"$RedoItems", RedoItemsActive[0],OPTION_FLAG_DISABLED) EndIf EndIf I hope this helps. Link to comment Share on other sites More sharing options...
Kalambre Posted August 28, 2018 Author Share Posted August 28, 2018 Thanks for your reply, I use a similar state to save/load settings but I need to save slots setings in a different file because I validate them at least 2 times: for player and for NPCs. So I had thought about an "array of states" that can be called repeatedly, but not sure if it's possible. I've tryed using a strings array to name states: State Slot[index]EndState But I get a error, seems that it only supports simple strings for StateName... Link to comment Share on other sites More sharing options...
IsharaMeradin Posted August 28, 2018 Share Posted August 28, 2018 It isn't really an array as the states have to be explicitly written out for each one but you can refer to them as if it were an array. If you look at the OnPageReset portion that I posted you'll see where a state is referenced as "ToggleState"+0 This is because the state itself is labeled "ToggleState0" It allows one to use repeating code for the states and just change the referencing number according to which option will be targeting that state. Link to comment Share on other sites More sharing options...
Kalambre Posted August 28, 2018 Author Share Posted August 28, 2018 It isn't really an array as the states have to be explicitly written out for each one but you can refer to them as if it were an array. If you look at the OnPageReset portion that I posted you'll see where a state is referenced as "ToggleState"+0 This is because the state itself is labeled "ToggleState0" It allows one to use repeating code for the states and just change the referencing number according to which option will be targeting that state.So, I can name a state as a string + an Int? I'll try tomorrow, if not, I'll try the old MCm way, since each option is asigned to an Int, maybe I can validate them to set each togle option. Link to comment Share on other sites More sharing options...
Kalambre Posted August 29, 2018 Author Share Posted August 29, 2018 After trying hundreds of options using states, sometimes it worked, but i was having other issues: data not saved in files, options disappear when reloading page... Finally, I've opted for the old way, I've used one array to store optionID and other to store bool values for each toggle option, not sure if it is the most effective way but it works... Now I can set and save changes validating them in the OnOptionSelect event: Event OnOptionSelect(Int optID) Int OptionIndex = 0 While OptionIndex < 31 If optID == OptionID[OptionIndex] OptionBool[OptionIndex] = !OptionBool[OptionIndex] SetToggleOptionValue(optID, OptionBool[OptionIndex]) SlotNumber = OptionIndex + 30 JSONUtil.SetIntValue(SlotsFile, "boolslot" + SlotNumber, OptionBool[OptionIndex] as Int) JSONUtil.Save(SlotsFile, true) EndIf OptionIndex += 1 EndWhile EndEvent Link to comment Share on other sites More sharing options...
IsharaMeradin Posted August 29, 2018 Share Posted August 29, 2018 Glad you got something to work. Link to comment Share on other sites More sharing options...
cdcooley Posted August 30, 2018 Share Posted August 30, 2018 There is a way to do this with the state method too and it's fairly easy. You don't ever create the actual "ArmorSlot"+SlotIndex states in your script. Instead you put the OnSelectST() and OnDefaultST() events in the default script state (outside of any named state) and then use something like: int OptionIndex = StringUtil.SubString(GetState(),9,2)) as intto pull that numeric part of the state name when you need it. Scripts can switch to states that aren't actually defined and when they do that any event or function calls will use the code defined in the main level of the script. So without testing I think your event above could be written: Event OnSelectST() Int OptionIndex = StringUtil.SubString(GetState(),9,2)) as int OptionBool[OptionIndex] = !OptionBool[OptionIndex] SetToggleOptionValueST(GetState(), OptionBool[OptionIndex]) SlotNumber = OptionIndex + 30 JSONUtil.SetIntValue(SlotsFile, "boolslot" + SlotNumber, OptionBool[OptionIndex] as Int) JSONUtil.Save(SlotsFile, true) EndEvent Link to comment Share on other sites More sharing options...
Kalambre Posted August 30, 2018 Author Share Posted August 30, 2018 Interesting... I suppose GetState() give me current state name, true?I'm not familiar with StrigUtil functions, and I didn't know that this kind of function was available. And probably it's fater and more efficient because don't need a "while" loop. I'll try, thanks. Link to comment Share on other sites More sharing options...
cdcooley Posted August 31, 2018 Share Posted August 31, 2018 Yes, GetState() gives you the current state name as a string. And I know the concept works (even if I have some error in that code) because I use the technique in my Storage Helpers mod. Link to comment Share on other sites More sharing options...
Recommended Posts