<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://chronocrash.com/openbor/wiki/index.php?action=history&amp;feed=atom&amp;title=Model_Lifecycle_Scripts</id>
	<title>Model Lifecycle Scripts - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://chronocrash.com/openbor/wiki/index.php?action=history&amp;feed=atom&amp;title=Model_Lifecycle_Scripts"/>
	<link rel="alternate" type="text/html" href="https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;action=history"/>
	<updated>2026-08-25T07:23:06Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;diff=1074&amp;oldid=prev</id>
		<title>Dcurrent at 03:49, 22 August 2026</title>
		<link rel="alternate" type="text/html" href="https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;diff=1074&amp;oldid=prev"/>
		<updated>2026-08-22T03:49:31Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:49, 21 August 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Model]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Model]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Script]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Script]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Script Events]]&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Model lifecycle scripts&amp;#039;&amp;#039;&amp;#039; are event hooks that execute when a model template enters or leaves OpenBOR&amp;#039;s loaded model collection. The series provides project-wide global observers and model-owned callbacks for both load and unload transitions.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Model lifecycle scripts&amp;#039;&amp;#039;&amp;#039; are event hooks that execute when a model template enters or leaves OpenBOR&amp;#039;s loaded model collection. The series provides project-wide global observers and model-owned callbacks for both load and unload transitions.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l296&quot;&gt;Line 296:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 294:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Models]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Models]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Script Overview]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Script Overview]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Openbor]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Dcurrent</name></author>
	</entry>
	<entry>
		<id>https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;diff=1068&amp;oldid=prev</id>
		<title>Dcurrent: Dcurrent moved page Model Load Scripts to Model Lifecycle Scripts: Misspelled title</title>
		<link rel="alternate" type="text/html" href="https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;diff=1068&amp;oldid=prev"/>
		<updated>2026-08-22T03:45:24Z</updated>

		<summary type="html">&lt;p&gt;Dcurrent moved page &lt;a href=&quot;/openbor/wiki/index.php/Model_Load_Scripts&quot; class=&quot;mw-redirect&quot; title=&quot;Model Load Scripts&quot;&gt;Model Load Scripts&lt;/a&gt; to &lt;a href=&quot;/openbor/wiki/index.php/Model_Lifecycle_Scripts&quot; title=&quot;Model Lifecycle Scripts&quot;&gt;Model Lifecycle Scripts&lt;/a&gt;: Misspelled title&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:45, 21 August 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Dcurrent</name></author>
	</entry>
	<entry>
		<id>https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;diff=1067&amp;oldid=prev</id>
		<title>Dcurrent: Created page with &quot;Category:Model Category:Script Category:Script Events  &#039;&#039;&#039;Model lifecycle scripts&#039;&#039;&#039; are event hooks that execute when a model template enters or leaves OpenBOR&#039;s loaded model collection. The series provides project-wide global observers and model-owned callbacks for both load and unload transitions.  {| class=&quot;wikitable&quot; ! Hook ! Scope ! Execution point |- | &lt;code&gt;modelloadscript&lt;/code&gt; | Model-owned | After that model finishes loading |- | &lt;code&gt;data/script...&quot;</title>
		<link rel="alternate" type="text/html" href="https://chronocrash.com/openbor/wiki/index.php?title=Model_Lifecycle_Scripts&amp;diff=1067&amp;oldid=prev"/>
		<updated>2026-08-22T03:44:33Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&lt;a href=&quot;/openbor/wiki/index.php/Category:Model&quot; title=&quot;Category:Model&quot;&gt;Category:Model&lt;/a&gt; &lt;a href=&quot;/openbor/wiki/index.php/Category:Script&quot; title=&quot;Category:Script&quot;&gt;Category:Script&lt;/a&gt; &lt;a href=&quot;/openbor/wiki/index.php/Category:Script_Events&quot; title=&quot;Category:Script Events&quot;&gt;Category:Script Events&lt;/a&gt;  &amp;#039;&amp;#039;&amp;#039;Model lifecycle scripts&amp;#039;&amp;#039;&amp;#039; are event hooks that execute when a model template enters or leaves OpenBOR&amp;#039;s loaded model collection. The series provides project-wide global observers and model-owned callbacks for both load and unload transitions.  {| class=&amp;quot;wikitable&amp;quot; ! Hook ! Scope ! Execution point |- | &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; | Model-owned | After that model finishes loading |- | &amp;lt;code&amp;gt;data/script...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Category:Model]]&lt;br /&gt;
[[Category:Script]]&lt;br /&gt;
[[Category:Script Events]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Model lifecycle scripts&amp;#039;&amp;#039;&amp;#039; are event hooks that execute when a model template enters or leaves OpenBOR&amp;#039;s loaded model collection. The series provides project-wide global observers and model-owned callbacks for both load and unload transitions.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Hook&lt;br /&gt;
! Scope&lt;br /&gt;
! Execution point&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt;&lt;br /&gt;
| Model-owned&lt;br /&gt;
| After that model finishes loading&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;data/scripts/modelload.c&amp;lt;/code&amp;gt;&lt;br /&gt;
| Project-wide&lt;br /&gt;
| After the loaded model&amp;#039;s &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt;&lt;br /&gt;
| Model-owned&lt;br /&gt;
| Before that model begins native destruction&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;data/scripts/modelunload.c&amp;lt;/code&amp;gt;&lt;br /&gt;
| Project-wide&lt;br /&gt;
| After the model&amp;#039;s &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt;, before native destruction&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Model lifecycle is distinct from entity lifecycle. Loading a model makes its template available for spawning one or many entities. Unloading removes that template from active memory. Neither transition represents an entity spawn, death, or removal.&lt;br /&gt;
&lt;br /&gt;
This distinction makes the series useful for model registries, template-specific initialization, dynamic loading systems, model analysis, custom resource maps, diagnostics, subsystem registration, teardown, and other work that should occur once per model transition instead of once per spawned entity or once per loading-screen update.&lt;br /&gt;
&lt;br /&gt;
== Global Usage ==&lt;br /&gt;
&lt;br /&gt;
Create either or both global files in &amp;lt;code&amp;gt;data/scripts&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;data/scripts/modelload.c&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;data/scripts/modelunload.c&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenBOR loads them automatically. &amp;lt;code&amp;gt;modelload.c&amp;lt;/code&amp;gt; observes every completed model load, while &amp;lt;code&amp;gt;modelunload.c&amp;lt;/code&amp;gt; observes every model immediately before it is destroyed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    setglobalvar(&amp;quot;last_loaded_model_name&amp;quot;, modelname);&lt;br /&gt;
    setglobalvar(&amp;quot;last_loaded_model_index&amp;quot;, modelindex);&lt;br /&gt;
    setglobalvar(&amp;quot;model_registry_dirty&amp;quot;, 1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example is suitable for &amp;lt;code&amp;gt;modelload.c&amp;lt;/code&amp;gt;. Central managers can use the reported name and index to refresh only the affected registry entry rather than scanning the full loaded-model collection during every [[Loading|loading.c]] execution.&lt;br /&gt;
&lt;br /&gt;
== Model Usage ==&lt;br /&gt;
&lt;br /&gt;
Add either command to a model definition and provide the path to its script file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
modelloadscript data/scripts/models/boss_template_load.c&lt;br /&gt;
modelunloadscript data/scripts/models/boss_template_unload.c&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The commands belong to the model template that declares them. They do not belong to spawned entities and are not copied into entity &amp;lt;code&amp;gt;modeldata&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    setglobalvar(&amp;quot;boss_template_ready&amp;quot;, 1);&lt;br /&gt;
    setglobalvar(&amp;quot;boss_template_index&amp;quot;, modelindex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Model-owned callbacks are useful when one template requires specialized setup or teardown that does not belong in the global observer.&lt;br /&gt;
&lt;br /&gt;
Only one &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; and one &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt; may be assigned to a model. Global and model-owned layers may be used independently or together.&lt;br /&gt;
&lt;br /&gt;
== Inline Model Scripts ==&lt;br /&gt;
&lt;br /&gt;
Both commands support inline script blocks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
modelloadscript @script&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    setglobalvar(&amp;quot;guardian_template_loaded&amp;quot;, 1);&lt;br /&gt;
}&lt;br /&gt;
@end_script&lt;br /&gt;
&lt;br /&gt;
modelunloadscript @script&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    setglobalvar(&amp;quot;guardian_template_loaded&amp;quot;, 0);&lt;br /&gt;
}&lt;br /&gt;
@end_script&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inline form is convenient for concise model-specific bookkeeping. External files are easier to reuse and organize when lifecycle work contains several systems or helper functions.&lt;br /&gt;
&lt;br /&gt;
== Event Data ==&lt;br /&gt;
&lt;br /&gt;
All four lifecycle hooks receive the same automatic local variables:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Variable&lt;br /&gt;
! Type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
| Object pointer&lt;br /&gt;
| Pointer to the loaded model template. The pointer is fully available during both load and unload callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modelindex&amp;lt;/code&amp;gt;&lt;br /&gt;
| Integer&lt;br /&gt;
| Stable index of the model&amp;#039;s cache entry.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modelname&amp;lt;/code&amp;gt;&lt;br /&gt;
| String&lt;br /&gt;
| Name assigned to the model&amp;#039;s cache entry.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    if (model)&lt;br /&gt;
    {&lt;br /&gt;
        setglobalvar(&amp;quot;lifecycle_model_name&amp;quot;, modelname);&lt;br /&gt;
        setglobalvar(&amp;quot;lifecycle_model_index&amp;quot;, modelindex);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; value refers to a template rather than an entity. Entity property functions and entity-local assumptions do not apply to it. Use the model property API or another model-aware system when inspecting or modifying the template.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;modelindex&amp;lt;/code&amp;gt; identifies the cache slot and remains stable when an unloadable model is later loaded again. &amp;lt;code&amp;gt;modelname&amp;lt;/code&amp;gt; is safe to preserve after an unload callback. The &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; pointer is not safe to retain after unloading completes.&lt;br /&gt;
&lt;br /&gt;
== Model Load Event ==&lt;br /&gt;
&lt;br /&gt;
The load event executes only after OpenBOR successfully finishes parsing and constructing the model. Defaults, inherited model data, animations, scripts, palettes, collision information, and other declared properties have already been processed when &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; begins.&lt;br /&gt;
&lt;br /&gt;
The load sequence is:&lt;br /&gt;
&lt;br /&gt;
# OpenBOR locates the model&amp;#039;s existing cache entry.&lt;br /&gt;
# The model file is read and its template is constructed.&lt;br /&gt;
# Model properties, animations, ordinary event scripts, and lifecycle commands are parsed.&lt;br /&gt;
# Temporary parser resources are released.&lt;br /&gt;
# The model&amp;#039;s &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; executes when declared.&lt;br /&gt;
# Global &amp;lt;code&amp;gt;data/scripts/modelload.c&amp;lt;/code&amp;gt; executes when present.&lt;br /&gt;
# The model enters its normal loaded state and the original load request receives the completed template.&lt;br /&gt;
&lt;br /&gt;
Model-owned logic always executes before the global observer. The global script may therefore consume registration, flags, or other state established by the model&amp;#039;s own callback.&lt;br /&gt;
&lt;br /&gt;
Requesting a model that is already loaded does not produce another load event. The event represents an actual transition from cached model definition to loaded template, not each lookup or each entity spawn using that template.&lt;br /&gt;
&lt;br /&gt;
== Model Unload Event ==&lt;br /&gt;
&lt;br /&gt;
The unload event executes while the model remains intact and immediately before OpenBOR begins native destruction.&lt;br /&gt;
&lt;br /&gt;
The unload sequence is:&lt;br /&gt;
&lt;br /&gt;
# OpenBOR receives a valid request to unload a currently loaded model or begins a native model-cleanup operation.&lt;br /&gt;
# The model&amp;#039;s &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt; executes when declared.&lt;br /&gt;
# Global &amp;lt;code&amp;gt;data/scripts/modelunload.c&amp;lt;/code&amp;gt; executes when present.&lt;br /&gt;
# OpenBOR frees the template&amp;#039;s animations, palettes, scripts, collections, and other owned resources.&lt;br /&gt;
# The template is removed from the loaded model collection while its cache entry remains available for a later reload.&lt;br /&gt;
&lt;br /&gt;
Model-owned teardown always executes before the global observer. Both layers may inspect the model and coordinate cleanup while &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; is still valid.&lt;br /&gt;
&lt;br /&gt;
The pointer becomes invalid after the unload chain returns and native destruction begins. Cleanup systems that need persistent identification should retain &amp;lt;code&amp;gt;modelname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modelindex&amp;lt;/code&amp;gt;, or creator-owned data instead of retaining the pointer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    setglobalvar(&amp;quot;last_unloaded_model_name&amp;quot;, modelname);&lt;br /&gt;
    setglobalvar(&amp;quot;last_unloaded_model_index&amp;quot;, modelindex);&lt;br /&gt;
    setglobalvar(&amp;quot;model_registry_dirty&amp;quot;, 1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example allows a registry manager to remove or rebuild the affected entry without touching the model pointer after the event ends.&lt;br /&gt;
&lt;br /&gt;
== Cache and Reload Behavior ==&lt;br /&gt;
&lt;br /&gt;
OpenBOR distinguishes a cached model definition from a loaded model template. Entries created from &amp;lt;code&amp;gt;data/models.txt&amp;lt;/code&amp;gt; retain the model name, source path, flags, and stable cache position even while the full template is unloaded.&lt;br /&gt;
&lt;br /&gt;
Lifecycle scripts follow transitions of the full template:&lt;br /&gt;
&lt;br /&gt;
* Registering the cache entry alone does not execute &amp;lt;code&amp;gt;modelload&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loading and completing the template executes the load chain once.&lt;br /&gt;
* Looking up or requesting an already loaded template does not repeat the chain.&lt;br /&gt;
* Unloading the template executes the unload chain once.&lt;br /&gt;
* Loading the same cache entry again parses its model lifecycle commands and executes a new load chain.&lt;br /&gt;
* Requesting &amp;lt;code&amp;gt;unload_model()&amp;lt;/code&amp;gt; for an absent model does not load it and therefore produces no lifecycle event.&lt;br /&gt;
&lt;br /&gt;
This behavior provides precise change notifications without requiring a recurring scan to discover whether the loaded collection changed.&lt;br /&gt;
&lt;br /&gt;
== Lifecycle Safety ==&lt;br /&gt;
&lt;br /&gt;
OpenBOR guards lifecycle transitions against recursive self-removal and partially constructed templates. An unload request targeting the same model from its load or unload callback is ignored because that model is already inside a protected lifecycle phase.&lt;br /&gt;
&lt;br /&gt;
The guard keeps one callback from re-entering destruction of its own template. Lifecycle scripts may still coordinate creator-owned cleanup, request later work through flags or registries, and operate on other valid systems during the event.&lt;br /&gt;
&lt;br /&gt;
Model subclasses do not inherit &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt; from their parent template. Each subclass may declare its own lifecycle callbacks. This prevents parent and child cache entries from sharing compiled callback ownership while preserving normal inheritance for ordinary model data and supported entity event scripts.&lt;br /&gt;
&lt;br /&gt;
== Lifecycle Events and Entity Events ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Hook&lt;br /&gt;
! Object represented&lt;br /&gt;
! Frequency&lt;br /&gt;
! Typical responsibility&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;modelload.c&amp;lt;/code&amp;gt;&lt;br /&gt;
| Loaded model template&lt;br /&gt;
| Once per actual template load&lt;br /&gt;
| Template registration, analysis, and initialization&lt;br /&gt;
|-&lt;br /&gt;
| [[Onmodelcopyscript|onmodelcopyscript]]&lt;br /&gt;
| Model data being copied for an entity&lt;br /&gt;
| During applicable model-copy operations&lt;br /&gt;
| Per-instance model-data adjustment&lt;br /&gt;
|-&lt;br /&gt;
| [[Onspawnscript|onspawnscript]]&lt;br /&gt;
| Newly created entity&lt;br /&gt;
| Once per applicable entity creation&lt;br /&gt;
| Entity initialization&lt;br /&gt;
|-&lt;br /&gt;
| [[Ondeathscript|ondeathscript]]&lt;br /&gt;
| Dying entity&lt;br /&gt;
| During applicable entity death processing&lt;br /&gt;
| Entity-specific death behavior&lt;br /&gt;
|-&lt;br /&gt;
| [[Onkillscript|onkillscript]]&lt;br /&gt;
| Entity being removed&lt;br /&gt;
| Immediately before applicable entity removal&lt;br /&gt;
| Entity cleanup&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;modelunload.c&amp;lt;/code&amp;gt;&lt;br /&gt;
| Loaded model template&lt;br /&gt;
| Once per actual template unload&lt;br /&gt;
| Template deregistration and teardown&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
One loaded model may create many entities. Model lifecycle scripts execute for the template transition, while entity events execute separately for individual instances.&lt;br /&gt;
&lt;br /&gt;
== Global and Model-Owned Responsibilities ==&lt;br /&gt;
&lt;br /&gt;
The two scopes support a useful division of responsibility:&lt;br /&gt;
&lt;br /&gt;
* Model-owned &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;modelunloadscript&amp;lt;/code&amp;gt; handle behavior unique to one template.&lt;br /&gt;
* Global &amp;lt;code&amp;gt;modelload.c&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;modelunload.c&amp;lt;/code&amp;gt; maintain project-wide registries and systems after the model-owned callback has run.&lt;br /&gt;
&lt;br /&gt;
For example, a boss model can publish its specialized combat role during &amp;lt;code&amp;gt;modelloadscript&amp;lt;/code&amp;gt;. Global &amp;lt;code&amp;gt;modelload.c&amp;lt;/code&amp;gt; can then add the completed template to a project-wide model registry. During removal, the model-owned callback can release its custom relationships before &amp;lt;code&amp;gt;modelunload.c&amp;lt;/code&amp;gt; reconciles the common registry.&lt;br /&gt;
&lt;br /&gt;
== Other Uses ==&lt;br /&gt;
&lt;br /&gt;
Quick applications include:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Model registries&amp;#039;&amp;#039;&amp;#039; - Add and remove exact cache entries without repeatedly scanning every loaded model.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Template analysis&amp;#039;&amp;#039;&amp;#039; - Inspect capabilities, animations, classifications, resources, or creator-defined metadata once after parsing.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Subsystem registration&amp;#039;&amp;#039;&amp;#039; - Connect models to combat managers, factories, selectors, randomizers, encounter systems, or development tools.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dynamic loading&amp;#039;&amp;#039;&amp;#039; - Track runtime &amp;lt;code&amp;gt;loadmodel()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unload_model()&amp;lt;/code&amp;gt; transitions as they occur.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Model-specific initialization&amp;#039;&amp;#039;&amp;#039; - Prepare template-owned creator state before any entity needs to use it.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Resource coordination&amp;#039;&amp;#039;&amp;#039; - Build or release creator-managed lookup tables, auxiliary assets, caches, or relationships alongside a template.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Diagnostics&amp;#039;&amp;#039;&amp;#039; - Log load order, unload order, names, cache indices, reloads, or unexpected lifecycle transitions.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Loading optimization&amp;#039;&amp;#039;&amp;#039; - Replace repeated full-model scans in &amp;lt;code&amp;gt;loading.c&amp;lt;/code&amp;gt; with exact event-driven notifications.&lt;br /&gt;
&lt;br /&gt;
== Related Scripts ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Script&lt;br /&gt;
! Relationship&lt;br /&gt;
|-&lt;br /&gt;
| [[Loading|loading.c]]&lt;br /&gt;
| Recurring loading-screen hook. Model lifecycle events provide exact template transition notifications without repeated collection scans.&lt;br /&gt;
|-&lt;br /&gt;
| [[Onmodelcopyscript|onmodelcopyscript]]&lt;br /&gt;
| Executes during applicable model-data copy operations rather than model-cache loading.&lt;br /&gt;
|-&lt;br /&gt;
| [[Onspawnscript|onspawnscript]]&lt;br /&gt;
| Executes for applicable entity creation after a model template is available.&lt;br /&gt;
|-&lt;br /&gt;
| [[Ondeathscript|ondeathscript]]&lt;br /&gt;
| Model-owned hook for entity death processing.&lt;br /&gt;
|-&lt;br /&gt;
| [[Onkillscript|onkillscript]]&lt;br /&gt;
| Model-owned hook for entity removal.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Loading]]&lt;br /&gt;
* [[Model Properties]]&lt;br /&gt;
* [[Onmodelcopyscript]]&lt;br /&gt;
* [[Onspawnscript]]&lt;br /&gt;
* [[Ondeathscript]]&lt;br /&gt;
* [[Onkillscript]]&lt;br /&gt;
* [[Models]]&lt;br /&gt;
* [[Script Overview]]&lt;/div&gt;</summary>
		<author><name>Dcurrent</name></author>
	</entry>
</feed>