Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 229 additions & 3 deletions engine/openbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,10 @@ 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 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
Expand Down Expand Up @@ -1182,6 +1186,10 @@ 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(&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);
Expand Down Expand Up @@ -1230,6 +1238,22 @@ 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(&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);
Expand Down Expand Up @@ -1352,6 +1376,10 @@ void load_scripts()
}
Script_Compile(&update_script);
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);
Expand Down Expand Up @@ -1405,6 +1433,10 @@ 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(&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);
Expand Down Expand Up @@ -2455,7 +2487,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);
Expand All @@ -2467,8 +2499,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);
}
}
Expand Down Expand Up @@ -7777,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))
Expand Down Expand Up @@ -7878,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--;
Expand Down Expand Up @@ -12173,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;
Expand All @@ -12186,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);
Expand Down Expand Up @@ -15738,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);
Expand Down Expand Up @@ -17407,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;
Expand Down Expand Up @@ -21027,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;
}
Expand Down Expand Up @@ -23481,6 +23646,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);
Expand Down Expand Up @@ -24481,6 +24648,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:
Expand All @@ -24494,6 +24663,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";
Expand Down Expand Up @@ -50715,6 +50892,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;
Expand Down Expand Up @@ -51140,6 +51355,11 @@ void update(int ingame, int usevwait)

while(_time < newtime)
{
if(ingame == 1 || alwaysupdate)
{
execute_updatelogicscripts();
}

if(ingame == 1)
{
update_scroller();
Expand Down Expand Up @@ -51193,6 +51413,12 @@ void update(int ingame, int usevwait)
{
update_ents();
}

if(ingame == 1 || alwaysupdate)
{
execute_updatedlogicscripts();
}

++_time;
}

Expand Down
Loading
Loading