#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.1; // seconds CONST_soda_count = 12; // number of soda per machine CONST_soda_launch_force = 1000; // soda shoot out force CONST_soda_random_factor = 0.15; // 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", "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" ); 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(); } 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( "fire/jet_afterburner" ); self.jet_flash_fx_red = loadfx( "misc/aircraft_light_wingtip_red" ); self.jet_flash_fx_green = loadfx( "misc/aircraft_light_wingtip_green" ); self.jet_flash_fx_blink = loadfx( "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 = Vector_multiply( 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; 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 .05; plane thread playsound_loop_on_ent( "veh_mig29_close_loop" ); while ( targetisinfront( plane, bombsite ) ) wait .05; wait .5; plane thread playsound_float( "veh_mig29_sonic_boom" ); while ( targetisclose( plane, bombsite ) ) wait .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 + Vector_Multiply( 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" ); self.vm_launch_from = getent( vm_soda_stop.target, "targetname" ); assertex( isdefined( self.vm_launch_from ), "End-soda can script_model is missing target to the physics launch-from script_origin" ); self.vm_launch_to = getent( self.vm_launch_from.target, "targetname" ); assertex( isdefined( self.vm_launch_to ), "launch-from can script_origin is missing target to the physics launch-to script_origin" ); if ( isdefined( self.vm_launch_to.target ) ) self.vm_fx_loc = getent( self.vm_launch_to.target, "targetname" ); //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(); 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( "explosions/tv_explosion" ); while ( 1 ) { 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.origin; 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 = CONST_soda_launch_force * ( 1 + CONST_soda_random_factor ); force_min = force_max * 0.75 * ( 1 + CONST_soda_random_factor ); launch_vec = vectorNormalize( self.vm_launch_to.origin - self.vm_launch_from.origin ); force_vec = vector_multiply( launch_vec, randomfloatrange( force_min, force_max ) ); launch_force_vec = ( force_vec[ 0 ] * randomfloatrange( 1, 1 + CONST_soda_random_factor ), force_vec[ 1 ] * randomfloatrange( 1, 1 + CONST_soda_random_factor ), force_vec[ 2 ] * randomfloatrange( 1, 1 + CONST_soda_random_factor ) ); self.soda_slot PhysicsLaunchClient( self.vm_launch_from.origin, 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( "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 ); precacheModel( "com_two_light_fixture_off" ); precacheModel( "com_two_light_fixture_on" ); 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( "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 ); precacheModel( "com_two_light_fixture_off" ); precacheModel( "com_two_light_fixture_on" ); 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 + vector_multiply( 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.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" ) speed = randomfloatrange( 100*speed_multiplier, 360*speed_multiplier ); else if ( type == "fast" ) speed = randomfloatrange( 720*speed_multiplier, 1000*speed_multiplier ); else assertmsg( "Type must be fast or slow" ); wait randomfloatrange( 0, 1 ); fan_angles = self.angles; fan_vec = Vector_multiply( 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() { 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 ] ) ); }