#include common_scripts\utility; /*QUAKED trigger_multiple_dyn_metal_detector (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Comments to be added.*/ /*QUAKED trigger_multiple_dyn_creaky_board (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Comments to be added.*/ /*QUAKED trigger_multiple_dyn_photo_copier (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Comments to be added.*/ /*QUAKED trigger_multiple_dyn_copier_no_light (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Comments to be added.*/ /*QUAKED trigger_radius_dyn_motion_light (0.12 0.23 1.0) (-16 -16 -16) (16 16 16) Comments to be added.*/ /*QUAKED trigger_radius_dyn_motion_dlight (0.12 0.23 1.0) (-16 -16 -16) (16 16 16) Comments to be added.*/ /*QUAKED trigger_multiple_dog_bark (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE Comments to be added.*/ /*QUAKED trigger_radius_bird_startle (0.12 0.23 1.0) (-16 -16 -16) (16 16 16) Comments to be added.*/ /*QUAKED trigger_multiple_dyn_motion_light (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Comments to be added.*/ /*QUAKED trigger_multiple_dyn_door (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Comments to be added.*/ /*QUAKED trigger_multiple_freefall (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE defaulttexture="flag" Player free falling with animation and screaming of doom.*/ // Crouch Speed 5.7-6.0 // Run Speed 8.7-9.2 // Sprint Speed 13.0-14.0 // ========================= Constants ========================== // Vending Machine CONST_vending_machine_health = 400; CONST_soda_pop_time = 0.2; //seconds CONST_soda_count = 12; //number of soda per machine CONST_soda_launch_force = 1000; //soda shoot out force CONST_soda_random_factor = 0.3; //in percentage 0.2 = 20% CONST_soda_splash_dmg_scaler = 3; //splash damage multiplier // Metal Detector CONST_alarm_tolerance = 0; //number of alarm sounds before silenced, 0 disables silencing CONST_alarm_interval = 7; //alarm interval time in seconds CONST_alarm_interval_sp = 2; //alarm interval time in seconds for single player // Civilian Jet CONST_jet_speed = 2000; //jet while landing is 130 - 160mph( 2292inch / sec - 2820inch / sec ), emergency landing is 110mph CONST_jet_extend = 20000; //units, each jet and flyto origin will extend from each other by init() { //rotate fan blades in mp_highrise array_thread( GetEntArray( "com_wall_fan_blade_rotate_slow", "targetname" ), ::fan_blade_rotate, "veryslow" ); array_thread( GetEntArray( "com_wall_fan_blade_rotate", "targetname" ), ::fan_blade_rotate, "slow" ); array_thread( GetEntArray( "com_wall_fan_blade_rotate_fast", "targetname" ), ::fan_blade_rotate, "fast" ); trigger_classes = []; trigger_classes[ "trigger_multiple_dyn_metal_detector" ] = ::metal_detector; trigger_classes[ "trigger_multiple_dyn_creaky_board" ] = ::creaky_board; trigger_classes[ "trigger_multiple_dyn_photo_copier" ] = ::photo_copier; trigger_classes[ "trigger_multiple_dyn_copier_no_light" ] = ::photo_copier_no_light; trigger_classes[ "trigger_radius_motion_light" ] = ::motion_light; trigger_classes[ "trigger_radius_dyn_motion_dlight" ] = ::outdoor_motion_dlight; trigger_classes[ "trigger_multiple_dog_bark" ] = ::dog_bark; trigger_classes[ "trigger_radius_bird_startle" ] = ::bird_startle; trigger_classes[ "trigger_multiple_dyn_motion_light" ] = ::motion_light; trigger_classes[ "trigger_multiple_dyn_door" ] = ::trigger_door; //trigger_classes[ "trigger_multiple_freefall" ] = ::freefall; player_init(); foreach ( classname, function in trigger_classes ) { triggers = GetEntArray( classname, "classname" ); // entities process array_thread( triggers , ::triggerTouchThink ); array_thread( triggers , function ); } array_thread( GetEntArray( "vending_machine", "targetname" ), ::vending_machine ); array_thread( GetEntArray( "toggle", "targetname" ), ::use_toggle ); level thread onPlayerConnect(); civilian_jet = GetEnt( "civilian_jet_origin", "targetname" ); if ( IsDefined( civilian_jet ) ) civilian_jet thread civilian_jet_flyby(); thread interactive_tv(); } onPlayerConnect() { for ( ;; ) { level waittill( "connecting", player ); player thread movementTracker(); } } player_init() { if ( isSP() ) { foreach ( player in level.players ) { player.touchTriggers = []; player thread movementTracker(); } } } ai_init() { /*if ( !isdefined( level.registeredAI ) ) level.registeredAI = []; level.registeredAI[ level.registeredAI.size ] = self; */ // self is AI self.touchTriggers = []; self thread movementTracker(); } // ================================================================================ // // Civilian Jet // // ================================================================================ // civilian_jet_flyby() { level endon( "game_ended" ); self jet_init(); level waittill( "prematch_over" ); while ( 1 ) { self thread jet_timer(); self waittill( "start_flyby" ); self thread jet_flyby(); self waittill( "flyby_done" ); self jet_reset(); } } jet_init() { // move jet plane and flyto origin out of the map and hide on level load self.jet_parts = GetEntArray( self.target, "targetname" ); self.jet_flyto = GetEnt( "civilian_jet_flyto", "targetname" ); self.engine_fxs = GetEntArray( "engine_fx", "targetname" ); self.flash_fxs = GetEntArray( "flash_fx", "targetname" ); self.jet_engine_fx = LoadFX( "fx/fire/jet_afterburner" ); self.jet_flash_fx_red = LoadFX( "fx/misc/aircraft_light_wingtip_red" ); self.jet_flash_fx_green = LoadFX( "fx/misc/aircraft_light_wingtip_green" ); self.jet_flash_fx_blink = LoadFX( "fx/misc/aircraft_light_red_blink" ); level.civilianJetFlyBy = undefined; // priority with air supremacies AssertEx( IsDefined( self.jet_parts ), "Missing cilivian jet model" ); AssertEx( IsDefined( self.jet_flyto ), "Missing cilivian jet flyto script_origin: civilian_jet_flyto" ); AssertEx( IsDefined( self.engine_fxs ), "Missing cilivian jet engine fxs script_origins: engine_fx" ); AssertEx( IsDefined( self.flash_fxs ), "Missing cilivian jet signal light script_origins: flash_fxs" ); // extending vector to place jet and flyto origin outside sky box negative_vec = ( VectorNormalize( self.origin - self.jet_flyto.origin ) * CONST_jet_extend ); // extend flyto origin self.jet_flyto.origin -= negative_vec; // extend jet self.origin += negative_vec; foreach ( part in self.jet_parts ) { part.origin += negative_vec; part.old_origin = part.origin; part Hide(); } // extend jet's engine fx origins foreach ( engine_fx in self.engine_fxs ) engine_fx.origin += negative_vec; foreach ( flash_fx in self.flash_fxs ) flash_fx.origin += negative_vec; // -------------- flight time and vector calculation ------------- jet_origin = self.origin; // origin is the nose of the jet jet_flyto_pos = self.jet_flyto.origin; self.jet_fly_vec = jet_flyto_pos - jet_origin; jet_speed = CONST_jet_speed; jet_flight_dist = abs( Distance( jet_origin, jet_flyto_pos ) ); self.jet_flight_time = jet_flight_dist / jet_speed; } jet_reset() { foreach ( part in self.jet_parts ) { part.origin = part.old_origin; part Hide(); } } jet_timer() { level endon( "game_ended" ); match_timelimit = getTimeInterval(); Assert( IsDefined( match_timelimit ) ); timelimit = max( 10 , match_timelimit ); timelimit = min( timelimit, 100 ); if ( GetDvar( "jet_flyby_timer" ) != "" ) level.civilianJetFlyBy_timer = 5 + GetDvarInt( "jet_flyby_timer" ); else level.civilianJetFlyBy_timer = ( 0.25 + RandomFloatRange( 0.3, 0.7 ) ) * 60 * timeLimit; // seconds into the match when jet flys by wait level.civilianJetFlyBy_timer; // wait till all the airborne kill streaks are done while ( IsDefined( level.airstrikeInProgress ) || IsDefined( level.ac130player ) || IsDefined( level.chopper ) || IsDefined( level.remoteMissileInProgress ) ) wait 0.05; // start flyby self notify( "start_flyby" ); // blocks out all airborne kill streaks level.civilianJetFlyBy = true; self waittill( "flyby_done" ); level.civilianJetFlyBy = undefined; } getTimeInterval() { if ( isSP() ) return 10.0; if ( IsDefined( game[ "status" ] ) && game[ "status" ] == "overtime" ) return 1.0; else return getWatchedDvar( "timelimit" ); } getWatchedDvar( dvarString ) { dvarString = "scr_" + level.gameType + "_" + dvarString; if ( IsDefined( level.overrideWatchDvars ) && IsDefined( level.overrideWatchDvars[ dvarString ] ) ) { return level.overrideWatchDvars[ dvarString ]; } return( level.watchDvars[ dvarString ].value ); } jet_flyby() { // show plane foreach ( part in self.jet_parts ) part Show(); engine_fx_array = []; flash_fx_array = []; foreach ( engine_fx in self.engine_fxs ) { engine_fx_ent = Spawn( "script_model", engine_fx.origin ); engine_fx_ent SetModel( "tag_origin" ); engine_fx_ent.angles = engine_fx.angles; engine_fx_array[ engine_fx_array.size ] = engine_fx_ent; } foreach ( flash_fx in self.flash_fxs ) { flash_fx_ent = Spawn( "script_model", flash_fx.origin ); flash_fx_ent SetModel( "tag_origin" ); flash_fx_ent.color = flash_fx.script_noteworthy; flash_fx_ent.angles = flash_fx.angles; flash_fx_array[ flash_fx_array.size ] = flash_fx_ent; } AssertEx( IsDefined( level.mapcenter ), "Calling for civilian jet flyby when level.mapcenter is not yet defined." ); self thread jet_planeSound( self.jet_parts[ 0 ], level.mapcenter ); wait 0.05; // play engine fx on fx ents foreach ( engine_fx_ent in engine_fx_array ) PlayFXOnTag( self.jet_engine_fx, engine_fx_ent, "tag_origin" ); // play flash fx on fx ents foreach ( flash_fx_ent in flash_fx_array ) { if ( IsDefined( flash_fx_ent.color ) && flash_fx_ent.color == "blink" ) PlayFXOnTag( self.jet_flash_fx_blink, flash_fx_ent, "tag_origin" ); else if ( IsDefined( flash_fx_ent.color ) && flash_fx_ent.color == "red" ) PlayFXOnTag( self.jet_flash_fx_red, flash_fx_ent, "tag_origin" ); else PlayFXOnTag( self.jet_flash_fx_green, flash_fx_ent, "tag_origin" ); } // move plane foreach ( part in self.jet_parts ) part MoveTo( part.origin + self.jet_fly_vec, self.jet_flight_time ); // move fx ents foreach ( engine_fx_ent in engine_fx_array ) engine_fx_ent MoveTo( engine_fx_ent.origin + self.jet_fly_vec, self.jet_flight_time ); foreach ( flash_fx_ent in flash_fx_array ) flash_fx_ent MoveTo( flash_fx_ent.origin + self.jet_fly_vec, self.jet_flight_time ); wait( self.jet_flight_time + 1 ); // delete fxs foreach ( engine_fx_ent in engine_fx_array ) engine_fx_ent Delete(); foreach ( flash_fx_ent in flash_fx_array ) flash_fx_ent Delete(); self notify( "flyby_done" ); } jet_planeSound( plane, bombsite ) { plane thread playsound_loop_on_ent( "veh_mig29_dist_loop" ); while ( !targetisclose( plane, bombsite ) ) wait 0.05; plane thread playsound_loop_on_ent( "veh_mig29_close_loop" ); while ( targetisinfront( plane, bombsite ) ) wait 0.05; wait 0.5; plane thread playsound_float( "veh_mig29_sonic_boom" ); while ( targetisclose( plane, bombsite ) ) wait 0.05; plane notify( "stop sound" + "veh_mig29_close_loop" ); self waittill( "flyby_done" ); plane notify( "stop sound" + "veh_mig29_dist_loop" ); } playsound_float( alias, origin, master ) { org = Spawn( "script_origin", ( 0, 0, 1 ) ); org Hide(); if ( !IsDefined( origin ) ) origin = self.origin; org.origin = origin; if ( IsDefined( master ) && master ) org PlaySoundAsMaster( alias ); else org PlaySound( alias ); wait( 10.0 ); org Delete(); } playsound_loop_on_ent( alias, offset ) { org = Spawn( "script_origin", ( 0, 0, 0 ) ); org Hide(); org endon( "death" ); thread delete_on_death( org ); if ( IsDefined( offset ) ) { org.origin = self.origin + offset; org.angles = self.angles; org LinkTo( self ); } else { org.origin = self.origin; org.angles = self.angles; org LinkTo( self ); } // org endon ("death"); org PlayLoopSound( alias ); // println ("playing loop sound ", alias," on entity at origin ", self.origin, " at ORIGIN ", org.origin); self waittill( "stop sound" + alias ); org StopLoopSound( alias ); org Delete(); } targetisinfront( other, target ) { forwardvec = AnglesToForward( flat_angle( other.angles ) ); normalvec = VectorNormalize( flat_origin( target ) - other.origin ); dot = VectorDot( forwardvec, normalvec ); if ( dot > 0 ) return true; else return false; } targetisclose( other, target ) { infront = targetisinfront( other, target ); if ( infront ) dir = 1; else dir = -1; a = flat_origin( other.origin ); b = a + ( AnglesToForward( flat_angle( other.angles ) ) * ( dir * 100000 ) ); point = PointOnSegmentNearestToPoint( a, b, target ); dist = Distance( a, point ); if ( dist < 3000 ) return true; else return false; } // ================================================================================ // // Vending Machine // // ================================================================================ // vending_machine() { level endon( "game_ended" ); self endon( "death" ); // self is use trigger self SetCursorHint( "HINT_ACTIVATE" ); self.vm_normal = GetEnt( self.target, "targetname" ); AssertEx( IsDefined( self.vm_normal ), "Vending machine use trigger is missing target to the normal vending machine script_model" ); vm_soda_start = GetEnt( self.vm_normal.target, "targetname" ); AssertEx( IsDefined( vm_soda_start ), "Vending machine normal script_model is missing target to the start-soda can script_model" ); vm_soda_stop = GetEnt( vm_soda_start.target, "targetname" ); AssertEx( IsDefined( vm_soda_start ), "Start-soda can script_model is missing target to the end-soda can script_model" ); vm_launch_from = GetEnt( vm_soda_stop.target, "targetname" ); AssertEx( IsDefined( vm_launch_from ), "End-soda can script_model is missing target to the physics launch-from script_origin" ); self.vm_launch_from = vm_launch_from.origin; vm_launch_to = GetEnt( vm_launch_from.target, "targetname" ); AssertEx( IsDefined( vm_launch_to ), "launch-from can script_origin is missing target to the physics launch-to script_origin" ); self.vm_launch_to = vm_launch_to.origin; if ( IsDefined( vm_launch_to.target ) ) self.vm_fx_loc = GetEnt( vm_launch_to.target, "targetname" ).origin; //assertex( isdefined( self.vm_launch_to ), "launch-to can script_origin is missing target to the fx location script_origin" ); self.vm_normal SetCanDamage( true ); self.vm_normal_model = self.vm_normal.model; self.vm_damaged_model = self.vm_normal.script_noteworthy; self.vm_soda_model = vm_soda_start.model; self.vm_soda_start_pos = vm_soda_start.origin; self.vm_soda_start_angle = vm_soda_start.angles; self.vm_soda_stop_pos = vm_soda_stop.origin; self.vm_soda_stop_angle = vm_soda_stop.angles; // precache damage model PreCacheModel( self.vm_damaged_model ); // ride the no longer needed models vm_soda_start Delete(); vm_soda_stop Delete(); vm_launch_from Delete(); vm_launch_to Delete(); self.soda_array = []; self.soda_count = CONST_soda_count; self.soda_slot = undefined; // the soda can thats resting in the slot self.hp = CONST_vending_machine_health; self thread vending_machine_damage_monitor( self.vm_normal ); self PlayLoopSound( "vending_machine_hum" ); while ( 1 ) { self waittill( "trigger", player ); //level.players[0] iprintln( "used" ); self PlaySound( "vending_machine_button_press" ); if ( !self.soda_count ) continue; // drop a can, and shoot out the previous one if in slot if ( IsDefined( self.soda_slot ) ) self soda_can_eject(); soda_can_drop( spawn_soda() ); wait 0.05; } } vending_machine_damage_monitor( vending_machine ) { level endon( "game_ended" ); exp_dmg = "mod_grenade mod_projectile mod_explosive mod_grenade_splash mod_projectile_splash splash"; sparks_fx = LoadFX( "fx/explosions/tv_explosion" ); while ( 1 ) { damage = undefined; other = undefined; direction_vec = undefined; P = undefined; type = undefined; vending_machine waittill( "damage", damage, other, direction_vec, P, type ); if ( IsDefined( type ) ) { if ( IsSubStr( exp_dmg, ToLower( type ) ) ) damage *= CONST_soda_splash_dmg_scaler; // multiply explosive dmg self.hp -= damage; if ( self.hp > 0 ) continue; // vending machine is now dead, button usage is disabled self notify( "death" ); // disable use trigger self.origin += ( 0, 0, 10000 ); if ( !IsDefined( self.vm_fx_loc ) ) playfx_loc = self.vm_normal.origin + ( ( 17, -13, 52 ) - ( -20, 18, 0 ) ); else playfx_loc = self.vm_fx_loc; PlayFX( sparks_fx, playfx_loc ); // when vending machine is explosively damaged, shoots out soda cans self.vm_normal SetModel( self.vm_damaged_model ); while ( self.soda_count > 0 ) { // drop a can, and shoot out the previous one if in slot if ( IsDefined( self.soda_slot ) ) self soda_can_eject(); soda_can_drop( spawn_soda() ); wait 0.05; } self StopLoopSound( "vending_machine_hum" ); return; } } } spawn_soda() { soda = Spawn( "script_model", self.vm_soda_start_pos ); soda SetModel( self.vm_soda_model ); soda.origin = self.vm_soda_start_pos; soda.angles = self.vm_soda_start_angle; return soda; } soda_can_drop( soda ) { soda MoveTo( self.vm_soda_stop_pos, CONST_soda_pop_time ); soda PlaySound( "vending_machine_soda_drop" ); // soda can drop sound wait CONST_soda_pop_time; self.soda_slot = soda; self.soda_count--; } soda_can_eject() { self endon( "death" ); if ( IsDefined( self.soda_slot.ejected ) && self.soda_slot.ejected == true ) return; // physics launch force_max = 1; force_min = force_max * ( 1 - CONST_soda_launch_force ); random_offset = Int( 40 * CONST_soda_launch_force ); random_launch_offset = ( Int( random_offset / 2 ), Int( random_offset / 2 ), 0 ) - ( RandomInt( random_offset ), RandomInt( random_offset ), 0 ); launch_vec = VectorNormalize( self.vm_launch_to - self.vm_launch_from + random_launch_offset ); launch_force_vec = ( launch_vec * RandomFloatRange( force_min, force_max ) ); self.soda_slot PhysicsLaunchClient( self.vm_launch_from, launch_force_vec ); self.soda_slot.ejected = true; } // ================================================================================ // // Free Fall // // ================================================================================ // freefall() { level endon( "game_ended" ); freefall_weapon = "briefcase_bomb_mp"; PreCacheItem( freefall_weapon ); while ( 1 ) { self waittill( "trigger_enter", player ); if ( !( player HasWeapon( freefall_weapon ) ) ) { player PlaySound( "freefall_death" ); player GiveWeapon( freefall_weapon ); player SetWeaponAmmoStock( freefall_weapon, 0 ); player SetWeaponAmmoClip( freefall_weapon, 0 ); player SwitchToWeapon( freefall_weapon ); } } } // ================================================================================ // // Metal Detector // // ================================================================================ // metal_detector() { // self is trigger: trigger_multiple_dyn_metal_detector level endon( "game_ended" ); AssertEx( IsDefined( self.target ), "trigger_multiple_dyn_metal_detector is missing target damage trigger used for detecting entities other than players" ); damage_trig = GetEnt( self.target, "targetname" ); damage_trig EnableGrenadeTouchDamage(); bound_org_1 = GetEnt( damage_trig.target, "targetname" ); bound_org_2 = GetEnt( bound_org_1.target, "targetname" ); AssertEx( IsDefined( bound_org_1 ) && IsDefined( bound_org_2 ), "Metal detector missing bound origins for claymore test" ); detector_1 = GetEnt( bound_org_2.target, "targetname" ); detector_2 = GetEnt( detector_1.target, "targetname" ); AssertEx( IsDefined( detector_1 ) && IsDefined( detector_2 ), "Recompile the bsp to fix this, metal detector prefab changed." ); bounds = []; bound_x_min = min( bound_org_1.origin[ 0 ], bound_org_2.origin[ 0 ] ); bounds[ 0 ] = bound_x_min; bound_x_max = max( bound_org_1.origin[ 0 ], bound_org_2.origin[ 0 ] ); bounds[ 1 ] = bound_x_max; bound_y_min = min( bound_org_1.origin[ 1 ], bound_org_2.origin[ 1 ] ); bounds[ 2 ] = bound_y_min; bound_y_max = max( bound_org_1.origin[ 1 ], bound_org_2.origin[ 1 ] ); bounds[ 3 ] = bound_y_max; bound_z_min = min( bound_org_1.origin[ 2 ], bound_org_2.origin[ 2 ] ); bounds[ 4 ] = bound_z_min; bound_z_max = max( bound_org_1.origin[ 2 ], bound_org_2.origin[ 2 ] ); bounds[ 5 ] = bound_z_max; bound_org_1 Delete(); bound_org_2 Delete(); if ( !isSP() ) self.alarm_interval = CONST_alarm_interval; else self.alarm_interval = CONST_alarm_interval_sp; self.alarm_playing = 0; self.alarm_annoyance = 0; self.tolerance = CONST_alarm_tolerance; self thread metal_detector_dmg_monitor( damage_trig ); self thread metal_detector_touch_monitor(); self thread metal_detector_weapons( bounds, "weapon_claymore", "weapon_c4" ); light_pos1 = ( detector_1.origin[ 0 ], detector_1.origin[ 1 ], bound_z_max ); light_pos2 = ( detector_2.origin[ 0 ], detector_2.origin[ 1 ], bound_z_max ); //light_pos1 = ( bound_x_min, bound_y_min, bound_z_max ); //light_pos2 = ( bound_x_max, bound_y_max, bound_z_max ); md_light = LoadFX( "fx/props/metal_detector_light" ); while ( 1 ) { self waittill_any( "dmg_triggered", "touch_triggered", "weapon_triggered" ); self thread playsound_and_light( "alarm_metal_detector", md_light, light_pos1, light_pos2 ); } } playsound_and_light( sound, light, light_pos1, light_pos2 ) { level endon( "game_ended" ); if ( !self.alarm_playing ) { self.alarm_playing = 1; self thread annoyance_tracker(); if ( !self.alarm_annoyance ) self PlaySound( sound ); // 1000ms red light fx PlayFX( light, light_pos1 ); PlayFX( light, light_pos2 ); wait self.alarm_interval; self.alarm_playing = 0; } } annoyance_tracker() { level endon( "game_ended" ); if ( !self.tolerance ) return; interval = self.alarm_interval + 0.15; if ( self.tolerance ) self.tolerance--; else self.alarm_annoyance = 1; current_time = GetTime(); // ms alarm_timeout = CONST_alarm_interval; if ( isSP() ) alarm_timeout = CONST_alarm_interval_sp; self waittill_any_or_timeout( "dmg_triggered", "touch_triggered", "weapon_triggered", ( alarm_timeout + 2 ) ); time_delta = ( GetTime() - current_time ); if ( time_delta > ( ( alarm_timeout * 1000 ) + 1150 ) ) { self.alarm_annoyance = 0; self.tolerance = CONST_alarm_tolerance; } } waittill_any_or_timeout( msg1, msg2, msg3, timer ) { level endon( "game_ended" ); self endon( msg1 ); self endon( msg2 ); self endon( msg3 ); wait timer; } metal_detector_weapons( bounds, weapon_1, weapon_2 ) { level endon( "game_ended" ); while ( 1 ) { self waittill_weapon_placed(); all_grenades = GetEntArray( "grenade", "classname" ); foreach ( grenade in all_grenades ) { if ( IsDefined( grenade.model ) && ( grenade.model == weapon_1 || grenade.model == weapon_2 ) ) { if ( isInBound( grenade, bounds ) ) self thread weapon_notify_loop( grenade, bounds ); } } } } waittill_weapon_placed() { level endon( "game_ended" ); self endon( "dmg_triggered" ); self waittill( "touch_triggered" ); } weapon_notify_loop( grenade, bounds ) { grenade endon( "death" ); while ( isInBound( grenade, bounds ) ) { self notify( "weapon_triggered" ); wait self.alarm_interval; } } isInBound( ent, bounds ) { bound_x_min = bounds[ 0 ]; bound_x_max = bounds[ 1 ]; bound_y_min = bounds[ 2 ]; bound_y_max = bounds[ 3 ]; bound_z_min = bounds[ 4 ]; bound_z_max = bounds[ 5 ]; ent_x = ent.origin[ 0 ]; ent_y = ent.origin[ 1 ]; ent_z = ent.origin[ 2 ]; if ( isInBound_single( ent_x, bound_x_min, bound_x_max ) ) { if ( isInBound_single( ent_y, bound_y_min, bound_y_max ) ) { if ( isInBound_single( ent_z, bound_z_min, bound_z_max ) ) return true; } } return false; } isInBound_single( var, v_min, v_max ) { if ( var > v_min && var < v_max ) return true; return false; } metal_detector_dmg_monitor( damage_trig ) { level endon( "game_ended" ); while ( 1 ) { damage_trig waittill( "damage", damage, other, direction_vec, P, type ); if ( IsDefined( type ) && alarm_validate_damage( type ) ) self notify( "dmg_triggered" ); } } metal_detector_touch_monitor() { level endon( "game_ended" ); while ( 1 ) { self waittill( "trigger_enter" ); while ( anythingTouchingTrigger( self ) ) { self notify( "touch_triggered" ); wait self.alarm_interval; } } } alarm_validate_damage( damageType ) { //disallowed_dmg = "mod_pistol_bullet mod_rifle_bullet bullet mod_crush mod_grenade_splash mod_projectile_splash splash unknown"; //disallowed_dmg_array = strtok( disallowed_damage, " " ); allowed_dmg = "mod_melee melee mod_grenade mod_projectile mod_explosive mod_impact"; allowed_dmg_array = StrTok( allowed_dmg, " " ); foreach ( dmg in allowed_dmg_array ) { if ( ToLower( dmg ) == ToLower( damageType ) ) return true; } return false; } // ================================================================================ // creaky_board() { level endon( "game_ended" ); for ( ;; ) { self waittill( "trigger_enter", player ); player thread do_creak( self ); } } do_creak( trigger ) { self endon( "disconnect" ); self endon( "death" ); self PlaySound( "step_walk_plr_woodcreak_on" ); for ( ;; ) { self waittill( "trigger_leave", leftTrigger ); if ( trigger != leftTrigger ) continue; self PlaySound( "step_walk_plr_woodcreak_off" ); return; } } motion_light() { level endon( "game_ended" ); self.moveTracker = true; self.lightsOn = false; lights = GetEntArray( self.target, "targetname" ); AssertEx( lights.size, "ERROR: trigger_ * _motion_light with no targets at " + self.origin ); noself_array_call( [ "com_two_light_fixture_off", "com_two_light_fixture_on" ], ::PreCacheModel ); foreach ( light in lights ) { light.lightRigs = []; infoNull = GetEnt( light.target, "targetname" ); if ( !IsDefined( infoNull.target ) ) continue; light.lightRigs = GetEntArray( infoNull.target, "targetname" ); } for ( ;; ) { self waittill( "trigger_enter" ); while ( anythingTouchingTrigger( self ) ) { objectMoved = false; foreach ( object in self.touchList ) { if ( IsDefined( object.distMoved ) && object.distMoved > 5.0 ) objectMoved = true; } if ( objectMoved ) { if ( !self.lightsOn ) { self.lightsOn = true; lights[ 0 ] PlaySound( "switch_auto_lights_on" ); foreach ( light in lights ) { light SetLightIntensity( 1.0 ); if ( IsDefined( light.lightRigs ) ) { foreach ( rig in light.lightRigs ) rig SetModel( "com_two_light_fixture_on" ); } } } self thread motion_light_timeout( lights, 10.0 ); } wait( 0.05 ); } } } motion_light_timeout( lights, timeout ) { self notify( "motion_light_timeout" ); self endon( "motion_light_timeout" ); wait( timeout ); foreach ( light in lights ) { light SetLightIntensity( 0 ); if ( IsDefined( light.lightRigs ) ) { foreach ( rig in light.lightRigs ) rig SetModel( "com_two_light_fixture_off" ); } } lights[ 0 ] PlaySound( "switch_auto_lights_off" ); self.lightsOn = false; } outdoor_motion_dlight() { if ( !IsDefined( level.outdoor_motion_light ) ) level.outdoor_motion_light = LoadFX( "fx/misc/outdoor_motion_light" ); level endon( "game_ended" ); self.moveTracker = true; self.lightsOn = false; lightRig = GetEnt( self.target, "targetname" ); AssertEx( lightRig.size, "ERROR: trigger_ * _motion_light with no targets at " + self.origin ); lights = GetEntArray( lightRig.target, "targetname" ); AssertEx( lights.size, "ERROR: trigger_ * _motion_light model target with no light targets at " + lightRig.origin ); noself_array_call( [ "com_two_light_fixture_off", "com_two_light_fixture_on" ], ::PreCacheModel ); for ( ;; ) { self waittill( "trigger_enter" ); while ( anythingTouchingTrigger( self ) ) { objectMoved = false; foreach ( object in self.touchList ) { if ( IsDefined( object.distMoved ) && object.distMoved > 5.0 ) objectMoved = true; } if ( objectMoved ) { if ( !self.lightsOn ) { self.lightsOn = true; lightRig PlaySound( "switch_auto_lights_on" ); lightRig SetModel( "com_two_light_fixture_on" ); foreach ( light in lights ) { Assert( !IsDefined( light.lightEnt ) ); light.lightEnt = Spawn( "script_model", light.origin ); light.lightEnt SetModel( "tag_origin" ); PlayFXOnTag( level.outdoor_motion_light, light.lightEnt, "tag_origin" ); } } self thread outdoor_motion_dlight_timeout( lightRig, lights, 10.0 ); } wait( 0.05 ); } } } outdoor_motion_dlight_timeout( lightRig, lights, timeout ) { self notify( "motion_light_timeout" ); self endon( "motion_light_timeout" ); wait( timeout ); foreach ( light in lights ) { Assert( IsDefined( light.lightEnt ) ); light.lightEnt Delete(); } lightRig PlaySound( "switch_auto_lights_off" ); lightRig SetModel( "com_two_light_fixture_off" ); self.lightsOn = false; } dog_bark() { level endon( "game_ended" ); self.moveTracker = true; dogOrigin = GetEnt( self.target, "targetname" ); AssertEx( IsDefined( dogOrigin ), "ERROR: trigger_multiple_dog_bark with no target at " + self.origin ); for ( ;; ) { self waittill( "trigger_enter", player ); while ( anythingTouchingTrigger( self ) ) { maxDistMoved = 0; foreach ( object in self.touchList ) { if ( IsDefined( object.distMoved ) && object.distMoved > maxDistMoved ) maxDistMoved = object.distMoved; } if ( maxDistMoved > 6.0 ) { dogOrigin PlaySound( "dyn_anml_dog_bark" ); wait( RandomFloatRange( 16 / maxDistMoved, 16 / maxDistMoved + RandomFloat( 1.0 ) ) ); } else { wait( 0.05 ); } } } } trigger_door() { doorEnt = GetEnt( self.target, "targetname" ); AssertEx( IsDefined( doorEnt ), "ERROR: trigger_multiple_dyn_door with no door brush at " + self.origin ); self.doorEnt = doorEnt; self.doorAngle = getVectorRightAngle( VectorNormalize( self GetOrigin() - doorEnt GetOrigin() ) ); doorEnt.baseYaw = doorEnt.angles[ 1 ]; openTime = 1.0; for ( ;; ) { self waittill( "trigger_enter", player ); doorEnt thread doorOpen( openTime, self getDoorSide( player ) ); if ( anythingTouchingTrigger( self ) ) self waittill( "trigger_empty" ); wait( 3.0 ); if ( anythingTouchingTrigger( self ) ) self waittill( "trigger_empty" ); doorEnt thread doorClose( openTime ); } } doorOpen( openTime, doorSide ) { if ( doorSide ) self RotateTo( ( 0, self.baseYaw + 90, 1 ), openTime, 0.1, 0.75 ); else self RotateTo( ( 0, self.baseYaw - 90, 1 ), openTime, 0.1, 0.75 ); self PlaySound( "door_generic_house_open" ); wait( openTime + 0.05 ); } doorClose( openTime ) { self RotateTo( ( 0, self.baseYaw, 1 ), openTime ); self PlaySound( "door_generic_house_close" ); wait( openTime + 0.05 ); } getDoorSide( player ) { return( VectorDot( self.doorAngle, VectorNormalize( player.origin - self.doorEnt GetOrigin() ) ) > 0 ); } getVectorRightAngle( vDir ) { return( vDir[ 1 ], 0 - vDir[ 0 ], vDir[ 2 ] ); } use_toggle() { if ( self.classname != "trigger_use_touch" ) return; lights = GetEntArray( self.target, "targetname" ); Assert( lights.size ); self.lightsOn = 1; foreach ( light in lights ) light SetLightIntensity( 1.5 * self.lightsOn ); for ( ;; ) { self waittill( "trigger" ); self.lightsOn = !self.lightsOn; if ( self.lightsOn ) { foreach ( light in lights ) light SetLightIntensity( 1.5 ); self PlaySound( "switch_auto_lights_on" ); } else { foreach ( light in lights ) light SetLightIntensity( 0 ); self PlaySound( "switch_auto_lights_off" ); } } } bird_startle() { } photo_copier_init( trigger ) { // self is trigger self.copier = get_photo_copier( trigger ); AssertEx( self.copier.classname == "script_model", "Photocopier at " + trigger.origin + " doesn't target a photo copier" ); copy_bar = GetEnt( self.copier.target, "targetname" ); AssertEx( copy_bar.classname == "script_brushmodel", "Photocopier at " + trigger.origin + " doesn't target a photo copier" ); light = GetEnt( copy_bar.target, "targetname" ); AssertEx( light.classname == "light_spot" || light.classname == "light", "Photocopier at " + trigger.origin + " doesn't have a light" ); light.intensity = light GetLightIntensity(); light SetLightIntensity( 0 ); trigger.copy_bar = copy_bar; trigger.start_pos = copy_bar.origin; trigger.light = light; angles = self.copier.angles + ( 0, 90, 0 ); forward = AnglesToForward( angles ); trigger.end_pos = trigger.start_pos + ( forward * 30 ); } get_photo_copier( trigger ) { if ( !IsDefined( trigger.target ) ) { //cant target directly to a destructible toy, so we are grabing the nearest one, since primary light requires them to be far anyway toys = GetEntArray( "destructible_toy", "targetname" ); copier = toys[ 0 ]; foreach ( toy in toys ) { if ( IsDefined( toy.destructible_type ) && toy.destructible_type == "toy_copier" ) { if ( Distance( trigger.origin, copier.origin ) > Distance( trigger.origin, toy.origin ) ) copier = toy; } } AssertEx( Distance( trigger.origin, copier.origin ) < 128, "Photocopier at " + trigger.origin + " doesn't contain a photo copier" ); } else { copier = GetEnt( trigger.target, "targetname" ); AssertEx( IsDefined( copier ), "Photocopier at " + trigger.origin + " doesn't target a photo copier" ); copier SetCanDamage( true ); } return copier; } waittill_copier_copies() { self.copier endon( "FX_State_Change0" ); self.copier endon( "death" ); self waittill( "trigger_enter" ); } photo_copier() { level endon( "game_ended" ); photo_copier_init( self ); self.copier endon( "FX_State_Change0" ); // this is when copier breaks self thread photo_copier_stop(); // monitor copier for quick stop for ( ;; ) { waittill_copier_copies(); self PlaySound( "mach_copier_run" ); if ( IsDefined( self.copy_bar ) ) { reset_copier( self ); thread photo_copier_copy_bar_goes(); thread photo_copier_light_on(); } wait( 3 ); } } photo_copier_no_light() { level endon( "game_ended" ); self endon ( "death" ); if ( get_template_level() == "hamburg" ) return; // I don't need no stinking copies. // masking is not friendly for this - Nate self.copier = get_photo_copier( self ); AssertEx( self.copier.classname == "script_model", "Photocopier at " + self.origin + " doesn't target or contain a photo copier" ); self.copier endon( "FX_State_Change0" ); // this is when copier breaks for ( ;; ) { waittill_copier_copies(); self PlaySound( "mach_copier_run" ); wait( 3 ); } } // reset light and copy bar position, interruptes previous copy in progress reset_copier( trigger ) { trigger.copy_bar MoveTo( trigger.start_pos, 0.2 ); // reset position trigger.light SetLightIntensity( 0 ); } photo_copier_copy_bar_goes() { self.copier notify( "bar_goes" ); self.copier endon( "bar_goes" ); self.copier endon( "FX_State_Change0" ); self.copier endon( "death" ); copy_bar = self.copy_bar; wait( 2.0 ); copy_bar MoveTo( self.end_pos, 1.6 ); wait( 1.8 ); copy_bar MoveTo( self.start_pos, 1.6 ); wait( 1.6 ); // wait( 13.35 ); light = self.light; timer = 0.2; steps = timer / 0.05; for ( i = 0; i < steps; i++ ) { intensity = i * 0.05; intensity /= timer; intensity = 1 - ( intensity * light.intensity ); if ( intensity > 0 ) light SetLightIntensity( intensity ); wait( 0.05 ); } } photo_copier_light_on() { self.copier notify( "light_on" ); self.copier endon( "light_on" ); self.copier endon( "FX_State_Change0" ); self.copier endon( "death" ); light = self.light; timer = 0.2; steps = timer / 0.05; for ( i = 0; i < steps; i++ ) { intensity = i * 0.05; intensity /= timer; light SetLightIntensity( intensity * light.intensity ); wait( 0.05 ); } photo_light_flicker( light ); } // stopping light and bar move on death photo_copier_stop() { self.copier waittill( "FX_State_Change0" ); self.copier endon( "death" ); reset_copier( self ); } photo_light_flicker( light ) { // flicker light SetLightIntensity( 1 ); wait( 0.05 ); light SetLightIntensity( 0 ); wait( 0.10 ); light SetLightIntensity( 1 ); wait( 0.05 ); light SetLightIntensity( 0 ); wait( 0.10 ); light SetLightIntensity( 1 ); } fan_blade_rotate( type ) { Assert( IsDefined( type ) ); speed = 0; time = 20000; speed_multiplier = 1.0; if ( IsDefined( self.speed ) ) { speed_multiplier = self.speed; } if ( type == "slow" ) { if ( IsDefined( self.script_noteworthy ) && ( self.script_noteworthy == "lockedspeed" ) ) speed = 180; else speed = RandomFloatRange( 100 * speed_multiplier, 360 * speed_multiplier ); } else if ( type == "fast" ) speed = RandomFloatRange( 720 * speed_multiplier, 1000 * speed_multiplier ); else if ( type == "veryslow" ) speed = RandomFloatRange( 1 * speed_multiplier, 2 * speed_multiplier ); // use the speed to really tune else AssertMsg( "Type must be fast, slow, or veryslow" ); if ( IsDefined( self.script_noteworthy ) && ( self.script_noteworthy == "lockedspeed" ) ) wait 0; else wait RandomFloatRange( 0, 1 ); fan_angles = self.angles; fan_vec = ( AnglesToRight( self.angles ) * 100 ); // assures normalized vector is length of "1" fan_vec = VectorNormalize( fan_vec ); while ( true ) { dot_x = abs( VectorDot( fan_vec, ( 1, 0, 0 ) ) ); dot_y = abs( VectorDot( fan_vec, ( 0, 1, 0 ) ) ); dot_z = abs( VectorDot( fan_vec, ( 0, 0, 1 ) ) ); if ( dot_x > 0.9 ) self RotateVelocity( ( speed, 0, 0 ), time ); else if ( dot_y > 0.9 ) self RotateVelocity( ( speed, 0, 0 ), time ); else if ( dot_z > 0.9 ) self RotateVelocity( ( 0, speed, 0 ), time ); else self RotateVelocity( ( 0, speed, 0 ), time ); wait time; } } triggerTouchThink( enterFunc, exitFunc ) { level endon( "game_ended" ); self.entNum = self GetEntityNumber(); while ( true ) { self waittill( "trigger", player ); if ( !IsPlayer( player ) && !IsDefined( player.finished_spawning ) ) continue; if ( !IsAlive( player ) ) continue; if ( !IsDefined( player.touchTriggers[ self.entNum ] ) ) player thread playerTouchTriggerThink( self, enterFunc, exitFunc ); } } playerTouchTriggerThink( trigger, enterFunc, exitFunc ) { if ( !IsPlayer( self ) ) self endon( "death" ); if ( !isSP() ) touchName = self.guid; // generate GUID else touchName = "player" + GetTime(); // generate GUID trigger.touchList[ touchName ] = self; if ( IsDefined( trigger.moveTracker ) ) self.moveTrackers++; trigger notify( "trigger_enter", self ); self notify( "trigger_enter", trigger ); if ( IsDefined( enterFunc ) ) self thread [[ enterFunc ]]( trigger ); self.touchTriggers[ trigger.entNum ] = trigger; while ( IsAlive( self ) && self IsTouching( trigger ) && ( isSP() || !level.gameEnded ) ) wait( 0.05 ); // disconnected player will skip this code if ( IsDefined( self ) ) { self.touchTriggers[ trigger.entNum ] = undefined; if ( IsDefined( trigger.moveTracker ) ) self.moveTrackers--; self notify( "trigger_leave", trigger ); if ( IsDefined( exitFunc ) ) self thread [[ exitFunc ]]( trigger ); } if ( !isSP() && level.gameEnded ) return; trigger.touchList[ touchName ] = undefined; trigger notify( "trigger_leave", self ); if ( !anythingTouchingTrigger( trigger ) ) trigger notify( "trigger_empty" ); } movementTracker() { if ( IsDefined( level.DisablemovementTracker ) ) return; self endon( "disconnect" ); if ( !IsPlayer( self ) ) self endon( "death" ); self.moveTrackers = 0; self.distMoved = 0; for ( ;; ) { self waittill( "trigger_enter" ); lastOrigin = self.origin; while ( self.moveTrackers ) { self.distMoved = Distance( lastOrigin, self.origin ); lastOrigin = self.origin; wait( 0.05 ); } self.distMoved = 0; } } anythingTouchingTrigger( trigger ) { return( trigger.touchList.size ); } playerTouchingTrigger( player, trigger ) { Assert( IsDefined( trigger.entNum ) ); return( IsDefined( player.touchTriggers[ trigger.entNum ] ) ); } interactive_tv() { tv_array = GetEntArray( "interactive_tv", "targetname" ); if ( tv_array.size ) { noself_array_call( [ "com_tv2_d", "com_tv1_d", "com_tv1", "com_tv2", "com_tv1_testpattern", "com_tv2_testpattern" ], ::PreCacheModel ); level.breakables_fx[ "tv_explode" ] = LoadFX( "fx/explosions/tv_explosion" ); } level.tv_lite_array = GetEntArray( "interactive_tv_light", "targetname" ); array_thread( GetEntArray( "interactive_tv", "targetname" ), ::tv_logic ); } tv_logic() { self SetCanDamage( true ); self.damagemodel = undefined; self.offmodel = undefined; self.damagemodel = "com_tv2_d"; self.offmodel = "com_tv2"; self.onmodel = "com_tv2_testpattern"; if ( IsSubStr( self.model, "1" ) ) { self.offmodel = "com_tv1"; self.onmodel = "com_tv1_testpattern"; } if ( IsDefined( self.target ) ) { if ( IsDefined( level.disable_interactive_tv_use_triggers ) ) { usetrig = GetEnt( self.target, "targetname" ); if ( IsDefined( usetrig ) ) usetrig Delete(); } else { self.usetrig = GetEnt( self.target, "targetname" ); self.usetrig UseTriggerRequireLookAt(); self.usetrig SetCursorHint( "HINT_NOICON" ); } } array = get_array_of_closest( self.origin, level.tv_lite_array, undefined, undefined, 64 ); if ( array.size ) { self.lite = array[ 0 ]; level.tv_lite_array = array_remove( level.tv_lite_array, self.lite ); self.liteintensity = self.lite GetLightIntensity(); } self thread tv_damage(); if ( IsDefined( self.usetrig ) ) self thread tv_off(); } tv_off() { self.usetrig endon( "death" ); while ( 1 ) { wait 0.2; self.usetrig waittill( "trigger" ); // it would be nice to play a sound here self notify( "off" ); if ( self.model == self.offmodel ) { self SetModel( self.onmodel ); if ( IsDefined( self.lite ) ) self.lite SetLightIntensity( self.liteintensity ); } else { self SetModel( self.offmodel ); if ( IsDefined( self.lite ) ) self.lite SetLightIntensity( 0 ); } } } tv_damage() { self waittill( "damage", damage, other, direction_vec, P, type ); self notify( "off" ); if ( IsDefined( self.usetrig ) ) self.usetrig notify( "death" ); self SetModel( self.damagemodel ); if ( IsDefined( self.lite ) ) self.lite SetLightIntensity( 0 ); PlayFXOnTag( level.breakables_fx[ "tv_explode" ], self, "tag_fx" ); self PlaySound( "tv_shot_burst" ); if ( IsDefined( self.usetrig ) ) self.usetrig Delete(); }