#using scripts\shared\animation_debug_shared; #using scripts\shared\clientfield_shared; #using scripts\shared\flag_shared; #using scripts\shared\flagsys_shared; #using scripts\shared\postfx_shared; #using scripts\shared\shaderanim_shared; #using scripts\shared\system_shared; #namespace animation; function autoexec __init__sytem__() { system::register("animation",&__init__,undefined,undefined); } function __init__() { clientfield::register( "scriptmover", "cracks_on", 1, GetMinBitCountForNum( 4 ), "int", &cf_cracks_on, !true, !true ); clientfield::register( "scriptmover", "cracks_off", 1, GetMinBitCountForNum( 4 ), "int", &cf_cracks_off, !true, !true ); setup_notetracks(); } /@ "Name: first_frame( , , [str_tag], [animname_override] )" "Summary: Puts the animating models or AI or vehicles into the first frame of the animated scene. The animation is played relative to the entity that calls the scene" "Module: Animation" "CallOn: The root entity that is the point of relativity for the scene, be it node, ai, vehicle, etc." "MandatoryArg: Array of entities that will animate." "MandatoryArg: The animation scene name." "OptionalArg: [str_tag] The str_tag to animate relative to (must exist in the entity this function is called on)." "OptionalArg: [animname_override] Animname to use instead of ent.animname" "Example: node first_frame( guys, "rappel_sequence" );" "SPMP: singleplayer" @/ function first_frame( animation, v_origin_or_ent, v_angles_or_tag ) { self thread play( animation, v_origin_or_ent, v_angles_or_tag, 0 ); } function play( animation, v_origin_or_ent, v_angles_or_tag, n_rate = 1, n_blend_in = .2, n_blend_out = .2, n_lerp, b_link = false ) { self endon( "entityshutdown" ); self thread _play( animation, v_origin_or_ent, v_angles_or_tag, n_rate, n_blend_in, n_blend_out, n_lerp, b_link ); self waittill( "scriptedanim" ); } function _play( animation, v_origin_or_ent, v_angles_or_tag, n_rate = 1, n_blend_in = .2, n_blend_out = .2, n_lerp, b_link = false ) { self endon( "entityshutdown" ); self notify( "new_scripted_anim" ); self endon( "new_scripted_anim" ); flagsys::set_val( "firstframe", n_rate == 0 ); flagsys::set( "scripted_anim_this_frame" ); flagsys::set( "scriptedanim" ); if(!isdefined(v_origin_or_ent))v_origin_or_ent=self; if ( IsVec( v_origin_or_ent ) && IsVec( v_angles_or_tag ) ) { self AnimScripted( "_anim_notify_", v_origin_or_ent, v_angles_or_tag, animation, n_blend_in, n_rate ); } else { if ( IsString( v_angles_or_tag ) ) { Assert( isdefined( v_origin_or_ent.model ), "Cannot align animation '" + animation + "' to tag '" + v_angles_or_tag + "' because the animation is not aligned to a model." ); v_pos = v_origin_or_ent GetTagOrigin( v_angles_or_tag ); v_ang = v_origin_or_ent GetTagAngles( v_angles_or_tag ); self.origin = v_pos; self.angles = v_ang; b_link = true; // self LinkTo( v_origin_or_ent, v_angles_or_tag, ( 0, 0, 0 ), ( 0, 0, 0 ) ); // TODO: LinkTo with animation is broken client side and will mis-align the entities self AnimScripted( "_anim_notify_", self.origin, self.angles, animation, n_blend_in, n_rate ); } else { v_angles = ( isdefined( v_origin_or_ent.angles ) ? v_origin_or_ent.angles : ( 0, 0, 0 ) ); self AnimScripted( "_anim_notify_", v_origin_or_ent.origin, v_angles, animation, n_blend_in, n_rate ); } } if ( !b_link ) { self Unlink(); } /# self thread anim_info_render_thread( animation, v_origin_or_ent, v_angles_or_tag, n_rate, n_blend_in, n_blend_out, n_lerp ); #/ // if ( !IsAnimLooping( animation ) && ( n_blend_out > 0 ) && ( n_rate > 0 ) ) // { // self thread _blend_out( animation, n_blend_out, n_rate ); // } self thread handle_notetracks(); self waittill_end(); if ( b_link ) { self Unlink(); } flagsys::clear( "scriptedanim" ); flagsys::clear( "firstframe" ); waittillframeend; flagsys::clear( "scripted_anim_this_frame" ); } function private waittill_end() { level endon("demo_jump"); // end when theater mode rewinds self waittillmatch( "_anim_notify_", "end" ); } //function _blend_out( animation, n_blend, n_rate ) //{ // self endon( "death" ); // self endon( "scriptedanim" ); // // n_len = GetAnimLength( animation ); // n_wait = ( n_len - n_blend ) * ( 1 / n_rate ); // // if ( n_wait > n_len ) // { // wait n_wait; // // self StopAnimScripted( n_blend ); // } //} function _get_align_ent( e_align ) { e = self; if ( isdefined( e_align ) ) { e = e_align; } if(!isdefined(e.angles))e.angles=( 0, 0, 0 ); return e; } function _get_align_pos( v_origin_or_ent, v_angles_or_tag ) { if(!isdefined(v_origin_or_ent))v_origin_or_ent=self.origin; if(!isdefined(v_angles_or_tag))v_angles_or_tag=(isdefined(self.angles)?self.angles:( 0, 0, 0 )); s = SpawnStruct(); if ( IsVec( v_origin_or_ent ) ) { Assert( IsVec( v_angles_or_tag ), "Angles must be a vector if origin is." ); s.origin = v_origin_or_ent; s.angles = v_angles_or_tag; } else { e_align = _get_align_ent( v_origin_or_ent ); if ( IsString( v_angles_or_tag ) ) { s.origin = e_align GetTagOrigin( v_angles_or_tag ); s.angles = e_align GetTagAngles( v_angles_or_tag ); } else { s.origin = e_align.origin; s.angles = e_align.angles; } } if(!isdefined(s.angles))s.angles=( 0, 0, 0 ); return s; } function play_siege( str_anim, str_shot = "default", n_rate = 1, b_loop = false ) { level endon("demo_jump"); // end when theater mode rewinds self endon( "entityshutdown" ); if(!isdefined(str_shot))str_shot="default"; if ( n_rate == 0 ) { self SiegeCmd( "set_anim", str_anim, "set_shot", str_shot, "pause", "goto_start" ); } else { self SiegeCmd( "set_anim", str_anim, "set_shot", str_shot, "unpause", "set_playback_speed", n_rate, "send_end_events", true, ( b_loop ? "loop" : "unloop" ) ); } self waittill( "end" ); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Notetrack Handling ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function add_notetrack_func( funcname, func ) { if(!isdefined(level._animnotifyfuncs))level._animnotifyfuncs=[]; Assert( !isdefined( level._animnotifyfuncs[ funcname ] ), "Notetrack function already exists." ); level._animnotifyfuncs[ funcname ] = func; } function add_global_notetrack_handler( str_note, func, ... ) { if(!isdefined(level._animnotetrackhandlers))level._animnotetrackhandlers=[]; if(!isdefined(level._animnotetrackhandlers[ str_note ]))level._animnotetrackhandlers[ str_note ]=[]; if ( !isdefined( level._animnotetrackhandlers[ str_note ] ) ) level._animnotetrackhandlers[ str_note ] = []; else if ( !IsArray( level._animnotetrackhandlers[ str_note ] ) ) level._animnotetrackhandlers[ str_note ] = array( level._animnotetrackhandlers[ str_note ] ); level._animnotetrackhandlers[ str_note ][level._animnotetrackhandlers[ str_note ].size]=array( func, vararg );; } function call_notetrack_handler( str_note ) { if ( isdefined( level._animnotetrackhandlers ) && isdefined( level._animnotetrackhandlers[ str_note ] ) ) { foreach ( handler in level._animnotetrackhandlers[ str_note ] ) { func = handler[0]; args = handler[1]; switch ( args.size ) { case 6: self [[ func ]]( args[0], args[1], args[2], args[3], args[4], args[5] ); break; case 5: self [[ func ]]( args[0], args[1], args[2], args[3], args[4] ); break; case 4: self [[ func ]]( args[0], args[1], args[2], args[3] ); break; case 3: self [[ func ]]( args[0], args[1], args[2] ); break; case 2: self [[ func ]]( args[0], args[1] ); break; case 1: self [[ func ]]( args[0] ); break; case 0: self [[ func ]](); break; default: AssertMsg( "Too many args passed to notetrack handler." ); } } } } function setup_notetracks() { add_notetrack_func( "flag::set", &flag::set ); add_notetrack_func( "flag::clear", &flag::clear ); add_notetrack_func( "postfx::PlayPostFxBundle", &postfx::PlayPostFxBundle ); add_notetrack_func( "postfx::StopPostFxBundle", &postfx::StopPostFxBundle ); add_global_notetrack_handler( "red_cracks_on", &cracks_on, "red" ); add_global_notetrack_handler( "green_cracks_on", &cracks_on, "green" ); add_global_notetrack_handler( "blue_cracks_on", &cracks_on, "blue" ); add_global_notetrack_handler( "all_cracks_on", &cracks_on, "all" ); add_global_notetrack_handler( "red_cracks_off", &cracks_off, "red" ); add_global_notetrack_handler( "green_cracks_off", &cracks_off, "green" ); add_global_notetrack_handler( "blue_cracks_off", &cracks_off, "blue" ); add_global_notetrack_handler( "all_cracks_off", &cracks_off, "all" ); } function handle_notetracks() { level endon("demo_jump"); // end when theater mode rewinds self endon( "entityshutdown" ); while ( true ) { self waittill( "_anim_notify_", str_note ); if ( str_note != "end" && str_note != "loop_end" ) { self thread call_notetrack_handler( str_note ); } else { return; } } } function cracks_on( str_type ) { switch ( str_type ) { case "red": cf_cracks_on( self.localClientNum, 0, 1 ); break; case "green": cf_cracks_on( self.localClientNum, 0, 3 ); break; case "blue": cf_cracks_on( self.localClientNum, 0, 2 ); break; case "all": cf_cracks_on( self.localClientNum, 0, 4 ); break; } } function cracks_off( str_type ) { switch ( str_type ) { case "red": cf_cracks_off( self.localClientNum, 0, 1 ); break; case "green": cf_cracks_off( self.localClientNum, 0, 3 ); break; case "blue": cf_cracks_off( self.localClientNum, 0, 2 ); break; case "all": cf_cracks_off( self.localClientNum, 0, 4 ); break; } } function cf_cracks_on( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump ) { const delay = 0; const duration = 3; const start = 0; const end = 1; switch ( newVal ) { case 1: shaderanim::animate_crack( localClientNum, "scriptVector1", delay, duration, start, end ); break; case 3: shaderanim::animate_crack( localClientNum, "scriptVector2", delay, duration, start, end ); break; case 2: shaderanim::animate_crack( localClientNum, "scriptVector3", delay, duration, start, end ); break; case 4: shaderanim::animate_crack( localClientNum, "scriptVector1", delay, duration, start, end ); shaderanim::animate_crack( localClientNum, "scriptVector2", delay, duration, start, end ); shaderanim::animate_crack( localClientNum, "scriptVector3", delay, duration, start, end ); } } function cf_cracks_off( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump ) { const delay = 0; const duration = 0; const start = 1; const end = 0; switch ( newVal ) { case 1: shaderanim::animate_crack( localClientNum, "scriptVector1", delay, duration, start, end ); break; case 3: shaderanim::animate_crack( localClientNum, "scriptVector2", delay, duration, start, end ); break; case 2: shaderanim::animate_crack( localClientNum, "scriptVector3", delay, duration, start, end ); break; case 4: shaderanim::animate_crack( localClientNum, "scriptVector1", delay, duration, start, end ); shaderanim::animate_crack( localClientNum, "scriptVector2", delay, duration, start, end ); shaderanim::animate_crack( localClientNum, "scriptVector3", delay, duration, start, end ); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // !Notetrack Handling /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////