#include maps/mp/zombies/_zm_weapons; #include maps/mp/animscripts/zm_death; #include maps/mp/zombies/_zm_laststand; #include maps/mp/_visionset_mgr; #include maps/mp/zombies/_zm_net; #include maps/mp/zombies/_zm_score; #include maps/mp/zombies/_zm_utility; #include maps/mp/_utility; #include common_scripts/utility; init() //checked matches cerberus output { level.trap_kills = 0; traps = getentarray( "zombie_trap", "targetname" ); array_thread( traps, ::trap_init ); level thread register_visionsets( traps ); level.burning_zombies = []; level.elec_trap_time = 40; level.elec_trap_cooldown_time = 60; } trap_init() //checked partially changed to match cerberus output //did not change for loop to while loop to prevent infinite loop bug caused by continue in a for loop { self ent_flag_init( "flag_active" ); self ent_flag_init( "flag_cooldown" ); self._trap_type = ""; if ( isDefined( self.script_noteworthy ) ) { self._trap_type = self.script_noteworthy; if ( isDefined( level._zombiemode_trap_activate_funcs ) && isDefined( level._zombiemode_trap_activate_funcs[ self._trap_type ] ) ) { self._trap_activate_func = level._zombiemode_trap_activate_funcs[ self._trap_type ]; } switch( self.script_noteworthy ) { case "rotating": self._trap_activate_func = ::trap_activate_rotating; break; case "electric": self._trap_activate_func = ::trap_activate_electric; break; case "flipper": self._trap_activate_func = ::trap_activate_flipper; break; case "fire": default: self._trap_activate_func = ::trap_activate_fire; } if ( isDefined( level._zombiemode_trap_use_funcs ) && isDefined( level._zombiemode_trap_use_funcs[ self._trap_type ] ) ) { self._trap_use_func = level._zombiemode_trap_use_funcs[ self._trap_type ]; } else { self._trap_use_func = ::trap_use_think; } } self trap_model_type_init(); self._trap_use_trigs = []; self._trap_lights = []; self._trap_movers = []; self._trap_switches = []; components = getentarray( self.target, "targetname" ); for ( i = 0; i < components.size; i++ ) { if ( isDefined( components[ i ].script_noteworthy ) ) { switch( components[ i ].script_noteworthy ) { case "counter_1s": self.counter_1s = components[ i ]; break; case "counter_10s": self.counter_10s = components[ i ]; break; case "counter_100s": self.counter_100s = components[ i ]; break; case "mover": self._trap_movers[ self._trap_movers.size ] = components[ i ]; break; case "switch": self._trap_switches[ self._trap_switches.size ] = components[ i ]; break; case "light": self._trap_lightes[ self._trap_lightes.size ] = components[ i ]; break; } } if ( isDefined( components[ i ].script_string ) ) { switch( components[ i ].script_string ) { case "flipper1": self.flipper1 = components[ i ]; break; case "flipper2": self.flipper2 = components[ i ]; break; case "flipper1_radius_check": self.flipper1_radius_check = components[ i ]; break; case "flipper2_radius_check": self.flipper2_radius_check = components[ i ]; break; case "target1": self.target1 = components[ i ]; break; case "target2": self.target2 = components[ i ]; break; case "target3": self.target3 = components[ i ]; break; } } switch( components[ i ].classname ) { case "trigger_use": self._trap_use_trigs[ self._trap_use_trigs.size ] = components[ i ]; break; case "script_model": if ( components[ i ].model == self._trap_light_model_off ) { self._trap_lights[ self._trap_lights.size ] = components[ i ]; } else if ( components[ i ].model == self._trap_switch_model ) { self._trap_switches[ self._trap_switches.size ] = components[ i ]; } } } self._trap_fx_structs = []; components = getstructarray( self.target, "targetname" ); i = 0; while ( i < components.size ) { if ( isDefined( components[ i ].script_string ) && components[ i ].script_string == "use_this_angle" ) { self.use_this_angle = components[ i ]; i++; continue; } self._trap_fx_structs[ self._trap_fx_structs.size ] = components[ i ]; i++; } /* /# assert( self._trap_use_trigs.size > 0, "_zm_traps::init no use triggers found for " + self.target ); #/ */ if ( !isDefined( self.zombie_cost ) ) { self.zombie_cost = 1000; } self._trap_in_use = 0; self._trap_cooling_down = 0; self thread trap_dialog(); flag_wait( "start_zombie_round_logic" ); self trap_lights_red(); for ( i = 0; i < self._trap_use_trigs.size; i++ ) { self._trap_use_trigs[ i ] setcursorhint( "HINT_NOICON" ); } if ( !isDefined( self.script_flag_wait ) ) { self trap_set_string( &"ZOMBIE_NEED_POWER" ); flag_wait( "power_on" ); } else if ( !isDefined( level.flag[ self.script_flag_wait ] ) ) { flag_init( self.script_flag_wait ); } flag_wait( self.script_flag_wait ); self trap_set_string( &"ZOMBIE_BUTTON_BUY_TRAP", self.zombie_cost ); self trap_lights_green(); for ( i = 0; i < self._trap_use_trigs.size; i++ ) { self._trap_use_trigs[ i ] thread [[ self._trap_use_func ]]( self ); } } trap_use_think( trap ) //checked changed to match cerberus output { while ( 1 ) { self waittill( "trigger", who ); if ( who in_revive_trigger() ) { continue; } if ( is_player_valid( who ) && !trap._trap_in_use ) { if ( who.score >= trap.zombie_cost ) { who maps/mp/zombies/_zm_score::minus_to_player_score( trap.zombie_cost ); } else { continue; } trap._trap_in_use = 1; trap trap_set_string( &"ZOMBIE_TRAP_ACTIVE" ); play_sound_at_pos( "purchase", who.origin ); if ( trap._trap_switches.size ) { trap thread trap_move_switches(); trap waittill( "switch_activated" ); } trap trigger_on(); trap thread [[ trap._trap_activate_func ]](); trap waittill( "trap_done" ); trap trigger_off(); trap._trap_cooling_down = 1; trap trap_set_string( &"ZOMBIE_TRAP_COOLDOWN" ); /* /# if ( getDvarInt( "zombie_cheat" ) >= 1 ) { trap._trap_cooldown_time = 5; #/ } */ wait trap._trap_cooldown_time; trap._trap_cooling_down = 0; trap notify( "available" ); trap._trap_in_use = 0; trap trap_set_string( &"ZOMBIE_BUTTON_BUY_TRAP", trap.zombie_cost ); } } } trap_lights_red() //checked changed to match cerberus output { for ( i = 0; i < self._trap_lights.size; i++ ) { light = self._trap_lights[ i ]; light setmodel( self._trap_light_model_red ); if ( isDefined( light.fx ) ) { light.fx delete(); } light.fx = maps/mp/zombies/_zm_net::network_safe_spawn( "trap_lights_red", 2, "script_model", light.origin ); light.fx setmodel( "tag_origin" ); light.fx.angles = light.angles; playfxontag( level._effect[ "zapper_light_notready" ], light.fx, "tag_origin" ); } } trap_lights_green() //checked partially changed to match cerberus output //did not change while loop to for loop to prevent infinite loop bug { i = 0; while ( i < self._trap_lights.size ) { light = self._trap_lights[ i ]; if ( isDefined( light._switch_disabled ) ) { i++; continue; } light setmodel( self._trap_light_model_green ); if ( isDefined( light.fx ) ) { light.fx delete(); } light.fx = maps/mp/zombies/_zm_net::network_safe_spawn( "trap_lights_green", 2, "script_model", light.origin ); light.fx setmodel( "tag_origin" ); light.fx.angles = light.angles; playfxontag( level._effect[ "zapper_light_ready" ], light.fx, "tag_origin" ); i++; } } trap_set_string( string, param1, param2 ) //checked partially changed to match cerberus output //did not change while loop to for loop to prevent infinite loop bug with continues { i = 0; while ( i < self._trap_use_trigs.size ) { if ( !isDefined( param1 ) ) { self._trap_use_trigs[ i ] sethintstring( string ); i++; continue; } if ( !isDefined( param2 ) ) { self._trap_use_trigs[ i ] sethintstring( string, param1 ); i++; continue; } self._trap_use_trigs[ i ] sethintstring( string, param1, param2 ); i++; } } trap_move_switches() //checked checked changed to match cerberus output { self trap_lights_red(); for ( i = 0; i < self._trap_switches.size; i++ ) { self._trap_switches[ i ] rotatepitch( 180, 0,5 ); self._trap_switches[ i ] playsound( "amb_sparks_l_b" ); } self._trap_switches[ 0 ] waittill( "rotatedone" ); self notify( "switch_activated" ); self waittill( "available" ); for ( i = 0; i < self._trap_switches.size; i++ ) { self._trap_switches[ i ] rotatepitch( -180, 0,5 ); } self._trap_switches[ 0 ] waittill( "rotatedone" ); self trap_lights_green(); } trap_activate_electric() //checked changed to match cerberus output { self._trap_duration = 40; self._trap_cooldown_time = 60; self notify( "trap_activate" ); if ( isDefined( self.script_string ) ) { number = int( self.script_string ); if ( number != 0 ) { exploder( number ); } else { clientnotify( self.script_string + "1" ); } } fx_points = getstructarray( self.target, "targetname" ); for ( i = 0; i < fx_points.size; i++ ) { wait_network_frame(); fx_points[ i ] thread trap_audio_fx( self ); } self thread trap_damage(); wait self._trap_duration; self notify( "trap_done" ); if ( isDefined( self.script_string ) ) { clientnotify( self.script_string + "0" ); } } trap_activate_fire() //checked changed to match cerberus output { self._trap_duration = 40; self._trap_cooldown_time = 60; clientnotify( self.script_string + "1" ); clientnotify( self.script_parameters ); fx_points = getstructarray( self.target, "targetname" ); for ( i = 0; i < fx_points.size; i++ ) { wait_network_frame(); fx_points[ i ] thread trap_audio_fx( self ); } self thread trap_damage(); wait self._trap_duration; self notify( "trap_done" ); clientnotify( self.script_string + "0" ); clientnotify( self.script_parameters ); } trap_activate_rotating() //checked partially changed to match cerberus output { self endon( "trap_done" ); self._trap_duration = 30; self._trap_cooldown_time = 60; self thread trap_damage(); self thread trig_update( self._trap_movers[ 0 ] ); old_angles = self._trap_movers[ 0 ].angles; for ( i = 0; i < self._trap_movers.size; i++ ) { self._trap_movers[ i ] rotateyaw( 360, 5, 4.5 ); } wait 5; step = 1.5; t = 0; while ( t < self._trap_duration ) //this would not make sense as a for loop leaving as a while loop { for ( i = 0; i < self._trap_movers.size; i++ ) { self._trap_movers[ i ] rotateyaw( 360, step ); } wait step; t += step; } for ( i = 0; i < self._trap_movers.size; i++ ) { self._trap_movers[ i ] rotateyaw( 360, 5, 0, 4.5 ); } wait 5; for ( i = 0; i < self._trap_movers.size; i++ ) { self._trap_movers[ i ].angles = old_angles; } self notify( "trap_done" ); } trap_activate_flipper() //checked matches cerberus output { } trap_audio_fx( trap ) //checked matches cerberus output { sound_origin = undefined; if ( trap.script_noteworthy == "electric" ) { sound_origin = spawn( "script_origin", self.origin ); sound_origin playsound( "zmb_elec_start" ); sound_origin playloopsound( "zmb_elec_loop" ); self thread play_electrical_sound( trap ); } else { if ( trap.script_noteworthy == "fire" ) { sound_origin = spawn( "script_origin", self.origin ); sound_origin playsound( "zmb_firetrap_start" ); sound_origin playloopsound( "zmb_firetrap_loop" ); } } trap waittill_any_or_timeout( trap._trap_duration, "trap_done" ); if ( isDefined( sound_origin ) ) { if ( trap.script_noteworthy == "fire" ) { playsoundatposition( "zmb_firetrap_end", sound_origin.origin ); } sound_origin stoploopsound(); wait 0.05; sound_origin delete(); } } play_electrical_sound( trap ) //checked matches cerberus output { trap endon( "trap_done" ); while ( 1 ) { wait randomfloatrange( 0.1, 0.5 ); playsoundatposition( "zmb_elec_arc", self.origin ); } } trap_damage() //checked partially changed to match cerberus output { self endon( "trap_done" ); while ( 1 ) { self waittill( "trigger", ent ); if ( isplayer( ent ) ) { switch( self._trap_type ) { case "electric": ent thread player_elec_damage(); break; case "fire": case "rocket": ent thread player_fire_damage(); break; case "rotating": if ( ent getstance() == "stand" ) { ent dodamage( 50, ent.origin + vectorScale( ( 0, 0, 1 ), 20 ) ); ent setstance( "crouch" ); } break; } //break; //this doesn't make much sense commenting out } else if ( !isDefined( ent.marked_for_death ) ) { switch( self._trap_type ) { case "rocket": ent thread zombie_trap_death( self, 100 ); break; break; case "rotating": ent thread zombie_trap_death( self, 200 ); break; break; case "electric": case "fire": default: ent thread zombie_trap_death( self, randomint( 100 ) ); break; } } } } trig_update( parent ) //checked matches cerberus output { self endon( "trap_done" ); start_angles = self.angles; while ( 1 ) { self.angles = parent.angles; wait 0.05; } } player_elec_damage() //checked changed to match cerberus output { self endon( "death" ); self endon( "disconnect" ); if ( !isDefined( level.elec_loop ) ) { level.elec_loop = 0; } if ( !isDefined( self.is_burning ) && is_player_valid( self ) ) { self.is_burning = 1; if ( is_true( level.trap_electric_visionset_registered ) ) { maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_trap_electric", self, 1.25, 1.25 ); } else { self setelectrified( 1.25 ); } shocktime = 2.5; self shellshock( "electrocution", shocktime ); if ( level.elec_loop == 0 ) { elec_loop = 1; self playsound( "zmb_zombie_arc" ); } if ( !self hasperk( "specialty_armorvest" ) || self.health - 100 < 1 ) { radiusdamage( self.origin, 10, self.health + 100, self.health + 100 ); self.is_burning = undefined; } else { self dodamage( 50, self.origin ); wait 0.1; self.is_burning = undefined; } } } player_fire_damage() //checked changed to match cerberus output { self endon( "death" ); self endon( "disconnect" ); if ( !isDefined( self.is_burning ) && !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) { self.is_burning = 1; if ( is_true( level.trap_fire_visionset_registered ) ) { maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_trap_burn", self, 1.25, 1.25 ); } else { self setburn( 1.25 ); } self notify( "burned" ); if ( !self hasperk( "specialty_armorvest" ) || self.health - 100 < 1 ) { radiusdamage( self.origin, 10, self.health + 100, self.health + 100 ); self.is_burning = undefined; } else { self dodamage( 50, self.origin ); wait 0.1; self.is_burning = undefined; } } } zombie_trap_death( trap, param ) //checked matches cerberus output { self endon( "death" ); self.marked_for_death = 1; switch( trap._trap_type ) { case "electric": case "fire": case "rocket": if ( isDefined( self.animname ) && self.animname != "zombie_dog" ) { if ( param > 90 && level.burning_zombies.size < 6 ) { level.burning_zombies[ level.burning_zombies.size ] = self; self thread zombie_flame_watch(); self playsound( "ignite" ); self thread maps/mp/animscripts/zm_death::flame_death_fx(); playfxontag( level._effect[ "character_fire_death_torso" ], self, "J_SpineLower" ); wait randomfloat( 1.25 ); } else { refs[ 0 ] = "guts"; refs[ 1 ] = "right_arm"; refs[ 2 ] = "left_arm"; refs[ 3 ] = "right_leg"; refs[ 4 ] = "left_leg"; refs[ 5 ] = "no_legs"; refs[ 6 ] = "head"; self.a.gib_ref = refs[ randomint( refs.size ) ]; playsoundatposition( "zmb_zombie_arc", self.origin ); if ( trap._trap_type == "electric" ) { if ( randomint( 100 ) > 50 ) { self thread electroctute_death_fx(); self thread play_elec_vocals(); } } wait randomfloat( 1.25 ); self playsound( "zmb_zombie_arc" ); } } if ( isDefined( self.fire_damage_func ) ) { self [[ self.fire_damage_func ]]( trap ); } else { level notify( "trap_kill" ); self dodamage( self.health + 666, self.origin, trap ); } break; case "centrifuge": case "rotating": ang = vectorToAngle( trap.origin - self.origin ); direction_vec = vectorScale( anglesToRight( ang ), param ); if ( isDefined( self.trap_reaction_func ) ) { self [[ self.trap_reaction_func ]]( trap ); } level notify( "trap_kill" ); self startragdoll(); self launchragdoll( direction_vec ); wait_network_frame(); self.a.gib_ref = "head"; self dodamage( self.health, self.origin, trap ); break; } } zombie_flame_watch() //checked matches cerberus output { self waittill( "death" ); self stoploopsound(); arrayremovevalue( level.burning_zombies, self ); } play_elec_vocals() //checked matches cerberus output { if ( isDefined( self ) ) { org = self.origin; wait 0.15; playsoundatposition( "zmb_elec_vocals", org ); playsoundatposition( "zmb_zombie_arc", org ); playsoundatposition( "zmb_exp_jib_zombie", org ); } } electroctute_death_fx() //checked matches cerberus output { self endon( "death" ); if ( isDefined( self.is_electrocuted ) && self.is_electrocuted ) { return; } self.is_electrocuted = 1; self thread electrocute_timeout(); if ( self.team == level.zombie_team ) { level.bconfiretime = getTime(); level.bconfireorg = self.origin; } if ( isDefined( level._effect[ "elec_torso" ] ) ) { playfxontag( level._effect[ "elec_torso" ], self, "J_SpineLower" ); } self playsound( "zmb_elec_jib_zombie" ); wait 1; tagarray = []; tagarray[ 0 ] = "J_Elbow_LE"; tagarray[ 1 ] = "J_Elbow_RI"; tagarray[ 2 ] = "J_Knee_RI"; tagarray[ 3 ] = "J_Knee_LE"; tagarray = array_randomize( tagarray ); if ( isDefined( level._effect[ "elec_md" ] ) ) { playfxontag( level._effect[ "elec_md" ], self, tagarray[ 0 ] ); } self playsound( "zmb_elec_jib_zombie" ); wait 1; self playsound( "zmb_elec_jib_zombie" ); tagarray[ 0 ] = "J_Wrist_RI"; tagarray[ 1 ] = "J_Wrist_LE"; if ( !isDefined( self.a.gib_ref ) || self.a.gib_ref != "no_legs" ) { tagarray[ 2 ] = "J_Ankle_RI"; tagarray[ 3 ] = "J_Ankle_LE"; } tagarray = array_randomize( tagarray ); if ( isDefined( level._effect[ "elec_sm" ] ) ) { playfxontag( level._effect[ "elec_sm" ], self, tagarray[ 0 ] ); playfxontag( level._effect[ "elec_sm" ], self, tagarray[ 1 ] ); } } electrocute_timeout() //checked matches cerberus output { self endon( "death" ); self playloopsound( "fire_manager_0" ); wait 12; self stoploopsound(); if ( isDefined( self ) && isalive( self ) ) { self.is_electrocuted = 0; self notify( "stop_flame_damage" ); } } trap_dialog() //checked partially changed to match cerberus output //did not change while loop to for loop to prevent in the infinite for loop bug caused by continues { self endon( "warning_dialog" ); level endon( "switch_flipped" ); timer = 0; while ( 1 ) { wait 0.5; players = get_players(); i = 0; while ( i < players.size ) { dist = distancesquared( players[ i ].origin, self.origin ); if ( dist > 4900 ) { timer = 0; i++; continue; } if ( dist < 4900 && timer < 3 ) { wait 0.5; timer++; } if ( dist < 4900 && timer == 3 ) { index = maps/mp/zombies/_zm_weapons::get_player_index( players[ i ] ); plr = "plr_" + index + "_"; wait 3; self notify( "warning_dialog" ); } i++; } } } get_trap_array( trap_type ) //checked changed to match cerberus output { ents = getentarray( "zombie_trap", "targetname" ); traps = []; for ( i = 0; i < ents.size; i++ ) { if ( ents[ i ].script_noteworthy == trap_type ) { traps[ traps.size ] = ents[ i ]; } } return traps; } trap_disable() //checked matches cerberus output { cooldown = self._trap_cooldown_time; if ( self._trap_in_use ) { self notify( "trap_done" ); self._trap_cooldown_time = 0.05; self waittill( "available" ); } array_thread( self._trap_use_trigs, ::trigger_off ); self trap_lights_red(); self._trap_cooldown_time = cooldown; } trap_enable() //checked matches cerberus output { array_thread( self._trap_use_trigs, ::trigger_on ); self trap_lights_green(); } trap_model_type_init() //checked matches cerberus output { if ( !isDefined( self.script_parameters ) ) { self.script_parameters = "default"; } switch( self.script_parameters ) { case "pentagon_electric": self._trap_light_model_off = "zombie_trap_switch_light"; self._trap_light_model_green = "zombie_trap_switch_light_on_green"; self._trap_light_model_red = "zombie_trap_switch_light_on_red"; self._trap_switch_model = "zombie_trap_switch_handle"; break; case "default": default: self._trap_light_model_off = "zombie_zapper_cagelight"; self._trap_light_model_green = "zombie_zapper_cagelight_green"; self._trap_light_model_red = "zombie_zapper_cagelight_red"; self._trap_switch_model = "zombie_zapper_handle"; break; } } register_visionsets( a_traps ) //checked changed to match cerberus output { a_registered_traps = []; foreach ( trap in a_traps ) { if ( isDefined( trap.script_noteworthy ) ) { if ( !trap is_trap_registered( a_registered_traps ) ) { a_registered_traps[ trap.script_noteworthy ] = 1; } } } keys = getarraykeys( a_registered_traps ); foreach ( key in keys ) { switch( key ) { case "electric": if ( !isDefined( level.vsmgr_prio_overlay_zm_trap_electrified ) ) { level.vsmgr_prio_overlay_zm_trap_electrified = 60; } maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_trap_electric", 16000, level.vsmgr_prio_overlay_zm_trap_electrified, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); level.trap_electric_visionset_registered = 1; break; case "fire": if ( !isDefined( level.vsmgr_prio_overlay_zm_trap_burn ) ) { level.vsmgr_prio_overlay_zm_trap_burn = 61; } maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_trap_burn", 16000, level.vsmgr_prio_overlay_zm_trap_burn, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); level.trap_fire_visionset_registered = 1; break; } } } is_trap_registered( a_registered_traps ) //checked matches cerberus output { return isDefined( a_registered_traps[ self.script_noteworthy ] ); }