# IH ivar & menu declaration schema (standalone) *Shard of mgsv-modding-pack — generated 2026-08-13. 1 files. Provenance is on every entry as `source:path`.* The complete ivar and menu declaration schema, copied from real IH source, pulled into its own small shard because in the big ih-contract shard it sits thousands of lines deep and models reading through a summarizer never reach it. Fetch THIS when you need to wire an ivar or menu, not the whole contract. ## Verified reference (local) — schemas copied from real IH source ### `reference_local:ivar-and-menu-declarations.md` #### Complete ivar and menu declaration schema **Confidence:** VERIFIED — copied verbatim from Infinite Heaven's own modules (`ih_kap:.../mod/modules/InfWeather.lua` and siblings). The `ih-framework` listings show ivar *usage* everywhere but elide the *declaration* bodies; this fills that gap with real source so a module doesn't have to invent the schema and risk a silent load failure. ##### registerIvars Two parts: a name list, then one table per ivar named `this.`. ```lua this.registerIvars = { "weather_forceType", "weather_fogDensity", "weather_fogType", } -- an enum/dropdown ivar this.weather_forceType = { inMission = true, settings = { "NONE", "SUNNY", "CLOUDY", "RAINY", "SANDSTORM", "FOGGY" }, OnChange = OnChangeWeather, } -- a numeric slider ivar this.weather_fogDensity = { save = IvarProc.CATEGORY_EXTERNAL, range = { min = 0, max = 1.0, increment = 0.01 }, default = 0.1, OnChange = OnChangeWeather, } -- an action ivar (a button that runs code, not a stored value) this.weather_requestTag = { settings = this.weatherTags, OnActivate = function(self, setting) local tag = self.settings[setting + 1] WeatherManager.RequestTag(tag, ivars.weather_requestTagInterpTime) end, } ``` ##### The field vocabulary Counts are how many times each field appears across all shipped IH modules — a high count means it's load-bearing and safe to rely on. | field | ~uses | meaning | |---|---|---| | `range` | 344 | `{min, max, increment}` — makes it a numeric slider | | `save` | 338 | persistence category, e.g. `IvarProc.CATEGORY_EXTERNAL` | | `OnChange` | 161 | function called when the value changes | | `inMission` | 145 | whether it applies/shows during a mission | | `default` | 124 | initial value | | `settings` | 103 | array of strings — makes it an enum/dropdown | | `OnActivate` | 44 | function for an action ivar (self, setting) | | `category` | 1 | rare grouping field | An ivar with `range` is a slider; with `settings` it's a dropdown; with `OnActivate` and no stored value it's a button. Read the live value as `ivars.`. ##### registerMenus Same pattern: a name list, then one table per menu. ```lua this.registerMenus = { "weatherMenu" } this.weatherMenu = { parentRefs = { "InfMenuDefs.safeSpaceMenu", "InfMenuDefs.inMissionMenu", "InfMenuDefs.inDemoMenu", }, options = { "InfWeather.weather_forceType", -- an ivar, by "Module.ivarName" "InfWeather.weather_fogDensity", "InfWeather.SetSkyParameters", -- or a function on the module }, } ``` `parentRefs` attaches the menu under existing IH menus; `options` lists ivars (as `"Module.ivarName"`) and module functions in display order. ##### Why this matters Inventing the ivar schema and getting a field name wrong is a nil-index at load, which under Fox Engine drops the whole module with no error (see the silent-drop note in the hard rules). Copy these shapes rather than guessing them.