- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- Battery.Utility Menus help
- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- Battery.Utility Menus help
Posts: 1,491
Thanks: 4231 in 39 Posts
This is what I have managed so far. I need to figure out how to add things to the menu and how to display the menu by clicking the interaction.
using Battery.UI.Menus; public class PuddingFace_Menus { public static void AddToMenu() { bool vari; MenuContainer ExampleMenu = new Battery.UI.Menus.MenuContainer("Puddingface", "Enhanced Vampire"); MenuObject ExampleObject=new MenuObject();// This doesn't work cause MenuObject is an abstract class ExampleMenu.AddMenuObject(ExampleObject); } } public class PuddingFaceMenu : ImmediateInteraction<Sim, CityHall> { public static InteractionDefinition Singleton = new Definition(); public override bool Run() { } }
Posts: 433
Thanks: 782 in 6 Posts
first sorry that the documentation is still a mess i will work on that in the future or as an alternative provide some small code examples in a solution file
The MenuObject itself is just a baseclass that should not be just hence why its abstract.
you can either create your own menu object by inheireting from that abstract class or use one of the premade other classes.
The most generic example would be the GenericOption
Example:
MenuObject ExampleObject = new GenericOption(Name, DisplayMethod, SetValueMethod)
Name = this is a string that tells the player what this is eg "Vari"
DisplayMethod = This is the method that converts your variable into a string to display eg ()=>{return vari.ToString();}
SetValueMethod = This method will be activated when you click on the item eg ()=>{vari=!vari;}
all together
MenuObject ExampleObject = new GenericOption("Vari", ()=>{return vari.ToString();}, ()=>{vari=!vari;})
This will display Vari false in a menu and on click false will become true
There are of course other methods to use the menu the SetDictionaryOption and the CycleableMenuOption to name two.
e: be aware that in the example you gave the menu only lives withing the "public static void AddToMenu()" Method in order to redeem this just put
MenuContainer ExampleMenu; into your Class instead of the method (it would be probably also a good idea o do that with the variable you want to set
Example:
using Battery.UI.Menus; public static class PuddingFace_Menus { static bool vari; public static MenuContainer ExampleMenu; public static void AddToMenu() { ExampleMenu = new MenuContainer("Puddingface", "Enhanced Vampire"); MenuObject ExampleObject = new GenericOption("Vari", ()=>{return vari.ToString();}, ()=>{vari=!vari;}); ExampleMenu.AddMenuObject(ExampleObject); } } public class PuddingFaceMenu : ImmediateInteraction<Sim, CityHall> { public static InteractionDefinition Singleton = new Definition(); public override bool Run() { MenuController.Show(PuddingFace_Menus.ExampleMenu); //Put any Ready MenuContainer as a parameter to show it to the player. } }
Posts: 1,491
Thanks: 4231 in 39 Posts
I will create another class called GenricOption (for the trial).
Once my mod works I can help a bit with documentation.
Posts: 433
Thanks: 782 in 6 Posts
Thank you so much! I'll let you know how it went. I will create another class called GenricOption (for the trial). Once my mod works I can help a bit with documentation. |
There already is a genericoption menu object that you can use its in the menu namespace. Thanks for using the mod
And thanks for offering your help
Posts: 1,491
Thanks: 4231 in 39 Posts
Is it ok to do on World load?
Posts: 1,491
Thanks: 4231 in 39 Posts
Now to figure out a way to not add the menu object if it's already added. And change the tab 2s.
Posts: 433
Thanks: 782 in 6 Posts
sorry about the "Tab2" stuff i did some testing on that and forget to remove the test code i patch it soon tm (hopefully within an hour)*
as for the check if a menu object is already in the Menucontainer check the Menuobjectlist
ExampleMenu.mMenuObjects[0] this will get you the list of menuobjects you have added (so check if the object thats in there matches the one you want to add but i can put an id var into menu objects if you prefer)
*the good news is you can put in headers without the need of localizing them
E: Sorry for the inconvenience
i had to delay releasing the set any header text a bit since i need to do more testing
if you want to set the headers (Version 1.02b2 now uploaded with the quick fix)
ExampleMenu = new MenuContainer("Puddingface", "Enhanced Vampire"); ExampleMenu .mHeaders.Add(new ObjectPicker.HeaderInfo("Ui/Caption/ObjectPicker:Name", "Ui/Tooltip/ObjectPicker:Name", 500)); ExampleMenu .mHeaders.Add(new ObjectPicker.HeaderInfo("Ui/Caption/ObjectPicker:Name", "Ui/Tooltip/ObjectPicker:Name", 500)); MenuObject ExampleObject = new GenericOption("Vari", ()=>{return vari.ToString();}, ()=>{vari=!vari;}); ExampleMenu.AddMenuObject(ExampleObject);
"Ui/Caption/ObjectPicker:Name" is an example of the localized key for the displayed header text
"Ui/Tooltip/ObjectPicker:Name" is an example of the localized key for the displayed header tooltip text
500 how long the header is on the screen
Posts: 1,491
Thanks: 4231 in 39 Posts
Posts: 433
Thanks: 782 in 6 Posts
here is a generic SetValue Action you can use where in this case name would be your variable and nameoftype the type of it (you also can do some error checking to see if the input makes sense)
Setter = ()=>{ string value = Sims3.UI.StringInputDialog.Show("Set Value for" + name,"",name.ToString()); if(!string.IsNullOrEmpty(value)) { name = (nameoftype)Convert.ChangeType(value,typeof(nameoftype)); }
E: while this is a general method you might wan to specialize for your settings and use the tryparse method when applicable example for an int value
Setter = ()=>{ string value = Sims3.UI.StringInputDialog.Show("Set Value for" + name,"",name.ToString()); if(!string.IsNullOrEmpty(value)) { int temp; if (int.TryParse(value,out temp)) { name = temp; } }
Posts: 1,491
Thanks: 4231 in 39 Posts
if (!ExampleMenu.mMenuObjects[0].Contains(ExampleObject)) { ExampleMenu.AddMenuObject(ExampleObject); }
This gave a runtime error.
Now I'm trying this
foreach (MenuObject menuobject in ExampleMenu.mMenuObjects[0]) { if (menuobject.GetType() != ExampleObject.GetType()) { ExampleMenu.AddMenuObject(ExampleObject); } }
This also failed.
Also I wanted to ask why can't I find mMenuObjects inside MenuContainer.CS when I text search? .NET Reflector says it's there. But where?
Posts: 433
Thanks: 782 in 6 Posts
thanks for beeing my beta tester...
I had not planned for checking if a menu object is already in the Menu, thanks to you the add method will now only add menu objects which are not already in that menu (it will return false otherwise)
If you want Multiple Copies of the same MenuObject in one menu you can set the new "AllowMultipleCopiesOfOneMenuObjects" of the MenuContainer to true (default false)
Unfortunately i cant tell you why mMenuObjects isnt showing for you. (You have tried this on an Instance and not the type itself right ? )
All these new changes are included in the version 1.0.2b3 which should be available for download now
A big THANK YOU for helping to make this Utility better !
Posts: 1,491
Thanks: 4231 in 39 Posts
If you are open to more ideas I have one. You know how the add Interactions functions has a boolean to check if an interaction is already added for example
sim.AddInteraction(ShowNotification.Singleton, true);
Similarly a method for AddMenuObject that does that like this
ExampleMenu.AddMenuObject(ExampleObject, true);
could be very handy. I think it might be simpler to do on your end because you will only have to add one new function.
I'm just talking about ideas not making demands or anything. Thanks again for such a quick update and hope you're doing well.
Oh and btw the object of Menucontainer class does get mMenuObjects but when I open MenuContainer.CS using .NET reflector and then press ctrl + f to search for it. It doesn't appear. Which is what's confusing me.
Posts: 1,491
Thanks: 4231 in 39 Posts
Posts: 433
Thanks: 782 in 6 Posts
If you ant to make your data Persistent you need to:
1. add [assembly: PersistableStatic] to your Assemblyproperties like you did with [assembly: Tunable]
2. you need to decorate a static field that holds your data with the [PersistableStatic] attribute
3. you might want to use the simple Singleton Pattern for that Example below
SingletonPattern via a property
[PersistableStatic] static DataClass mOptions; public static DataClass optionen { get { if (mOptions== null) { mOptions = new DataClass(); } return mOptions; } }
Your DataClass which holds all the values must have an empty default constructor declaration
Example (continuation of the first example)
public class DataClass { ...Your Variables Here public DataClass() //Importaint !!!!!11111eleven { } }
If you want each savegame to have its own settings you need to empty the settings when quiting the game
Example
World.OnWorldQuitEventHandler += OnQuit; static void OnQuit(object sender, EventArgs e) { mOptions = null; }
I Hope this Helps.
I am now working on your suggestion and i would encourage you to make any suggestion that might be useful !
Posts: 1,491
Thanks: 4231 in 39 Posts
Posts: 433
Thanks: 782 in 6 Posts
you can also create an anonymuos Object and give it an id to check for duplications
MenuContainer.AddMenuObject(new GenericOption("Hi",()=>{return "1";},null,"MyFirstOptionID"), true);
I am still working on bringing up the auto menu to the new version but there are some changes i want to make first.
Posts: 1,491
Thanks: 4231 in 39 Posts
I tried this
[PersistableStatic] static bool vari
And it worked. I will use a better solution like what you suggested later.
In Nraas menu. You can click on one of these options to open another submenu. Do you know how this can be done?
Posts: 433
Thanks: 782 in 6 Posts
@Battery I tried this
Code:
[PersistableStatic] And it worked. I will use a better solution like what you suggested later. In Nraas menu. You can click on one of these options to open another submenu. Do you know how this can be done? |
Hi PuddingFace,
for that i have created the MenuSelectionOption
AddMenuObject(new MenuSelectionOption("Click to open",AnotherMenuContainer),true);
E: if you want to go deeper into multi stage menus there is another setup which allows you to go back and forth between menus and also allows the player to go back to the exact tab that called the menu change before
Posts: 1,491
Thanks: 4231 in 39 Posts
Posts: 433
Thanks: 782 in 6 Posts
general purpose setter
int myint = 1234; ()=>{ string value = Sims3.UI.StringInputDialog.Show("Set Value for" + myint ,"",myint .ToString()); if(!string.IsNullOrEmpty(value)) { myint = (int)Convert.ChangeType(value,typeof(int)); } }
or this save method
int myint = 1234; . . . ()=>{ string value = Sims3.UI.StringInputDialog.Show("Set Value for" + myint ,"",myint .ToString()); int temp; if(int.TryParse(value ,out temp)) // most primitives like float etc have the TryParse method aswell { myint = temp; } }
you can then use that as parameter in your generic option
Example with tryparse:
var optionint = new GenericOption("My Cool Int Setting",()=>{return myint .ToString();}, ()=>{ string value = Sims3.UI.StringInputDialog.Show("My Cool Int Setting" ,"",myint .ToString()); int temp; if(int.TryParse(value ,out temp)) // most primitives like float etc have the TryParse method aswell { myint = temp; } } );
Note you can use any parameterless Action as a setter so you could write the Setter Method for each variable you have and then use the name as the parameter
Posts: 1,491
Thanks: 4231 in 39 Posts
Posts: 1,491
Thanks: 4231 in 39 Posts
Firstly here is the code
BackButton = new MenuSelectionOption("Back", EnhancedVampiresMainMenu); InteractionsMenuButton = new MenuSelectionOption("Enhanced Vampires Interactions Menu", EnhancedVampiresInteractionsMenu); MenuObject ReadMindSkillLevelVariable = new GenericOption("", () => { return ReadMindSkillLevel.ToString(); }, () => { string value = Sims3.UI.StringInputDialog.Show("Set Value for " + ReadMindSkillLevel, "", ReadMindSkillLevel.ToString()); if (!string.IsNullOrEmpty(value)) { ReadMindSkillLevel = (int)Convert.ChangeType(value, typeof(int)); } }); //Main Menu additions EnhancedVampiresMainMenu.AddMenuObject(CompatibilityMenuButton, true); EnhancedVampiresMainMenu.AddMenuObject(InteractionsMenuButton, true); //Compatibility Menu additions EnhancedVampiresCompatibilityMenu.AddMenuObject(BackButton, true); EnhancedVampiresCompatibilityMenu.AddMenuObject(VampireBiteReplacement, true); //Interactions Menu additions EnhancedVampiresInteractionsMenu.AddMenuObject(BackButton, true); EnhancedVampiresInteractionsMenu.AddMenuObject(ReadMindSkillLevelVariable, true);
Ok so problem 1:
The buttons will open the sub menus like I want. But the back button to reopen the main menu doesn't work or it opens the new menu but without the menu objects. So a blank menu opens.
Also the buttons have a ... in the value section instead of being blank like in the Nraas menu. This is not a major problem but still reporting it.
Problem 2:
After I change the integer value and close the menu. I can't reopen it. I go to Pudding face> Enhanced Vampires option in the city hall but the menu doesn't appear. Oh and I get a script error related to UIs. I'll post this error here.
<?xml version="1.0" encoding="utf-8"?> <ScriptError Version="6" Type="MiniScriptError" MaxRecursionDepth="0"> <ExceptionData>simulating object is null unable to obtain an interaction object Argument is out of range. Parameter name: index #0: 0x0000d throw in System.Collections.Generic.System.Collections.Generic.List`1:get_Item (int) (5BE70810 [0] ) #1: 0x000d2 callvirt in Sims3.UI.Sims3.UI.ObjectPicker:RepopulateHeaders () () #2: 0x000a4 call in Sims3.UI.Sims3.UI.ObjectPicker:Populate (System.Collections.Generic.List`1,System.Collections.Generic.List`1,int) (5A1EC690 [1541878264/0x5be731f8] [1541878792/0x5be73408] [1] ) #3: 0x0000f callvirt in Battery.UI.Menus.Battery.UI.Menus.MenuController:PopulateMenu (System.Collections.Generic.List`1,System.Collections.Generic.List`1,int) (4CCB5098 [1541878264/0x5be731f8] [1541878792/0x5be73408] [1] ) #4: 0x00024 call in Battery.UI.Menus.Battery.UI.Menus.MenuController:OpenMenu (Battery.UI.Menus.MenuContainer) (4CCB5098 [3A37AE40] ) #5: 0x00036 callvirt in Battery.UI.Menus.Battery.UI.Menus.MenuSelectionOption:OnActivation (Sims3.UI.MouseKeys,Battery.UI.Menus.MenuController) (52D1C260 [1000] [4CCB5098] ) #6: 0x00037 callvirt in Battery.UI.Menus.Battery.UI.Menus.MenuController:OnTableMouseUP (Sims3.UI.WindowBase,Sims3.UI.UIMouseEventArgs) (4CCB5098 [4B7378C0] [5CBC2BD0] ) #7: 0x00000 in Sims3.UI.Sims3.UI.UIEventHandler`1:Invoke (Sims3.UI.WindowBase,Sims3.UI.UIMouseEventArgs) (4AE97DC0 [4B7378C0] [5CBC2BD0] ) #8: 0x00031 callvirt in Sims3.UI.Sims3.UI.UIEventHandlerGlue`1:Invoke (Sims3.UI.WindowBase,Sims3.UI.UIEventArgs) (4B740740 [4B7378C0] [5CBC2BD0] ) #9: 0x000a7 callvirt in Sims3.UI.Sims3.UI.UIManager:ProcessEvent (uint,uint,Sims3.UI.WindowBase,Sims3.UI.WindowBase,int,int&,int,single,single,single,single,bool&,string) ([819443748] [7] [00000000] [4B7378C0] [1000] [1733048928] [0] [304] [17] [0] [0] [601485360] [3A158380] ) #10: 0x00046 call in Sims3.UI.Sims3.UI.UIManager:ProcessEvent (uint,uint,uint,uint,int,int,int,single,single,single,single,bool&,string) ([819443748] [7] [0] [819443748] [1000] [1000] [0] [304] [17] [0] [0] [601485360] [3A158380] ) #11: 0x00034 call in Sims3.UI.Sims3.UI.UIManager:ProcessEventCallback (uint,uint,uint,uint,int,int,int,single,single,single,single,bool&,string) ([819443748] [7] [0] [819443748] [1000] [1000] [0] [304] [17] [0] [0] [601485360] [3A158380] ) #12: 0x00000 in Sims3.SimIFace.Sims3.SimIFace.UIEventCallback:Invoke (uint,uint,uint,uint,int,int,int,single,single,single,single,bool&,string) (3B1A8DE8 [819443748] [7] [0] [819443748] [1000] [1000] [0] [304] [17] [0] [0] [601485360] [3A158380] ) </ExceptionData> <GameData> <BuildType>Release Mono</BuildType> <CommandLine>F:\Electronic Arts\The Sims 3\Game\Bin\TS3W.exe</CommandLine> <Game_Version>21.0.150.024001</Game_Version> <Code_Version>0.RL-2.0.209</Code_Version> <Content_Version>1.Content.rl.41</Content_Version> <Thumbnail_Version>1.Thumbnail.dl.933</Thumbnail_Version> <TCC_Version>1.TCC.dl.1209</TCC_Version> <Build_Version>0.2.0.209</Build_Version> <Type>Release</Type> <Timestamp>2014-01-16-1625</Timestamp> <CPU_Level>High</CPU_Level> <GPU_Level>Uber</GPU_Level> <Game_Start>2020-04-02 18:44:31</Game_Start> <Data>F:\Electronic Arts\The Sims 3/GameData\</Data> <Overrides>(none)</Overrides> <Exe_Path>F:\Electronic Arts\The Sims 3\Game\Bin\</Exe_Path> <User>slcbuilder</User> <Host>SLC1-BUILD111</Host> </GameData> </ScriptError>
Posts: 433
Thanks: 782 in 6 Posts
the ... was a decision i made but if you rather want it to be blank its not a problem i will change that.
could you upload your mod so that i can have a look at the links between the single code pieces ? (either on the mts discord or via an pm link to an upload)
As for the going back thing there is another option that would not require you to add an extra option.
Posts: 1,491
Thanks: 4231 in 39 Posts
I think it looks better as a blank as opposed to ... . The Nraas menu had a cleaner look with the blank I feel. But it's your decision.
Posts: 433
Thanks: 782 in 6 Posts
@Battery Ok I will post the mod here. Should I upload the whole project or just the DLL file? I'll post it tomorrow. I think it looks better as a blank as opposed to ... . The Nraas menu had a cleaner look with the blank I feel. But it's your decision. |
Ok done no ... anymore for the menu selection
i just want to have a look at the complete code to see how the menu is intended to work within your project so that i can provide a solution, since i was not able to reproduce the error myself with a few tests
Who Posted
|