/* ** 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 . */ /****************************************************************************** * * FILE * * DESCRIPTION * * PROGRAMMER * Byon Garrabrant * * VERSION INFO * $Author: Greg_h $ * $Revision: 51 $ * $Modtime: 12/13/01 10:37a $ * $Archive: /Commando/Code/Scripts/Test_Cinematic.cpp $ * ******************************************************************************/ #include "scripts.h" #include "toolkit.h" #include #include #define LAST_VALID_TIMESTAMP 999000.0f DECLARE_SCRIPT (M00_Cinematic_Attack_Command_DLS, "AttackDuration=1.0:float") { void Created( GameObject * obj ) { float facing = Commands->Get_Facing(Owner()); Vector3 target = Commands->Get_Position(Owner()); target.X += cos(DEG_TO_RADF(facing)) * 10.0f; target.Y += sin(DEG_TO_RADF(facing)) * 10.0f; target.Z += 2.0f; ActionParamsStruct params; params.Set_Basic( this, 99, 1 ); params.Set_Attack( target, 100.0f, 0.0f, true ); params.AttackForceFire = true; Commands->Action_Attack( obj, params ); Commands->Send_Custom_Event( obj, obj, 1, 1, Get_Float_Parameter("AttackDuration") ); } void Custom( GameObject * obj, int type, int param, GameObject * sender ) { Commands->Action_Reset( obj, 100 ); } }; DECLARE_SCRIPT(Test_Cinematic_Primary_Killed, "CallbackID=:int") { bool custom_sent; // Register variables to be Auto-Saved // All variables must have a unique ID, less than 256, that never changes REGISTER_VARIABLES() { SAVE_VARIABLE( custom_sent, 1 ); } virtual void Created (GameObject *game_obj) { custom_sent = false; } virtual void Killed( GameObject * obj, GameObject * killer ) { if (!custom_sent) { custom_sent = true; Commands->Debug_Message( "Cinematic Primary Killed\n" ); int id = Get_Int_Parameter( "CallbackID" ); GameObject * callback = Commands->Find_Object( id ); if ( callback ) { Commands->Send_Custom_Event( obj, callback, M00_CUSTOM_CINEMATIC_PRIMARY_KILLED, 0 ); } } } virtual void Destroyed( GameObject * obj ) { if (!custom_sent) { custom_sent = true; Commands->Debug_Message( "Cinematic Primary Destroyed\n" ); int id = Get_Int_Parameter( "CallbackID" ); GameObject * callback = Commands->Find_Object( id ); if ( callback ) { Commands->Send_Custom_Event( obj, callback, M00_CUSTOM_CINEMATIC_PRIMARY_KILLED, 0 ); } } } }; DECLARE_SCRIPT(Test_Cinematic, "ControlFilename=:string") { public: /* ** Object Slots */ #define NUM_SLOTS 40 int ObjectSlots[ NUM_SLOTS ]; int MyID; // doesn't need to be saved /* ** Timing */ unsigned int LastSyncTime; float Time; float FrameSync; bool PrimaryKilled; bool IsCameraCinematic; /* ** Parameters */ char * NextParameter; /* ** Control Lines */ struct ControlLine { float Time; char * Command; ControlLine * Next; }; ControlLine * Controls; void Add_Control_Line( float time, const char * command ) { ControlLine * control = new ControlLine; control->Time = time; control->Command = strdup( command ); control->Next = NULL; if ( Controls == NULL || Controls->Time > time ) { control->Next = Controls; Controls = control; } else { ControlLine * node = Controls; while ( (node->Next != NULL) && (node->Next->Time <= time) ) { node = node->Next; } control->Next = node->Next; node->Next = control; } } void Remove_Head_Control_Line( void ) { if ( Controls != NULL ) { ControlLine * control = Controls; Controls = Controls->Next; free( control->Command ); delete control; } } void Display_Control_Lines( void ) { for ( ControlLine * node = Controls; node != NULL; node = node->Next ) { // Commands->Debug_Message( "%3.2f \"%s\"\n", node->Time, node->Command ); } } /* ** Loading the control file, line-by-line */ void Load_Control_File( const char * filename ) { Commands->Debug_Message( "Loading Control File %s\n", (int)filename ); char full_filename[80]; sprintf( full_filename, "DATA\\%s", filename ); // FILE * in = fopen( full_filename, "rt" ); int handle = Commands->Text_File_Open( filename ); if ( handle == 0 ) { Commands->Debug_Message( "Failed to open %s\n", (int)full_filename ); return; } char *line,line_data[200]; while ( Commands->Text_File_Get_String( handle, line_data, sizeof( line_data )-1 ) != NULL ) { line = line_data; // Convert tabs to spaces for ( char * l = line; *l; l++ ) { if ( *l == 9 ) *l = ' '; } // Remove leading and trailing white space while ( *line && *line <= ' ' ) line++; int length = ::strlen( line ); while ( (length != 0) && (line[length-1] <= ' ') ) { line[--length] = 0; } if ( *line && *line != ';' ) { // ignore comments float time; time = atof( line ); if ( time < 0 ) { // handle frame numbers time = -time / 30.f; } while ( *line && *line > ' ' ) line++; while ( *line && *line <= ' ' ) line++; if ( *line ) { Add_Control_Line( time, line ); } } } // fclose( in ); Commands->Text_File_Close( handle ); } /* ** */ char * Get_Command_Parameter( char * string = NULL ) { if ( string != NULL ) { NextParameter = string; } if ( NextParameter == NULL || *NextParameter == 0 ) return ""; // Start at this parameter; char * parameter = NextParameter; // Skip leading whitespace while ( *parameter != 0 && *parameter <= ' ' ) parameter++; // if starting with quote, find end quote if ( *parameter == '\"' ) { parameter++; NextParameter = parameter; while ( *NextParameter && *NextParameter != '\"' ) { NextParameter++; } } // Find next parameter end while ( *NextParameter && *NextParameter != ',' ) { NextParameter++; } // Terminate if ( *NextParameter ) { *NextParameter++ = 0; } // Remove trailing whitespace int length = ::strlen( parameter ); while ( length && parameter[ length-1 ] <= ' ' ) { parameter[ --length ] = 0; } // Remove end quote if ( length && parameter[ length-1 ] == '\"' ) { parameter[ --length ] = 0; } return parameter; } #define CHUNKID_VARIABLES 1000 #define CHUNKID_OBJECT_SLOTS 1001 #define CHUNKID_CONTROL_LINES 1002 #define CHUNKID_VARIABLE_SYNC_DIFF 1 #define CHUNKID_VARIABLE_TIME 2 #define CHUNKID_CONTROL_TIME 4 #define CHUNKID_CONTROL_COMMAND_SIZE 5 #define CHUNKID_CONTROL_COMMAND 6 #define CHUNKID_PRIMARY_KILLED 7 /* ** */ void Save(ScriptSaver& saver) { // Commands->Debug_Message( "Cinematic Saving\n" ); // Commands->Debug_Message("Sync time is %d.\n", Commands->Get_Sync_Time()); // Save the Variables Commands->Begin_Chunk(saver, CHUNKID_VARIABLES); int sync_diff = Commands->Get_Sync_Time() - LastSyncTime; Commands->Save_Data(saver, CHUNKID_VARIABLE_SYNC_DIFF, sizeof( sync_diff ), &sync_diff ); //Commands->Debug_Message( "Saving sync_diff %d\n", sync_diff ); Commands->Save_Data(saver, CHUNKID_VARIABLE_TIME, sizeof( Time ), &Time ); //Commands->Debug_Message( "Saving Time %f\n", Time ); Commands->Save_Data(saver, CHUNKID_PRIMARY_KILLED, sizeof( PrimaryKilled ), &PrimaryKilled ); Commands->End_Chunk(saver); // Save the Object Slots Commands->Begin_Chunk(saver, CHUNKID_OBJECT_SLOTS); for ( int i = 0; i < NUM_SLOTS; i++ ) { if ( ObjectSlots[i] != 0 ) { Commands->Save_Data(saver, i, sizeof( ObjectSlots[i] ), &ObjectSlots[ i ] ); //Commands->Debug_Message( "Saving Slot %d as %d\n", i, ObjectSlots[ i ] ); } } Commands->End_Chunk(saver); // Save Control Lines Commands->Begin_Chunk(saver, CHUNKID_CONTROL_LINES); ControlLine * controls = Controls; while ( controls != NULL ) { Commands->Save_Data(saver, CHUNKID_CONTROL_TIME, sizeof( controls->Time ), &controls->Time ); int len = strlen( controls->Command ) + 1; Commands->Save_Data(saver, CHUNKID_CONTROL_COMMAND_SIZE, sizeof( len ), &len ); Commands->Save_Data(saver, CHUNKID_CONTROL_COMMAND, len, controls->Command ); //Commands->Debug_Message( "Saving Command %f %s\n", controls->Time, controls->Command ); controls = controls->Next; } Commands->End_Chunk(saver); } void Load(ScriptLoader& loader) { Controls = NULL; NextParameter = NULL; for ( int i = 0; i < NUM_SLOTS; i++ ) { ObjectSlots[i] =0; } // Commands->Debug_Message( "Cinematic Loading\n" ); // Commands->Debug_Message("Sync time is %d.\n", Commands->Get_Sync_Time()); unsigned int chunkID; while (Commands->Open_Chunk(loader, &chunkID)) { switch (chunkID) { case CHUNKID_VARIABLES: { int id; int sync_diff; while (Commands->Load_Begin(loader, &id)) { switch ( id ) { case CHUNKID_VARIABLE_SYNC_DIFF: Commands->Load_Data(loader, sizeof( sync_diff ), &sync_diff ); //Commands->Debug_Message( "Loading sync_diff %d\n", sync_diff ); LastSyncTime = Commands->Get_Sync_Time() - sync_diff; break; case CHUNKID_VARIABLE_TIME: Commands->Load_Data(loader, sizeof( Time ), &Time ); //Commands->Debug_Message( "Loading Time %f\n", Time ); break; case CHUNKID_PRIMARY_KILLED: Commands->Load_Data(loader, sizeof( PrimaryKilled ), &PrimaryKilled ); //Commands->Debug_Message( "Loading Time %f\n", Time ); break; } Commands->Load_End(loader); } } break; case CHUNKID_OBJECT_SLOTS: { int id; while (Commands->Load_Begin(loader, &id)) { if ( id >= 0 && id < NUM_SLOTS ) { Commands->Load_Data(loader, sizeof( ObjectSlots[id] ), &ObjectSlots[id] ); //Commands->Debug_Message( "Loading Slot %d as %d\n", id, ObjectSlots[ id ] ); } Commands->Load_End(loader); } } break; case CHUNKID_CONTROL_LINES: { int id; float time = 0; int len = 0; while (Commands->Load_Begin(loader, &id)) { if ( id == CHUNKID_CONTROL_TIME ) { Commands->Load_Data(loader, sizeof( time ), &time ); } if ( id == CHUNKID_CONTROL_COMMAND_SIZE ) { Commands->Load_Data(loader, sizeof( len ), &len ); } if ( id == CHUNKID_CONTROL_COMMAND ) { #define MAX_COMMAND_LOAD_SIZE 200 char load_command[MAX_COMMAND_LOAD_SIZE+1]; if ( len < MAX_COMMAND_LOAD_SIZE ) { Commands->Load_Data(loader, len, &load_command[0] ); Add_Control_Line( time, load_command ); //Commands->Debug_Message( "Loading Command %f %s\n", time, load_command ); } } Commands->Load_End(loader); } } break; default: DebugPrint("***** Cinematic Script::Load() - Unrecognized chunk %0x!\n", chunkID); break; } Commands->Close_Chunk(loader); } } char * Get_First_Parameter( char * str ) { return Get_Command_Parameter( str ); } char * Get_Next_Parameter( void ) { return Get_Command_Parameter(); } /* ** */ void Command_Create_Object( char * params ) { // Commands->Debug_Message_2( "Creating Object %s\n", (int)params ); int slot = atoi( Get_First_Parameter( params ) ); char * model_name = Get_Next_Parameter(); if ( (slot < 0) || ( slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", slot ); slot = -1; } if ( slot != -1 && ObjectSlots[ slot ] != 0 ) { // Commands->Debug_Message( "Used Slot number %d\n", slot ); // Commands->Debug_Message( "Slot used by %d\n", ObjectSlots[ slot ] ); } // Create a decoration cinematic object, then set it's model GameObject * obj = Commands->Create_Object( "Generic_Cinematic", Commands->Get_Position( Owner() ) ); Commands->Enable_Hibernation( obj, false ); if ( obj ) { Commands->Add_To_Dirty_Cull_List(obj); Commands->Set_Model( obj, model_name ); Commands->Set_Facing( obj, Commands->Get_Facing( Owner() ) ); if ( slot != -1 ) { ObjectSlots[ slot ] = Commands->Get_ID( obj ); } if ( IsCameraCinematic ) { Commands->Enable_Cinematic_Freeze( obj, false ); Commands->Enable_Hibernation(obj, false); } } else { // Commands->Debug_Message( "Failed to create %s\n", (int)model_name ); } } /* ** */ void Command_Create_Real_Object( char * params ) { // Commands->Debug_Message_2( "Creating Real Object %s\n", (int)params ); int slot = atoi( Get_First_Parameter( params ) ); char * preset_name = Get_Next_Parameter(); char * host_slot_name = Get_Next_Parameter(); char * host_bone_name = Get_Next_Parameter(); if ( (slot < 0) || ( slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", slot ); slot = -1; } if ( slot != -1 && ObjectSlots[ slot ] != 0 ) { // Commands->Debug_Message( "Used Slot number %d\n", slot ); // Commands->Debug_Message( "Slot used by %d\n", ObjectSlots[ slot ] ); } GameObject * obj = NULL; if (( host_slot_name != NULL ) && ( *host_slot_name != 0 ) ) { int host_slot = atoi( host_slot_name ); GameObject * host_obj = Commands->Find_Object( ObjectSlots[ host_slot ] ); obj = Commands->Create_Object_At_Bone( host_obj, preset_name, host_bone_name ); } else { obj = Commands->Create_Object( preset_name, Commands->Get_Position( Owner() ) ); Commands->Set_Facing( obj, Commands->Get_Facing( Owner() ) ); } if ( obj ) { Commands->Enable_Engine( obj, true ); Commands->Add_To_Dirty_Cull_List(obj); // Commands->Enable_Hibernation( obj, false ); if ( slot != -1 ) { ObjectSlots[ slot ] = Commands->Get_ID( obj ); } if ( IsCameraCinematic ) { Commands->Enable_Cinematic_Freeze( obj, false ); Commands->Enable_Hibernation(obj, false); } } else { // Commands->Debug_Message( "Failed to create real %s\n", (int)preset_name ); } } /* ** */ void Command_Create_Explosion( char * params ) { // Commands->Debug_Message_2( "Creating Explosion %s\n", (int)params ); char * preset_name = Get_First_Parameter( params ); int host_slot = atoi( Get_Next_Parameter() ); char * host_bone_name = Get_Next_Parameter(); GameObject * host_obj = Commands->Find_Object( ObjectSlots[ host_slot ] ); Commands->Create_Explosion_At_Bone( preset_name, host_obj, host_bone_name ); } void Command_Destroy_Object( char * params ) { // Commands->Debug_Message_2( "Destroying Object %s\n", (int)params ); int slot = atoi( Get_First_Parameter( params ) ); if ( (slot < 0) || ( slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", slot ); slot = -1; } if ( slot != -1 ) { if ( ObjectSlots[ slot ] == 0 ) { // Commands->Debug_Message( "Empty Slot number %d\n", slot ); } else { int id = ObjectSlots[ slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Commands->Destroy_Object( obj ); } } } } void Command_Play_Animation( char * params ) { // Commands->Debug_Message( "Playing Animation %s\n", (int)params ); int slot = atoi( Get_First_Parameter( params ) ); char * name = Get_Next_Parameter(); bool looping = atoi( Get_Next_Parameter() ) != 0; char * sub_obj_name = Get_Next_Parameter(); bool is_blended = atoi( Get_Next_Parameter() ) == 1; if ( (slot < 0) || ( slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", slot ); slot = -1; } if ( slot != -1 ) { int id = ObjectSlots[ slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Commands->Set_Animation( obj, name, looping, sub_obj_name, FrameSync, -1.0F, is_blended ); // Anyone that plays an animation in a camera cine, doesn't get innate if ( IsCameraCinematic ) { Commands->Innate_Disable( obj ); } } else { // Commands->Debug_Message( "Slot Object not found %d\n", slot ); } } } void Command_Play_Audio( char * params ) { // Commands->Debug_Message( "Playing Audio %s\n", (int)params ); char * preset_name = Get_First_Parameter( params ); char * slot_name = Get_Next_Parameter(); char * bone_name = Get_Next_Parameter(); int slot = -1; if (( slot_name != NULL ) && ( *slot_name != 0 ) ) { slot = atoi( slot_name ); } if ( (slot < 0) || ( slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", slot ); slot = -1; } if ( slot != -1 ) { int id = ObjectSlots[ slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Commands->Create_3D_Sound_At_Bone( preset_name, obj, bone_name ); } else { // Commands->Debug_Message( "Slot Object not found %d\n", slot ); } } else { Commands->Create_2D_Sound( preset_name ); } } void Command_Control_Camera( char * params ) { // Commands->Debug_Message_2( "Controlling the camera %s\n", (int)params ); int slot = atoi( Get_First_Parameter( params ) ); if ( (slot < -1) || ( slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", slot ); slot = -1; } if ( slot != -1 ) { int id = ObjectSlots[ slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Commands->Set_Camera_Host( obj ); Commands->Control_Enable( Commands->Get_The_Star(), false ); Commands->Enable_HUD(0); IsCameraCinematic = true; Commands->Enable_Cinematic_Freeze( obj, false ); Commands->Enable_Hibernation(obj, false); } else { // Commands->Debug_Message( "Slot Object not found %d\n", slot ); } } else { Commands->Set_Camera_Host( NULL ); Commands->Control_Enable( Commands->Get_The_Star(), true ); Commands->Enable_HUD(1); } } void Command_Send_Custom( char * params ) { // Commands->Debug_Message_2( "Send Custom %s\n", (int)params ); char * to_id_name = Get_First_Parameter( params ); int type = atoi( Get_Next_Parameter() ); char * parameter_name = Get_Next_Parameter(); int to_id = -1; if ( ::strchr( to_id_name, '#' ) != NULL ) { int to_slot = atoi( ::strchr( to_id_name, '#' ) + 1 ); if ( (to_slot < 0) || ( to_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", to_slot ); } else { to_id = ObjectSlots[ to_slot ]; } } else { to_id = atoi( to_id_name ); } int parameter = 0; if ( ::strchr( parameter_name, '#' ) != NULL ) { int parameter_slot = atoi( ::strchr( parameter_name, '#' ) + 1 ); if ( (parameter_slot < 0) || ( parameter_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Slot Number %d\n", parameter_slot ); } else { parameter = ObjectSlots[ parameter_slot ]; } } else { parameter = atoi( parameter_name ); } GameObject * to = Commands->Find_Object( to_id ); if ( to ) { Commands->Send_Custom_Event( Owner(), to, type, parameter ); } else { // Commands->Debug_Message( "Send Custom Target not found %d\n", to_id ); } } void Command_Attach_To_Bone( char * params ) { // Commands->Debug_Message_2( "Attach_To_Bone %s\n", (int)params ); int obj_slot = atoi( Get_First_Parameter( params ) ); int host_slot = atoi( Get_Next_Parameter() ); char * bone_name = Get_Next_Parameter(); if ( (obj_slot < 0) || ( obj_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Obj Slot Number %d\n", obj_slot ); obj_slot = -1; } if ( (host_slot < 0) || ( host_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Host Slot Number %d\n", host_slot ); host_slot = -1; } if ( obj_slot != -1 ) { int id = ObjectSlots[ obj_slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { if ( host_slot != -1 ) { int id = ObjectSlots[ host_slot ]; GameObject * host = Commands->Find_Object( id ); if ( host ) { Commands->Attach_To_Object_Bone( obj, host, bone_name ); } else { // Commands->Debug_Message( "Host Object not found %d\n", host_slot ); } } else { Commands->Attach_To_Object_Bone( obj, NULL, NULL ); } } else { // Commands->Debug_Message( "Slot Object not found %d\n", obj_slot ); } } } void Command_Attach_Script( char * params ) { // Commands->Debug_Message_2( "Attach_Script %s\n", (int)params ); int obj_slot = atoi( Get_First_Parameter( params ) ); char * script_name = Get_Next_Parameter(); char * script_parameters = Get_Next_Parameter(); if ( (obj_slot < 0) || ( obj_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Obj Slot Number %d\n", obj_slot ); obj_slot = -1; } if ( obj_slot != -1 ) { int id = ObjectSlots[ obj_slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { // Commands->Debug_Message( "Attaching Script %s \"%s\"\n", script_name, script_parameters ); Commands->Attach_Script( obj, script_name, script_parameters ); } else { // Commands->Debug_Message( "Slot Object not found %d\n", obj_slot ); } } } void Command_Set_Primary( char * params ) { // Commands->Debug_Message_2( "Set_Primary %s\n", (int)params ); int obj_slot = atoi( Get_First_Parameter( params ) ); if ( (obj_slot < 0) || ( obj_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Obj Slot Number %d\n", obj_slot ); obj_slot = -1; } if ( obj_slot != -1 ) { int id = ObjectSlots[ obj_slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Commands->Enable_Hibernation( obj, false ); char id[10]; sprintf( id, "%d", MyID ); Commands->Attach_Script( obj, "Test_Cinematic_Primary_Killed", id ); } else { // Commands->Debug_Message( "Slot Object not found %d\n", obj_slot ); } } } void Command_Move_Slot( char * params ) { int new_slot = atoi( Get_First_Parameter( params ) ); int old_slot = atoi( Get_Next_Parameter() ); if ( (new_slot < 0) || ( new_slot >= NUM_SLOTS ) ) { new_slot = -1; } if ( (old_slot < 0) || ( old_slot >= NUM_SLOTS ) ) { old_slot = -1; } if ( new_slot != -1 && old_slot != -1 && new_slot != old_slot ) { ObjectSlots[ new_slot ] = ObjectSlots[ old_slot ]; ObjectSlots[ old_slot ] = 0; } } void Command_Sniper_Control( char * params ) { int enabled = atoi( Get_First_Parameter( params ) ); float zoom = atof( Get_Next_Parameter() ); Commands->Cinematic_Sniper_Control( enabled != 0, zoom ); } void Command_Shake_Camera( char * params ) { int obj_slot = atoi( Get_First_Parameter( params ) ); float intensity = atof( Get_Next_Parameter() ); float duration = atof( Get_Next_Parameter() ); if ( (obj_slot < 0) || ( obj_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Obj Slot Number %d\n", obj_slot ); obj_slot = -1; } if ( obj_slot != -1 ) { int id = ObjectSlots[ obj_slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Vector3 pos = Commands->Get_Bone_Position( obj, "Camera" ); Commands->Shake_Camera( pos, 100, intensity, duration ); } else { // Commands->Debug_Message( "Slot Object not found %d\n", obj_slot ); } } } void Command_Enable_Shadow( char * params ) { int obj_slot = atoi( Get_First_Parameter( params ) ); int onoff = atoi( Get_Next_Parameter() ); if ( (obj_slot < 0) || ( obj_slot >= NUM_SLOTS ) ) { // Commands->Debug_Message( "Bad Obj Slot Number %d\n", obj_slot ); obj_slot = -1; } if ( obj_slot != -1 ) { int id = ObjectSlots[ obj_slot ]; GameObject * obj = Commands->Find_Object( id ); if ( obj ) { Commands->Enable_Shadow(obj,(onoff != 0)); } else { // Commands->Debug_Message( "Slot Object not found %d\n", obj_slot ); } } } void Command_Enable_Letterbox( char * params ) { int onoff = atoi( Get_First_Parameter( params ) ); float time = atof( Get_Next_Parameter() ); Commands->Enable_Letterbox(!!onoff,time); } void Command_Set_Screen_Fade_Color( char * params ) { float r = atof( Get_First_Parameter( params ) ); float g = atof( Get_Next_Parameter() ); float b = atof( Get_Next_Parameter() ); float time = atof( Get_Next_Parameter() ); Commands->Set_Screen_Fade_Color(r,g,b,time); } void Command_Set_Screen_Fade_Opacity( char * params ) { float opacity = atof( Get_First_Parameter( params ) ); float time = atof( Get_Next_Parameter() ); Commands->Set_Screen_Fade_Opacity(opacity,time); } /* ** */ bool Title_Match( char * * command, char * title ) { if ( ::strnicmp( *command, title, strlen( title ) ) == 0 ) { *command += strlen( title ); while ( **command && **command != ',' ) { (*command)++; } if ( **command == ',' ) { (*command)++; } return true; } return false; } void Parse_Command( char *command ) { // Commands->Debug_Message( "Parse %s\n", (int)command ); if ( Title_Match( &command, "Create_Object" ) ) Command_Create_Object( command ); else if ( Title_Match( &command, "Create_Real_Object" ) ) Command_Create_Real_Object( command ); else if ( Title_Match( &command, "Create_Explosion" ) ) Command_Create_Explosion( command ); else if ( Title_Match( &command, "Destroy_Object" ) ) Command_Destroy_Object( command ); else if ( Title_Match( &command, "Play_Animation" ) ) Command_Play_Animation( command ); else if ( Title_Match( &command, "Play_Audio" ) ) Command_Play_Audio( command ); else if ( Title_Match( &command, "Control_Camera" ) ) Command_Control_Camera( command ); else if ( Title_Match( &command, "Send_Custom" ) ) Command_Send_Custom( command ); else if ( Title_Match( &command, "Attach_To_Bone" ) ) Command_Attach_To_Bone( command ); else if ( Title_Match( &command, "Attach_Script" ) ) Command_Attach_Script( command ); else if ( Title_Match( &command, "Set_Primary" ) ) Command_Set_Primary( command ); else if ( Title_Match( &command, "Move_Slot" ) ) Command_Move_Slot( command ); else if ( Title_Match( &command, "Sniper_Control" ) ) Command_Sniper_Control( command ); else if ( Title_Match( &command, "Shake_Camera" ) ) Command_Shake_Camera( command ); else if ( Title_Match( &command, "Enable_Shadow" ) ) Command_Enable_Shadow( command ); else if ( Title_Match( &command, "Enable_Letterbox" ) ) Command_Enable_Letterbox( command ); else if ( Title_Match( &command, "Set_Screen_Fade_Color" ) ) Command_Set_Screen_Fade_Color( command ); else if ( Title_Match( &command, "Set_Screen_Fade_Opacity" ) ) Command_Set_Screen_Fade_Opacity( command ); else { // Commands->Debug_Message( "Failed to parse %s\n", (int)command ); } } void Parse_Commands( GameObject* obj ) { unsigned int sync_diff = Commands->Get_Sync_Time() - LastSyncTime; LastSyncTime += sync_diff; float bump_time = ((float)sync_diff) / 1000.0f; Time += bump_time; MyID = Commands->Get_ID( obj ); // Commands->Debug_Message( "Cinematic Time %1.3f Frame %1.3f Bump Time %1.3f\n", Time, Time * 30.0f, bump_time ); // If Primary Destroyed, if ( PrimaryKilled ) { // skip all timestamps < LAST_VALID_TIMESTAMP while ( Controls != NULL && Controls->Time <= LAST_VALID_TIMESTAMP ) { Remove_Head_Control_Line(); } // Run all remaining commands while ( Controls != NULL ) { Parse_Command( Controls->Command ); Remove_Head_Control_Line(); } } while ( Controls != NULL && Controls->Time <= Time ) { FrameSync = (Time - Controls->Time) * 30.0f; Parse_Command( Controls->Command ); Remove_Head_Control_Line(); } if ( Controls != NULL ) { // if the next command is > than the LAST_VALID_TIMESTAMP, we are done if ( Controls->Time >= LAST_VALID_TIMESTAMP ) { Commands->Destroy_Object( obj ); } else { float time_diff = Controls->Time - Time; Commands->Start_Timer( obj, this, time_diff, 0 ); } } else { Commands->Destroy_Object( obj ); } // Make sure we don't sleep if ( IsCameraCinematic ) { Commands->Enable_Cinematic_Freeze( obj, false ); } } /* ** */ void Created(GameObject* obj) { Commands->Enable_Hibernation( obj, false ); Controls = NULL; for ( int i = 0; i < NUM_SLOTS; i++ ) { ObjectSlots[ i ] = 0; } LastSyncTime = Commands->Get_Sync_Time(); Time = 0; PrimaryKilled = false; IsCameraCinematic = false; Load_Control_File( Get_Parameter( "ControlFilename" ) ); Parse_Commands( obj ); } void Timer_Expired (GameObject* obj, int Timer_ID) { // Commands->Debug_Message("In Timer_Expired Get_Sync_Time is %d.\n", Commands->Get_Sync_Time()); Parse_Commands(obj); } void Custom( GameObject * obj, int type, int param, GameObject * sender ) { if ( type == M00_CUSTOM_CINEMATIC_PRIMARY_KILLED ) { if ( !PrimaryKilled ) { // Prevent loops Commands->Debug_Message("Cinematic:Primary Killed\n"); PrimaryKilled = true; Parse_Commands( obj ); } } if ( type >= M00_CUSTOM_CINEMATIC_SET_SLOT ) { int slot = type - M00_CUSTOM_CINEMATIC_SET_SLOT; if ( slot < NUM_SLOTS ) { if ( ObjectSlots[ slot ] != 0 ) { // Commands->Debug_Message( "Slot number %d used by %d\n", slot, ObjectSlots[ slot ] ); } else { ObjectSlots[ slot ] = param; // Commands->Debug_Message( "Slot number %d set to %d\n", slot, ObjectSlots[ slot ] ); } } } } }; #if 0 ;_________________________________________ ; ; Available Cinematic Script Commands ; ; time/frame Create_Object, id (slot), preset_name, x, y, z, facing, animation ; id can be -1 to mean do not store this object, and do not destroy ; 0 Create_Object, 0, .44 Magnum, 0, 0, 0, 180, "Human.jump" ; ; time/frame Destroy_Object, id (slot) ; 0 Destroy_Object, 0 ; ; time/frame Play_Animation, id (slot), animation_name, looping, sub_obj_name ; 0 Play_Animation, 0, "Human.Jump", false ; ; time/frame Control_Camera, id ( slot ) ; use id -1 for disabling control; ; note this will also disable star control and disbale the hud ; 0 Control_Camera, 0 ; TIME Create_Object SLOT MODEL_NAME TIME Create_Real_Object SLOT PRESET_NAME HOST_SLOT HOST_BONE_NAME TIME Destroy_Object SLOT TIME Play_Animation SLOT ANIMATION_NAME LOOPING SUB_OBJ_NAME IS_BLENDED TIME Play_Audio PRESET_NAME HOST_SLOT HOST_BONE_NAME TIME Control_Camera SLOT TIME Send_Custon [TO_ID/#TO_SLOT] TYPE [PARAM/#SLOT_PARAM] TIME Attach_To_Bone SLOT HOST_SLOT HOST_BONE_NAME TIME Attach_Script SLOT SCRIPT_NAME "SCRIPT_PARAMETERS" TIME Move_Slot New_Slot, Old_Slot TIME Sniper_Control ENABLED, ZOOM TIME Shake_Camera SLOT, INTENSITY, DURATION TIME Enable_Shadow SLOT, [1/0] TIME Enable_Letterbox [1/0], TIME_TO_ANIMATE_IN TIME Set_Screen_Fade_Color RED,GREEN,BLUE,TIME_TO_FADE (all colors floating point 0.0-1.0) TIME Set_Screen_Fade_Opacity OPACITY,TIME_TO_FADE To fill a slot, Send_Custom to the controller with type = M00_CUSTOM_CINEMATIC_SET_SLOT + SLOT_NUMBER parameter = OBJECT_ID ;_________________________________________ #endif