From 558c11f22c06c3fc135b9640ddf36aaeca291d14 Mon Sep 17 00:00:00 2001 From: DCurrent Date: Fri, 21 Aug 2026 21:55:09 -0400 Subject: [PATCH 1/2] Add logical clock update script events Add updatelogic.c and updatedlogic.c global event hooks that execute before and after each engine logical tick. Place the post-update hook before the logical clock advances so both events observe the same tick value. Add matching updatelogicscript and updatedlogicscript level commands, along with level property constants for accessing their script objects. Run global hooks before their level counterparts and preserve the existing ingame and alwaysupdate execution policy. Logical hooks remain inactive while paused or when an outer-loop iteration processes no logical tick. Fix missing breaks in the level script-property getter that caused script properties to fall through and return an incorrect value. --- engine/openbor.c | 81 ++++++++++++++++++++++++- engine/openbor.h | 4 ++ engine/source/openborscript/commands.c | 2 + engine/source/openborscript/commands.h | 2 + engine/source/openborscript/constants.c | 2 + engine/source/openborscript/level.c | 38 +++++++++++- 6 files changed, 126 insertions(+), 3 deletions(-) diff --git a/engine/openbor.c b/engine/openbor.c index 7cfeca536..f49443996 100644 --- a/engine/openbor.c +++ b/engine/openbor.c @@ -852,6 +852,8 @@ Script level_script; //execute when level start Script endlevel_script; //execute when level finished Script update_script; //execute when ingame update Script updated_script; //execute when ingame update finished +Script update_logic_script; //execute before each logical tick +Script updated_logic_script; //execute after each logical tick Script loading_script; // in loading screen Script input_script_all; //keyscript for all players Script key_script_all; //keyscript for all players @@ -1182,6 +1184,8 @@ void init_scripts() Script_Global_Init(); Script_Init(&update_script, "update", NULL, 1); Script_Init(&updated_script, "updated", NULL, 1); + Script_Init(&update_logic_script, "updatelogic", NULL, 1); + Script_Init(&updated_logic_script, "updatedlogic", NULL, 1); Script_Init(&level_script, "level", NULL, 1); Script_Init(&endlevel_script, "endlevel", NULL, 1); Script_Init(&input_script_all, "inputall", NULL, 1); @@ -1230,6 +1234,14 @@ void load_scripts() { Script_Clear(&updated_script, 2); } + if(!load_script(&update_logic_script, "data/scripts/updatelogic.c")) + { + Script_Clear(&update_logic_script, 2); + } + if(!load_script(&updated_logic_script, "data/scripts/updatedlogic.c")) + { + Script_Clear(&updated_logic_script, 2); + } if(!load_script(&level_script, "data/scripts/level.c")) { Script_Clear(&level_script, 2); @@ -1352,6 +1364,8 @@ void load_scripts() } Script_Compile(&update_script); Script_Compile(&updated_script); + Script_Compile(&update_logic_script); + Script_Compile(&updated_logic_script); Script_Compile(&level_script); Script_Compile(&endlevel_script); Script_Compile(&input_script_all); @@ -1405,6 +1419,8 @@ void clear_scripts() //and will never have another chance to be loaded, so just clear the variable list in it Script_Clear(&update_script, 2); Script_Clear(&updated_script, 2); + Script_Clear(&update_logic_script, 2); + Script_Clear(&updated_logic_script, 2); Script_Clear(&level_script, 2); Script_Clear(&endlevel_script, 2); Script_Clear(&input_script_all, 2); @@ -2455,7 +2471,7 @@ void execute_spawn_script(s_spawn_entry *p, entity *e) Script_Set_Local_Variant(cs, "spawnz", &tempvar); tempvar.dblVal = (DOUBLE)p->position.y; Script_Set_Local_Variant(cs, "spawny", &tempvar); - Script_Set_Local_Variant(cs, "spawna", &tempvar); // Legacy alias. + Script_Set_Local_Variant(cs, "spawna", &tempvar); ScriptVariant_ChangeType(&tempvar, VT_INTEGER); tempvar.lVal = (LONG)p->at; Script_Set_Local_Variant(cs, "spawnat", &tempvar); @@ -2467,8 +2483,8 @@ void execute_spawn_script(s_spawn_entry *p, entity *e) Script_Set_Local_Variant(cs, "self", &tempvar); Script_Set_Local_Variant(cs, "spawnx", &tempvar); Script_Set_Local_Variant(cs, "spawnz", &tempvar); - Script_Set_Local_Variant(cs, "spawna", &tempvar); Script_Set_Local_Variant(cs, "spawny", &tempvar); + Script_Set_Local_Variant(cs, "spawna", &tempvar); Script_Set_Local_Variant(cs, "spawnat", &tempvar); } } @@ -23481,6 +23497,8 @@ void free_level(s_level *lv) //offload scripts Script_Clear(&(lv->update_script), 2); Script_Clear(&(lv->updated_script), 2); + Script_Clear(&(lv->update_logic_script), 2); + Script_Clear(&(lv->updated_logic_script), 2); Script_Clear(&(lv->key_script), 2); Script_Clear(&(lv->level_script), 2); Script_Clear(&(lv->endlevel_script), 2); @@ -24481,6 +24499,8 @@ void load_level(char *filename) break; case CMD_LEVEL_UPDATESCRIPT: case CMD_LEVEL_UPDATEDSCRIPT: + case CMD_LEVEL_UPDATELOGICSCRIPT: + case CMD_LEVEL_UPDATEDLOGICSCRIPT: case CMD_LEVEL_KEYSCRIPT: case CMD_LEVEL_LEVELSCRIPT: case CMD_LEVEL_ENDLEVELSCRIPT: @@ -24494,6 +24514,14 @@ void load_level(char *filename) tempscript = &(level->updated_script); scriptname = "levelupdatedscript"; break; + case CMD_LEVEL_UPDATELOGICSCRIPT: + tempscript = &(level->update_logic_script); + scriptname = "levelupdatelogicscript"; + break; + case CMD_LEVEL_UPDATEDLOGICSCRIPT: + tempscript = &(level->updated_logic_script); + scriptname = "levelupdatedlogicscript"; + break; case CMD_LEVEL_KEYSCRIPT: tempscript = &(level->key_script); scriptname = "levelkeyscript"; @@ -50715,6 +50743,44 @@ void execute_updatedscripts() } } +/* +* Caskey, Damon V. +* 2026-08-21 +* +* Execute global and level scripts immediately before an +* engine logical clock tick is processed. +*/ +void execute_updatelogicscripts() +{ + if(Script_IsInitialized(&update_logic_script)) + { + Script_Execute(&update_logic_script); + } + if(level && Script_IsInitialized(&level->update_logic_script)) + { + Script_Execute(&level->update_logic_script); + } +} + +/* +* Caskey, Damon V. +* 2026-08-21 +* +* Execute global and level scripts after an engine logical +* clock tick is processed, before its clock value advances. +*/ +void execute_updatedlogicscripts() +{ + if(Script_IsInitialized(&updated_logic_script)) + { + Script_Execute(&updated_logic_script); + } + if(level && Script_IsInitialized(&level->updated_logic_script)) + { + Script_Execute(&level->updated_logic_script); + } +} + void draw_textobjs() { int i; @@ -51140,6 +51206,11 @@ void update(int ingame, int usevwait) while(_time < newtime) { + if(ingame == 1 || alwaysupdate) + { + execute_updatelogicscripts(); + } + if(ingame == 1) { update_scroller(); @@ -51193,6 +51264,12 @@ void update(int ingame, int usevwait) { update_ents(); } + + if(ingame == 1 || alwaysupdate) + { + execute_updatedlogicscripts(); + } + ++_time; } diff --git a/engine/openbor.h b/engine/openbor.h index cf46ee4ed..abff5d69c 100644 --- a/engine/openbor.h +++ b/engine/openbor.h @@ -1072,7 +1072,9 @@ typedef enum LEVEL_PROPERTY_SCRIPT_LEVEL_END, // Script endlevel_script; LEVEL_PROPERTY_SCRIPT_LEVEL_START, // Script level_script; LEVEL_PROPERTY_SCRIPT_KEY, // Script key_script; + LEVEL_PROPERTY_SCRIPT_UPDATE_LOGIC, // Script update_logic_script; LEVEL_PROPERTY_SCRIPT_UPDATE, // Script update_script; + LEVEL_PROPERTY_SCRIPT_UPDATED_LOGIC, // Script updated_logic_script; LEVEL_PROPERTY_SCRIPT_UPDATED, // Script updated_script; LEVEL_PROPERTY_SCROLL_DIRECTION, // int scrolldir; LEVEL_PROPERTY_SCROLL_VELOCITY, // float scrollspeed; @@ -4303,6 +4305,8 @@ typedef struct //---------------------scripts------------------------------- Script update_script; Script updated_script; + Script update_logic_script; + Script updated_logic_script; Script key_script; Script level_script; Script endlevel_script; diff --git a/engine/source/openborscript/commands.c b/engine/source/openborscript/commands.c index 88dd1d77a..240575d4c 100644 --- a/engine/source/openborscript/commands.c +++ b/engine/source/openborscript/commands.c @@ -758,7 +758,9 @@ List *createLevelCommandList(void) LIST_ADD(CMD_LEVEL_SPAWNSCRIPT, "spawnscript"); LIST_ADD(CMD_LEVEL_STAGENUMBER, "stagenumber"); LIST_ADD(CMD_LEVEL_TYPE, "type"); + LIST_ADD(CMD_LEVEL_UPDATEDLOGICSCRIPT, "updatedlogicscript"); LIST_ADD(CMD_LEVEL_UPDATEDSCRIPT, "updatedscript"); + LIST_ADD(CMD_LEVEL_UPDATELOGICSCRIPT, "updatelogicscript"); LIST_ADD(CMD_LEVEL_UPDATESCRIPT, "updatescript"); LIST_ADD(CMD_LEVEL_VBGSPEED, "vbgspeed"); LIST_ADD(CMD_LEVEL_WAIT, "wait"); diff --git a/engine/source/openborscript/commands.h b/engine/source/openborscript/commands.h index 297025ed5..6beb23b2a 100644 --- a/engine/source/openborscript/commands.h +++ b/engine/source/openborscript/commands.h @@ -234,7 +234,9 @@ typedef enum levelCommand CMD_LEVEL_SPAWNSCRIPT, CMD_LEVEL_STAGENUMBER, CMD_LEVEL_TYPE, + CMD_LEVEL_UPDATEDLOGICSCRIPT, CMD_LEVEL_UPDATEDSCRIPT, + CMD_LEVEL_UPDATELOGICSCRIPT, CMD_LEVEL_UPDATESCRIPT, CMD_LEVEL_VBGSPEED, CMD_LEVEL_WAIT, diff --git a/engine/source/openborscript/constants.c b/engine/source/openborscript/constants.c index db610f02c..cd30d042c 100644 --- a/engine/source/openborscript/constants.c +++ b/engine/source/openborscript/constants.c @@ -1381,7 +1381,9 @@ bool mapstrings_transconst(ScriptVariant **varlist, int paramCount) ICMPCONST(LEVEL_PROPERTY_SCRIPT_LEVEL_END) ICMPCONST(LEVEL_PROPERTY_SCRIPT_LEVEL_START) ICMPCONST(LEVEL_PROPERTY_SCRIPT_KEY) + ICMPCONST(LEVEL_PROPERTY_SCRIPT_UPDATE_LOGIC) ICMPCONST(LEVEL_PROPERTY_SCRIPT_UPDATE) + ICMPCONST(LEVEL_PROPERTY_SCRIPT_UPDATED_LOGIC) ICMPCONST(LEVEL_PROPERTY_SCRIPT_UPDATED) ICMPCONST(LEVEL_PROPERTY_SCROLL_DIRECTION) ICMPCONST(LEVEL_PROPERTY_SCROLL_VELOCITY) diff --git a/engine/source/openborscript/level.c b/engine/source/openborscript/level.c index c4eb29089..2d1b2ed9b 100644 --- a/engine/source/openborscript/level.c +++ b/engine/source/openborscript/level.c @@ -729,6 +729,7 @@ HRESULT openbor_get_level_property(ScriptVariant **varlist, ScriptVariant **pret ScriptVariant_ChangeType(*pretvar, VT_PTR); (*pretvar)->ptrVal = &handle->endlevel_script; //} + break; case LEVEL_PROPERTY_SCRIPT_LEVEL_START: // Script level_script; @@ -737,6 +738,7 @@ HRESULT openbor_get_level_property(ScriptVariant **varlist, ScriptVariant **pret ScriptVariant_ChangeType(*pretvar, VT_PTR); (*pretvar)->ptrVal = &handle->level_script; //} + break; case LEVEL_PROPERTY_SCRIPT_KEY: @@ -745,6 +747,13 @@ HRESULT openbor_get_level_property(ScriptVariant **varlist, ScriptVariant **pret ScriptVariant_ChangeType(*pretvar, VT_PTR); (*pretvar)->ptrVal = &handle->key_script; //} + break; + + case LEVEL_PROPERTY_SCRIPT_UPDATE_LOGIC: + + ScriptVariant_ChangeType(*pretvar, VT_PTR); + (*pretvar)->ptrVal = &handle->update_logic_script; + break; case LEVEL_PROPERTY_SCRIPT_UPDATE: @@ -753,6 +762,13 @@ HRESULT openbor_get_level_property(ScriptVariant **varlist, ScriptVariant **pret ScriptVariant_ChangeType(*pretvar, VT_PTR); (*pretvar)->ptrVal = &handle->update_script; //} + break; + + case LEVEL_PROPERTY_SCRIPT_UPDATED_LOGIC: + + ScriptVariant_ChangeType(*pretvar, VT_PTR); + (*pretvar)->ptrVal = &handle->updated_logic_script; + break; case LEVEL_PROPERTY_SCRIPT_UPDATED: @@ -761,6 +777,7 @@ HRESULT openbor_get_level_property(ScriptVariant **varlist, ScriptVariant **pret ScriptVariant_ChangeType(*pretvar, VT_PTR); (*pretvar)->ptrVal = &handle->updated_script; //} + break; case LEVEL_PROPERTY_SCROLL_DIRECTION: @@ -1455,6 +1472,16 @@ HRESULT openbor_set_level_property(ScriptVariant **varlist, ScriptVariant **pret handle->key_script = *(Script *)arg_value->ptrVal; break; + case LEVEL_PROPERTY_SCRIPT_UPDATE_LOGIC: + + if(invalid_pointer_input) + { + goto error_local; + } + + handle->update_logic_script = *(Script *)arg_value->ptrVal; + break; + case LEVEL_PROPERTY_SCRIPT_UPDATE: if(invalid_pointer_input) @@ -1465,6 +1492,16 @@ HRESULT openbor_set_level_property(ScriptVariant **varlist, ScriptVariant **pret handle->update_script = *(Script *)arg_value->ptrVal; break; + case LEVEL_PROPERTY_SCRIPT_UPDATED_LOGIC: + + if(invalid_pointer_input) + { + goto error_local; + } + + handle->updated_logic_script = *(Script *)arg_value->ptrVal; + break; + case LEVEL_PROPERTY_SCRIPT_UPDATED: if(invalid_pointer_input) @@ -2504,4 +2541,3 @@ HRESULT openbor_changelevelproperty(ScriptVariant **varlist , ScriptVariant **pr printf("\n"); return E_FAIL; } - From 963d6ff375ae9f5951009ad76116a3db84ad7530 Mon Sep 17 00:00:00 2001 From: DCurrent Date: Fri, 21 Aug 2026 22:25:05 -0400 Subject: [PATCH 2/2] Add global and per-model lifecycle script events Add modelload.c and odelunload.c global hooks for observing model cache state transitions without repeatedly scanning the full model collection. Add modelloadscript and modelunloadscript model commands for template- specific initialization and teardown. Expose the model pointer, cache index, and model name through model, modelindex, and modelname locals. Store lifecycle scripts in model cache entries so they are not copied into spawned entity modeldata. Fire model-owned callbacks before their global counterparts, and fire unload callbacks before native model destruction while the model pointer remains valid. Add lifecycle state guards to prevent recursive self-unloading and removal of partially loaded models. Preserve cache-owned script storage across ordinary unload and reload operations, then release it during model cache shutdown. Do not inherit lifecycle callbacks through model subclassing, avoiding shared compiled-script lifetime dependencies between parent and child models. Update unload_model() to use findmodel() so requesting removal of an absent model no longer loads it merely to unload it. --- engine/openbor.c | 151 ++++++++++++++++++++++++- engine/openbor.h | 11 ++ engine/openborscript.c | 3 +- engine/source/openborscript/commands.c | 2 + engine/source/openborscript/commands.h | 2 + 5 files changed, 166 insertions(+), 3 deletions(-) diff --git a/engine/openbor.c b/engine/openbor.c index f49443996..b278d0df8 100644 --- a/engine/openbor.c +++ b/engine/openbor.c @@ -854,6 +854,8 @@ Script update_script; //execute when ingame update Script updated_script; //execute when ingame update finished Script update_logic_script; //execute before each logical tick Script updated_logic_script; //execute after each logical tick +Script model_load_script; //execute after any model finishes loading +Script model_unload_script; //execute before any model is unloaded Script loading_script; // in loading screen Script input_script_all; //keyscript for all players Script key_script_all; //keyscript for all players @@ -1186,6 +1188,8 @@ void init_scripts() Script_Init(&updated_script, "updated", NULL, 1); Script_Init(&update_logic_script, "updatelogic", NULL, 1); Script_Init(&updated_logic_script, "updatedlogic", NULL, 1); + Script_Init(&model_load_script, "modelload", NULL, 1); + Script_Init(&model_unload_script, "modelunload", NULL, 1); Script_Init(&level_script, "level", NULL, 1); Script_Init(&endlevel_script, "endlevel", NULL, 1); Script_Init(&input_script_all, "inputall", NULL, 1); @@ -1242,6 +1246,14 @@ void load_scripts() { Script_Clear(&updated_logic_script, 2); } + if(!load_script(&model_load_script, "data/scripts/modelload.c")) + { + Script_Clear(&model_load_script, 2); + } + if(!load_script(&model_unload_script, "data/scripts/modelunload.c")) + { + Script_Clear(&model_unload_script, 2); + } if(!load_script(&level_script, "data/scripts/level.c")) { Script_Clear(&level_script, 2); @@ -1366,6 +1378,8 @@ void load_scripts() Script_Compile(&updated_script); Script_Compile(&update_logic_script); Script_Compile(&updated_logic_script); + Script_Compile(&model_load_script); + Script_Compile(&model_unload_script); Script_Compile(&level_script); Script_Compile(&endlevel_script); Script_Compile(&input_script_all); @@ -1421,6 +1435,8 @@ void clear_scripts() Script_Clear(&updated_script, 2); Script_Clear(&update_logic_script, 2); Script_Clear(&updated_logic_script, 2); + Script_Clear(&model_load_script, 2); + Script_Clear(&model_unload_script, 2); Script_Clear(&level_script, 2); Script_Clear(&endlevel_script, 2); Script_Clear(&input_script_all, 2); @@ -7793,15 +7809,101 @@ void cache_model_sprites(s_model *m, int ld) } } +/* +* Caskey, Damon V. +* 2026-08-21 +* +* Execute a model lifecycle script with the model template, +* stable cache index, and model name exposed as local values. +*/ +static void execute_model_lifecycle_script(Script *cs, s_model *model) +{ + ScriptVariant tempvar; + + if(!Script_IsInitialized(cs)) + { + return; + } + + ScriptVariant_Init(&tempvar); + + ScriptVariant_ChangeType(&tempvar, VT_PTR); + tempvar.ptrVal = (VOID *)model; + Script_Set_Local_Variant(cs, "model", &tempvar); + + ScriptVariant_ChangeType(&tempvar, VT_INTEGER); + tempvar.lVal = (LONG)model->index; + Script_Set_Local_Variant(cs, "modelindex", &tempvar); + + ScriptVariant_ChangeType(&tempvar, VT_STR); + tempvar.strVal = StrCache_CreateNewFrom(model_cache[model->index].name); + Script_Set_Local_Variant(cs, "modelname", &tempvar); + + Script_Execute(cs); + + ScriptVariant_Clear(&tempvar); + Script_Set_Local_Variant(cs, "model", &tempvar); + Script_Set_Local_Variant(cs, "modelindex", &tempvar); + Script_Set_Local_Variant(cs, "modelname", &tempvar); +} + +/* +* Caskey, Damon V. +* 2026-08-21 +* +* Execute model-owned setup before notifying the global +* model-load observer of a completed model parse. +*/ +static void execute_model_load_scripts(s_model *model) +{ + s_modelcache *cache = &model_cache[model->index]; + + execute_model_lifecycle_script(cache->load_script, model); + execute_model_lifecycle_script(&model_load_script, model); +} + +/* +* Caskey, Damon V. +* 2026-08-21 +* +* Execute model-owned teardown before notifying the global +* model-unload observer and beginning native destruction. +*/ +static void execute_model_unload_scripts(s_model *model) +{ + s_modelcache *cache = &model_cache[model->index]; + + execute_model_lifecycle_script(cache->unload_script, model); + execute_model_lifecycle_script(&model_unload_script, model); +} + // Unload single model from memory int free_model(s_model *model) { int i; + s_modelcache *cache; + if(!model) { return 0; } + + cache = &model_cache[model->index]; + + /* + * Ignore recursive removal from lifecycle callbacks and + * attempts to remove a model that has not finished loading. + */ + if(cache->lifecycle != MODEL_LIFECYCLE_LOADED) + { + return 0; + } + + cache->lifecycle = MODEL_LIFECYCLE_UNLOAD_EVENT; + execute_model_unload_scripts(model); + cache->lifecycle = MODEL_LIFECYCLE_UNLOADING; + printf("Unload '%s' ", model->name); if(hasFreetype(model, MF_ANIMLIST)) @@ -7894,10 +7996,14 @@ int free_model(s_model *model) } printf("."); - model_cache[model->index].model = NULL; + cache->model = NULL; deleteModel(model->name); printf("."); + Script_Clear(cache->load_script, 1); + Script_Clear(cache->unload_script, 1); + cache->lifecycle = MODEL_LIFECYCLE_UNLOADED; + printf("Done.\n"); return models_loaded--; @@ -12189,6 +12295,8 @@ void cache_model(char *name, char *path, int flag) model_cache[models_cached].path[len] = 0; model_cache[models_cached].loadflag = flag; + model_cache[models_cached].load_script = alloc_script(); + model_cache[models_cached].unload_script = alloc_script(); _peek_model_name(models_cached); ++models_cached; @@ -12202,6 +12310,12 @@ void free_modelcache() while(models_cached) { --models_cached; + Script_Clear(model_cache[models_cached].load_script, 2); + free(model_cache[models_cached].load_script); + model_cache[models_cached].load_script = NULL; + Script_Clear(model_cache[models_cached].unload_script, 2); + free(model_cache[models_cached].unload_script); + model_cache[models_cached].unload_script = NULL; free(model_cache[models_cached].name); model_cache[models_cached].name = NULL; free(model_cache[models_cached].path); @@ -15754,6 +15868,8 @@ s_model *load_cached_model(char *name, char *owner, char unload) borShutdown(1, "Fatal: No cache entry for '%s' within '%s'\n\n", name, owner); } + model_cache[cacheindex].lifecycle = MODEL_LIFECYCLE_LOADING; + // Get the text file name of model. filename = model_cache[cacheindex].path; printf(" from %s \n", filename); @@ -17423,6 +17539,36 @@ s_model *load_cached_model(char *name, char *owner, char unload) case CMD_MODEL_ONKILLSCRIPT: pos += lcmHandleCommandScripts(&arglist, buf + pos, newchar->scripts->onkill_script, "onkillscript", filename, 1, 0); break; + case CMD_MODEL_MODELLOADSCRIPT: + if(Script_IsInitialized(model_cache[cacheindex].load_script)) + { + Script_Clear(model_cache[cacheindex].load_script, 1); + } + pos += lcmHandleCommandScripts( + &arglist, + buf + pos, + model_cache[cacheindex].load_script, + "modelloadscript", + filename, + 1, + 0 + ); + break; + case CMD_MODEL_MODELUNLOADSCRIPT: + if(Script_IsInitialized(model_cache[cacheindex].unload_script)) + { + Script_Clear(model_cache[cacheindex].unload_script, 1); + } + pos += lcmHandleCommandScripts( + &arglist, + buf + pos, + model_cache[cacheindex].unload_script, + "modelunloadscript", + filename, + 1, + 0 + ); + break; case CMD_MODEL_DIDBLOCKSCRIPT: pos += lcmHandleCommandScripts(&arglist, buf + pos, newchar->scripts->didblock_script, "didblockscript", filename, 1, 0); break; @@ -21043,6 +21189,9 @@ s_model *load_cached_model(char *name, char *owner, char unload) if(!shutdownmessage) { + model_cache[cacheindex].lifecycle = MODEL_LIFECYCLE_LOAD_EVENT; + execute_model_load_scripts(newchar); + model_cache[cacheindex].lifecycle = MODEL_LIFECYCLE_LOADED; printf(" ...done!\n"); return newchar; } diff --git a/engine/openbor.h b/engine/openbor.h index abff5d69c..06159b03d 100644 --- a/engine/openbor.h +++ b/engine/openbor.h @@ -3811,6 +3811,17 @@ typedef struct char *name; char *path; s_model *model; + Script *load_script; + Script *unload_script; + enum + { + MODEL_LIFECYCLE_UNLOADED, + MODEL_LIFECYCLE_LOADING, + MODEL_LIFECYCLE_LOAD_EVENT, + MODEL_LIFECYCLE_LOADED, + MODEL_LIFECYCLE_UNLOAD_EVENT, + MODEL_LIFECYCLE_UNLOADING + } lifecycle; int loadflag; int selectable; } s_modelcache; diff --git a/engine/openborscript.c b/engine/openborscript.c index 655dd6ce7..112adb435 100644 --- a/engine/openborscript.c +++ b/engine/openborscript.c @@ -15778,7 +15778,6 @@ HRESULT openbor_loadmodel(ScriptVariant **varlist , ScriptVariant **pretvar, int //unload_model("name"); HRESULT openbor_unload_model(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount) { - LONG unload = 0; s_model *model; if(paramCount < 1) { @@ -15789,7 +15788,7 @@ HRESULT openbor_unload_model(ScriptVariant **varlist , ScriptVariant **pretvar, goto unload_model_error; } - model = load_cached_model(StrCache_Get(varlist[0]->strVal), "openbor_loadmodel", (char)unload); + model = findmodel(StrCache_Get(varlist[0]->strVal)); if(paramCount >= 1 && model) { diff --git a/engine/source/openborscript/commands.c b/engine/source/openborscript/commands.c index 240575d4c..9684ef3e1 100644 --- a/engine/source/openborscript/commands.c +++ b/engine/source/openborscript/commands.c @@ -513,6 +513,8 @@ List *createModelCommandList(void) LIST_ADD(CMD_MODEL_ONENTITYCOLLISIONSCRIPT, "onentitycollisionscript"); LIST_ADD(CMD_MODEL_ONFALLSCRIPT, "onfallscript"); LIST_ADD(CMD_MODEL_ONKILLSCRIPT, "onkillscript"); + LIST_ADD(CMD_MODEL_MODELLOADSCRIPT, "modelloadscript"); + LIST_ADD(CMD_MODEL_MODELUNLOADSCRIPT, "modelunloadscript"); LIST_ADD(CMD_MODEL_ONMODELCOPYSCRIPT, "onmodelcopyscript"); LIST_ADD(CMD_MODEL_ONMOVEYSCRIPT, "onmoveyscript"); LIST_ADD(CMD_MODEL_ONMOVEXSCRIPT, "onmovexscript"); diff --git a/engine/source/openborscript/commands.h b/engine/source/openborscript/commands.h index 6beb23b2a..a52c0737a 100644 --- a/engine/source/openborscript/commands.h +++ b/engine/source/openborscript/commands.h @@ -622,6 +622,8 @@ typedef enum modelCommand CMD_MODEL_ONENTITYCOLLISIONSCRIPT, CMD_MODEL_ONFALLSCRIPT, CMD_MODEL_ONKILLSCRIPT, + CMD_MODEL_MODELLOADSCRIPT, + CMD_MODEL_MODELUNLOADSCRIPT, CMD_MODEL_ONMODELCOPYSCRIPT, CMD_MODEL_ONMOVEYSCRIPT, CMD_MODEL_ONMOVEXSCRIPT,