From b4565d1f0356691520e2202e25392d79d65d003b Mon Sep 17 00:00:00 2001 From: themuffinator Date: Tue, 30 Dec 2025 21:42:19 +0000 Subject: [PATCH] Align botlib setup diagnostics and ordering --- src/botlib/interface/bot_interface.c | 17 +- src/botlib/interface/botlib_interface.c | 671 ++++++++++++++---------- 2 files changed, 407 insertions(+), 281 deletions(-) diff --git a/src/botlib/interface/bot_interface.c b/src/botlib/interface/bot_interface.c index c3d1bba..b4c2e0e 100644 --- a/src/botlib/interface/bot_interface.c +++ b/src/botlib/interface/bot_interface.c @@ -1636,28 +1636,14 @@ static char *BotVersion(void) ============= BotSetupLibraryWrapper -Initialises the botlib bridge and emits the historical startup banners. +Initialises the botlib bridge and delegates setup to the core entry point. ============= */ static int BotSetupLibraryWrapper(void) { - if (BotLibraryInitialized()) - { - BotInterface_Printf(PRT_ERROR, "bot library already setup\n"); - return BLERR_LIBRARYALREADYSETUP; - } - - BotInterface_PrintBanner(PRT_MESSAGE, "------- BotLib Initialization -------\n"); - BotInterface_PrintBanner(PRT_MESSAGE, "BotLib v0.96\n"); BotInterface_SetImportTable(&g_botlibImportTable); int result = BotSetupLibrary(); - if (result != BLERR_NOERROR) - { - return result; - } - - BotInterface_PrintBanner(PRT_MESSAGE, "-------------------------------------\n"); return result; } @@ -3485,4 +3471,3 @@ GLADIATOR_API bot_export_t *GetBotAPI(bot_import_t *import) return &exportTable; } - diff --git a/src/botlib/interface/botlib_interface.c b/src/botlib/interface/botlib_interface.c index cc066e1..339e3f2 100644 --- a/src/botlib/interface/botlib_interface.c +++ b/src/botlib/interface/botlib_interface.c @@ -25,11 +25,11 @@ * the reverse engineering effort progresses. */ typedef struct botlib_subsystem_state_s { - bool aas_initialised; - bool ea_initialised; - bool ai_initialised; - bool sound_initialised; - bool utilities_initialised; + bool aas_initialised; + bool ea_initialised; + bool ai_initialised; + bool sound_initialised; + bool utilities_initialised; } botlib_subsystem_state_t; static const botlib_import_table_t *g_import_table = NULL; @@ -38,367 +38,508 @@ static botlib_library_variables_t g_library_variables; static botlib_subsystem_state_t g_subsystem_state; static ai_weapon_library_t *g_weapon_library = NULL; +/* +============= +Botlib_DefaultWeaponConfig +============= +*/ static const char *Botlib_DefaultWeaponConfig(void) { - return BOTLIB_DEFAULT_WEAPONCONFIG; + return BOTLIB_DEFAULT_WEAPONCONFIG; } +/* +============= +Botlib_ResetSubsystemState + +Clears subsystem bookkeeping so setup/shutdown order can restart cleanly. +============= +*/ static void Botlib_ResetSubsystemState(void) { - memset(&g_subsystem_state, 0, sizeof(g_subsystem_state)); - g_weapon_library = NULL; + memset(&g_subsystem_state, 0, sizeof(g_subsystem_state)); + g_weapon_library = NULL; } +/* +============= +Botlib_ResetLibraryVariables + +Clears the cached library configuration variables. +============= +*/ static void Botlib_ResetLibraryVariables(void) { - memset(&g_library_variables, 0, sizeof(g_library_variables)); + memset(&g_library_variables, 0, sizeof(g_library_variables)); } +/* +============= +Botlib_ReadIntLibVarCached +============= +*/ static int Botlib_ReadIntLibVarCached(libvar_t *var, int fallback) { - return (var != NULL) ? (int)var->value : fallback; + return (var != NULL) ? (int)var->value : fallback; } +/* +============= +Botlib_ReadFloatLibVarCached +============= +*/ static float Botlib_ReadFloatLibVarCached(libvar_t *var, float fallback) { - return (var != NULL) ? var->value : fallback; + return (var != NULL) ? var->value : fallback; } +/* +============= +Botlib_CacheLibraryVariables + +Snapshots configuration values from the bridge into the local cache. +============= +*/ static void Botlib_CacheLibraryVariables(void) { - g_library_variables.maxclients = Botlib_ReadIntLibVarCached(Bridge_MaxClients(), 4); - g_library_variables.maxentities = Botlib_ReadIntLibVarCached(Bridge_MaxEntities(), 1024); - g_library_variables.sv_gravity = Botlib_ReadFloatLibVarCached(Bridge_Gravity(), 800.0f); - g_library_variables.sv_maxvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxVelocity(), 300.0f); - g_library_variables.sv_airaccelerate = Botlib_ReadFloatLibVarCached(Bridge_AirAccelerate(), 0.0f); - g_library_variables.sv_maxwalkvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxWalkVelocity(), 300.0f); - g_library_variables.sv_maxcrouchvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxCrouchVelocity(), 100.0f); - g_library_variables.sv_maxswimvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxSwimVelocity(), 150.0f); - g_library_variables.sv_jumpvel = Botlib_ReadFloatLibVarCached(Bridge_JumpVelocity(), 224.0f); - g_library_variables.sv_maxacceleration = Botlib_ReadFloatLibVarCached(Bridge_MaxAcceleration(), 2200.0f); - g_library_variables.sv_friction = Botlib_ReadFloatLibVarCached(Bridge_Friction(), 6.0f); - g_library_variables.sv_stopspeed = Botlib_ReadFloatLibVarCached(Bridge_StopSpeed(), 100.0f); - g_library_variables.sv_maxstep = Botlib_ReadFloatLibVarCached(Bridge_MaxStep(), 18.0f); - g_library_variables.sv_maxbarrier = Botlib_ReadFloatLibVarCached(Bridge_MaxBarrier(), 50.0f); - g_library_variables.sv_maxsteepness = Botlib_ReadFloatLibVarCached(Bridge_MaxSteepness(), 0.7f); - g_library_variables.sv_maxwaterjump = Botlib_ReadFloatLibVarCached(Bridge_MaxWaterJump(), 20.0f); - g_library_variables.sv_watergravity = Botlib_ReadFloatLibVarCached(Bridge_WaterGravity(), 400.0f); - g_library_variables.sv_waterfriction = Botlib_ReadFloatLibVarCached(Bridge_WaterFriction(), 1.0f); - g_library_variables.max_weaponinfo = Botlib_ReadIntLibVarCached(Bridge_MaxWeaponInfo(), 32); - g_library_variables.max_projectileinfo = Botlib_ReadIntLibVarCached(Bridge_MaxProjectileInfo(), 32); - g_library_variables.max_soundinfo = Botlib_ReadIntLibVarCached(Bridge_MaxSoundInfo(), 256); - g_library_variables.max_aassounds = Botlib_ReadIntLibVarCached(Bridge_MaxAASSounds(), 256); - g_library_variables.forceclustering = Botlib_ReadIntLibVarCached(Bridge_ForceClustering(), 0); - g_library_variables.forcereachability = Botlib_ReadIntLibVarCached(Bridge_ForceReachability(), 0); - g_library_variables.forcewrite = Botlib_ReadIntLibVarCached(Bridge_ForceWrite(), 0); - g_library_variables.framereachability = Botlib_ReadIntLibVarCached(Bridge_FrameReachability(), 0); - - const libvar_t *weaponconfig = Bridge_WeaponConfig(); - const char *weaponconfig_string = (weaponconfig != NULL && weaponconfig->string != NULL && weaponconfig->string[0] != '\0') - ? weaponconfig->string - : Botlib_DefaultWeaponConfig(); - strncpy(g_library_variables.weaponconfig, - weaponconfig_string, - sizeof(g_library_variables.weaponconfig) - 1); - g_library_variables.weaponconfig[sizeof(g_library_variables.weaponconfig) - 1] = '\0'; - - const libvar_t *soundconfig = Bridge_SoundConfig(); - const char *soundconfig_string = (soundconfig != NULL && soundconfig->string != NULL - && soundconfig->string[0] != '\0') - ? soundconfig->string - : "sounds.c"; - strncpy(g_library_variables.soundconfig, - soundconfig_string, - sizeof(g_library_variables.soundconfig) - 1); - g_library_variables.soundconfig[sizeof(g_library_variables.soundconfig) - 1] = '\0'; + g_library_variables.maxclients = Botlib_ReadIntLibVarCached(Bridge_MaxClients(), 4); + g_library_variables.maxentities = Botlib_ReadIntLibVarCached(Bridge_MaxEntities(), 1024); + g_library_variables.sv_gravity = Botlib_ReadFloatLibVarCached(Bridge_Gravity(), 800.0f); + g_library_variables.sv_maxvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxVelocity(), 300.0f); + g_library_variables.sv_airaccelerate = Botlib_ReadFloatLibVarCached(Bridge_AirAccelerate(), 0.0f); + g_library_variables.sv_maxwalkvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxWalkVelocity(), 300.0f); + g_library_variables.sv_maxcrouchvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxCrouchVelocity(), 100.0f); + g_library_variables.sv_maxswimvelocity = Botlib_ReadFloatLibVarCached(Bridge_MaxSwimVelocity(), 150.0f); + g_library_variables.sv_jumpvel = Botlib_ReadFloatLibVarCached(Bridge_JumpVelocity(), 224.0f); + g_library_variables.sv_maxacceleration = Botlib_ReadFloatLibVarCached(Bridge_MaxAcceleration(), 2200.0f); + g_library_variables.sv_friction = Botlib_ReadFloatLibVarCached(Bridge_Friction(), 6.0f); + g_library_variables.sv_stopspeed = Botlib_ReadFloatLibVarCached(Bridge_StopSpeed(), 100.0f); + g_library_variables.sv_maxstep = Botlib_ReadFloatLibVarCached(Bridge_MaxStep(), 18.0f); + g_library_variables.sv_maxbarrier = Botlib_ReadFloatLibVarCached(Bridge_MaxBarrier(), 50.0f); + g_library_variables.sv_maxsteepness = Botlib_ReadFloatLibVarCached(Bridge_MaxSteepness(), 0.7f); + g_library_variables.sv_maxwaterjump = Botlib_ReadFloatLibVarCached(Bridge_MaxWaterJump(), 20.0f); + g_library_variables.sv_watergravity = Botlib_ReadFloatLibVarCached(Bridge_WaterGravity(), 400.0f); + g_library_variables.sv_waterfriction = Botlib_ReadFloatLibVarCached(Bridge_WaterFriction(), 1.0f); + g_library_variables.max_weaponinfo = Botlib_ReadIntLibVarCached(Bridge_MaxWeaponInfo(), 32); + g_library_variables.max_projectileinfo = Botlib_ReadIntLibVarCached(Bridge_MaxProjectileInfo(), 32); + g_library_variables.max_soundinfo = Botlib_ReadIntLibVarCached(Bridge_MaxSoundInfo(), 256); + g_library_variables.max_aassounds = Botlib_ReadIntLibVarCached(Bridge_MaxAASSounds(), 256); + g_library_variables.forceclustering = Botlib_ReadIntLibVarCached(Bridge_ForceClustering(), 0); + g_library_variables.forcereachability = Botlib_ReadIntLibVarCached(Bridge_ForceReachability(), 0); + g_library_variables.forcewrite = Botlib_ReadIntLibVarCached(Bridge_ForceWrite(), 0); + g_library_variables.framereachability = Botlib_ReadIntLibVarCached(Bridge_FrameReachability(), 0); + + const libvar_t *weaponconfig = Bridge_WeaponConfig(); + const char *weaponconfig_string = (weaponconfig != NULL && weaponconfig->string != NULL && weaponconfig->string[0] != '\0') + ? weaponconfig->string + : Botlib_DefaultWeaponConfig(); + strncpy(g_library_variables.weaponconfig, + weaponconfig_string, + sizeof(g_library_variables.weaponconfig) - 1); + g_library_variables.weaponconfig[sizeof(g_library_variables.weaponconfig) - 1] = '\0'; + + const libvar_t *soundconfig = Bridge_SoundConfig(); + const char *soundconfig_string = (soundconfig != NULL && soundconfig->string != NULL + && soundconfig->string[0] != '\0') + ? soundconfig->string + : "sounds.c"; + strncpy(g_library_variables.soundconfig, + soundconfig_string, + sizeof(g_library_variables.soundconfig) - 1); + g_library_variables.soundconfig[sizeof(g_library_variables.soundconfig) - 1] = '\0'; } +/* +============= +Botlib_SetupAASSubsystem + +Initialises the AAS subsystem state. +============= +*/ static int Botlib_SetupAASSubsystem(void) { - if (g_subsystem_state.aas_initialised) { - return BLERR_NOERROR; - } + if (g_subsystem_state.aas_initialised) { + return BLERR_NOERROR; + } - int status = AAS_Init(); - if (status != BLERR_NOERROR) { - return status; - } + int status = AAS_Init(); + if (status != BLERR_NOERROR) { + return status; + } - g_subsystem_state.aas_initialised = true; - return BLERR_NOERROR; + g_subsystem_state.aas_initialised = true; + return BLERR_NOERROR; } +/* +============= +Botlib_SetupEASubsystem + +Initialises the EA subsystem for the configured client limit. +============= +*/ static int Botlib_SetupEASubsystem(void) { - if (g_subsystem_state.ea_initialised) { - return BLERR_NOERROR; - } - - int max_clients = (g_library_variables.maxclients > 0) ? g_library_variables.maxclients : 0; - int status = EA_Init(max_clients); - if (status != BLERR_NOERROR) { - return status; - } - - g_subsystem_state.ea_initialised = true; - return BLERR_NOERROR; + if (g_subsystem_state.ea_initialised) { + return BLERR_NOERROR; + } + + int max_clients = (g_library_variables.maxclients > 0) ? g_library_variables.maxclients : 0; + int status = EA_Init(max_clients); + if (status != BLERR_NOERROR) { + return status; + } + + g_subsystem_state.ea_initialised = true; + return BLERR_NOERROR; } +/* +============= +Botlib_SetupAISubsystem + +Loads the weapon AI library configuration. +============= +*/ static bool Botlib_SetupAISubsystem(void) { - if (g_subsystem_state.ai_initialised) { - return true; - } + if (g_subsystem_state.ai_initialised) { + return true; + } - const char *weapon_config_path = - (g_library_variables.weaponconfig[0] != '\0') ? g_library_variables.weaponconfig : NULL; + const char *weapon_config_path = + (g_library_variables.weaponconfig[0] != '\0') ? g_library_variables.weaponconfig : NULL; - g_weapon_library = AI_LoadWeaponLibrary(weapon_config_path); - if (g_weapon_library == NULL) { - return false; - } + g_weapon_library = AI_LoadWeaponLibrary(weapon_config_path); + if (g_weapon_library == NULL) { + return false; + } - g_subsystem_state.ai_initialised = true; - return true; + g_subsystem_state.ai_initialised = true; + return true; } +/* +============= +Botlib_SetupSoundSubsystem + +Initialises the AAS sound data for bot sensing. +============= +*/ static int Botlib_SetupSoundSubsystem(void) { - if (g_subsystem_state.sound_initialised) { - return BLERR_NOERROR; - } + if (g_subsystem_state.sound_initialised) { + return BLERR_NOERROR; + } - int status = AAS_SoundSubsystem_Init(&g_library_variables); - if (status != BLERR_NOERROR) { - return status; - } + int status = AAS_SoundSubsystem_Init(&g_library_variables); + if (status != BLERR_NOERROR) { + return status; + } - g_subsystem_state.sound_initialised = true; - return BLERR_NOERROR; + g_subsystem_state.sound_initialised = true; + return BLERR_NOERROR; } +/* +============= +Botlib_SetupUtilities + +Initialises shared utility subsystems and bridge configuration helpers. +============= +*/ static int Botlib_SetupUtilities(void) { - if (g_subsystem_state.utilities_initialised) { - return BLERR_NOERROR; - } - - if (!BridgeConfig_Init()) { - BotLib_Print(PRT_ERROR, "Botlib_SetupUtilities: failed to initialise bridge configuration\n"); - return BLERR_INVALIDIMPORT; - } - - if (!L_Utils_Init()) { - BridgeConfig_Shutdown(); - BotLib_Print(PRT_ERROR, "Botlib_SetupUtilities: l_utils bootstrap failed\n"); - return BLERR_INVALIDIMPORT; - } - - if (!L_Struct_Init()) { - L_Utils_Shutdown(); - BridgeConfig_Shutdown(); - BotLib_Print(PRT_ERROR, "Botlib_SetupUtilities: l_struct bootstrap failed\n"); - return BLERR_INVALIDIMPORT; - } - - char asset_root[BOTLIB_ASSET_MAX_PATH]; - if (BotLib_LocateAssetRoot(asset_root, sizeof(asset_root))) { - BotLib_Print(PRT_MESSAGE, "[botlib_interface] assets root resolved to %s\n", asset_root); - } else { - BotLib_Print(PRT_WARNING, "[botlib_interface] unable to resolve Gladiator asset root\n"); - } - - g_subsystem_state.utilities_initialised = true; - return BLERR_NOERROR; + if (g_subsystem_state.utilities_initialised) { + return BLERR_NOERROR; + } + + if (!BridgeConfig_Init()) { + BotLib_Print(PRT_ERROR, "Botlib_SetupUtilities: failed to initialise bridge configuration\n"); + return BLERR_INVALIDIMPORT; + } + + if (!L_Utils_Init()) { + BridgeConfig_Shutdown(); + BotLib_Print(PRT_ERROR, "Botlib_SetupUtilities: l_utils bootstrap failed\n"); + return BLERR_INVALIDIMPORT; + } + + if (!L_Struct_Init()) { + L_Utils_Shutdown(); + BridgeConfig_Shutdown(); + BotLib_Print(PRT_ERROR, "Botlib_SetupUtilities: l_struct bootstrap failed\n"); + return BLERR_INVALIDIMPORT; + } + + char asset_root[BOTLIB_ASSET_MAX_PATH]; + if (BotLib_LocateAssetRoot(asset_root, sizeof(asset_root))) { + BotLib_Print(PRT_MESSAGE, "[botlib_interface] assets root resolved to %s\n", asset_root); + } else { + BotLib_Print(PRT_WARNING, "[botlib_interface] unable to resolve Gladiator asset root\n"); + } + + g_subsystem_state.utilities_initialised = true; + return BLERR_NOERROR; } +/* +============= +Botlib_ShutdownUtilities + +Tears down the utility subsystem stack in reverse order. +============= +*/ static void Botlib_ShutdownUtilities(void) { - if (!g_subsystem_state.utilities_initialised) { - return; - } - - L_Struct_Shutdown(); - L_Utils_Shutdown(); - BridgeConfig_Shutdown(); - g_subsystem_state.utilities_initialised = false; + if (!g_subsystem_state.utilities_initialised) { + return; + } + + L_Struct_Shutdown(); + L_Utils_Shutdown(); + BridgeConfig_Shutdown(); + g_subsystem_state.utilities_initialised = false; } +/* +============= +Botlib_ShutdownAISubsystem +============= +*/ static void Botlib_ShutdownAISubsystem(void) { - if (!g_subsystem_state.ai_initialised) { - return; - } + if (!g_subsystem_state.ai_initialised) { + return; + } - if (g_weapon_library != NULL) { - AI_UnloadWeaponLibrary(g_weapon_library); - g_weapon_library = NULL; - } + if (g_weapon_library != NULL) { + AI_UnloadWeaponLibrary(g_weapon_library); + g_weapon_library = NULL; + } - g_subsystem_state.ai_initialised = false; + g_subsystem_state.ai_initialised = false; } +/* +============= +Botlib_ShutdownSoundSubsystem +============= +*/ static void Botlib_ShutdownSoundSubsystem(void) { - if (!g_subsystem_state.sound_initialised) { - return; - } + if (!g_subsystem_state.sound_initialised) { + return; + } - AAS_SoundSubsystem_Shutdown(); - g_subsystem_state.sound_initialised = false; + AAS_SoundSubsystem_Shutdown(); + g_subsystem_state.sound_initialised = false; } +/* +============= +Botlib_ShutdownEASubsystem +============= +*/ static void Botlib_ShutdownEASubsystem(void) { - if (!g_subsystem_state.ea_initialised) { - return; - } + if (!g_subsystem_state.ea_initialised) { + return; + } - EA_Shutdown(); - g_subsystem_state.ea_initialised = false; + EA_Shutdown(); + g_subsystem_state.ea_initialised = false; } +/* +============= +Botlib_ShutdownAASSubsystem +============= +*/ static void Botlib_ShutdownAASSubsystem(void) { - if (!g_subsystem_state.aas_initialised) { - return; - } + if (!g_subsystem_state.aas_initialised) { + return; + } - AAS_Shutdown(); - g_subsystem_state.aas_initialised = false; + AAS_Shutdown(); + g_subsystem_state.aas_initialised = false; } +/* +============= +BotInterface_SetImportTable + +Stores the import table supplied by the engine. +============= +*/ void BotInterface_SetImportTable(const botlib_import_table_t *import_table) { - g_import_table = import_table; + g_import_table = import_table; } +/* +============= +BotInterface_GetImportTable +============= +*/ const botlib_import_table_t *BotInterface_GetImportTable(void) { - return g_import_table; + return g_import_table; } +/* +============= +BotSetupLibrary + +Initialises the botlib subsystems following the HLIL setup ordering. +============= +*/ int BotSetupLibrary(void) { - if (g_library_initialised) { - return BLERR_LIBRARYALREADYSETUP; - } - - if (g_import_table == NULL || g_import_table->BotLibVarGet == NULL) { - return BLERR_INVALIDIMPORT; - } - - if (!BotMemory_Init(BOT_MEMORY_DEFAULT_HEAP_SIZE)) { - return BLERR_INVALIDIMPORT; - } - - Botlib_ResetSubsystemState(); - Botlib_ResetLibraryVariables(); - LibVar_ResetCache(); - BotLib_LogShutdown(); - - int status = Botlib_SetupUtilities(); - if (status != BLERR_NOERROR) { - Botlib_ResetLibraryVariables(); - Botlib_ResetSubsystemState(); - LibVar_Shutdown(); - BotMemory_Shutdown(); - return status; - } - - Botlib_CacheLibraryVariables(); - - status = Botlib_SetupAASSubsystem(); - if (status != BLERR_NOERROR) { - Botlib_ShutdownUtilities(); - Botlib_ResetLibraryVariables(); - Botlib_ResetSubsystemState(); - LibVar_Shutdown(); - BotMemory_Shutdown(); - return status; - } - - status = Botlib_SetupEASubsystem(); - if (status != BLERR_NOERROR) { - Botlib_ShutdownAASSubsystem(); - Botlib_ShutdownUtilities(); - Botlib_ResetLibraryVariables(); - Botlib_ResetSubsystemState(); - LibVar_Shutdown(); - BotMemory_Shutdown(); - return status; - } - - /* - * The Gladiator HLIL initialises shared data before exposing the bot state - * table: item configuration is loaded via sub_100309d0 ("itemconfig") and - * the weapon library comes online through sub_10035680 ("weaponconfig") - * prior to character setup routines that request per-bot weight handles and - * chat files. When the AI subsystem grows beyond stubs, its setup function - * will need to honour that order so movement, weight, and character modules - * can acquire their dependencies deterministically. - *【F:dev_tools/gladiator.dll.bndb_hlil.txt†L38344-L38405】【F:dev_tools/gladiator.dll.bndb_hlil.txt†L41398-L41415】【F:dev_tools/gladiator.dll.bndb_hlil.txt†L32483-L32552】 - */ - if (!Botlib_SetupAISubsystem()) { - Botlib_ShutdownEASubsystem(); - Botlib_ShutdownAASSubsystem(); - Botlib_ShutdownUtilities(); - Botlib_ResetLibraryVariables(); - Botlib_ResetSubsystemState(); - LibVar_Shutdown(); - BotMemory_Shutdown(); - return BLERR_CANNOTLOADWEAPONCONFIG; - } - - status = Botlib_SetupSoundSubsystem(); - if (status != BLERR_NOERROR) { - Botlib_ShutdownAISubsystem(); - Botlib_ShutdownEASubsystem(); - Botlib_ShutdownAASSubsystem(); - Botlib_ShutdownUtilities(); - Botlib_ResetLibraryVariables(); - Botlib_ResetSubsystemState(); - LibVar_Shutdown(); - BotMemory_Shutdown(); - return status; - } - - AAS_DebugRegisterConsoleCommands(); - - g_library_initialised = true; - return BLERR_NOERROR; + if (g_library_initialised) { + BotLib_Print(PRT_ERROR, "bot library already setup\n"); + return BLERR_LIBRARYALREADYSETUP; + } + + if (g_import_table == NULL || g_import_table->BotLibVarGet == NULL) { + BotLib_Print(PRT_ERROR, "BotSetupLibrary: invalid import table\n"); + return BLERR_INVALIDIMPORT; + } + + BotLib_Print(PRT_MESSAGE, "------- BotLib Initialization -------\n"); + BotLib_Print(PRT_MESSAGE, "BotLib v0.96\n"); + + if (!BotMemory_Init(BOT_MEMORY_DEFAULT_HEAP_SIZE)) { + BotLib_Print(PRT_ERROR, "BotSetupLibrary: memory allocation failed\n"); + return BLERR_INVALIDIMPORT; + } + + Botlib_ResetSubsystemState(); + Botlib_ResetLibraryVariables(); + LibVar_ResetCache(); + BotLib_LogShutdown(); + + int status = Botlib_SetupUtilities(); + if (status != BLERR_NOERROR) { + Botlib_ResetLibraryVariables(); + Botlib_ResetSubsystemState(); + LibVar_Shutdown(); + BotMemory_Shutdown(); + return status; + } + + Botlib_CacheLibraryVariables(); + + /* + * The Gladiator HLIL initialises shared data before exposing the bot state + * table: item configuration is loaded via sub_100309d0 ("itemconfig") and + * the weapon library comes online through sub_10035680 ("weaponconfig") + * prior to character setup routines that request per-bot weight handles and + * chat files. When the AI subsystem grows beyond stubs, its setup function + * will need to honour that order so movement, weight, and character modules + * can acquire their dependencies deterministically. + *【F:dev_tools/gladiator.dll.bndb_hlil.txt†L38344-L38405】【F:dev_tools/gladiator.dll.bndb_hlil.txt†L41398-L41415】【F:dev_tools/gladiator.dll.bndb_hlil.txt†L32483-L32552】 + */ + if (!Botlib_SetupAISubsystem()) { + Botlib_ShutdownUtilities(); + Botlib_ResetLibraryVariables(); + Botlib_ResetSubsystemState(); + LibVar_Shutdown(); + BotMemory_Shutdown(); + return BLERR_CANNOTLOADWEAPONCONFIG; + } + + status = Botlib_SetupEASubsystem(); + if (status != BLERR_NOERROR) { + Botlib_ShutdownAISubsystem(); + Botlib_ShutdownUtilities(); + Botlib_ResetLibraryVariables(); + Botlib_ResetSubsystemState(); + LibVar_Shutdown(); + BotMemory_Shutdown(); + return status; + } + + status = Botlib_SetupAASSubsystem(); + if (status != BLERR_NOERROR) { + Botlib_ShutdownEASubsystem(); + Botlib_ShutdownAISubsystem(); + Botlib_ShutdownUtilities(); + Botlib_ResetLibraryVariables(); + Botlib_ResetSubsystemState(); + LibVar_Shutdown(); + BotMemory_Shutdown(); + return status; + } + + status = Botlib_SetupSoundSubsystem(); + if (status != BLERR_NOERROR) { + Botlib_ShutdownAASSubsystem(); + Botlib_ShutdownEASubsystem(); + Botlib_ShutdownAISubsystem(); + Botlib_ShutdownUtilities(); + Botlib_ResetLibraryVariables(); + Botlib_ResetSubsystemState(); + LibVar_Shutdown(); + BotMemory_Shutdown(); + return status; + } + + AAS_DebugRegisterConsoleCommands(); + + g_library_initialised = true; + BotLib_Print(PRT_MESSAGE, "-------------------------------------\n"); + return BLERR_NOERROR; } +/* +============= +BotShutdownLibrary + +Tears down the botlib subsystems and releases shared state. +============= +*/ int BotShutdownLibrary(void) { - if (!g_library_initialised) { - return BLERR_LIBRARYNOTSETUP; - } + if (!g_library_initialised) { + return BLERR_LIBRARYNOTSETUP; + } - AAS_DebugUnregisterConsoleCommands(); + AAS_DebugUnregisterConsoleCommands(); - Botlib_ShutdownSoundSubsystem(); - Botlib_ShutdownAISubsystem(); - Botlib_ShutdownEASubsystem(); - Botlib_ShutdownAASSubsystem(); - Botlib_ShutdownUtilities(); + Botlib_ShutdownSoundSubsystem(); + Botlib_ShutdownAISubsystem(); + Botlib_ShutdownEASubsystem(); + Botlib_ShutdownAASSubsystem(); + Botlib_ShutdownUtilities(); - Botlib_ResetLibraryVariables(); - Botlib_ResetSubsystemState(); - LibVar_Shutdown(); + Botlib_ResetLibraryVariables(); + Botlib_ResetSubsystemState(); + LibVar_Shutdown(); - g_library_initialised = false; + g_library_initialised = false; - BotMemory_Shutdown(); - return BLERR_NOERROR; + BotMemory_Shutdown(); + return BLERR_NOERROR; } +/* +============= +BotLibraryInitialized +============= +*/ bool BotLibraryInitialized(void) { - return g_library_initialised; + return g_library_initialised; } +/* +============= +BotInterface_GetLibraryVariables +============= +*/ const botlib_library_variables_t *BotInterface_GetLibraryVariables(void) { - return &g_library_variables; + return &g_library_variables; }