///////////////////////////////////////////////////////////////////////////////////////////////////////////// // http://tawiki/display/Design/Scene+System ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////// #using scripts\codescripts\struct; #using scripts\shared\ai_shared; #using scripts\shared\animation_shared; #using scripts\shared\array_shared; #using scripts\shared\callbacks_shared; #using scripts\shared\clientfield_shared; #using scripts\shared\flag_shared; #using scripts\shared\flagsys_shared; #using scripts\shared\laststand_shared; #using scripts\shared\player_shared; #using scripts\shared\scene_debug_shared; #using scripts\shared\scriptbundle_shared; #using scripts\shared\spawner_shared; #using scripts\shared\system_shared; #using scripts\shared\trigger_shared; #using scripts\shared\util_shared; #using scripts\shared\lui_shared; #precache( "lui_menu", "CPSkipSceneMenu" ); #precache( "lui_menu_data", "showSkipButton" ); #precache( "lui_menu_data", "hostIsSkipping" ); #precache( "lui_menu_data", "sceneSkipEndTime" ); #namespace scene; #using_animtree( "all_player" ); function private prepare_player_model_anim( ent ) { if ( !( ent.animtree === "all_player" ) ) { ent UseAnimTree( #animtree ); ent.animtree = "all_player"; } } #using_animtree( "generic" ); function private prepare_generic_model_anim( ent ) { if ( !( ent.animtree === "generic" ) ) { ent UseAnimTree( #animtree ); ent.animtree = "generic"; } } // Player weapon animation indexes defined in code ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ___ ___ ___ _ _ ___ ___ ___ _ ___ ___ _____ // / __| / __| | __| | \| | | __| / _ \ | _ ) _ | | | __| / __| |_ _| // \__ \ | (__ | _| | .` | | _| | (_) | | _ \ | || | | _| | (__ | | // |___/ \___| |___| |_|\_| |___| \___/ |___/ \__/ |___| \___| |_| // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class cSceneObject : cScriptBundleObjectBase { var _b_spawnonce_used; var _is_valid; var _str_name; var _str_state; var _player; var _str_death_anim; var _str_death_anim_loop; var _b_set_goal; constructor() { _is_valid = true; _b_spawnonce_used = false; _b_set_goal = true; } destructor() { } function first_init( s_objdef, o_scene, e_ent ) { cScriptBundleObjectBase::init( s_objdef, o_scene, e_ent ); _assign_unique_name(); return self; } function initialize( b_force_first_frame = false ) { if ( has_init_state() || b_force_first_frame ) { flagsys::clear( "ready" ); flagsys::clear( "done" ); flagsys::clear( "main_done" ); _str_state = "init"; self notify( "new_state" ); self endon( "new_state" ); self notify("init"); log( "init" ); waittillframeend;; //Exclude the player since now need to spawn or init him. if ( ( !( isdefined( _s.sharedIGC ) && _s.sharedIGC ) && !( isdefined( _s.player ) && _s.player ) ) && ( isdefined( _s.spawnoninit ) && _s.spawnoninit ) || b_force_first_frame ) { _spawn( undefined, ( isdefined( _s.firstframe ) && _s.firstframe ) || isdefined( _s.initanim ) || isdefined( _s.initanimloop ) ); } if ( ( isdefined( _s.firstframe ) && _s.firstframe ) || b_force_first_frame ) { if ( !error( !isdefined( _s.mainanim ), "No animation defined for first frame." ) ) { _str_death_anim = _s.mainanimdeath; _str_death_anim_loop = _s.mainanimdeathloop; _play_anim( _s.mainanim, 0, 0, 0 ); } } else if ( isdefined( _s.initanim ) ) { _str_death_anim = _s.initanimdeath; _str_death_anim_loop = _s.initanimdeathloop; _play_anim( _s.initanim, _s.initdelaymin, _s.initdelaymax, 1 ); if ( is_alive() ) { if ( isdefined( _s.initanimloop ) ) { _str_death_anim = _s.initanimloopdeath; _str_death_anim_loop = _s.initanimloopdeathloop; _play_anim( _s.initanimloop, 0, 0, 1 ); } } } else if ( isdefined( _s.initanimloop ) ) { _str_death_anim = _s.initanimloopdeath; _str_death_anim_loop = _s.initanimloopdeathloop; _play_anim( _s.initanimloop, _s.initdelaymin, _s.initdelaymax, 1 ); } } else { flagsys::set( "ready" ); } if ( !_is_valid ) { flagsys::set( "done" ); } } function play() { /# if( GetDvarInt("debug_scene") > 0) { if(isdefined(_s.name)) { PrintTopRightln("csceneobject::play : " + _s.name); } else { PrintTopRightln("csceneobject::play : " + _s.model); } } #/ flagsys::clear( "ready" ); flagsys::clear( "done" ); flagsys::clear( "main_done" ); _str_state = "play"; self notify( "new_state" ); self endon( "new_state" ); self notify("play"); log( "play" ); waittillframeend;; if( ( isdefined( _s.hide ) && _s.hide ) && _is_valid ) { _spawn( undefined, false, false ); _e Hide(); } else if ( isdefined( _s.mainanim ) && _is_valid ) { _str_death_anim = _s.mainanimdeath; _str_death_anim_loop = _s.mainanimdeathloop; //if it is a starting of a scene and no value is provided, do a default 0.2 animation blend. if ( !( isdefined( _s.IsCutScene ) && _s.IsCutScene ) ) { if( !isdefined( _s.MainBlend ) || _s.MainBlend == 0 ) { _s.mainblend = 0.2; } else if(_s.MainBlend == 0.001) //MALI - A hack to enable 0 blending between cuts, this should be removed once we ship TU5 and _s.MainBlend = 0 should mean 0 not 0.2. { _s.MainBlend = 0; } } _play_anim( _s.mainanim, _s.maindelaymin, _s.maindelaymax, 1, _s.mainblend, _o_bundle.n_start_time ); flagsys::set( "main_done" ); if ( isdefined( _e ) && ( isdefined( _s.DynamicPaths ) && _s.DynamicPaths ) ) { if ( Distance2DSquared( _e.origin, _e.scene_orig_origin ) > 4 ) { _e DisconnectPaths( 2, false ); } } if ( is_alive() ) { if ( !isdefined( _s.EndBlend ) || _s.EndBlend == 0 ) { _s.EndBlend = 0.2; } if ( isdefined( _s.endanim ) ) { _str_death_anim = _s.endanimdeath; _str_death_anim_loop = _s.endanimdeathloop; _play_anim( _s.endanim, 0, 0, 1, _s.EndBlend ); if ( is_alive() ) { if ( isdefined( _s.endanimloop ) ) { _str_death_anim = _s.endanimloopdeath; _str_death_anim_loop = _s.endanimloopdeathloop; _play_anim( _s.endanimloop, 0, 0, 1 ); } } } else if ( isdefined( _s.endanimloop ) ) { _str_death_anim = _s.endanimloopdeath; _str_death_anim_loop = _s.endanimloopdeathloop; _play_anim( _s.endanimloop, 0, 0, 1 ); } } } thread finish(); } function stop( b_clear = false, b_dont_clear_anim = false, b_finished = false ) { /# if ( GetDvarInt( "debug_scene" ) > 0 ) { PrintTopRightln( "csceneobject::stop : " + ( isdefined( _s.name ) ? _s.name : _s.model ) ); } #/ if ( IsAlive( _e ) ) { if ( is_shared_player() ) { foreach ( player in level.players ) { player StopAnimScripted( .2 ); } } else if ( !( isdefined( _s.DieWhenFinished ) && _s.DieWhenFinished ) || !b_finished ) { if ( !b_dont_clear_anim || IsPlayer( _e ) ) { _e StopAnimScripted( .2 ); } } } finish( b_clear, !b_finished ); } function get_align_ent() { e_align = undefined; if ( isdefined( _s.aligntarget ) && !( _s.aligntarget === _o_bundle._s.aligntarget ) ) { a_scene_ents = [[_o_bundle]]->get_ents(); if ( isdefined( a_scene_ents[ _s.aligntarget ] ) ) { e_align = a_scene_ents[ _s.aligntarget ]; } else { e_align = scene::get_existing_ent( _s.aligntarget, false, true ); } if ( !isdefined( e_align ) ) { str_msg = "Align target '" + (isdefined(_s.aligntarget)?""+_s.aligntarget:"") + "' doesn't exist for scene object."; if ( !warning( _o_bundle._testing, str_msg ) ) { error( GetDvarInt( "scene_align_errors", 1 ), str_msg ); } } } if ( !isdefined( e_align ) ) { e_align = [[scene()]]->get_align_ent(); } return e_align; } function get_align_tag() { if ( isdefined( _s.AlignTargetTag ) ) { return _s.AlignTargetTag; } else { if ( isdefined( _o_bundle._e_root.e_scene_link ) ) { return "tag_origin"; } else { return _o_bundle._s.AlignTargetTag; } } } /* Scene Helpers */ function scene() { return _o_bundle; } /* internal functions */ function _on_damage_run_scene_thread() { self endon( "play" ); self endon( "done" ); str_damage_types = ( !isdefined( _s.runsceneondmg0 ) || _s.runsceneondmg0 == "none" ? "" : _s.runsceneondmg0 ) + ( !isdefined( _s.runsceneondmg1 ) || _s.runsceneondmg1 == "none" ? "" : _s.runsceneondmg1 ) + ( !isdefined( _s.runsceneondmg2 ) || _s.runsceneondmg2 == "none" ? "" : _s.runsceneondmg2 ) + ( !isdefined( _s.runsceneondmg3 ) || _s.runsceneondmg3 == "none" ? "" : _s.runsceneondmg3 ) + ( !isdefined( _s.runsceneondmg4 ) || _s.runsceneondmg4 == "none" ? "" : _s.runsceneondmg4 ); if ( str_damage_types != "" ) { b_run_scene = false; while ( !b_run_scene ) { _e waittill( "damage", n_amount, e_attacker, v_org, v_dir, str_mod ); switch ( str_mod ) { case "MOD_PISTOL_BULLET": case "MOD_RIFLE_BULLET": if ( IsSubStr( str_damage_types, "bullet" ) ) { b_run_scene = true; } break; case "MOD_GRENADE": case "MOD_GRENADE_SPLASH": case "MOD_EXPLOSIVE": if ( IsSubStr( str_damage_types, "explosive" ) ) { b_run_scene = true; } break; case "MOD_PROJECTILE": case "MOD_PROJECTILE_SPLASH": if ( IsSubStr( str_damage_types, "projectile" ) ) { b_run_scene = true; } break; case "MOD_MELEE": if ( IsSubStr( str_damage_types, "melee" ) ) { b_run_scene = true; } break; default: if ( IsSubStr( str_damage_types, "all" ) ) { b_run_scene = true; } } } thread [[scene()]]->play(); } } function _assign_unique_name() { if ( is_player() ) { _str_name = "player " + _s.player; } else { if ( [[scene()]]->allows_multiple() ) { if ( isdefined( _s.name ) ) { _str_name = _s.name + "_gen" + level.scene_object_id; } else { _str_name = [[scene()]]->get_name() + "_noname" + level.scene_object_id; } level.scene_object_id++; } else { if ( isdefined( _s.name ) ) { _str_name = _s.name; } else { _str_name = [[scene()]]->get_name() + "_noname" + [[scene()]]->get_object_id(); } } } } function get_name() { return _str_name; } function get_orig_name() { return _s.name; } function _spawn( e_spawner, b_hide = true, b_set_ready_when_spawned = true ) { if ( isdefined( e_spawner ) ) { _e = e_spawner; } if ( isdefined( _e ) && ( isdefined( _e.isDying ) && _e.isDying ) ) { _e Delete(); // previous ent is marked for cleanup, do it now so it doesn't delete a frame later when we don't want it to } if ( is_player() ) { if ( IsPlayer( _e ) ) { _player = _e; } else { n_player = GetDvarInt( "scene_debug_player", 0 ); if ( n_player > 0 ) { n_player--; if ( n_player == _s.player ) { _player = level.activeplayers[ 0 ]; } } else { _player = level.activeplayers[ _s.player ]; } } } b_skip = ( _s.type === "actor" ) && IsSubStr( _o_bundle._str_mode, "noai" ); b_skip = b_skip || ( ( _s.type === "player" ) && IsSubStr( _o_bundle._str_mode, "noplayers" ) ); if(!b_skip && _should_skip_entity()) { b_skip = true; } if ( !b_skip ) { if ( !isdefined( _e ) && is_player() && ( isdefined( _s.newplayermethod ) && _s.newplayermethod ) ) { _e = _player; } else if ( !isdefined( _e ) || IsSpawner( _e ) ) { b_allows_multiple = [[scene()]]->allows_multiple(); if ( /*error( !b_allows_multiple && !isdefined( _s.name ), "Scene that don't allow multiple instances must specify a name for all objects." ) || */error( b_allows_multiple && ( isdefined( _s.nospawn ) && _s.nospawn ), "Scene that allow multiple instances must be allowed to spawn (uncheck 'Do Not Spawn')." ) ) { return; } if ( !IsSpawner( _e ) ) { e = scene::get_existing_ent( _str_name, b_allows_multiple ); if ( !isdefined( e ) && isdefined( _s.name ) ) { e = scene::get_existing_ent( _s.name, b_allows_multiple ); } if ( IsPlayer( e ) ) { if ( !( isdefined( _s.newplayermethod ) && _s.newplayermethod ) ) { e = undefined; } } if ( ( !isdefined( e ) || IsSpawner( e ) ) && ( ( !( isdefined( _s.nospawn ) && _s.nospawn ) && !_b_spawnonce_used ) || _o_bundle._testing ) ) { e_spawned = spawn_ent( e ); } } else { e_spawned = spawn_ent( _e ); } if ( isdefined( e_spawned ) ) { if ( b_hide && !_o_bundle._s scene::is_igc() ) { e_spawned Hide(); // Hide teleporting glitches and for any delay set on this object } e_spawned DontInterpolate(); e_spawned.scene_spawned = _o_bundle._s.name; if ( !isdefined( e_spawned.targetname ) ) { e_spawned.targetname = _s.name; } if ( is_player() ) { e_spawned Hide(); } } _e = ( isdefined( e_spawned ) ? e_spawned : e ); if ( ( isdefined( _s.spawnonce ) && _s.spawnonce ) && _b_spawnonce_used ) { return; } } error( !is_player() && !( isdefined( _s.nospawn ) && _s.nospawn ) && ( !isdefined( _e ) || IsSpawner( _e ) ), "Object failed to spawn or doesn't exist." ); } if ( isdefined( _e ) && !IsSpawner( _e ) ) { [[self]]->_prepare(); if ( b_set_ready_when_spawned ) { flagsys::set( "ready" ); } if ( ( isdefined( _s.spawnonce ) && _s.spawnonce ) ) { _b_spawnonce_used = true; } } else { flagsys::set( "ready" ); flagsys::set( "done" ); finish(); } } function _prepare() { if ( ( isdefined( _s.DynamicPaths ) && _s.DynamicPaths ) && ( _str_state == "play" ) ) { _e.scene_orig_origin = _e.origin; _e ConnectPaths(); } if ( ( _e.current_scene === _o_bundle._str_name ) ) { //Since we do not fire the "scene_sequence_started" on init state, we need to do so here. [[_o_bundle]]->trigger_scene_sequence_started( self, _e ); return false; // already prepared this entity for this scene } _e endon( "death" ); if ( !( isdefined( _s.IgnoreAliveCheck ) && _s.IgnoreAliveCheck ) && error( IsAI( _e ) && !IsAlive( _e ), "Trying to play a scene on a dead AI." ) ) { return; } // cleanup any current/previous scenes if ( isdefined( _e._o_scene ) ) { foreach ( obj in _e._o_scene._a_objects ) { if ( obj._e === _e ) { [[ obj ]]->finish(); break; } } } if ( !IsAI( _e ) && !IsPlayer( _e ) ) { if ( !is_player() || !( isdefined( _s.newplayermethod ) && _s.newplayermethod ) ) { if ( is_player_model() ) { scene::prepare_player_model_anim( _e ); } else { scene::prepare_generic_model_anim( _e ); } } } if ( !is_player() ) { if ( !isdefined( _e._scene_old_takedamage ) ) { _e._scene_old_takedamage = _e.takedamage; } if ( IsSentient( _e ) ) { // For sentients, don't override if damage/death is turned off _e.takedamage = ( isdefined( _e.takedamage ) && _e.takedamage ) && ( isdefined( _s.takedamage ) && _s.takedamage ); if ( !( isdefined( _e.magic_bullet_shield ) && _e.magic_bullet_shield ) ) { _e.allowdeath = ( isdefined( _s.allowdeath ) && _s.allowdeath ); } if ( ( isdefined( _s.OverrideAICharacter ) && _s.OverrideAICharacter ) ) { _e DetachAll(); _e SetModel( _s.model ); } } else { _e.health = ( _e.health > 0 ? _e.health : 1 ); if ( _s.type === "actor" ) // Drone { _e MakeFakeAI(); if ( !( isdefined( _s.RemoveWeapon ) && _s.RemoveWeapon ) ) { _e animation::attach_weapon( GetWeapon( "ar_standard" ) ); // TODO: see if we can get the weapon from the aitype if using one for the character model } } _e.takedamage = ( isdefined( _s.takedamage ) && _s.takedamage ); _e.allowdeath = ( isdefined( _s.allowdeath ) && _s.allowdeath ); } set_objective(); if ( ( isdefined( _s.DynamicPaths ) && _s.DynamicPaths ) ) { _e DisconnectPaths( 2, false ); } } else if ( !is_shared_player() ) { player = ( IsPlayer( _player ) ? _player : _e ); _prepare_player( player ); } if ( ( isdefined( _s.RemoveWeapon ) && _s.RemoveWeapon ) ) { if ( !( isdefined( _e.gun_removed ) && _e.gun_removed ) ) { if ( IsPlayer( _e ) ) { _e player::take_weapons(); } else { _e animation::detach_weapon(); } } else { _e._scene_old_gun_removed = true; } } // TODO: refactor all of this stuff so it can be set/cleared on all players in a shared animation _e.animname = _str_name; _e.anim_debug_name = _s.name; _e flagsys::set( "scene" ); _e flagsys::set( _o_bundle._str_name ); _e.current_scene = _o_bundle._str_name; _e.finished_scene = undefined; _e._o_scene = scene(); //only shared IGC can skip the scene if it is just started [[_o_bundle]]->trigger_scene_sequence_started( self, _e ); if ( ( isdefined( _e.takedamage ) && _e.takedamage ) ) { thread _on_damage_run_scene_thread(); thread _on_death(); } if ( IsActor( _e ) ) { thread _track_goal(); if ( ( isdefined( _s.LookAtPlayer ) && _s.LookAtPlayer ) ) { _e LookAtEntity( level.activeplayers[0] ); } } if ( _o_bundle._s scene::is_igc() || [[ _o_bundle ]]->has_player() ) { if ( !IsPlayer( _e ) ) // players handled in _prepare_player { _e SetHighDetail( true ); } } return true; } function _prepare_player( player ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::_prepare_player"); } #/ if ( ( isdefined( player.play_scene_transition_effect ) && player.play_scene_transition_effect ) ) { player.play_scene_transition_effect = undefined; play_regroup_fx_for_scene( player ); } if ( ( player.current_player_scene === _o_bundle._str_name ) ) { //Since we do not fire the "scene_sequence_started" on init state, we need to do so here. [[_o_bundle]]->trigger_scene_sequence_started( self, player ); return false; // already prepared this entity for this scene } player SetHighDetail( true ); // close the mobile armory if it's open if ( player flagsys::get( "mobile_armory_in_use" ) ) { player flagsys::set("cancel_mobile_armory"); player CloseMenu( "ChooseClass_InGame" ); player notify( "menuresponse", "ChooseClass_InGame", "cancel" ); } //if player was starting to interact with an armory and never finished if( player flagsys::get( "mobile_armory_begin_use" ) ) { player util::_enableWeapon(); player flagsys::clear( "mobile_armory_begin_use" ); } if( GetDvarInt("scene_hide_player") > 0 ) { player Hide(); } player.current_player_scene = _o_bundle._str_name; if ( !( isdefined( player.magic_bullet_shield ) && player.magic_bullet_shield ) ) { player.allowdeath = ( isdefined( _s.allowdeath ) && _s.allowdeath ); } player.scene_takedamage = ( isdefined( _s.takedamage ) && _s.takedamage ); if ( isdefined( player.hijacked_vehicle_entity ) ) { player.hijacked_vehicle_entity Delete(); } else if ( player IsInVehicle() ) { vh_occupied = player GetVehicleOccupied(); n_seat = vh_occupied GetOccupantSeat( player ); vh_occupied UseVehicle( player, n_seat ); // make player exit vehicle } revive_player( player ); player thread scene::scene_disable_player_stuff( !( isdefined( _s.ShowHUD ) && _s.ShowHUD ) ); if ( ( isdefined( _s.FirstWeaponRaise ) && _s.FirstWeaponRaise ) ) { //SetDvar( "playerWeaponRaisePostIGC", WEAP_FIRST_RAISE ); } player.player_anim_look_enabled = !( isdefined( _s.LockView ) && _s.LockView ); player.player_anim_clamp_right = (isdefined(_s.viewClampRight)?_s.viewClampRight:0); player.player_anim_clamp_left = (isdefined(_s.viewClampLeft)?_s.viewClampLeft:0); player.player_anim_clamp_top = (isdefined(_s.viewClampBottom)?_s.viewClampBottom:0); player.player_anim_clamp_bottom = (isdefined(_s.viewClampBottom)?_s.viewClampBottom:0); if ( ( !( isdefined( _s.RemoveWeapon ) && _s.RemoveWeapon ) || ( isdefined( _s.ShowWeaponInFirstPerson ) && _s.ShowWeaponInFirstPerson ) ) && !( isdefined( _s.DisablePrimaryWeaponSwitch ) && _s.DisablePrimaryWeaponSwitch ) ) { player player::switch_to_primary_weapon( true ); } set_player_stance( player ); } function revive_player( player ) { if ( player.sessionstate === "spectator" ) { player thread [[ level.spawnPlayer ]](); } else if ( player laststand::player_is_in_laststand() ) { player notify( "auto_revive" ); // currently CP only } } function set_player_stance( player ) { if ( _s.PlayerStance === "crouch" ) { player AllowStand( false ); player AllowCrouch( true ); player AllowProne( false ); } else if ( _s.PlayerStance === "prone" ) { player AllowStand( false ); player AllowCrouch( false ); player AllowProne( true ); } else // default to stand { player AllowStand( true ); player AllowCrouch( false ); player AllowProne( false ); } } function finish( b_clear = false, b_canceled = false ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::finish: " + ((isdefined(_s.name))? _s.name : _s.model)); } #/ if ( isdefined( _str_state ) ) { _str_state = undefined; self notify( "new_state" ); if ( !is_shared_player() && !is_alive() ) //TU1: need to only skip this if SHARED scene, not just for !is_player { _cleanup(); _e = undefined; _is_valid = false; } else { if ( !is_player() ) { if ( isdefined( _e._scene_old_takedamage ) ) { _e.takedamage = _e._scene_old_takedamage; } if ( !( isdefined( _e.magic_bullet_shield ) && _e.magic_bullet_shield ) ) { _e.allowdeath = true; } _e._scene_old_takedamage = undefined; _e._scene_old_gun_removed = undefined; } else { if ( is_shared_player() ) { foreach ( player in level.players ) { if( player flagsys::get( "shared_igc" ) ) { _finish_player( player ); } } } else { player = ( IsPlayer( _player ) ? _player : _e ); _finish_player( player ); } } if ( ( isdefined( _s.RemoveWeapon ) && _s.RemoveWeapon ) && !( isdefined( _e._scene_old_gun_removed ) && _e._scene_old_gun_removed ) ) { if ( IsPlayer( _e ) ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::finish::giveweapon : " + ((isdefined(_s.name))? _s.name : _s.model)); } #/ _e player::give_back_weapons(); } else { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::finish::giveweapon : " + ((isdefined(_s.name))? _s.name : _s.model)); } #/ _e animation::attach_weapon(); } } if ( !IsPlayer( _e ) ) // players are handled in _finish_player { if ( isdefined( _e ) ) { _e SetHighDetail( false ); } } } flagsys::set( "ready" ); flagsys::set( "done" ); if ( isdefined( _e ) ) { if ( !is_player() ) { if ( is_alive() && ( ( isdefined( _s.DeleteWhenFinished ) && _s.DeleteWhenFinished ) || b_clear ) ) { _e thread scene::synced_delete(); } else if ( is_alive() && ( isdefined( _s.DieWhenFinished ) && _s.DieWhenFinished ) && !b_canceled ) { _e.skipdeath = true; _e.allowdeath = true; _e.skipscenedeath = true; _e Kill(); } } if ( IsActor( _e ) && IsAlive( _e ) ) { if ( ( isdefined( _s.DelayMovementAtEnd ) && _s.DelayMovementAtEnd ) ) { _e PathMode( "move delayed", true, RandomFloatRange( 2, 3 ) ); } else { _e PathMode( "move allowed" ); } if ( ( isdefined( _s.LookAtPlayer ) && _s.LookAtPlayer ) ) { _e LookAtEntity(); } } } _cleanup(); } } function _finish_player( player ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::_finish_player"); } #/ /* /# PrintTopRightln("SetVisibleToAll : " + GetTime(), BLUE, -1); #/ */ player.scene_set_visible_time = level.time; player SetVisibleToAll(); player flagsys::clear( "shared_igc" ); if ( !( isdefined( player.magic_bullet_shield ) && player.magic_bullet_shield ) ) { player.allowdeath = true; } player.current_player_scene = undefined; player.scene_takedamage = undefined; player._scene_old_gun_removed = undefined; player thread scene::scene_enable_player_stuff( !( isdefined( _s.ShowHUD ) && _s.ShowHUD ) ); //SetDvar( "playerWeaponRaisePostIGC", WEAP_RAISE ); if(!([[_o_bundle]]->has_next_scene()) ) { if([[_o_bundle]]->is_player_anim_ending_early()) { if(![[_o_bundle]]->is_skipping_scene() && [[_o_bundle]]->is_scene_shared_sequence()) //if we are not skipping a scene then just notify that the scene sequence has ended { [[_o_bundle]]->init_scene_sequence_started(false); } _o_bundle thread cscene::_stop_camera_anim_on_player(player); } else if(_o_bundle._s scene::is_igc()) { _o_bundle thread cscene::_stop_camera_anim_on_player(player); } } n_camera_tween_out = get_camera_tween_out(); if ( n_camera_tween_out > 0 ) { player StartCameraTween( n_camera_tween_out ); } if ( !( isdefined( _s.DontReloadAmmo ) && _s.DontReloadAmmo ) ) { player player::fill_current_clip(); } player AllowStand( true ); player AllowCrouch( true ); player AllowProne( true ); player SetHighDetail( false ); } function set_objective() { if ( !isdefined( _e.script_objective ) ) { if ( isdefined( _o_bundle._e_root.script_objective ) ) { _e.script_objective = _o_bundle._e_root.script_objective; } else if ( isdefined( _o_bundle._s.script_objective ) ) { _e.script_objective = _o_bundle._s.script_objective; } } } function _on_death() { self endon( "cleanup" ); _e waittill( "death" ); if ( isdefined( _e ) && !( isdefined( _e.skipscenedeath ) && _e.skipscenedeath ) ) { self thread do_death_anims(); } } function do_death_anims() { ent = _e; if ( IsAI( ent ) && !isdefined( _str_death_anim ) && !isdefined( _str_death_anim_loop ) ) { ent StopAnimScripted(); if ( IsActor( ent ) ) { ent StartRagDoll(); } } if ( isdefined( _str_death_anim ) ) { ent.skipdeath = true; ent animation::play( _str_death_anim, ent, undefined, 1, .2, 0 ); } if ( isdefined( _str_death_anim_loop ) ) { ent.skipdeath = true; ent animation::play( _str_death_anim_loop, ent, undefined, 1, 0, 0 ); } } function _cleanup() { if ( isdefined( _e ) && isdefined( _e.current_scene ) ) { _e flagsys::clear( _o_bundle._str_name ); if ( _e.current_scene == _o_bundle._str_name ) { _e flagsys::clear( "scene" ); _e.finished_scene = _o_bundle._str_name; _e.current_scene = undefined; _e._o_scene = undefined; if ( is_player() ) { if ( !( isdefined( _s.newplayermethod ) && _s.newplayermethod ) ) { _e Delete(); thread reset_player(); } _e.animname = undefined; } } } self notify( "death" ); self endon( "new_state" ); waittillframeend; // allow death anims and other things to execute before killing those threads self notify( "cleanup" ); if ( IsAI( _e ) ) { _set_goal(); } if ( isdefined( _o_bundle ) && ( isdefined( _o_bundle.scene_stopping ) && _o_bundle.scene_stopping ) ) // don't clear this if the scene is looping { _o_bundle = undefined; } } function _set_goal() { if ( !( ( _e.scene_spawned === _o_bundle._s.name ) && isdefined( _e.target ) ) ) { if ( !isdefined( _e.script_forcecolor ) ) { if ( !_e flagsys::get( "anim_reach" ) ) { if ( isdefined( _e.scenegoal ) ) { _e SetGoal( _e.scenegoal ); // use secene goal _e.scenegoal = undefined; } else if ( _b_set_goal ) { _e SetGoal( _e.origin ); // default to current location } } } } } function _track_goal() { // disable setting goal when animation is done if goal is changed any time during animation // (assume scripter knows what they are doing and don't override it) self endon( "cleanup" ); _e endon( "death" ); _e waittill( "goal_changed" ); _b_set_goal = false; } function _play_anim( animation, n_delay_min = 0, n_delay_max = 0, n_rate = 1, n_blend = 0.2, n_time = 0 ) { /# if ( GetDvarInt( "debug_scene" ) > 0 ) { if ( isdefined( _s.name ) ) { PrintTopRightln( "csceneobject::_play_anim : " + _s.name ); } else { PrintTopRightln( "csceneobject::_play_anim : " + _s.model ); } } #/ if ( _should_skip_anim( animation ) ) { return; } if ( n_time != 0 ) { n_time = [[ _o_bundle ]]->get_anim_relative_start_time( animation, n_time ); } n_delay = n_delay_min; if ( n_delay_max > n_delay_min ) { n_delay = RandomFloatRange( n_delay_min, n_delay_max ); } do_reach = ( ( n_time == 0 ) && ( ( isdefined( _s.doreach ) && _s.doreach ) && ( !( isdefined( _o_bundle._testing ) && _o_bundle._testing ) || GetDvarInt( "scene_test_with_reach", 0 ) ) ) ); _spawn( undefined, !do_reach, !do_reach ); if ( !IsActor( _e ) ) { do_reach = false; } if ( n_delay > 0 ) { if ( n_delay > 0 ) { wait n_delay; } } if ( do_reach ) { [[scene()]]->wait_till_scene_ready( self ); if ( ( isdefined( _s.DisableArrivalInReach ) && _s.DisableArrivalInReach ) ) { _e animation::reach( animation, get_align_ent(), get_align_tag(), true ); } else { _e animation::reach( animation, get_align_ent(), get_align_tag() ); } flagsys::set( "ready" ); } else if ( n_rate > 0 ) // Go ahead and first-frame the anim right away without waiting { [[scene()]]->wait_till_scene_ready(); } else if ( isdefined( _s.aligntarget ) ) { foreach ( o_obj in _o_bundle._a_objects ) { // If align target is an object in this scene, wait for it to spawn if ( o_obj._str_name == _s.aligntarget ) { o_obj flagsys::wait_till( "ready" ); break; } } } if ( is_alive() ) { align = get_align_ent(); tag = get_align_tag(); if ( align == level ) { align = ( 0, 0, 0 ); tag = ( 0, 0, 0 ); } if ( is_shared_player() ) { _play_shared_player_anim( animation, align, tag, n_rate, n_time ); } else { if ( is_player() && !( isdefined( _s.newplayermethod ) && _s.newplayermethod ) ) { thread link_player(); } if ( ( /*!is_player() && */_o_bundle._s scene::is_igc() ) || ( _e.scene_spawned === _o_bundle._s.name ) ) { _e DontInterpolate(); _e Show(); } // Lerping and camera tween n_lerp = get_lerp_time(); if ( IsPlayer( _e ) && !_o_bundle._s scene::is_igc() ) { n_camera_tween = get_camera_tween(); if ( n_camera_tween > 0 ) { _e StartCameraTween( n_camera_tween ); } } /////////////////// if ( ![[ _o_bundle ]]->has_next_scene() ) { n_blend_out = ( IsAI( _e ) ? .2 : 0 ); } else { n_blend_out = 0; } if ( ( isdefined( _s.DieWhenFinished ) && _s.DieWhenFinished ) ) { n_blend_out = 0; } /# if ( GetDvarInt( "debug_scene" ) > 0 ) { PrintTopRightln( "csceneobject::_play_anim : ::animation::play: " + ( ( isdefined( _s.name ) )? _s.name : _s.model ) + " : " + animation ); } #/ /# if ( GetDvarInt( "debug_scene_skip" ) > 0 ) { if ( !isdefined( level.animation_played ) ) { level.animation_played = []; animation_played_name = ( ( isdefined( _s.name ) )? _s.name : _s.model ) + " : " + animation; if ( !isdefined( level.animation_played ) ) level.animation_played = []; else if ( !IsArray( level.animation_played ) ) level.animation_played = array( level.animation_played ); level.animation_played[level.animation_played.size]=animation_played_name;; } } #/ self.current_playing_anim = animation; //skip the new animation if we are skipping the scene if ( ( isdefined( [[ _o_bundle ]]->is_skipping_scene() ) && [[ _o_bundle ]]->is_skipping_scene() ) && n_rate != 0 ) { thread skip_scene( true ); } _e animation::play( animation, align, tag, n_rate, n_blend, n_blend_out, n_lerp, n_time, _s.ShowWeaponInFirstPerson ); if ( !isdefined( _e ) || !_e IsPlayingAnimScripted() ) { self.current_playing_anim = undefined; } /# if ( GetDvarInt( "debug_scene_skip" ) > 0 ) { if(isdefined(level.animation_played)) { for ( i = 0; i < level.animation_played.size; i++ ) { animation_played_name = ( isdefined( _s.name ) ? _s.name : _s.model ) + " : " + animation; if ( level.animation_played[ i ] == animation_played_name ) { ArrayRemoveValue( level.animation_played, animation_played_name ); i--; continue; } } } } #/ /# if ( GetDvarInt( "debug_scene" ) > 0 ) { PrintTopRightln("csceneobject::_play_anim : ::animation::Stop: " + ((isdefined(_s.name))? _s.name : _s.model) + " : " + animation); } #/ } } else { /# log( "No entity for animation '" + animation + "' so not playing it." ); #/ } _is_valid = ( is_alive() && !in_a_different_scene() ); } function spawn_ent( e ) { b_disable_throttle = ( _o_bundle._s scene::is_igc() || ( isdefined( _o_bundle._s.DontThrottle ) && _o_bundle._s.DontThrottle ) ); if ( is_player() && !( isdefined( _s.newplayermethod ) && _s.newplayermethod ) ) { system::wait_till( "loadout" ); m_player = util::spawn_anim_model( level.player_interactive_model ); return m_player; } else if ( isdefined( e ) ) { if ( IsSpawner( e ) ) { /# if ( _o_bundle._testing ) { e.count++; } #/ if ( !error( e.count < 1, "Trying to spawn AI for scene with spawner count < 1" ) ) { return e spawner::spawn( true, undefined, undefined, undefined, b_disable_throttle ); } } } else if ( isdefined( _s.model ) ) { new_model = undefined; if ( is_player_model() ) { new_model = util::spawn_anim_player_model( _s.model, _o_bundle._e_root.origin, _o_bundle._e_root.angles ); } else { new_model = util::spawn_anim_model( _s.model, _o_bundle._e_root.origin, _o_bundle._e_root.angles, undefined, !b_disable_throttle ); } return new_model; } } function _play_shared_player_anim( animation, align, tag, n_rate, n_time ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::_play_shared_player_anim: " + animation); } #/ self.player_animation = animation; self.player_animation_notify = animation + "_notify"; self.player_animation_length = GetAnimLength( animation ); self.player_align = align; self.player_tag = tag; self.player_rate = n_rate; self.player_time_frac = n_time; self.player_start_time = GetTime(); callback::on_loadout( &_play_shared_player_anim_for_player, self ); foreach ( player in level.players ) { if ( player flagsys::get( "loadout_given" ) && ( player.sessionstate !== "spectator" ) ) { self thread _play_shared_player_anim_for_player( player ); } else if( ( isdefined( player.initialLoadoutGiven ) && player.initialLoadoutGiven ) ) { revive_player( player ); } } waittillframeend; do { b_playing = false; a_players = ArrayCopy( level.activeplayers ); foreach ( player in a_players ) { if ( isdefined( player ) && player flagsys::get( self.player_animation_notify ) ) { b_playing = true; player flagsys::wait_till_clear( self.player_animation_notify ); break; } } } while ( b_playing ); callback::remove_on_loadout( &_play_shared_player_anim_for_player, self ); thread [[_o_bundle]]->_call_state_funcs( "players_done" ); } function _play_shared_player_anim_for_player( player ) { player endon( "death" ); /# //PrintTopRightln( __FUNCTION__ ); #/ /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::_play_shared_player_anim_for_player: " + self.player_animation); } #/ if ( !isdefined( _o_bundle ) ) return; player flagsys::set( "shared_igc" ); //Do not clear the flag for the init state if( player flagsys::get( self.player_animation_notify ) ) { player flagsys::set( self.player_animation_notify + "_skip_init_clear" ); } player flagsys::set( self.player_animation_notify ); if ( isdefined( player GetLinkedEnt() ) ) { player Unlink(); } if ( !( isdefined( _s.DisableTransitionIn ) && _s.DisableTransitionIn ) ) { if ( ( player != _player ) || GetDvarInt( "scr_player1_postfx", 0 ) ) { if ( !isdefined( player.screen_fade_menus ) ) { if ( !( isdefined( level.chyron_text_active ) && level.chyron_text_active ) ) { if ( !( isdefined( player.fullscreen_black_active ) && player.fullscreen_black_active ) ) { player.play_scene_transition_effect = true; } } } } } player Show(); // Make sure the player is not hidden before hidding to the other players player SetInvisibleToAll(); /* /# PrintTopRightln("SetInvisibleToAll : " + GetTime(), ORANGE, -1); #/ */ _prepare_player( player ); n_time_passed = ( GetTime() - self.player_start_time ) / 1000; n_start_time = self.player_time_frac * self.player_animation_length; n_time_left = self.player_animation_length - n_time_passed - n_start_time; n_time_frac = 1 - ( n_time_left / self.player_animation_length ); if ( isdefined( _e ) && ( player != _e ) ) { // Teleport coop players to the player who is triggering this scene // so that the camera tween and lerping happens from the same place player DontInterpolate(); player SetOrigin( _e.origin ); player SetPlayerAngles( _e GetPlayerAngles() ); } // Lerping and camera tween n_lerp = get_lerp_time(); if ( !_o_bundle._s scene::is_igc() ) { n_camera_tween = get_camera_tween(); if ( n_camera_tween > 0 ) { player StartCameraTween( n_camera_tween ); } } /////////////////// if ( n_time_frac < 1 ) { // scene_set_visible_time = player.scene_set_visible_time; // if ( isdefined( scene_set_visible_time ) ) // { // Assert( scene_set_visible_time == level.time ); // } //// player.scene_set_visible_time = undefined; /# if( GetDvarInt("scene_hide_player") > 0 ) { player Hide(); } if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("csceneobject::_play_shared_player_anim_for_player::animation::play: " + _s.name + " : " + self.player_animation); } #/ str_animation = self.player_animation; // load gender specific player animation if ( player util::is_female() ) { if ( isdefined( _o_bundle._s.s_female_bundle ) ) { s_bundle = _o_bundle._s.s_female_bundle; } } else { if ( isdefined( _o_bundle._s.s_male_bundle ) ) { s_bundle = _o_bundle._s.s_male_bundle; } } if ( isdefined( s_bundle ) ) { foreach ( s_object in s_bundle.objects ) { if ( isdefined( s_object ) && ( s_object.type === "player" ) ) { str_animation = s_object.mainanim; break; } } } player_num = player GetEntityNumber(); if(!isdefined(self.current_playing_anim)) { self.current_playing_anim = []; } self.current_playing_anim[player_num] = str_animation; //skip the new animation if we are skipping the scene if ( ( isdefined( [[ _o_bundle ]]->is_skipping_scene() ) && [[ _o_bundle ]]->is_skipping_scene() ) ) { thread skip_scene( true ); } ////////////////////////////////////////// player animation::play( str_animation, self.player_align, self.player_tag, self.player_rate, 0, 0, n_lerp, n_time_frac, _s.ShowWeaponInFirstPerson ); if( !(player flagsys::get( self.player_animation_notify + "_skip_init_clear" )) ) { player flagsys::clear( self.player_animation_notify ); // all players use the same aniamtion name for the flag to track when they are done } else { player flagsys::clear( self.player_animation_notify + "_skip_init_clear" ); } if ( !player IsPlayingAnimScripted() ) { self.current_playing_anim[player_num] = undefined; } /# if ( GetDvarInt( "debug_scene" ) > 0 ) { PrintTopRightln( "csceneobject::_play_shared_player_anim_for_player::animation::Stopped: " + _s.name + " : " + self.player_animation ); } #/ } } function play_regroup_fx_for_scene( e_player ) { align = get_align_ent(); v_origin = align.origin; v_angles = align.angles; tag = get_align_tag(); if ( isdefined( tag ) ) { v_origin = align GetTagOrigin( tag ); v_angles = align GetTagAngles( tag ); } v_start = GetStartOrigin( v_origin, v_angles, _s.mainanim ); n_dist_sq = DistanceSquared( e_player.origin, v_start ); if ( ( n_dist_sq > 500 * 500 || isdefined( e_player.hijacked_vehicle_entity ) ) && ( !( isdefined( e_player.force_short_scene_transition_effect ) && e_player.force_short_scene_transition_effect ) ) ) { self thread regroup_invulnerability( e_player ); e_player clientfield::increment_to_player( "postfx_igc", 1 ); // full effect } else { e_player clientfield::increment_to_player( "postfx_igc", 3 ); // minimal effect } util::wait_network_frame(); // make sure postfx capture frame before we teleport } function regroup_invulnerability( e_player ) { e_player endon( "disconnect" ); e_player.ignoreme = true; e_player.b_teleport_invulnerability = true; e_player util::streamer_wait( undefined, 0, 7 ); e_player.ignoreme = false; e_player.b_teleport_invulnerability = undefined; } function get_lerp_time() { if ( IsPlayer( _e ) ) { return ( isdefined( _s.LerpTime ) ? _s.LerpTime : 0 ); } else { return ( isdefined( _s.EntityLerpTime ) ? _s.EntityLerpTime : 0 ); } } function get_camera_tween() { return ( isdefined( _s.CameraTween ) ? _s.CameraTween : 0 ); } function get_camera_tween_out() { return ( isdefined( _s.CameraTweenOut ) ? _s.CameraTweenOut : 0 ); } function link_player() { self endon( "done" ); level flag::wait_till( "all_players_spawned" ); player = _player; player Hide(); e_linked = player GetLinkedEnt(); if ( isdefined( e_linked ) && ( e_linked == _e ) ) { // Update link/clamp if linking to same entity if ( ( isdefined( _s.lockview ) && _s.lockview ) ) { player PlayerLinkToAbsolute( _e, "tag_player" ); } else { player LerpViewAngleClamp( .2, .1, .1, (isdefined(_s.viewclampright)?_s.viewclampright:0), (isdefined(_s.viewclampleft)?_s.viewclampleft:0), (isdefined(_s.viewclamptop)?_s.viewclamptop:0), (isdefined(_s.viewclampbottom)?_s.viewclampbottom:0) ); } return; } player DisableUsability(); player DisableOffhandWeapons(); // player DisableWeapons( true ); player DisableWeapons(); //TODO_CODE: QUICK weapon switch only supported for SP at the momement util::wait_network_frame(); if ( _s.cameratween > 0 ) { // player StartCameraTween( _s.cameratween ); //TODO_CODE: only supported for SP at the momement } player notify( "scene_link" ); waittillframeend; // allow level script to do custom stuff before linking if ( ( isdefined( _s.lockview ) && _s.lockview ) ) { player PlayerLinkToAbsolute( _e, "tag_player" ); } else { player PlayerLinkToDelta( _e, "tag_player", 1, (isdefined(_s.viewclampright)?_s.viewclampright:0), (isdefined(_s.viewclampleft)?_s.viewclampleft:0), (isdefined(_s.viewclamptop)?_s.viewclamptop:0), (isdefined(_s.viewclampbottom)?_s.viewclampbottom:0), 1, 1 ); // player SetPlayerViewRateScale( 100 ); //TODO_CODE: only supported for SP at the momement } wait ( _s.cameratween > .2 ? _s.cameratween : .2 ); _e Show(); } function reset_player() { level flag::wait_till( "all_players_spawned" ); player = _player; // player StartCameraTween( .2 ); //TODO_CODE: only supported for SP at the momement // player ShowViewModel(); //TODO_CODE: only supported for SP at the momement // player SetLowReady( false ); //TODO_CODE: only supported for SP at the momement // player ResetPlayerViewRateScale(); //TODO_CODE: only supported for SP at the momement player EnableUsability(); player EnableOffhandWeapons(); player EnableWeapons(); player Show(); } function has_init_state() { return _s scene::_has_init_state(); } function is_alive() { return ( isdefined( _e ) && ( _e.health > 0 || _s.IgnoreAliveCheck === true ) ); } function is_player() { return ( IsDefined( _s.player ) ); } function is_player_model() { return _s.type === "player model"; } function is_shared_player() { return ( IsDefined( _s.player ) && ( isdefined( _s.SharedIGC ) && _s.SharedIGC ) ); } function in_a_different_scene() { return ( isdefined( _e ) && isdefined( _e.current_scene ) && ( _e.current_scene != _o_bundle._str_name ) ); } function _should_skip_anim( animation ) { if(!( isdefined( _s.player ) && _s.player ) && !( isdefined( _s.sharedigc ) && _s.sharedigc ) && !( isdefined( _s.KeepWhileSkipping ) && _s.KeepWhileSkipping ) && ( isdefined( [[_o_bundle]]->is_skipping_scene() ) && [[_o_bundle]]->is_skipping_scene() ) && ( isdefined( _s.DeleteWhenFinished ) && _s.DeleteWhenFinished )) { if( !AnimHasImportantNotifies(animation) ) { if ( !IsSpawner( _e ) ) { b_allows_multiple = [[scene()]]->allows_multiple(); e = scene::get_existing_ent( _str_name, b_allows_multiple ); if( isdefined(e) ) { return false; } } return true; } } return false; } function _should_skip_entity() { if(!( isdefined( _s.player ) && _s.player ) && !( isdefined( _s.sharedigc ) && _s.sharedigc ) && !( isdefined( _s.KeepWhileSkipping ) && _s.KeepWhileSkipping ) && ( isdefined( [[_o_bundle]]->is_skipping_scene() ) && [[_o_bundle]]->is_skipping_scene() ) && ( isdefined( _s.DeleteWhenFinished ) && _s.DeleteWhenFinished )) { if( isdefined(_s.initanim) && AnimHasImportantNotifies(_s.initanim) ) { return false; } if( isdefined(_s.mainanim) && AnimHasImportantNotifies(_s.mainanim) ) { return false; } if( isdefined(_s.endanim) && AnimHasImportantNotifies(_s.endanim) ) { return false; } if ( !IsSpawner( _e ) ) { b_allows_multiple = [[scene()]]->allows_multiple(); e = scene::get_existing_ent( _str_name, b_allows_multiple ); if( isdefined(e) ) { return false; } } return true; } return false; } function private skip_anim_on_client(entity, anim_name) { if(!isdefined(anim_name)) return; if(!isdefined(entity)) return; if(!( entity IsPlayingAnimScripted())) return; is_looping = IsAnimLooping(anim_name); if(is_looping) return; entity clientfield::increment( "player_scene_animation_skip" ); } function private skip_anim_on_server( entity, anim_name ) { if(!isdefined(anim_name)) return; if(!isdefined(entity)) return; //@ToDo : change this to check on the anim_name if(!( entity IsPlayingAnimScripted())) return; is_looping = IsAnimLooping(anim_name); if(is_looping) { entity animation::stop(); } else { entity SetAnimTimebyName(anim_name, 1); } entity stopsounds(); } function skip_scene_on_client() { if(isdefined(self.current_playing_anim)) { /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln( "csceneobject::skip_scene_on_client: " + _s.mainanim + " : " + GetTime(), (0.8, 0.8 , 0.8) ); } #/ if ( is_shared_player() ) { foreach ( player in level.players ) { skip_anim_on_client(player, self.current_playing_anim[player GetEntityNumber()]); } } else { skip_anim_on_client(_e, self.current_playing_anim ); } return true; } return false; } function skip_scene_on_server() { if(isdefined(self.current_playing_anim)) { /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("csceneobject::skip_scene: " + _s.mainanim + " : " + GetTime(), ( 1, 1, 1 )); } #/ if ( is_shared_player() ) { foreach ( player in level.players ) { //ToDo: follow up //player EnableInvulnerability(); skip_anim_on_server(player, self.current_playing_anim[player GetEntityNumber()]); } } else { /* *ToDo: follow up if(IsPlayer( _e) ) { player EnableInvulnerability(); } */ skip_anim_on_server(_e, self.current_playing_anim ); } } } function skip_scene(b_wait_one_frame) { if(isdefined(b_wait_one_frame)) //wait for the animation to start { wait 0.05; } if(skip_scene_on_client()) { wait 0.05; } skip_scene_on_server(); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ___ ___ ___ _ _ ___ // / __| / __| | __| | \| | | __| // \__ \ | (__ | _| | .` | | _| // |___/ \___| |___| |_|\_| |___| // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class cScene : cScriptBundleBase { var _e_root; var _str_state; var _n_object_id; var _str_mode; var _str_notify_name; var _n_request_time; var _n_streamer_req; constructor() { _n_object_id = 0; _str_mode = ""; _n_streamer_req = -1; } destructor() { } function init( str_scenedef, s_scenedef, e_align, a_ents, b_test_run ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("cscene::init : " + str_scenedef); } if( isdefined( level.scriptbundles[ "scene" ][ s_scenedef.name ] ) ) { level.scriptbundles[ "scene" ][ s_scenedef.name ].used = true; } #/ cScriptBundleBase::init( str_scenedef, s_scenedef, b_test_run ); if( isdefined( s_scenedef.streamerhint ) && s_scenedef.streamerhint != "" && !is_skipping_scene()) { _n_streamer_req = streamerRequest( "set", s_scenedef.streamerhint ); } _str_notify_name = ( IsString( _s.MaleBundle ) ? _s.MaleBundle : _str_name ); if ( !isdefined( a_ents ) ) a_ents = []; else if ( !IsArray( a_ents ) ) a_ents = array( a_ents );; if ( !error( a_ents.size > _s.objects.size, "Trying to use more entities than scene supports." ) ) { _e_root = e_align; if ( !isdefined( level.active_scenes[ _str_name ] ) ) level.active_scenes[ _str_name ] = []; else if ( !IsArray( level.active_scenes[ _str_name ] ) ) level.active_scenes[ _str_name ] = array( level.active_scenes[ _str_name ] ); level.active_scenes[ _str_name ][level.active_scenes[ _str_name ].size]=_e_root;; if ( !isdefined( _e_root.scenes ) ) _e_root.scenes = []; else if ( !IsArray( _e_root.scenes ) ) _e_root.scenes = array( _e_root.scenes ); _e_root.scenes[_e_root.scenes.size]=self;; a_objs = get_valid_object_defs(); foreach ( s_obj in a_objs ) { add_object( [[ [[self]]->new_object() ]]->first_init( s_obj, self ) ); } _n_request_time = GetTime(); if ( !( isdefined( _s.DontSync ) && _s.DontSync ) ) { add_to_sync_list(); } self thread initialize( a_ents ); } } function add_to_sync_list() { if(!isdefined(level.scene_sync_list))level.scene_sync_list=[]; if(!isdefined(level.scene_sync_list[ _n_request_time ]))level.scene_sync_list[ _n_request_time ]=[]; array::add( level.scene_sync_list[ _n_request_time ], self, false ); } function remove_from_sync_list() { if ( isdefined(level.scene_sync_list) && isdefined( level.scene_sync_list[ _n_request_time ] ) ) { ArrayRemoveValue( level.scene_sync_list[ _n_request_time ], self ); if ( !level.scene_sync_list[ _n_request_time ].size ) { level.scene_sync_list[ _n_request_time ] = undefined; } } } function new_object() { return new cSceneObject(); } function get_valid_object_defs() { a_obj_defs = []; foreach ( s_obj in _s.objects ) { if ( _s.vmtype == "server" || s_obj.vmtype == "server" ) { if ( isdefined( s_obj.name ) || isdefined( s_obj.model ) || isdefined( s_obj.initanim ) || isdefined( s_obj.mainanim ) ) { if ( !( isdefined( s_obj.disabled ) && s_obj.disabled ) ) { if ( !isdefined( a_obj_defs ) ) a_obj_defs = []; else if ( !IsArray( a_obj_defs ) ) a_obj_defs = array( a_obj_defs ); a_obj_defs[a_obj_defs.size]=s_obj;; } } } } return a_obj_defs; } function initialize( a_ents, b_playing = false ) { self notify( "new_state" ); self endon( "new_state" ); self thread sync_with_client_scene( "init", _testing ); assign_ents( a_ents ); if ( get_valid_objects().size > 0 ) { level flagsys::set( _str_name + "_initialized" ); _str_state = "init"; foreach ( o_obj in _a_objects ) { thread [[o_obj]]->initialize(); } } if ( !b_playing ) { thread _call_state_funcs( "init" ); } wait_till_scene_ready(); level flagsys::set( _str_notify_name + "_ready" ); // stops the scene if all objects die in the initialize state array::flagsys_wait( _a_objects, "done" ); thread stop(); } function get_object_id() { _n_object_id++; return _n_object_id; } function sync_with_client_scene( str_state, b_test_run = false ) { if ( _s.vmtype == "both" && !_s scene::is_igc() ) { self endon( "new_state" ); wait_till_scene_ready(); n_val = undefined; if ( b_test_run ) { switch ( str_state ) { case "stop": n_val = 3; break; case "init": n_val = 4; break; case "play": n_val = 5; break; } } else { switch ( str_state ) { case "stop": n_val = 0; break; case "init": n_val = 1; break; case "play": n_val = 2; break; } } level clientfield::set( _s.name, n_val ); } } function assign_ents( a_ents ) { if ( !isdefined( a_ents ) ) a_ents = []; else if ( !IsArray( a_ents ) ) a_ents = array( a_ents );; a_objects = ArrayCopy( _a_objects ); if ( _assign_ents_by_name( a_objects, a_ents ) ) { if ( _assign_ents_by_type( a_objects, a_ents, "player", &_is_ent_player ) ) { if ( _assign_ents_by_type( a_objects, a_ents, "actor", &_is_ent_actor ) ) { if ( _assign_ents_by_type( a_objects, a_ents, "vehicle", &_is_ent_vehicle ) ) { if ( _assign_ents_by_type( a_objects, a_ents, "prop" ) ) { foreach ( ent in a_ents ) { obj = array::pop( a_objects ); if ( !error( !isdefined( obj ), "No scene object to assign entity too. You might have passed in more than the scene supports." ) ) { obj._e = ent; } } } } } } } } function _assign_ents_by_name( &a_objects, &a_ents ) { if ( a_ents.size ) { foreach ( str_name, e_ent in ArrayCopy( a_ents ) ) { foreach ( i, o_obj in ArrayCopy( a_objects ) ) { if ( isdefined( o_obj._s.name ) && ( (isdefined(o_obj._s.name)?""+o_obj._s.name:"") == ToLower( (isdefined(str_name)?""+str_name:"") ) ) ) { o_obj._e = e_ent; ArrayRemoveIndex( a_ents, str_name, true ); ArrayRemoveIndex( a_objects, i ); break; } } } /# // Check for any remaining entities with specific names that don't have objects to assign them to foreach ( i, ent in a_ents ) { error( IsString( i ), "No scene object with name '" + i + "'." ); } #/ } return a_ents.size; } function _assign_ents_by_type( &a_objects, &a_ents, str_type, func_test ) { if ( a_ents.size ) { a_objects_of_type = get_objects( str_type ); if ( a_objects_of_type.size ) { foreach ( ent in ArrayCopy( a_ents ) ) { if ( isdefined( func_test ) && [[ func_test ]]( ent ) ) { obj = array::pop_front( a_objects_of_type ); if ( isdefined( obj ) ) { obj._e = ent; ArrayRemoveValue( a_ents, ent, true ); ArrayRemoveValue( a_objects, obj ); } else { break; } } } } } return a_ents.size; } function _is_ent_player( ent ) { return ( IsPlayer( ent ) ); } function _is_ent_actor( ent ) { return ( IsActor( ent ) || IsActorSpawner( ent ) ); } function _is_ent_vehicle( ent ) { return ( IsVehicle( ent ) || IsVehicleSpawner( ent ) ); } function get_objects( str_type ) { a_ret = []; foreach ( obj in _a_objects ) { if ( obj._s.type == str_type ) { if ( !isdefined( a_ret ) ) a_ret = []; else if ( !IsArray( a_ret ) ) a_ret = array( a_ret ); a_ret[a_ret.size]=obj;; } } return a_ret; } function get_anim_relative_start_time(animation, n_time) { if(!isdefined(self.n_start_time) || self.n_start_time == 0 || !isdefined(self.longest_anim_length) || self.longest_anim_length == 0) return n_time; anim_length = GetAnimLength(animation); is_looping = IsAnimLooping(animation); n_time = self.longest_anim_length / anim_length * n_time; if(is_looping) { if(n_time > 0.95) n_time = 0.95; } else { if(n_time > 0.99) n_time = 0.99; } return n_time; } function is_player_anim_ending_early() { max_anim_length = -1; player_anim_length = -1; foreach ( obj in _a_objects ) { if(isdefined(obj._s.MainAnim)) { anim_length = GetAnimLength( obj._s.MainAnim ); } if ( ( obj._s.type === "player" ) ) { player_anim_length = anim_length; } if(anim_length > max_anim_length) { max_anim_length = anim_length; } } return player_anim_length < max_anim_length; } function play( str_state = "play", a_ents, b_testing = false, str_mode = "" ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("cscene::play : " + _s.name); } #/ self notify( "new_state" ); self endon( "new_state" ); if(str_mode == "skip_scene") { thread skip_scene( true ); } else if(str_mode == "skip_scene_player") { self.b_player_scene = true; thread skip_scene( true ); } else if(!is_skipping_scene() && is_scene_shared_sequence() && !is_scene_shared()) //stop the shared sequence if the next (current) scene is not shared. { init_scene_sequence_started( false); } update_scene_sequence(); _testing = b_testing; _str_mode = str_mode; if(( isdefined( _s.SpectateOnJoin ) && _s.SpectateOnJoin )) { level.scene_should_spectate_on_hot_join = true; } assign_ents( a_ents ); if ( StrStartsWith( _str_mode, "capture" ) ) { /* First-frame the scene and move player to align node to stream the scene */ if ( get_valid_objects().size ) { foreach ( o_obj in _a_objects ) { thread [[o_obj]]->initialize( true ); } } thread loop_camera_anim_to_set_up_for_capture(); // put player camera in a more accurate postiion for streaming // move the player to the align node and link them so they don't fall if there's nothing under them capture_player = level.players[ 0 ]; v_origin = get_align_ent().origin; if ( !isdefined( capture_player.e_capture_link ) ) { capture_player.e_capture_link = util::spawn_model( "tag_origin", v_origin ); capture_player SetOrigin( v_origin ); capture_player Linkto( level.players[ 0 ].e_capture_link ); } else { capture_player.e_capture_link.origin = v_origin; } wait 15; // give scene time in the init state to load textures, also the code needs time in between captures thread _stop_camera_anims(); } self thread sync_with_client_scene( "play", b_testing ); /* Get animation start time from the mode string */ self.n_start_time = 0; if ( IsSubStr( str_mode, "skipto" ) ) { args = StrTok( str_mode, ":" ); if ( isdefined( args[1] ) ) { self.n_start_time = Float( args[1] ); } else { // skip to end of animation - can't go all the way to 1 because looping animations will assert self.n_start_time = .95; } self.longest_anim_length = 0; foreach ( s_obj in _a_objects ) { if ( isdefined( s_obj._s.MainAnim ) ) { anim_length = GetAnimLength( s_obj._s.MainAnim ); if ( anim_length > self.longest_anim_length ) { self.longest_anim_length = anim_length; } } } } /* ---------------------------------------------- */ if ( get_valid_objects().size || _s scene::is_igc() ) { level flagsys::set( _str_name + "_playing" ); _str_state = "play"; foreach ( o_obj in _a_objects ) { thread [[o_obj]]->play(); } wait_till_scene_ready(); level flagsys::set( _str_notify_name + "_ready" ); if ( StrStartsWith( _str_mode, "capture" ) ) { /# AddDebugCommand( "startGfxCapture sceneFinal 0 30 tga captures/" + _str_name + " " + _str_name ); #/ } if ( self.n_start_time == 0 ) { self thread _play_camera_anims(); } /# if ( is_scene_shared() ) { display_dev_info(); } #/ if( _n_streamer_req != -1 && !is_skipping_scene()) { streamerRequest( "play", _s.streamerhint ); } thread _call_state_funcs( "play" ); if ( _s scene::is_igc() ) { if ( !( isdefined( _s.DisableSceneSkipping ) && _s.DisableSceneSkipping ) && _str_state != "init" ) { trigger_scene_sequence_started(self); //send self as cscene to force triggering the sequnce } if ( IsString( _s.cameraswitcher ) ) { _wait_for_camera_animation( _s.cameraswitcher, self.n_start_time ); } else if ( IsString( _s.extraCamSwitcher1 ) ) { _wait_for_camera_animation( _s.extraCamSwitcher1, self.n_start_time ); } else if ( IsString( _s.extraCamSwitcher2 ) ) { _wait_for_camera_animation( _s.extraCamSwitcher2, self.n_start_time ); } else if ( IsString( _s.extraCamSwitcher3 ) ) { _wait_for_camera_animation( _s.extraCamSwitcher3, self.n_start_time ); } else if ( IsString( _s.extraCamSwitcher4 ) ) { _wait_for_camera_animation( _s.extraCamSwitcher4, self.n_start_time ); } foreach ( o_obj in _a_objects ) { thread [[o_obj]]->stop( false, ( isdefined( o_obj._s.DontClamp ) && o_obj._s.DontClamp ), true ); } _e_root notify( "scene_done", _str_notify_name ); thread _call_state_funcs( "done" ); if ( ( isdefined( _s.SpectateOnJoin ) && _s.SpectateOnJoin ) ) { level.scene_should_spectate_on_hot_join = undefined; } } else { array::flagsys_wait_any_flag( _a_objects, "done", "main_done" ); if ( isdefined( _e_root ) ) { _e_root notify( "scene_done", _str_notify_name ); } thread _call_state_funcs( "done" ); if ( ( isdefined( _s.SpectateOnJoin ) && _s.SpectateOnJoin ) ) { level.scene_should_spectate_on_hot_join = undefined; } array::flagsys_wait( _a_objects, "done" ); } if ( is_looping() || ( StrEndsWith( _str_mode, "loop" ) ) ) { if ( has_init_state() ) { level flagsys::clear( _str_name + "_playing" ); thread initialize(); } else { level flagsys::clear( _str_name + "_initialized" ); thread play( str_state, undefined, b_testing, str_mode ); } } else { if ( !StrEndsWith( _str_mode, "single" ) ) { thread run_next(); } else { if( !is_skipping_scene() ) //if we are not skipping a scene then just notify that a scene sequence has ended { if(is_scene_shared_sequence()) { init_scene_sequence_started(false); } } else if(isdefined(level.linked_scenes)) //if we are skipping a scene, remove it from the linked scenes if it exists { ArrayRemoveValue(level.linked_scenes, _s.name ); } streamer_request_completed(); } if ( !_s scene::is_igc() || !( isdefined( _s.holdCameraLastFrame ) && _s.holdCameraLastFrame ) ) { // Scenes set to hold camera last frame must be stopped manually with scene::stop() thread stop( false, true ); } } } else { thread stop( false, true ); } } function _wait_server_time( n_time, n_start_time = 0 ) { n_len = ( n_time - ( n_time * n_start_time ) ); // get the length we need to wait from the desired start time fraction n_len = n_len / .05; n_len_int = Int( n_len ); if ( n_len_int != n_len ) { n_len = Floor( n_len ); } n_server_length = n_len * .05; // clamp to full server frames. wait n_server_length; } function _wait_for_camera_animation( str_cam, n_start_time ) { self endon( "skip_camera_anims" ); if ( IsCamAnimLooping( str_cam ) ) { level waittill( "forever" ); } else { _wait_server_time( GetCamAnimTime( str_cam ) / 1000, n_start_time ); } } function _play_camera_anims() { level endon( "stop_camera_anims" ); waittillframeend; e_align = get_align_ent(); v_origin = ( isdefined( e_align.origin ) ? e_align.origin : ( 0, 0, 0 ) ); v_angles = ( isdefined( e_align.angles ) ? e_align.angles : ( 0, 0, 0 ) ); xcam_players = []; if(( isdefined( _s.LinkXCamToOnePlayer ) && _s.LinkXCamToOnePlayer )) { foreach ( o_obj in _a_objects ) { if( isdefined(o_obj) && [[o_obj]]->is_player() && ![[o_obj]]->is_shared_player() ) { if ( !isdefined( xcam_players ) ) xcam_players = []; else if ( !IsArray( xcam_players ) ) xcam_players = array( xcam_players ); xcam_players[xcam_players.size]=o_obj._player;; } } if(xcam_players.size == 0) { xcam_players = level.players; } else { self.a_xcam_players = xcam_players; } } else { xcam_players = level.players; } if ( IsString( _s.cameraswitcher ) ) { if(!( isdefined( _s.LinkXCamToOnePlayer ) && _s.LinkXCamToOnePlayer )) { callback::on_loadout( &_play_camera_anim_on_player_callback, self ); } self.camera_v_origin = v_origin; self.camera_v_angles = v_angles; self.camera_start_time = GetTime(); array::thread_all_ents( xcam_players, &_play_camera_anim_on_player, v_origin, v_angles, false ); // hide_players(); /#display_dev_info();#/ } if ( IsString( _s.extraCamSwitcher1 ) ) { array::thread_all_ents( xcam_players, &_play_extracam_on_player, 0, _s.extraCamSwitcher1, v_origin, v_angles ); } if ( IsString( _s.extraCamSwitcher2 ) ) { array::thread_all_ents( xcam_players, &_play_extracam_on_player, 1, _s.extraCamSwitcher2, v_origin, v_angles ); } if ( IsString( _s.extraCamSwitcher3 ) ) { array::thread_all_ents( xcam_players, &_play_extracam_on_player, 2, _s.extraCamSwitcher3, v_origin, v_angles ); } if ( IsString( _s.extraCamSwitcher4 ) ) { array::thread_all_ents( xcam_players, &_play_extracam_on_player, 3, _s.extraCamSwitcher4, v_origin, v_angles ); } } function _play_camera_anim_on_player_callback( player ) { self thread _play_camera_anim_on_player(player, self.camera_v_origin, self.camera_v_angles, true); } function _play_camera_anim_on_player( player, v_origin, v_angles, ignore_initial_notetracks ) { player notify( "new_camera_switcher" ); player DontInterpolate(); player thread scene::scene_disable_player_stuff(); self.played_camera_anims = true; n_start_time = self.camera_start_time; if(!isdefined(_s.cameraSwitcherGraphicContents) || IsMature( player )) { //@ToDo - Enable once the new exe populated (8/14/2015) CamAnimScripted( player, _s.cameraswitcher, n_start_time, v_origin, v_angles ); //CamAnimScripted( player, _s.cameraswitcher, n_start_time, v_origin, v_angles, 0, "", ignore_initial_notetracks ); } else { //@ToDo - Enable once the new exe populated (8/14/2015) CamAnimScripted( player, _s.cameraSwitcherGraphicContents, n_start_time, v_origin, v_angles ); //CamAnimScripted( player, _s.cameraSwitcherGraphicContents, n_start_time, v_origin, v_angles, 0, "", ignore_initial_notetracks ); } } function loop_camera_anim_to_set_up_for_capture() { level endon( "stop_camera_anims" ); while ( true ) { _play_camera_anims(); _wait_for_camera_animation( _s.cameraswitcher ); } } function _play_extracam_on_player( player, n_index, str_camera_anim, v_origin, v_angles ) { self.played_camera_anims = true; ExtraCamAnimScripted( player, n_index, str_camera_anim, GetTime(), v_origin, v_angles ); } function _stop_camera_anims() { if(!( isdefined( self.played_camera_anims ) && self.played_camera_anims )) //no camera anims were played to be stopped { return; } level notify( "stop_camera_anims" ); xcam_players = []; if(isdefined(self.a_xcam_players)) { xcam_players = self.a_xcam_players; } else { xcam_players = GetPlayers(); } foreach ( player in xcam_players ) { if ( isdefined( player ) ) { self thread _stop_camera_anim_on_player( player ); } } // show_players(); } function _stop_camera_anim_on_player( player ) { player endon( "disconnect" ); if ( IsString( _s.cameraswitcher ) ) { player endon( "new_camera_switcher" ); player DontInterpolate(); EndCamAnimScripted( player ); player thread scene::scene_enable_player_stuff(); if(!( isdefined( _s.LinkXCamToOnePlayer ) && _s.LinkXCamToOnePlayer )) { callback::remove_on_loadout( &_play_camera_anim_on_player_callback, self ); } } // TODO: do we want the extracam animations to stop? if ( IsString( _s.extraCamSwitcher1 ) ) { EndExtraCamAnimScripted( player, 0 ); } if ( IsString( _s.extraCamSwitcher2 ) ) { EndExtraCamAnimScripted( player, 1 ); } if ( IsString( _s.extraCamSwitcher3 ) ) { EndExtraCamAnimScripted( player, 2 ); } if ( IsString( _s.extraCamSwitcher4 ) ) { EndExtraCamAnimScripted( player, 3 ); } } function display_dev_info() { if ( IsString( _s.devstate ) && GetDvarInt( "scr_show_shot_info_for_igcs", 0 ) ) { if ( !isdefined( level.hud_scene_dev_info1 ) ) { level.hud_scene_dev_info1 = NewHudElem(); level.hud_scene_dev_info1.alignX = "right"; level.hud_scene_dev_info1.alignY = "bottom"; level.hud_scene_dev_info1.horzAlign = "user_right"; level.hud_scene_dev_info1.y = 400; level.hud_scene_dev_info1.fontScale = 1.3; level.hud_scene_dev_info1.color = (112/255,128/255,144/255); level.hud_scene_dev_info1 SetText( "SCENE: " + ToUpper( _s.name ) ); } if ( !isdefined( level.hud_scene_dev_info2 ) ) { level.hud_scene_dev_info2 = NewHudElem(); level.hud_scene_dev_info2.alignX = "right"; level.hud_scene_dev_info2.alignY = "bottom"; level.hud_scene_dev_info2.horzAlign = "user_right"; level.hud_scene_dev_info2.y = 420; level.hud_scene_dev_info2.fontScale = 1.3; level.hud_scene_dev_info2.color = (112/255,128/255,144/255); } level.hud_scene_dev_info2 SetText( "SHOT: " + ToUpper( _s.name ) ); if ( !isdefined( level.hud_scene_dev_info3 ) ) { level.hud_scene_dev_info3 = NewHudElem(); level.hud_scene_dev_info3.alignX = "right"; level.hud_scene_dev_info3.alignY = "bottom"; level.hud_scene_dev_info3.horzAlign = "user_right"; level.hud_scene_dev_info3.y = 440; level.hud_scene_dev_info3.fontScale = 1.3; level.hud_scene_dev_info3.color = (112/255,128/255,144/255); level.hud_scene_dev_info3 SetText( "STATE: " + ToUpper( _s.devstate ) ); } } else { destroy_dev_info(); } } function destroy_dev_info() { if ( isdefined( level.hud_scene_dev_info1 ) ) { level.hud_scene_dev_info1 Destroy(); } if ( isdefined( level.hud_scene_dev_info2 ) ) { level.hud_scene_dev_info2 Destroy(); } if ( isdefined( level.hud_scene_dev_info3 ) ) { level.hud_scene_dev_info3 Destroy(); } } function is_skipping_scene() { if( _s.name == "cin_ram_02_04_interview_part04" )//HACK - TU1, remove this later and enable the commented out section below { return false; } return ( ( ( isdefined( self.skipping_scene ) && self.skipping_scene ) || self._str_mode == "skip_scene" || self._str_mode == "skip_scene_player" ) /*&& !IS_TRUE( _s.disablesceneskipping )*/ );//TU1 - add this in later } function is_skipping_player_scene() { return ( ( isdefined( self.b_player_scene ) && self.b_player_scene ) || self._str_mode == "skip_scene_player") && !array::contains(level.linked_scenes, _s.name); } function has_next_scene() { return isdefined(_s.nextscenebundle); } function run_next() { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("cscene::run_next : " + GetTime()); } #/ b_run_next_scene = false; if ( isdefined( _s.nextscenebundle ) ) { self waittill( "stopped", b_finished ); if ( b_finished ) { b_skip_scene = is_skipping_scene(); if(b_skip_scene) { self util::waittill_any_timeout( 5, "scene_skip_completed"); /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::run_next - scene skipped : " + _s.nextscenebundle + " : " + GetTime(), (1, 1, 0)); } #/ } /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::run_next : " + _s.nextscenebundle + " : " + GetTime(), ( 1, 0, 0 )); } #/ if ( _s.scenetype == "fxanim" && ( _s.nextscenemode === "init" ) ) { if ( !error( !has_init_state(), "Scene can't init next scene '" + _s.nextscenebundle + "' because it doesn't have an init state." ) ) { if ( allows_multiple() ) { _e_root thread scene::init( _s.nextscenebundle, get_ents() ); } else { _e_root thread scene::init( _s.nextscenebundle ); } } } else { if(b_skip_scene) { if( is_skipping_player_scene() ) { _str_mode = "skip_scene_player"; } else { _str_mode = "skip_scene"; } } else { b_run_next_scene = true; } if ( allows_multiple() ) { _e_root thread scene::play( _s.nextscenebundle, get_ents(), undefined, undefined, undefined, _str_mode ); } else { _e_root thread scene::play( _s.nextscenebundle, undefined, undefined, undefined, undefined, _str_mode ); } } } } if( !( isdefined( b_run_next_scene ) && b_run_next_scene ) ) { if(!is_skipping_scene()) //if we are not skipping a scene then just notify that the scene sequence has ended { if(is_scene_shared_sequence()) { init_scene_sequence_started(false); } } else if(isdefined(level.linked_scenes)) //if we are skipping a scene, remove it from the linked scenes if it exists { ArrayRemoveValue(level.linked_scenes, _s.name ); } streamer_request_completed(); } } function streamer_request_completed() { if( IsString( _s._endStreamerHint ) ) { if( GetDvarInt("scene_hide_player") > 0 ) { foreach(player in level.players) { player Show(); } } streamerRequest( "clear", _s._endStreamerHint ); } } function stop( b_clear = false, b_finished = false ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("cscene::stop : " + _s.name); } #/ if ( isdefined( _str_state ) ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("cscene::stop : " + _s.name + " : "+ _str_state); } #/ /# if ( StrStartsWith( _str_mode, "capture" ) ) { AddDebugCommand( "stopGfxCapture 1" ); } #/ if ( !b_finished ) { streamer_request_completed(); } //Handle the case where the scene was explicitly stopped if(!is_skipping_scene()) { if ( !isdefined( _s.nextscenebundle ) && is_scene_shared_sequence()) { init_scene_sequence_started(false); } } self thread sync_with_client_scene( "stop", b_clear ); _str_state = undefined; self notify( "new_state" ); self notify( "death" ); level flagsys::clear( _str_name + "_playing" ); level flagsys::clear( _str_name + "_initialized" ); thread _call_state_funcs( "stop" ); self.scene_stopping = true; if ( IsDefined( _a_objects ) && !b_finished ) { foreach ( o_obj in _a_objects ) { if ( isdefined( o_obj ) && ![[ o_obj ]]->in_a_different_scene() ) { thread [[o_obj]]->stop( b_clear ); } } } self thread _stop_camera_anims(); /# if ( !isdefined( _s.nextscenebundle ) || !b_finished ) { destroy_dev_info(); } #/ /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("cscene::stopped notify sent : " + _s.name); } #/ self.scene_stopped = true; self notify( "stopped", b_finished ); remove_from_sync_list(); ArrayRemoveValue( level.active_scenes[ _str_name ], _e_root ); if ( level.active_scenes[ _str_name ].size == 0 ) { level.active_scenes[ _str_name ] = undefined; } if ( isdefined( _e_root ) ) { ArrayRemoveValue( _e_root.scenes, self ); if ( _e_root.scenes.size == 0 ) { _e_root.scenes = undefined; } _e_root notify( "scene_done", _str_notify_name ); _e_root.scene_played = true; } } if(( isdefined( _s.SpectateOnJoin ) && _s.SpectateOnJoin )) { level.scene_should_spectate_on_hot_join = undefined; } self thread _release_object(); } function _release_object() { // HACK: Make sure all the objects release their handle to the scene {wait(.05);}; foreach ( o_obj in _a_objects ) { o_obj._o_bundle = undefined; } } // function hide_players() // { // if ( IS_TRUE( _s.HidePlayers ) ) // { // foreach ( player in level.players ) // { // player SetInvisibleToAll(); // } // } // } // function show_players() // { // if ( IS_TRUE( _s.HidePlayers ) ) // { // foreach ( player in level.players ) // { // player SetVisibleToAll(); // } // } // } function has_init_state() { b_has_init_state = false; foreach ( o_scene_object in _a_objects ) { if ( [[o_scene_object]]->has_init_state() ) { b_has_init_state = true; break; } } return b_has_init_state; } function _call_state_funcs( str_state ) { self endon( "stopped" ); wait_till_scene_ready( undefined, true ); if ( str_state == "play" ) { waittillframeend; // HACK: need to allow init callbacks to happen first if init and play happen on same frame } level notify( _str_notify_name + "_" + str_state ); if ( isdefined( level.scene_funcs ) && isdefined( level.scene_funcs[ _str_notify_name ] ) && isdefined( level.scene_funcs[ _str_notify_name ][ str_state ] ) ) { a_ents = get_ents(); foreach ( handler in level.scene_funcs[ _str_notify_name ][ str_state ] ) { func = handler[0]; args = handler[1]; switch ( args.size ) { case 6: _e_root thread [[ func ]]( a_ents, args[0], args[1], args[2], args[3], args[4], args[5] ); break; case 5: _e_root thread [[ func ]]( a_ents, args[0], args[1], args[2], args[3], args[4] ); break; case 4: _e_root thread [[ func ]]( a_ents, args[0], args[1], args[2], args[3] ); break; case 3: _e_root thread [[ func ]]( a_ents, args[0], args[1], args[2] ); break; case 2: _e_root thread [[ func ]]( a_ents, args[0], args[1] ); break; case 1: _e_root thread [[ func ]]( a_ents, args[0] ); break; case 0: _e_root thread [[ func ]]( a_ents ); break; default: AssertMsg( "Too many args passed to scene func." ); } } } } function get_ents() { a_ents = []; foreach ( o_obj in _a_objects ) { ent = [[o_obj]]->get_ent(); if ( isdefined( o_obj._s.name ) ) { a_ents[ o_obj._s.name ] = ent; } else { if ( !isdefined( a_ents ) ) a_ents = []; else if ( !IsArray( a_ents ) ) a_ents = array( a_ents ); a_ents[a_ents.size]=ent;; } } return a_ents; } function get_root() { return _e_root; } function get_align_ent() { e_align = _e_root; if ( isdefined( _s.aligntarget ) ) { e_gdt_align = scene::get_existing_ent( _s.aligntarget, false, true ); if ( isdefined( e_gdt_align ) ) { e_align = e_gdt_align; } if ( !isdefined( e_gdt_align ) ) { str_msg = "Align target '" + (isdefined(_s.aligntarget)?""+_s.aligntarget:"") + "' doesn't exist for scene."; if ( !warning( _testing, str_msg ) ) { error( GetDvarInt( "scene_align_errors", 1 ), str_msg ); } } } else if ( isdefined( _e_root.e_scene_link ) ) { e_align = _e_root.e_scene_link; } return e_align; } function allows_multiple() { return ( isdefined( _s.allowmultiple ) && _s.allowmultiple ); } function is_looping() { return ( isdefined( _s.looping ) && _s.looping ); } function wait_till_scene_ready( o_exclude, b_ignore_streamer = false ) { a_objects = []; if ( isdefined( o_exclude ) ) { a_objects = array::exclude( _a_objects, o_exclude ); } else { a_objects = _a_objects; } wait_till_objects_ready( a_objects ); if ( _n_streamer_req != -1 ) { if ( !b_ignore_streamer ) { if ( isdefined( level.wait_for_streamer_hint_scenes ) ) { if ( IsInArray( level.wait_for_streamer_hint_scenes, _s.name ) ) { if ( !is_skipping_scene() ) { level util::streamer_wait( _n_streamer_req, 0, 5 ); } } } } } flagsys::set( "ready" ); sync_with_other_scenes(); } function wait_till_objects_ready( &array ) { do { recheck = false; foreach ( ent in array ) { if ( isdefined( ent ) && !ent flagsys::get( "ready" ) ) { ent util::waittill_either( "death", "ready" ); recheck = true; break; } } } while ( recheck ); } function sync_with_other_scenes() { if ( !( isdefined( _s.DontSync ) && _s.DontSync ) && isdefined(level.scene_sync_list) && IsArray(level.scene_sync_list[ _n_request_time ]) ) { // Wait for all scene objects that were requested to start on the same frame wait_till_objects_ready( level.scene_sync_list[ _n_request_time ] ); } } function get_valid_objects() { a_obj = []; foreach ( obj in _a_objects ) { if ( obj._is_valid ) { if ( !isdefined( a_obj ) ) a_obj = []; else if ( !IsArray( a_obj ) ) a_obj = array( a_obj ); a_obj[a_obj.size]=obj;; } } return a_obj; } function on_error() { stop(); } function get_state() { return _str_state; } function is_scene_shared() { if( !( isdefined( _s.skip_scene ) && _s.skip_scene ) && !(_s scene::is_igc()) ) { foreach ( o_scene_object in _a_objects ) { if ( o_scene_object._is_valid && [[o_scene_object]]->is_shared_player()) { b_shared_player = true; } } if(!isdefined(b_shared_player)) { /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("Cannot skip scene..cscene::level.players[0].skipping_scene = undefined : " + GetTime(), ( 1, 0, 0 )); } #/ self notify("scene_skip_completed"); return false; } } return true; } function skip_scene( b_sequence ) { if(( isdefined( b_sequence ) && b_sequence ) && ( isdefined( _s.DisableSceneSkipping ) && _s.DisableSceneSkipping )) { /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::skip_scene DisableSceneSkipping - Abort: " + _s.name + " : " + GetTime(), ( 1, 0, 0 )); } #/ finish_skip_scene(); return; } /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::skip_scene: " + _s.name + " : " + GetTime(), ( 0, 1, 0 )); } #/ if( !( isdefined( b_sequence ) && b_sequence ) ) { if(_str_state == "init") { while(_str_state == "init") { wait 0.05; } } if( is_skipping_player_scene() ) { /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::lui::screen_fade BLACK : " + GetTime()); } #/ /# if(GetDvarInt("scene_skip_no_fade") == 0) { b_skip_fading = false; } else { b_skip_fading = true; } #/ if(!( isdefined( b_skip_fading ) && b_skip_fading )) { //Freeze player controls foreach(player in level.players) { player FreezeControls( true ); } level.suspend_scene_skip_until_fade = true; level thread lui::screen_fade( 1, 1, 0, "black", false, "scene_system" ); wait 1; level.suspend_scene_skip_until_fade = undefined; } SetPauseWorld( false ); } while(( isdefined( level.suspend_scene_skip_until_fade ) && level.suspend_scene_skip_until_fade )) { wait 0.05; } } if(isdefined( _s.nextscenebundle )) { bNextSceneExist = true; } else { bNextSceneExist = false; } wait_till_scene_ready(); wait 0.05; /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::skip_scene - READY: " + _s.name + " : " + GetTime(), ( 0, 0, 1 )); } #/ _call_state_funcs("skip_started"); thread _skip_scene(); /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::skip_scene - Waiting for stopped event : " + GetTime(), ( 0, 1, 0 )); } #/ /# if( GetDvarInt("debug_scene_skip") > 0) { if(isdefined(level.animation_played)) { for(i = 0 ; i < level.animation_played.size; i++) { PrintTopRightln("NON-STOPPED-ANIMATIONS : " + level.animation_played[i], ( 1, 0, 0 ), -1); } } } #/ scene_skip_timeout = GetTime() + 4000; while( !( isdefined( self.scene_stopped ) && self.scene_stopped ) && GetTime() < scene_skip_timeout ) { wait 0.05; } /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::skip_scene - END: " + _s.name + " : " + GetTime(), ( 1, .5, 0 )); } #/ _call_state_funcs("skip_completed"); self notify("scene_skip_completed"); if(!bNextSceneExist) { if(is_skipping_player_scene()) { if(isdefined(level.linked_scenes)) { linked_scenes_timeout = GetTime() + 4000; while(level.linked_scenes.size > 0 && GetTime() < linked_scenes_timeout) { wait 0.05; } } finish_skip_scene(); } else if(( isdefined( self.skipping_scene ) && self.skipping_scene )) { self.skipping_scene = undefined; if(isdefined(level.linked_scenes)) { //level.skipping_linked_scenes--; ArrayRemoveValue(level.linked_scenes, _s.name ); } } } else { if(is_skipping_player_scene()) { if( _s scene::is_igc() ) { foreach(player in level.players) { player stopsounds(); } } } } } function private finish_skip_scene() { /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::scene_sequence_ended : " + GetTime(), ( 1, 0, 0 )); } #/ if(isdefined(level.player_skipping_scene)) { //Send a notify to the client that the skipping is completed. foreach(player in level.players) { player clientfield::increment_to_player( "player_scene_skip_completed" ); player FreezeControls( false ); //Stop sounds on the player player stopsounds(); } self.b_player_scene = undefined; self.skipping_scene = undefined; level.player_skipping_scene = undefined; level.linked_scenes = undefined; init_scene_sequence_started( false ); level notify("scene_skip_sequence_ended"); if( IsDefined( level.BZM_SceneSeqEndedCallback ) ) level thread [[level.BZM_SceneSeqEndedCallback]](_s.name);; /# if( GetDvarInt("debug_scene_skip") > 0) { PrintTopRightln("cscene::lui::screen_fade BLACK : " + GetTime()); } #/ /# if(GetDvarInt("scene_skip_no_fade") == 0) { b_skip_fading = false; } else { b_skip_fading = true; } #/ if ( !( isdefined( b_skip_fading ) && b_skip_fading ) ) { if ( !( isdefined( level.level_ending ) && level.level_ending ) ) { level thread lui::screen_fade( 1, 0, 1, "black", false, "scene_system" ); } } } } function private _skip_scene() { self endon( "stopped" ); wait 0.05; //wait one frame to make sure all entities spawned since clientfields cannot be sent on the same spawn frame. //animations on clients foreach ( o_scene_object in _a_objects ) { if ( o_scene_object._is_valid ) { [[o_scene_object]]->skip_scene_on_client(); } } wait 0.05; //wait one frame to give the clients a chance to process their animations //animations on server foreach ( o_scene_object in _a_objects ) { if ( o_scene_object._is_valid ) { [[o_scene_object]]->skip_scene_on_server(); } } self notify( "skip_camera_anims" ); } function should_skip_linked_to_players_scene() { if(isdefined(level.player_skipping_scene) && !( isdefined( _s.DisableSceneSkipping ) && _s.DisableSceneSkipping ) && array::contains(level.linked_scenes, _s.name)) { return true; } return false; } function private is_scene_shared_sequence() { return isdefined(level.shared_scene_sequence_started) && isdefined(_s.shared_scene_sequence); } function private update_scene_sequence() { if(isdefined(_s.shared_scene_sequence)) { if(isdefined(level.shared_scene_sequence_started)) { level.shared_scene_sequence_name = _s.name; } else { level.shared_scene_sequence_name = undefined; } } } function private init_scene_sequence_started( b_started) { if(( isdefined( b_started ) && b_started )) { scene::waittill_skip_sequence_completed(); if(isdefined(level.shared_scene_sequence_started)) { return; } _s.shared_scene_sequence = true; if(isdefined(_s.s_female_bundle)) { _s.s_female_bundle.shared_scene_sequence = _s.shared_scene_sequence; } if ( IsString( _s.nextscenebundle ) ) { s_cur_bundle = scene::get_scenedef( _s.nextscenebundle ); while( true ) { s_cur_bundle.shared_scene_sequence = _s.shared_scene_sequence; if(isdefined(s_cur_bundle.s_female_bundle)) { s_cur_bundle.s_female_bundle.shared_scene_sequence = _s.shared_scene_sequence; } if ( IsString( s_cur_bundle.nextscenebundle ) ) { s_cur_bundle = scene::get_scenedef( s_cur_bundle.nextscenebundle ); } else { break; } } } level.shared_scene_sequence_started = true; update_scene_sequence(); level notify("scene_sequence_started"); } else { if(!isdefined(level.shared_scene_sequence_started)) { return; } if(isdefined(_s.shared_scene_sequence)) { level.shared_scene_sequence_started = undefined; update_scene_sequence(); level notify("scene_sequence_ended", _s.name); } } } function private trigger_scene_sequence_started( scene_object, entity ) { if(self === scene_object) { if(!is_skipping_scene()) { init_scene_sequence_started( true ); } return; } if ( IsPlayer( entity ) ) { if ( !( isdefined( _s.DisableSceneSkipping ) && _s.DisableSceneSkipping ) && !is_skipping_scene()) { if ( [[scene_object]]->is_shared_player() || (_s scene::is_igc()) ) { if(_str_state != "init" || (isdefined(scene_object._s.initanim) || isdefined(scene_object._s.initanimloop))) { init_scene_sequence_started( true ); } } } } } function has_player() { foreach ( obj in _a_objects ) { if ( ( obj._s.type === "player" ) ) { return true; } } return false; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // _ __ __ _ ___ ___ _ _ ___ ___ ___ ___ ___ ___ _ _ ___ ___ ___ _ ___ ___ _____ // /_\ \ \ / / /_\ | _ \ | __| | \| | | __| / __| / __| / __| / __| | __| | \| | | __| / _ \ | _ ) _ | | | __| / __| |_ _| // / _ \ \ \/\/ / / _ \ | / | _| | .` | | _| \__ \ \__ \ \__ \ | (__ | _| | .` | | _| | (_) | | _ \ | || | | _| | (__ | | // /_/ \_\ \_/\_/ /_/ \_\ |_|_\ |___| |_|\_| |___| |___/ |___/ |___/ \___| |___| |_|\_| |___| \___/ |___/ \__/ |___| \___| |_| // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class cAwarenessSceneObject : cSceneObject { function play( str_alert_state ) { flagsys::clear( "ready" ); flagsys::clear( "done" ); flagsys::clear( "main_done" ); _str_state = "play"; self notify( "new_state" ); self endon( "new_state" ); self notify("play"); log( "play" ); waittillframeend;; switch ( str_alert_state ) { case "low_alert": log( "LOW ALERT" ); if ( isdefined( _s.LowAlertAnim ) ) { _str_death_anim = _s.LowAlertAnimDeath; _str_death_anim_loop = _s.LowAlertAnimDeathLoop; _play_anim( _s.LowAlertAnim ); } break; case "high_alert": log( "HIGH ALERT" ); if ( isdefined( _s.HighAlertAnim ) ) { _str_death_anim = _s.HighAlertAnimDeath; _str_death_anim_loop = _s.HighAlertAnimDeathLoop; _play_anim( _s.HighAlertAnim ); } break; case "combat": log( "COMBAT ALERT" ); if ( isdefined( _s.CombatAlertAnim ) ) { _str_death_anim = _s.CombatAlertAnimDeath; _str_death_anim_loop = _s.CombatAlertAnimDeathLoop; _play_anim( _s.CombatAlertAnim ); } break; default: error( 1, "Unsupported alert state" ); } thread finish(); } function _prepare() { if ( cSceneObject::_prepare() ) { if ( IsAI( _e ) ) { thread _on_alert_run_scene_thread(); } } } function _on_alert_run_scene_thread() { self endon( "play" ); self endon( "done" ); _e waittill( "alert", str_alert_state ); /# if ( GetDvarInt( "anim_debug", 0 ) ) { Print3d( _e.origin, "ALERT", ( 1, 0, 0 ), 1, .5, 20 ); } #/ thread [[scene()]]->play( str_alert_state ); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // _ __ __ _ ___ ___ _ _ ___ ___ ___ ___ ___ ___ _ _ ___ // /_\ \ \ / / /_\ | _ \ | __| | \| | | __| / __| / __| / __| / __| | __| | \| | | __| // / _ \ \ \/\/ / / _ \ | / | _| | .` | | _| \__ \ \__ \ \__ \ | (__ | _| | .` | | _| // /_/ \_\ \_/\_/ /_/ \_\ |_|_\ |___| |_|\_| |___| |___/ |___/ |___/ \___| |___| |_|\_| |___| // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class cAwarenessScene : cScene { function new_object() { return new cAwarenessSceneObject(); } function init( str_scenedef, s_scenedef, e_align, a_ents, b_test_run ) { cScene::init( str_scenedef, s_scenedef, e_align, a_ents, b_test_run ); } function play( str_awareness_state = "low_alert" ) { self notify( "new_state" ); self endon( "new_state" ); if ( get_valid_objects().size > 0 ) { foreach ( o_obj in _a_objects ) { thread [[o_obj]]->play( str_awareness_state ); } level flagsys::set( _str_name + "_playing" ); _str_state = "play"; wait_till_scene_ready(); thread _call_state_funcs( str_awareness_state ); array::flagsys_wait_any_flag( _a_objects, "done", "main_done" ); if ( is_looping() ) { if ( has_init_state() ) { // TODO: do this on return to unaware? //level flagsys::clear( _str_name + "_playing" ); //thread initialize(); } } else { thread stop(); } } else { thread stop( false, true ); } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // _ _ ___ _ ___ ___ ___ ___ // | || | | __| | | | _ \ | __| | _ \ / __| // | __ | | _| | |__ | _/ | _| | / \__ \ // |_||_| |___| |____| |_| |___| |_|_\ |___/ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function get_existing_ent( str_name, b_spawner_only = false, b_nodes_and_structs = false ) { e = undefined; if ( b_spawner_only ) { e_array = GetSpawnerArray( str_name, "script_animname" ); // a spawner exists with script_animname if ( e_array.size == 0 ) { e_array = GetSpawnerArray( str_name, "targetname" ); // lastly grab any ent with targetname } Assert( e_array.size <= 1, "Multiple spawners found." ); foreach ( ent in e_array ) { if ( !isdefined( ent.isDying ) ) { e = ent; break; } } } else { e = GetEnt( str_name, "animname", false ); // entity already exists if ( !is_valid_ent( e ) ) { e = GetEnt( str_name, "script_animname" ); // a spawner exists with script_animname if ( !is_valid_ent( e ) ) { e = GetEnt( str_name + "_ai", "targetname", true ); // any already spawned AI if ( !is_valid_ent( e ) ) { e = GetEnt( str_name + "_vh", "targetname", true ); // any already spawned vehicles if ( !is_valid_ent( e ) ) { e = GetEnt( str_name, "targetname", true ); // any spawned ents that don't have a targetname suffix if ( !is_valid_ent( e ) ) { e = GetEnt( str_name, "targetname" ); // lastly grab any ent with targetname if ( !is_valid_ent( e ) && b_nodes_and_structs ) { e = GetNode( str_name, "targetname" ); // if no ent, grab node with targetname if ( !is_valid_ent( e ) ) { e = struct::get( str_name, "targetname" ); // if no node, grab struct with targetname } } } } } } } } if ( !is_valid_ent( e ) ) { e = undefined; } return e; } function is_valid_ent( ent ) { return ( isdefined( ent ) && ( ( !isdefined( ent.isDying ) && !ent ai::is_dead_sentient() ) || self._s.IgnoreAliveCheck === true ) ); } function synced_delete() { self endon( "death" ); self.isDying = true; if ( isdefined( self.targetname ) ) { self.targetname = self.targetname + "_sync_deleting"; } if ( isdefined( self.animname ) ) { self.animname = self.animname + "_sync_deleting"; } if ( isdefined( self.script_animname ) ) { self.script_animname = self.script_animname + "_sync_deleting"; } if(!IsPlayer(self)) { SetHideonClientWhenScriptedAnimCompleted( self ); self StopAnimScripted(); } else { {wait(.05);}; self Ghost(); } self NotSolid(); if(isAlive(self)) { if(isSentient( self )) { self.ignoreall = true; } if(IsActor(self)) { self PathMode("dont move"); } } wait 1; //this will make the server wait until the client syned the transition to the next shot self delete(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // _ _ _____ ___ _ ___ _____ __ __ // | | | | |_ _| |_ _| | | |_ _| |_ _| \ \ / / // | |_| | | | | | | |__ | | | | \ V / // \___/ |_| |___| |____| |___| |_| |_| // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function autoexec __init__sytem__() { system::register("scene",&__init__,&__main__,undefined); } function __init__() { /* INIT SYSTEM VARS */ level.scene_object_id = 0; level.active_scenes = []; level.sceneSkippedCount = 0; level.wait_for_streamer_hint_scenes = []; streamerRequest( "clear" ); foreach ( s_scenedef in struct::get_script_bundles( "scene" ) ) { s_scenedef.editaction = undefined; // only used in the asset editor s_scenedef.newobject = undefined; // only used in the asset editor if ( IsString( s_scenedef.FemaleBundle ) ) { // Set the MaleBundle attribute of female bundles so they know which male bundle they are associated with s_female_bundle = struct::get_script_bundle( "scene", s_scenedef.FemaleBundle ); s_female_bundle.MaleBundle = s_scenedef.name; s_scenedef.s_female_bundle = s_female_bundle; s_female_bundle.s_male_bundle = s_scenedef; } if ( IsString( s_scenedef.NextSceneBundle ) ) { foreach ( i, s_object in s_scenedef.objects ) { // Disable transition fx between shots in chained bundles if ( ( s_object.type === "player" ) ) { s_object.DisableTransitionOut = true; } } s_next_bundle = struct::get_script_bundle( "scene", s_scenedef.NextSceneBundle ); s_next_bundle.DontSync = true; foreach ( i, s_object in s_next_bundle.objects ) { // Disable transition fx between shots in chained bundles if ( ( s_object.type === "player" ) ) { s_object.DisableTransitionIn = true; } //let he next scene know that it is a isCutScene (a scene was played before it); s_object.isCutScene = true; } // Do the same for the female bundle if one exists if ( isdefined( s_next_bundle.FemaleBundle ) ) { s_next_female_bundle = struct::get_script_bundle( "scene", s_next_bundle.FemaleBundle ); if ( isdefined( s_next_female_bundle ) ) { s_next_female_bundle.DontSync = true; foreach ( i, s_object in s_next_female_bundle.objects ) { // Disable transition fx between shots in chained bundles if ( ( s_object.type === "player" ) ) { s_object.DisableTransitionIn = true; } //let he next scene know that it is a isCutScene (a scene was played before it); s_object.isCutScene = true; } } } } // if this bundle has a streamer hint then loop through the next bundles // and give them the same streamer hint if ( IsString( s_scenedef.streamerHint ) ) { s_cur_bundle = s_scenedef; while( true ) { s_cur_bundle._endStreamerHint = s_scenedef.streamerHint; if ( IsString( s_cur_bundle.NextSceneBundle ) ) { s_cur_bundle = struct::get_script_bundle( "scene", s_cur_bundle.NextSceneBundle ); } else { break; } } } foreach ( i, s_object in s_scenedef.objects ) { if ( ( s_object.type === "player" ) ) { if(!isdefined(s_object.cameratween))s_object.cameratween=0; if ( isdefined( s_object.player ) ) { s_object.player--; // adjust for zero-based level.players index } else { s_object.player = 0; } s_object.name = "player " + ( s_object.player + 1 ); s_object.NewPlayerMethod = true; // Fully switching over to new method, no longer supporting ol-style player linkto method } else { s_object.player = undefined; } } if ( s_scenedef.vmtype == "both" && !s_scenedef is_igc() ) { n_clientbits = GetMinBitCountForNum( 3 ); /# n_clientbits = GetMinBitCountForNum( 6 ); #/ clientfield::register( "world", s_scenedef.name, 1, n_clientbits, "int" ); } } clientfield::register( "toplayer", "postfx_igc", 1, 2, "counter" ); clientfield::register( "world", "in_igc", 1, 4, "int" ); clientfield::register( "toplayer", "player_scene_skip_completed", 1, 2, "counter" ); clientfield::register( "allplayers", "player_scene_animation_skip", 1, 2, "counter" ); clientfield::register( "actor", "player_scene_animation_skip", 1, 2, "counter" ); clientfield::register( "vehicle", "player_scene_animation_skip", 1, 2, "counter" ); clientfield::register( "scriptmover", "player_scene_animation_skip", 1, 2, "counter" ); callback::on_connect( &on_player_connect ); callback::on_disconnect( &on_player_disconnect ); } function remove_invalid_scene_objects( s_scenedef ) { a_invalid_object_indexes = []; foreach ( i, s_object in s_scenedef.objects ) { if ( !isdefined( s_object.name ) && !isdefined( s_object.model ) && !( s_object.type === "player" ) ) { if ( !isdefined( a_invalid_object_indexes ) ) a_invalid_object_indexes = []; else if ( !IsArray( a_invalid_object_indexes ) ) a_invalid_object_indexes = array( a_invalid_object_indexes ); a_invalid_object_indexes[a_invalid_object_indexes.size]=i;; } } for ( i = a_invalid_object_indexes.size - 1; i >= 0 ; i-- ) { ArrayRemoveIndex( s_scenedef.objects, a_invalid_object_indexes[i] ); } return s_scenedef; } function __main__() { /* RUN INSTANCES */ a_instances = ArrayCombine( struct::get_array( "scriptbundle_scene", "classname" ), struct::get_array( "scriptbundle_fxanim", "classname" ), false, false ); foreach ( s_instance in a_instances ) { if ( isdefined( s_instance.linkto ) ) { s_instance thread _scene_link(); } if ( isdefined( s_instance.script_flag_set ) ) { level flag::init( s_instance.script_flag_set ); } if ( isdefined( s_instance.scriptgroup_initscenes ) ) { foreach ( trig in GetEntArray( s_instance.scriptgroup_initscenes, "scriptgroup_initscenes" ) ) { s_instance thread _trigger_init( trig ); } } if ( isdefined( s_instance.scriptgroup_playscenes ) ) { foreach ( trig in GetEntArray( s_instance.scriptgroup_playscenes, "scriptgroup_playscenes" ) ) { s_instance thread _trigger_play( trig ); } } if ( isdefined( s_instance.scriptgroup_stopscenes ) ) { foreach ( trig in GetEntArray( s_instance.scriptgroup_stopscenes, "scriptgroup_stopscenes" ) ) { s_instance thread _trigger_stop( trig ); } } } level thread on_load_wait(); level thread run_instances(); } function private _scene_link() { self.e_scene_link = util::spawn_model( "tag_origin", self.origin, self.angles ); e_linkto = GetEnt( self.linkto, "linkname" ); self.e_scene_link LinkTo( e_linkto ); util::waittill_any_ents_two( self, "death", e_linkto, "death" ); // Delete link ent when either the scene root entity dies or the entity that it's linked to self.e_scene_link Delete(); } function on_load_wait() { // wait for client script so "both" type scenes will work properly on load. util::wait_network_frame(); util::wait_network_frame(); level flagsys::set( "scene_on_load_wait" ); } function run_instances() { foreach ( s_instance in struct::get_script_bundle_instances( "scene" ) ) { if ( (isdefined(s_instance.spawnflags)&&((s_instance.spawnflags & 2) == 2)) ) { s_instance thread play(); } else if ( (isdefined(s_instance.spawnflags)&&((s_instance.spawnflags & 1) == 1)) ) { s_instance thread init(); } } } function _trigger_init( trig ) { trig endon( "death" ); trig trigger::wait_till(); a_ents = []; if ( get_player_count( self.scriptbundlename ) > 0 ) { if ( IsPlayer( trig.who ) ) { a_ents[ 0 ] = trig.who; } } self thread _init_instance( undefined, a_ents ); } function _trigger_play( trig ) { trig endon( "death" ); do { trig trigger::wait_till(); a_ents = []; if ( get_player_count( self.scriptbundlename ) > 0 ) { if ( IsPlayer( trig.who ) ) { a_ents[ 0 ] = trig.who; } } self thread play( a_ents ); } while ( ( isdefined( get_scenedef( self.scriptbundlename ).looping ) && get_scenedef( self.scriptbundlename ).looping ) ); } function _trigger_stop( trig ) { trig endon( "death" ); trig trigger::wait_till(); self thread stop(); } /@ "Summary: Adds a function to be called when a scene starts" "SPMP: shared" "Name: add_scene_func( str_scenedef, func, str_state = "play" )" "CallOn: level" "MandatoryArg: Name of scene" "MandatoryArg: function to call when scene starts" "OptionalArg: [str_state] set to "init" or "done" if you want to the function to get called in one of those states" "Example: level scene::init( "my_scenes", "targetname" );" @/ function add_scene_func( str_scenedef, func, str_state = "play", ... ) { /# Assert( isdefined( get_scenedef( str_scenedef ) ), "Trying to add a scene function for scene '" + str_scenedef + "' that doesn't exist." ); #/ if(!isdefined(level.scene_funcs))level.scene_funcs=[]; if(!isdefined(level.scene_funcs[ str_scenedef ]))level.scene_funcs[ str_scenedef ]=[]; if(!isdefined(level.scene_funcs[ str_scenedef ][ str_state ]))level.scene_funcs[ str_scenedef ][ str_state ]=[]; array::add( level.scene_funcs[ str_scenedef ][ str_state ], Array( func, vararg ), false ); } /@ "Summary: Removes a function to be called when a scene starts" "SPMP: shared" "Name: remove_scene_func( str_scenedef, func, str_state = "play" )" "CallOn: level" "MandatoryArg: Name of scene" "MandatoryArg: function to remove" "OptionalArg: [str_state] set to "init" or "done" if you want to the function to get removed from one of those states" "Example: level scene::init( "my_scenes", "targetname" );" @/ function remove_scene_func( str_scenedef, func, str_state = "play" ) { /# Assert( isdefined( get_scenedef( str_scenedef ) ), "Trying to remove a scene function for scene '" + str_scenedef + "' that doesn't exist." ); #/ if(!isdefined(level.scene_funcs))level.scene_funcs=[]; if ( isdefined( level.scene_funcs[ str_scenedef ] ) && isdefined( level.scene_funcs[ str_scenedef ][ str_state ] ) ) { for ( i = level.scene_funcs[ str_scenedef ][ str_state ].size - 1; i >= 0; i-- ) { if ( level.scene_funcs[ str_scenedef ][ str_state ][ i ][ 0 ] == func ) { ArrayRemoveIndex( level.scene_funcs[ str_scenedef ][ str_state ], i ); } } } } function get_scenedef( str_scenedef ) { return struct::get_script_bundle( "scene", str_scenedef ); } function get_scenedefs( str_type = "scene" ) { a_scenedefs = []; foreach ( s_scenedef in struct::get_script_bundles( "scene" ) ) { if ( s_scenedef.sceneType == str_type ) { if ( !isdefined( a_scenedefs ) ) a_scenedefs = []; else if ( !IsArray( a_scenedefs ) ) a_scenedefs = array( a_scenedefs ); a_scenedefs[a_scenedefs.size]=s_scenedef;; } } return a_scenedefs; } /@ "Summary: Spawns a scene" "SPMP: shared" "Name: spawn( str_scenedef, v_origin, v_angles, ents )" "CallOn: NA "MandatoryArg: Name of scene to spawn" "OptionalArg: [v_origin] The origin to spawn the scene at - defaults to (0, 0, 0)" "OptionalArg: [v_angles] The angles to spawn the scene at - defaults to (0, 0, 0)" "OptionalArg: [a_ents] Entities to use for the scene" "Example: level scene::spawn( "my_scene", (99, 45, 156) );" "Name: spawn( str_scenedef, ents, v_origin, v_angles )" "CallOn: NA "MandatoryArg: Name of scene to spawn" "OptionalArg: [a_ents] Entities to use for the scene" "OptionalArg: [v_origin] The origin to spawn the scene at - defaults to (0, 0, 0)" "OptionalArg: [v_angles] The angles to spawn the scene at - defaults to (0, 0, 0)" "Example: level scene::spawn( "my_scene", array( my_ent1, my_ent2 ) );" @/ function spawn( arg1, arg2, arg3, arg4, b_test_run ) { str_scenedef = arg1; Assert( isdefined( str_scenedef ), "Cannot create a scene without a scene def." ); if ( IsVec( arg2 ) ) { v_origin = arg2; v_angles = arg3; a_ents = arg4; } else // overloaded the params so you can put them in different orders { a_ents = arg2; v_origin = arg3; v_angles = arg4; } s_instance = SpawnStruct(); s_instance.origin = ( isdefined( v_origin ) ? v_origin : (0, 0, 0) ); s_instance.angles = ( isdefined( v_angles ) ? v_angles : (0, 0, 0) ); s_instance.classname = "scriptbundle_scene"; s_instance.scriptbundlename = str_scenedef; s_instance struct::init(); s_instance scene::init( str_scenedef, a_ents, undefined, b_test_run ); return s_instance; } /@ "Summary: Initializes a scene or multiple scenes" "SPMP: shared" "Name: init( str_val, str_key, ents )" "CallOn: level using KVP to specify the scene instances" "MandatoryArg: value of the KVP of the scene entity" "MandatoryArg: key of the KVP of the scene entity" "OptionalArg: [ents] override the entities used for this scene" "Example: level scene::init( "my_scenes", "targetname" );" "Name: init( str_scenedef, ents )" "CallOn: level" "MandatoryArg: specify the scene name, will play all instances of this scene" "OptionalArg: [ents] override the entities used for this scene" "Example: level scene::init( "level1_scene_3" );" "Name: init( str_scenedef, ents )" "CallOn: Any entity (script_origin, script_struct, ai, script_model, script_brushmodel, player)" "OptionalArg: [str_scenedef] specify the scene name if needed" "OptionalArg: [ents] override the entities used for this scene" "Example: e_scene_root scene::init( "level1_scene_3" );" "Name: init( ents, str_scenedef )" "CallOn: Any entity (script_origin, script_struct, ai, script_model, script_brushmodel, player)" "OptionalArg: [ents] override the entities used for this scene" "OptionalArg: [str_scenedef] specify the scene name if needed" "Example: s_scene_object scene::init( array( e_guy1, e_guy2 ) );" @/ function init( arg1, arg2, arg3, b_test_run ) { if ( self == level ) { if ( IsString( arg1 ) ) { if ( IsString( arg2 ) ) { str_value = arg1; str_key = arg2; a_ents = arg3; } else { str_value = arg1; a_ents = arg2; } if ( isdefined( str_key ) ) { a_instances = struct::get_array( str_value, str_key ); /# Assert( a_instances.size, "No scene instances with KVP '" + str_key + "'/'" + str_value + "'." ); #/ } else { a_instances = struct::get_array( str_value, "targetname" ); if ( !a_instances.size ) { a_instances = struct::get_array( str_value, "scriptbundlename" ); } } if ( !a_instances.size ) { _init_instance( str_value, a_ents, b_test_run ); } else { foreach ( s_instance in a_instances ) { if ( isdefined( s_instance ) ) { s_instance thread _init_instance( undefined, a_ents, b_test_run ); } } } } } else { if ( IsString( arg1 ) ) { _init_instance( arg1, arg2, b_test_run ); } else { _init_instance( arg2, arg1, b_test_run ); } return self; } } function _init_instance( str_scenedef, a_ents, b_test_run = false ) { level flagsys::wait_till( "scene_on_load_wait" ); if(!isdefined(str_scenedef))str_scenedef=self.scriptbundlename; /# if ( array().size && !IsInArray( array(), str_scenedef ) ) { return; } #/ s_bundle = get_scenedef( str_scenedef ); /# Assert( isdefined( str_scenedef ), "Scene at (" + ( isdefined( self.origin ) ? self.origin : "level" ) + ") is missing its scene def." ); Assert( isdefined( s_bundle ), "Scene at (" + ( isdefined( self.origin ) ? self.origin : "level" ) + ") is using a scene name '" + str_scenedef + "' that doesn't exist." ); #/ o_scene = get_active_scene( str_scenedef ); if ( !isdefined( o_scene ) ) { if ( s_bundle.scenetype == "awareness" ) { o_scene = new cAwarenessScene(); } else { o_scene = new cScene(); } s_bundle = _load_female_scene( s_bundle, a_ents ); [[o_scene]]->init( s_bundle.name, s_bundle, self, a_ents, b_test_run ); } else { thread [[o_scene]]->initialize( a_ents, true ); } return o_scene; } function private _load_female_scene( s_bundle, a_ents ) { /* Check if this bundle has a player object */ b_has_player = false; foreach ( s_object in s_bundle.objects ) { if ( !isDefined( s_object ) ) continue; if ( ( s_object.type === "player" ) ) { b_has_player = true; break; } } /* Check if if a player was passed in to use for the scene */ if ( b_has_player ) { e_player = undefined; if ( IsPlayer( a_ents ) ) { e_player = a_ents; } else if ( IsArray( a_ents ) ) { foreach ( ent in a_ents ) { if ( IsPlayer( ent ) ) { e_player = ent; break; } } } /* Default to first player none are passed in */ if ( !isdefined( e_player ) ) { e_player = level.activeplayers[0]; } if ( IsPlayer( e_player ) && e_player util::is_female() ) { if ( isdefined( s_bundle.FemaleBundle ) ) { s_female_bundle = struct::get_script_bundle( "scene", s_bundle.FemaleBundle ); if ( isdefined( s_female_bundle ) ) { return s_female_bundle; } } } } return s_bundle; } /@ "Summary: Plays a scene or multiple scenes" "SPMP: shared" "Name: play( str_val, str_key, ents )" "CallOn: level using KVP to specify the scene instances" "MandatoryArg: value of the KVP of the scene entity" "MandatoryArg: key of the KVP of the scene entity" "OptionalArg: [ents] override the entities used for this scene" "Example: level scene::play( "my_scenes", "targetname" );" "Name: play( str_scenedef, ents )" "CallOn: level" "MandatoryArg: specify the scene name, will play all instances of this scene" "OptionalArg: [ents] override the entities used for this scene" "Example: level scene::play( "level1_scene_3" );" "Name: play( str_scenedef, ents )" "CallOn: Any entity (script_origin, script_struct, ai, script_model, script_brushmodel, player)" "OptionalArg: [str_scenedef] specify the scene name if needed" "OptionalArg: [ents] override the entities used for this scene" "Example: e_scene_root scene::play( "level1_scene_3" );" "Name: play( ents, str_scenedef )" "CallOn: Any entity (script_origin, script_struct, ai, script_model, script_brushmodel, player)" "OptionalArg: [ents] override the entities used for this scene" "OptionalArg: [str_scenedef] specify the scene name if needed" "Example: s_scene_object scene::play( array( e_guy1, e_guy2 ) );" @/ function play( arg1, arg2, arg3, b_test_run = false, str_state, str_mode = "" ) { /# if( GetDvarInt("debug_scene") > 0) { if(isdefined(arg1) && IsString(arg1) ) { PrintTopRightln("scene::play : " + arg1); } else { PrintTopRightln("scene::play"); } } #/ if(isdefined(arg1) && IsString(arg1) && arg1 == "p7_fxanim_zm_castle_rocket_bell_tower_bundle") { arg1 = arg1; } s_tracker = SpawnStruct(); s_tracker.n_scene_count = 1; if ( self == level ) { if ( IsString( arg1 ) ) { if ( IsString( arg2 ) ) { str_value = arg1; str_key = arg2; a_ents = arg3; } else { str_value = arg1; a_ents = arg2; } str_scenedef = str_value; if ( isdefined( str_key ) ) { a_instances = struct::get_array( str_value, str_key ); str_scenedef = undefined; // use struct scenedef /# Assert( a_instances.size, "No scene instances with KVP '" + str_key + "'/'" + str_value + "'." ); #/ } else { a_instances = struct::get_array( str_value, "targetname" ); if ( !a_instances.size ) { a_instances = struct::get_array( str_value, "scriptbundlename" ); } else { str_scenedef = undefined; // use struct scenedef } } if ( isdefined( str_scenedef ) ) { a_active_instances = get_active_scenes( str_scenedef ); a_instances = ArrayCombine( a_active_instances, a_instances, false, false ); } if ( !a_instances.size ) { self thread _play_instance( s_tracker, str_scenedef, a_ents, b_test_run, undefined, str_mode ); } else { s_tracker.n_scene_count = a_instances.size; foreach ( s_instance in a_instances ) { if ( isdefined( s_instance ) ) { s_instance thread _play_instance( s_tracker, str_scenedef, a_ents, b_test_run, str_state, str_mode ); } } } } } else { if ( IsString( arg1 ) ) { self thread _play_instance( s_tracker, arg1, arg2, b_test_run, str_state, str_mode ); } else { self thread _play_instance( s_tracker, arg2, arg1, b_test_run, str_state, str_mode ); } } for ( i = 0; i < s_tracker.n_scene_count; i++ ) { s_tracker waittill( "scene_done" ); } } function _play_instance( s_tracker, str_scenedef, a_ents, b_test_run = false, str_state, str_mode ) { /# if ( array().size && !IsInArray( array(), str_scenedef ) ) { return; } #/ if(!isdefined(str_scenedef))str_scenedef=self.scriptbundlename; if ( self.scriptbundlename === str_scenedef ) // Radiant placed scene, only play once unless specified to play more than once { if ( !( isdefined( self.script_play_multiple ) && self.script_play_multiple ) ) { if ( ( isdefined( self.scene_played ) && self.scene_played ) && !b_test_run ) { waittillframeend; while ( is_playing( str_scenedef ) ) { {wait(.05);}; } s_tracker notify( "scene_done" ); return; } } self.scene_played = true; } o_scene = _init_instance( str_scenedef, a_ents, b_test_run ); if ( IsDefined(o_scene) ) { if( (!isdefined(str_mode) || str_mode == "") && [[o_scene]]->should_skip_linked_to_players_scene() ) { skip_scene( o_scene._s.name, false, false, true); } thread [[o_scene]]->play( str_state, a_ents, b_test_run, str_mode ); } self waittillmatch( "scene_done", str_scenedef ); if ( isdefined( self ) ) { if ( isdefined( self.scriptbundlename ) && ( isdefined( get_scenedef( self.scriptbundlename ).looping ) && get_scenedef( self.scriptbundlename ).looping ) ) { self.scene_played = false; } if ( isdefined( self.script_flag_set ) ) { level flag::set( self.script_flag_set ); } } s_tracker notify( "scene_done" ); } /@ "Summary: Skipts a scene or multiple scenes to the end state (last frame or looping animation). Look at scene::play() for all the various ways this can be called." "SPMP: shared" "OptionalArg: [n_time] Value between 0 and 1 to only skip through a portion of the scene. 0 will start at the beginning of the scene, 1 skips completely to the end." "Example: level scene::skipto_end( "my_scene" );" @/ function skipto_end( arg1, arg2, arg3, n_time, b_include_players = false ) { str_mode = "skipto"; if ( !b_include_players ) { str_mode += "_noplayers"; } if ( isdefined( n_time ) ) { str_mode += ":" + n_time; } play( arg1, arg2, arg3, false, undefined, str_mode ); } /@ "Summary: Skipts a scene or multiple scenes to the end state (last frame or looping animation), but skips AI. Look at scene::play() for all the various ways this can be called." "SPMP: shared" "OptionalArg: [n_time] Value between 0 and 1 to only skip through a portion of the scene. 0 will start at the beginning of the scene, 1 skips completely to the end." "Example: level scene::skipto_end_noai( "my_scene" );" @/ function skipto_end_noai( arg1, arg2, arg3, n_time ) { str_mode = "skipto_noai_noplayers"; if ( isdefined( n_time ) ) { str_mode += ":" + n_time; } play( arg1, arg2, arg3, false, undefined, str_mode ); } /@ "Summary: Stops a scene or multiple scenes" "SPMP: shared" "Name: stop( str_val, str_key, b_clear )" "CallOn: level using KVP to specify the scene instances" "MandatoryArg: value of the KVP of the scene entity" "MandatoryArg: key of the KVP of the scene entity" "OptionalArg: [b_clear] optionally delete the ents if they were spawned by the scene, regardless of options in scene definition" "Example: level scene::stop( "my_scenes", "targetname" );" "Name: stop( str_scenedef, b_clear )" "CallOn: level" "MandatoryArg: specify the scene name, will stop all instances of this scene" "OptionalArg: [b_clear] optionally delete the ents if they were spawned by the scene, regardless of options in scene definition" "Example: level scene::stop( "level1_scene_3" );" "Name: stop( str_scenedef, b_clear )" "CallOn: Any entity (script_origin, script_struct, ai, script_model, script_brushmodel, player)" "OptionalArg: [str_scenedef] specify the scene name if multiple scenes are running on the entity" "OptionalArg: [b_clear] optionally delete the ents if they were spawned by the scene, regardless of options in scene definition" "Example: e_my_scene scene::stop( "level1_scene_3" );" "Name: stop( b_clear, str_scenedef )" "CallOn: Any entity (script_origin, script_struct, ai, script_model, script_brushmodel, player)" "OptionalArg: [b_clear] optionally delete the ents if they were spawned by the scene, regardless of options in scene definition" "OptionalArg: [str_scenedef] specify the scene name if multiple scenes are running on the entity" "Example: s_scene_object scene::stop( true );" @/ function stop( arg1, arg2, arg3 ) { if ( self == level ) { if ( IsString( arg1 ) ) { if ( IsString( arg2 ) ) { str_value = arg1; str_key = arg2; b_clear = arg3; } else { str_value = arg1; b_clear = arg2; } if ( isdefined( str_key ) ) { a_instances = struct::get_array( str_value, str_key ); /# Assert( a_instances.size, "No scene instances with KVP '" + str_key + "'/'" + str_value + "'." ); #/ str_value = undefined; } else { a_instances = struct::get_array( str_value, "targetname" ); if ( !a_instances.size ) { a_instances = get_active_scenes( str_value ); } else { str_value = undefined; } } foreach ( s_instance in ArrayCopy( a_instances ) ) { if ( isdefined( s_instance ) ) { s_instance _stop_instance( b_clear, str_value ); } } } } else { if ( IsString( arg1 ) ) { _stop_instance( arg2, arg1 ); } else { _stop_instance( arg1 ); } } } function _stop_instance( b_clear = false, str_scenedef ) { if ( isdefined( self.scenes ) ) { foreach ( o_scene in ArrayCopy( self.scenes ) ) { str_scene_name = [[o_scene]]->get_name(); if ( !isdefined( str_scenedef ) || ( str_scene_name == str_scenedef ) ) { thread [[o_scene]]->stop( b_clear ); } } } } function has_init_state( str_scenedef ) { s_scenedef = get_scenedef( str_scenedef ); foreach ( s_obj in s_scenedef.objects ) { if ( !( isdefined( s_obj.disabled ) && s_obj.disabled ) && s_obj _has_init_state() ) { return true; } } return false; } function _has_init_state() { return ( ( isdefined( self.spawnoninit ) && self.spawnoninit ) || isdefined( self.initanim ) || isdefined( self.initanimloop ) || ( isdefined( self.firstframe ) && self.firstframe ) ); } /@ "Summary: returns the number of props defined for a scene" "SPMP: shared" "Name: get_prop_count( str_scenedef )" "CallOn: Any" "MandatoryArg: scene definition name (from gdt)" "Example: level scene::get_prop_count( "my_scene" );" "Name: get_prop_count()" "CallOn: scene object" "Example: s_scene scene::get_prop_count();" @/ function get_prop_count( str_scenedef ) { return _get_type_count( "prop", str_scenedef ); } /@ "Summary: returns the number of vehicles defined for a scene" "SPMP: shared" "Name: get_vehicle_count( str_scenedef )" "CallOn: Any" "MandatoryArg: scene definition name (from gdt)" "Example: level scene::get_vehicle_count( "my_scene" );" "Name: get_vehicle_count()" "CallOn: scene object" "Example: s_scene scene::get_vehicle_count();" @/ function get_vehicle_count( str_scenedef ) { return _get_type_count( "vehicle", str_scenedef ); } /@ "Summary: returns the number of actors defined for a scene" "SPMP: shared" "Name: get_actor_count( str_scenedef )" "CallOn: Any" "MandatoryArg: scene definition name (from gdt)" "Example: level scene::get_actor_count( "my_scene" );" "Name: get_actor_count()" "CallOn: scene object" "Example: s_scene scene::get_actor_count();" @/ function get_actor_count( str_scenedef ) { return _get_type_count( "actor", str_scenedef ); } /@ "Summary: returns the number of players defined for a scene" "SPMP: shared" "Name: get_player_count( str_scenedef )" "CallOn: Any" "MandatoryArg: scene definition name (from gdt)" "Example: level scene::get_player_count( "my_scene" );" "Name: get_player_count()" "CallOn: scene object" "Example: s_scene scene::get_player_count();" @/ function get_player_count( str_scenedef ) { return _get_type_count( "player", str_scenedef ); } function _get_type_count( str_type, str_scenedef ) { s_scenedef = ( isdefined( str_scenedef ) ? get_scenedef( str_scenedef ) : get_scenedef( self.scriptbundlename ) ); n_count = 0; foreach ( s_obj in s_scenedef.objects ) { if ( isdefined( s_obj.type ) ) { if ( ToLower( s_obj.type ) == ToLower( str_type ) ) { n_count++; } } } return n_count; } /@ "Summary: Checks if a scene is playing" "SPMP: shared" "Name: is_active( str_scenedef )" "CallOn: level or a scene instance" "OptionalArg: [str_scenedef] The name of the scene to check" "Example: level scene::is_active( "my_scene" );" "Example: s_scene scene::is_active();" @/ function is_active( str_scenedef ) { if ( self == level ) { return ( get_active_scenes( str_scenedef ).size > 0 ); } else { return ( isdefined( get_active_scene( str_scenedef ) ) ); } } /@ "Summary: Checks if a scene is playing" "SPMP: shared" "Name: is_playing( str_scenedef )" "OptionalArg: [str_scenedef] The name of the scene to check" "Example: s_scene scene::is_playing( "my_scene" );" "Example: s_scene scene::is_playing();" @/ function is_playing( str_scenedef ) { if ( self == level ) { return ( level flagsys::get( str_scenedef + "_playing" ) ); } else { if(!isdefined(str_scenedef))str_scenedef=self.scriptbundlename; o_scene = get_active_scene( str_scenedef ); if ( isdefined( o_scene ) ) { return ( ( o_scene._str_state === "play" ) ); } } return false; } /@ "Summary: Checks if a scene is ready" "SPMP: shared" "Name: is_ready( str_scenedef )" "OptionalArg: [str_scenedef] The name of the scene to check" "Example: s_scene scene::is_ready( "my_scene" );" "Example: s_scene scene::is_ready();" @/ function is_ready( str_scenedef ) { if ( self == level ) { return ( level flagsys::get( str_scenedef + "_ready" ) ); } else { if(!isdefined(str_scenedef))str_scenedef=self.scriptbundlename; o_scene = get_active_scene( str_scenedef ); if ( isdefined( o_scene ) ) { return ( o_scene flagsys::get( "ready" ) ); } } return false; } function get_active_scenes( str_scenedef ) { if(!isdefined(level.active_scenes))level.active_scenes=[]; if ( isdefined( str_scenedef ) ) { return ( isdefined( level.active_scenes[ str_scenedef ] ) ? level.active_scenes[ str_scenedef ] : [] ); } else { a_active_scenes = []; foreach ( str_scenedef, _ in level.active_scenes ) { a_active_scenes = ArrayCombine( a_active_scenes, level.active_scenes[ str_scenedef ], false, false ); } return a_active_scenes; } } function get_active_scene( str_scenedef ) { if ( isdefined( str_scenedef ) && isdefined( self.scenes ) ) { foreach ( o_scene in self.scenes ) { if ( [[o_scene]]->get_name() == str_scenedef ) { return o_scene; } } } } //TODO: this should be turned into something more automatic and part of the system function delete_scene_data( str_scenename ) { if(IsDefined( level.scriptbundles["scene"][str_scenename] )) { level.scriptbundles["scene"][str_scenename] = undefined; } } function is_igc() { return ( IsString( self.cameraswitcher ) || IsString( self.extraCamSwitcher1 ) || IsString( self.extraCamSwitcher2 ) || IsString( self.extraCamSwitcher3 ) || IsString( self.extraCamSwitcher4 ) ); } function scene_disable_player_stuff( b_hide_hud = true ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("scene::scene_disable_player_stuff"); } #/ self notify( "scene_disable_player_stuff" ); self notify( "kill_hint_text" ); self DisableOffhandWeapons(); if ( b_hide_hud ) { set_igc_active( true ); level notify( "disable_cybercom", self, true ); self util::show_hud( 0 ); util::wait_network_frame(); // let "in_igc" get set so deleted weapon objects can bypass HUD effects self notify( "delete_weapon_objects" ); } } function scene_enable_player_stuff( b_hide_hud = true ) { /# if( GetDvarInt("debug_scene") > 0) { PrintTopRightln("scene::scene_enable_player_stuff"); } #/ self endon( "scene_disable_player_stuff" ); self endon( "disconnect" ); wait .5; self EnableOffhandWeapons(); if ( b_hide_hud ) { set_igc_active( false ); level notify( "enable_cybercom", self ); self notify( "scene_enable_cybercom" ); //TU1: Need to track when the scene system is turning it on per player. self util::show_hud( 1 ); } } function updateIGCViewtime(b_in_igc) { if (b_in_igc && !isDefined(level.igcStartTime)) { level.igcStartTime = GetTime(); } else if (!b_in_igc && isDefined(level.igcStartTime)) { igcViewtimeSec = GetTime() - level.igcStartTime; level.igcStartTime = undefined; foreach (player in level.players) { if (!isDefined(player.totalIGCViewtime)) { player.totalIGCViewtime = 0; } player.totalIGCViewtime += int(igcViewtimeSec / 1000); } } } function set_igc_active( b_in_igc ) { n_ent_num = self GetEntityNumber(); n_players_in_igc_field = level clientfield::get( "in_igc" ); if ( b_in_igc ) { n_players_in_igc_field |= ( 1 << n_ent_num ); } else { n_players_in_igc_field &= ~( 1 << n_ent_num ); } updateIGCViewtime(b_in_igc); level clientfield::set( "in_igc", n_players_in_igc_field ); /# //PrintTopRightln( "SERVER " + n_ent_num + ": setting 'in_igc' to " + b_in_igc, RED, -1 ); #/ } function is_igc_active() { n_players_in_igc = level clientfield::get( "in_igc" ); n_entnum = self GetEntityNumber(); return ( n_players_in_igc & ( 1 << n_entnum ) ); } function is_capture_mode() { str_mode = GetDvarString( "scene_menu_mode", "default" ); if ( IsSubStr( str_mode, "capture" ) ) { return true; } else { return false; } } function should_spectate_on_join() { return ( isdefined( level.scene_should_spectate_on_hot_join ) && level.scene_should_spectate_on_hot_join ); } function wait_until_spectate_on_join_completes() { while(( isdefined( level.scene_should_spectate_on_hot_join ) && level.scene_should_spectate_on_hot_join )) { wait 0.05; } } //-----------------------------------------------------------------SCENE-SKIPPING-------------------------------------------------------------------------------- function skip_scene( scene_name, b_sequence, b_player_scene, b_check_linked_scene ) { if(!isdefined(scene_name)) { if(isdefined(level.shared_scene_sequence_name)) { scene_name = level.shared_scene_sequence_name; } if(!isdefined(scene_name)) { if(isdefined(level.players) && isdefined(level.players[0].current_scene)) { scene_name = level.players[0].current_scene; } if(!isdefined(scene_name)) { foreach(player in level.players) { if(isdefined(player.current_scene)) { scene_name = player.current_scene; break; } } } } } /# if( GetDvarInt("debug_scene_skip") > 0) { if(isdefined(scene_name)) { PrintTopRightln("scene::skip_scene: SCENE NAME " + scene_name + " : " + GetTime(), ( 1, .5, 0 )); } else { PrintTopRightln("scene::skip_scene: CANNOT FIND SCENE NAME : " + GetTime(), ( 1, .5, 0 )); } } #/ //check if it is a player scene if(!( isdefined( b_sequence ) && b_sequence ) && !isdefined(b_player_scene) ) { foreach(player in level.players) { if(isdefined(player.current_scene) && player.current_scene == scene_name) { b_player_scene = true; break; } } } //start skipping player scenes and the scenes linked to it. if(!( isdefined( b_sequence ) && b_sequence ) && ( isdefined( b_player_scene ) && b_player_scene )) { //start the player scene a_instances = get_active_scenes( scene_name ); b_can_skip_player_scene = false; foreach ( s_instance in ArrayCopy( a_instances ) ) { if ( isdefined( s_instance ) ) { b_shared_scene = (s_instance _skip_scene( scene_name, b_sequence, true, false )); if(b_shared_scene == 2) break; if(b_shared_scene == 1) { b_can_skip_player_scene = true; break; } } } //if it is a player skippable scene, we need to skip all the scenes that are associated with it. if( ( isdefined( b_can_skip_player_scene ) && b_can_skip_player_scene ) ) { a_instances = get_active_scenes(); foreach ( s_instance in ArrayCopy( a_instances ) ) { if ( isdefined( s_instance ) ) { s_instance _skip_scene( scene_name, b_sequence, false, true ); } } } else { level.shared_scene_sequence_started = undefined; level.shared_scene_sequence_name = undefined; } return; } a_instances = struct::get_array( scene_name, "targetname" ); if ( !a_instances.size ) { a_instances = get_active_scenes( scene_name ); } foreach ( s_instance in ArrayCopy( a_instances ) ) { if ( isdefined( s_instance ) ) { s_instance _skip_scene( scene_name, b_sequence, b_player_scene, b_check_linked_scene ); } } } function _skip_scene( skipped_scene_name, b_sequence, b_player_scene, b_check_linked_scene ) { b_shared_scene = 0; if ( isdefined( self.scenes ) ) { foreach ( o_scene in ArrayCopy( self.scenes ) ) { //scene is skipping already if( ( isdefined( o_scene.skipping_scene ) && o_scene.skipping_scene ) ) continue; //If a player scene skipping is starting, we can only skip the shared IGCs ones if( !( isdefined( b_sequence ) && b_sequence ) && ( isdefined( b_player_scene ) && b_player_scene ) && !( isdefined( b_check_linked_scene ) && b_check_linked_scene ) ) { if(o_scene._s.name === skipped_scene_name) { if(( isdefined( o_scene._s.DisableSceneSkipping ) && o_scene._s.DisableSceneSkipping )) { return 2; } else { if(o_scene._str_state === "init") continue; b_shared_scene = 1; } } else if(!isdefined(skipped_scene_name)) { if([[o_scene]]->is_scene_shared()) { if(( isdefined( o_scene._s.DisableSceneSkipping ) && o_scene._s.DisableSceneSkipping )) { return 2; } else { if(o_scene._str_state === "init") continue; b_shared_scene = 1; } } else { continue; } } else { continue; } } str_scene_name = [[o_scene]]->get_name(); if( !( isdefined( b_sequence ) && b_sequence ) ) { b_linked_scene = array::contains(level.linked_scenes, str_scene_name); //ignore non linked player scenes if( ( isdefined( b_check_linked_scene ) && b_check_linked_scene ) && (!b_linked_scene || ( isdefined( o_scene._s.DisableSceneSkipping ) && o_scene._s.DisableSceneSkipping )) ) { continue; } if( !b_linked_scene && o_scene._str_state === "init" ) { continue; } if ( ( !isdefined(skipped_scene_name) || str_scene_name == skipped_scene_name ) || (b_linked_scene && !( isdefined( o_scene._s.DisableSceneSkipping ) && o_scene._s.DisableSceneSkipping )) ) { if( ( !isdefined(skipped_scene_name) || str_scene_name == skipped_scene_name) && ( isdefined( b_player_scene ) && b_player_scene ) && !( isdefined( b_check_linked_scene ) && b_check_linked_scene ) && !b_linked_scene) //if player scene { b_shared_scene = 1; o_scene.b_player_scene = true; level.player_skipping_scene = str_scene_name; } o_scene.skipping_scene = true; thread [[o_scene]]->skip_scene( b_sequence ); } } else { o_scene.b_player_scene = b_player_scene; o_scene.skipping_scene = true; thread [[o_scene]]->skip_scene( b_sequence); } } } return b_shared_scene; } function add_player_linked_scene(linked_scene_str) { if(!isdefined(level.linked_scenes))level.linked_scenes=[]; array::add(level.linked_scenes, linked_scene_str); } function remove_player_linked_scene(linked_scene_str) { if(isdefined(level.linked_scenes)) { ArrayRemoveValue( level.linked_scenes, linked_scene_str ); } } function waittill_skip_sequence_completed() { while(isdefined(level.player_skipping_scene)) { wait 0.05; } } function is_skipping_in_progress() { return isdefined(level.player_skipping_scene); } function watch_scene_skip_requests() { self endon( "disconnect" ); while(1) { level waittill("scene_sequence_started"); self thread should_skip_scene_loop(); self thread watch_scene_ending(); self thread watch_scene_skipping(); level waittill( "scene_sequence_ended" ); } } function clear_scene_skipping_ui() { level endon("scene_sequence_started"); if(isdefined(self.scene_skip_timer)) { //PrintTopRightln("Hide Skip Scene Button", WHITE, 10000); self.scene_skip_timer = undefined; } if(isdefined(self.scene_skip_start_time)) { self.scene_skip_start_time = undefined; } foreach(player in level.players) { if(isdefined(player.skip_scene_menu_handle)) { player CloseLuiMenu( player.skip_scene_menu_handle ); player.skip_scene_menu_handle = undefined; } } } function watch_scene_ending() { self endon( "disconnect" ); self endon( "scene_being_skipped"); level waittill( "scene_sequence_ended" ); clear_scene_skipping_ui(); } function watch_scene_skipping() { self endon( "disconnect" ); level endon( "scene_sequence_ended"); self waittill( "scene_being_skipped"); level.sceneSkippedCount++; clear_scene_skipping_ui(); } function should_skip_scene_loop() { self endon( "disconnect" ); level endon( "scene_sequence_ended" ); b_skip_scene = false; clear_scene_skipping_ui(); wait 0.05; //wait a frame for the menus to be closed foreach(player in level.players) { if(isdefined(player.skip_scene_menu_handle)) { player CloseLuiMenu( player.skip_scene_menu_handle ); wait 0.05; //wait a frame for the menus to be closed } player.skip_scene_menu_handle = player OpenLuiMenu( "CPSkipSceneMenu" ); player SetLUIMenuData( player.skip_scene_menu_handle, "showSkipButton", 0 ); player SetLUIMenuData( player.skip_scene_menu_handle, "hostIsSkipping", 0 ); player SetLUIMenuData( player.skip_scene_menu_handle, "sceneSkipEndTime", 0 ); } while(1) { if((self any_button_pressed()) && !( isdefined( level.chyron_text_active ) && level.chyron_text_active )) { if(!isdefined(self.scene_skip_timer)) { //PrintTopRightln("Show Skip Scene Button", ORANGE , 10000); self SetLUIMenuData( self.skip_scene_menu_handle, "showSkipButton", 1 ); } self.scene_skip_timer = GetTime(); } else if(isdefined(self.scene_skip_timer)) { if((GetTime() - self.scene_skip_timer) > 3000) { //PrintTopRightln("Hide Skip Scene Button", WHITE, 10000); self SetLUIMenuData( self.skip_scene_menu_handle, "showSkipButton", 2 ); self.scene_skip_timer = undefined; } } if((self PrimaryButtonPressedLocal()) && !( isdefined( level.chyron_text_active ) && level.chyron_text_active )) { if( !isdefined(self.scene_skip_start_time) ) { foreach(player in level.players) { if(player IsHost()) { player SetLUIMenuData( player.skip_scene_menu_handle, "sceneSkipEndTime", GetTime() + 2500 ); continue; } if(isdefined(player.skip_scene_menu_handle)) { player SetLUIMenuData( player.skip_scene_menu_handle, "hostIsSkipping", 1 ); } } //PrintTopRightln("Scene is being skipped....", GREEN, 10000); self.scene_skip_start_time = GetTime(); } else if((GetTime() - self.scene_skip_start_time) > 2500) { b_skip_scene = true; break; } } else if( isdefined(self.scene_skip_start_time) ) { foreach(player in level.players) { if(player IsHost()) { player SetLUIMenuData( player.skip_scene_menu_handle, "sceneSkipEndTime", 0 ); continue; } if(isdefined(player.skip_scene_menu_handle)) { player SetLUIMenuData( player.skip_scene_menu_handle, "hostIsSkipping", 2 ); } } //PrintTopRightln("Scene skipping cancelled", (0, 1, 1) , 10000); self.scene_skip_start_time = undefined; } if(( isdefined( level.chyron_text_active ) && level.chyron_text_active )) { while(( isdefined( level.chyron_text_active ) && level.chyron_text_active )) { wait 0.05; } //give Chyron text a chance to fade out wait 3; } wait 0.05; } if(b_skip_scene) { //PrintTopRightln("SCENE SKIPPED", RED, 10000); self playsound( "uin_igc_skip" ); //C.Ayers: Plays a skip sound with a duck to cover up the switch self notify("scene_being_skipped"); level notify("scene_skip_sequence_started"); scene::skip_scene(level.shared_scene_sequence_name, false, true); } } function any_button_pressed() { //DPad if( self ActionSlotOneButtonPressed() ) { return true; } else if( self ActionSlotTwoButtonPressed() ) { return true; } else if( self ActionSlotThreeButtonPressed() ) { return true; } else if( self ActionSlotFourButtonPressed() ) { return true; } //Action Buttons else if(self JumpButtonPressed() ) { return true; } else if(self StanceButtonPressed() ) { return true; } else if(self WeaponSwitchButtonPressed() ) { return true; } else if(self ReloadButtonPressed() ) { return true; } //Triggers else if(self fragbuttonpressed() ) { return true; } else if(self throwbuttonpressed() ) { return true; } else if(self AttackButtonPressed()) { return true; } else if(self secondaryoffhandbuttonpressed() ) { return true; } //Sticks else if(self meleebuttonpressed() ) { return true; } return false; } function on_player_connect() { if( self IsHost() ) { self thread watch_scene_skip_requests(); } } function on_player_disconnect() { // Clear out the igc active level flag so if somebody hot joins in they don't think they are in an igc self set_igc_active( false ); } //------------------------------------------------------------------------------------------------------------------------------------------------- function add_scene_ordered_notetrack( group_name, str_note ) { if(!isdefined(level.scene_ordered_notetracks))level.scene_ordered_notetracks=[]; group_obj = level.scene_ordered_notetracks[group_name]; if(!isdefined( group_obj )) { group_obj = SpawnStruct(); group_obj.count = 0; group_obj.current_count = 0; level.scene_ordered_notetracks[group_name] = group_obj; } group_obj.count++; //PrintTopRightln("Registered " + str_note, WHITE, -1); self thread _wait_for_ordered_notify( group_obj.count - 1, group_obj, group_name, str_note ); } function private _wait_for_ordered_notify( id, group_obj, group_name, str_note ) { self waittill(str_note); //PrintTopRightln("Received " + str_note, ORANGE, -1); if( group_obj.current_count == id ) { group_obj.current_count++; self notify("scene_" + str_note); //PrintTopRightln("FIRE " + str_note, BLUE, -1); wait 0.05; //if we fired all notifies, release all arrays if(group_obj.current_count == group_obj.count) { group_obj.pending_notifies = undefined; level.scene_ordered_notetracks[group_name] = undefined; } else if( isdefined(group_obj.pending_notifies) && ((group_obj.current_count + group_obj.pending_notifies.size) == group_obj.count) ) { self thread _fire_ordered_notitifes( group_obj, group_name); } } else { if( !isdefined(group_obj.pending_notifies) ) { group_obj.pending_notifies = []; } //out of order notetrack fired...insert it in it's ordered position notetrack = SpawnStruct(); notetrack.id = id; notetrack.str_note = str_note; i = 0; while(i < group_obj.pending_notifies.size && group_obj.pending_notifies[i].id < id) { i++; } ArrayInsert(group_obj.pending_notifies, notetrack, i); if( (group_obj.current_count + group_obj.pending_notifies.size) == group_obj.count ) { self thread _fire_ordered_notitifes( group_obj, group_name); } } } function private _fire_ordered_notitifes( group_obj, group_name ) { if( isdefined(group_obj.pending_notifies) ) { while( group_obj.pending_notifies.size > 0) { self notify("scene_" + group_obj.pending_notifies[0].str_note); //PrintTopRightln("FIRE " + group_obj.pending_notifies[0].str_note, BLUE, -1); ArrayRemoveIndex(group_obj.pending_notifies, 0); wait 0.05; } } group_obj.pending_notifies = undefined; level.scene_ordered_notetracks[group_name] = undefined; } function add_wait_for_streamer_hint_scene( str_scene_name ) { if(!isdefined(level.wait_for_streamer_hint_scenes))level.wait_for_streamer_hint_scenes=[]; array::add( level.wait_for_streamer_hint_scenes, str_scene_name ); }