| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Combat/scripts.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 7/09/02 9:19a $*
- * *
- * $Revision:: 53 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "scripts.h"
- #include "debug.h"
- #include "scriptcommands.h"
- #include "physicalgameobj.h"
- #include "wwstring.h"
- #include "combat.h"
- #include "wwprofile.h"
- #include "ffactorylist.h"
- #include "rawfile.h"
- #include "gametype.h"
- #include <stdio.h>
- #include <win.h>
- ScriptCommands* EngineCommands = NULL;
- #if 1
- #define SCRIPT_PROFILE_START( x ) WWProfileManager::Profile_Start( "Scripts" );
- #define SCRIPT_PROFILE_STOP( x ) WWProfileManager::Profile_Stop( );
- #else
- #define SCRIPT_PROFILE_START( x )
- #define SCRIPT_PROFILE_STOP( x )
- #endif
- /*
- **
- */
- HINSTANCE hDLL = NULL;
- LPFN_CREATE_SCRIPT ScriptManager::ScriptCreateFunct = NULL;
- LPFN_DESTROY_SCRIPT ScriptManager::ScriptDestroyFunct = NULL;
- SimpleDynVecClass<ScriptClass *> ScriptManager::ActiveScriptList;
- SimpleDynVecClass<ScriptClass *> ScriptManager::PendingDestroyList;
- bool ScriptManager::EnableScriptCreation = true;
- /*
- **
- */
- void ScriptManager::Init(void)
- {
- hDLL = NULL;
- EngineCommands = Get_Script_Commands();
- #ifdef PARAM_EDITING_ON // Editor build
- Load_Scripts("SCRIPTS.DLL");
- #else
- #ifdef WWDEBUG // DEBUG and PROFILE
- if ( DebugManager::Load_Debug_Scripts() ) {
- Load_Scripts("SCRIPTSD.DLL"); // DEBUG
- } else {
- #ifdef NDEBUG // PROFILE
- Load_Scripts("SCRIPTSP.DLL"); // PROFILE
- #else
- Load_Scripts("SCRIPTSD.DLL"); // DEBUG
- #endif
- }
- #else
- Load_Scripts("SCRIPTS.DLL"); // RELEASE
- #endif
- #endif
- }
- /*
- **
- */
- void ScriptManager::Shutdown(void)
- {
- // Release scripts
- while (ActiveScriptList.Count()) {
- ScriptClass* script = ActiveScriptList[0];
- assert(script != NULL);
- assert(ScriptDestroyFunct != NULL);
- ScriptDestroyFunct(script);
-
- ActiveScriptList.Delete(0);
- }
- if (hDLL != NULL) {
- FreeLibrary(hDLL);
- hDLL = NULL;
- }
- }
- void ScriptManager::Destroy_Pending(void)
- {
- // Destroy all the scripts in the pending destroy list.
- while (PendingDestroyList.Count()) {
- ScriptClass* script = PendingDestroyList[0];
- assert(script != NULL);
- // If the script has an owner then it must be detached before it
- // can be destroyed.
- ScriptableGameObj* object = script->Owner();
- if (object != NULL) {
- object->Remove_Observer(script);
- }
- // Destroy the script
- assert(ScriptDestroyFunct != NULL);
- ScriptDestroyFunct(script);
- PendingDestroyList.Delete(0);
- }
- }
- /*
- **
- */
- void ScriptManager::Load_Scripts(const char* dll_filename)
- {
- Debug_Say(("Script Manager Loading Script File %s\n", dll_filename));
- // If we're in multiplay and not the server, just bail
- if (!IS_SOLOPLAY && CombatManager::I_Am_Only_Client())
- {
- return;
- }
- #ifndef PARAM_EDITING_ON // Only do this in the *game*
- // Check if we have a mod, if so, un-pack the scripts from the PKG (if present)
- FileFactoryClass * mod_pkg = FileFactoryListClass::Get_Instance()->Peek_Temp_FileFactory();
- if (mod_pkg != NULL) {
- FileClass * scripts_dll = mod_pkg->Get_File( dll_filename );
- if ((scripts_dll != NULL) && (scripts_dll->Is_Available())) {
- const char * _TMP_SCRIPTS_DLL_FILENAME = "_MOD_SCRIPTS.DLL";
- scripts_dll->Open(FileClass::READ);
- RawFileClass unpacked_scripts(_TMP_SCRIPTS_DLL_FILENAME);
- if (unpacked_scripts.Create()) {
-
- unpacked_scripts.Open(FileClass::WRITE);
- // Copy the dll from the PKG (mix) file into our temporary _scripts directory
- static char buffer[16000];
- int scripts_size = scripts_dll->Size();
- int cur_pos = 0;
- while (cur_pos < scripts_size) {
- int read_count = WWMath::Min(scripts_size - cur_pos,sizeof(buffer));
- scripts_dll->Read(buffer,read_count);
- unpacked_scripts.Write(buffer,read_count);
- cur_pos += read_count;
- }
- // change 'dll_filename' so that we load the newly created dll
- if (cur_pos == scripts_size) {
- dll_filename = _TMP_SCRIPTS_DLL_FILENAME;
- }
- unpacked_scripts.Close();
- }
- scripts_dll->Close();
- mod_pkg->Return_File(scripts_dll);
- }
- }
- #endif
- hDLL = LoadLibrary(dll_filename);
- if (hDLL == NULL) {
- Debug_Say(("Cound not load DLL file %s\n", dll_filename));
- return;
- }
- // Get create script function
- ScriptCreateFunct = (LPFN_CREATE_SCRIPT)GetProcAddress(hDLL, LPSTR_CREATE_SCRIPT);
- assert(ScriptCreateFunct != NULL);
- if (!ScriptCreateFunct) {
- Debug_Say(("Cound not find Create_Script\n"));
- }
- // Get destroy script function
- ScriptDestroyFunct = (LPFN_DESTROY_SCRIPT)GetProcAddress(hDLL, LPSTR_DESTROY_SCRIPT);
- assert(ScriptDestroyFunct != NULL);
- if (!ScriptDestroyFunct) {
- Debug_Say(("Cound not find Destroy_Script\n"));
- }
- // Initialize request script destroy function
- LPFN_SET_REQUEST_DESTROY_FUNC set_request_destroy_func =
- (LPFN_SET_REQUEST_DESTROY_FUNC)GetProcAddress(hDLL, LPSTR_SET_REQUEST_DESTROY_FUNC);
- assert(set_request_destroy_func != NULL);
- if (set_request_destroy_func != NULL) {
- set_request_destroy_func(Request_Destroy_Script);
- } else {
- Debug_Say(("Cound not find Set_Request_Destroy_Func\n"));
- }
- // Initialize script commands if not being run from the editor
- if (CombatManager::Are_Observers_Active()) {
- LPFN_SET_SCRIPT_COMMANDS set_commands_func =
- (LPFN_SET_SCRIPT_COMMANDS)GetProcAddress(hDLL, LPSTR_SET_SCRIPT_COMMANDS);
- assert(set_commands_func != NULL);
- if (set_commands_func != NULL) {
- ScriptCommandsClass commands;
- commands.Commands = EngineCommands;
- bool success = set_commands_func(&commands);
- if (!success) {
- Debug_Say(("Failed to set script commands!\n"));
- // This should keep us from going to scripts!
- ScriptCreateFunct = NULL;
- }
- } else {
- Debug_Say(("Cound not find Set_Script_Commands\n"));
- }
- }
- }
- /*
- **
- */
- ScriptClass* ScriptManager::Create_Script(const char* script_name)
- {
- ScriptClass* script = NULL;
- if (EnableScriptCreation && ScriptCreateFunct != NULL) {
- script = ScriptCreateFunct(script_name);
- if (script != NULL) {
- script->Set_ID( GameObjObserverManager::Get_Next_Observer_ID() );
- ActiveScriptList.Add(script);
- }
- }
- return script;
- }
- /*
- **
- */
- void ScriptManager::Request_Destroy_Script(ScriptClass* script)
- {
- ActiveScriptList.Delete(script);
- // Do not add the script to the destroy list if it is already there.
- for (int index = 0; index < PendingDestroyList.Count(); index++) {
- if (PendingDestroyList[index] == script) {
- return;
- }
- }
- PendingDestroyList.Add(script);
- }
- /*
- ** Script Manager Save and Load
- */
- enum {
- CHUNKID_SCRIPT_ENTRY = 131001134,
- CHUNKID_SCRIPT_HEADER,
- CHUNKID_SCRIPT_DATA,
- MICROCHUNKID_NAME = 1,
- // Denzil 3/31/00 - This information is now saved by the script.
- #if(0)
- MICROCHUNKID_PARAM_COUNT,
- #endif
- MICROCHUNKID_PARAM,
- MICROCHUNKID_GAME_OBJ_OBSERVER_PTR,
- MICROCHUNKID_OWNER_PTR,
- MICROCHUNKID_ID,
- };
- /*
- **
- */
- bool ScriptManager::Save(ChunkSaveClass& csave)
- {
- for (int index = 0; index < ActiveScriptList.Count(); index++) {
- ScriptClass* script = ActiveScriptList[ index ];
- csave.Begin_Chunk( CHUNKID_SCRIPT_ENTRY );
- csave.Begin_Chunk( CHUNKID_SCRIPT_HEADER );
- StringClass name = script->Get_Name();
- // Debug_Say(("Saving script '%s'\n", name));
- WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_NAME, name );
- char paramString[256];
- script->Get_Parameters_String(paramString, sizeof(paramString));
- // Debug_Say(("\tParameters: '%s'\n", paramString));
- WRITE_MICRO_CHUNK_STRING(csave, MICROCHUNKID_PARAM, paramString);
- GameObjObserverClass* game_obj_observer_ptr = (GameObjObserverClass*)script;
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_GAME_OBJ_OBSERVER_PTR, game_obj_observer_ptr );
- ScriptableGameObj* owner_ptr = *(script->Get_Owner_Ptr());
- // Debug_Say(("\tObjectPtr: '%p'\n", *owner_ptr));
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_OWNER_PTR, owner_ptr );
- int id = script->Get_ID();
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ID, id );
- // Debug_Say(( "Saved Script ID %d\n", id ));
- csave.End_Chunk();
- // If data is not saved, script will be re-created
- if (CombatManager::Are_Observers_Active()) {
- csave.Begin_Chunk(CHUNKID_SCRIPT_DATA);
- ScriptSaver saver(csave);
- script->Save(saver);
- csave.End_Chunk();
- }
- csave.End_Chunk();
- }
- return true;
- }
- bool ScriptManager::Load( ChunkLoadClass & cload )
- {
- WWASSERT( ActiveScriptList.Count() == 0 );
- while (cload.Open_Chunk()) {
- GameObjObserverClass * game_obj_observer_ptr = NULL;
- PhysicalGameObj * owner_ptr = NULL;
- WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_SCRIPT_ENTRY );
- ScriptClass *script = NULL;
- // Load header
- cload.Open_Chunk();
- WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_SCRIPT_HEADER );
- int obs_id = -1;
- // int param_index = 0;
- while (cload.Open_Micro_Chunk()) {
- int id = cload.Cur_Micro_Chunk_ID();
- switch( id ) {
- case MICROCHUNKID_NAME:
- {
- StringClass name;
- LOAD_MICRO_CHUNK_WWSTRING( cload, name );
- WWASSERT( script == NULL );
- script = Create_Script( name );
- if ( script == NULL ) {
- Debug_Say(( "Script %s not found \n", name ));
- }
- // A Missing script is not fatal
- // WWASSERT( script != NULL );
- break;
- }
- case MICROCHUNKID_PARAM:
- {
- if ( script != NULL ) {
- StringClass param;
- LOAD_MICRO_CHUNK_WWSTRING( cload, param );
- script->Set_Parameters_String(param);
- }
- break;
- }
- READ_MICRO_CHUNK( cload, MICROCHUNKID_GAME_OBJ_OBSERVER_PTR, game_obj_observer_ptr );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_OWNER_PTR, owner_ptr );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_ID, obs_id );
- default:
- Debug_Say(( "Unrecognized ScriptCollection Header chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- cload.Close_Chunk();
- if ( script != NULL ) {
- if ( obs_id != -1 ) {
- script->Set_ID( obs_id );
- // Debug_Say(( "Loaded Script ID %d\n", obs_id ));
- }
- // If there is data, load
- if ( cload.Open_Chunk() ) {
- WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_SCRIPT_DATA );
- ScriptLoader loader( cload );
- script->Load( loader );
- cload.Close_Chunk();
- }
- WWASSERT( game_obj_observer_ptr != NULL );
- if ( game_obj_observer_ptr != NULL ) {
- SaveLoadSystemClass::Register_Pointer(game_obj_observer_ptr, (GameObjObserverClass *)script);
- }
- // set the owner, and request remap
- *(script->Get_Owner_Ptr()) = owner_ptr;
- REQUEST_POINTER_REMAP( (void **)script->Get_Owner_Ptr() );
- } else {
- SaveLoadSystemClass::Register_Pointer(game_obj_observer_ptr, (GameObjObserverClass *)NULL);
- }
- cload.Close_Chunk();
- }
- return true;
- }
-
|