iamzip Posted July 17, 2020 Posted July 17, 2020 I'm working on my first scripted mod, dynamically altering racemenu overlay colors based on a variety of selectable factors, and I'm running into an issue. My MCM script is getting huge and I've hit some kind of limit when adding all the state option definitions. I get to a point where if I add more lines of code, or maybe character limit, I get an error in the CK saying that the script was unable to load, even though it compiles fine. Am I missing something about a character limit or a lines of code limit somewhere? Is it possible to offload state definitions to secondary scripts? For reference I've attached what I have so far for the MCM script. Thank you for any help, I'm very new to scripting. zao_menu_script.psc
blank_v Posted July 18, 2020 Posted July 18, 2020 I think there may be limit of: 32768 characters lenght for Scripts minus Comments ofc. But I'm not sure... there is some scipts that are bigger than 32k ( thats 2^15 - almost 2 bytes ) Maybe split your Script to few files? Btw. first time i see 150k+ Script xD Biggest i saw till this moment was 51kb ( - Comments ofc. ) Biggest i wrote was 21k ( compiled )
Seijin8 Posted July 18, 2020 Posted July 18, 2020 1 hour ago, iamzip said: I'm working on my first scripted mod, dynamically altering racemenu overlay colors based on a variety of selectable factors, and I'm running into an issue. My MCM script is getting huge and I've hit some kind of limit when adding all the state option definitions. I get to a point where if I add more lines of code, or maybe character limit, I get an error in the CK saying that the script was unable to load, even though it compiles fine. Am I missing something about a character limit or a lines of code limit somewhere? Is it possible to offload state definitions to secondary scripts? For reference I've attached what I have so far for the MCM script. Thank you for any help, I'm very new to scripting. zao_menu_script.psc 153.15 kB · 3 downloads I have a large script I run normally that is a bit larger than yours in total character count and line length. I don't think string limits are the issue here. EDIT: I should note though that I don't use the CK for writing or compiling scripts.
iamzip Posted July 18, 2020 Author Posted July 18, 2020 I actually an not using the CK to write or comple either, and even compiling in the CK works ok when I checked that. The issue comes up when I try to attach or edit an already attached instance of the script, I get the error saying the script failed somehow and won't be attached. I've tried offloading some of the non-state functions but adding more states for the MCM still causes the error to pop up. Is there a limit on how many states I can set up in a single script? And is it possible to offload state definitions to a sub script?
Seijin8 Posted July 18, 2020 Posted July 18, 2020 6 minutes ago, iamzip said: I get the error saying the script failed somehow It would help to know exactly what the error is.
iamzip Posted July 18, 2020 Author Posted July 18, 2020 39 minutes ago, Seijin8 said: It would help to know exactly what the error is. If I try to add the script it says: script "zao_menu_script" had errors while loading, it will not be added to the object. If I try editing it in an already attached quest it says: Error encountered while attempting to reload the script. If I then remove a few of the state definitions it starts working again. In either case it compiles fine.
iamzip Posted July 18, 2020 Author Posted July 18, 2020 https://forums.nexusmods.com/index.php?/topic/6111118-splitting-mcm-menu-into-multiple-smaller-scripts/page-1 I found this in my search, given the number of options I'm presenting I suspect this is my issue, despite the error messages not matching. I'll have to give the listed solution an attempt once I figure out the optionID method.
Monoman1 Posted July 18, 2020 Posted July 18, 2020 Chances are states are limited to 128. I'm just guessing here but states are probably stored in a string array which are limited to 128. Script variables are also limited. I've recently hit that limit in Survivals mcm script. But I've since clawed back variable space by using storageutil. I'm not sure what the actual limit is but it is surprisingly low. Or at least I was surprised.
iamzip Posted July 18, 2020 Author Posted July 18, 2020 Spoiler Example of me use State "" in MCM, it look like old format doesn't it? Without integers, but using States Event OnInputOpenST() Int a_index String sResult = GetState() Int nClone = FDQMain.nCloneTypeID While(a_index < nClone) If(sResult == "INPUT_POSITION_X_STATE" + a_index) Float fTemp = FDQMain.fSetPositionX[a_index] SetInputDialogStartText(fTemp As Int) ElseIf(sResult == "INPUT_POSITION_Y_STATE" + a_index) Float fTemp = FDQMain.fSetPositionY[a_index] SetInputDialogStartText(fTemp As Int) ElseIf(sResult == "INPUT_ROTATION_Z_STATE" + a_index) Float fTemp = FDQMain.fSetAngleZ[a_index] SetInputDialogStartText(fTemp As Int) EndIf a_index +=1 EndWhile EndEvent One of the workarounds in the linked thread has promise, using while loops in the events to use getstate() as If gates instead of as actual states. Every script I looked at to try to understand how to do what I'm trying defined each state rather than using while loops so it didn't occur to me to treat the MCM events just like any other event. I'm going to give that a shot when I get time.
Fotogen Posted July 18, 2020 Posted July 18, 2020 I counted 125 different states. Plus "main", null state its 126 and maybe i missed one ... Papyrus limit is 127. You are fucked up. You'll need to redesign/rethink the whole MCM thing.
Guest Posted July 19, 2020 Posted July 19, 2020 On 7/17/2020 at 8:54 PM, iamzip said: I'm working on my first scripted mod, dynamically altering racemenu overlay colors based on a variety of selectable factors, and I'm running into an issue. My MCM script is getting huge and I've hit some kind of limit when adding all the state option definitions. I get to a point where if I add more lines of code, or maybe character limit, I get an error in the CK saying that the script was unable to load, even though it compiles fine. Am I missing something about a character limit or a lines of code limit somewhere? Is it possible to offload state definitions to secondary scripts? For reference I've attached what I have so far for the MCM script. Thank you for any help, I'm very new to scripting. zao_menu_script.psc 153.15 kB · 7 downloads Just took a quick look and what I've noticed is that most of your data can be packed into mapped and multi-dimensional arrays. While Papyrus doesn't support these, you can use JContainers or something similar and then restructure your statemachine into sections rather than individual options. Doing it like this will also prevent namespace pollution. I would strongly suggest against splitting them into multiple MCM entries. MCM pollution is a real pain in the ass and honestly, if you need something like that your design is flawed. P.S. The character limit on a Papyrus script is completely bullshit. The PapyrusVM buffers blocks of bytecode into memory. Most of the abstraction from a source code file is lost when it's compiled into PapyrusVM bytecode (.pex). As long as you don't have huge ass bytecode functions, your source code can be as big as you want. There are 123 (as counted by Notepad++) EndState statements, so there is a maximum of 124 states within the posted script.
iamzip Posted July 21, 2020 Author Posted July 21, 2020 For posterity, in case somebody else has too many MCM options for states, after some research and digging through a few scripts I was able to get all of my options using the MCM events and without resorting to OID spam. Updated script attached, significantly reduced line count too. On 7/18/2020 at 5:19 PM, Hawk9969 said: Just took a quick look and what I've noticed is that most of your data can be packed into mapped and multi-dimensional arrays. While Papyrus doesn't support these, you can use JContainers or something similar and then restructure your statemachine into sections rather than individual options. Doing it like this will also prevent namespace pollution. I would strongly suggest against splitting them into multiple MCM entries. MCM pollution is a real pain in the ass and honestly, if you need something like that your design is flawed. I agree on JContainers and now that I have a better handle on scripting I might go back and see if I can implement that, but when I first looked into them I couldn't make sense of how they worked. Also totally agree on not splitting MCMs, I have so many in my LO already I don't feel my stuff is so important that it should take 2 slots. zao_menu_script.psc
Guest Posted July 21, 2020 Posted July 21, 2020 9 hours ago, iamzip said: For posterity, in case somebody else has too many MCM options for states, after some research and digging through a few scripts I was able to get all of my options using the MCM events and without resorting to OID spam. Updated script attached, significantly reduced line count too. I agree on JContainers and now that I have a better handle on scripting I might go back and see if I can implement that, but when I first looked into them I couldn't make sense of how they worked. Also totally agree on not splitting MCMs, I have so many in my LO already I don't feel my stuff is so important that it should take 2 slots. zao_menu_script.psc 106.29 kB · 0 downloads Just create an object and then use the returned int to access or modify that object. Use retain to keep the object alive and serialized into the co-save, and release if you ever need to free it. Example into turning 4 global variables from your script into a JC map. int property PulseDriver auto hidden ... init PulseDriver .... PulseDriver = JValue.retain(JMap.object()) JMap.setObj(PulseDriver, "Body", JArray.object()) JMap.setObj(PulseDriver, "Hand", JArray.object()) JMap.setObj(PulseDriver, "Feet", JArray.object()) JMap.setObj(PulseDriver, "Face", JArray.object()) ... int Function FindPulseDriver(string part, string driver) int arr = JMap.getObj(PulseDriver, part) if arr == 0 return -2 endif return JArray.findStr(arr, driver) EndFunction bool Function AddPulseDriver(string part, string driver) int idx = FindPulseDriver(part, driver) if idx >= 0 return true elseif idx != -1 return false endif JArray.addStr(JMap.getObj(PulseDriver, part), driver) return true EndFunction Or you can use JDB: string property ModKeyBase = "my_mod_key_base" autoReadonly string Function Key(string k) return "." + ModKeyBase + "." + k EndFunction ... init main map JDB.setObj(ModKeyBase, JValue.retain(JMap.object())) ... ... init PulseDriver ... JDB.solveObjSetter(Key("PulseDriver.Body"), JArray.object(), createMissingKeys=true) JDB.solveObjSetter(Key("PulseDriver.Hand"), JArray.object(), createMissingKeys=true) JDB.solveObjSetter(Key("PulseDriver.Feet"), JArray.object(), createMissingKeys=true) JDB.solveObjSetter(Key("PulseDriver.Face"), JArray.object(), createMissingKeys=true) ... int Function FindPulseDriver(string part, string driver) int arr = JDB.solveObj(Key("PulseDriver." + part)) if arr == 0 return -2 return JArray.findStr(arr, driver) EndFunction bool Function AddPulseDriver(string part, string driver) int idx = FindPulseDriver(part, driver) if idx >= 0 return true elseif idx != -1 return false endif JArray.addStr(JDB.solveObj(Key("PulseDriver." + part)), driver) return true EndFunction
iamzip Posted July 22, 2020 Author Posted July 22, 2020 21 hours ago, Hawk9969 said: Example into turning 4 global variables from your script into a JC map. Thank you for this, once I wrap my head around this stuff it should clean things up a lot.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.