From 866baa824c3693d17446dd7a8fb34646a36856ed Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Sun, 30 Aug 2020 17:40:45 -0700 Subject: [PATCH] added 42 scripts to zm_transit_patch as a baseline --- .../maps/mp/gametypes_zm/zmeat.gsc | 2473 +++++++++++ .../maps/mp/gametypes_zm/zstandard.gsc | 43 + zm_transit_patch/maps/mp/zm_transit.gsc | 3587 ++++++++++++++++ .../maps/mp/zm_transit_achievement.gsc | 181 + .../maps/mp/zm_transit_ai_screecher.gsc | 291 ++ .../maps/mp/zm_transit_ambush.gsc | 295 ++ .../maps/mp/zm_transit_automaton.gsc | 654 +++ .../maps/mp/zm_transit_buildables.gsc | 442 ++ zm_transit_patch/maps/mp/zm_transit_bus.gsc | 3759 +++++++++++++++++ zm_transit_patch/maps/mp/zm_transit_cling.gsc | 359 ++ .../maps/mp/zm_transit_distance_tracking.gsc | 161 + zm_transit_patch/maps/mp/zm_transit_ffotd.gsc | 291 ++ zm_transit_patch/maps/mp/zm_transit_fx.gsc | 121 + .../maps/mp/zm_transit_gamemodes.gsc | 21 + .../maps/mp/zm_transit_grief_farm.gsc | 98 + .../maps/mp/zm_transit_grief_station.gsc | 59 + .../maps/mp/zm_transit_grief_town.gsc | 66 + zm_transit_patch/maps/mp/zm_transit_lava.gsc | 384 ++ .../maps/mp/zm_transit_openings.gsc | 2500 +++++++++++ zm_transit_patch/maps/mp/zm_transit_power.gsc | 583 +++ zm_transit_patch/maps/mp/zm_transit_sq.gsc | 1600 +++++++ .../maps/mp/zm_transit_standard_farm.gsc | 95 + .../maps/mp/zm_transit_standard_town.gsc | 64 + .../maps/mp/zombies/_zm_ai_avogadro.gsc | 1600 +++++++ .../maps/mp/zombies/_zm_ai_screecher.gsc | 1254 ++++++ .../maps/mp/zombies/_zm_banking.gsc | 326 ++ .../mp/zombies/_zm_equip_electrictrap.gsc | 414 ++ .../maps/mp/zombies/_zm_equip_turret.gsc | 350 ++ .../maps/mp/zombies/_zm_game_module_grief.gsc | 11 + .../maps/mp/zombies/_zm_game_module_meat.gsc | 6 + .../zombies/_zm_game_module_meat_utility.gsc | 685 +++ .../mp/zombies/_zm_game_module_standard.gsc | 0 .../mp/zombies/_zm_game_module_utility.gsc | 46 + .../maps/mp/zombies/_zm_melee_weapon.gsc | 627 +++ .../maps/mp/zombies/_zm_riotshield.gsc | 665 +++ .../mp/zombies/_zm_weap_ballistic_knife.gsc | 308 ++ .../maps/mp/zombies/_zm_weap_bowie.gsc | 19 + .../maps/mp/zombies/_zm_weap_claymore.gsc | 482 +++ .../maps/mp/zombies/_zm_weap_emp_bomb.gsc | 369 ++ .../maps/mp/zombies/_zm_weap_riotshield.gsc | 778 ++++ .../mp/zombies/_zm_weap_tazer_knuckles.gsc | 120 + .../maps/mp/zombies/_zm_weapon_locker.gsc | 338 ++ zm_transit_patch/readme.md | 48 + 43 files changed, 26573 insertions(+) create mode 100644 zm_transit_patch/maps/mp/gametypes_zm/zmeat.gsc create mode 100644 zm_transit_patch/maps/mp/gametypes_zm/zstandard.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_achievement.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_ai_screecher.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_ambush.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_automaton.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_buildables.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_bus.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_cling.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_distance_tracking.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_ffotd.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_fx.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_gamemodes.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_grief_farm.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_grief_station.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_grief_town.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_lava.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_openings.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_power.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_sq.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_standard_farm.gsc create mode 100644 zm_transit_patch/maps/mp/zm_transit_standard_town.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_ai_avogadro.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_ai_screecher.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_banking.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_equip_electrictrap.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_equip_turret.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_game_module_grief.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_game_module_meat.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_game_module_standard.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_game_module_utility.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_melee_weapon.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_riotshield.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weap_bowie.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weap_claymore.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weap_emp_bomb.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weap_riotshield.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc create mode 100644 zm_transit_patch/maps/mp/zombies/_zm_weapon_locker.gsc diff --git a/zm_transit_patch/maps/mp/gametypes_zm/zmeat.gsc b/zm_transit_patch/maps/mp/gametypes_zm/zmeat.gsc new file mode 100644 index 0000000..c4f2ad5 --- /dev/null +++ b/zm_transit_patch/maps/mp/gametypes_zm/zmeat.gsc @@ -0,0 +1,2473 @@ +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_game_module_meat_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; + +#using_animtree( "zombie_meat" ); + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::main(); + registerclientfield( "allplayers", "holding_meat", 7000, 1, "int" ); + registerclientfield( "scriptmover", "ring_glowfx", 7000, 1, "int" ); + registerclientfield( "scriptmover", "ring_glow_meatfx", 7000, 1, "int" ); + level.onprecachegametype = ::onprecachegametype; + level.onstartgametype = ::onstartgametype; + set_game_var( "ZM_roundLimit", 5 ); + set_game_var( "ZM_scoreLimit", 5 ); + set_gamemode_var( "post_init_zombie_spawn_func", ::meat_zombie_post_spawn_init ); + set_gamemode_var( "match_end_notify", "meat_end" ); + set_gamemode_var( "match_end_func", ::meat_end_match ); + level._no_static_unitriggers = 1; + level._game_module_player_damage_callback = ::maps/mp/gametypes_zm/_zm_gametype::game_module_player_damage_callback; + level._game_module_player_laststand_callback = ::meat_last_stand_callback; + level.no_end_game_check = 1; + maps/mp/gametypes_zm/_zm_gametype::post_gametype_main( "zmeat" ); + level thread maps/mp/gametypes_zm/_zm_gametype::init(); + level.zm_roundswitch = 1; + level.zm_switchsides_on_roundswitch = 1; + level._effect[ "meat_marker" ] = loadfx( "maps/zombie/fx_zmb_meat_marker" ); + level._effect[ "butterflies" ] = loadfx( "maps/zombie/fx_zmb_impact_noharm" ); + level._effect[ "meat_glow" ] = loadfx( "maps/zombie/fx_zmb_meat_glow" ); + level._effect[ "meat_glow3p" ] = loadfx( "maps/zombie/fx_zmb_meat_glow_3p" ); + level._effect[ "spawn_cloud" ] = loadfx( "maps/zombie/fx_zmb_race_zombie_spawn_cloud" ); + level._effect[ "fw_burst" ] = loadfx( "maps/zombie/fx_zmb_race_fireworks_burst_center" ); + level._effect[ "fw_impact" ] = loadfx( "maps/zombie/fx_zmb_race_fireworks_drop_impact" ); + level._effect[ "fw_drop" ] = loadfx( "maps/zombie/fx_zmb_race_fireworks_drop_trail" ); + level._effect[ "fw_trail" ] = loadfx( "maps/zombie/fx_zmb_race_fireworks_trail" ); + level._effect[ "fw_trail_cheap" ] = loadfx( "maps/zombie/fx_zmb_race_fireworks_trail_intro" ); + level._effect[ "fw_pre_burst" ] = loadfx( "maps/zombie/fx_zmb_race_fireworks_burst_small" ); + level._effect[ "meat_bounce" ] = loadfx( "maps/zombie/fx_zmb_meat_collision_glow" ); + level._effect[ "ring_glow" ] = loadfx( "misc/fx_zombie_powerup_on" ); + level.can_revive_game_module = ::can_revive; + onplayerconnect_callback( ::meat_on_player_connect ); + spawn_level_meat_manager(); + init_animtree(); +} + +onprecachegametype() +{ + level thread maps/mp/zombies/_zm_game_module_meat_utility::init_item_meat( "zmeat" ); + maps/mp/gametypes_zm/_zm_gametype::rungametypeprecache( "zmeat" ); + game_mode_objects = getstructarray( "game_mode_object", "targetname" ); + meat_objects = getstructarray( "meat_object", "targetname" ); + all_structs = arraycombine( game_mode_objects, meat_objects, 1, 0 ); + i = 0; + while ( i < all_structs.size ) + { + if ( isDefined( all_structs[ i ].script_parameters ) ) + { + precachemodel( all_structs[ i ].script_parameters ); + } + i++; + } + precacheshellshock( "grief_stab_zm" ); + precacheitem( "minigun_zm" ); + precacheshader( "faction_cdc" ); + precacheshader( "faction_cia" ); + precachemodel( "p6_zm_sign_meat_01_step1" ); + precachemodel( "p6_zm_sign_meat_01_step2" ); + precachemodel( "p6_zm_sign_meat_01_step3" ); + precachemodel( "p6_zm_sign_meat_01_step4" ); +} + +meat_hub_start_func() +{ + level thread meat_player_initial_spawn(); + level thread item_meat_reset( level._meat_start_point ); + level thread spawn_meat_zombies(); + level thread monitor_meat_on_team(); + level thread init_minigun_ring(); + level thread init_splitter_ring(); + level thread init_ammo_ring(); + level thread hide_non_meat_objects(); + level thread setup_meat_world_objects(); + level._zombie_path_timer_override = ::zombie_path_timer_override; + level.zombie_health = level.zombie_vars[ "zombie_health_start" ]; + level._zombie_spawning = 0; + level._poi_override = ::meat_poi_override_func; + level._meat_on_team = undefined; + level._meat_zombie_spawn_timer = 2; + level._meat_zombie_spawn_health = 1; + level._minigun_time_override = 15; + level._get_game_module_players = ::get_game_module_players; + level.powerup_drop_count = 0; + level.meat_spawners = level.zombie_spawners; + if ( isDefined( level._meat_callback_initialized ) && !level._meat_callback_initialized ) + { + maps/mp/zombies/_zm::register_player_damage_callback( ::maps/mp/zombies/_zm_game_module::damage_callback_no_pvp_damage ); + level._meat_callback_initialized = 1; + } + setmatchtalkflag( "DeadChatWithDead", 1 ); + setmatchtalkflag( "DeadChatWithTeam", 1 ); + setmatchtalkflag( "DeadHearTeamLiving", 1 ); + setmatchtalkflag( "DeadHearAllLiving", 1 ); + setmatchtalkflag( "EveryoneHearsEveryone", 1 ); + setteamhasmeat( "allies", 0 ); + setteamhasmeat( "axis", 0 ); + level thread zmbmusicsetupmeat(); + level.zombie_spawn_fx = level._effect[ "spawn_cloud" ]; + weapon_spawns = getentarray( "weapon_upgrade", "targetname" ); + i = 0; + while ( i < weapon_spawns.size ) + { + weapon_spawns[ i ] trigger_off(); + i++; + } + level thread monitor_meat_on_side(); + level thread item_meat_watch_for_throw(); + level thread hold_meat_monitor(); + flag_wait( "start_encounters_match_logic" ); + level thread wait_for_team_death( 1 ); + level thread wait_for_team_death( 2 ); + level.team_a_downed = 0; + level.team_b_downed = 0; +} + +meat_on_player_connect() +{ + hotjoined = flag( "initial_players_connected" ); + self thread spawn_player_meat_manager(); + self thread wait_for_player_disconnect(); + self thread wait_for_player_downed(); +/# + self thread watch_debug_input(); +#/ + if ( hotjoined ) + { + one = 1; + two = 2; + if ( get_game_var( "switchedsides" ) ) + { + one = 2; + two = 1; + } + if ( get_game_var( "side_selection" ) == 1 ) + { + if ( self.team == "allies" ) + { + self._meat_team = one; + } + else + { + self._meat_team = two; + } + } + else if ( self.team == "allies" ) + { + self._meat_team = two; + } + else + { + self._meat_team = one; + } + self meat_player_setup(); + } +} + +meat_on_player_disconnect() +{ + team0 = 1; + team1 = 2; + team_counts = []; + team_counts[ team0 ] = 0; + team_counts[ team1 ] = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + team_counts[ players[ i ]._meat_team ] += 1; + i++; + } + if ( team_counts[ team0 ] == 0 ) + { + maps/mp/gametypes_zm/_zm_gametype::end_rounds_early( "B" ); + } + if ( team_counts[ team1 ] == 0 ) + { + maps/mp/gametypes_zm/_zm_gametype::end_rounds_early( "A" ); + } +} + +wait_for_player_disconnect() +{ + level endon( "end_game" ); + self waittill( "disconnect" ); + meat_on_player_disconnect(); +} + +watch_debug_input() +{ +/# + self endon( "disconnect" ); + for ( ;; ) + { + if ( self actionslottwobuttonpressed() ) + { + if ( getDvar( #"0B188A91" ) != "" ) + { + self disableinvulnerability(); + self dodamage( self.health + 666, self.origin ); + } + } + wait 0,05; +#/ + } +} + +zmbmusicsetupmeat() +{ + level thread maps/mp/zombies/_zm_audio::setupmusicstate( "waiting", "ENC_WAITING", 0, 0, 0, undefined ); + level thread maps/mp/zombies/_zm_audio::setupmusicstate( "round_start", "ENC_ROUND_START", 0, 0, 0, undefined ); + level thread maps/mp/zombies/_zm_audio::setupmusicstate( "round_end", "ENC_ROUND_END", 0, 0, 0, undefined ); + level thread maps/mp/zombies/_zm_audio::setupmusicstate( "halftime", "ENC_HALFTIME", 0, 0, 0, undefined ); + level thread maps/mp/zombies/_zm_audio::setupmusicstate( "match_over", "ENC_MATCH_OVER", 0, 0, 0, undefined ); +} + +monitor_meat_on_side() +{ + level endon( "meat_end" ); + level waittill( "meat_grabbed" ); + last_team = level._meat_on_team; + level.meat_lost_time_limit = 5000; + while ( 1 ) + { + if ( isDefined( level.item_meat ) ) + { + if ( !isDefined( level._meat_team_1_volume ) || !isDefined( level._meat_team_2_volume ) ) + { + iprintlnbold( "BUG: There is something wrong with the team volumes" ); + } + if ( isDefined( level._meat_team_1_volume ) && level.item_meat istouching( level._meat_team_1_volume ) ) + { + level._meat_on_team = 1; + level.meat_lost_time = undefined; + } + else + { + if ( isDefined( level._meat_team_2_volume ) && level.item_meat istouching( level._meat_team_2_volume ) ) + { + level._meat_on_team = 2; + level.meat_lost_time = undefined; + break; + } + else + { + if ( isDefined( last_team ) ) + { + if ( !isDefined( level.meat_lost_time ) ) + { + level.meat_lost_time = getTime(); + break; + } + else + { + if ( ( getTime() - level.meat_lost_time ) > level.meat_lost_time_limit ) + { + add_meat_event( "level_lost_meat" ); + level thread item_meat_reset( level._meat_start_point, 1 ); + level.meat_lost_time = undefined; + level waittill( "meat_grabbed" ); + } + } + } + } + } + } + else player_with_meat = get_player_with_meat(); + if ( !isDefined( player_with_meat ) ) + { + if ( !isDefined( level.meat_lost_time ) ) + { + level.meat_lost_time = getTime(); + } + else + { + if ( ( getTime() - level.meat_lost_time ) > level.meat_lost_time_limit ) + { + add_meat_event( "level_lost_meat" ); + level thread item_meat_reset( level._meat_start_point, 1 ); + level.meat_lost_time = undefined; + level waittill( "meat_grabbed" ); + } + } + } + else + { + level.meat_lost_time = undefined; + } + if ( isDefined( level._meat_on_team ) && isDefined( last_team ) && level._meat_on_team != last_team ) + { + level notify( "clear_ignore_all" ); + add_meat_event( "level_meat_team", level._meat_on_team ); + last_team = level._meat_on_team; + assign_meat_to_team( undefined, level._meat_on_team ); +/# + if ( isDefined( level.item_meat ) ) + { + playfx( level._effect[ "spawn_cloud" ], level.item_meat.origin ); +#/ + } + } + wait 0,05; + } +} + +item_meat_watch_for_throw() +{ + level endon( "meat_end" ); + for ( ;; ) + { + level waittill( "meat_thrown", who ); + add_meat_event( "player_thrown", who ); + if ( isDefined( who._spawning_meat ) && who._spawning_meat ) + { + continue; + } + else + { + if ( randomintrange( 1, 101 ) <= 10 ) + { + } + who._has_meat = 0; + if ( isDefined( who._has_meat_hud ) ) + { + who._has_meat_hud destroy(); + } + assign_meat_to_team( undefined, level._meat_on_team ); + } + } +} + +hold_meat_monitor() +{ + level endon( "meat_end" ); + level waittill( "meat_grabbed" ); + while ( 1 ) + { + player = get_player_with_meat(); + while ( !isDefined( player ) ) + { + wait 0,2; + } + while ( !should_try_to_bring_back_teammate( player._meat_team ) ) + { + wait 0,2; + } + if ( isDefined( player._bringing_back_teammate ) && !player._bringing_back_teammate ) + { + player thread bring_back_teammate_progress(); + } + wait 0,2; + } +} + +meat_zombie_post_spawn_init() +{ +} + +create_item_meat_watcher() +{ + wait 0,05; + watcher = self maps/mp/gametypes_zm/_weaponobjects::createuseweaponobjectwatcher( "item_meat", get_gamemode_var( "item_meat_name" ), self.team ); + watcher.pickup = ::item_meat_on_pickup; + watcher.onspawn = ::item_meat_spawned; + watcher.onspawnretrievetriggers = ::play_item_meat_on_spawn_retrieve_trigger; + watcher.headicon = 0; +} + +item_meat_spawned( unused0, unused1 ) +{ + maps/mp/gametypes_zm/_weaponobjects::voidonspawn( unused0, unused1 ); + self.meat_is_moving = 0; + self.meat_is_flying = 0; +} + +wait_for_player_downed() +{ + self endon( "disconnect" ); + while ( isDefined( self ) ) + { + self waittill_any( "player_downed", "fake_death", "death" ); + add_meat_event( "player_down", self ); + wait 0,1; + if ( isDefined( self._meat_team ) ) + { + self thread watch_save_player(); + players = get_players_on_meat_team( self._meat_team ); + if ( players.size >= 2 ) + { + } + } + } +} + +item_meat_watch_stationary() +{ + self endon( "death" ); + self endon( "picked_up" ); + self.meat_is_moving = 1; + self waittill( "stationary" ); + self playloopsound( "zmb_meat_looper", 2 ); + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + add_meat_event( "meat_stationary", self ); + } + else + { + add_meat_event( "fake_meat_stationary", self ); + } + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + level._meat_moving = 0; + level._meat_splitter_activated = 0; + level._last_person_to_throw_meat = undefined; + } + self.meat_is_moving = 0; + while ( isDefined( level._meat_on_team ) ) + { + teamplayers = get_players_on_meat_team( level._meat_on_team ); + i = 0; + while ( i < teamplayers.size ) + { + if ( isDefined( teamplayers[ i ] ) && isDefined( teamplayers[ i ]._encounters_team ) ) + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_land", teamplayers[ i ]._encounters_team ); + return; + } + else + { + i++; + } + } + } +} + +item_meat_watch_bounce() +{ + self endon( "death" ); + self endon( "picked_up" ); + self.meat_is_flying = 1; + self waittill( "grenade_bounce", pos, normal, ent ); + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + add_meat_event( "meat_bounce", self, pos, normal, ent ); + } + else + { + add_meat_event( "fake_meat_bounce", self, pos, normal, ent ); + } + if ( isDefined( level.meat_bounce_override ) ) + { + self thread [[ level.meat_bounce_override ]]( pos, normal, ent ); + return; + } + if ( isDefined( level.spawned_collmap ) ) + { + if ( isDefined( ent ) && ent == level.spawned_collmap ) + { + playfx( level._effect[ "meat_bounce" ], pos, normal ); + } + } + if ( isDefined( ent ) && isplayer( ent ) ) + { + add_meat_event( "player_hit_player", self.owner, ent ); + self.owner hit_player_with_meat( ent ); + } + self.meat_is_flying = 0; + self thread watch_for_roll(); + playfxontag( level._effect[ "meat_marker" ], self, "tag_origin" ); +} + +watch_for_roll() +{ + self endon( "stationary" ); + self endon( "death" ); + self endon( "picked_up" ); + self.meat_is_rolling = 0; + while ( 1 ) + { + old_z = self.origin[ 2 ]; + wait 1; + if ( abs( old_z - self.origin[ 2 ] ) < 10 ) + { + self.meat_is_rolling = 1; + self playloopsound( "zmb_meat_looper", 2 ); + } + } +} + +stop_rolling() +{ + self.origin = self.origin; + self.angles = self.angles; +} + +hit_player_with_meat( hit_player ) +{ +/# + println( "MEAT: Player " + self.name + " hit " + hit_player.name + " with the meat\n" ); +#/ +} + +item_meat_pickup() +{ + self.meat_is_moving = 0; + self.meat_is_flying = 0; + level._meat_moving = 0; + level._meat_splitter_activated = 0; + self notify( "picked_up" ); +} + +player_wait_take_meat( meat_name ) +{ + self.dont_touch_the_meat = 1; + if ( isDefined( self.pre_meat_weapon ) && self hasweapon( self.pre_meat_weapon ) ) + { + self switchtoweapon( self.pre_meat_weapon ); + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + else + { +/# + assert( 0, "Player has no weapon" ); +#/ + self maps/mp/zombies/_zm_weapons::give_fallback_weapon(); + } + } + self waittill_notify_or_timeout( "weapon_change_complete", 3 ); + self takeweapon( meat_name ); + self.pre_meat_weapon = undefined; + if ( self.is_drinking ) + { + self decrement_is_drinking(); + } + self.dont_touch_the_meat = 0; +} + +cleanup_meat() +{ + if ( isDefined( self.altmodel ) ) + { + self.altmodel delete(); + } + self delete(); +} + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +animate_meat( grenade ) +{ + grenade waittill_any( "bounce", "stationary", "death" ); + waittillframeend; + if ( isDefined( grenade ) ) + { + grenade hide(); + altmodel = spawn( "script_model", grenade.origin ); + altmodel setmodel( get_gamemode_var( "item_meat_model" ) ); + altmodel useanimtree( -1 ); + altmodel.angles = grenade.angles; + altmodel linkto( grenade, "", ( 0, 0, 0 ), ( 0, 0, 0 ) ); + altmodel setanim( %o_zombie_head_idle_v1 ); + grenade.altmodel = altmodel; + while ( isDefined( grenade ) ) + { + wait 0,05; + } + if ( isDefined( altmodel ) ) + { + altmodel delete(); + } + } +} + +indexinarray( array, value ) +{ + if ( isDefined( array ) && isarray( array ) || !isDefined( value ) && !isinarray( array, value ) ) + { + return undefined; + } + _a686 = array; + index = getFirstArrayKey( _a686 ); + while ( isDefined( index ) ) + { + item = _a686[ index ]; + if ( item == value ) + { + return index; + } + index = getNextArrayKey( _a686, index ); + } + return undefined; +} + +item_meat_on_spawn_retrieve_trigger( watcher, player, weaponname ) +{ + self endon( "death" ); + add_meat_event( "meat_spawn", self ); + thread animate_meat( self ); + while ( isDefined( level.splitting_meat ) && level.splitting_meat ) + { + wait 0,15; + } + if ( isDefined( player ) ) + { + self setowner( player ); + self setteam( player.pers[ "team" ] ); + self.owner = player; + self.oldangles = self.angles; + if ( player hasweapon( weaponname ) ) + { + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + player thread player_wait_take_meat( weaponname ); + } + else + { + player takeweapon( weaponname ); + player decrement_is_drinking(); + } + } + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + if ( isDefined( self._respawned_meat ) && !self._respawned_meat ) + { + level notify( "meat_thrown" ); + level._last_person_to_throw_meat = player; + level._last_person_to_throw_meat_time = getTime(); + } + } + } + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + level._meat_moving = 1; + if ( isDefined( level.item_meat ) && level.item_meat != self ) + { + level.item_meat cleanup_meat(); + } + level.item_meat = self; + } + self thread item_meat_watch_stationary(); + self thread item_meat_watch_bounce(); + self.item_meat_pick_up_trigger = spawn( "trigger_radius_use", self.origin, 0, 36, 72 ); + self.item_meat_pick_up_trigger setcursorhint( "HINT_NOICON" ); + self.item_meat_pick_up_trigger sethintstring( &"ZOMBIE_MEAT_PICKUP" ); + self.item_meat_pick_up_trigger enablelinkto(); + self.item_meat_pick_up_trigger linkto( self ); + self.item_meat_pick_up_trigger triggerignoreteam(); + level.item_meat_pick_up_trigger = self.item_meat_pick_up_trigger; + self thread item_meat_watch_shutdown(); + self.meat_id = indexinarray( level._fake_meats, self ); + if ( !isDefined( self.meat_id ) ) + { + self.meat_id = 0; + } + if ( isDefined( level.dont_allow_meat_interaction ) && level.dont_allow_meat_interaction ) + { + self.item_meat_pick_up_trigger setinvisibletoall(); + } + else + { + self thread item_meat_watch_trigger( self.meat_id, self.item_meat_pick_up_trigger, ::item_meat_on_pickup, level.meat_pickupsoundplayer, level.meat_pickupsound ); + self thread kick_meat_monitor(); + self thread last_stand_meat_nudge(); + } + self._respawned_meat = undefined; +} + +last_stand_meat_nudge() +{ + level endon( "meat_grabbed" ); + level endon( "end_meat" ); + self endon( "death" ); + wait 0,15; + while ( 1 ) + { + players = get_players(); + _a789 = players; + _k789 = getFirstArrayKey( _a789 ); + while ( isDefined( _k789 ) ) + { + player = _a789[ _k789 ]; + if ( distancesquared( player.origin, self.origin ) < 2304 && player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + player thread kick_the_meat( self, 1 ); + } + _k789 = getNextArrayKey( _a789, _k789 ); + } + wait 0,05; + } +} + +kick_meat_monitor() +{ + level endon( "meat_grabbed" ); + level endon( "end_meat" ); + self endon( "death" ); + kick_meat_timeout = 150; + while ( 1 ) + { + players = get_players(); + curr_time = getTime(); + _a813 = players; + _k813 = getFirstArrayKey( _a813 ); + while ( isDefined( _k813 ) ) + { + player = _a813[ _k813 ]; + if ( isDefined( level._last_person_to_throw_meat ) && player == level._last_person_to_throw_meat && ( curr_time - level._last_person_to_throw_meat_time ) <= kick_meat_timeout ) + { + } + else + { + if ( distancesquared( player.origin, self.origin ) < 2304 && player issprinting() && !player usebuttonpressed() ) + { + if ( isDefined( player._meat_team ) && isDefined( level._meat_on_team ) && level._meat_on_team == player._meat_team ) + { + add_meat_event( "player_kick_meat", player, self ); + player thread kick_the_meat( self ); + } + } + } + _k813 = getNextArrayKey( _a813, _k813 ); + } + wait 0,05; + } +} + +is_meat( weapon ) +{ + return weapon == get_gamemode_var( "item_meat_name" ); +} + +spike_the_meat( meat ) +{ + if ( isDefined( self._kicking_meat ) && self._kicking_meat ) + { + return; + } + fake_meat = 0; + self._kicking_meat = 1; + self._spawning_meat = 1; + org = self getweaponmuzzlepoint(); + vel = meat getvelocity(); + if ( isDefined( meat._fake_meat ) && !meat._fake_meat ) + { + meat cleanup_meat(); + level._last_person_to_throw_meat = self; + level._last_person_to_throw_meat_time = getTime(); + level._meat_splitter_activated = 0; + } + else + { + fake_meat = 1; + meat cleanup_meat(); + } + kickangles = self.angles; + kickangles += ( randomfloatrange( -30, -20 ), randomfloatrange( -5, 5 ), 0 ); + launchdir = anglesToForward( kickangles ); + speed = length( vel ) * 1,5; + launchvel = vectorScale( launchdir, speed ); + grenade = self magicgrenadetype( get_gamemode_var( "item_meat_name" ), org, ( launchvel[ 0 ], launchvel[ 1 ], 380 ) ); + grenade playsound( "zmb_meat_meat_tossed" ); + grenade thread waittill_loopstart(); + if ( fake_meat ) + { + grenade._fake_meat = 1; + grenade thread delete_on_real_meat_pickup(); + level._kicked_meat = grenade; + } + wait 0,1; + self._spawning_meat = 0; + self._kicking_meat = 0; + if ( !fake_meat ) + { + level notify( "meat_thrown" ); + level notify( "meat_kicked" ); + } +} + +show_meat_throw_hint() +{ + level endon( "meat_thrown" ); + self endon( "player_downed" ); + self thread meat_screen_message_delete_on_death(); + wait 1; + self meat_create_hint_message( &"ZOMBIE_THROW_MEAT_HINT" ); + self thread meat_screen_message_delete(); +} + +meat_create_hint_message( string_message_1, string_message_2, string_message_3, n_offset_y ) +{ + if ( !isDefined( n_offset_y ) ) + { + n_offset_y = 0; + } + if ( !isDefined( self._screen_message_1 ) ) + { + self._screen_message_1 = newclienthudelem( self ); + self._screen_message_1.elemtype = "font"; + self._screen_message_1.font = "objective"; + self._screen_message_1.fontscale = 1,8; + self._screen_message_1.horzalign = "center"; + self._screen_message_1.vertalign = "middle"; + self._screen_message_1.alignx = "center"; + self._screen_message_1.aligny = "middle"; + self._screen_message_1.y = -60 + n_offset_y; + self._screen_message_1.sort = 2; + self._screen_message_1.color = ( 0, 0, 0 ); + self._screen_message_1.alpha = 0,7; + self._screen_message_1.hidewheninmenu = 1; + } + self._screen_message_1 settext( string_message_1 ); + if ( isDefined( string_message_2 ) ) + { + if ( !isDefined( self._screen_message_2 ) ) + { + self._screen_message_2 = newclienthudelem( self ); + self._screen_message_2.elemtype = "font"; + self._screen_message_2.font = "objective"; + self._screen_message_2.fontscale = 1,8; + self._screen_message_2.horzalign = "center"; + self._screen_message_2.vertalign = "middle"; + self._screen_message_2.alignx = "center"; + self._screen_message_2.aligny = "middle"; + self._screen_message_2.y = -33 + n_offset_y; + self._screen_message_2.sort = 2; + self._screen_message_2.color = ( 0, 0, 0 ); + self._screen_message_2.alpha = 0,7; + self._screen_message_2.hidewheninmenu = 1; + } + level._screen_message_2 settext( string_message_2 ); + } + else + { + if ( isDefined( self._screen_message_2 ) ) + { + self._screen_message_2 destroy(); + } + } + if ( isDefined( string_message_3 ) ) + { + if ( !isDefined( self._screen_message_3 ) ) + { + self._screen_message_3 = newclienthudelem( self ); + self._screen_message_3.elemtype = "font"; + self._screen_message_3.font = "objective"; + self._screen_message_3.fontscale = 1,8; + self._screen_message_3.horzalign = "center"; + self._screen_message_3.vertalign = "middle"; + self._screen_message_3.alignx = "center"; + self._screen_message_3.aligny = "middle"; + self._screen_message_3.y = -6 + n_offset_y; + self._screen_message_3.sort = 2; + self._screen_message_3.color = ( 0, 0, 0 ); + self._screen_message_3.alpha = 0,7; + self._screen_message_3.hidewheninmenu = 1; + } + self._screen_message_3 settext( string_message_3 ); + } + else + { + if ( isDefined( self._screen_message_3 ) ) + { + self._screen_message_3 destroy(); + } + } +} + +meat_screen_message_delete() +{ + self endon( "disconnect" ); + level waittill_notify_or_timeout( "meat_thrown", 5 ); + if ( isDefined( self._screen_message_1 ) ) + { + self._screen_message_1 destroy(); + } + if ( isDefined( self._screen_message_2 ) ) + { + self._screen_message_2 destroy(); + } + if ( isDefined( self._screen_message_3 ) ) + { + self._screen_message_3 destroy(); + } +} + +meat_screen_message_delete_on_death() +{ + level endon( "meat_thrown" ); + self endon( "disconnect" ); + self waittill( "player_downed" ); + if ( isDefined( self._screen_message_1 ) ) + { + self._screen_message_1 destroy(); + } + if ( isDefined( self._screen_message_2 ) ) + { + self._screen_message_2 destroy(); + } + if ( isDefined( self._screen_message_3 ) ) + { + self._screen_message_3 destroy(); + } +} + +set_ignore_all() +{ + level endon( "clear_ignore_all" ); + if ( isDefined( level._zombies_ignoring_all ) && level._zombies_ignoring_all ) + { + return; + } + level._zombies_ignoring_all = 1; + zombies = getaiarray( level.zombie_team ); + _a1051 = zombies; + _k1051 = getFirstArrayKey( _a1051 ); + while ( isDefined( _k1051 ) ) + { + zombie = _a1051[ _k1051 ]; + if ( isDefined( zombie ) ) + { + zombie.ignoreall = 1; + } + _k1051 = getNextArrayKey( _a1051, _k1051 ); + } + wait 0,5; + clear_ignore_all(); +} + +clear_ignore_all() +{ + if ( isDefined( level._zombies_ignoring_all ) && !level._zombies_ignoring_all ) + { + return; + } + zombies = getaiarray( level.zombie_team ); + _a1070 = zombies; + _k1070 = getFirstArrayKey( _a1070 ); + while ( isDefined( _k1070 ) ) + { + zombie = _a1070[ _k1070 ]; + if ( isDefined( zombie ) ) + { + zombie.ignoreall = 0; + } + _k1070 = getNextArrayKey( _a1070, _k1070 ); + } + level._zombies_ignoring_all = 0; +} + +bring_back_teammate_progress() +{ + self notify( "bring_back_teammate_progress" ); + self endon( "bring_back_teammate_progress" ); + self endon( "disconnect" ); + player = self; + player._bringing_back_teammate = 1; + revivetime = 15; + progress = 0; + while ( player_has_meat( player ) && is_player_valid( player ) && progress >= 0 ) + { + if ( !isDefined( player.revive_team_progressbar ) ) + { + player.revive_team_progressbar = player createprimaryprogressbar(); + player.revive_team_progressbar updatebar( 0,01, 1 / revivetime ); + player.revive_team_progressbar.progresstext = player createprimaryprogressbartext(); + player.revive_team_progressbar.progresstext settext( &"ZOMBIE_MEAT_RESPAWN_TEAMMATE" ); + player thread destroy_revive_progress_on_downed(); + } + progress++; + if ( progress > ( revivetime * 10 ) ) + { + level bring_back_dead_teammate( player._meat_team ); + player destroy_revive_progress(); + wait 1; + player._bringing_back_teammate = 0; + progress = -1; + } + wait 0,1; + } + player._bringing_back_teammate = 0; + player destroy_revive_progress(); +} + +should_try_to_bring_back_teammate( team ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ]._meat_team == team && players[ i ].sessionstate == "spectator" ) + { + return 1; + } + i++; + } + return 0; +} + +bring_back_dead_teammate( team ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ]._meat_team == team && players[ i ].sessionstate == "spectator" ) + { + player = players[ i ]; + break; + } + else + { + i++; + } + } + if ( !isDefined( player ) ) + { + return; + } + player playsound( level.zmb_laugh_alias ); + wait 0,25; + playfx( level._effect[ "poltergeist" ], player.spectator_respawn.origin ); + playsoundatposition( "zmb_bolt", player.spectator_respawn.origin ); + earthquake( 0,5, 0,75, player.spectator_respawn.origin, 1000 ); + level.custom_spawnplayer = ::respawn_meat_player; + player.pers[ "spectator_respawn" ] = player.spectator_respawn; + player [[ level.spawnplayer ]](); + level.custom_spawnplayer = undefined; +} + +respawn_meat_player() +{ + spawnpoint = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "meat_spectator_respawn" ); + self spawn( spawnpoint.origin, spawnpoint.angles ); + self._meat_team = self.pers[ "zteam" ]; + self._encounters_team = self.pers[ "encounters_team" ]; + self.characterindex = self.pers[ "characterindex" ]; + self._team_name = self.pers[ "team_name" ]; + self.spectator_respawn = self.pers[ "meat_spectator_respawn" ]; + self reviveplayer(); + self.is_burning = 0; + self.is_zombie = 0; + self.ignoreme = 0; +} + +destroy_revive_progress_on_downed() +{ + level endon( "end_game" ); + level endon( "meat_end" ); + self waittill_any( "fake_death", "player_downed", "death" ); + self destroy_revive_progress(); +} + +destroy_revive_progress() +{ + if ( isDefined( self.revive_team_progressbar ) ) + { + self.revive_team_progressbar destroyelem(); + self.revive_team_progressbar.progresstext destroyelem(); + } +} + +kick_the_meat( meat, laststand_nudge ) +{ + if ( isDefined( self._kicking_meat ) && self._kicking_meat ) + { + return; + } + fake_meat = 0; + self._kicking_meat = 1; + self._spawning_meat = 1; + org = meat.origin; + if ( isDefined( meat._fake_meat ) && !meat._fake_meat ) + { + meat cleanup_meat(); + level._last_person_to_throw_meat = self; + level._last_person_to_throw_meat_time = getTime(); + level._meat_splitter_activated = 0; + } + else + { + fake_meat = 1; + meat cleanup_meat(); + } + kickangles = self.angles; + kickangles += ( randomfloatrange( -30, -20 ), randomfloatrange( -5, 5 ), 0 ); + launchdir = anglesToForward( kickangles ); + vel = self getvelocity(); + speed = length( vel ) * 1,5; + height_boost = 380; + if ( isDefined( laststand_nudge ) && laststand_nudge ) + { + if ( vel == ( 0, 0, 0 ) ) + { + vel = ( 30, 30, 5 ); + } + speed = length( vel ) * 2; + height_boost = 120; + } + launchvel = vectorScale( launchdir, speed ); + grenade = self magicgrenadetype( get_gamemode_var( "item_meat_name" ), org, ( launchvel[ 0 ], launchvel[ 1 ], height_boost ) ); + grenade playsound( "zmb_meat_meat_tossed" ); + grenade thread waittill_loopstart(); + if ( fake_meat ) + { + grenade._fake_meat = 1; + grenade thread delete_on_real_meat_pickup(); + level._kicked_meat = grenade; + } + wait 0,1; + self._spawning_meat = 0; + self._kicking_meat = 0; + if ( !fake_meat ) + { + level notify( "meat_thrown" ); + level notify( "meat_kicked" ); + } +} + +delete_on_real_meat_pickup() +{ + if ( isDefined( self._fake_meat ) && !self._fake_meat ) + { + return; + } + self endon( "death" ); + level waittill_any( "meat_grabbed", "end_game", "meat_kicked" ); + add_meat_event( "fake_meat_killed_by_real", self ); + if ( isDefined( level._kicked_meat ) && level._kicked_meat == self ) + { + level._kicked_meat = undefined; + } + if ( isDefined( self ) ) + { + self cleanup_meat(); + } +} + +play_item_meat_on_spawn_retrieve_trigger( watcher, player ) +{ + self item_meat_on_spawn_retrieve_trigger( watcher, player, get_gamemode_var( "item_meat_name" ) ); +} + +can_revive( revivee ) +{ + if ( self hasweapon( get_gamemode_var( "item_meat_name" ) ) ) + { + return 0; + } + if ( !self maps/mp/zombies/_zm_laststand::is_reviving_any() && isDefined( level.item_meat_pick_up_trigger ) && self istouching( level.item_meat_pick_up_trigger ) ) + { + return 0; + } + return 1; +} + +pickup_origin() +{ + origin = self get_eye(); + if ( !isDefined( origin ) ) + { + origin = self gettagorigin( "tag_weapon" ); + } + if ( !isDefined( origin ) ) + { + origin = self gettagorigin( "tag_weapon_right" ); + } + if ( !isDefined( origin ) ) + { + origin = self.origin; + } + return origin; +} + +can_spike_meat() +{ + if ( isDefined( level._last_person_to_throw_meat ) && self == level._last_person_to_throw_meat ) + { + return 0; + } + meat = level.item_meat; + meat_spike_dist_sq = 4096; + meat_spike_dot = 0,1; + if ( isDefined( meat ) ) + { + view_pos = self getweaponmuzzlepoint(); + if ( distancesquared( view_pos, meat.origin ) < meat_spike_dist_sq ) + { + return 1; + } + } + return 0; +} + +start_encounters_round_logic() +{ + if ( isDefined( level.flag[ "start_zombie_round_logic" ] ) ) + { + flag_wait( "start_zombie_round_logic" ); + } + flag_wait( "initial_players_connected" ); + if ( !flag( "start_encounters_match_logic" ) ) + { + flag_set( "start_encounters_match_logic" ); + } +} + +onstartgametype() +{ + thread start_encounters_round_logic(); + maps/mp/gametypes_zm/_zm_gametype::rungametypemain( "zmeat", ::meat_hub_start_func, 1 ); +} + +hide_non_meat_objects() +{ + door_trigs = getentarray( "zombie_door", "targetname" ); + i = 0; + while ( i < door_trigs.size ) + { + if ( isDefined( door_trigs[ i ] ) ) + { + door_trigs[ i ] delete(); + } + i++; + } + objects = getentarray(); + i = 0; + while ( i < objects.size ) + { + if ( objects[ i ] is_meat_object() ) + { + i++; + continue; + } + else if ( objects[ i ] iszbarrier() ) + { + i++; + continue; + } + else + { + if ( isDefined( objects[ i ].spawnflags ) && objects[ i ].spawnflags == 1 ) + { + objects[ i ] connectpaths(); + } + objects[ i ] notsolid(); + objects[ i ] hide(); + } + i++; + } +} + +is_meat_object() +{ + if ( !isDefined( self.script_parameters ) ) + { + return 1; + } + tokens = strtok( self.script_parameters, " " ); + i = 0; + while ( i < tokens.size ) + { + if ( tokens[ i ] == "meat_remove" ) + { + return 0; + } + i++; + } + return 1; +} + +setup_meat_world_objects() +{ + objects = getentarray( level.scr_zm_map_start_location, "script_noteworthy" ); + i = 0; + while ( i < objects.size ) + { + if ( !objects[ i ] is_meat_object() ) + { + i++; + continue; + } + else if ( isDefined( objects[ i ].script_gameobjectname ) ) + { + i++; + continue; + } + else + { + if ( isDefined( objects[ i ].script_vector ) ) + { + objects[ i ] moveto( objects[ i ].origin + objects[ i ].script_vector, 0,05 ); + objects[ i ] waittill( "movedone" ); + } + if ( isDefined( objects[ i ].spawnflags ) && objects[ i ].spawnflags == 1 && isDefined( level._dont_reconnect_paths ) && !level._dont_reconnect_paths ) + { + objects[ i ] disconnectpaths(); + } + } + i++; + } + level clientnotify( "meat_" + level.scr_zm_map_start_location ); +} + +spawn_meat_zombies() +{ + level endon( "meat_end" ); + force_riser = 0; + force_chaser = 0; + num = 0; + max_ai_num = 15; + if ( getDvarInt( #"CD22CF55" ) > 0 ) + { + max_ai_num = 0; + } + if ( getDvarInt( "zombie_cheat" ) == 2 ) + { + max_ai_num = -1; + } + level waittill( "meat_grabbed" ); + while ( 1 ) + { + ai = getaiarray( level.zombie_team ); + if ( ai.size > max_ai_num ) + { + wait 0,1; + } + else + { + if ( ( num % 2 ) == 0 ) + { + spawn_points = level._meat_team_1_zombie_spawn_points; + num++; + continue; + } + else + { + spawn_points = level._meat_team_2_zombie_spawn_points; + } + num++; + spawn_point = undefined; + dist = 512; + distcheck = dist * dist; + startindex = randomint( spawn_points.size ); + while ( !isDefined( spawn_point ) ) + { + i = 0; + while ( i < spawn_points.size ) + { + index = ( startindex + i ) % spawn_points.size; + point = spawn_points[ index ]; + if ( ( num % 2 ) == 0 ) + { + players = get_players_on_meat_team( 1 ); + } + else + { + players = get_players_on_meat_team( 2 ); + } + clear = 1; + _a1503 = players; + _k1503 = getFirstArrayKey( _a1503 ); + while ( isDefined( _k1503 ) ) + { + player = _a1503[ _k1503 ]; + if ( distancesquared( player.origin, point.origin ) < distcheck ) + { + clear = 0; + } + _k1503 = getNextArrayKey( _a1503, _k1503 ); + } + if ( clear ) + { + spawn_point = point; + break; + } + else + { + i++; + } + } + if ( dist <= 128 ) + { + spawn_point = point; + } + else + { + dist /= 4; + distcheck = dist * dist; + } + wait 0,05; + } + zombie = spawn_meat_zombie( level.meat_spawners[ 0 ], "meat_zombie", spawn_point, level._meat_zombie_spawn_health ); + if ( isDefined( zombie ) ) + { + zombie maps/mp/zombies/_zm_game_module::make_supersprinter(); + } + } + wait level._meat_zombie_spawn_timer; + } +} + +spawn_meat_zombie( spawner, target_name, spawn_point, round_number ) +{ + level endon( "meat_end" ); + if ( !isDefined( spawner ) ) + { + iprintlnbold( "BUG: There is something wrong with the zombie spawners" ); + return; + } + while ( isDefined( level._meat_zombie_spawning ) && level._meat_zombie_spawning ) + { + wait 0,05; + } + level._meat_zombie_spawning = 1; + level.zombie_spawn_locations = []; + level.zombie_spawn_locations[ level.zombie_spawn_locations.size ] = spawn_point; + zombie = maps/mp/zombies/_zm_utility::spawn_zombie( spawner, target_name, spawn_point, round_number ); + if ( isDefined( zombie ) ) + { + zombie thread maps/mp/zombies/_zm_spawner::zombie_spawn_init(); + zombie thread maps/mp/zombies/_zm::round_spawn_failsafe(); + } + else + { + iprintlnbold( "BUG: There is something wrong with the zombie spawning" ); + } + spawner._spawning = undefined; + level._meat_zombie_spawning = 0; + return zombie; +} + +monitor_meat_on_team() +{ + level endon( "meat_end" ); + while ( 1 ) + { + players = get_players(); + if ( isDefined( level._meat_on_team ) ) + { + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ] ) ) + { + i++; + continue; + } + else + { + if ( players[ i ]._meat_team == level._meat_on_team ) + { + if ( players[ i ].ignoreme ) + { + players[ i ].ignoreme = 0; + } + } + else + { + if ( !players[ i ].ignoreme ) + { + players[ i ].ignoreme = 1; + } + } + wait 0,05; + } + i++; + } + } + else i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ] ) ) + { + i++; + continue; + } + else + { + if ( players[ i ].ignoreme ) + { + players[ i ].ignoreme = 0; + } + wait 0,05; + } + i++; + } + wait 0,1; + } +} + +item_meat_reset( origin, immediate ) +{ + level notify( "new_meat" ); + level endon( "new_meat" ); + if ( isDefined( level.item_meat ) ) + { + level.item_meat cleanup_meat(); + level.item_meat = undefined; + } + if ( isDefined( immediate ) && !immediate ) + { + level waittill( "reset_meat" ); + } + item_meat_clear(); + if ( isDefined( origin ) ) + { + item_meat_spawn( origin ); + } +} + +meat_player_initial_spawn() +{ + players = get_players(); + one = 1; + two = 2; + if ( get_game_var( "switchedsides" ) ) + { + one = 2; + two = 1; + } + i = 0; + while ( i < players.size ) + { + if ( get_game_var( "side_selection" ) == 1 ) + { + if ( players[ i ].team == "allies" ) + { + players[ i ]._meat_team = one; + } + else + { + players[ i ]._meat_team = two; + } + } + else if ( players[ i ].team == "allies" ) + { + players[ i ]._meat_team = two; + } + else + { + players[ i ]._meat_team = one; + } + if ( isDefined( level.custom_player_fake_death_cleanup ) ) + { + players[ i ] [[ level.custom_player_fake_death_cleanup ]](); + } + players[ i ] setstance( "stand" ); + if ( isDefined( players[ i ]._meat_team ) ) + { + if ( players[ i ]._meat_team == one ) + { + players[ i ]._meat_team = one; + } + else + { + players[ i ]._meat_team = two; + } + } + else if ( players[ i ].team == "axis" ) + { + players[ i ]._meat_team = one; + } + else + { + players[ i ]._meat_team = two; + } + players[ i ] meat_player_setup(); + i++; + } + waittillframeend; + maps/mp/gametypes_zm/_zm_gametype::start_round(); + award_grenades_for_team( 1 ); + award_grenades_for_team( 2 ); +} + +meat_player_setup() +{ + self.pers[ "zteam" ] = self._meat_team; + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "encounters_team", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "characterindex", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "team_name", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "spectator_respawn", 0 ); + self.pers[ "encounters_team" ] = self._encounters_team; + self.pers[ "characterindex" ] = self.characterindex; + self.pers[ "team_name" ] = self._team_name; + self.pers[ "meat_spectator_respawn" ] = self.spectator_respawn; + self.score = 1000; + self.pers[ "score" ] = 1000; + self takeallweapons(); + self giveweapon( "knife_zm" ); + self give_start_weapon( 1 ); + if ( !isDefined( self._saved_by_throw ) ) + { + self._saved_by_throw = 0; + } + self setmovespeedscale( 1 ); + self._has_meat = 0; + self setclientfield( "holding_meat", 0 ); + self freeze_player_controls( 1 ); +} + +can_touch_meat() +{ + if ( isDefined( self.dont_touch_the_meat ) && self.dont_touch_the_meat ) + { + return 0; + } + meat = level.item_meat; + if ( isDefined( meat ) ) + { + meatorg = meat.origin + vectorScale( ( 0, 0, 0 ), 8 ); + trace = bullettrace( self pickup_origin(), meatorg, 0, meat ); + return distancesquared( trace[ "position" ], meatorg ) < 1; + } + return 0; +} + +trying_to_use() +{ + self.use_ever_released |= !self usebuttonpressed(); + if ( self.use_ever_released ) + { + return self usebuttonpressed(); + } +} + +trying_to_spike( item ) +{ + if ( item.meat_is_flying ) + { + return self meleebuttonpressed(); + } +} + +item_quick_trigger( meat_id, trigger ) +{ + self endon( "death" ); + meat_trigger_time = 150; + if ( isDefined( trigger.radius ) ) + { + radius = trigger.radius + 15; + } + else + { + radius = 51; + } + trigrad2 = radius * radius; + players = get_players(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + player.use_ever_released = !player usebuttonpressed(); + i++; + } + while ( isDefined( trigger ) ) + { + trigorg = trigger.origin; + players = get_players(); + while ( players.size ) + { + random_start_point = randomint( players.size ); + i = 0; + while ( i < players.size ) + { + player = players[ ( i + random_start_point ) % players.size ]; + if ( !isDefined( player.trying_to_trigger_meat ) ) + { + player.trying_to_trigger_meat = []; + } + if ( !isDefined( player.trying_to_trigger_meat_time ) ) + { + player.trying_to_trigger_meat_time = []; + } + if ( player maps/mp/zombies/_zm_laststand::is_reviving_any() ) + { + i++; + continue; + } + else meleeing = player ismeleeing(); + if ( isDefined( trigger ) && player istouching( trigger ) && distance2dsquared( player.origin, trigorg ) < trigrad2 && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && !player trying_to_use() && self.meat_is_flying && meleeing && player can_touch_meat() ) + { + if ( self.meat_is_flying && meleeing ) + { + if ( player can_spike_meat() ) + { + player.trying_to_trigger_meat[ meat_id ] = 0; + trigger notify( "usetrigger" ); + } + } + else + { + if ( isDefined( player.trying_to_trigger_meat[ meat_id ] ) && !player.trying_to_trigger_meat[ meat_id ] ) + { + player.trying_to_trigger_meat[ meat_id ] = 1; + player.trying_to_trigger_meat_time[ meat_id ] = getTime(); + break; + } + else + { + if ( ( getTime() - player.trying_to_trigger_meat_time[ meat_id ] ) >= meat_trigger_time ) + { + player.trying_to_trigger_meat[ meat_id ] = 0; + trigger notify( "usetrigger" ); + } + } + } + i++; + continue; + } + else + { + player.trying_to_trigger_meat[ meat_id ] = 0; + } + i++; + } + } + wait 0,05; + } +} + +item_meat_watch_trigger( meat_id, trigger, callback, playersoundonuse, npcsoundonuse ) +{ + self endon( "death" ); + self thread item_quick_trigger( meat_id, trigger ); + while ( 1 ) + { + trigger waittill( "usetrigger", player ); + while ( !isalive( player ) ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + continue; + } + while ( player has_powerup_weapon() ) + { + continue; + } + while ( player maps/mp/zombies/_zm_laststand::is_reviving_any() ) + { + continue; + } + if ( self.meat_is_flying ) + { + volley = player meleebuttonpressed(); + } + player.volley_meat = volley; + if ( isDefined( self._fake_meat ) && self._fake_meat ) + { + add_meat_event( "player_fake_take", player, self ); + } + else + { + if ( volley ) + { + add_meat_event( "player_volley", player, self ); + break; + } + else if ( self.meat_is_moving ) + { + add_meat_event( "player_catch", player, self ); + break; + } + else + { + add_meat_event( "player_take", player, self ); + } + } + if ( isDefined( self._fake_meat ) && self._fake_meat ) + { + player playlocalsound( level.zmb_laugh_alias ); + wait_network_frame(); + if ( !isDefined( self ) ) + { + return; + } + self cleanup_meat(); + return; + } + curr_weap = player getcurrentweapon(); + if ( !is_meat( curr_weap ) ) + { + player.pre_meat_weapon = curr_weap; + } + if ( self.meat_is_moving ) + { + if ( volley ) + { + self item_meat_volley( player ); + break; + } + else + { + self item_meat_caught( player, self.meat_is_flying ); + } + } + self item_meat_pickup(); + if ( isDefined( playersoundonuse ) ) + { + player playlocalsound( playersoundonuse ); + } + if ( isDefined( npcsoundonuse ) ) + { + player playsound( npcsoundonuse ); + } + if ( volley ) + { + player thread spike_the_meat( self ); + continue; + } + else + { + self thread [[ callback ]]( player ); + if ( !isDefined( player._meat_hint_shown ) ) + { + player thread show_meat_throw_hint(); + player._meat_hint_shown = 1; + } + } + } +} + +item_meat_volley( player ) +{ +/# + println( "MEAT: Spiked the meat\n" ); +#/ +} + +item_meat_caught( player, in_air ) +{ + if ( in_air ) + { +/# + println( "MEAT: Caught the meat on the fly\n" ); +#/ + } + else + { +/# + println( "MEAT: Caught the meat while moving\n" ); +#/ + } +} + +item_meat_on_pickup( player ) +{ +/# + assert( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand(), "Player in last stand triggered meat pickup" ); +#/ + player maps/mp/gametypes_zm/_weaponobjects::deleteweaponobjecthelper( self ); + self cleanup_meat(); + level.item_meat = undefined; + level._last_person_to_throw_meat = undefined; + assign_meat_to_team( player ); + level notify( "meat_grabbed" ); + player notify( "meat_grabbed" ); + level thread zmbvoxmeatonteamspecific( player._encounters_team ); + if ( !player hasweapon( get_gamemode_var( "item_meat_name" ) ) ) + { + player giveweapon( get_gamemode_var( "item_meat_name" ) ); + } + player increment_is_drinking(); + player switchtoweapon( get_gamemode_var( "item_meat_name" ) ); + player setweaponammoclip( get_gamemode_var( "item_meat_name" ), 2 ); + player thread waittill_thrown(); +} + +waittill_thrown() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "reset_downed" ); + self waittill( "grenade_fire", grenade ); + grenade playsound( "zmb_meat_meat_tossed" ); + grenade thread waittill_loopstart(); +} + +waittill_loopstart() +{ + self endon( "stationary" ); + self endon( "death" ); + level endon( "meat_grabbed" ); + level endon( "end_game" ); + level endon( "meat_kicked" ); + while ( 1 ) + { + self waittill( "grenade_bounce", pos, normal, ent ); + self stopsounds(); + wait 0,05; + self playsound( "zmb_meat_bounce" ); + } +} + +item_meat_watch_shutdown() +{ + self waittill( "death" ); + if ( isDefined( self.item_meat_pick_up_trigger ) ) + { + self.item_meat_pick_up_trigger delete(); + level.item_meat_pick_up_trigger = undefined; + } +} + +item_meat_clear() +{ + if ( isDefined( level.item_meat ) ) + { + level.item_meat cleanup_meat(); + level.item_meat = undefined; + } + if ( isDefined( level._fake_meats ) ) + { + _a2090 = level._fake_meats; + _k2090 = getFirstArrayKey( _a2090 ); + while ( isDefined( _k2090 ) ) + { + meat = _a2090[ _k2090 ]; + if ( isDefined( meat ) ) + { + meat cleanup_meat(); + } + _k2090 = getNextArrayKey( _a2090, _k2090 ); + } + level._fake_meats = undefined; + } +} + +zombie_path_timer_override() +{ + return getTime() + ( randomfloatrange( 0,35, 1 ) * 1000 ); +} + +meat_poi_override_func() +{ + if ( isDefined( level.item_meat ) && isDefined( level.item_meat.meat_is_moving ) && level.item_meat.meat_is_moving ) + { + if ( abs( level.item_meat.origin[ 2 ] - groundpos( level.item_meat.origin )[ 2 ] ) < 35 ) + { + level._zombies_ignoring_all = 0; + level notify( "clear_ignore_all" ); + return undefined; + } + level thread set_ignore_all(); + meat_poi = []; + meat_poi[ 0 ] = groundpos( level.item_meat.origin ); + meat_poi[ 1 ] = level.item_meat; + return meat_poi; + } + level._zombies_ignoring_all = 0; + return undefined; +} + +meat_end_match( winning_team ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ].has_minigun ) && players[ i ].has_minigun ) + { + primaryweapons = players[ i ] getweaponslistprimaries(); + x = 0; + while ( x < primaryweapons.size ) + { + if ( primaryweapons[ x ] == "minigun_zm" ) + { + players[ i ] takeweapon( "minigun_zm" ); + } + x++; + } + players[ i ] notify( "minigun_time_over" ); + players[ i ].zombie_vars[ "zombie_powerup_minigun_on" ] = 0; + players[ i ]._show_solo_hud = 0; + players[ i ].has_minigun = 0; + players[ i ].has_powerup_weapon = 0; + } + if ( isDefined( players[ i ]._has_meat_hud ) ) + { + players[ i ]._has_meat_hud destroy(); + } + if ( players[ i ] hasweapon( get_gamemode_var( "item_meat_name" ) ) ) + { + players[ i ] takeweapon( get_gamemode_var( "item_meat_name" ) ); + players[ i ] decrement_is_drinking(); + } + i++; + } + level notify( "game_module_ended" ); + wait 0,1; + level delay_thread( 2, ::item_meat_clear ); + if ( isDefined( level.gameended ) && level.gameended ) + { + level clientnotify( "end_meat" ); + } +} + +updatedownedcounters() +{ + if ( self._encounters_team == "A" ) + { + level.team_a_downed++; + self thread waitforrevive( "A" ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_revive_" + level.team_a_downed, "A" ); + } + else + { + level.team_b_downed++; + self thread waitforrevive( "B" ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_revive_" + level.team_b_downed, "B" ); + } +} + +waitforrevive( team ) +{ + self endon( "death" ); + self waittill( "player_revived" ); + if ( team == "A" ) + { + level.team_a_downed--; + + } + else + { + level.team_b_downed--; + + } +} + +assign_meat_to_team( player, team_num ) +{ + meat_team = undefined; + players = get_players(); + if ( isDefined( player ) ) + { + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ] ) ) + { + i++; + continue; + } + else + { + if ( players[ i ] != player || isDefined( player._meat_hint_shown ) && player._meat_hint_shown ) + { + players[ i ] iprintlnbold( &"ZOMBIE_GRABBED_MEAT", player.name ); + } + } + i++; + } + meat_team = player._meat_team; + } + else + { + if ( isDefined( team_num ) ) + { + i = 0; + while ( i < players.size ) + { + if ( players[ i ]._meat_team == team_num ) + { + players[ i ] iprintlnbold( &"ZOMBIE_YOUR_TEAM_MEAT" ); + i++; + continue; + } + else + { + players[ i ] iprintlnbold( &"ZOMBIE_OTHER_TEAM_MEAT" ); + } + i++; + } + meat_team = team_num; + } + } + level._meat_on_team = meat_team; + teamplayers = get_players_on_meat_team( meat_team ); + if ( isDefined( teamplayers ) && teamplayers.size > 0 ) + { + if ( teamplayers[ 0 ]._encounters_team == "B" ) + { + setteamhasmeat( "allies", 1 ); + setteamhasmeat( "axis", 0 ); + } + else + { + if ( teamplayers[ 0 ]._encounters_team == "A" ) + { + setteamhasmeat( "allies", 0 ); + setteamhasmeat( "axis", 1 ); + } + } + } + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ] ) ) + { + i++; + continue; + } + else if ( isDefined( player ) && players[ i ] == player ) + { + if ( isDefined( players[ i ]._has_meat ) && players[ i ]._has_meat ) + { + i++; + continue; + } + else + { + players[ i ]._has_meat = 1; + players[ i ] thread slow_down_player_with_meat(); + players[ i ] thread reset_meat_when_player_downed(); + players[ i ] thread reset_meat_when_player_disconnected(); + i++; + continue; + } + } + i++; + } +} + +zmbvoxmeatonteamspecific( team ) +{ + if ( !isDefined( level.zmbvoxteamlasthadmeat ) ) + { + level.zmbvoxteamlasthadmeat = team; + } + if ( level.zmbvoxteamlasthadmeat == team ) + { + return; + } + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_grab", team ); + level.zmbvoxteamlasthadmeat = team; + otherteam = maps/mp/zombies/_zm_audio_announcer::getotherteam( team ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_grab_" + otherteam, otherteam ); +} + +create_meat_team_hud( meat_team, destroy_only ) +{ + if ( isDefined( self._has_meat_hud ) ) + { + self._has_meat_hud destroy(); + if ( isDefined( destroy_only ) ) + { + return; + } + } + if ( !isDefined( meat_team ) ) + { + return; + } + elem = newclienthudelem( self ); + elem.hidewheninmenu = 1; + elem.horzalign = "LEFT"; + elem.vertalign = "BOTTOM"; + elem.alignx = "left"; + elem.aligny = "middle"; + elem.x = 10; + elem.y = -10; + elem.foreground = 1; + elem.font = "default"; + elem.fontscale = 1,4; + elem.color = vectorScale( ( 0, 0, 0 ), 0,9 ); + elem.alpha = 1; + if ( isDefined( self._meat_team ) && self._meat_team == meat_team ) + { + elem.label = &"ZOMBIE_TEAM_HAS_MEAT"; + } + else + { + elem.label = &"ZOMBIE_OTHER_TEAM_HAS_MEAT"; + } + self._has_meat_hud = elem; +} + +create_meat_player_hud() +{ + if ( isDefined( self._has_meat_hud ) ) + { + self._has_meat_hud destroy(); + } + elem = newclienthudelem( self ); + elem.hidewheninmenu = 1; + elem.horzalign = "LEFT"; + elem.vertalign = "BOTTOM"; + elem.alignx = "left"; + elem.aligny = "middle"; + elem.x = 10; + elem.y = -10; + elem.foreground = 1; + elem.font = "default"; + elem.fontscale = 1,4; + elem.color = vectorScale( ( 0, 0, 0 ), 0,9 ); + elem.alpha = 1; + elem.label = &"ZOMBIE_PLAYER_HAS_MEAT"; + self._has_meat_hud = elem; +} + +slow_down_player_with_meat() +{ + self endon( "disconnect" ); + self setclientfield( "holding_meat", 1 ); + self setmovespeedscale( 0,6 ); + self thread zmbvoxstartholdcounter(); + while ( isDefined( self._has_meat ) && self._has_meat ) + { + level._meat_player_tracker_origin = self.origin; + wait 0,2; + } + self setmovespeedscale( 1 ); + self setclientfield( "holding_meat", 0 ); +} + +zmbvoxstartholdcounter() +{ + meat_hold_counter = 0; + while ( isDefined( self._has_meat ) && self._has_meat ) + { + if ( meat_hold_counter >= 15 ) + { + self thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "meat_hold" ); + return; + } + else + { + wait 0,5; + meat_hold_counter++; + } + } +} + +reset_meat_when_player_downed() +{ + self notify( "reset_downed" ); + self endon( "reset_downed" ); + level endon( "meat_reset" ); + level endon( "meat_thrown" ); + self waittill_any( "player_downed", "death", "fake_death", "replace_weapon_powerup" ); + self._has_meat = 0; + self._spawning_meat = 1; + grenade = self magicgrenadetype( get_gamemode_var( "item_meat_name" ), self.origin + ( randomintrange( 5, 10 ), randomintrange( 5, 10 ), 15 ), ( randomintrange( 5, 10 ), randomintrange( 5, 10 ), 0 ) ); + grenade._respawned_meat = 1; + level._last_person_to_throw_meat = undefined; + playsoundatposition( "zmb_spawn_powerup", self.origin ); + wait 0,1; + self._spawning_meat = undefined; + level notify( "meat_reset" ); +} + +meat_last_stand_callback( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + if ( isDefined( self._has_meat ) && self._has_meat ) + { + level thread item_meat_drop( self.origin, self._meat_team ); + } +} + +reset_meat_when_player_disconnected() +{ + level endon( "meat_thrown" ); + level endon( "meat_reset" ); + level endon( "meat_end" ); + team = self._meat_team; + self waittill( "disconnect" ); + level thread item_meat_drop( level._meat_player_tracker_origin, team ); +} + +item_meat_drop( org, team ) +{ + players = get_alive_players_on_meat_team( team ); + if ( players.size > 0 ) + { + player = players[ 0 ]; + player endon( "disconnect" ); + player._spawning_meat = 1; + grenade = player magicgrenadetype( get_gamemode_var( "item_meat_name" ), org + ( randomintrange( 5, 10 ), randomintrange( 5, 10 ), 15 ), ( 0, 0, 0 ) ); + grenade._respawned_meat = 1; + level._last_person_to_throw_meat = undefined; + playsoundatposition( "zmb_spawn_powerup", grenade.origin ); + wait 0,1; + player._spawning_meat = undefined; + level notify( "meat_reset" ); + } +} + +player_has_meat( player ) +{ + return player getcurrentweapon() == get_gamemode_var( "item_meat_name" ); +} + +get_player_with_meat() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ]._has_meat ) && players[ i ]._has_meat ) + { + return players[ i ]; + } + i++; + } + return undefined; +} + +spawn_player_meat_manager() +{ + self thread player_watch_weapon_change(); + self thread player_watch_grenade_throw(); +} + +player_watch_weapon_change() +{ + self endon( "death_or_disconnect" ); + for ( ;; ) + { + self waittill( "weapon_change", weapon ); + if ( weapon == get_gamemode_var( "item_meat_name" ) ) + { + add_meat_event( "player_meat", self ); + continue; + } + else + { + add_meat_event( "player_no_meat", self ); + } + } +} + +player_watch_grenade_throw() +{ + self endon( "death_or_disconnect" ); + for ( ;; ) + { + self waittill( "grenade_fire", weapon, weapname ); + if ( weapname == get_gamemode_var( "item_meat_name" ) ) + { + add_meat_event( "player_grenade_fire", self, weapon ); + weapon thread item_meat_on_spawn_retrieve_trigger( undefined, self, get_gamemode_var( "item_meat_name" ) ); + } + } +} + +spawn_level_meat_manager() +{ +/# + level.meat_manager = spawnstruct(); + level.meat_manager.events = []; + level.meat_manager thread handle_meat_events(); +#/ +} + +add_meat_event( e, p1, p2, p3, p4 ) +{ +/# + event = spawnstruct(); + event.e = e; + event.numparams = 0; + event.param = []; + if ( isDefined( p1 ) ) + { + event.param[ 0 ] = p1; + event.numparams = 1; + } + if ( isDefined( p2 ) ) + { + event.param[ 1 ] = p2; + event.numparams = 2; + } + if ( isDefined( p3 ) ) + { + event.param[ 2 ] = p3; + event.numparams = 3; + } + if ( isDefined( p4 ) ) + { + event.param[ 3 ] = p4; + event.numparams = 4; + } + if ( isDefined( level.meat_manager ) ) + { + level.meat_manager.events[ level.meat_manager.events.size ] = event; +#/ + } +} + +handle_meat_events() +{ + while ( 1 ) + { + while ( self.events.size ) + { + self handle_meat_event( self.events[ 0 ] ); + arrayremoveindex( self.events, 0 ); + } + wait 0,05; + } +} + +paramstr( param ) +{ +/# + if ( !isDefined( param ) ) + { + return "undefined"; + } + if ( isplayer( param ) ) + { + return param.name; + } + if ( !isstring( param ) && !isint( param ) || isfloat( param ) && isvec( param ) ) + { + return param; + } + if ( isarray( param ) ) + { + return "[]"; + } + return ""; +#/ +} + +handle_meat_event( event ) +{ +/# + estr = "ZM MEAT: [" + event.e + "]("; + i = 0; + while ( i < event.numparams ) + { + estr += paramstr( event.param[ i ] ); + if ( i < ( event.numparams - 1 ) ) + { + estr += ","; + } + i++; + } + estr += ") \n"; + println( estr ); +#/ +} diff --git a/zm_transit_patch/maps/mp/gametypes_zm/zstandard.gsc b/zm_transit_patch/maps/mp/gametypes_zm/zstandard.gsc new file mode 100644 index 0000000..95e51ef --- /dev/null +++ b/zm_transit_patch/maps/mp/gametypes_zm/zstandard.gsc @@ -0,0 +1,43 @@ +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_ai_dogs; +#include maps/mp/zombies/_zm_stats; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::main(); + level.onprecachegametype = ::onprecachegametype; + level.onstartgametype = ::onstartgametype; + level._game_module_custom_spawn_init_func = ::maps/mp/gametypes_zm/_zm_gametype::custom_spawn_init_func; + level._game_module_stat_update_func = ::maps/mp/zombies/_zm_stats::survival_classic_custom_stat_update; + maps/mp/gametypes_zm/_zm_gametype::post_gametype_main( "zstandard" ); +} + +onprecachegametype() +{ + level.playersuicideallowed = 1; + level.canplayersuicide = ::canplayersuicide; + level.suicide_weapon = "death_self_zm"; + precacheitem( "death_self_zm" ); + maps/mp/zombies/_zm_ai_dogs::init(); + maps/mp/gametypes_zm/_zm_gametype::rungametypeprecache( "zstandard" ); +} + +onstartgametype() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_classic_gametype(); + maps/mp/gametypes_zm/_zm_gametype::rungametypemain( "zstandard", ::zstandard_main ); +} + +zstandard_main() +{ + level.dog_rounds_allowed = getgametypesetting( "allowdogs" ); + if ( level.dog_rounds_allowed ) + { + maps/mp/zombies/_zm_ai_dogs::enable_dog_rounds(); + } + level thread maps/mp/zombies/_zm::round_start(); + level thread maps/mp/gametypes_zm/_zm_gametype::kill_all_zombies(); +} diff --git a/zm_transit_patch/maps/mp/zm_transit.gsc b/zm_transit_patch/maps/mp/zm_transit.gsc new file mode 100644 index 0000000..2273730 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit.gsc @@ -0,0 +1,3587 @@ +#include maps/mp/zombies/_zm_tombstone; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zm_transit_distance_tracking; +#include maps/mp/zm_transit_sq; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zm_transit_cling; +#include maps/mp/zombies/_zm_devgui; +#include maps/mp/zombies/_zm_power; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zm_transit_openings; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/_visionset_mgr; +#include maps/mp/zm_transit_power; +#include maps/mp/zm_transit_lava; +#include maps/mp/gametypes_zm/_spawning; +#include maps/mp/teams/_teamset_cdc; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zm_transit_ffotd; +#include maps/mp/zombies/_zm_banking; +#include maps/mp/zombies/_zm_weapon_locker; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/_utility; +#include common_scripts/utility; + +gamemode_callback_setup() +{ + maps/mp/zm_transit_gamemodes::init(); +} + +encounter_init() +{ + precacheshader( "sun_moon_zombie" ); + level.precachecustomcharacters = ::precache_team_characters; + level.givecustomcharacters = ::give_team_characters; +} + +zgrief_init() +{ + encounter_init(); + level thread maps/mp/zombies/_zm_banking::delete_bank_teller(); + flag_wait( "start_zombie_round_logic" ); + level.custom_intermission = ::transit_standard_intermission; + if ( isDefined( level.scr_zm_map_start_location ) && level.scr_zm_map_start_location == "transit" ) + { + level thread lava_damage_depot(); + } +} + +survival_init() +{ + level.force_team_characters = 1; + level.should_use_cia = 0; + if ( randomint( 100 ) > 50 ) + { + level.should_use_cia = 1; + } + level.precachecustomcharacters = ::precache_team_characters; + level.givecustomcharacters = ::give_team_characters; + level.dog_spawn_func = ::dog_spawn_transit_logic; + level thread maps/mp/zombies/_zm_banking::delete_bank_teller(); + flag_wait( "start_zombie_round_logic" ); + level.custom_intermission = ::transit_standard_intermission; + if ( isDefined( level.scr_zm_map_start_location ) && level.scr_zm_map_start_location == "transit" ) + { + level thread lava_damage_depot(); + } +} + +zclassic_init() +{ + level.precachecustomcharacters = ::precache_personality_characters; + level.givecustomcharacters = ::give_personality_characters; + level.setupcustomcharacterexerts = ::setup_personality_character_exerts; + level.level_specific_init_powerups = ::add_transit_powerups; + level.powerup_intro_vox = ::powerup_intro_vox; + level.powerup_vo_available = ::powerup_vo_available; + level.buildable_build_custom_func = ::buildable_build_custom_func; + level.custom_update_retrieve_trigger = ::transit_bus_update_retrieve_trigger; + level.buildable_pickup_vo_override = ::transit_buildable_vo_override; + precachemodel( "p6_zm_window_dest_glass_small_broken" ); + precachemodel( "p6_zm_window_dest_glass_big_broken" ); + precachemodel( "p6_zm_keycard" ); + flag_wait( "start_zombie_round_logic" ); + level.custom_intermission = ::transit_intermission; + level.custom_trapped_zombies = ::kill_zombies_depot; + level thread lava_damage_depot(); + level thread bank_teller_init(); + level thread transit_breakable_glass_init(); + level thread sndsetupmusiceasteregg(); + level thread bank_pap_hint(); + level thread power_pap_hint(); + level thread sndtoiletflush(); +} + +zclassic_preinit() +{ + zclassic_init(); +} + +zcleansed_preinit() +{ + level._zcleansed_weapon_progression = array( "rpd_zm", "srm1216_zm", "judge_zm", "qcw05_zm", "kard_zm" ); + survival_init(); +} + +zcontainment_preinit() +{ + survival_init(); +} + +zdeadpool_preinit() +{ + encounter_init(); +} + +zgrief_preinit() +{ + registerclientfield( "toplayer", "meat_stink", 1, 1, "int" ); + zgrief_init(); + level thread delete_bus_pieces(); +} + +zmeat_preinit() +{ + encounter_init(); +} + +znml_preinit() +{ + survival_init(); +} + +zpitted_preinit() +{ + encounter_init(); +} + +zrace_preinit() +{ + encounter_init(); +} + +zstandard_preinit() +{ + survival_init(); + level thread delete_bus_pieces(); +} + +zturned_preinit() +{ + encounter_init(); +} + +createfx_callback() +{ + ents = getentarray(); + i = 0; + while ( i < ents.size ) + { + if ( ents[ i ].classname != "info_player_start" ) + { + ents[ i ] delete(); + } + i++; + } +} + +main() +{ + level thread maps/mp/zm_transit_ffotd::main_start(); + level.hotjoin_player_setup = ::hotjoin_setup_player; + level.level_createfx_callback_thread = ::createfx_callback; + level.ignore_spawner_func = ::transit_ignore_spawner; + level.default_game_mode = "zclassic"; + level.default_start_location = "transit"; + level._get_random_encounter_func = ::maps/mp/zm_transit_utility::get_random_encounter_match; + setup_rex_starts(); + maps/mp/zm_transit_bus::init_animtree(); + maps/mp/zm_transit_bus::init_props_animtree(); + maps/mp/zm_transit_automaton::init_animtree(); + maps/mp/zombies/_zm_equip_turbine::init_animtree(); + maps/mp/zm_transit_fx::main(); + maps/mp/zombies/_zm::init_fx(); + maps/mp/animscripts/zm_death::precache_gib_fx(); + level.zombiemode = 1; + level._no_water_risers = 1; + level.riser_fx_on_client = 1; + if ( !isDefined( level.zombie_surfing_kills ) ) + { + level.zombie_surfing_kills = 1; + level.zombie_surfing_kill_count = 6; + } + maps/mp/teams/_teamset_cdc::register(); + maps/mp/_sticky_grenade::init(); + level.level_specific_stats_init = ::init_transit_stats; + maps/mp/zombies/_load::main(); + init_clientflags(); + level thread transit_pathnode_spawning(); + registerclientfield( "allplayers", "playerinfog", 1, 1, "int" ); + level.set_player_in_fog = ::set_player_in_fog; + level.custom_breadcrumb_store_func = ::transit_breadcrumb_store_func; + register_screecher_lights(); + if ( getDvar( "createfx" ) == "1" ) + { + return; + } + maps/mp/teams/_teamset_cdc::level_init(); + maps/mp/zm_transit_ai_screecher::init(); + level.is_player_in_screecher_zone = ::is_player_in_screecher_zone; + level.revive_trigger_spawn_override_link = ::revive_trigger_spawn_override_link; + level.revive_trigger_should_ignore_sight_checks = ::revive_trigger_should_ignore_sight_checks; + level.allow_move_in_laststand = ::allow_move_in_laststand; + level.can_revive = ::can_revive; + level.melee_miss_func = ::melee_miss_func; + level.grenade_watcher = ::grenade_watcher; + level.ignore_find_flesh = ::ignore_find_flesh; + level.ignore_equipment = ::ignore_equipment; + level.should_attack_equipment = ::should_attack_equipment; + level.gib_on_damage = ::gib_on_damage; + level.melee_anim_state = ::melee_anim_state; + level.ignore_stop_func = ::ignore_stop_func; + level.can_melee = ::can_melee; + level.ignore_traverse = ::ignore_traverse; + level.exit_level_func = ::exit_level_func; + level.inert_substate_override = ::inert_substate_override; + level.attack_item = ::attack_item; + level.attack_item_stop = ::attack_item_stop; + level.check_valid_poi = ::check_valid_poi; + level.dog_melee_miss = ::dog_melee_miss; + precacheshellshock( "lava" ); + precacheshellshock( "lava_small" ); + precache_survival_barricade_assets(); + include_game_modules(); + maps/mp/gametypes_zm/_spawning::level_use_unified_spawning( 1 ); + level.givecustomloadout = ::givecustomloadout; + level.giveextrazombies = ::giveextrazombies; + initcharacterstartindex(); + if ( level.xenon ) + { + level.giveextrazombies = ::giveextrazombies; + precacheextrazombies(); + } + level.custom_player_fake_death = ::transit_player_fake_death; + level.custom_player_fake_death_cleanup = ::transit_player_fake_death_cleanup; + level.initial_round_wait_func = ::initial_round_wait_func; + level.zombie_speed_up = ::zombie_speed_up; + level.zombie_init_done = ::zombie_init_done; + level.zombiemode_using_pack_a_punch = 1; + level.zombiemode_reusing_pack_a_punch = 1; + level.pap_interaction_height = 47; + level.zombiemode_using_doubletap_perk = 1; + level.zombiemode_using_juggernaut_perk = 1; + level.zombiemode_using_marathon_perk = 1; + level.zombiemode_using_revive_perk = 1; + level.zombiemode_using_sleightofhand_perk = 1; + level.zombiemode_using_tombstone_perk = 1; + init_persistent_abilities(); + level.register_offhand_weapons_for_level_defaults_override = ::offhand_weapon_overrride; + if ( is_classic() ) + { + level.player_intersection_tracker_override = ::zombie_transit_player_intersection_tracker_override; + level.taser_trig_adjustment = ( 2, 7, 0 ); + } + level.player_too_many_weapons_monitor_callback = ::zombie_transit_player_too_many_weapons_monitor_callback; + level._zmbvoxlevelspecific = ::zombie_transit_audio_alias_override; + level._zombie_custom_add_weapons = ::custom_add_weapons; + level._allow_melee_weapon_switching = 1; + level.disable_melee_wallbuy_icons = 1; + level.uses_gumps = 1; + setdvar( "aim_target_fixed_actor_size", 1 ); + level.banking_update_enabled = 1; + level.raygun2_included = 1; + include_weapons(); + include_powerups(); + include_equipment_for_level(); + include_powered_items(); + level.powerup_bus_range = 500; + level.pay_turret_cost = 300; + level.auto_turret_cost = 500; + setup_dvars(); + onplayerconnect_callback( ::setup_players ); + level thread disable_triggers(); + level thread maps/mp/zm_transit_lava::lava_damage_init(); + level.zm_transit_burn_max_duration = 2; + level thread maps/mp/zm_transit_power::precache_models(); + setup_zombie_init(); + maps/mp/zombies/_zm::init(); + maps/mp/zombies/_zm_ai_basic::init_inert_zombies(); + maps/mp/zombies/_zm_weap_riotshield::init(); + maps/mp/zombies/_zm_weap_jetgun::init(); + level.special_weapon_magicbox_check = ::transit_special_weapon_magicbox_check; + maps/mp/zombies/_zm_weap_emp_bomb::init(); + zm_transit_emp_init(); + level.legacy_cymbal_monkey = 1; + maps/mp/zombies/_zm_weap_cymbal_monkey::init(); + maps/mp/zombies/_zm_weap_tazer_knuckles::init(); + maps/mp/zombies/_zm_weap_bowie::init(); + maps/mp/zombies/_zm_weap_claymore::init(); + maps/mp/zombies/_zm_weap_ballistic_knife::init(); + if ( !isDefined( level.vsmgr_prio_overlay_zm_transit_burn ) ) + { + level.vsmgr_prio_overlay_zm_transit_burn = 20; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_transit_burn", 1, level.vsmgr_prio_overlay_zm_transit_burn, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); + level maps/mp/zm_transit_achievement::init(); + precacheitem( "death_throe_zm" ); + if ( level.splitscreen && getDvarInt( "splitscreen_playerCount" ) > 2 ) + { + level.optimise_for_splitscreen = 1; + } + else + { + level.optimise_for_splitscreen = 0; + } + if ( level.ps3 ) + { + if ( isDefined( level.optimise_for_splitscreen ) && level.optimise_for_splitscreen ) + { + level.culldist = 1500; + } + else + { + level.culldist = 4500; + } + } + else if ( isDefined( level.optimise_for_splitscreen ) && level.optimise_for_splitscreen ) + { + level.culldist = 2500; + } + else + { + level.culldist = 5500; + } + setculldist( level.culldist ); + level.zones = []; + level.zone_manager_init_func = ::transit_zone_init; + init_zones[ 0 ] = "zone_pri"; + init_zones[ 1 ] = "zone_station_ext"; + init_zones[ 2 ] = "zone_tow"; + if ( is_classic() ) + { + init_zones[ 3 ] = "zone_far"; + init_zones[ 4 ] = "zone_pow"; + init_zones[ 5 ] = "zone_trans_1"; + init_zones[ 6 ] = "zone_trans_2"; + init_zones[ 7 ] = "zone_trans_3"; + init_zones[ 8 ] = "zone_trans_4"; + init_zones[ 9 ] = "zone_trans_5"; + init_zones[ 10 ] = "zone_trans_6"; + init_zones[ 11 ] = "zone_trans_7"; + init_zones[ 12 ] = "zone_trans_8"; + init_zones[ 13 ] = "zone_trans_9"; + init_zones[ 14 ] = "zone_trans_10"; + init_zones[ 15 ] = "zone_trans_11"; + init_zones[ 16 ] = "zone_amb_tunnel"; + init_zones[ 17 ] = "zone_amb_forest"; + init_zones[ 18 ] = "zone_amb_cornfield"; + init_zones[ 19 ] = "zone_amb_power2town"; + init_zones[ 20 ] = "zone_amb_bridge"; + } + else + { + init_zones[ 3 ] = "zone_far_ext"; + init_zones[ 4 ] = "zone_brn"; + } + level thread maps/mp/zombies/_zm_zonemgr::manage_zones( init_zones ); + if ( isDefined( level.optimise_for_splitscreen ) && level.optimise_for_splitscreen ) + { + if ( is_classic() ) + { + level.zombie_ai_limit = 20; + } + setdvar( "fx_marks_draw", 0 ); + setdvar( "disable_rope", 1 ); + setdvar( "cg_disableplayernames", 1 ); + setdvar( "disableLookAtEntityLogic", 1 ); + } + else + { + level.zombie_ai_limit = 24; + } + setdvar( "zombiemode_path_minz_bias", 13 ); + level thread maps/mp/zm_transit_ffotd::main_end(); + flag_wait( "start_zombie_round_logic" ); + level notify( "players_done_connecting" ); +/# + execdevgui( "devgui_zombie_transit" ); + level.custom_devgui = ::zombie_transit_devgui; +#/ + level thread set_transit_wind(); + if ( is_classic() ) + { + level thread player_name_fade_control(); + } + level._audio_custom_response_line = ::transit_audio_custom_response_line; + level.speed_change_round = 15; + level.speed_change_max = 5; + init_screecher_zones(); + elec_door_triggers = getentarray( "local_electric_door", "script_noteworthy" ); + _a548 = elec_door_triggers; + _k548 = getFirstArrayKey( _a548 ); + while ( isDefined( _k548 ) ) + { + trigger = _a548[ _k548 ]; + while ( isDefined( trigger.door_hold_trigger ) && trigger.door_hold_trigger == "zombie_door_hold_farm" ) + { + while ( isDefined( trigger.doors ) ) + { + _a554 = trigger.doors; + _k554 = getFirstArrayKey( _a554 ); + while ( isDefined( _k554 ) ) + { + door = _a554[ _k554 ]; + if ( door.origin == ( 8833, -5697, 135 ) ) + { + door.ignore_use_blocker_clip_for_pathing_check = 1; + } + _k554 = getNextArrayKey( _a554, _k554 ); + } + } + } + _k548 = getNextArrayKey( _a548, _k548 ); + } +} + +init_persistent_abilities() +{ + if ( is_classic() ) + { + level.pers_upgrade_boards = 1; + level.pers_upgrade_revive = 1; + level.pers_upgrade_multi_kill_headshots = 1; + level.pers_upgrade_cash_back = 1; + level.pers_upgrade_insta_kill = 1; + level.pers_upgrade_jugg = 1; + level.pers_upgrade_carpenter = 1; + level.pers_upgrade_box_weapon = 1; + level.pers_magic_box_firesale = 1; + level.pers_treasure_chest_get_weapons_array_func = ::pers_treasure_chest_get_weapons_array_transit; + level.pers_upgrade_sniper = 1; + level.pers_upgrade_pistol_points = 1; + level.pers_upgrade_perk_lose = 1; + level.pers_upgrade_double_points = 1; + level.pers_upgrade_nube = 1; + } +} + +pers_treasure_chest_get_weapons_array_transit() +{ + if ( !isDefined( level.pers_box_weapons ) ) + { + level.pers_box_weapons = []; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "knife_ballistic_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "cymbal_monkey_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "judge_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "emp_grenade_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "galil_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "hamr_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "ray_gun_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "rpd_zm"; + } +} + +setup_rex_starts() +{ + add_gametype( "zclassic", ::dummy, "zclassic", ::dummy ); + add_gametype( "zstandard", ::dummy, "zstandard", ::dummy ); + add_gametype( "zgrief", ::dummy, "zgrief", ::dummy ); + add_gameloc( "transit", ::dummy, "transit", ::dummy ); + add_gameloc( "town", ::dummy, "town", ::dummy ); + add_gameloc( "farm", ::dummy, "farm", ::dummy ); +} + +dummy() +{ +} + +init_clientflags() +{ + level._clientflag_vehicle_bus_flashing_lights = 0; + level._clientflag_vehicle_bus_head_lights = 1; + level._clientflag_vehicle_bus_brake_lights = 2; + level._clientflag_vehicle_bus_turn_signal_left_lights = 3; + level._clientflag_vehicle_bus_turn_signal_right_lights = 4; +} + +set_player_in_fog( onoff ) +{ + if ( onoff ) + { + self setclientfield( "playerinfog", 1 ); + } + else + { + self setclientfield( "playerinfog", 0 ); + } +} + +transit_breadcrumb_store_func( store_crumb ) +{ + if ( isDefined( self.isonbus ) && self.isonbus ) + { + return 0; + } + return store_crumb; +} + +transit_ignore_spawner( spawner ) +{ + if ( spawner.classname == "actor_zm_zombie_transit_screecher" ) + { + return 1; + } + return 0; +} + +allow_move_in_laststand( player_down ) +{ + if ( isDefined( player_down.isonbus ) && player_down.isonbus ) + { + return 0; + } + return 1; +} + +can_revive( player_down ) +{ + if ( isDefined( self.screecher ) ) + { + return 0; + } + return 1; +} + +melee_miss_func() +{ + if ( isDefined( self.enemy ) ) + { + if ( !isDefined( self.enemy.screecher ) || self.enemy getstance() == "prone" && self.enemy maps/mp/zombies/_zm_laststand::is_reviving_any() ) + { + dist_sq = distancesquared( self.enemy.origin, self.origin ); + melee_dist_sq = self.meleeattackdist * self.meleeattackdist; + if ( dist_sq < melee_dist_sq ) + { + self.enemy dodamage( self.meleedamage, self.origin, self, self, "none", "MOD_MELEE" ); + } + } + } +} + +grenade_watcher( grenade, weapname ) +{ + if ( weapname != "frag_grenade_zm" || weapname == "claymore_zm" && weapname == "sticky_grenade_zm" ) + { + self thread maps/mp/zombies/_zm_ai_basic::grenade_watcher( grenade ); + } +} + +ignore_find_flesh() +{ + if ( isDefined( self.isonbus ) && self.isonbus ) + { + return 1; + } + return 0; +} + +ignore_equipment( zombie ) +{ + if ( isDefined( zombie.completed_emerging_into_playable_area ) && !zombie.completed_emerging_into_playable_area ) + { + return 1; + } + if ( isDefined( zombie.is_avogadro ) && zombie.is_avogadro ) + { + return 1; + } + if ( isDefined( zombie.is_inert ) && zombie.is_inert ) + { + return 1; + } + if ( isDefined( zombie.inert_delay ) ) + { + return 1; + } + return 0; +} + +should_attack_equipment( dist ) +{ + if ( !isDefined( level.door_triggers ) ) + { + level.door_triggers = getentarray( "bus_door_trigger", "targetname" ); + } + i = 0; + while ( i < level.door_triggers.size ) + { + if ( self istouching( level.door_triggers[ i ] ) ) + { + if ( dist < 4096 ) + { + return 1; + } + } + i++; + } + return 0; +} + +gib_on_damage() +{ + opening = self.opening; + if ( isDefined( opening ) ) + { + if ( isDefined( self.a.gib_ref ) || self.a.gib_ref == "left_arm" && self.a.gib_ref == "right_arm" ) + { + level maps/mp/zombies/_zm_spawner::zombie_death_points( self.origin, self.damagemod, self.a.gib_ref, self.attacker, self ); + opening.zombie = undefined; + launchvector = ( 0, -1, 0 ); + self thread maps/mp/zombies/_zm_spawner::zombie_ragdoll_then_explode( launchvector, self.attacker ); + self notify( "killanimscript" ); + return; + } + } + if ( isDefined( self.is_inert ) && self.is_inert ) + { + if ( isDefined( self.has_legs ) && !self.has_legs ) + { + self notify( "stop_zombie_inert_transition" ); + self setanimstatefromasd( "zm_inert_crawl", maps/mp/zombies/_zm_ai_basic::get_inert_crawl_substate() ); + } + } +} + +melee_anim_state() +{ + if ( self.zombie_move_speed == "bus_walk" ) + { + return maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "zm_walk_melee" ); + } + return undefined; +} + +ignore_stop_func() +{ + if ( isDefined( self.is_inert ) && self.is_inert ) + { + return 1; + } + if ( isDefined( self.opening ) ) + { + return 1; + } + if ( isDefined( self.entering_bus ) ) + { + return 1; + } + return 0; +} + +can_melee() +{ + if ( isDefined( self.dont_die_on_me ) && self.dont_die_on_me ) + { + return 0; + } + if ( isDefined( self.isonbus ) || self.isonbus && isDefined( self.isonbusroof ) && self.isonbusroof ) + { + if ( self.enemydistancesq > anim.meleerangesq ) + { + return 0; + } + } + return 1; +} + +ignore_traverse() +{ + if ( isDefined( self.is_inert ) && self.is_inert ) + { + if ( isDefined( self.in_place ) && !self.in_place ) + { + self setgoalpos( self.origin ); + if ( randomint( 100 ) > 50 ) + { + self setanimstatefromasd( "zm_inert", "inert1" ); + } + else + { + self setanimstatefromasd( "zm_inert", "inert2" ); + } + self.in_place = 1; + } + return 1; + } + return 0; +} + +exit_level_func() +{ + zombies = getaiarray( level.zombie_team ); + _a905 = zombies; + _k905 = getFirstArrayKey( _a905 ); + while ( isDefined( _k905 ) ) + { + zombie = _a905[ _k905 ]; + if ( isDefined( zombie.ignore_solo_last_stand ) && zombie.ignore_solo_last_stand ) + { + } + else + { + if ( isDefined( zombie.find_exit_point ) ) + { + zombie thread [[ zombie.find_exit_point ]](); + break; + } + else if ( isDefined( zombie.isonbus ) && zombie.isonbus ) + { + zombie thread find_exit_bus(); + break; + } + else + { + if ( zombie.ignoreme ) + { + zombie thread maps/mp/zombies/_zm::default_delayed_exit(); + break; + } + else + { + zombie thread maps/mp/zombies/_zm::default_find_exit_point(); + } + } + } + _k905 = getNextArrayKey( _a905, _k905 ); + } +} + +inert_substate_override( substate ) +{ + in_bar = 0; + if ( flag( "OnTowDoorBar" ) ) + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_bar" ) ) + { + in_bar = 1; + } + } + if ( isDefined( self.isonbus ) || self.isonbus && in_bar ) + { + if ( randomint( 100 ) > 50 ) + { + substate = "inert1"; + } + else + { + substate = "inert2"; + } + } + return substate; +} + +attack_item() +{ + if ( isDefined( self.isonbus ) && self.isonbus ) + { + self linkto( level.the_bus ); + } +} + +attack_item_stop() +{ + if ( isDefined( self.isonbus ) && self.isonbus ) + { + self unlink(); + } +} + +check_valid_poi( valid ) +{ + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_bar" ) ) + { + if ( !flag( "OnTowDoorBar" ) ) + { + return 0; + } + } + else + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_town_barber" ) ) + { + if ( !flag( "OnTowDoorBarber" ) ) + { + return 0; + } + } + } + return valid; +} + +dog_melee_miss() +{ + if ( isDefined( self.enemy ) ) + { + stance = self.enemy getstance(); + if ( stance == "prone" || stance == "crouch" ) + { + dist_sq = distancesquared( self.enemy.origin, self.origin ); + if ( dist_sq < 10000 ) + { + meleedamage = getDvarInt( "dog_MeleeDamage" ); + self.enemy dodamage( meleedamage, self.origin, self, self, "none", "MOD_MELEE" ); + } + } + } +} + +find_exit_loc() +{ + player = self.favoriteenemy; + dist_zombie = 0; + dist_player = 0; + dest = 0; + away = vectornormalize( self.origin - player.origin ); + endpos = self.origin + vectorScale( away, 600 ); + locs = array_randomize( level.enemy_dog_locations ); + i = 0; + while ( i < locs.size ) + { + dist_zombie = distancesquared( locs[ i ].origin, endpos ); + dist_player = distancesquared( locs[ i ].origin, player.origin ); + if ( dist_zombie < dist_player ) + { + dest = i; + break; + } + else + { + i++; + } + } + if ( isDefined( locs[ dest ] ) ) + { + self.solo_revive_exit_pos = locs[ dest ].origin; + } +} + +find_exit_bus() +{ + self endon( "death" ); + self.solo_revive_exit = 1; + self notify( "endOnBus" ); + self thread maps/mp/zm_transit_openings::zombieexitbus(); + self find_exit_loc(); + off_the_bus = 0; + while ( flag( "wait_and_revive" ) ) + { + if ( !off_the_bus && self.ai_state == "find_flesh" ) + { + off_the_bus = 1; + self thread maps/mp/zombies/_zm::default_find_exit_point(); + } + wait 0,1; + } + self.solo_revive_exit = 0; + if ( isDefined( self.exiting_window ) && !self.exiting_window ) + { + if ( isDefined( self.isonbus ) && self.isonbus ) + { + self notify( "stop_zombieExitBus" ); + self.walk_to_exit = 0; + self thread zombiemoveonbus(); + } + } +} + +post_first_init() +{ + while ( !isDefined( anim.notfirsttime ) ) + { + wait 0,5; + } + anim.meleerange = 36; + anim.meleerangesq = anim.meleerange * anim.meleerange; +} + +set_transit_wind() +{ + setdvar( "enable_global_wind", 1 ); + setdvar( "wind_global_vector", "-120 -115 -120" ); + setdvar( "wind_global_low_altitude", 0 ); + setdvar( "wind_global_hi_altitude", 2000 ); + setdvar( "wind_global_low_strength_percent", 0,5 ); +} + +revive_trigger_move_with_player() +{ + self endon( "stop_revive_trigger" ); + self endon( "death" ); + while ( isDefined( self.revivetrigger ) ) + { + my_position = self gettagorigin( "J_SpineLower" ); + self.revivetrigger unlink(); + self.revivetrigger.origin = my_position; + self.revivetrigger linkto( level.the_bus ); + wait 0,1; + } +} + +revive_trigger_should_ignore_sight_checks( player_down ) +{ + if ( isDefined( player_down.isonbus ) && player_down.isonbus && level.the_bus.ismoving ) + { + return 1; + } + return 0; +} + +revive_trigger_spawn_override_link( player_down ) +{ + radius = getDvarInt( "revive_trigger_radius" ); + player_down.revivetrigger = spawn( "trigger_radius", ( 0, -1, 0 ), 0, radius, radius ); + player_down.revivetrigger sethintstring( "" ); + player_down.revivetrigger setcursorhint( "HINT_NOICON" ); + player_down.revivetrigger setmovingplatformenabled( 1 ); + player_down.revivetrigger enablelinkto(); + if ( isDefined( player_down.isonbus ) && player_down.isonbus ) + { + player_down.revivetrigger linkto( level.the_bus ); + player_down thread revive_trigger_move_with_player(); + } + else + { + player_down.revivetrigger.origin = player_down.origin; + player_down.revivetrigger linkto( player_down ); + } + player_down.revivetrigger.beingrevived = 0; + player_down.revivetrigger.createtime = getTime(); +} + +init_screecher_zones() +{ + _a1158 = level.zone_keys; + _k1158 = getFirstArrayKey( _a1158 ); + while ( isDefined( _k1158 ) ) + { + key = _a1158[ _k1158 ]; + if ( issubstr( key, "_trans_" ) || issubstr( key, "_amb_" ) ) + { + level.zones[ key ].screecher_zone = 1; + } + else + { + level.zones[ key ].screecher_zone = 0; + } + _k1158 = getNextArrayKey( _a1158, _k1158 ); + } +} + +is_player_in_screecher_zone( player ) +{ + if ( isDefined( player.isonbus ) && player.isonbus ) + { + return 0; + } + if ( player_entered_safety_zone( player ) ) + { + return 0; + } + if ( player_entered_safety_light( player ) ) + { + return 0; + } + curr_zone = player get_current_zone( 1 ); + if ( isDefined( curr_zone ) && isDefined( curr_zone.screecher_zone ) && !curr_zone.screecher_zone ) + { + return 0; + } + return 1; +} + +player_entered_safety_zone( player ) +{ + if ( !isDefined( level.safety_volumes ) ) + { + level.safety_volumes = getentarray( "screecher_volume", "targetname" ); + } + if ( isDefined( player.last_safety_volume ) ) + { + if ( player istouching( player.last_safety_volume ) ) + { + return 1; + } + } + while ( isDefined( level.safety_volumes ) ) + { + i = 0; + while ( i < level.safety_volumes.size ) + { + if ( player istouching( level.safety_volumes[ i ] ) ) + { + player.last_safety_volume = level.safety_volumes[ i ]; + return 1; + } + i++; + } + } + player.last_safety_volume = undefined; + return 0; +} + +player_entered_safety_light( player ) +{ + safety = getstructarray( "screecher_escape", "targetname" ); + if ( !isDefined( safety ) ) + { + return 0; + } + player.green_light = undefined; + i = 0; + while ( i < safety.size ) + { + if ( isDefined( safety[ i ].power_on ) && !safety[ i ].power_on ) + { + i++; + continue; + } + else + { + if ( !isDefined( safety[ i ].radius ) ) + { + safety[ i ].radius = 256; + } + plyr_dist = distancesquared( player.origin, safety[ i ].origin ); + if ( plyr_dist < ( safety[ i ].radius * safety[ i ].radius ) ) + { + player.green_light = safety[ i ]; + return 1; + } + } + i++; + } + return 0; +} + +zombie_transit_player_intersection_tracker_override( other_player ) +{ + if ( isDefined( self.isonbus ) || self.isonbus && isDefined( self.isonbus ) && self.isonbus ) + { + return 1; + } + if ( isDefined( other_player.isonbus ) || other_player.isonbus && isDefined( other_player.isonbus ) && other_player.isonbus ) + { + return 1; + } + return 0; +} + +precache_team_characters() +{ + precachemodel( "c_zom_player_cdc_fb" ); + precachemodel( "c_zom_hazmat_viewhands" ); + precachemodel( "c_zom_player_cia_fb" ); + precachemodel( "c_zom_suit_viewhands" ); +} + +precache_personality_characters() +{ + character/c_transit_player_farmgirl::precache(); + character/c_transit_player_oldman::precache(); + character/c_transit_player_engineer::precache(); + character/c_transit_player_reporter::precache(); + precachemodel( "c_zom_farmgirl_viewhands" ); + precachemodel( "c_zom_oldman_viewhands" ); + precachemodel( "c_zom_engineer_viewhands" ); + precachemodel( "c_zom_reporter_viewhands" ); +} + +precache_survival_barricade_assets() +{ + survival_barricades = getstructarray( "game_mode_object" ); + i = 0; + while ( i < survival_barricades.size ) + { + if ( isDefined( survival_barricades[ i ].script_string ) && survival_barricades[ i ].script_string == "survival" ) + { + if ( isDefined( survival_barricades[ i ].script_parameters ) ) + { + precachemodel( survival_barricades[ i ].script_parameters ); + } + } + i++; + } +} + +initcharacterstartindex() +{ + level.characterstartindex = 0; +/# + forcecharacter = getDvarInt( #"FEE4CB69" ); + if ( forcecharacter != 0 ) + { + level.characterstartindex = forcecharacter - 1; +#/ + } +} + +precacheextrazombies() +{ +} + +giveextrazombies() +{ +} + +give_team_characters() +{ + if ( isDefined( level.hotjoin_player_setup ) && [[ level.hotjoin_player_setup ]]( "c_zom_suit_viewhands" ) ) + { + return; + } + self detachall(); + self set_player_is_female( 0 ); + if ( isDefined( level.should_use_cia ) ) + { + if ( level.should_use_cia ) + { + self setmodel( "c_zom_player_cia_fb" ); + self setviewmodel( "c_zom_suit_viewhands" ); + self.characterindex = 0; + } + else + { + self setmodel( "c_zom_player_cdc_fb" ); + self setviewmodel( "c_zom_hazmat_viewhands" ); + self.characterindex = 1; + } + } + else if ( !isDefined( self.characterindex ) ) + { + self.characterindex = 1; + if ( self.team == "axis" ) + { + self.characterindex = 0; + } + } + switch( self.characterindex ) + { + case 0: + case 2: + self setmodel( "c_zom_player_cia_fb" ); + self.voice = "american"; + self.skeleton = "base"; + self setviewmodel( "c_zom_suit_viewhands" ); + self.characterindex = 0; + break; + case 1: + case 3: + self setmodel( "c_zom_player_cdc_fb" ); + self.voice = "american"; + self.skeleton = "base"; + self setviewmodel( "c_zom_hazmat_viewhands" ); + self.characterindex = 1; + break; + } + self setmovespeedscale( 1 ); + self setsprintduration( 4 ); + self setsprintcooldown( 0 ); + self set_player_tombstone_index(); +} + +give_personality_characters() +{ + if ( isDefined( level.hotjoin_player_setup ) && [[ level.hotjoin_player_setup ]]( "c_zom_farmgirl_viewhands" ) ) + { + return; + } + self detachall(); + if ( !isDefined( self.characterindex ) ) + { + self.characterindex = assign_lowest_unused_character_index(); + } + self.favorite_wall_weapons_list = []; + self.talks_in_danger = 0; +/# + if ( getDvar( #"40772CF1" ) != "" ) + { + self.characterindex = getDvarInt( #"40772CF1" ); +#/ + } + switch( self.characterindex ) + { + case 2: + self character/c_transit_player_farmgirl::main(); + self setviewmodel( "c_zom_farmgirl_viewhands" ); + level.vox maps/mp/zombies/_zm_audio::zmbvoxinitspeaker( "player", "vox_plr_", self ); + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "rottweil72_zm"; + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "870mcs_zm"; + self set_player_is_female( 1 ); + break; + case 0: + self character/c_transit_player_oldman::main(); + self setviewmodel( "c_zom_oldman_viewhands" ); + level.vox maps/mp/zombies/_zm_audio::zmbvoxinitspeaker( "player", "vox_plr_", self ); + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "frag_grenade_zm"; + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "claymore_zm"; + self set_player_is_female( 0 ); + break; + case 3: + self character/c_transit_player_engineer::main(); + self setviewmodel( "c_zom_engineer_viewhands" ); + level.vox maps/mp/zombies/_zm_audio::zmbvoxinitspeaker( "player", "vox_plr_", self ); + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "m14_zm"; + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "m16_zm"; + self set_player_is_female( 0 ); + break; + case 1: + self character/c_transit_player_reporter::main(); + self setviewmodel( "c_zom_reporter_viewhands" ); + level.vox maps/mp/zombies/_zm_audio::zmbvoxinitspeaker( "player", "vox_plr_", self ); + self.talks_in_danger = 1; + level.rich_sq_player = self; + self.favorite_wall_weapons_list[ self.favorite_wall_weapons_list.size ] = "beretta93r_zm"; + self set_player_is_female( 0 ); + break; + } + self setmovespeedscale( 1 ); + self setsprintduration( 4 ); + self setsprintcooldown( 0 ); + self set_player_tombstone_index(); + self thread set_exert_id(); +} + +set_exert_id() +{ + self endon( "disconnect" ); + wait_network_frame(); + wait_network_frame(); + self maps/mp/zombies/_zm_audio::setexertvoice( self.characterindex + 1 ); +} + +setup_personality_character_exerts() +{ + level.exert_sounds[ 1 ][ "burp" ][ 0 ] = "vox_plr_0_exert_burp_0"; + level.exert_sounds[ 1 ][ "burp" ][ 1 ] = "vox_plr_0_exert_burp_1"; + level.exert_sounds[ 1 ][ "burp" ][ 2 ] = "vox_plr_0_exert_burp_2"; + level.exert_sounds[ 1 ][ "burp" ][ 3 ] = "vox_plr_0_exert_burp_3"; + level.exert_sounds[ 1 ][ "burp" ][ 4 ] = "vox_plr_0_exert_burp_4"; + level.exert_sounds[ 1 ][ "burp" ][ 5 ] = "vox_plr_0_exert_burp_5"; + level.exert_sounds[ 1 ][ "burp" ][ 6 ] = "vox_plr_0_exert_burp_6"; + level.exert_sounds[ 2 ][ "burp" ][ 0 ] = "vox_plr_1_exert_burp_0"; + level.exert_sounds[ 2 ][ "burp" ][ 1 ] = "vox_plr_1_exert_burp_1"; + level.exert_sounds[ 2 ][ "burp" ][ 2 ] = "vox_plr_1_exert_burp_2"; + level.exert_sounds[ 2 ][ "burp" ][ 3 ] = "vox_plr_1_exert_burp_3"; + level.exert_sounds[ 3 ][ "burp" ][ 0 ] = "vox_plr_2_exert_burp_0"; + level.exert_sounds[ 3 ][ "burp" ][ 1 ] = "vox_plr_2_exert_burp_1"; + level.exert_sounds[ 3 ][ "burp" ][ 2 ] = "vox_plr_2_exert_burp_2"; + level.exert_sounds[ 3 ][ "burp" ][ 3 ] = "vox_plr_2_exert_burp_3"; + level.exert_sounds[ 3 ][ "burp" ][ 4 ] = "vox_plr_2_exert_burp_4"; + level.exert_sounds[ 3 ][ "burp" ][ 5 ] = "vox_plr_2_exert_burp_5"; + level.exert_sounds[ 3 ][ "burp" ][ 6 ] = "vox_plr_2_exert_burp_6"; + level.exert_sounds[ 4 ][ "burp" ][ 0 ] = "vox_plr_3_exert_burp_0"; + level.exert_sounds[ 4 ][ "burp" ][ 1 ] = "vox_plr_3_exert_burp_1"; + level.exert_sounds[ 4 ][ "burp" ][ 2 ] = "vox_plr_3_exert_burp_2"; + level.exert_sounds[ 4 ][ "burp" ][ 3 ] = "vox_plr_3_exert_burp_3"; + level.exert_sounds[ 4 ][ "burp" ][ 4 ] = "vox_plr_3_exert_burp_4"; + level.exert_sounds[ 4 ][ "burp" ][ 5 ] = "vox_plr_3_exert_burp_5"; + level.exert_sounds[ 4 ][ "burp" ][ 6 ] = "vox_plr_3_exert_burp_6"; + level.exert_sounds[ 1 ][ "hitmed" ][ 0 ] = "vox_plr_0_exert_pain_medium_0"; + level.exert_sounds[ 1 ][ "hitmed" ][ 1 ] = "vox_plr_0_exert_pain_medium_1"; + level.exert_sounds[ 1 ][ "hitmed" ][ 2 ] = "vox_plr_0_exert_pain_medium_2"; + level.exert_sounds[ 1 ][ "hitmed" ][ 3 ] = "vox_plr_0_exert_pain_medium_3"; + level.exert_sounds[ 2 ][ "hitmed" ][ 0 ] = "vox_plr_1_exert_pain_medium_0"; + level.exert_sounds[ 2 ][ "hitmed" ][ 1 ] = "vox_plr_1_exert_pain_medium_1"; + level.exert_sounds[ 2 ][ "hitmed" ][ 2 ] = "vox_plr_1_exert_pain_medium_2"; + level.exert_sounds[ 2 ][ "hitmed" ][ 3 ] = "vox_plr_1_exert_pain_medium_3"; + level.exert_sounds[ 3 ][ "hitmed" ][ 0 ] = "vox_plr_2_exert_pain_medium_0"; + level.exert_sounds[ 3 ][ "hitmed" ][ 1 ] = "vox_plr_2_exert_pain_medium_1"; + level.exert_sounds[ 3 ][ "hitmed" ][ 2 ] = "vox_plr_2_exert_pain_medium_2"; + level.exert_sounds[ 3 ][ "hitmed" ][ 3 ] = "vox_plr_2_exert_pain_medium_3"; + level.exert_sounds[ 4 ][ "hitmed" ][ 0 ] = "vox_plr_3_exert_pain_medium_0"; + level.exert_sounds[ 4 ][ "hitmed" ][ 1 ] = "vox_plr_3_exert_pain_medium_1"; + level.exert_sounds[ 4 ][ "hitmed" ][ 2 ] = "vox_plr_3_exert_pain_medium_2"; + level.exert_sounds[ 4 ][ "hitmed" ][ 3 ] = "vox_plr_3_exert_pain_medium_3"; + level.exert_sounds[ 1 ][ "hitlrg" ][ 0 ] = "vox_plr_0_exert_pain_high_0"; + level.exert_sounds[ 1 ][ "hitlrg" ][ 1 ] = "vox_plr_0_exert_pain_high_1"; + level.exert_sounds[ 1 ][ "hitlrg" ][ 2 ] = "vox_plr_0_exert_pain_high_2"; + level.exert_sounds[ 1 ][ "hitlrg" ][ 3 ] = "vox_plr_0_exert_pain_high_3"; + level.exert_sounds[ 2 ][ "hitlrg" ][ 0 ] = "vox_plr_1_exert_pain_high_0"; + level.exert_sounds[ 2 ][ "hitlrg" ][ 1 ] = "vox_plr_1_exert_pain_high_1"; + level.exert_sounds[ 2 ][ "hitlrg" ][ 2 ] = "vox_plr_1_exert_pain_high_2"; + level.exert_sounds[ 2 ][ "hitlrg" ][ 3 ] = "vox_plr_1_exert_pain_high_3"; + level.exert_sounds[ 3 ][ "hitlrg" ][ 0 ] = "vox_plr_2_exert_pain_high_0"; + level.exert_sounds[ 3 ][ "hitlrg" ][ 1 ] = "vox_plr_2_exert_pain_high_1"; + level.exert_sounds[ 3 ][ "hitlrg" ][ 2 ] = "vox_plr_2_exert_pain_high_2"; + level.exert_sounds[ 3 ][ "hitlrg" ][ 3 ] = "vox_plr_2_exert_pain_high_3"; + level.exert_sounds[ 4 ][ "hitlrg" ][ 0 ] = "vox_plr_3_exert_pain_high_0"; + level.exert_sounds[ 4 ][ "hitlrg" ][ 1 ] = "vox_plr_3_exert_pain_high_1"; + level.exert_sounds[ 4 ][ "hitlrg" ][ 2 ] = "vox_plr_3_exert_pain_high_2"; + level.exert_sounds[ 4 ][ "hitlrg" ][ 3 ] = "vox_plr_3_exert_pain_high_3"; +} + +givecustomloadout( takeallweapons, alreadyspawned ) +{ + self giveweapon( "knife_zm" ); + self give_start_weapon( 1 ); +} + +transit_intermission() +{ + self closemenu(); + self closeingamemenu(); + level endon( "stop_intermission" ); + self endon( "disconnect" ); + self endon( "death" ); + self notify( "_zombie_game_over" ); + self.score = self.score_total; + self.sessionstate = "intermission"; + self.spectatorclient = -1; + self.killcamentity = -1; + self.archivetime = 0; + self.psoffsettime = 0; + self.friendlydamage = undefined; + maps/mp/_visionset_mgr::vsmgr_deactivate( "overlay", "zm_transit_burn", self ); + self stopshellshock(); + self.game_over_bg = newclienthudelem( self ); + self.game_over_bg.x = 0; + self.game_over_bg.y = 0; + self.game_over_bg.horzalign = "fullscreen"; + self.game_over_bg.vertalign = "fullscreen"; + self.game_over_bg.foreground = 1; + self.game_over_bg.sort = 1; + self.game_over_bg setshader( "black", 640, 480 ); + self.game_over_bg.alpha = 1; + if ( !isDefined( level.the_bus ) ) + { + self.game_over_bg fadeovertime( 1 ); + self.game_over_bg.alpha = 0; + wait 5; + self.game_over_bg thread maps/mp/zombies/_zm::fade_up_over_time( 1 ); + } + else + { + zonestocheck = []; + zonestocheck[ zonestocheck.size ] = "zone_amb_bridge"; + zonestocheck[ zonestocheck.size ] = "zone_trans_11"; + zonestocheck[ zonestocheck.size ] = "zone_town_west"; + zonestocheck[ zonestocheck.size ] = "zone_town_west2"; + zonestocheck[ zonestocheck.size ] = "zone_tow"; + near_bridge = 0; + _a1665 = zonestocheck; + _k1665 = getFirstArrayKey( _a1665 ); + while ( isDefined( _k1665 ) ) + { + zone = _a1665[ _k1665 ]; + if ( level.the_bus maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_amb_bridge" ) ) + { + near_bridge = 1; + } + _k1665 = getNextArrayKey( _a1665, _k1665 ); + } + if ( near_bridge ) + { + trig = getent( "bridge_trig", "targetname" ); + trig notify( "trigger" ); + } + org = spawn( "script_model", level.the_bus gettagorigin( "tag_camera" ) ); + org setmodel( "tag_origin" ); + org.angles = level.the_bus gettagangles( "tag_camera" ); + org linkto( level.the_bus ); + self setorigin( org.origin ); + self.angles = org.angles; + if ( !flag( "OnPriDoorYar" ) || !flag( "OnPriDoorYar2" ) ) + { + flag_set( "OnPriDoorYar" ); + wait_network_frame(); + } + if ( !level.the_bus.ismoving ) + { + level.the_bus.gracetimeatdestination = 0,1; + level.the_bus notify( "depart_early" ); + } + players = get_players(); + j = 0; + while ( j < players.size ) + { + player = players[ j ]; + player camerasetposition( org ); + player camerasetlookat(); + player cameraactivate( 1 ); + j++; + } + self.game_over_bg fadeovertime( 1 ); + self.game_over_bg.alpha = 0; + wait 12; + self.game_over_bg fadeovertime( 1 ); + self.game_over_bg.alpha = 1; + wait 1; + } +} + +transit_standard_intermission() +{ + self closemenu(); + self closeingamemenu(); + level endon( "stop_intermission" ); + self endon( "disconnect" ); + self endon( "death" ); + self notify( "_zombie_game_over" ); + self.score = self.score_total; + self.sessionstate = "intermission"; + self.spectatorclient = -1; + self.killcamentity = -1; + self.archivetime = 0; + self.psoffsettime = 0; + self.friendlydamage = undefined; + maps/mp/_visionset_mgr::vsmgr_deactivate( "overlay", "zm_transit_burn", self ); + self stopshellshock(); + points = getstructarray( "intermission", "targetname" ); + point = undefined; + if ( !isDefined( points ) || points.size == 0 ) + { + points = getentarray( "info_intermission", "classname" ); + if ( points.size < 1 ) + { +/# + println( "NO info_intermission POINTS IN MAP" ); +#/ + return; + } + } + self.game_over_bg = newclienthudelem( self ); + self.game_over_bg.x = 0; + self.game_over_bg.y = 0; + self.game_over_bg.horzalign = "fullscreen"; + self.game_over_bg.vertalign = "fullscreen"; + self.game_over_bg.foreground = 1; + self.game_over_bg.sort = 1; + self.game_over_bg setshader( "black", 640, 480 ); + self.game_over_bg.alpha = 1; + org = undefined; + while ( 1 ) + { + _a1768 = points; + _k1768 = getFirstArrayKey( _a1768 ); + while ( isDefined( _k1768 ) ) + { + struct = _a1768[ _k1768 ]; + if ( isDefined( struct.script_string ) && struct.script_string == level.scr_zm_map_start_location ) + { + point = struct; + } + _k1768 = getNextArrayKey( _a1768, _k1768 ); + } + if ( !isDefined( point ) ) + { + point = points[ 0 ]; + } + if ( !isDefined( org ) ) + { + self spawn( point.origin, point.angles ); + } + if ( isDefined( point.target ) ) + { + if ( !isDefined( org ) ) + { + org = spawn( "script_model", self.origin + vectorScale( ( 0, -1, 0 ), 60 ) ); + org setmodel( "tag_origin" ); + } + org.origin = point.origin; + org.angles = point.angles; + j = 0; + while ( j < get_players().size ) + { + player = get_players()[ j ]; + player camerasetposition( org ); + player camerasetlookat(); + player cameraactivate( 1 ); + j++; + } + speed = 20; + if ( isDefined( point.speed ) ) + { + speed = point.speed; + } + target_point = getstruct( point.target, "targetname" ); + dist = distance( point.origin, target_point.origin ); + time = dist / speed; + q_time = time * 0,25; + if ( q_time > 1 ) + { + q_time = 1; + } + self.game_over_bg fadeovertime( q_time ); + self.game_over_bg.alpha = 0; + org moveto( target_point.origin, time, q_time, q_time ); + org rotateto( target_point.angles, time, q_time, q_time ); + wait ( time - q_time ); + self.game_over_bg fadeovertime( q_time ); + self.game_over_bg.alpha = 1; + wait q_time; + continue; + } + else + { + self.game_over_bg fadeovertime( 1 ); + self.game_over_bg.alpha = 0; + wait 5; + self.game_over_bg thread fade_up_over_time( 1 ); + } + } +} + +meetupwithothercharacters() +{ + self endon( "disconnect" ); + isalone = 1; + flag_wait( "begin_spawning" ); + while ( isalone ) + { + players = get_players(); + if ( flag( "solo_game" ) ) + { + break; + } + else + { + _a1863 = players; + _k1863 = getFirstArrayKey( _a1863 ); + while ( isDefined( _k1863 ) ) + { + player = _a1863[ _k1863 ]; + if ( player == self ) + { + } + else + { + if ( distancesquared( self.origin, player.origin ) < 1048576 ) + { +/# + println( "^2Transit Debug: " + self.name + " met up with " + player.name ); +#/ + isalone = 0; + } + } + _k1863 = getNextArrayKey( _a1863, _k1863 ); + } + wait 1; + } + } + self.characterrespawnpoint = undefined; +} + +transit_respawn_override( player ) +{ + if ( isDefined( player.characterrespawnpoint ) ) + { +/# + println( "^2Transit Debug: Using character respawn point for " + player.name ); +#/ + return player.characterrespawnpoint.origin; + } + return undefined; +} + +disable_triggers() +{ + trig = getentarray( "trigger_Keys", "targetname" ); + i = 0; + while ( i < trig.size ) + { + trig[ i ] trigger_off(); + i++; + } +} + +transit_zone_init() +{ + flag_init( "always_on" ); + flag_init( "init_classic_adjacencies" ); + flag_set( "always_on" ); + if ( is_classic() ) + { + flag_set( "init_classic_adjacencies" ); + add_adjacent_zone( "zone_trans_2", "zone_trans_2b", "init_classic_adjacencies" ); + add_adjacent_zone( "zone_station_ext", "zone_trans_2b", "init_classic_adjacencies", 1 ); + add_adjacent_zone( "zone_town_west2", "zone_town_west", "init_classic_adjacencies" ); + add_adjacent_zone( "zone_town_south", "zone_town_church", "init_classic_adjacencies" ); + add_adjacent_zone( "zone_trans_pow_ext1", "zone_trans_7", "init_classic_adjacencies" ); + add_adjacent_zone( "zone_far", "zone_far_ext", "OnFarm_enter" ); + } + else + { + playable_area = getentarray( "player_volume", "script_noteworthy" ); + _a1939 = playable_area; + _k1939 = getFirstArrayKey( _a1939 ); + while ( isDefined( _k1939 ) ) + { + area = _a1939[ _k1939 ]; + add_adjacent_zone( "zone_station_ext", "zone_trans_2b", "always_on" ); + if ( isDefined( area.script_parameters ) && area.script_parameters == "classic_only" ) + { + area delete(); + } + _k1939 = getNextArrayKey( _a1939, _k1939 ); + } + } + add_adjacent_zone( "zone_pri2", "zone_station_ext", "OnPriDoorYar", 1 ); + add_adjacent_zone( "zone_pri2", "zone_pri", "OnPriDoorYar3", 1 ); + if ( getDvar( "ui_zm_mapstartlocation" ) == "transit" ) + { + level thread disconnect_door_zones( "zone_pri2", "zone_station_ext", "OnPriDoorYar" ); + level thread disconnect_door_zones( "zone_pri2", "zone_pri", "OnPriDoorYar3" ); + } + add_adjacent_zone( "zone_station_ext", "zone_pri", "OnPriDoorYar2" ); + add_adjacent_zone( "zone_roadside_west", "zone_din", "OnGasDoorDin" ); + add_adjacent_zone( "zone_roadside_west", "zone_gas", "always_on" ); + add_adjacent_zone( "zone_roadside_east", "zone_gas", "always_on" ); + add_adjacent_zone( "zone_roadside_east", "zone_gar", "OnGasDoorGar" ); + add_adjacent_zone( "zone_trans_diner", "zone_roadside_west", "always_on", 1 ); + add_adjacent_zone( "zone_trans_diner", "zone_gas", "always_on", 1 ); + add_adjacent_zone( "zone_trans_diner2", "zone_roadside_east", "always_on", 1 ); + add_adjacent_zone( "zone_gas", "zone_din", "OnGasDoorDin" ); + add_adjacent_zone( "zone_gas", "zone_gar", "OnGasDoorGar" ); + add_adjacent_zone( "zone_diner_roof", "zone_din", "OnGasDoorDin", 1 ); + add_adjacent_zone( "zone_amb_cornfield", "zone_cornfield_prototype", "always_on" ); + add_adjacent_zone( "zone_tow", "zone_bar", "always_on", 1 ); + add_adjacent_zone( "zone_bar", "zone_tow", "OnTowDoorBar", 1 ); + add_adjacent_zone( "zone_tow", "zone_ban", "OnTowDoorBan" ); + add_adjacent_zone( "zone_ban", "zone_ban_vault", "OnTowBanVault" ); + add_adjacent_zone( "zone_tow", "zone_town_north", "always_on" ); + add_adjacent_zone( "zone_town_north", "zone_ban", "OnTowDoorBan" ); + add_adjacent_zone( "zone_tow", "zone_town_west", "always_on" ); + add_adjacent_zone( "zone_tow", "zone_town_south", "always_on" ); + add_adjacent_zone( "zone_town_south", "zone_town_barber", "always_on", 1 ); + add_adjacent_zone( "zone_tow", "zone_town_east", "always_on" ); + add_adjacent_zone( "zone_town_east", "zone_bar", "OnTowDoorBar" ); + add_adjacent_zone( "zone_tow", "zone_town_barber", "always_on", 1 ); + add_adjacent_zone( "zone_town_barber", "zone_tow", "OnTowDoorBarber", 1 ); + add_adjacent_zone( "zone_town_barber", "zone_town_west", "OnTowDoorBarber" ); + add_adjacent_zone( "zone_far_ext", "zone_brn", "OnFarm_enter" ); + add_adjacent_zone( "zone_far_ext", "zone_farm_house", "open_farmhouse" ); + add_adjacent_zone( "zone_prr", "zone_pow", "OnPowDoorRR", 1 ); + add_adjacent_zone( "zone_pcr", "zone_prr", "OnPowDoorRR" ); + add_adjacent_zone( "zone_pcr", "zone_pow_warehouse", "OnPowDoorWH" ); + add_adjacent_zone( "zone_pow", "zone_pow_warehouse", "OnPowDoorWH" ); + add_adjacent_zone( "zone_tbu", "zone_tow", "vault_opened", 1 ); +} + +include_powerups() +{ + gametype = getDvar( "ui_gametype" ); + include_powerup( "nuke" ); + include_powerup( "insta_kill" ); + include_powerup( "double_points" ); + include_powerup( "full_ammo" ); + include_powerup( "insta_kill_ug" ); + if ( gametype != "zgrief" ) + { + include_powerup( "carpenter" ); + } + if ( is_encounter() && gametype != "zgrief" ) + { + include_powerup( "minigun" ); + } + include_powerup( "teller_withdrawl" ); +} + +add_transit_powerups() +{ + maps/mp/zombies/_zm_powerups::add_zombie_powerup( "teller_withdrawl", "zombie_z_money_icon", &"ZOMBIE_TELLER_PICKUP_DEPOSIT", ::maps/mp/zombies/_zm_powerups::func_should_never_drop, 1, 0, 0 ); +} + +include_equipment_for_level() +{ + level.equipment_turret_needs_power = 1; + level.equipment_etrap_needs_power = 1; + include_equipment( "jetgun_zm" ); + include_equipment( "riotshield_zm" ); + include_equipment( "equip_turbine_zm" ); + include_equipment( "equip_turret_zm" ); + include_equipment( "equip_electrictrap_zm" ); + level.equipment_planted = ::equipment_planted; + level.equipment_safe_to_drop = ::equipment_safe_to_drop; + level.check_force_deploy_origin = ::use_safe_spawn_on_bus; + limit_equipment( "jetgun_zm", 1 ); + level.explode_overheated_jetgun = 1; + level.exploding_jetgun_fx = level._effect[ "lava_burning" ]; +} + +transit_bus_update_retrieve_trigger( player ) +{ + self endon( "death" ); + player endon( "zmb_lost_knife" ); + if ( isDefined( level.the_bus ) && isDefined( player.isonbus ) && player.isonbus ) + { + wait 2; + trigger = self.retrievabletrigger; + trigger.origin = ( self.origin[ 0 ], self.origin[ 1 ], self.origin[ 2 ] + 10 ); + self linkto( level.the_bus ); + trigger linkto( self ); + } + else + { + self waittill( "stationary" ); + trigger = self.retrievabletrigger; + trigger.origin = ( self.origin[ 0 ], self.origin[ 1 ], self.origin[ 2 ] + 10 ); + trigger linkto( self ); + } +} + +claymore_safe_to_plant() +{ + if ( self maps/mp/zm_transit_lava::object_touching_lava() ) + { + return 0; + } + if ( self.owner maps/mp/zm_transit_lava::object_touching_lava() ) + { + return 0; + } + return 1; +} + +claymore_planted( weapon ) +{ + weapon waittill( "stationary" ); + if ( !isDefined( weapon ) ) + { + return; + } + weaponbus = weapon maps/mp/zm_transit_bus::object_is_on_bus(); + if ( weaponbus ) + { + if ( isDefined( weapon ) ) + { + weapon setmovingplatformenabled( 1 ); + weapon.equipment_can_move = 1; + weapon.isonbus = 1; + weapon.move_parent = level.the_bus; + if ( isDefined( weapon.damagearea ) ) + { + weapon.damagearea setmovingplatformenabled( 1 ); + } + } + } +} + +fakelinkto( linkee ) +{ + self.backlinked = 1; + while ( isDefined( self ) && isDefined( linkee ) ) + { + self.origin = linkee.origin; + self.angles = linkee.angles; + wait 0,05; + } +} + +knife_planted( knife, trigger, parent ) +{ + if ( !isDefined( knife ) ) + { + return; + } + weaponbus = knife maps/mp/zm_transit_bus::object_is_on_bus(); + if ( weaponbus ) + { + trigger linkto( knife ); + trigger setmovingplatformenabled( 1 ); + trigger.isonbus = 1; + knife setmovingplatformenabled( 1 ); + knife.isonbus = 1; + } +} + +grenade_planted( grenade, model ) +{ + if ( !isDefined( grenade ) ) + { + return; + } + weaponbus = grenade maps/mp/zm_transit_bus::object_is_on_bus(); + if ( weaponbus ) + { + if ( isDefined( grenade ) ) + { + grenade setmovingplatformenabled( 1 ); + grenade.equipment_can_move = 1; + grenade.isonbus = 1; + grenade.move_parent = level.the_bus; + if ( isDefined( model ) ) + { + model setmovingplatformenabled( 1 ); + model linkto( level.the_bus ); + model.isonbus = 1; + grenade fakelinkto( model ); + } + } + } +} + +grenade_safe_to_throw( player, weapname ) +{ + return 1; +} + +grenade_safe_to_bounce( player, weapname ) +{ + if ( !is_offhand_weapon( weapname ) && !is_grenade_launcher( weapname ) ) + { + return 1; + } + if ( self maps/mp/zm_transit_lava::object_touching_lava() ) + { + return 0; + } + return 1; +} + +equipment_safe_to_drop( weapon ) +{ + if ( !isDefined( weapon.canmove ) ) + { + weapon.canmove = weapon maps/mp/zm_transit_bus::object_is_on_bus(); + } + if ( isDefined( weapon.canmove ) && weapon.canmove ) + { + return 1; + } + if ( weapon maps/mp/zm_transit_lava::object_touching_lava() ) + { + return 0; + } + return 1; +} + +use_safe_spawn_on_bus( weapon, origin, angles ) +{ + if ( isDefined( self.isonbus ) && self.isonbus && level.the_bus.ismoving ) + { + weapon.canmove = 1; + return 1; + } + return 0; +} + +equipment_planted( weapon, equipname, groundfrom ) +{ + weaponbus = groundfrom maps/mp/zm_transit_bus::object_is_on_bus(); + if ( !weaponbus && weapon maps/mp/zm_transit_lava::object_touching_lava() ) + { + self maps/mp/zombies/_zm_equipment::equipment_take( equipname ); + wait 0,05; + self notify( equipname + "_taken" ); + return; + } + if ( isDefined( self ) && weaponbus ) + { + if ( isDefined( weapon ) ) + { + if ( isDefined( weapon.canmove ) && !weapon.canmove ) + { + weapon.canmove = 1; + reregister_unitrigger_as_dynamic( weapon.stub ); + } + weapon linkto( level.the_bus ); + weapon setmovingplatformenabled( 1 ); + if ( isDefined( weapon.stub ) ) + { + weapon.stub.link_parent = level.the_bus; + weapon.stub.origin_parent = weapon; + } + weapon.equipment_can_move = 1; + weapon.isonbus = 1; + weapon.move_parent = level.the_bus; + } + } +} + +offhand_weapon_overrride() +{ + register_lethal_grenade_for_level( "frag_grenade_zm" ); + level.zombie_lethal_grenade_player_init = "frag_grenade_zm"; + register_lethal_grenade_for_level( "sticky_grenade_zm" ); + register_tactical_grenade_for_level( "cymbal_monkey_zm" ); + register_tactical_grenade_for_level( "emp_grenade_zm" ); + level.zombie_tactical_grenade_player_init = undefined; + level.grenade_safe_to_throw = ::grenade_safe_to_throw; + level.grenade_safe_to_bounce = ::grenade_safe_to_bounce; + level.grenade_planted = ::grenade_planted; + level.knife_planted = ::knife_planted; + register_placeable_mine_for_level( "claymore_zm" ); + level.zombie_placeable_mine_player_init = undefined; + level.claymore_safe_to_plant = ::claymore_safe_to_plant; + level.claymore_planted = ::claymore_planted; + register_melee_weapon_for_level( "knife_zm" ); + register_melee_weapon_for_level( "bowie_knife_zm" ); + register_melee_weapon_for_level( "tazer_knuckles_zm" ); + level.zombie_melee_weapon_player_init = "knife_zm"; + register_equipment_for_level( "jetgun_zm" ); + register_equipment_for_level( "riotshield_zm" ); + register_equipment_for_level( "equip_turbine_zm" ); + register_equipment_for_level( "equip_turret_zm" ); + register_equipment_for_level( "equip_electrictrap_zm" ); + level.zombie_equipment_player_init = undefined; +} + +include_weapons() +{ + gametype = getDvar( "ui_gametype" ); + include_weapon( "knife_zm", 0 ); + include_weapon( "frag_grenade_zm", 0 ); + include_weapon( "claymore_zm", 0 ); + include_weapon( "sticky_grenade_zm", 0 ); + include_weapon( "m1911_zm", 0 ); + include_weapon( "m1911_upgraded_zm", 0 ); + include_weapon( "python_zm" ); + include_weapon( "python_upgraded_zm", 0 ); + include_weapon( "judge_zm" ); + include_weapon( "judge_upgraded_zm", 0 ); + include_weapon( "kard_zm" ); + include_weapon( "kard_upgraded_zm", 0 ); + include_weapon( "fiveseven_zm" ); + include_weapon( "fiveseven_upgraded_zm", 0 ); + include_weapon( "beretta93r_zm", 0 ); + include_weapon( "beretta93r_upgraded_zm", 0 ); + include_weapon( "fivesevendw_zm" ); + include_weapon( "fivesevendw_upgraded_zm", 0 ); + include_weapon( "ak74u_zm", 0 ); + include_weapon( "ak74u_upgraded_zm", 0 ); + include_weapon( "mp5k_zm", 0 ); + include_weapon( "mp5k_upgraded_zm", 0 ); + include_weapon( "qcw05_zm" ); + include_weapon( "qcw05_upgraded_zm", 0 ); + include_weapon( "870mcs_zm", 0 ); + include_weapon( "870mcs_upgraded_zm", 0 ); + include_weapon( "rottweil72_zm", 0 ); + include_weapon( "rottweil72_upgraded_zm", 0 ); + include_weapon( "saiga12_zm" ); + include_weapon( "saiga12_upgraded_zm", 0 ); + include_weapon( "srm1216_zm" ); + include_weapon( "srm1216_upgraded_zm", 0 ); + include_weapon( "m14_zm", 0 ); + include_weapon( "m14_upgraded_zm", 0 ); + include_weapon( "saritch_zm" ); + include_weapon( "saritch_upgraded_zm", 0 ); + include_weapon( "m16_zm", 0 ); + include_weapon( "m16_gl_upgraded_zm", 0 ); + include_weapon( "xm8_zm" ); + include_weapon( "xm8_upgraded_zm", 0 ); + include_weapon( "type95_zm" ); + include_weapon( "type95_upgraded_zm", 0 ); + include_weapon( "tar21_zm" ); + include_weapon( "tar21_upgraded_zm", 0 ); + include_weapon( "galil_zm" ); + include_weapon( "galil_upgraded_zm", 0 ); + include_weapon( "fnfal_zm" ); + include_weapon( "fnfal_upgraded_zm", 0 ); + include_weapon( "dsr50_zm" ); + include_weapon( "dsr50_upgraded_zm", 0 ); + include_weapon( "barretm82_zm" ); + include_weapon( "barretm82_upgraded_zm", 0 ); + include_weapon( "rpd_zm" ); + include_weapon( "rpd_upgraded_zm", 0 ); + include_weapon( "hamr_zm" ); + include_weapon( "hamr_upgraded_zm", 0 ); + include_weapon( "usrpg_zm" ); + include_weapon( "usrpg_upgraded_zm", 0 ); + include_weapon( "m32_zm" ); + include_weapon( "m32_upgraded_zm", 0 ); + include_weapon( "cymbal_monkey_zm" ); + include_weapon( "emp_grenade_zm", 1, undefined, ::less_than_normal ); + if ( is_classic() ) + { + include_weapon( "screecher_arms_zm", 0 ); + } + if ( gametype != "zgrief" ) + { + include_weapon( "ray_gun_zm" ); + include_weapon( "ray_gun_upgraded_zm", 0 ); + include_weapon( "jetgun_zm", 0, undefined, ::less_than_normal ); + include_weapon( "riotshield_zm", 0 ); + include_weapon( "tazer_knuckles_zm", 0 ); + include_weapon( "knife_ballistic_no_melee_zm", 0 ); + include_weapon( "knife_ballistic_no_melee_upgraded_zm", 0 ); + include_weapon( "knife_ballistic_zm" ); + include_weapon( "knife_ballistic_upgraded_zm", 0 ); + include_weapon( "knife_ballistic_bowie_zm", 0 ); + include_weapon( "knife_ballistic_bowie_upgraded_zm", 0 ); + level._uses_retrievable_ballisitic_knives = 1; + add_limited_weapon( "knife_ballistic_zm", 1 ); + add_limited_weapon( "jetgun_zm", 1 ); + add_limited_weapon( "ray_gun_zm", 4 ); + add_limited_weapon( "ray_gun_upgraded_zm", 4 ); + add_limited_weapon( "knife_ballistic_upgraded_zm", 0 ); + add_limited_weapon( "knife_ballistic_no_melee_zm", 0 ); + add_limited_weapon( "knife_ballistic_no_melee_upgraded_zm", 0 ); + add_limited_weapon( "knife_ballistic_bowie_zm", 0 ); + add_limited_weapon( "knife_ballistic_bowie_upgraded_zm", 0 ); + if ( isDefined( level.raygun2_included ) && level.raygun2_included ) + { + include_weapon( "raygun_mark2_zm" ); + include_weapon( "raygun_mark2_upgraded_zm", 0 ); + add_weapon_to_content( "raygun_mark2_zm", "dlc3" ); + add_limited_weapon( "raygun_mark2_zm", 1 ); + add_limited_weapon( "raygun_mark2_upgraded_zm", 1 ); + } + } + add_limited_weapon( "m1911_zm", 0 ); + add_weapon_locker_mapping( "lsat_zm", "hamr_zm" ); + add_weapon_locker_mapping( "lsat_upgraded_zm", "hamr_upgraded_zm" ); + add_weapon_locker_mapping( "svu_zm", "fnfal_zm" ); + add_weapon_locker_mapping( "svu_upgraded_zm", "fnfal_upgraded_zm" ); + add_weapon_locker_mapping( "pdw57_zm", "qcw05_zm" ); + add_weapon_locker_mapping( "pdw57_upgraded_zm", "qcw05_upgraded_zm" ); + add_weapon_locker_mapping( "an94_zm", "galil_zm" ); + add_weapon_locker_mapping( "an94_upgraded_zm", "galil_upgraded_zm" ); + add_weapon_locker_mapping( "rnma_zm", "python_zm" ); + add_weapon_locker_mapping( "rnma_upgraded_zm", "python_upgraded_zm" ); +} + +less_than_normal() +{ + return 0,5; +} + +custom_add_weapons() +{ + add_zombie_weapon( "m1911_zm", "m1911_upgraded_zm", &"ZOMBIE_WEAPON_M1911", 50, "", "", undefined ); + add_zombie_weapon( "python_zm", "python_upgraded_zm", &"ZOMBIE_WEAPON_PYTHON", 50, "wpck_python", "", undefined, 1 ); + add_zombie_weapon( "judge_zm", "judge_upgraded_zm", &"ZOMBIE_WEAPON_JUDGE", 50, "wpck_judge", "", undefined, 1 ); + add_zombie_weapon( "kard_zm", "kard_upgraded_zm", &"ZOMBIE_WEAPON_KARD", 50, "wpck_kap", "", undefined, 1 ); + add_zombie_weapon( "fiveseven_zm", "fiveseven_upgraded_zm", &"ZOMBIE_WEAPON_FIVESEVEN", 50, "wpck_57", "", undefined, 1 ); + add_zombie_weapon( "beretta93r_zm", "beretta93r_upgraded_zm", &"ZOMBIE_WEAPON_BERETTA93r", 1000, "", "", undefined ); + add_zombie_weapon( "fivesevendw_zm", "fivesevendw_upgraded_zm", &"ZOMBIE_WEAPON_FIVESEVENDW", 50, "wpck_duel57", "", undefined, 1 ); + add_zombie_weapon( "ak74u_zm", "ak74u_upgraded_zm", &"ZOMBIE_WEAPON_AK74U", 1200, "smg", "", undefined ); + add_zombie_weapon( "mp5k_zm", "mp5k_upgraded_zm", &"ZOMBIE_WEAPON_MP5K", 1000, "smg", "", undefined ); + add_zombie_weapon( "qcw05_zm", "qcw05_upgraded_zm", &"ZOMBIE_WEAPON_QCW05", 50, "wpck_chicom", "", undefined, 1 ); + add_zombie_weapon( "870mcs_zm", "870mcs_upgraded_zm", &"ZOMBIE_WEAPON_870MCS", 1500, "shotgun", "", undefined ); + add_zombie_weapon( "rottweil72_zm", "rottweil72_upgraded_zm", &"ZOMBIE_WEAPON_ROTTWEIL72", 500, "shotgun", "", undefined ); + add_zombie_weapon( "saiga12_zm", "saiga12_upgraded_zm", &"ZOMBIE_WEAPON_SAIGA12", 50, "wpck_saiga12", "", undefined, 1 ); + add_zombie_weapon( "srm1216_zm", "srm1216_upgraded_zm", &"ZOMBIE_WEAPON_SRM1216", 50, "wpck_m1216", "", undefined, 1 ); + add_zombie_weapon( "m14_zm", "m14_upgraded_zm", &"ZOMBIE_WEAPON_M14", 500, "rifle", "", undefined ); + add_zombie_weapon( "saritch_zm", "saritch_upgraded_zm", &"ZOMBIE_WEAPON_SARITCH", 50, "wpck_sidr", "", undefined, 1 ); + add_zombie_weapon( "m16_zm", "m16_gl_upgraded_zm", &"ZOMBIE_WEAPON_M16", 1200, "burstrifle", "", undefined ); + add_zombie_weapon( "xm8_zm", "xm8_upgraded_zm", &"ZOMBIE_WEAPON_XM8", 50, "wpck_m8a1", "", undefined, 1 ); + add_zombie_weapon( "type95_zm", "type95_upgraded_zm", &"ZOMBIE_WEAPON_TYPE95", 50, "wpck_type25", "", undefined, 1 ); + add_zombie_weapon( "tar21_zm", "tar21_upgraded_zm", &"ZOMBIE_WEAPON_TAR21", 50, "wpck_x95l", "", undefined, 1 ); + add_zombie_weapon( "galil_zm", "galil_upgraded_zm", &"ZOMBIE_WEAPON_GALIL", 50, "wpck_galil", "", undefined, 1 ); + add_zombie_weapon( "fnfal_zm", "fnfal_upgraded_zm", &"ZOMBIE_WEAPON_FNFAL", 50, "wpck_fal", "", undefined, 1 ); + add_zombie_weapon( "dsr50_zm", "dsr50_upgraded_zm", &"ZOMBIE_WEAPON_DR50", 50, "wpck_dsr50", "", undefined, 1 ); + add_zombie_weapon( "barretm82_zm", "barretm82_upgraded_zm", &"ZOMBIE_WEAPON_BARRETM82", 50, "sniper", "", undefined ); + add_zombie_weapon( "rpd_zm", "rpd_upgraded_zm", &"ZOMBIE_WEAPON_RPD", 50, "wpck_rpd", "", undefined, 1 ); + add_zombie_weapon( "hamr_zm", "hamr_upgraded_zm", &"ZOMBIE_WEAPON_HAMR", 50, "wpck_hamr", "", undefined, 1 ); + add_zombie_weapon( "frag_grenade_zm", undefined, &"ZOMBIE_WEAPON_FRAG_GRENADE", 250, "grenade", "", 250 ); + add_zombie_weapon( "sticky_grenade_zm", undefined, &"ZOMBIE_WEAPON_STICKY_GRENADE", 250, "grenade", "", 250 ); + add_zombie_weapon( "claymore_zm", undefined, &"ZOMBIE_WEAPON_CLAYMORE", 1000, "grenade", "", undefined ); + add_zombie_weapon( "usrpg_zm", "usrpg_upgraded_zm", &"ZOMBIE_WEAPON_USRPG", 50, "wpck_rpg", "", undefined, 1 ); + add_zombie_weapon( "m32_zm", "m32_upgraded_zm", &"ZOMBIE_WEAPON_M32", 50, "wpck_m32", "", undefined, 1 ); + add_zombie_weapon( "cymbal_monkey_zm", undefined, &"ZOMBIE_WEAPON_SATCHEL_2000", 2000, "wpck_monkey", "", undefined, 1 ); + add_zombie_weapon( "emp_grenade_zm", undefined, &"ZOMBIE_WEAPON_EMP_GRENADE", 2000, "wpck_emp", "", undefined, 1 ); + add_zombie_weapon( "ray_gun_zm", "ray_gun_upgraded_zm", &"ZOMBIE_WEAPON_RAYGUN", 10000, "wpck_ray", "", undefined, 1 ); + add_zombie_weapon( "knife_ballistic_zm", "knife_ballistic_upgraded_zm", &"ZOMBIE_WEAPON_KNIFE_BALLISTIC", 10, "sickle", "", undefined ); + add_zombie_weapon( "knife_ballistic_bowie_zm", "knife_ballistic_bowie_upgraded_zm", &"ZOMBIE_WEAPON_KNIFE_BALLISTIC", 10, "wpck_knife", "", undefined, 1 ); + add_zombie_weapon( "knife_ballistic_no_melee_zm", "knife_ballistic_no_melee_upgraded_zm", &"ZOMBIE_WEAPON_KNIFE_BALLISTIC", 10, "sickle", "", undefined ); + add_zombie_weapon( "riotshield_zm", undefined, &"ZOMBIE_WEAPON_RIOTSHIELD", 2000, "riot", "", undefined ); + add_zombie_weapon( "jetgun_zm", undefined, &"ZOMBIE_WEAPON_JETGUN", 2000, "jet", "", undefined ); + add_zombie_weapon( "tazer_knuckles_zm", undefined, &"ZOMBIE_WEAPON_TAZER_KNUCKLES", 100, "tazerknuckles", "", undefined ); + if ( isDefined( level.raygun2_included ) && level.raygun2_included ) + { + add_zombie_weapon( "raygun_mark2_zm", "raygun_mark2_upgraded_zm", &"ZOMBIE_WEAPON_RAYGUN_MARK2", 10000, "raygun_mark2", "", undefined ); + } +} + +include_game_modules() +{ +} + +initial_round_wait_func() +{ + flag_wait( "initial_blackscreen_passed" ); +} + +zombie_speed_up() +{ + if ( isDefined( self.isonbus ) && self.isonbus ) + { + return; + } + if ( self.zombie_move_speed != "sprint" ) + { + self set_zombie_run_cycle( "sprint" ); + } +} + +zombie_init_done() +{ + self.allowpain = 0; + self setphysparams( 15, 0, 48 ); +} + +setup_dvars() +{ +/# + dvars = []; + dvars[ dvars.size ] = "zombie_bus_debug_path"; + dvars[ dvars.size ] = "zombie_bus_debug_speed"; + dvars[ dvars.size ] = "zombie_bus_debug_near"; + dvars[ dvars.size ] = "zombie_bus_debug_attach"; + dvars[ dvars.size ] = "zombie_bus_skip_objectives"; + dvars[ dvars.size ] = "zombie_bus_debug_spawners"; + i = 0; + while ( i < dvars.size ) + { + if ( getDvar( dvars[ i ] ) == "" ) + { + setdvar( dvars[ i ], "0" ); + } + i++; +#/ + } +} + +setup_zombie_init() +{ + zombies = getentarray( "zombie_spawner", "script_noteworthy" ); + array_thread( zombies, ::add_spawn_function, ::custom_zombie_setup ); +} + +setup_players() +{ + self.isonbus = 0; + self.isonbusroof = 0; + self.isinhub = 1; + self.insafearea = 1; +} + +transit_player_fake_death( vdir ) +{ + level notify( "fake_death" ); + self notify( "fake_death" ); + if ( isDefined( self.isonbus ) && self.isonbus ) + { + level thread transit_player_fake_death_zombies(); + } + stance = self getstance(); + self.ignoreme = 1; + self enableinvulnerability(); + self takeallweapons(); + if ( isDefined( self.insta_killed ) && !self.insta_killed || self istouching( getent( "depot_lava_pit", "targetname" ) ) && isDefined( self.isonbus ) && self.isonbus && level.the_bus.ismoving ) + { + self maps/mp/zombies/_zm::player_fake_death(); + self allowprone( 1 ); + self allowcrouch( 0 ); + self allowstand( 0 ); + wait 0,25; + self freezecontrols( 1 ); + } + else + { + self freezecontrols( 1 ); + self thread fall_down( vdir, stance ); + wait 1; + } +} + +transit_player_fake_death_zombies() +{ + zombies = getaiarray( level.zombie_team ); + _a2705 = zombies; + index = getFirstArrayKey( _a2705 ); + while ( isDefined( index ) ) + { + zombie = _a2705[ index ]; + if ( !isalive( zombie ) ) + { + } + else if ( isDefined( zombie.ignore_game_over_death ) && zombie.ignore_game_over_death ) + { + } + else + { + if ( isDefined( zombie ) ) + { + zombie dodamage( zombie.health + 666, zombie.origin ); + } + if ( ( index % 3 ) == 0 ) + { + wait_network_frame(); + } + } + index = getNextArrayKey( _a2705, index ); + } +} + +fall_down( vdir, stance ) +{ + self endon( "disconnect" ); + level endon( "game_module_ended" ); + self ghost(); + origin = self.origin; + xyspeed = ( 0, -1, 0 ); + angles = self getplayerangles(); + angles = ( angles[ 0 ], angles[ 1 ], angles[ 2 ] + randomfloatrange( -5, 5 ) ); + if ( isDefined( vdir ) && length( vdir ) > 0 ) + { + xyspeedmag = 40 + randomint( 12 ) + randomint( 12 ); + xyspeed = xyspeedmag * vectornormalize( ( vdir[ 0 ], vdir[ 1 ], 0 ) ); + } + linker = spawn( "script_origin", ( 0, -1, 0 ) ); + linker.origin = origin; + linker.angles = angles; + self._fall_down_anchor = linker; + self playerlinkto( linker ); + self playsoundtoplayer( "zmb_player_death_fall", self ); + falling = stance != "prone"; + if ( falling ) + { + origin = playerphysicstrace( origin, origin + xyspeed ); + eye = self get_eye(); + floor_height = ( 10 + origin[ 2 ] ) - eye[ 2 ]; + origin += ( 0, 0, floor_height ); + lerptime = 0,5; + linker moveto( origin, lerptime, lerptime ); + linker rotateto( angles, lerptime, lerptime ); + } + self freezecontrols( 1 ); + if ( falling ) + { + linker waittill( "movedone" ); + } + if ( isDefined( self.isonbus ) && self.isonbus ) + { + linker linkto( level.the_bus ); + } + self giveweapon( "death_throe_zm" ); + self switchtoweapon( "death_throe_zm" ); + if ( falling && isDefined( self.isonbus ) && !self.isonbus ) + { + bounce = randomint( 4 ) + 8; + origin = ( origin + ( 0, 0, bounce ) ) - ( xyspeed * 0,1 ); + lerptime = bounce / 50; + linker moveto( origin, lerptime, 0, lerptime ); + linker waittill( "movedone" ); + origin = ( origin + ( 0, 0, bounce * -1 ) ) + ( xyspeed * 0,1 ); + lerptime /= 2; + linker moveto( origin, lerptime, lerptime ); + linker waittill( "movedone" ); + linker moveto( origin, 5, 0 ); + } + wait 15; + linker delete(); +} + +transit_player_fake_death_cleanup() +{ + if ( isDefined( self._fall_down_anchor ) ) + { + self._fall_down_anchor delete(); + self._fall_down_anchor = undefined; + } +} + +custom_zombie_setup() +{ + if ( is_survival() && !is_standard() ) + { + self.nearbus = 0; + self.isonbus = 0; + self.isonbusroof = 0; + self.was_walking = 0; + self.candropsafekey = 1; + self.candropbuskey = 1; + self.custom_points_on_turret_damage = 0; + } +} + +bunkerdoorrotate( open, time ) +{ + if ( !isDefined( time ) ) + { + time = 0,2; + } + rotate = self.script_float; + if ( !open ) + { + rotate *= -1; + } + if ( isDefined( self.script_angles ) ) + { + self notsolid(); + self rotateto( self.script_angles, time, 0, 0 ); + self thread maps/mp/zombies/_zm_blockers::door_solid_thread(); + } +} + +zm_transit_emp_init() +{ + level.custom_emp_detonate = ::zm_transit_emp_detonate; + set_zombie_var( "emp_bus_off_range", 1200 ); + set_zombie_var( "emp_bus_off_time", 45 ); +} + +zm_transit_emp_detonate( grenade_origin ) +{ + test_ent = spawn( "script_origin", grenade_origin ); + if ( test_ent maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr" ) ) + { + if ( flag( "power_on" ) ) + { + trig = getent( "powerswitch_buildable_trigger_power", "targetname" ); + trig notify( "trigger" ); + } + } + test_ent delete(); +} + +emp_detonate_boss( grenade_origin ) +{ +} + +register_screecher_lights() +{ + level.safety_lights = getstructarray( "screecher_escape", "targetname" ); + i = 0; + while ( i < level.safety_lights.size ) + { + safety = level.safety_lights[ i ]; + name = safety.script_noteworthy; + if ( !isDefined( name ) ) + { +/# + println( "ERROR Unnamed screecher light detected" ); +#/ + name = "light_" + i; + } + clientfieldname = "screecher_light_" + name; + level.safety_lights[ i ].clientfieldname = clientfieldname; + registerclientfield( "world", clientfieldname, 1, 1, "int" ); + i++; + } +} + +include_powered_items() +{ + while ( is_classic() ) + { + include_powered_item( ::bus_power_on, ::bus_power_off, ::bus_range, ::maps/mp/zombies/_zm_power::cost_negligible, 1, 1, undefined ); + while ( isDefined( level.safety_lights ) ) + { + i = 0; + while ( i < level.safety_lights.size ) + { + include_powered_item( ::safety_light_power_on, ::safety_light_power_off, ::safety_light_range, ::maps/mp/zombies/_zm_power::cost_low_if_local, 0, 0, level.safety_lights[ i ] ); + i++; + } + } + } +} + +bus_range( delta, origin, radius ) +{ + if ( isDefined( level.the_bus ) ) + { + if ( distance2dsquared( origin, level.the_bus.origin ) < ( radius * radius ) ) + { + return 1; + } + forward = anglesToForward( level.the_bus.angles ); + forward = vectorScale( forward, 275 ); + bus_front = level.the_bus.origin + forward; + if ( distance2dsquared( origin, bus_front ) < ( radius * radius ) ) + { + return 1; + } + } + return 0; +} + +bus_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: bus on\n" ); +#/ + level.the_bus thread maps/mp/zm_transit_bus::bus_power_on(); +} + +bus_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: bus off\n" ); +#/ + level.the_bus thread maps/mp/zm_transit_bus::bus_power_off(); +} + +safety_light_range( delta, origin, radius ) +{ + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +safety_light_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: bus on\n" ); +#/ + self.target.power_on = 1; + self.target notify( "power_on" ); + if ( isDefined( self.target.clientfieldname ) ) + { + level setclientfield( self.target.clientfieldname, 1 ); + } + level notify( "safety_light_power_on" ); +} + +safety_light_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: bus off\n" ); +#/ + self.target.power_on = 0; + self.target notify( "power_off" ); + if ( isDefined( self.target.clientfieldname ) ) + { + level setclientfield( self.target.clientfieldname, 0 ); + } + level notify( "safety_light_power_off" ); +} + +zombie_transit_devgui( cmd ) +{ +/# + cmd_strings = strtok( cmd, " " ); + switch( cmd_strings[ 0 ] ) + { + case "pickup": + if ( !level.the_bus.upgrades[ cmd_strings[ 1 ] ].pickedup ) + { + level.the_bus.upgrades[ cmd_strings[ 1 ] ].trigger notify( "trigger" ); + } + break; + case "spawn": + player = get_players()[ 0 ]; + spawnername = undefined; + if ( cmd_strings[ 1 ] == "regular" ) + { + spawnername = "zombie_spawner"; + } + else if ( cmd_strings[ 1 ] == "screecher" ) + { + } + else + { + return; + } + direction = player getplayerangles(); + direction_vec = anglesToForward( direction ); + eye = player geteye(); + scale = 8000; + direction_vec = ( direction_vec[ 0 ] * scale, direction_vec[ 1 ] * scale, direction_vec[ 2 ] * scale ); + trace = bullettrace( eye, eye + direction_vec, 0, undefined ); + guy = undefined; + if ( cmd_strings[ 1 ] == "screecher" ) + { + spawner = level.screecher_spawners[ 0 ]; + guy = maps/mp/zombies/_zm_utility::spawn_zombie( spawner ); + } + else + { + if ( cmd_strings[ 1 ] == "regular" ) + { + spawners = getentarray( spawnername, "script_noteworthy" ); + spawner = spawners[ 0 ]; + guy = maps/mp/zombies/_zm_utility::spawn_zombie( spawner ); + guy.favoriteenemy = player; + guy.script_string = "zombie_chaser"; + guy thread maps/mp/zombies/_zm_spawner::zombie_spawn_init(); + guy custom_zombie_setup(); + } + } + guy forceteleport( trace[ "position" ], player.angles + vectorScale( ( 0, -1, 0 ), 180 ) ); + break; + case "test_attach": + attach_name = getDvar( "zombie_bus_debug_attach" ); + opening = level.the_bus maps/mp/zm_transit_openings::busgetopeningfortag( attach_name ); + jump = level.the_bus maps/mp/zm_transit_openings::_busgetjumptagfrombindtag( attach_name ); + if ( isDefined( opening ) ) + { + if ( isDefined( opening.zombie ) ) + { + iprintln( "Zombie already attached to opening: " + attach_name ); + } + else + { + origin = level.the_bus gettagorigin( attach_name ); + if ( isDefined( jump ) ) + { + jump_origin = level.the_bus gettagorigin( jump ); + if ( isDefined( opening.enabled ) && opening.enabled ) + { + debugstar( jump_origin, 1000, ( 0, -1, 0 ) ); + } + else + { + debugstar( jump_origin, 1000, ( 0, -1, 0 ) ); + } + } + zombie_spawners = getentarray( "zombie_spawner", "script_noteworthy" ); + zombie = spawn_zombie( zombie_spawners[ 0 ] ); + zombie.cannotattachtobus = 1; + zombie thread maps/mp/zm_transit_openings::zombieattachtobus( level.the_bus, opening, 0 ); + } + } + else + { + iprintln( "Couldn't find opening for tag: " + attach_name ); + } + break; + case "attach_tag": + setdvar( "zombie_bus_debug_attach", cmd_strings[ 1 ] ); + break; + case "hatch_available": + if ( isDefined( level.the_bus ) ) + { + level.the_bus notify( "hatch_mantle_allowed" ); + } + break; + case "ambush_round": + if ( isDefined( level.ambushpercentageperstop ) ) + { + if ( cmd_strings[ 1 ] == "always" ) + { + level.ambushpercentageperstop = 100; + } + else + { + if ( cmd_strings[ 1 ] == "never" ) + { + level.ambushpercentageperstop = 0; + } + } + } + break; + case "gas": + if ( cmd_strings[ 1 ] == "add" ) + { + level.the_bus maps/mp/zm_transit_bus::busgasadd( getDvarInt( #"69C4D2C1" ) ); + } + else + { + if ( cmd_strings[ 1 ] == "remove" ) + { + level.the_bus maps/mp/zm_transit_bus::busgasremove( getDvarInt( #"69C4D2C1" ) ); + } + } + break; + case "force_bus_to_leave": + level.the_bus notify( "depart_early" ); + if ( isDefined( level.bus_leave_hud ) ) + { + level.bus_leave_hud.alpha = 0; + } + break; + case "teleport_to_bus": + get_players()[ 0 ] setorigin( level.the_bus localtoworldcoords( vectorScale( ( 0, -1, 0 ), 25 ) ) ); + break; + case "teleport_bus": + node = getvehiclenode( cmd_strings[ 1 ], "script_noteworthy" ); + if ( isDefined( node ) ) + { + level.the_bus thread buspathblockerdisable(); + wait 0,1; + level.the_bus attachpath( node ); + level.the_bus maps/mp/zm_transit_bus::busstopmoving( 1 ); + wait 0,1; + level.the_bus thread buspathblockerenable(); + } + break; + case "avogadro_round_skip": + if ( isDefined( level.next_avogadro_round ) ) + { + maps/mp/zombies/_zm_devgui::zombie_devgui_goto_round( level.next_avogadro_round ); + } + break; + case "debug_print_emp_points": + while ( isDefined( level.debug_print_emp_points ) && !level.debug_print_emp_points ) + { + level.debug_print_emp_points = 1; + vehnodes = getvehiclenodearray( "emp_stop_point", "script_noteworthy" ); + _a3190 = vehnodes; + _k3190 = getFirstArrayKey( _a3190 ); + while ( isDefined( _k3190 ) ) + { + node = _a3190[ _k3190 ]; + maps/mp/zombies/_zm_devgui::showonespawnpoint( node, ( 0, -1, 0 ), "kill_debug_print_emp_points", undefined, "EMP STOP" ); + _k3190 = getNextArrayKey( _a3190, _k3190 ); + } + } + case "debug_stop_print_emp_points": + if ( isDefined( level.debug_print_emp_points ) && level.debug_print_emp_points ) + { + level notify( "kill_debug_print_emp_points" ); + level.debug_print_emp_points = undefined; + } + break; + default: + } +#/ + } + } +} + +is_valid_powerup_location( powerup ) +{ + valid = 0; + if ( !isDefined( level.powerup_areas ) ) + { + level.powerup_areas = getentarray( "powerup_area", "script_noteworthy" ); + } + if ( !isDefined( level.playable_areas ) ) + { + level.playable_areas = getentarray( "player_volume", "script_noteworthy" ); + } + i = 0; + while ( i < level.powerup_areas.size && !valid ) + { + area = level.powerup_areas[ i ]; + valid = powerup istouching( area ); + i++; + } + i = 0; + while ( i < level.playable_areas.size && !valid ) + { + area = level.playable_areas[ i ]; + valid = powerup istouching( area ); + i++; + } + return valid; +} + +zombie_transit_player_too_many_weapons_monitor_callback( weapon ) +{ + if ( self maps/mp/zm_transit_cling::playerisclingingtobus() ) + { + return 0; + } + return 1; +} + +zombie_transit_audio_alias_override() +{ + maps/mp/zm_transit_automaton::initaudioaliases(); + init_transit_player_dialogue(); + add_transit_response_chance(); +} + +falling_death_init() +{ + trig = getent( "transit_falling_death", "targetname" ); + while ( isDefined( trig ) ) + { + while ( 1 ) + { + trig waittill( "trigger", who ); + if ( isDefined( who.insta_killed ) && !who.insta_killed ) + { + who thread insta_kill_player(); + } + } + } +} + +insta_kill_player() +{ + self endon( "disconnect" ); + if ( isDefined( self.insta_killed ) && self.insta_killed ) + { + return; + } + self maps/mp/zombies/_zm_buildables::player_return_piece_to_original_spawn(); + if ( is_player_killable( self ) ) + { + self.insta_killed = 1; + in_last_stand = 0; + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + in_last_stand = 1; + } + if ( getnumconnectedplayers() == 1 ) + { + if ( isDefined( self.lives ) && self.lives > 0 ) + { + self.waiting_to_revive = 1; + points = getstruct( "zone_pcr", "script_noteworthy" ); + spawn_points = getstructarray( points.target, "targetname" ); + point = spawn_points[ 0 ]; + self dodamage( self.health + 1000, ( 0, -1, 0 ) ); + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_transit_burn", self, 1, level.zm_transit_burn_max_duration ); + wait 0,5; + self freezecontrols( 1 ); + wait 0,25; + self setorigin( point.origin + vectorScale( ( 0, -1, 0 ), 20 ) ); + self.angles = point.angles; + if ( in_last_stand ) + { + flag_set( "instant_revive" ); + wait_network_frame(); + flag_clear( "instant_revive" ); + } + else + { + self thread maps/mp/zombies/_zm_laststand::auto_revive( self ); + self.waiting_to_revive = 0; + self.solo_respawn = 0; + self.lives = 0; + } + self freezecontrols( 0 ); + self.insta_killed = 0; + } + else + { + self dodamage( self.health + 1000, ( 0, -1, 0 ) ); + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_transit_burn", self, 2, level.zm_transit_burn_max_duration ); + } + } + else + { + self dodamage( self.health + 1000, ( 0, -1, 0 ) ); + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_transit_burn", self, 1, level.zm_transit_burn_max_duration ); + wait_network_frame(); + self.bleedout_time = 0; + } + self notify( "burned" ); + self.insta_killed = 0; + } +} + +is_player_killable( player, checkignoremeflag ) +{ + if ( !isDefined( player ) ) + { + return 0; + } + if ( !isalive( player ) ) + { + return 0; + } + if ( !isplayer( player ) ) + { + return 0; + } + if ( player.sessionstate == "spectator" ) + { + return 0; + } + if ( player.sessionstate == "intermission" ) + { + return 0; + } + if ( isDefined( checkignoremeflag ) && player.ignoreme ) + { + return 0; + } + return 1; +} + +delete_bus_pieces() +{ + wait 3; + if ( isDefined( level._bus_pieces_deleted ) && level._bus_pieces_deleted ) + { + return; + } + level._bus_pieces_deleted = 1; + hatch_mantle = getent( "hatch_mantle", "targetname" ); + if ( isDefined( hatch_mantle ) ) + { + hatch_mantle delete(); + } + hatch_clip = getentarray( "hatch_clip", "targetname" ); + array_thread( hatch_clip, ::self_delete ); + plow_clip = getentarray( "plow_clip", "targetname" ); + array_thread( plow_clip, ::self_delete ); + light = getent( "busLight2", "targetname" ); + if ( isDefined( light ) ) + { + light delete(); + } + light = getent( "busLight1", "targetname" ); + if ( isDefined( light ) ) + { + light delete(); + } + blocker = getent( "bus_path_blocker", "targetname" ); + if ( isDefined( blocker ) ) + { + blocker delete(); + } + lights = getentarray( "bus_break_lights", "targetname" ); + array_thread( lights, ::self_delete ); + orgs = getentarray( "bus_bounds_origin", "targetname" ); + array_thread( orgs, ::self_delete ); + door_blocker = getentarray( "bus_door_blocker", "targetname" ); + array_thread( door_blocker, ::self_delete ); + driver = getent( "bus_driver_head", "targetname" ); + if ( isDefined( driver ) ) + { + driver delete(); + } + plow = getent( "trigger_plow", "targetname" ); + if ( isDefined( plow ) ) + { + plow delete(); + } + plow_attach_point = getent( "plow_attach_point", "targetname" ); + if ( isDefined( plow_attach_point ) ) + { + plow_attach_point delete(); + } + bus = getent( "the_bus", "targetname" ); + if ( isDefined( bus ) ) + { + bus delete(); + } + barriers = getzbarrierarray(); + _a3487 = barriers; + _k3487 = getFirstArrayKey( _a3487 ); + while ( isDefined( _k3487 ) ) + { + barrier = _a3487[ _k3487 ]; + if ( isDefined( barrier.classname ) && issubstr( barrier.classname, "zb_bus" ) ) + { + x = 0; + while ( x < barrier getnumzbarrierpieces() ) + { + barrier setzbarrierpiecestate( x, "opening" ); + x++; + } + barrier hide(); + } + _k3487 = getNextArrayKey( _a3487, _k3487 ); + } +} + +init_transit_stats() +{ + self maps/mp/zm_transit_sq::init_player_sidequest_stats(); + self maps/mp/zm_transit_achievement::init_player_achievement_stats(); +} + +kill_zombies_depot() +{ + if ( level.zones[ "zone_pri" ].is_occupied == 1 || flag( "OnPriDoorYar2" ) ) + { + return; + } + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_pri" ) ) + { + self.marked_for_recycle = 1; + self dodamage( self.health + 666, self.origin, self ); + return; + } + if ( isDefined( self.zone_name ) && self.zone_name != "zone_pri" && self.zone_name == "zone_pri2" || self.ignoreall && !self in_playable_zone() ) + { + self.marked_for_recycle = 1; + self dodamage( self.health + 666, self.origin, self ); + return; + } +} + +in_playable_zone() +{ + if ( !isDefined( level.playable_areas ) ) + { + level.playable_areas = getentarray( "player_volume", "script_noteworthy" ); + } + _a3541 = level.playable_areas; + _k3541 = getFirstArrayKey( _a3541 ); + while ( isDefined( _k3541 ) ) + { + zone = _a3541[ _k3541 ]; + if ( self istouching( zone ) ) + { + return 1; + } + _k3541 = getNextArrayKey( _a3541, _k3541 ); + } + return 0; +} + +lava_damage_depot() +{ + trigs = getentarray( "lava_damage", "targetname" ); + volume = getent( "depot_lava_volume", "targetname" ); + exploder( 2 ); + _a3560 = trigs; + _k3560 = getFirstArrayKey( _a3560 ); + while ( isDefined( _k3560 ) ) + { + trigger = _a3560[ _k3560 ]; + if ( isDefined( trigger.script_string ) && trigger.script_string == "depot_lava" ) + { + trig = trigger; + } + _k3560 = getNextArrayKey( _a3560, _k3560 ); + } + if ( isDefined( trig ) ) + { + trig.script_float = 0,05; + } + while ( level.round_number < 3 ) + { + level waittill( "start_of_round" ); + } + while ( !volume depot_lava_seen() ) + { + wait 2; + } + if ( isDefined( trig ) ) + { + trig.script_float = 0,4; + earthquake( 0,5, 1,5, trig.origin, 1000 ); + level clientnotify( "earth_crack" ); + crust = getent( "depot_black_lava", "targetname" ); + crust delete(); + } + stop_exploder( 2 ); + exploder( 3 ); +} + +depot_lava_seen() +{ + check_volume = getent( "depot_lava_check", "targetname" ); + players = get_players(); + _a3603 = players; + _k3603 = getFirstArrayKey( _a3603 ); + while ( isDefined( _k3603 ) ) + { + player = _a3603[ _k3603 ]; + if ( player istouching( check_volume ) ) + { + seen = self maps/mp/zm_transit_distance_tracking::player_can_see_me( player ); + if ( seen ) + { + return 1; + } + } + _k3603 = getNextArrayKey( _a3603, _k3603 ); + } + return 0; +} + +assign_lowest_unused_character_index() +{ + charindexarray = []; + charindexarray[ 0 ] = 0; + charindexarray[ 1 ] = 1; + charindexarray[ 2 ] = 2; + charindexarray[ 3 ] = 3; + players = get_players(); + if ( players.size == 1 ) + { + charindexarray = array_randomize( charindexarray ); + return charindexarray[ 0 ]; + } + else + { + if ( players.size == 2 ) + { + _a3633 = players; + _k3633 = getFirstArrayKey( _a3633 ); + while ( isDefined( _k3633 ) ) + { + player = _a3633[ _k3633 ]; + if ( isDefined( player.characterindex ) ) + { + if ( player.characterindex == 2 || player.characterindex == 0 ) + { + if ( randomint( 100 ) > 50 ) + { + return 1; + } + return 3; + } + else + { + if ( player.characterindex == 3 || player.characterindex == 1 ) + { + if ( randomint( 100 ) > 50 ) + { + return 0; + } + return 2; + } + } + } + _k3633 = getNextArrayKey( _a3633, _k3633 ); + } + } + else _a3659 = players; + _k3659 = getFirstArrayKey( _a3659 ); + while ( isDefined( _k3659 ) ) + { + player = _a3659[ _k3659 ]; + if ( isDefined( player.characterindex ) ) + { + arrayremovevalue( charindexarray, player.characterindex, 0 ); + } + _k3659 = getNextArrayKey( _a3659, _k3659 ); + } + if ( charindexarray.size > 0 ) + { + return charindexarray[ 0 ]; + } + } + return 0; +} + +dog_spawn_transit_logic( dog_array, favorite_enemy ) +{ + dog_locs = array_randomize( level.enemy_dog_locations ); + i = 0; + while ( i < dog_locs.size ) + { + if ( isDefined( level.old_dog_spawn ) && level.old_dog_spawn == dog_locs[ i ] ) + { + i++; + continue; + } + else + { + canuse = 1; + players = get_players(); + _a3692 = players; + _k3692 = getFirstArrayKey( _a3692 ); + while ( isDefined( _k3692 ) ) + { + player = _a3692[ _k3692 ]; + if ( !canuse ) + { + } + else + { + dist_squared = distancesquared( dog_locs[ i ].origin, player.origin ); + if ( dist_squared < 160000 || dist_squared > 1322500 ) + { + canuse = 0; + } + } + _k3692 = getNextArrayKey( _a3692, _k3692 ); + } + if ( canuse ) + { + level.old_dog_spawn = dog_locs[ i ]; + return dog_locs[ i ]; + } + } + i++; + } + return dog_locs[ 0 ]; +} + +bank_teller_init() +{ + playfx( level._effect[ "fx_zmb_tranzit_key_glint" ], ( 760, 461, -30 ), vectorScale( ( 0, -1, 0 ), 90 ) ); + playfx( level._effect[ "fx_zmb_tranzit_key_glint" ], ( 760, 452, -30 ), vectorScale( ( 0, -1, 0 ), 90 ) ); +} + +player_name_fade_control() +{ + while ( 1 ) + { + players = get_players(); + _a3731 = players; + _k3731 = getFirstArrayKey( _a3731 ); + while ( isDefined( _k3731 ) ) + { + player = _a3731[ _k3731 ]; + if ( !isDefined( player.infog ) ) + { + player.infog = 0; + player.old_infog = 0; + player.infogtimer = 0; + } + player.old_infog = player.infog; + infog = is_player_in_fog( player ); + if ( infog ) + { + player.infogtimer++; + } + player.infog = infog; + if ( player.infog != player.old_infog && isDefined( player.isonbus ) && !player.isonbus ) + { + if ( infog ) + { + if ( player.infogtimer < 5 ) + { + } + else line = "in_fog"; + } + else + { + if ( player.infogtimer < 15 ) + { + } + else + { + line = "out_of_fog"; + player.infogtimer = 0; + } + if ( maps/mp/zombies/_zm_audio::get_response_chance( line ) > randomint( 100 ) && !isDefined( player.screecher ) ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", line ); + } + } + if ( isDefined( level.set_player_in_fog ) ) + { + player thread [[ level.set_player_in_fog ]]( infog ); + } + } + _k3731 = getNextArrayKey( _a3731, _k3731 ); + } + wait 1; + } +} + +is_player_in_fog( player ) +{ + if ( player_entered_safety_zone( player ) ) + { + return 0; + } + if ( player_entered_safety_light( player ) ) + { + return 0; + } + curr_zone = player get_current_zone( 1 ); + if ( isDefined( curr_zone ) && isDefined( curr_zone.screecher_zone ) && !curr_zone.screecher_zone ) + { + return 0; + } + return 1; +} + +add_transit_response_chance() +{ + add_vox_response_chance( "in_fog", 100 ); + add_vox_response_chance( "out_of_fog", 65 ); + add_vox_response_chance( "killed_screecher", 20 ); + add_vox_response_chance( "screecher_attack", 5 ); + add_vox_response_chance( "screecher_flee", 50 ); + add_vox_response_chance( "screecher_cut", 15 ); + add_vox_response_chance( "screecher_flee_green", 75 ); + add_vox_response_chance( "crawl_spawn", 10 ); + add_vox_response_chance( "screecher_jumpoff", 50 ); + add_vox_response_chance( "reboard", 5 ); + add_vox_response_chance( "jetgun_kill", 10 ); + add_vox_response_chance( "achievement", 100 ); + add_vox_response_chance( "power_on", 100 ); + add_vox_response_chance( "power_off", 100 ); + add_vox_response_chance( "power_core", 100 ); + add_vox_response_chance( "upgrade", 100 ); + add_vox_response_chance( "build_pck_bshield", 45 ); + add_vox_response_chance( "build_pck_bturret", 45 ); + add_vox_response_chance( "build_pck_btrap", 45 ); + add_vox_response_chance( "build_pck_bturbine", 45 ); + add_vox_response_chance( "build_pck_bjetgun", 45 ); + add_vox_response_chance( "build_pck_wshield", 45 ); + add_vox_response_chance( "build_pck_wturret", 45 ); + add_vox_response_chance( "build_pck_wtrap", 45 ); + add_vox_response_chance( "build_pck_wturbine", 45 ); + add_vox_response_chance( "build_pck_wjetgun", 45 ); + add_vox_response_chance( "build_plc_shield", 45 ); + add_vox_response_chance( "build_plc_turret", 45 ); + add_vox_response_chance( "build_plc_trap", 45 ); + add_vox_response_chance( "build_plc_turbine", 45 ); + add_vox_response_chance( "build_pickup", 45 ); + add_vox_response_chance( "build_swap", 45 ); + add_vox_response_chance( "build_add", 45 ); + add_vox_response_chance( "build_final", 45 ); +} + +init_transit_player_dialogue() +{ + level.vox zmbvoxadd( "player", "general", "in_fog", "map_in_fog", undefined ); + level.vox zmbvoxadd( "player", "general", "out_of_fog", "map_out_fog", undefined ); + level.vox zmbvoxadd( "player", "perk", "specialty_scavenger", "perk_tombstone", undefined ); + level.vox zmbvoxadd( "player", "general", "revive_down", "bus_down", undefined ); + level.vox zmbvoxadd( "player", "general", "revive_up", "heal_revived", undefined ); + level.vox zmbvoxadd( "player", "general", "screecher_attack", "screecher_attack", "resp_screecher_attack" ); + level.vox zmbvoxadd( "player", "general", "hr_resp_screecher_attack", "hr_resp_screecher_attack", undefined ); + level.vox zmbvoxadd( "player", "general", "riv_resp_screecher_attack", "riv_resp_screecher_attack", undefined ); + level.vox zmbvoxadd( "player", "general", "screecher_flee", "screecher_flee", undefined ); + level.vox zmbvoxadd( "player", "general", "screecher_jumpoff", "screecher_off", undefined ); + level.vox zmbvoxadd( "player", "general", "screecher_flee_green", "screecher_teleport", undefined ); + level.vox zmbvoxadd( "player", "kill", "screecher", "kill_screecher", undefined ); + level.vox zmbvoxadd( "player", "general", "screecher_cut", "screecher_cut", undefined ); + level.vox zmbvoxadd( "player", "general", "achievement", "earn_acheivement", undefined ); + level.vox zmbvoxadd( "player", "general", "no_money_weapon", "nomoney_weapon", undefined ); + level.vox zmbvoxadd( "player", "general", "no_money_box", "nomoney_box", undefined ); + level.vox zmbvoxadd( "player", "general", "exert_sigh", "exert_sigh", undefined ); + level.vox zmbvoxadd( "player", "general", "exert_laugh", "exert_laugh", undefined ); + level.vox zmbvoxadd( "player", "general", "pain_high", "pain_high", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_bshield", "build_pck_bshield", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_bturret", "build_pck_bturret", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_btrap", "build_pck_btrap", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_bturbine", "build_pck_bturbine", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_bjetgun", "build_pck_bjetgun", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_wshield", "build_pck_wshield", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_wturret", "build_pck_wturret", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_wtrap", "build_pck_wtrap", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_wturbine", "build_pck_wturbine", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pck_wjetgun", "build_pck_wjetgun", undefined ); + level.vox zmbvoxadd( "player", "general", "build_plc_shield", "build_plc_shield", undefined ); + level.vox zmbvoxadd( "player", "general", "build_plc_turret", "build_plc_turret", undefined ); + level.vox zmbvoxadd( "player", "general", "build_plc_trap", "build_plc_trap", undefined ); + level.vox zmbvoxadd( "player", "general", "build_plc_turbine", "build_plc_turbine", undefined ); + level.vox zmbvoxadd( "player", "general", "build_pickup", "build_pickup", undefined ); + level.vox zmbvoxadd( "player", "general", "build_swap", "build_swap", undefined ); + level.vox zmbvoxadd( "player", "general", "build_add", "build_add", undefined ); + level.vox zmbvoxadd( "player", "general", "build_final", "build_final", undefined ); + level.vox zmbvoxadd( "player", "general", "intro", "power_off", undefined ); + level.vox zmbvoxadd( "player", "power", "power_on", "power_on", undefined ); + level.vox zmbvoxadd( "player", "power", "power_core", "power_core", undefined ); + level.vox zmbvoxadd( "player", "general", "reboard", "rebuild_boards", undefined ); + level.vox zmbvoxadd( "player", "general", "upgrade", "find_secret", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_bus", "map_out_bus", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_tunnel", "map_out_tunnel", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_diner", "map_out_diner", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_1forest", "map_out_1forest", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_farm", "map_out_farm", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_corn", "map_out_corn", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_power", "map_out_power", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_2forest", "map_out_2forest", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_town", "map_out_town", undefined ); + level.vox zmbvoxadd( "player", "general", "map_out_bridge", "map_out_bridge", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bus1", "map_in_bus1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_tunnel1", "map_in_tunnel1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_diner1", "map_in_diner1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_1forest1", "map_in_1forest1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_farm1", "map_in_farm1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_corn1", "map_in_corn1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_power1", "map_in_power1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_2forest1", "map_in_2forest1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_town1", "map_in_town1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bridge1", "map_in_bridge1", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bus2", "map_in_bus2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_tunnel2", "map_in_tunnel2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_diner2", "map_in_diner2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_1forest2", "map_in_1forest2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_farm2", "map_in_farm2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_corn2", "map_in_corn2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_power2", "map_in_power2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_2forest2", "map_in_2forest2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_town2", "map_in_town2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bridge2", "map_in_bridge2", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bus3", "map_in_bus3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_tunnel3", "map_in_tunnel3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_diner3", "map_in_diner3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_1forest3", "map_in_1forest3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_farm3", "map_in_farm3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_corn3", "map_in_corn3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_power3", "map_in_power3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_2forest3", "map_in_2forest3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_town3", "map_in_town3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bridge3", "map_in_bridge3", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bus4", "map_in_bus4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_tunnel4", "map_in_tunnel4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_diner4", "map_in_diner4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_1forest4", "map_in_1forest4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_farm4", "map_in_farm4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_corn4", "map_in_corn4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_power4", "map_in_power4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_2forest4", "map_in_2forest4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_town4", "map_in_town4", undefined ); + level.vox zmbvoxadd( "player", "general", "map_in_bridge4", "map_in_bridge4", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_zom_roof", "bus_zom_roof", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_zom_climb", "bus_zom_climb", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_zom_atk", "bus_zom_atk", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_zom_ent", "bus_zom_ent", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_zom_none", "bus_zom_none", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_zom_chase", "bus_zom_chase", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_stop", "bus_stop", undefined ); + level.vox zmbvoxadd( "player", "general", "bus_ride", "bus_ride", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_reveal", "avogadro_reveal", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_above", "avogadro_above", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_storm", "avogadro_storm", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_arrive", "avogadro_arrive", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_attack", "avogadro_attack", "resp_avogadro_attack" ); + level.vox zmbvoxadd( "player", "general", "hr_resp_avogadro_attack", "hr_resp_avogadro_attack", undefined ); + level.vox zmbvoxadd( "player", "general", "riv_resp_avogadro_attack", "riv_resp_avogadro_attack", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_wound", "avogadro_wound", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_flee", "avogadro_flee", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_onbus", "avogadro_onbus", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_atkbus", "avogadro_atkbus", undefined ); + level.vox zmbvoxadd( "player", "general", "avogadro_stopbus", "avogadro_stopbus", undefined ); + level.vox zmbvoxadd( "player", "general", "exert_death", "exert_death_high", undefined ); + level.vox zmbvoxadd( "player", "kill", "jetgun_kill", "kill_jet", undefined ); + level.vox zmbvoxadd( "player", "general", "pap_wait", "pap_wait", undefined ); + level.vox zmbvoxadd( "player", "general", "pap_wait2", "pap_wait2", undefined ); + level.vox zmbvoxadd( "player", "general", "pap_arm", "pap_arm", undefined ); + level.vox zmbvoxadd( "player", "general", "pap_arm2", "pap_arm2", undefined ); + level.vox zmbvoxadd( "player", "general", "pap_hint", "pap_hint", undefined ); + maps/mp/zombies/_zm_audio_announcer::createvox( "first_drop", "first_drop" ); + level.station_pa_vox = []; + i = 0; + while ( i < 10 ) + { + level.station_pa_vox[ i ] = "vox_stat_pa_generic_" + i; + i++; + } + level.survivor_vox = []; + i = 0; + while ( i < 5 ) + { + level.survivor_vox[ i ] = "vox_radi_distress_message_" + i; + i++; + } +} + +transit_audio_custom_response_line( player, index, category, type ) +{ + russman = 0; + samuel = 1; + misty = 2; + marlton = 3; + switch( player.characterindex ) + { + case 0: + level maps/mp/zombies/_zm_audio::setup_hero_rival( player, samuel, marlton, category, type ); + break; + case 1: + level maps/mp/zombies/_zm_audio::setup_hero_rival( player, russman, misty, category, type ); + break; + case 2: + level maps/mp/zombies/_zm_audio::setup_hero_rival( player, marlton, samuel, category, type ); + break; + case 3: + level maps/mp/zombies/_zm_audio::setup_hero_rival( player, misty, russman, category, type ); + break; + } + return; +} + +powerup_intro_vox( powerup ) +{ + say_intro = 0; + players = get_players(); + _a4062 = players; + _k4062 = getFirstArrayKey( _a4062 ); + while ( isDefined( _k4062 ) ) + { + player = _a4062[ _k4062 ]; + if ( player maps/mp/zombies/_zm_stats::get_global_stat( "POWERUP_INTRO_PLAYED" ) == 1 ) + { + } + else player maps/mp/zombies/_zm_stats::set_global_stat( "powerup_intro_played", 1 ); + say_intro = 1; + _k4062 = getNextArrayKey( _a4062, _k4062 ); + } + level.powerup_intro_vox = undefined; + powerup_name = powerup.powerup_name; + powerup thread maps/mp/zombies/_zm_powerups::powerup_delete(); + powerup notify( "powerup_grabbed" ); + if ( !say_intro ) + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( powerup_name ); + level.powerup_vo_available = undefined; + return; + } + flag_clear( "zombie_drop_powerups" ); + level.powerup_intro = 1; + org = spawn( "script_origin", get_players()[ 0 ].origin ); + org playsoundwithnotify( "vox_zmba_first_drop_0", "first_powerup_intro_done" ); + org waittill( "first_powerup_intro_done" ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( powerup_name ); + org delete(); + flag_set( "zombie_drop_powerups" ); + level.powerup_intro = 0; + level.powerup_vo_available = undefined; +} + +powerup_vo_available() +{ + wait 0,1; + if ( isDefined( level.powerup_intro ) && level.powerup_intro ) + { + return 0; + } + return 1; +} + +buildable_build_custom_func( stub ) +{ + buildable = stub.buildablezone; + counter = 0; + i = 0; + while ( i < buildable.pieces.size ) + { + if ( isDefined( buildable.pieces[ i ].built ) && buildable.pieces[ i ].built ) + { + counter++; + } + i++; + } + if ( counter == ( buildable.pieces.size - 1 ) ) + { + self thread do_player_general_vox( "general", "build_final", 45 ); + } +} + +bank_pap_hint() +{ + volume = getent( "zone_ban", "targetname" ); + while ( 1 ) + { + players = get_players(); + _a4136 = players; + _k4136 = getFirstArrayKey( _a4136 ); + while ( isDefined( _k4136 ) ) + { + player = _a4136[ _k4136 ]; + if ( player istouching( volume ) && is_player_valid( player ) ) + { + player thread do_player_general_vox( "general", "pap_hint", undefined, 100 ); + return; + } + _k4136 = getNextArrayKey( _a4136, _k4136 ); + } + wait 10; + } +} + +power_pap_hint() +{ + trigs = getentarray( "local_electric_door", "script_noteworthy" ); + lab_trig = undefined; + _a4155 = trigs; + _k4155 = getFirstArrayKey( _a4155 ); + while ( isDefined( _k4155 ) ) + { + trig = _a4155[ _k4155 ]; + if ( isDefined( trig.target ) && trig.target == "lab_secret_hatch" ) + { + lab_trig = trig; + } + _k4155 = getNextArrayKey( _a4155, _k4155 ); + } + if ( !isDefined( lab_trig ) ) + { + return; + } + while ( 1 ) + { + lab_trig waittill( "trigger", who ); + if ( isplayer( who ) && is_player_valid( who ) ) + { + who thread do_player_general_vox( "general", "pap_hint", undefined, 100 ); + return; + } + } +} + +transit_buildable_vo_override( name, from_world ) +{ + if ( isDefined( level.power_cycled ) && level.power_cycled && name == "turbine" && isDefined( from_world ) && !from_world && !flag( "power_on" ) ) + { + level.maxis_turbine_pickedup_vox = 1; + level thread maps/mp/zm_transit_sq::maxissay( "vox_maxi_build_complete_0", ( -6848, 5056, 56 ) ); + return 1; + } + return 0; +} + +sndsetupmusiceasteregg() +{ + origins = []; + origins[ 0 ] = ( -7562, 4570, -19 ); + origins[ 1 ] = ( 7914, -6557, 269 ); + origins[ 2 ] = ( 1864, -7, -19 ); + level.meteor_counter = 0; + level.music_override = 0; + i = 0; + while ( i < origins.size ) + { + level thread sndmusicegg( origins[ i ] ); + i++; + } +} + +sndmusicegg( bear_origin ) +{ + temp_ent = spawn( "script_origin", bear_origin ); + temp_ent playloopsound( "zmb_meteor_loop" ); + temp_ent thread maps/mp/zombies/_zm_sidequests::fake_use( "main_music_egg_hit", ::waitfor_override ); + temp_ent waittill( "main_music_egg_hit", player ); + temp_ent stoploopsound( 1 ); + player playsound( "zmb_meteor_activate" ); + level.meteor_counter += 1; + if ( level.meteor_counter == 3 ) + { + level thread sndplaymusicegg( player, temp_ent ); + } + else + { + wait 1,5; + temp_ent delete(); + } +} + +waitfor_override() +{ + if ( isDefined( level.music_override ) && level.music_override ) + { + return 0; + } + return 1; +} + +sndplaymusicegg( player, ent ) +{ + wait 1; + ent playsound( "mus_zmb_secret_song" ); + level waittill( "end_game" ); + ent stopsounds(); + wait 0,05; + ent delete(); +} + +sndtoiletflush() +{ + toilettrig = spawn( "trigger_radius", ( 11182, 7584, -596 ), 0, 150, 5 ); + toilettrig sethintstring( "" ); + toilettrig setcursorhint( "HINT_NOICON" ); + while ( 1 ) + { + toilettrig waittill( "trigger", who ); + if ( who is_player() ) + { + toilettrig playsound( "zmb_toilet_flush" ); + wait 5; + } + wait 0,1; + } +} + +transit_special_weapon_magicbox_check( weapon ) +{ + if ( isDefined( level.raygun2_included ) && level.raygun2_included ) + { + if ( weapon == "ray_gun_zm" ) + { + if ( self has_weapon_or_upgrade( "raygun_mark2_zm" ) || maps/mp/zombies/_zm_tombstone::is_weapon_available_in_tombstone( "raygun_mark2_zm", self ) ) + { + return 0; + } + } + if ( weapon == "raygun_mark2_zm" ) + { + if ( self has_weapon_or_upgrade( "ray_gun_zm" ) || maps/mp/zombies/_zm_tombstone::is_weapon_available_in_tombstone( "ray_gun_zm", self ) ) + { + return 0; + } + if ( randomint( 100 ) >= 33 ) + { + return 0; + } + } + } + return 1; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_achievement.gsc b/zm_transit_patch/maps/mp/zm_transit_achievement.gsc new file mode 100644 index 0000000..97d93b7 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_achievement.gsc @@ -0,0 +1,181 @@ +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +init() +{ + if ( is_classic() ) + { + level thread achievement_transit_sidequest(); + level thread achievement_undead_mans_party_bus(); + } + level.achievement_sound_func = ::achievement_sound_func; + onplayerconnect_callback( ::onplayerconnect ); +} + +init_player_achievement_stats() +{ + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dont_fire_until_you_see", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_the_lights_of_their_eyes", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dance_on_my_grave", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_standard_equipment_may_vary", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_you_have_no_power_over_me", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_i_dont_think_they_exist", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_fuel_efficient", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_happy_hour", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_transit_sidequest", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_undead_mans_party_bus", 0 ); +} + +onplayerconnect() +{ + self thread achievement_the_lights_of_their_eyes(); + self thread achievement_dance_on_my_grave(); + if ( is_classic() ) + { + self thread achievement_dont_fire_until_you_see(); + self thread achievement_standard_equipment_may_vary(); + self thread achievement_you_have_no_power_over_me(); + self thread achievement_i_dont_think_they_exist(); + self thread achievement_fuel_efficient(); + self thread achievement_zm_happy_hour(); + } +} + +achievement_transit_sidequest() +{ + level endon( "end_game" ); + level waittill( "transit_sidequest_achieved" ); + level giveachievement_wrapper( "ZM_TRANSIT_SIDEQUEST", 1 ); +} + +achievement_undead_mans_party_bus() +{ + level endon( "end_game" ); + flag_wait( "start_zombie_round_logic" ); + wait 0,05; + flag_wait( "ladder_attached" ); + flag_wait( "catcher_attached" ); + flag_wait( "hatch_attached" ); +/# +#/ + level giveachievement_wrapper( "ZM_UNDEAD_MANS_PARTY_BUS", 1 ); +} + +achievement_dont_fire_until_you_see() +{ + level endon( "end_game" ); + self endon( "burned" ); + zombie_doors = getentarray( "zombie_door", "targetname" ); + while ( 1 ) + { + level waittill( "door_opened" ); + num_left = 0; + all_opened = 1; + _a92 = zombie_doors; + _k92 = getFirstArrayKey( _a92 ); + while ( isDefined( _k92 ) ) + { + door = _a92[ _k92 ]; + if ( isDefined( door.has_been_opened ) && !door.has_been_opened ) + { + num_left++; + all_opened = 0; + } + _k92 = getNextArrayKey( _a92, _k92 ); + } + if ( all_opened ) + { + break; + } + else + { +/# +#/ + } + } +/# +#/ + self giveachievement_wrapper( "ZM_DONT_FIRE_UNTIL_YOU_SEE" ); +} + +achievement_the_lights_of_their_eyes() +{ + level endon( "end_game" ); + self waittill( "the_lights_of_their_eyes" ); +/# +#/ + self giveachievement_wrapper( "ZM_THE_LIGHTS_OF_THEIR_EYES" ); +} + +achievement_dance_on_my_grave() +{ + level endon( "end_game" ); + self waittill( "dance_on_my_grave" ); +/# +#/ + self giveachievement_wrapper( "ZM_DANCE_ON_MY_GRAVE" ); +} + +achievement_standard_equipment_may_vary() +{ + level endon( "end_game" ); + self waittill_subset( 4, "equip_electrictrap_zm_given", "riotshield_zm_given", "equip_turbine_zm_given", "equip_turret_zm_given", "jetgun_zm_given" ); +/# +#/ + self giveachievement_wrapper( "ZM_STANDARD_EQUIPMENT_MAY_VARY" ); +} + +achievement_you_have_no_power_over_me() +{ + level endon( "end_game" ); + self endon( "avogadro_damage_taken" ); + level waittill( "avogadro_defeated" ); +/# +#/ + self giveachievement_wrapper( "ZM_YOU_HAVE_NO_POWER_OVER_ME" ); +} + +achievement_i_dont_think_they_exist() +{ + level endon( "end_game" ); + self waittill( "i_dont_think_they_exist" ); +/# +#/ + self giveachievement_wrapper( "ZM_I_DONT_THINK_THEY_EXIST" ); +} + +achievement_fuel_efficient() +{ + level endon( "end_game" ); + self waittill( "used_screecher_hole" ); +/# +#/ + self giveachievement_wrapper( "ZM_FUEL_EFFICIENT" ); +} + +achievement_zm_happy_hour() +{ + level endon( "end_game" ); + level endon( "power_on" ); + while ( 1 ) + { + self waittill( "perk_acquired" ); + if ( isDefined( self.perk_history ) && self.perk_history.size >= 2 ) + { + break; + } + else + { + } + } +/# +#/ + self giveachievement_wrapper( "ZM_HAPPY_HOUR" ); +} + +achievement_sound_func( achievement_name_lower ) +{ + self thread do_player_general_vox( "general", "achievement" ); +} diff --git a/zm_transit_patch/maps/mp/zm_transit_ai_screecher.gsc b/zm_transit_patch/maps/mp/zm_transit_ai_screecher.gsc new file mode 100644 index 0000000..c09874c --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_ai_screecher.gsc @@ -0,0 +1,291 @@ +#include maps/mp/zm_transit; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_gump; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_ai_screecher; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level.screecher_should_burrow = ::screecher_should_burrow; + level.screecher_should_runaway = ::screecher_should_runaway; + level.screecher_cleanup = ::transit_screecher_cleanup; + level.screecher_init_done = ::screecher_init_done; + level.portals = []; +} + +screecher_should_burrow() +{ + green_light = self.green_light; + if ( isDefined( green_light ) ) + { + if ( isDefined( green_light.burrow_active ) && green_light.burrow_active ) + { +/# + screecher_print( "burrow: already active" ); +#/ + return 0; + } + if ( isDefined( green_light.claimed ) && green_light.claimed ) + { +/# + screecher_print( "burrow: already claimed" ); +#/ + return 0; + } + ground_pos = groundpos( green_light.origin ); + self.ignoreall = 1; + green_light.claimed = 1; + self setgoalpos( ground_pos ); + self waittill( "goal" ); + self.state = "burrow_started"; + self setfreecameralockonallowed( 0 ); + self animscripted( ground_pos, self.angles, "zm_burrow" ); + self playsound( "zmb_screecher_dig" ); + if ( isDefined( green_light.burrow_active ) && !green_light.burrow_active && isDefined( green_light.power_on ) && green_light.power_on ) + { + green_light thread create_portal(); + } + maps/mp/animscripts/zm_shared::donotetracks( "burrow_anim" ); + green_light notify( "burrow_done" ); + self.state = "burrow_finished"; + self delete(); + return 1; + } + return 0; +} + +create_portal() +{ + self endon( "portal_stopped" ); + self.burrow_active = 1; + ground_pos = groundpos( self.origin ); + if ( !isDefined( self.hole ) ) + { + self.hole = spawn( "script_model", ground_pos + vectorScale( ( 0, 0, 1 ), 20 ) ); + self.hole.start_origin = self.hole.origin; + self.hole setmodel( "p6_zm_screecher_hole" ); + self.hole playsound( "zmb_screecher_portal_spawn" ); + } + if ( !isDefined( self.hole_fx ) ) + { + self.hole_fx = spawn( "script_model", ground_pos ); + self.hole_fx setmodel( "tag_origin" ); + } + wait 0,1; + playfxontag( level._effect[ "screecher_hole" ], self.hole_fx, "tag_origin" ); + self.hole moveto( self.hole.origin + vectorScale( ( 0, 0, 1 ), 20 ), 1 ); + self waittill( "burrow_done" ); + self thread portal_think(); +} + +portal_think() +{ + playfxontag( level._effect[ "screecher_vortex" ], self.hole, "tag_origin" ); + self.hole_fx delete(); + self.hole playloopsound( "zmb_screecher_portal_loop", 2 ); + level.portals[ level.portals.size ] = self; +} + +portal_player_watcher() +{ + self endon( "disconnect" ); + while ( 1 ) + { + if ( !self isonground() ) + { + self player_wait_land(); + } + wait 0,1; + } +} + +player_wait_land() +{ + self endon( "disconnect" ); + while ( !self isonground() ) + { + wait 0,1; + } + if ( level.portals.size > 0 ) + { + remove_portal = undefined; + _a159 = level.portals; + _k159 = getFirstArrayKey( _a159 ); + while ( isDefined( _k159 ) ) + { + portal = _a159[ _k159 ]; + dist_sq = distance2dsquared( self.origin, portal.origin ); + if ( dist_sq < 4096 ) + { + remove_portal = portal; + break; + } + else + { + _k159 = getNextArrayKey( _a159, _k159 ); + } + } + if ( isDefined( remove_portal ) ) + { + arrayremovevalue( level.portals, remove_portal ); + portal portal_use( self ); + wait 0,5; + } + } +} + +portal_use( player ) +{ + player playsoundtoplayer( "zmb_screecher_portal_warp_2d", player ); + self thread teleport_player( player ); + playsoundatposition( "zmb_screecher_portal_end", self.hole.origin ); + self.hole delete(); + self.burrow_active = 0; +} + +teleport_player( player ) +{ + lights = getstructarray( "screecher_escape", "targetname" ); + lights = array_randomize( lights ); + dest_light = undefined; + _a198 = lights; + _k198 = getFirstArrayKey( _a198 ); + while ( isDefined( _k198 ) ) + { + light = _a198[ _k198 ]; + if ( light == self ) + { + } + else if ( light other_players_close_to_light( player ) ) + { + } + else + { + dest_light = light; + break; + } + _k198 = getNextArrayKey( _a198, _k198 ); + } + if ( isDefined( dest_light ) ) + { + playsoundatposition( "zmb_screecher_portal_arrive", dest_light.origin ); + player maps/mp/zombies/_zm_gump::player_teleport_blackscreen_on(); + player setorigin( dest_light.origin ); + player notify( "used_screecher_hole" ); + player maps/mp/zombies/_zm_stats::increment_client_stat( "screecher_teleporters_used", 0 ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "screecher_teleporters_used" ); + } +} + +other_players_close_to_light( ignore_player ) +{ + players = get_players(); + while ( players.size > 1 ) + { + _a236 = players; + _k236 = getFirstArrayKey( _a236 ); + while ( isDefined( _k236 ) ) + { + player = _a236[ _k236 ]; + if ( player == ignore_player ) + { + } + else + { + dist_sq = distance2dsquared( player.origin, self.origin ); + if ( dist_sq < 14400 ) + { + return 1; + } + } + _k236 = getNextArrayKey( _a236, _k236 ); + } + } + return 0; +} + +screecher_should_runaway( player ) +{ + if ( maps/mp/zm_transit::player_entered_safety_light( player ) ) + { +/# + screecher_print( "runaway: green light" ); +#/ + if ( !isDefined( player.screecher ) ) + { + player thread do_player_general_vox( "general", "screecher_flee_green" ); + } + return 1; + } + if ( maps/mp/zm_transit::player_entered_safety_zone( player ) ) + { +/# + screecher_print( "runaway: safety zone" ); +#/ + if ( !isDefined( player.screecher ) ) + { + player thread do_player_general_vox( "general", "screecher_flee" ); + } + return 1; + } + bus_dist_sq = distancesquared( player.origin, level.the_bus.origin ); + if ( bus_dist_sq < 62500 ) + { +/# + screecher_print( "runaway: bus" ); +#/ + if ( !isDefined( player.screecher ) ) + { + player thread do_player_general_vox( "general", "screecher_flee" ); + } + return 1; + } + return 0; +} + +transit_screecher_cleanup() +{ + green_light = self.green_light; + if ( isDefined( green_light ) ) + { + if ( isDefined( green_light.claimed ) ) + { + green_light.claimed = undefined; + } + if ( self.state == "burrow_started" ) + { +/# + screecher_print( "clean up portal" ); +#/ + green_light notify( "portal_stopped" ); + green_light.hole moveto( green_light.hole.start_origin, 1 ); + green_light.burrow_active = 0; + if ( isDefined( green_light.hole_fx ) ) + { + green_light.hole_fx delete(); + } + } + } +} + +screecher_init_done() +{ + self endon( "death" ); + while ( 1 ) + { + ground_ent = self getgroundent(); + if ( isDefined( ground_ent ) && ground_ent == level.the_bus ) + { + self dodamage( self.health + 666, self.origin ); +/# + screecher_print( "Died on bus" ); +#/ + } + wait 0,1; + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_ambush.gsc b/zm_transit_patch/maps/mp/zm_transit_ambush.gsc new file mode 100644 index 0000000..138b202 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_ambush.gsc @@ -0,0 +1,295 @@ +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zm_transit_bus; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +main() +{ + level.numroundssincelastambushround = 0; + level.numbusstopssincelastambushround = 0; + level.numambushrounds = 0; + level.ambushpercentageperstop = 10; + level.ambushpercentageperround = 25; + flag_init( "ambush_round", 0 ); + flag_init( "ambush_safe_area_active", 0 ); + initambusheffects(); + thread ambushroundkeeper(); +/# + adddebugcommand( "devgui_cmd "Zombies:1/Bus:14/Ambush Round:6/Always:1" "zombie_devgui ambush_round always"\n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Bus:14/Ambush Round:6/Never:2" "zombie_devgui ambush_round never"\n" ); +#/ +} + +initambusheffects() +{ + level._effect[ "ambush_bus_fire" ] = loadfx( "env/fire/fx_fire_md" ); +} + +shouldstartambushround() +{ +/# + if ( level.ambushpercentageperstop == 100 ) + { + return 1; + } + if ( getDvarInt( "zombie_cheat" ) == 2 ) + { + return 0; +#/ + } + if ( level.numbusstopssincelastambushround < 2 ) + { + } + randint = randomintrange( 0, 100 ); + percentchance = level.numbusstopssincelastambushround * level.ambushpercentageperstop; + if ( randint < percentchance ) + { + } + percentchance = level.numroundssincelastambushround * level.ambushpercentageperround; + if ( randint < percentchance ) + { + } + if ( maps/mp/zm_transit_bus::busgasempty() ) + { + return 1; + } + return 0; +} + +isambushroundactive() +{ + if ( flag_exists( "ambush_round" ) ) + { + return flag( "ambush_round" ); + } +} + +is_ambush_round_spawning_active() +{ + if ( flag_exists( "ambush_safe_area_active" ) ) + { + return flag( "ambush_safe_area_active" ); + } +} + +ambushstartround() +{ + flag_set( "ambush_round" ); + ambushroundthink(); +} + +ambushendround() +{ + level.the_bus.issafe = 1; + maps/mp/zm_transit_bus::busgasadd( 60 ); + level.numbusstopssincelastambushround = 0; + level.numroundssincelastambushround = 0; + flag_clear( "ambush_round" ); +} + +cancelambushround() +{ + flag_clear( "ambush_round" ); + flag_clear( "ambush_safe_area_active" ); + maps/mp/zm_transit_utility::try_resume_zombie_spawning(); + bbprint( "zombie_events", "category %s type %s round %d", "DOG", "stop", level.round_number ); + level.the_bus notify( "ambush_round_fail_safe" ); +} + +ambushroundspawning() +{ + level.numambushrounds++; + wait 6; + level.the_bus.issafe = 0; +} + +limitedambushspawn() +{ + if ( level.numambushrounds < 3 ) + { + dogcount = level.dog_targets.size * 6; + } + else + { + dogcount = level.dog_targets.size * 8; + } + setupdogspawnlocs(); + level thread ambushroundspawnfailsafe( 20 ); + while ( get_current_zombie_count() > 0 ) + { + wait 1; + } + level notify( "end_ambushWaitFunction" ); +} + +ambushroundthink() +{ + module = maps/mp/zombies/_zm_game_module::get_game_module( level.game_module_nml_index ); + if ( isDefined( module.hub_start_func ) ) + { + level thread [[ module.hub_start_func ]]( "nml" ); + level notify( "game_mode_started" ); + } + level thread ambushroundspawning(); + ambushwaitfunction(); + ambushendround(); +} + +ambushwaitfunction() +{ +} + +ambushpointfailsafe() +{ + level.the_bus endon( "ambush_point" ); + level.the_bus waittill( "reached_stop_point" ); + cancelambushround(); +} + +ambushroundspawnfailsafe( timer ) +{ + ambushroundtimelimit = timer; + currentambushtime = 0; + while ( currentambushtime < ambushroundtimelimit ) + { + if ( !flag( "ambush_round" ) ) + { + return; + } + wait 1; + currentambushtime++; + } + level notify( "end_ambushWaitFunction" ); + wait 5; + dogs = getaispeciesarray( "all", "zombie_dog" ); + i = 0; + while ( i < dogs.size ) + { + if ( isDefined( dogs[ i ].marked_for_death ) && dogs[ i ].marked_for_death ) + { + i++; + continue; + } + else + { + if ( is_magic_bullet_shield_enabled( dogs[ i ] ) ) + { + i++; + continue; + } + else + { + dogs[ i ] dodamage( dogs[ i ].health + 666, dogs[ i ].origin ); + } + } + i++; + } +} + +ambushdoghealthincrease() +{ + switch( level.numambushrounds ) + { + case 1: + level.dog_health = 400; + break; + case 2: + level.dog_health = 900; + break; + case 3: + level.dog_health = 1300; + break; + case 4: + level.dog_health = 1600; + break; + default: + level.dog_health = 1600; + break; + } +} + +ambushroundaftermath() +{ + power_up_origin = level.the_bus gettagorigin( "tag_body" ); + if ( isDefined( power_up_origin ) ) + { + level thread maps/mp/zombies/_zm_powerups::specific_powerup_drop( "full_ammo", power_up_origin ); + } +} + +ambushroundeffects() +{ + wait 2; + level thread ambushlightningeffect( "tag_body" ); + wait 0,5; + level thread ambushlightningeffect( "tag_wheel_back_left" ); + wait 0,5; + level thread ambushlightningeffect( "tag_wheel_back_right" ); + wait 0,5; + level thread ambushlightningeffect( "tag_wheel_front_left" ); + wait 0,5; + level thread ambushlightningeffect( "tag_wheel_front_right" ); + wait 1,5; + fxent0 = spawnandlinkfxtotag( level._effect[ "ambush_bus_fire" ], level.the_bus, "tag_body" ); + fxent1 = spawnandlinkfxtotag( level._effect[ "ambush_bus_fire" ], level.the_bus, "tag_wheel_back_left" ); + fxent2 = spawnandlinkfxtotag( level._effect[ "ambush_bus_fire" ], level.the_bus, "tag_wheel_back_right" ); + fxent3 = spawnandlinkfxtotag( level._effect[ "ambush_bus_fire" ], level.the_bus, "tag_wheel_front_left" ); + fxent4 = spawnandlinkfxtotag( level._effect[ "ambush_bus_fire" ], level.the_bus, "tag_wheel_front_right" ); + level waittill( "end_ambushWaitFunction" ); + fxent0 delete(); + fxent1 delete(); + fxent2 delete(); + fxent3 delete(); + fxent4 delete(); +} + +ambushlightningeffect( tag ) +{ + fxentlighting = spawnandlinkfxtotag( level._effect[ "lightning_dog_spawn" ], level.the_bus, tag ); + wait 5; + fxentlighting delete(); +} + +setupdogspawnlocs() +{ + level.enemy_dog_locations = []; + currentzone = undefined; + ambush_zones = getentarray( "ambush_volume", "script_noteworthy" ); + i = 0; + while ( i < ambush_zones.size ) + { + touching = 0; + b = 0; + while ( b < level.the_bus.bounds_origins.size && !touching ) + { + bounds = level.the_bus.bounds_origins[ b ]; + touching = bounds istouching( ambush_zones[ i ] ); + b++; + } + if ( touching ) + { + currentzone = ambush_zones[ i ]; + break; + } + else + { + i++; + } + } +/# + assert( isDefined( currentzone ), "Bus needs to be in an ambush zone for an ambush round: " + level.the_bus.origin ); +#/ + level.enemy_dog_locations = getstructarray( currentzone.target, "targetname" ); +} + +ambushroundkeeper() +{ + while ( 1 ) + { + level waittill( "between_round_over" ); + level.numroundssincelastambushround++; + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_automaton.gsc b/zm_transit_patch/maps/mp/zm_transit_automaton.gsc new file mode 100644 index 0000000..7629827 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_automaton.gsc @@ -0,0 +1,654 @@ +#include maps/mp/zm_transit_bus; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zm_transit_automaton" ); + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +initaudioaliases() +{ + level.vox zmbvoxadd( "automaton", "scripted", "discover_bus", "near_station1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "leaving_warning", "warning_out", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "leaving", "warning_leaving", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "emp_disable", "stop_generic", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "out_of_gas", "gas_out", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "refueled_gas", "gas_full", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "doors_open", "doors_open", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "doors_close", "doors_close", undefined ); + level.vox zmbvoxadd( "automaton", "convo", "player_enter", "player_enter", undefined ); + level.vox zmbvoxadd( "automaton", "convo", "player_leave", "player_exit", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "zombie_on_board", "zombie_enter", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "zombie_at_window", "zombie_attack", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "zombie_on_roof", "zombie_roof", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "player_attack_1", "player_1attack", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "player_attack_2", "player_2attack", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "player_attack_3", "player_3attack", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "hint_upgrade", "hint_upgrade", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "ride_generic", "ride_generic", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_station1", "near_station2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_station2", "near_station2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_station3", "near_station3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_station4", "near_station4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_station5", "near_station5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_diner1", "near_diner1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_diner2", "near_diner2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_diner3", "near_diner3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_diner4", "near_diner4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_diner5", "near_diner5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_tunnel1", "near_tunnel1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_tunnel2", "near_tunnel2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_tunnel3", "near_tunnel3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_tunnel4", "near_tunnel4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_tunnel5", "near_tunnel5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest1_1", "near_1forest1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest1_2", "near_1forest2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest1_3", "near_1forest3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest1_4", "near_1forest4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest1_5", "near_1forest5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest2_1", "near_2forest1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest2_2", "near_2forest2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest2_3", "near_2forest3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest2_4", "near_2forest4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_forest2_5", "near_2forest5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_farm1", "near_farm1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_farm2", "near_farm2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_farm3", "near_farm3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_farm4", "near_farm4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_farm5", "near_farm5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_corn1", "near_corn1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_corn2", "near_corn2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_corn3", "near_corn3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_corn4", "near_corn4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_corn5", "near_corn5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_power1", "near_power1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_power2", "near_power2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_power3", "near_power3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_power4", "near_power4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_power5", "near_power5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_town1", "near_town1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_town2", "near_town2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_town3", "near_town3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_town4", "near_town4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_town5", "near_town5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_bridge1", "near_bridge1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_bridge2", "near_bridge2", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_bridge3", "near_bridge3", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_bridge4", "near_bridge4", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "near_bridge5", "near_bridge5", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "leave_tunnel", "exit_tunnel1", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "bridge_collapse", "bridge_collapse", undefined ); + level.vox zmbvoxadd( "automaton", "inform", "player_pissed", "player_pissed", undefined ); +} + +main() +{ + level.automaton = getent( "bus_driver_head", "targetname" ); + level.automaton thread automatonsetup(); + level.timesplayerattackingautomaton = 0; + level.automaton.greeting_timer = 0; +} + +automatonsetup() +{ + self linkto( level.the_bus ); + self setmovingplatformenabled( 1 ); + self useanimtree( -1 ); + self setanim( %ai_zombie_bus_driver_idle ); + self addasspeakernpc( 1 ); + level.vox zmbvoxinitspeaker( "automaton", "vox_bus_", self ); + self thread automatondamagecallback(); + self thread automatonanimationsspeaking(); + self thread automatonemp(); + level thread bus_upgrade_vox(); +} + +automatondamagecallback() +{ + self setcandamage( 1 ); + self.health = 100000; + triggers = getentarray( "bus_door_trigger", "targetname" ); + while ( 1 ) + { + self waittill( "damage", amount, attacker, directionvec, point, type ); + self.health = 100000; + wait 1; + while ( isDefined( self.disabled_by_emp ) && !self.disabled_by_emp && isDefined( self.isspeaking ) || self.isspeaking && isDefined( level.playerattackingautomaton ) && level.playerattackingautomaton ) + { + continue; + } + self say_player_attack_vox(); + while ( level.timesplayerattackingautomaton < 3 ) + { + continue; + } + level.timesplayerattackingautomaton = 0; + if ( isDefined( attacker ) && isplayer( attacker ) ) + { + wait 5; + if ( !isDefined( self.dmgfxorigin ) ) + { + self.dmgfxorigin = spawn( "script_model", point ); + self.dmgfxorigin setmodel( "tag_origin" ); + if ( isDefined( type ) && type == "MOD_GRENADE_SPLASH" ) + { + self.dmgfxorigin.origin = self gettagorigin( "tag_origin" ) + vectorScale( ( 0, 0, 1 ), 40 ); + } + self.dmgfxorigin linkto( self, "J_neck" ); + } + wait 0,5; + playfxontag( level._effect[ "switch_sparks" ], self.dmgfxorigin, "tag_origin" ); + _a204 = triggers; + _k204 = getFirstArrayKey( _a204 ); + while ( isDefined( _k204 ) ) + { + trigger = _a204[ _k204 ]; + trigger setinvisibletoall(); + _k204 = getNextArrayKey( _a204, _k204 ); + } + level.the_bus.force_lock_doors = 1; + if ( randomint( 100 ) > 50 ) + { + if ( isDefined( level.the_bus.skip_next_destination ) && !level.the_bus.skip_next_destination ) + { + level thread bus_skip_destination(); + } + level thread automatonspeak( "inform", "player_pissed", undefined, 0 ); + } + else + { + level thread automatonspeak( "inform", "player_pissed", undefined, 1 ); + } + if ( level.the_bus.doorsclosed ) + { + triggers[ 0 ] playsound( "zmb_bus_door_open" ); + level.the_bus maps/mp/zm_transit_bus::busdoorsopen(); + wait 1,25; + shove_players_off_bus(); + wait 1,25; + triggers[ 0 ] playsound( "zmb_bus_door_close" ); + level.the_bus maps/mp/zm_transit_bus::busdoorsclose(); + } + else + { + shove_players_off_bus(); + wait 1,25; + triggers[ 0 ] playsound( "zmb_bus_door_close" ); + level.the_bus maps/mp/zm_transit_bus::busdoorsclose(); + } + wait 3,5; + level thread automatonspeak( "inform", "player_pissed", undefined, 2 ); + wait 28; + _a245 = triggers; + _k245 = getFirstArrayKey( _a245 ); + while ( isDefined( _k245 ) ) + { + trigger = _a245[ _k245 ]; + trigger setvisibletoall(); + _k245 = getNextArrayKey( _a245, _k245 ); + } + level.the_bus.force_lock_doors = 0; + } + if ( isDefined( self.dmgfxorigin ) ) + { + self.dmgfxorigin unlink(); + self.dmgfxorigin delete(); + self.dmgfxorigin = undefined; + } + } +} + +bus_skip_destination() +{ + level.the_bus.skip_next_destination = 1; + level.the_bus waittill( "skipping_destination" ); + level.the_bus.skip_next_destination = 0; +} + +automatonanimationsspeaking() +{ + self thread bus_driver_idle(); + while ( 1 ) + { + self waittill( "want_to_be_speaking", speakingline ); + self.isplayingspeakinganim = 1; + while ( isDefined( self.isplayingidleanim ) && self.isplayingidleanim ) + { + wait 0,05; + } + self notify( "startspeaking" ); + while ( isDefined( self.disabled_by_emp ) && self.disabled_by_emp ) + { + self.isplayingspeakinganim = 0; + } + speakinganim = %ai_zombie_bus_driver_idle_dialog; + speakingnum = 0; + if ( issubstr( speakingline, "attack" ) || issubstr( speakingline, "pissed" ) ) + { + speakinganim = %ai_zombie_bus_driver_idle_dialog_angry; + speakingnum = 1; + } + else + { + if ( issubstr( speakingline, "warning_out" ) || is_true( level.bus_driver_focused ) ) + { + speakinganim = %ai_zombie_bus_driver_idle_dialog_focused; + speakingnum = 2; + break; + } + else + { + if ( issubstr( speakingline, "zombie_enter" ) || isDefined( level.bus_zombie_danger ) && level.bus_zombie_danger ) + { + speakinganim = %ai_zombie_bus_driver_idle_dialog_panicked; + speakingnum = 3; + break; + } + else + { + if ( issubstr( speakingline, "stop_generic" ) || issubstr( speakingline, "warning_leaving" ) ) + { + speakinganim = %ai_zombie_bus_driver_idle_dialog_panicked; + speakingnum = 3; + break; + } + else + { + if ( issubstr( speakingline, "player_enter" ) ) + { + speakinganim = %ai_zombie_bus_driver_player_enter; + speakingnum = 4; + break; + } + else if ( issubstr( speakingline, "player_leave" ) ) + { + speakinganim = %ai_zombie_bus_driver_player_exit; + speakingnum = 5; + break; + } + else if ( issubstr( speakingline, "generic" ) ) + { + if ( randomint( 100 ) > 50 ) + { + speakinganim = %ai_zombie_bus_driver_forward_short_dialog; + speakingnum = 7; + } + else + { + speakinganim = %ai_zombie_bus_driver_turnback_short_dialog; + speakingnum = 6; + } + break; + } + else if ( issubstr( speakingline, "discover" ) ) + { + speakinganim = %ai_zombie_bus_driver_idle_dialog; + speakingnum = 0; + break; + } + else + { + if ( isDefined( level.stops ) && isDefined( level.stops[ "depot" ] ) && level.stops[ "depot" ] < 1 && issubstr( speakingline, "near_" ) ) + { + speakinganim = %ai_zombie_bus_driver_forward_short_dialog; + speakingnum = 7; + } + } + } + } + } + } + self setanim( speakinganim ); + self thread sndspeakinganimaudio( speakingnum ); +/# + if ( getDvar( #"96F6EBD9" ) != "" ) + { + iprintlnbold( "" + speakinganim ); +#/ + } + wait getanimlength( speakinganim ); + self.isplayingspeakinganim = 0; + } +} + +bus_driver_idle() +{ + danger_anims = []; + danger_anims[ 0 ] = %ai_zombie_bus_driver_idle_twitch_a; + danger_anims[ 1 ] = %ai_zombie_bus_driver_idle_twitch_focused; + danger_anims[ 2 ] = %ai_zombie_bus_driver_idle_twitch_panicked; + danger_anims[ 3 ] = %ai_zombie_bus_driver_idle_twitch_b; + focused_anims = []; + focused_anims[ 0 ] = %ai_zombie_bus_driver_idle_twitch_panicked; + focused_anims[ 1 ] = %ai_zombie_bus_driver_idle_twitch_focused; + twitch_anims = []; + twitch_anims[ 0 ] = %ai_zombie_bus_driver_idle_twitch_a; + twitch_anims[ 1 ] = %ai_zombie_bus_driver_idle_twitch_b; + idle_anims = []; + idle_anims[ 0 ] = %ai_zombie_bus_driver_idle_a; + idle_anims[ 1 ] = %ai_zombie_bus_driver_idle_b; + idle_anims[ 2 ] = %ai_zombie_bus_driver_idle_c; + idle_anims[ 3 ] = %ai_zombie_bus_driver_idle_d; + idle_anims[ 4 ] = %ai_zombie_bus_driver_idle; + while ( 1 ) + { + while ( isDefined( self.isplayingspeakinganim ) || self.isplayingspeakinganim && isDefined( self.disabled_by_emp ) && self.disabled_by_emp ) + { + wait 0,05; + } + if ( isDefined( level.bus_zombie_danger ) && level.bus_zombie_danger ) + { + driveranim = random( danger_anims ); + } + else + { + if ( is_true( level.bus_driver_focused ) ) + { + driveranim = random( focused_anims ); + break; + } + else if ( randomint( 100 ) > 90 ) + { + driveranim = random( twitch_anims ); + break; + } + else + { + driveranim = random( idle_anims ); + } + } + if ( isDefined( self.previous_anim ) && self.previous_anim == driveranim && driveranim != %ai_zombie_bus_driver_idle ) + { + driveranim = %ai_zombie_bus_driver_idle; + } +/# + if ( getDvar( #"6DF184E8" ) != "" ) + { + iprintlnbold( "Idle:" + driveranim ); +#/ + } + self.isplayingidleanim = 1; + self setanim( driveranim ); + self thread sndplaydriveranimsnd( driveranim ); + wait getanimlength( driveranim ); + self.previous_anim = driveranim; + self.isplayingidleanim = 0; + } +} + +automatonemp() +{ + while ( 1 ) + { + if ( isDefined( level.the_bus.disabled_by_emp ) && !level.the_bus.disabled_by_emp ) + { + level.the_bus waittill( "pre_power_off" ); + } + level.automaton.disabled_by_emp = 1; + level.automaton setanim( %ai_zombie_bus_driver_emp_powerdown ); + self thread sndplaydriveranimsnd( %ai_zombie_bus_driver_emp_powerdown ); + level.automaton maps/mp/zombies/_zm_audio::create_and_play_dialog( "inform", "emp_disable" ); + wait getanimlength( %ai_zombie_bus_driver_emp_powerdown ); + level.automaton setanim( %ai_zombie_bus_driver_emp_powerdown_idle ); + if ( isDefined( level.the_bus.pre_disabled_by_emp ) || level.the_bus.pre_disabled_by_emp && isDefined( level.the_bus.disabled_by_emp ) && level.the_bus.disabled_by_emp ) + { + level.the_bus waittill( "power_on" ); + } + level.automaton setanim( %ai_zombie_bus_driver_emp_powerup ); + self thread sndplaydriveranimsnd( %ai_zombie_bus_driver_emp_powerup ); + wait getanimlength( %ai_zombie_bus_driver_emp_powerup ); + level.automaton.disabled_by_emp = 0; + self setanim( %ai_zombie_bus_driver_idle ); + } +} + +say_player_attack_vox() +{ + if ( isDefined( level.the_bus.force_lock_doors ) && level.the_bus.force_lock_doors ) + { + level.timesplayerattackingautomaton = 0; + return; + } + else + { + if ( isDefined( level.playerattackingautomaton ) && level.playerattackingautomaton ) + { + return; + } + } + level.playerattackingautomaton = 1; + if ( level.timesplayerattackingautomaton == 0 ) + { + level thread automaton_attack_reset_timer(); + } + level.timesplayerattackingautomaton++; + level thread automatonspeak( "inform", "player_attack_" + level.timesplayerattackingautomaton ); + if ( level.timesplayerattackingautomaton >= 3 ) + { + level notify( "automaton_threshold_reached" ); + } + level thread automaton_attack_choke_timer(); +} + +automaton_attack_choke_timer() +{ + wait 10; + level.playerattackingautomaton = 0; +} + +automaton_attack_reset_timer() +{ + level endon( "automaton_threshold_reached" ); + wait 60; + level.timesplayerattackingautomaton = 0; +} + +bus_upgrade_vox() +{ + ladder_trig = getent( "bus_ladder_trigger", "targetname" ); + plow_trig = getent( "trigger_plow", "targetname" ); + hatch_trig = getent( "bus_hatch_bottom_trigger", "targetname" ); + while ( 1 ) + { + while ( isDefined( level.stops ) && isDefined( level.stops[ "depot" ] ) && level.stops[ "depot" ] < 1 ) + { + wait 1; + } + should_say_upgrade = -1; + players = get_players(); + _a534 = players; + _k534 = getFirstArrayKey( _a534 ); + while ( isDefined( _k534 ) ) + { + player = _a534[ _k534 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + if ( distancesquared( player.origin, hatch_trig.origin ) < 5184 && !flag( "hatch_attached" ) ) + { + should_say_upgrade = 2; + } + } + else + { + if ( distancesquared( player.origin, plow_trig.origin ) < 9216 && !flag( "catcher_attached" ) ) + { + should_say_upgrade = 1; + break; + } + else + { + if ( distancesquared( player.origin, ladder_trig.origin ) < 9216 && !flag( "ladder_attached" ) ) + { + should_say_upgrade = 0; + } + } + } + _k534 = getNextArrayKey( _a534, _k534 ); + } + if ( should_say_upgrade > -1 ) + { + level thread automatonspeak( "inform", "hint_upgrade", undefined, should_say_upgrade ); + wait 60; + } + wait 1; + } +} + +shove_players_off_bus() +{ + playfxontag( level._effect[ "turbine_on" ], level.automaton, "J_neck" ); + wait 0,25; + level.automaton playsound( "zmb_powerup_grabbed" ); + players = get_players(); + _a572 = players; + _k572 = getFirstArrayKey( _a572 ); + while ( isDefined( _k572 ) ) + { + player = _a572[ _k572 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + dir = anglesToRight( level.the_bus.angles ); + dir = vectornormalize( dir ); + player_velocity = dir * 900; + player setvelocity( player_velocity ); + earthquake( 0,25, 1, player.origin, 256, player ); + } + _k572 = getNextArrayKey( _a572, _k572 ); + } +} + +sndspeakinganimaudio( num ) +{ + switch( num ) + { + case 0: + wait 0,4; + self playsound( "evt_zmb_robot_jerk" ); + wait 2,4; + self playsound( "evt_zmb_robot_jerk" ); + wait 2,25; + self playsound( "evt_zmb_robot_jerk" ); + wait 1,1; + self playsound( "evt_zmb_robot_jerk" ); + break; + case 1: + wait 0,31; + self playsound( "evt_zmb_robot_jerk" ); + wait 3,55; + self playsound( "evt_zmb_robot_jerk" ); + break; + case 2: + wait 0,18; + self playsound( "evt_zmb_robot_jerk" ); + wait 4,83; + self playsound( "evt_zmb_robot_jerk" ); + break; + case 3: + wait 0,23; + self playsound( "evt_zmb_robot_jerk" ); + wait 0,77; + self playsound( "evt_zmb_robot_jerk" ); + wait 1,4; + self playsound( "evt_zmb_robot_jerk" ); + wait 0,15; + self playsound( "evt_zmb_robot_spin" ); + wait 0,53; + self playsound( "evt_zmb_robot_hat" ); + break; + case 4: + wait 0,3; + self playsound( "evt_zmb_robot_jerk" ); + wait 3,64; + self playsound( "evt_zmb_robot_jerk" ); + break; + case 5: + wait 0,38; + self playsound( "evt_zmb_robot_jerk" ); + wait 3,4; + self playsound( "evt_zmb_robot_jerk" ); + break; + case 6: + wait 0,3; + self playsound( "evt_zmb_robot_jerk" ); + break; + case 7: + } + } +} + +sndplaydriveranimsnd( the_anim ) +{ + if ( the_anim == %ai_zombie_bus_driver_idle_twitch_a ) + { + wait 0,55; + self playsound( "evt_zmb_robot_jerk" ); + wait 1,2; + self playsound( "evt_zmb_robot_hat" ); + wait 0,79; + self playsound( "evt_zmb_robot_spin" ); + wait 1,1; + self playsound( "evt_zmb_robot_hat" ); + self playsound( "evt_zmb_robot_spin" ); + } + else if ( the_anim == %ai_zombie_bus_driver_idle_twitch_focused ) + { + wait 0,25; + self playsound( "evt_zmb_robot_jerk" ); + wait 4,8; + self playsound( "evt_zmb_robot_jerk" ); + } + else if ( the_anim == %ai_zombie_bus_driver_idle_twitch_panicked ) + { + wait 0,31; + self playsound( "evt_zmb_robot_jerk" ); + wait 0,79; + self playsound( "evt_zmb_robot_jerk" ); + wait 1,3; + self playsound( "evt_zmb_robot_jerk" ); + wait 0,18; + self playsound( "evt_zmb_robot_spin" ); + wait 0,52; + self playsound( "evt_zmb_robot_hat" ); + } + else if ( the_anim == %ai_zombie_bus_driver_idle_twitch_b ) + { + wait 0,22; + self playsound( "evt_zmb_robot_hat" ); + wait 1,06; + self playsound( "evt_zmb_robot_spin" ); + wait 1,05; + self playsound( "evt_zmb_robot_hat" ); + wait 1,07; + self playsound( "evt_zmb_robot_spin" ); + wait 0,59; + self playsound( "evt_zmb_robot_hat" ); + } + else if ( the_anim == %ai_zombie_bus_driver_idle_d ) + { + wait 0,24; + self playsound( "evt_zmb_robot_spin" ); + wait 1,04; + self playsound( "evt_zmb_robot_hat" ); + } + else if ( the_anim == %ai_zombie_bus_driver_emp_powerdown ) + { + wait 0,1; + self playsound( "evt_zmb_robot_jerk" ); + wait 0,9; + self playsound( "evt_zmb_robot_jerk" ); + } + else + { + if ( the_anim == %ai_zombie_bus_driver_emp_powerup ) + { + wait 0,63; + self playsound( "evt_zmb_robot_jerk" ); + } + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_buildables.gsc b/zm_transit_patch/maps/mp/zm_transit_buildables.gsc new file mode 100644 index 0000000..ae30dcd --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_buildables.gsc @@ -0,0 +1,442 @@ +#include maps/mp/zm_transit_sq; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init_buildables() +{ + level.buildable_piece_count = 27; + add_zombie_buildable( "riotshield_zm", &"ZOMBIE_BUILD_RIOT", &"ZOMBIE_BUILDING_RIOT", &"ZOMBIE_BOUGHT_RIOT" ); + add_zombie_buildable( "jetgun_zm", &"ZOMBIE_BUILD_JETGUN", &"ZOMBIE_BUILDING_JETGUN", &"ZOMBIE_BOUGHT_JETGUN" ); + add_zombie_buildable( "turret", &"ZOMBIE_BUILD_TURRET", &"ZOMBIE_BUILDING_TURRET", &"ZOMBIE_BOUGHT_TURRET" ); + add_zombie_buildable( "electric_trap", &"ZOMBIE_BUILD_ELECTRIC_TRAP", &"ZOMBIE_BUILDING_ELECTRIC_TRAP", &"ZOMBIE_BOUGHT_ELECTRIC_TRAP" ); + add_zombie_buildable( "cattlecatcher", &"ZOMBIE_BUILD_CATTLE_CATCHER", &"ZOMBIE_BUILDING_CATTLE_CATCHER" ); + add_zombie_buildable( "bushatch", &"ZOMBIE_BUILD_BUSHATCH", &"ZOMBIE_BUILDING_BUSHATCH" ); + add_zombie_buildable( "dinerhatch", &"ZOMBIE_BUILD_DINERHATCH", &"ZOMBIE_BUILDING_DINERHATCH" ); + add_zombie_buildable( "busladder", &"ZOMBIE_BUILD_BUSLADDER", &"ZOMBIE_BUILDING_BUSLADDER" ); + add_zombie_buildable( "powerswitch", &"ZOMBIE_BUILD_POWER_SWITCH", &"ZOMBIE_BUILDING_POWER_SWITCH" ); + add_zombie_buildable( "pap", &"ZOMBIE_BUILD_PAP", &"ZOMBIE_BUILDING_PAP" ); + add_zombie_buildable( "turbine", &"ZOMBIE_BUILD_TURBINE", &"ZOMBIE_BUILDING_TURBINE", &"ZOMBIE_BOUGHT_TURBINE" ); + add_zombie_buildable( "sq_common", &"ZOMBIE_BUILD_SQ_COMMON", &"ZOMBIE_BUILDING_SQ_COMMON" ); +} + +include_buildables() +{ + battery = generate_zombie_buildable_piece( "pap", "p6_zm_buildable_battery", 32, 64, 0, "zm_hud_icon_battery", ::onpickup_common, ::ondrop_common, undefined, "tag_part_03", undefined, 1 ); + riotshield_dolly = generate_zombie_buildable_piece( "riotshield_zm", "t6_wpn_zmb_shield_dolly", 32, 64, 0, "zm_hud_icon_dolly", ::onpickup_common, ::ondrop_common, undefined, "TAG_RIOT_SHIELD_DOLLY", undefined, 2 ); + riotshield_door = generate_zombie_buildable_piece( "riotshield_zm", "t6_wpn_zmb_shield_door", 48, 15, 25, "zm_hud_icon_cardoor", ::onpickup_common, ::ondrop_common, undefined, "TAG_RIOT_SHIELD_DOOR", undefined, 3 ); + riotshield = spawnstruct(); + riotshield.name = "riotshield_zm"; + riotshield add_buildable_piece( riotshield_dolly ); + riotshield add_buildable_piece( riotshield_door ); + riotshield.onbuyweapon = ::onbuyweapon_riotshield; + riotshield.triggerthink = ::riotshieldbuildable; + include_buildable( riotshield ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "riotshield_zm_buildable_trigger" ); + powerswitch_arm = generate_zombie_buildable_piece( "powerswitch", "p6_zm_buildable_pswitch_hand", 32, 64, 10, "zm_hud_icon_arm", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 4 ); + powerswitch_lever = generate_zombie_buildable_piece( "powerswitch", "p6_zm_buildable_pswitch_body", 48, 64, 0, "zm_hud_icon_panel", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 5 ); + powerswitch_box = generate_zombie_buildable_piece( "powerswitch", "p6_zm_buildable_pswitch_lever", 32, 15, 0, "zm_hud_icon_lever", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 6 ); + powerswitch = spawnstruct(); + powerswitch.name = "powerswitch"; + powerswitch add_buildable_piece( powerswitch_arm ); + powerswitch add_buildable_piece( powerswitch_lever ); + powerswitch add_buildable_piece( powerswitch_box ); + powerswitch.onuseplantobject = ::onuseplantobject_powerswitch; + powerswitch.triggerthink = ::powerswitchbuildable; + include_buildable( powerswitch ); + packapunch_machine = generate_zombie_buildable_piece( "pap", "p6_zm_buildable_pap_body", 48, 64, 0, "zm_hud_icon_papbody", ::onpickup_common, ::ondrop_common, undefined, "tag_part_02", undefined, 7 ); + packapunch_legs = generate_zombie_buildable_piece( "pap", "p6_zm_buildable_pap_table", 48, 15, 0, "zm_hud_icon_chairleg", ::onpickup_common, ::ondrop_common, undefined, "tag_part_01", undefined, 8 ); + packapunch = spawnstruct(); + packapunch.name = "pap"; + packapunch add_buildable_piece( battery, "tag_part_03", 0 ); + packapunch add_buildable_piece( packapunch_machine ); + packapunch add_buildable_piece( packapunch_legs ); + packapunch.triggerthink = ::papbuildable; + include_buildable( packapunch ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "pap_buildable_trigger" ); + turbine_fan = generate_zombie_buildable_piece( "turbine", "p6_zm_buildable_turbine_fan", 32, 64, 0, "zm_hud_icon_fan", ::onpickup_common, ::ondrop_common, undefined, "tag_part_03", undefined, 9 ); + turbine_panel = generate_zombie_buildable_piece( "turbine", "p6_zm_buildable_turbine_rudder", 32, 64, 0, "zm_hud_icon_rudder", ::onpickup_common, ::ondrop_common, undefined, "tag_part_04", undefined, 10 ); + turbine_body = generate_zombie_buildable_piece( "turbine", "p6_zm_buildable_turbine_mannequin", 32, 15, 0, "zm_hud_icon_mannequin", ::onpickup_common, ::ondrop_common, undefined, "tag_part_01", undefined, 11 ); + turbine = spawnstruct(); + turbine.name = "turbine"; + turbine add_buildable_piece( turbine_fan ); + turbine add_buildable_piece( turbine_panel ); + turbine add_buildable_piece( turbine_body ); + turbine.onuseplantobject = ::onuseplantobject_turbine; + turbine.triggerthink = ::turbinebuildable; + include_buildable( turbine ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "turbine_buildable_trigger" ); + turret_barrel = generate_zombie_buildable_piece( "turret", "t6_wpn_lmg_rpd_world", 32, 64, 10, "zm_hud_icon_turrethead", ::onpickup_common, ::ondrop_common, undefined, "tag_aim", undefined, 12 ); + turret_body = generate_zombie_buildable_piece( "turret", "p6_zm_buildable_turret_mower", 48, 64, 0, "zm_hud_icon_lawnmower", ::onpickup_common, ::ondrop_common, undefined, "tag_part_01", undefined, 13 ); + turret_ammo = generate_zombie_buildable_piece( "turret", "p6_zm_buildable_turret_ammo", 32, 15, 0, "zm_hud_icon_ammobox", ::onpickup_common, ::ondrop_common, undefined, "tag_part_02", undefined, 14 ); + turret = spawnstruct(); + turret.name = "turret"; + turret add_buildable_piece( turret_barrel ); + turret add_buildable_piece( turret_body ); + turret add_buildable_piece( turret_ammo ); + turret.triggerthink = ::turretbuildable; + include_buildable( turret ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "turret_buildable_trigger" ); + electric_trap_spool = generate_zombie_buildable_piece( "electric_trap", "p6_zm_buildable_etrap_base", 32, 64, 0, "zm_hud_icon_coil", ::onpickup_common, ::ondrop_common, undefined, "tag_part_02", undefined, 15 ); + electric_trap_coil = generate_zombie_buildable_piece( "electric_trap", "p6_zm_buildable_etrap_tvtube", 32, 64, 10, "zm_hud_icon_tvtube", ::onpickup_common, ::ondrop_common, undefined, "tag_part_01", undefined, 16 ); + electric_trap = spawnstruct(); + electric_trap.name = "electric_trap"; + electric_trap add_buildable_piece( electric_trap_spool ); + electric_trap add_buildable_piece( electric_trap_coil ); + electric_trap add_buildable_piece( battery, "tag_part_03", 0 ); + electric_trap.triggerthink = ::electrictrapbuildable; + include_buildable( electric_trap ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "electric_trap_buildable_trigger" ); + jetgun_wires = generate_zombie_buildable_piece( "jetgun_zm", "p6_zm_buildable_jetgun_wires", 32, 64, 0, "zm_hud_icon_jetgun_wires", ::onpickup_common, ::ondrop_common, undefined, "TAG_WIRES", undefined, 17 ); + jetgun_engine = generate_zombie_buildable_piece( "jetgun_zm", "p6_zm_buildable_jetgun_engine", 48, 64, 0, "zm_hud_icon_jetgun_engine", ::onpickup_common, ::ondrop_common, undefined, "TAG_ENGINE", undefined, 18 ); + jetgun_gauges = generate_zombie_buildable_piece( "jetgun_zm", "p6_zm_buildable_jetgun_guages", 32, 15, 0, "zm_hud_icon_jetgun_gauges", ::onpickup_common, ::ondrop_common, undefined, "TAG_DIALS", undefined, 19 ); + jetgun_handle = generate_zombie_buildable_piece( "jetgun_zm", "p6_zm_buildable_jetgun_handles", 32, 15, 0, "zm_hud_icon_jetgun_handles", ::onpickup_common, ::ondrop_common, undefined, "TAG_HANDLES", undefined, 20 ); + jetgun = spawnstruct(); + jetgun.name = "jetgun_zm"; + jetgun add_buildable_piece( jetgun_wires ); + jetgun add_buildable_piece( jetgun_engine ); + jetgun add_buildable_piece( jetgun_gauges ); + jetgun add_buildable_piece( jetgun_handle ); + jetgun.onbuyweapon = ::onbuyweapon_jetgun; + jetgun.triggerthink = ::jetgunbuildable; + include_buildable( jetgun ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "jetgun_zm_buildable_trigger" ); + cattlecatcher_plow = generate_zombie_buildable_piece( "cattlecatcher", "veh_t6_civ_bus_zombie_cow_catcher", 72, 100, 20, "zm_hud_icon_plow", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 21 ); + bushatch_hatch = generate_zombie_buildable_piece( "bushatch", "veh_t6_civ_bus_zombie_roof_hatch", 32, 64, 5, "zm_hud_icon_hatch", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 22 ); + busladder_ladder = generate_zombie_buildable_piece( "busladder", "com_stepladder_large_closed", 32, 64, 0, "zm_hud_icon_ladder", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 23 ); + cattlecatcher = spawnstruct(); + cattlecatcher.name = "cattlecatcher"; + cattlecatcher add_buildable_piece( cattlecatcher_plow ); + cattlecatcher.triggerthink = ::cattlecatcherbuildable; + include_buildable( cattlecatcher ); + bushatch = spawnstruct(); + bushatch.name = "bushatch"; + bushatch add_buildable_piece( bushatch_hatch, undefined, 1 ); + bushatch.triggerthink = ::bushatchbuildable; + include_buildable( bushatch ); + dinerhatch = spawnstruct(); + dinerhatch.name = "dinerhatch"; + dinerhatch add_buildable_piece( bushatch_hatch, undefined, 1 ); + dinerhatch.triggerthink = ::dinerhatchbuildable; + include_buildable( dinerhatch ); + busladder = spawnstruct(); + busladder.name = "busladder"; + busladder add_buildable_piece( busladder_ladder ); + busladder.triggerthink = ::busladderbuildable; + include_buildable( busladder ); + if ( !isDefined( level.gamedifficulty ) || level.gamedifficulty != 0 ) + { + sq_common_electricbox = generate_zombie_buildable_piece( "sq_common", "p6_zm_buildable_sq_electric_box", 32, 64, 0, "zm_hud_icon_sq_powerbox", ::onpickup_common, ::ondrop_common, undefined, "tag_part_02", undefined, 24 ); + sq_common_meteor = generate_zombie_buildable_piece( "sq_common", "p6_zm_buildable_sq_meteor", 76, 64, 0, "zm_hud_icon_sq_meteor", ::onpickup_common, ::ondrop_common, undefined, "tag_part_04", undefined, 25 ); + sq_common_scaffolding = generate_zombie_buildable_piece( "sq_common", "p6_zm_buildable_sq_scaffolding", 64, 96, 0, "zm_hud_icon_sq_scafold", ::onpickup_common, ::ondrop_common, undefined, "tag_part_01", undefined, 26 ); + sq_common_transceiver = generate_zombie_buildable_piece( "sq_common", "p6_zm_buildable_sq_transceiver", 64, 96, 0, "zm_hud_icon_sq_tranceiver", ::onpickup_common, ::ondrop_common, undefined, "tag_part_03", undefined, 27 ); + sqcommon = spawnstruct(); + sqcommon.name = "sq_common"; + sqcommon add_buildable_piece( sq_common_electricbox ); + sqcommon add_buildable_piece( sq_common_meteor ); + sqcommon add_buildable_piece( sq_common_scaffolding ); + sqcommon add_buildable_piece( sq_common_transceiver ); + sqcommon.triggerthink = ::sqcommonbuildable; + include_buildable( sqcommon ); + maps/mp/zombies/_zm_buildables::hide_buildable_table_model( "sq_common_buildable_trigger" ); + } +} + +sqcommonbuildable() +{ + level.sq_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "sq_common_buildable_trigger", "sq_common", "sq_common", "", 1, 0 ); +} + +busladderbuildable() +{ + blb = maps/mp/zombies/_zm_buildables::vehicle_buildable_trigger_think( level.the_bus, "bus_ladder_trigger", "busladder", "busladder", "", 0, 0 ); + blb.require_look_at = 0; + blb.custom_buildablestub_update_prompt = ::busisonormovingbuildableupdateprompt; +} + +busisonormovingbuildableupdateprompt( player, sethintstringnow, buildabletrigger ) +{ + if ( isDefined( player.isonbus ) || player.isonbus && level.the_bus getspeedmph() > 0 ) + { + if ( isDefined( self ) ) + { + self.hint_string = ""; + if ( isDefined( sethintstringnow ) && sethintstringnow && isDefined( buildabletrigger ) ) + { + buildabletrigger sethintstring( self.hint_string ); + } + } + return 0; + } + return 1; +} + +bushatchbuildable() +{ + bhb = maps/mp/zombies/_zm_buildables::vehicle_buildable_trigger_think( level.the_bus, "bus_hatch_bottom_trigger", "bushatch", "bushatch", "", 0, 0 ); + bhb.require_look_at = 0; +} + +dinerhatchbuildable() +{ + dhb = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "diner_hatch_trigger", "dinerhatch", "dinerhatch", "", 1, 0 ); + dhb.require_look_at = 0; +} + +cattlecatcherbuildable() +{ + ccb = maps/mp/zombies/_zm_buildables::vehicle_buildable_trigger_think( level.the_bus, "trigger_plow", "cattlecatcher", "cattlecatcher", "", 0, 0 ); + ccb.require_look_at = 0; + ccb.custom_buildablestub_update_prompt = ::busisonormovingbuildableupdateprompt; +} + +papbuildable() +{ + maps/mp/zombies/_zm_buildables::buildable_trigger_think( "pap_buildable_trigger", "pap", "pap", "", 1, 0 ); +} + +riotshieldbuildable() +{ + maps/mp/zombies/_zm_buildables::buildable_trigger_think( "riotshield_zm_buildable_trigger", "riotshield_zm", "riotshield_zm", &"ZOMBIE_GRAB_RIOTSHIELD", 1, 1 ); +} + +powerswitchbuildable() +{ + maps/mp/zombies/_zm_buildables::buildable_trigger_think( "powerswitch_buildable_trigger", "powerswitch", "powerswitch", "", 1, 0 ); +} + +turbinebuildable() +{ + level.turbine_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "turbine_buildable_trigger", "turbine", "equip_turbine_zm", &"ZOMBIE_GRAB_TURBINE_PICKUP_HINT_STRING", 1, 1 ); +} + +turretbuildable() +{ + maps/mp/zombies/_zm_buildables::buildable_trigger_think( "turret_buildable_trigger", "turret", "equip_turret_zm", &"ZOMBIE_GRAB_TURRET_PICKUP_HINT_STRING", 1, 1 ); +} + +electrictrapbuildable() +{ + maps/mp/zombies/_zm_buildables::buildable_trigger_think( "electric_trap_buildable_trigger", "electric_trap", "equip_electrictrap_zm", &"ZOMBIE_GRAB_ELECTRICTRAP", 1, 1 ); +} + +jetgunbuildable() +{ + level.jetgun_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "jetgun_zm_buildable_trigger", "jetgun_zm", "jetgun_zm", &"ZOMBIE_GRAB_JETGUN", 1, 1 ); +} + +ondrop_common( player ) +{ +/# + println( "ZM >> Common part callback onDrop()" ); +#/ + self droponbus( player ); + self.piece_owner = undefined; +} + +onpickup_common( player ) +{ +/# + println( "ZM >> Common part callback onPickup()" ); +#/ + player playsound( "zmb_buildable_pickup" ); + self pickupfrombus(); + self.piece_owner = player; + if ( isDefined( self.buildablename ) ) + { + if ( self.buildablename == "turbine" ) + { + check_for_buildable_turbine_vox( level.turbine_buildable, 0 ); + return; + } + else + { + if ( self.buildablename == "jetgun_zm" ) + { + check_for_buildable_jetgun_vox( level.jetgun_buildable, 0 ); + } + } + } +} + +onbuyweapon_riotshield( player ) +{ + if ( isDefined( player.player_shield_reset_health ) ) + { + player [[ player.player_shield_reset_health ]](); + } + if ( isDefined( player.player_shield_reset_location ) ) + { + player [[ player.player_shield_reset_location ]](); + } +} + +onuseplantobject_powerswitch( player ) +{ +/# + println( "ZM >> PowerSwitch Buildable CallBack onUsePlantObject()" ); +#/ + if ( !isDefined( player player_get_buildable_piece() ) ) + { + return; + } + switch( player player_get_buildable_piece().modelname ) + { + case "p6_zm_buildable_pswitch_hand": + getent( "powerswitch_p6_zm_buildable_pswitch_hand", "targetname" ) show(); + break; + case "p6_zm_buildable_pswitch_body": + panel = getent( "powerswitch_p6_zm_buildable_pswitch_body", "targetname" ); + panel show(); + break; + case "p6_zm_buildable_pswitch_lever": + getent( "powerswitch_p6_zm_buildable_pswitch_lever", "targetname" ) show(); + break; + } +} + +onuseplantobject_turbine( player ) +{ +/# + println( "ZM >> Turbine Buildable CallBack onUsePlantObject()" ); +#/ + buildable = self.buildablezone; + first_part = "tag_part_03"; + second_part = "tag_part_02"; + i = 0; + while ( i < buildable.pieces.size ) + { + if ( buildable.pieces[ i ].part_name == first_part ) + { + if ( isDefined( buildable.pieces[ i ].built ) || buildable.pieces[ i ].built && player player_get_buildable_piece().part_name == first_part ) + { + buildable.stub.model showpart( second_part ); + i++; + continue; + } + else + { + buildable.stub.model hidepart( second_part ); + } + } + i++; + } + check_for_buildable_turbine_vox( level.turbine_buildable, 1 ); +} + +check_for_buildable_turbine_vox( stub, start_build_counter ) +{ + if ( isDefined( level.maxis_turbine_vox_played ) && level.maxis_turbine_vox_played ) + { + return; + } + buildable = stub.buildablezone; + piece_counter = 0; + build_counter = start_build_counter; + i = 0; + while ( i < buildable.pieces.size ) + { + if ( isDefined( buildable.pieces[ i ].built ) || buildable.pieces[ i ].built && isDefined( buildable.pieces[ i ].piece_owner ) ) + { + piece_counter++; + } + if ( isDefined( buildable.pieces[ i ].built ) && buildable.pieces[ i ].built ) + { + build_counter++; + } + i++; + } + if ( build_counter >= 2 && piece_counter == 3 ) + { + if ( !flag( "power_on" ) ) + { + level.maxis_turbine_vox_played = 1; + level thread maps/mp/zm_transit_sq::maxissay( "vox_maxi_turbine_final_0", stub.origin ); + } + } +} + +onbuyweapon_jetgun( player ) +{ + player switchtoweapon( self.stub.weaponname ); +} + +check_for_buildable_jetgun_vox( stub, start_build_counter ) +{ + if ( isDefined( level.rich_jetgun_vox_played ) || level.rich_jetgun_vox_played && !flag( "power_on" ) ) + { + return; + } + buildable = stub.buildablezone; + piece_counter = 0; + build_counter = start_build_counter; + i = 0; + while ( i < buildable.pieces.size ) + { + if ( isDefined( buildable.pieces[ i ].built ) || buildable.pieces[ i ].built && isDefined( buildable.pieces[ i ].piece_owner ) ) + { + piece_counter++; + } + if ( isDefined( buildable.pieces[ i ].built ) && buildable.pieces[ i ].built ) + { + build_counter++; + } + i++; + } + if ( build_counter == 3 && piece_counter == 4 ) + { + level thread maps/mp/zm_transit_sq::richtofensay( "vox_zmba_sidequest_jet_last_0" ); + } + else + { + if ( build_counter == 4 ) + { + level thread maps/mp/zm_transit_sq::richtofensay( "vox_zmba_sidequest_jet_complete_0" ); + } + } +} + +onenduse_sidequestcommon( team, player, result ) +{ + if ( isDefined( result ) && result ) + { + if ( isDefined( level.sq_clip ) ) + { + level.sq_clip trigger_on(); + level.sq_clip connectpaths(); + } + } +} + +droponbus( player ) +{ + if ( isDefined( player ) && isDefined( player.isonbus ) && player.isonbus ) + { + self.model linkto( level.the_bus ); + self.linked_to_bus = 1; + self.unitrigger.link_parent = level.the_bus; + } + else + { + self.unitrigger.link_parent = undefined; + } +} + +pickupfrombus() +{ + if ( isDefined( self.linked_to_bus ) && self.linked_to_bus ) + { + if ( isDefined( self.model ) ) + { + self.model unlink(); + } + self.linked_to_bus = undefined; + } + if ( isDefined( self.unitrigger ) ) + { + self.unitrigger.link_parent = undefined; + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_bus.gsc b/zm_transit_patch/maps/mp/zm_transit_bus.gsc new file mode 100644 index 0000000..801a684 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_bus.gsc @@ -0,0 +1,3759 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zm_transit_lava; +#include maps/mp/zombies/_zm_weap_emp_bomb; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm; +#include maps/mp/zm_transit_ambush; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zm_transit_cling; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zombie_bus" ); +#using_animtree( "zombie_bus_props" ); + +bussetup() +{ + flag_init( "ladder_attached" ); + flag_init( "catcher_attached" ); + flag_init( "hatch_attached" ); + self.immediatespeed = 0; + self.currentspeed = 0; + self.targetspeed = 0; + self.ismoving = 0; + self.isstopping = 0; + self.gas = 100; + self.accel = 10; + self.decel = 30; + self.radius = 88; + self.height = 240; + self.frontdist = 340; + self.backdist = 55; + self.floor = 36; + self.frontlocal = ( self.frontdist - ( self.radius / 2 ), 0, 0 ); + self.backlocal = ( ( self.backdist * -1 ) + ( self.radius / 2 ), 0, 0 ); + self.drivepath = 0; + self.zone = "zone_pri"; + self.roadzone = self.zone; + self.zombiesinside = 0; + self.zombiesatwindow = 0; + self.zombiesonroof = 0; + self.numplayers = 0; + self.numplayerson = 0; + self.numplayersonroof = 0; + self.numplayersinsidebus = 0; + self.numplayersnear = 0; + self.numaliveplayersridingbus = 0; + self.numflattires = 0; + self.doorsclosed = 1; + self.doorsdisabledfortime = 0; + self.stalled = 0; + self.issafe = 1; + self.waittimeatdestination = 0; + self.gracetimeatdestination = 10; + self.path_blocking = 0; + self.chase_pos = self.origin; + self.chase_pos_time = 0; + self.istouchingignorewindowsvolume = 0; + level.zm_mantle_over_40_move_speed_override = ::zm_mantle_over_40_move_speed_override; + self setmovingplatformenabled( 1 ); + self.supportsanimscripted = 1; + self setvehmaxspeed( 25 ); + self useanimtree( -1 ); + level.callbackactordamage = ::transit_actor_damage_override_wrapper; + self maps/mp/zm_transit_automaton::main(); + maps/mp/zm_transit_cling::initializecling(); + self maps/mp/zm_transit_openings::main(); + self bus_upgrades(); + self thread busplowsetup(); + self buslightssetup(); + self busdoorssetup(); + self buspathblockersetup(); + self bussetupbounds(); + self bus_roof_watch(); + self bus_set_nodes(); + self bus_set_exit_triggers(); + self thread bus_audio_setup(); + level thread init_bus_door_anims(); + level thread init_bus_props_anims(); + self thread bususeanimtree(); + self thread bususedoor( 0 ); + self thread busidledoor(); + self thread play_lava_audio(); + self thread busthink(); + self thread busopeningscene(); + busschedule(); + self thread busschedulethink(); + self thread bus_bridge_speedcontrol(); + self.door_nodes_linked = 1; + self thread bussetdoornodes( 0 ); +} + +bus_upgrades() +{ + self.upgrades = []; + self.ladder_local_offset = ( 142, -50, 100 ); + self.upgrades[ "Plow" ] = spawnstruct(); + self.upgrades[ "Plow" ].installed = 0; +} + +bus_debug() +{ + while ( 1 ) + { + bus_forward = vectornormalize( anglesToForward( level.the_bus.angles ) ); + ret = level.the_bus.origin + vectorScale( bus_forward, -144 ); + groundpos = groundpos_ignore_water_new( ret + vectorScale( ( 0, 0, 1 ), 60 ) ); +/# + debugstar( groundpos, 1000, ( 0, 0, 1 ) ); +#/ + wait 0,5; + } +} + +bus_set_nodes() +{ + self.front_door_inside = getnode( "front_door_inside_node", "targetname" ); + self.front_door = getnode( "front_door_node", "targetname" ); + self.back_door_inside1 = getnode( "back_door_inside_node1", "targetname" ); + self.back_door_inside2 = getnode( "back_door_inside_node2", "targetname" ); + self.back_door = getnode( "back_door_node", "targetname" ); + self.exit_back_l = getnode( "exit_back_l_node", "targetname" ); + self.exit_back_r = getnode( "exit_back_r_node", "targetname" ); +} + +bus_set_exit_triggers() +{ + spawnflags = 9; + trigger_exit = []; + trigger_exit[ trigger_exit.size ] = spawn( "trigger_radius", self.front_door_inside.origin, spawnflags, 32, 72 ); + trigger_exit[ trigger_exit.size ] = spawn( "trigger_radius", self.exit_back_l.origin, spawnflags, 32, 72 ); + trigger_exit[ trigger_exit.size ] = spawn( "trigger_radius", self.exit_back_r.origin, spawnflags, 32, 72 ); + tags = []; + tags[ 0 ] = "window_right_front_jnt"; + tags[ 1 ] = "window_left_rear_jnt"; + tags[ 2 ] = "window_right_rear_jnt"; + i = 0; + while ( i < trigger_exit.size ) + { + trigger = trigger_exit[ i ]; + trigger enablelinkto(); + trigger linkto( self, "", self worldtolocalcoords( trigger.origin ), ( 0, 0, 1 ) ); + trigger setmovingplatformenabled( 1 ); + trigger setteamfortrigger( level.zombie_team ); + trigger.tag = tags[ i ]; + trigger.substate = i; + self thread maps/mp/zm_transit_openings::busexitthink( trigger ); + i++; + } +} + +onplayerconnect() +{ + getent( "the_bus", "targetname" ) setclientfield( "the_bus_spawned", 1 ); +} + +zm_mantle_over_40_move_speed_override() +{ + traversealias = "barrier_walk"; + switch( self.zombie_move_speed ) + { + case "chase_bus": + traversealias = "barrier_sprint"; + break; + default: +/# + assertmsg( "Zombie move speed of '" + self.zombie_move_speed + "' is not supported for mantle_over_40." ); +#/ + } + return traversealias; +} + +follow_path( node ) +{ + self endon( "death" ); +/# + assert( isDefined( node ), "vehicle_path() called without a path" ); +#/ + self notify( "newpath" ); + if ( isDefined( node ) ) + { + self.attachedpath = node; + } + pathstart = self.attachedpath; + self.currentnode = self.attachedpath; + if ( !isDefined( pathstart ) ) + { + return; + } + self attachpath( pathstart ); + self startpath(); + self endon( "newpath" ); + nextpoint = pathstart; + while ( isDefined( nextpoint ) ) + { + self waittill( "reached_node", nextpoint ); + self.currentnode = nextpoint; + nextpoint notify( "trigger" ); + if ( isDefined( nextpoint.script_noteworthy ) ) + { + self notify( nextpoint.script_noteworthy ); + self notify( "noteworthy" ); + } + if ( isDefined( nextpoint.script_string ) ) + { + if ( issubstr( nextpoint.script_string, "map_" ) ) + { + level thread do_player_bus_location_vox( nextpoint.script_string ); + break; + } + else + { + level thread do_automoton_vox( nextpoint.script_string ); + } + } + waittillframeend; + } +} + +busopeningscene() +{ + startnode = getvehiclenode( "BUS_OPENING", "targetname" ); + self.currentnode = startnode; + self thread follow_path( startnode ); + self.targetspeed = 0; + flag_wait( "start_zombie_round_logic" ); + self busstartmoving( 12 ); + self busstartwait(); + self waittill( "opening_end_path" ); + self busstopmoving(); + startnode = getvehiclenode( "BUS_START", "targetname" ); + self.currentnode = startnode; + self thread follow_path( startnode ); + while ( !flag( "OnPriDoorYar" ) && !flag( "OnPriDoorYar2" ) ) + { + wait 0,5; + } + level.automaton notify( "start_head_think" ); + self notify( "noteworthy" ); +} + +busschedule() +{ + level.busschedule = busschedulecreate(); + level.busschedule busscheduleadd( "depot", 0, randomintrange( 40, 180 ), 19, 15 ); + level.busschedule busscheduleadd( "tunnel", 1, 10, 27, 5 ); + level.busschedule busscheduleadd( "diner", 0, randomintrange( 40, 180 ), 18, 20 ); + level.busschedule busscheduleadd( "forest", 1, 10, 18, 5 ); + level.busschedule busscheduleadd( "farm", 0, randomintrange( 40, 180 ), 26, 25 ); + level.busschedule busscheduleadd( "cornfields", 1, 10, 23, 10 ); + level.busschedule busscheduleadd( "power", 0, randomintrange( 40, 180 ), 19, 15 ); + level.busschedule busscheduleadd( "power2town", 1, 10, 26, 5 ); + level.busschedule busscheduleadd( "town", 0, randomintrange( 40, 180 ), 18, 20 ); + level.busschedule busscheduleadd( "bridge", 1, 10, 23, 10 ); +/# + _a369 = level.busschedule.destinations; + index = getFirstArrayKey( _a369 ); + while ( isDefined( index ) ) + { + stop = _a369[ index ]; + adddebugcommand( "devgui_cmd "Zombies:1/Bus:14/Teleport Bus:4/" + stop.name + ":" + index + "" "zombie_devgui teleport_bus " + stop.name + "\n" ); + index = getNextArrayKey( _a369, index ); +#/ + } +} + +busschedulethink() +{ + self endon( "death" ); + for ( ;; ) + { + while ( 1 ) + { + self waittill( "noteworthy", noteworthy, noteworthynode ); + zoneisempty = 1; + shouldremovegas = 0; + destinationindex = level.busschedule busschedulegetdestinationindex( noteworthy ); + while ( !isDefined( destinationindex ) || !isDefined( noteworthynode ) ) + { +/# + if ( isDefined( noteworthy ) ) + { + println( "^2Bus Debug: Not A Valid Destination (" + noteworthy + ")" ); + continue; + } + else + { + println( "^2Bus Debug: Not A Valid Destination" ); +#/ + } + } + self.destinationindex = destinationindex; + self.waittimeatdestination = level.busschedule busschedulegetmaxwaittimebeforeleaving( self.destinationindex ); + self.currentnode = noteworthynode; + targetspeed = level.busschedule busschedulegetbusspeedleaving( self.destinationindex ); + _a416 = level.zones; + _k416 = getFirstArrayKey( _a416 ); + while ( isDefined( _k416 ) ) + { + zone = _a416[ _k416 ]; + if ( !isDefined( zone.volumes ) || zone.volumes.size == 0 ) + { + } + else + { + zonename = zone.volumes[ 0 ].targetname; + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( zonename ) ) + { +/# + println( "^2Bus Debug: Bus Is Touching Zone (" + zonename + ")" ); +#/ + self.zone = zonename; + zonestocheck = []; + zonestocheck[ zonestocheck.size ] = zonename; + switch( zonename ) + { + case "zone_station_ext": + zonestocheck[ zonestocheck.size ] = "zone_trans_1"; + zonestocheck[ zonestocheck.size ] = "zone_pri"; + zonestocheck[ zonestocheck.size ] = "zone_pri2"; + zonestocheck[ zonestocheck.size ] = "zone_amb_bridge"; + zonestocheck[ zonestocheck.size ] = "zone_trans_2b"; + break; + case "zone_gas": + zonestocheck[ zonestocheck.size ] = "zone_trans_2"; + zonestocheck[ zonestocheck.size ] = "zone_amb_tunnel"; + zonestocheck[ zonestocheck.size ] = "zone_gar"; + zonestocheck[ zonestocheck.size ] = "zone_trans_diner"; + zonestocheck[ zonestocheck.size ] = "zone_trans_diner2"; + zonestocheck[ zonestocheck.size ] = "zone_diner_roof"; + zonestocheck[ zonestocheck.size ] = "zone_din"; + zonestocheck[ zonestocheck.size ] = "zone_roadside_west"; + zonestocheck[ zonestocheck.size ] = "zone_roadside_east"; + zonestocheck[ zonestocheck.size ] = "zone_trans_3"; + break; + case "zone_far": + zonestocheck[ zonestocheck.size ] = "zone_amb_forest"; + zonestocheck[ zonestocheck.size ] = "zone_far_ext"; + zonestocheck[ zonestocheck.size ] = "zone_farm_house"; + zonestocheck[ zonestocheck.size ] = "zone_brn"; + zonestocheck[ zonestocheck.size ] = "zone_trans_5"; + zonestocheck[ zonestocheck.size ] = "zone_trans_6"; + break; + case "zone_pow": + zonestocheck[ zonestocheck.size ] = "zone_trans_6"; + zonestocheck[ zonestocheck.size ] = "zone_amb_cornfield"; + zonestocheck[ zonestocheck.size ] = "zone_trans_7"; + zonestocheck[ zonestocheck.size ] = "zone_pow_ext1"; + zonestocheck[ zonestocheck.size ] = "zone_prr"; + zonestocheck[ zonestocheck.size ] = "zone_pcr"; + zonestocheck[ zonestocheck.size ] = "zone_pow_warehouse"; + break; + case "zone_town_north": + zonestocheck[ zonestocheck.size ] = "zone_trans_8"; + zonestocheck[ zonestocheck.size ] = "zone_amb_power2town"; + zonestocheck[ zonestocheck.size ] = "zone_tbu"; + zonestocheck[ zonestocheck.size ] = "zone_town_church"; + zonestocheck[ zonestocheck.size ] = "zone_bar"; + zonestocheck[ zonestocheck.size ] = "zone_town_east"; + zonestocheck[ zonestocheck.size ] = "zone_tow"; + zonestocheck[ zonestocheck.size ] = "zone_ban"; + zonestocheck[ zonestocheck.size ] = "zone_ban_vault"; + zonestocheck[ zonestocheck.size ] = "zone_town_west"; + zonestocheck[ zonestocheck.size ] = "zone_town_west2"; + zonestocheck[ zonestocheck.size ] = "zone_town_barber"; + zonestocheck[ zonestocheck.size ] = "zone_town_south"; + zonestocheck[ zonestocheck.size ] = "zone_trans_9"; + break; + } + _a500 = zonestocheck; + _k500 = getFirstArrayKey( _a500 ); + while ( isDefined( _k500 ) ) + { + zone = _a500[ _k500 ]; + if ( isDefined( zoneisempty ) && !zoneisempty ) + { + } + else if ( maps/mp/zombies/_zm_zonemgr::player_in_zone( zone ) ) + { +/# + println( "^2Bus Debug: Player(s) Detected Near Bus In The Zone (" + zone + ")" ); +#/ + zoneisempty = 0; + } + _k500 = getNextArrayKey( _a500, _k500 ); + } + if ( isDefined( zoneisempty ) && zoneisempty ) + { +/# + println( "^2Bus Debug: No Player(s) Are In The Same Zone As Bus (" + zonename + ")" ); +#/ + break; + } + else + { +/# + println( "^2Bus Debug: Player(s) Are In The Same Zone As Bus (" + zonename + ")" ); +#/ + } + } + } + _k416 = getNextArrayKey( _a416, _k416 ); + } + if ( isDefined( shouldremovegas ) && shouldremovegas ) + { + self busgasremove( level.busschedule busschedulegetbusgasusage( self.destinationindex ) ); + } + while ( isDefined( zoneisempty ) && zoneisempty ) + { +/# + println( "^2Bus Debug: Bus Won't Consider Stopping Since Zone Is Empty." ); +#/ + self busstartmoving( targetspeed ); + } + if ( isDefined( self.skip_next_destination ) && self.skip_next_destination ) + { +/# + println( "^2Bus Debug: Bus Won't Consider Stopping Since It's Skipping Destination." ); +#/ + self notify( "skipping_destination" ); + self busstartmoving( targetspeed ); + } + } + else /# + println( "^2Bus Debug: Bus Will Consider Stopping, Someone Is Nearby." ); +#/ + if ( level.busschedule busschedulegetisambushstop( self.destinationindex ) ) + { +/# + println( "^2Bus Debug: Arrived At Ambush Point." ); +#/ + if ( maps/mp/zm_transit_ambush::shouldstartambushround() && self.numplayersinsidebus != 0 ) + { +/# + println( "^2Bus Debug: Ambush Triggering" ); +#/ + self busstopmoving( 1 ); + level.nml_zone_name = "zone_amb_" + noteworthy; + thread maps/mp/zm_transit_ambush::ambushstartround(); + thread automatonspeak( "inform", "out_of_gas" ); + flag_waitopen( "ambush_round" ); + shouldremovegas = 1; + thread automatonspeak( "inform", "refueled_gas" ); + break; + } + else + { +/# + println( "^2Bus Debug: Over Ambush Point But No BreakDown Triggered." ); +#/ + } + } + } + else /# + println( "^2Bus Debug: Arrived At Destination" ); +#/ + self notify( "reached_destination" ); + shouldremovegas = 1; + thread do_automaton_arrival_vox( noteworthy ); + if ( noteworthy != "diner" || noteworthy == "town" && noteworthy == "power" ) + { + self busstopmoving( 1 ); + if ( noteworthy == "diner" ) + { + self bussetdineropenings( 0 ); + } + else if ( noteworthy == "power" ) + { + self bussetpoweropenings( 0 ); + } + else + { + if ( noteworthy == "town" ) + { + self bussettownopenings( 0 ); + } + } + } + else + { + self busstopmoving(); + } + self thread busscheduledepartearly(); + waittimeatdestination = self.waittimeatdestination; +/# + if ( getDvarInt( #"1CF9CD76" ) != 0 ) + { + println( "^2Bus Debug: Using custom wait time of: " + getDvarInt( #"1CF9CD76" ) + " seconds." ); + waittimeatdestination = getDvarInt( #"1CF9CD76" ); + } + if ( getDvarInt( "zombie_cheat" ) > 0 ) + { + thread busshowleavinghud( waittimeatdestination ); +#/ + } + self waittill_any_timeout( waittimeatdestination, "depart_early" ); +/# + while ( getDvarInt( #"F7C16264" ) ) + { + wait 0,1; +#/ + } + self notify( "ready_to_depart" ); + self thread buslightsflash(); + self thread buslightsignal( "turn_signal_left" ); + thread automatonspeak( "inform", "leaving_warning" ); + self thread play_bus_audio( "grace" ); + wait self.gracetimeatdestination; + thread automatonspeak( "inform", "leaving" ); + self.accel = 1; + self busstartmoving( targetspeed ); + self notify( "departing" ); + self setclientfield( "bus_flashing_lights", 0 ); +} +} + +busscheduledepartearly() +{ + self endon( "ready_to_depart" ); + wait 15; + triggerbuswait = 0; + while ( 1 ) + { + while ( isDefined( self.disabled_by_emp ) && self.disabled_by_emp ) + { + wait 1; + } + players = get_players(); + nearbyplayers = 0; + readytoleaveplayers = 0; + _a717 = players; + _k717 = getFirstArrayKey( _a717 ); + while ( isDefined( _k717 ) ) + { + player = _a717[ _k717 ]; + if ( !is_player_valid( player ) ) + { + } + else + { + if ( distancesquared( self.origin, player.origin ) < 262144 ) + { + nearbyplayers++; + if ( player.isonbus ) + { + readytoleaveplayers++; + } + } + } + _k717 = getNextArrayKey( _a717, _k717 ); + } + if ( readytoleaveplayers != 0 && readytoleaveplayers == nearbyplayers ) + { + if ( !triggerbuswait ) + { + wait 5; + triggerbuswait = 1; + } + else + { + self notify( "depart_early" ); +/# + if ( isDefined( level.bus_leave_hud ) ) + { + level.bus_leave_hud.alpha = 0; +#/ + } + return; + } + } + else + { + if ( triggerbuswait ) + { + triggerbuswait = 0; + } + } + wait 1; + } +} + +busschedulecreate() +{ + schedule = spawnstruct(); + schedule.destinations = []; + return schedule; +} + +busscheduleadd( stopname, isambush, maxwaittimebeforeleaving, busspeedleaving, gasusage ) +{ +/# + assert( isDefined( stopname ) ); +#/ +/# + assert( isDefined( isambush ) ); +#/ +/# + assert( isDefined( maxwaittimebeforeleaving ) ); +#/ +/# + assert( isDefined( busspeedleaving ) ); +#/ + destinationindex = self.destinations.size; + self.destinations[ destinationindex ] = spawnstruct(); + self.destinations[ destinationindex ].name = stopname; + self.destinations[ destinationindex ].isambush = isambush; + self.destinations[ destinationindex ].maxwaittimebeforeleaving = maxwaittimebeforeleaving; + self.destinations[ destinationindex ].busspeedleaving = busspeedleaving; + self.destinations[ destinationindex ].gasusage = gasusage; +} + +busschedulegetdestinationindex( stopname ) +{ + _a800 = self.destinations; + index = getFirstArrayKey( _a800 ); + while ( isDefined( index ) ) + { + stop = _a800[ index ]; + if ( stop.name != stopname ) + { + } + else + { + return index; + } + index = getNextArrayKey( _a800, index ); + } + return undefined; +} + +busschedulegetstopname( destinationindex ) +{ + return self.destinations[ destinationindex ].name; +} + +busschedulegetisambushstop( destinationindex ) +{ + return self.destinations[ destinationindex ].isambush; +} + +busschedulegetmaxwaittimebeforeleaving( destinationindex ) +{ + return self.destinations[ destinationindex ].maxwaittimebeforeleaving; +} + +busschedulegetbusspeedleaving( destinationindex ) +{ + return self.destinations[ destinationindex ].busspeedleaving; +} + +busschedulegetbusgasusage( destinationindex ) +{ + return self.destinations[ destinationindex ].gasusage; +} + +transit_actor_damage_override_wrapper( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( damage > self.health && isDefined( self.isonbus ) && self.isonbus ) + { + ret = self maps/mp/zombies/_zm::actor_damage_override_wrapper( inflictor, attacker, self.health - 1, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + self zombie_in_bus_death_animscript_callback( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + return ret; + } + return self maps/mp/zombies/_zm::actor_damage_override_wrapper( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); +} + +zombie_in_bus_death_animscript_callback( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( isDefined( self ) && isDefined( self.opening ) ) + { + self.opening.zombie = undefined; + } + if ( isDefined( self.exploding ) && self.exploding ) + { + self notify( "killanimscript" ); + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + return 1; + } + if ( isDefined( self ) && isDefined( self.isonbus ) && !self.isonbus && isDefined( self.onbuswindow ) && !self.onbuswindow && isDefined( self.climbing_into_bus ) || self.climbing_into_bus && isDefined( self.climbing_onto_bus ) && self.climbing_onto_bus ) + { + level maps/mp/zombies/_zm_spawner::zombie_death_points( self.origin, meansofdeath, shitloc, attacker, self ); + launchvector = undefined; + if ( isDefined( self.onbuswindow ) && self.onbuswindow && isDefined( self.climbing_into_bus ) || !self.climbing_into_bus && isDefined( self.climbing_onto_bus ) && self.climbing_onto_bus ) + { + fwd = anglesToForward( flat_angle( self.angles * -1 ) ); + my_velocity = vectorScale( fwd, 50 ); + launchvector = ( my_velocity[ 0 ], my_velocity[ 1 ], 20 ); + } + self thread maps/mp/zombies/_zm_spawner::zombie_ragdoll_then_explode( launchvector, attacker ); + self notify( "killanimscript" ); + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + return 1; + } + return 0; +} + +debug_busnear() +{ +/# + if ( getDvarInt( #"29B9C39F" ) > 0 ) + { + zombie_front_dist = 1200; + zombie_side_dist = self.radius + 50; + zombie_inside_dist = 240; + zombie_plow_dist = 340; + forward_dir = anglesToForward( self.angles ); + forward_proj = vectorScale( forward_dir, zombie_front_dist ); + forward_pos = self.origin + forward_proj; + backward_proj = vectorScale( forward_dir, zombie_inside_dist * -1 ); + backward_pos = self.origin + backward_proj; + bus_front_dist = 225; + bus_back_dist = 235; + bus_width = 120; + side_dir = anglesToForward( self.angles + vectorScale( ( 0, 0, 1 ), 90 ) ); + side_proj = vectorScale( side_dir, zombie_side_dist ); + inside_pos = self.origin + vectorScale( forward_dir, zombie_inside_dist ); + plow_pos = self.origin + vectorScale( forward_dir, zombie_plow_dist ); + line( backward_pos, forward_pos, ( 0, 0, 1 ), 1, 0, 2 ); + line( inside_pos - side_proj, inside_pos + side_proj, ( 0, 0, 1 ), 1, 0, 2 ); + line( plow_pos - side_proj, plow_pos + side_proj, ( 0, 0, 1 ), 1, 0, 2 ); +#/ + } +} + +debug_zombieonbus( zombie ) +{ +/# + if ( getDvarInt( #"29B9C39F" ) > 0 ) + { + zombie_front_dist = 1200; + zombie_side_dist = self.radius + 50; + zombie_inside_dist = 240; + zombie_plow_dist = 340; + forward_dir = anglesToForward( self.angles ); + forward_proj = vectorScale( forward_dir, zombie_front_dist ); + forward_pos = self.origin + forward_proj; + backward_proj = vectorScale( forward_dir, zombie_inside_dist * -1 ); + backward_pos = self.origin + backward_proj; + zombie_origin = zombie.origin; + zombie_origin_proj = pointonsegmentnearesttopoint( backward_pos, forward_pos, zombie_origin ); + if ( isDefined( zombie.isonbus ) && zombie.isonbus ) + { + line( zombie_origin_proj, zombie_origin, ( 0, 0, 1 ), 1, 0, 2 ); + return; + } + else + { + line( zombie_origin_proj, zombie_origin, ( 0, 0, 1 ), 1, 0, 2 ); +#/ + } + } +} + +busupdatenearzombies() +{ + level endon( "end_game" ); + audiozomonbus_old = 0; + audiozomonbus_new = 0; + zombiesatwindow_old = 0; + zombiesatwindow_new = 0; + zombiesonroof_old = 0; + zombiesonroof_new = 0; + zombiesclimbing_new = 0; + zombiesclimbing_old = 0; + while ( 1 ) + { + self.zombiesinside = 0; + self.zombies_climbing = 0; + self.zombies_chasing_bus = 0; + self.zombiesatwindow = 0; + self.zombiesonroof = 0; + self.zombies_near_bus = 0; +/# + self debug_busnear(); +#/ + zombies = get_round_enemy_array(); + while ( isDefined( zombies ) ) + { + i = 0; + while ( i < zombies.size ) + { + if ( !isDefined( zombies[ i ] ) ) + { + i++; + continue; + } + else zombie = zombies[ i ]; + if ( isDefined( zombie.completed_emerging_into_playable_area ) && !zombie.completed_emerging_into_playable_area ) + { + i++; + continue; + } + else + { + if ( isDefined( zombie.isscreecher ) || zombie.isscreecher && isDefined( zombie.is_avogadro ) && zombie.is_avogadro ) + { + i++; + continue; + } + else + { + if ( !isDefined( zombie.isonbus ) ) + { + zombie.isonbus = 0; + } + zombie.ground_ent = zombie getgroundent(); + if ( isDefined( zombie.ground_ent ) ) + { + if ( isDefined( zombie.ground_ent.isonbus ) && zombie.ground_ent.isonbus ) + { + zombie.isonbus = 1; + break; + } + else + { + groundname = zombie.ground_ent.targetname; + if ( isDefined( groundname ) ) + { + if ( level.the_bus.targetname != groundname || groundname == "bus_path_blocker" && groundname == "hatch_clip" ) + { + zombie.dont_throw_gib = 1; + zombie.isonbus = 1; + if ( isDefined( zombie.entering_bus ) && zombie.entering_bus ) + { + zombie.entering_bus = undefined; + } + } + else + { + zombie.isonbus = 0; + } + break; + } + else + { + zombie.isonbus = 0; + } + } + } + if ( isDefined( zombie.entering_bus ) && zombie.entering_bus ) + { + zombie.isonbus = 1; + } + zombie.isonbusroof = zombie _entityisonroof(); + if ( isDefined( zombie.isonbusroof ) && zombie.isonbusroof ) + { + zombie thread play_zmbonbusroof_sound(); + } + if ( isDefined( zombie.isonbus ) && zombie.isonbus ) + { + if ( isDefined( zombie.entering_bus ) && !zombie.entering_bus ) + { + if ( !isDefined( zombie.onbusfunc ) ) + { + zombie.onbusfunc = ::maps/mp/zm_transit_openings::zombiemoveonbus; + zombie thread [[ zombie.onbusfunc ]](); + } + } + } + else + { + if ( isDefined( zombie.onbusfunc ) ) + { + zombie.onbusfunc = undefined; + zombie notify( "endOnBus" ); + zombie animmode( "normal" ); + zombie orientmode( "face enemy" ); + zombie.forcemovementscriptstate = 0; + zombie thread maps/mp/zombies/_zm_ai_basic::find_flesh(); + } + } + if ( isDefined( zombie.isonbus ) && zombie.isonbus ) + { + self.zombiesinside++; + } + else + { + if ( isDefined( zombie.onbuswindow ) && zombie.onbuswindow ) + { + self.zombiesatwindow++; + break; + } + else + { + if ( isDefined( zombie.isonbusroof ) && zombie.isonbusroof ) + { + self.zombiesonroof++; + break; + } + else + { + if ( isDefined( zombie.climbing_into_bus ) && zombie.climbing_into_bus ) + { + self.zombies_climbing++; + break; + } + else + { + if ( distancesquared( zombie.origin, self.origin ) < 122500 ) + { + if ( zombie.zombie_move_speed == "chase_bus" ) + { + self.zombies_chasing_bus++; + } + self.zombies_near_bus++; + } + } + } + } + } + if ( self.zombies_near_bus && !self.zombiesinside && !self.zombiesatwindow && !self.zombies_climbing & !self.zombiesonroof ) + { + level.bus_driver_focused = 1; + } + else + { + level.bus_driver_focused = 0; + } + if ( !self.zombiesinside && !self.zombiesatwindow && !self.zombies_climbing || self.zombiesonroof && self.zombies_near_bus ) + { + level.bus_zombie_danger = 1; + } + else + { + level.bus_zombie_danger = 0; + } + if ( self.ismoving && self getspeedmph() > 5 ) + { + if ( isDefined( self.plowtrigger ) ) + { + if ( zombie istouching( self.plowtrigger ) ) + { +/# + println( "^2Transit Debug: Plow killing zombie." ); +#/ + self thread busplowkillzombie( zombie ); + i++; + continue; + } + else } + else if ( isDefined( self.bussmashtrigger ) ) + { + if ( !isDefined( zombie.opening ) && isDefined( zombie.isonbus ) && !zombie.isonbus && zombie istouching( self.bussmashtrigger ) ) + { +/# + println( "^2Transit Debug: Plow pushing zombie." ); +#/ + self thread buspushzombie( zombie, self.bussmashtrigger ); + i++; + continue; + } + } + } + else + { + self update_zombie_move_speed( zombie ); +/# + self debug_zombieonbus( zombie ); +#/ + if ( ( i % 4 ) == 3 ) + { + wait 0,05; + } + } + } + } + i++; + } + } + audiozomonbus_new = self.zombiesinside; + zombiesatwindow_new = self.zombiesatwindow; + zombiesonroof_new = self.zombiesonroof; + zombiesclimbing_new = self.zombies_climbing; + self zomonbusvox( audiozomonbus_old, audiozomonbus_new ); + self zomatwindowvox( zombiesatwindow_old, zombiesatwindow_new ); + self zomonroofvox( zombiesonroof_old, zombiesonroof_new ); + self zomclimbingvox( zombiesclimbing_old, zombiesclimbing_new ); + self zomchasingvox(); + audiozomonbus_old = audiozomonbus_new; + zombiesatwindow_old = zombiesatwindow_new; + zombiesonroof_old = zombiesonroof_new; + zombiesclimbing_old = zombiesclimbing_new; + wait 0,05; + } +} + +entity_is_on_bus( use_cache ) +{ + if ( isDefined( self.isonbus ) && isDefined( use_cache ) && use_cache ) + { + return self.isonbus; + } + self.isonbus = 0; + self.ground_ent = self getgroundent(); + if ( isDefined( self.ground_ent ) ) + { + groundname = self.ground_ent.targetname; + if ( isDefined( groundname ) ) + { + if ( level.the_bus.targetname != groundname || groundname == "bus_path_blocker" && groundname == "hatch_clip" ) + { + self.isonbus = 1; + } + } + } + return self.isonbus; +} + +busupdatechasers() +{ + while ( 1 ) + { + while ( isDefined( self.ismoving ) && self.ismoving && isDefined( self.exceed_chase_speed ) && self.exceed_chase_speed ) + { + max_speed = 0; + zombies = getaiarray( level.zombie_team ); + slow_zombies = []; + _a1238 = zombies; + _k1238 = getFirstArrayKey( _a1238 ); + while ( isDefined( _k1238 ) ) + { + zombie = _a1238[ _k1238 ]; + if ( isDefined( zombie.zombie_move_speed ) && zombie.zombie_move_speed == "chase_bus" && isDefined( zombie.close_to_bus ) && !zombie.close_to_bus && !isDefined( zombie.opening ) ) + { + substate = zombie getanimsubstatefromasd(); + if ( substate == 6 ) + { + max_speed++; + break; + } + else + { + slow_zombies[ slow_zombies.size ] = zombie; + } + } + _k1238 = getNextArrayKey( _a1238, _k1238 ); + } + while ( max_speed < 3 ) + { + speed_up = 3 - max_speed; + if ( speed_up > slow_zombies.size ) + { + speed_up = slow_zombies.size; + } + _a1263 = slow_zombies; + _k1263 = getFirstArrayKey( _a1263 ); + while ( isDefined( _k1263 ) ) + { + zombie = _a1263[ _k1263 ]; + zombie setanimstatefromasd( "zm_move_chase_bus", 6 ); + speed_up--; + + if ( speed_up <= 0 ) + { + break; + } + else + { + _k1263 = getNextArrayKey( _a1263, _k1263 ); + } + } + } + } + wait 0,25; + } +} + +play_zmbonbusroof_sound() +{ + if ( isDefined( self.sndbusroofplayed ) && !self.sndbusroofplayed ) + { + self playsound( "fly_step_zombie_bus" ); + self.sndbusroofplayed = 1; + } +} + +object_is_on_bus() +{ + ground_ent = self getgroundent(); + depth = 0; + while ( isDefined( ground_ent ) && depth < 2 ) + { + groundname = ground_ent.targetname; + if ( isDefined( groundname ) ) + { + if ( level.the_bus.targetname != groundname || groundname == "bus_path_blocker" && groundname == "hatch_clip" ) + { + return 1; + } + } + new_ground_ent = ground_ent getgroundent(); + if ( !isDefined( new_ground_ent ) || new_ground_ent == ground_ent ) + { + } + else + { + ground_ent = new_ground_ent; + depth++; + } + } + return 0; +} + +busupdatenearequipment() +{ + equipment = maps/mp/zombies/_zm_equipment::get_destructible_equipment_list(); + i = 0; + while ( i < equipment.size ) + { + item = equipment[ i ]; + if ( !isDefined( item ) ) + { + i++; + continue; + } + else if ( isDefined( item.isonbus ) && item.isonbus ) + { + i++; + continue; + } + else + { + if ( isDefined( self.bussmashtrigger ) && item istouching( self.bussmashtrigger ) ) + { + item maps/mp/zombies/_zm_equipment::item_damage( 10000 ); +/# + println( "^2Bus hit an item." ); +#/ + } + } + i++; + } +} + +update_zombie_move_speed( zombie ) +{ + if ( isDefined( zombie.completed_emerging_into_playable_area ) && !zombie.completed_emerging_into_playable_area ) + { + return; + } + if ( !isDefined( zombie.normal_move_speed ) ) + { + zombie.normal_move_speed = 1; + } + if ( !zombie.has_legs ) + { + return; + } + if ( isDefined( zombie.favoriteenemy ) ) + { + if ( isDefined( zombie.favoriteenemy.isonbus ) ) + { + enemyonbus = zombie.favoriteenemy.isonbus; + } + } + if ( isDefined( zombie.isonbus ) && zombie.isonbus ) + { + if ( zombie.normal_move_speed ) + { + zombie.normal_move_speed = 0; + } + walk_state = zombie.zombie_move_speed; + if ( self.ismoving && isDefined( self.disabled_by_emp ) && !self.disabled_by_emp ) + { + if ( zombie.zombie_move_speed != "bus_walk" ) + { + walk_state = "bus_walk"; + } + } + else + { + if ( zombie.zombie_move_speed != "walk" ) + { + walk_state = "walk"; + } + } + if ( zombie.zombie_move_speed != walk_state ) + { + zombie set_zombie_run_cycle( walk_state ); + } + return; + } + else + { + if ( enemyonbus && !isDefined( zombie.opening ) ) + { + if ( self should_chase_bus( zombie ) ) + { + if ( zombie.zombie_move_speed != "chase_bus" ) + { + zombie.normal_move_speed = 0; + zombie set_zombie_run_cycle( "chase_bus" ); + zombie.crawl_anim_override = ::normal_move_speed; + } + return; + } + else + { + if ( zombie.zombie_move_speed == "chase_bus" ) + { + dist_sq = distance2dsquared( self.origin, level.the_bus.origin ); + if ( dist_sq > 90000 ) + { + return; + } + } + } + } + } + if ( !zombie.normal_move_speed ) + { + zombie normal_move_speed(); + } +} + +should_chase_bus( zombie ) +{ + if ( !self.ismoving ) + { + return 0; + } + if ( isDefined( self.exceed_chase_speed ) && !self.exceed_chase_speed ) + { + return 0; + } + if ( isDefined( self.disabled_by_emp ) && self.disabled_by_emp ) + { + return 0; + } + if ( isDefined( zombie.is_inert ) && zombie.is_inert ) + { + return 0; + } + if ( isDefined( zombie.is_traversing ) && zombie.is_traversing ) + { + return 0; + } + if ( !flag( "OnPriDoorYar2" ) ) + { + if ( !flag( "OnPriDoorYar" ) || !flag( "OnPriDoorYar3" ) ) + { + if ( zombie maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_pri" ) ) + { + return 0; + } + } + } + return 1; +} + +normal_move_speed() +{ + self.normal_move_speed = 1; + self set_zombie_run_cycle(); +} + +plowhudfade( text ) +{ + level endon( "plowHudUpdate" ); + fadein = 0,1; + fadeout = 3; + level.hudbuscount fadeovertime( fadein ); + level.hudbuscount.alpha = 1; + level.hudbuscount settext( text ); + wait fadein; + level.hudbuscount fadeovertime( 3 ); + level.hudbuscount.alpha = 0; +} + +busupdatespeed() +{ + targetspeed = self.targetspeed; + if ( is_false( self.ismoving ) ) + { + targetspeed = 0; + } + if ( isDefined( self.forcestop ) && self.forcestop ) + { + targetspeed = 0; + } + if ( isDefined( self.stalled ) && self.stalled ) + { + targetspeed = 0; + } + if ( isDefined( self.disabled_by_emp ) && self.disabled_by_emp ) + { + targetspeed = 0; + } + if ( targetspeed < 0 ) + { + targetspeed = 0; + } + if ( self.currentspeed != targetspeed ) + { + self.currentspeed = targetspeed; + if ( isDefined( self.immediatespeed ) && self.immediatespeed ) + { + self setspeedimmediate( targetspeed, self.accel, self.decel ); + self.immediatespeed = undefined; + } + else + { + if ( targetspeed == 0 ) + { + self setspeed( 0, 30, 30 ); + } + else + { + self setspeed( targetspeed, self.accel, self.decel ); + } + } + } +/# + if ( getDvarInt( #"6152C9EA" ) > 0 ) + { + msgorigin = self localtoworldcoords( vectorScale( ( 0, 0, 1 ), 100 ) ); + msgtext = "speed " + self getspeedmph(); + print3d( msgorigin, msgtext, ( 0, 0, 1 ), 1, 0,5, 2 ); +#/ + } +} + +bus_power_off() +{ + self endon( "power_on" ); + self.pre_disabled_by_emp = 1; + self thread play_bus_audio( "emp" ); + self buslightsdisableall(); + self notify( "pre_power_off" ); + while ( isDefined( self.ismoving ) && self.ismoving ) + { + while ( isDefined( self.istouchingignorewindowsvolume ) && self.istouchingignorewindowsvolume ) + { + wait 0,1; + } + } + self.disabled_by_emp = 1; + self thread buspathblockerenable(); + self notify( "power_off" ); +} + +bus_power_on() +{ + self buslightsenableall(); + wait 2; + self.pre_disabled_by_emp = 0; + self.disabled_by_emp = 0; + self thread buspathblockerdisable(); + self notify( "power_on" ); + wait 0,25; + self thread play_bus_audio( "leaving" ); + wait 3; + level.automaton automatonspeak( "inform", "doors_open" ); +} + +bus_disabled_by_emp( disable_time ) +{ + self bus_power_off(); + wait ( disable_time - 2 ); + self bus_power_on(); +} + +busispointinside( entitypos ) +{ + entityposinbus = pointonsegmentnearesttopoint( self.frontworld, self.backworld, entitypos ); + entityposzdelta = entitypos[ 2 ] - entityposinbus[ 2 ]; + entityposdist2 = distance2dsquared( entitypos, entityposinbus ); + if ( entityposdist2 > ( self.radius * self.radius ) ) + { + return 0; + } + return 1; +} + +busupdateignorewindows() +{ + if ( self getspeed() <= 0 ) + { + return; + } + if ( !isDefined( level.bus_ignore_windows ) ) + { + level.bus_ignore_windows = getentarray( "bus_ignore_windows", "targetname" ); + } + ignorewindowsvolume = undefined; + istouchingignorewindowsvolume = 0; + while ( isDefined( level.bus_ignore_windows ) && level.bus_ignore_windows.size > 0 ) + { + _a1639 = level.bus_ignore_windows; + _k1639 = getFirstArrayKey( _a1639 ); + while ( isDefined( _k1639 ) ) + { + volume = _a1639[ _k1639 ]; + if ( isDefined( istouchingignorewindowsvolume ) && istouchingignorewindowsvolume ) + { + } + else + { + if ( self istouching( volume ) ) + { + ignorewindowsvolume = volume; + istouchingignorewindowsvolume = 1; + } + } + _k1639 = getNextArrayKey( _a1639, _k1639 ); + } + } + self.ignorewindowsvolume = ignorewindowsvolume; + self.istouchingignorewindowsvolume = istouchingignorewindowsvolume; +} + +zombie_surf( zombie ) +{ + if ( !isDefined( self.zombie_surf_count ) ) + { + self.zombie_surf_count = 0; + } + damage = int( self.maxhealth / 10 ); + if ( isDefined( zombie.isonbusroof ) && zombie.isonbusroof && ( self.origin[ 2 ] - zombie.origin[ 2 ] ) >= 35 && isDefined( zombie.climbing_onto_bus ) && !zombie.climbing_onto_bus && isDefined( self.hatch_jump ) && !self.hatch_jump ) + { + damage = int( self.maxhealth / 8 ); + self.zombie_surf_count++; + if ( isDefined( level.zombie_surfing_kills ) && level.zombie_surfing_kills && self.zombie_surf_count > level.zombie_surfing_kill_count ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + self playlocalsound( level.zmb_laugh_alias ); + self dodamage( self.maxhealth + 1, zombie.origin ); + } + } + self applyknockback( damage, ( 0, 0, 1 ) ); +} + +busupdateplayers() +{ + level endon( "end_game" ); + while ( 1 ) + { + self.numplayers = 0; + self.numplayerson = 0; + self.numplayersonroof = 0; + self.numplayersinsidebus = 0; + self.numplayersnear = 0; + self.numaliveplayersridingbus = 0; + self.frontworld = self localtoworldcoords( self.frontlocal ); + self.backworld = self localtoworldcoords( self.backlocal ); + self.bus_riders_alive = []; +/# + if ( getDvarInt( #"10AC3C99" ) > 0 ) + { + line( self.frontworld + ( 0, 0, self.floor ), self.backworld + ( 0, 0, self.floor ), ( 0, 0, 1 ), 1, 0, 4 ); + line( self.frontworld + ( 0, 0, self.floor ), self.frontworld + ( 0, 0, self.height ), ( 0, 0, 1 ), 1, 0, 4 ); + circle( self.backworld + ( 0, 0, self.floor ), self.radius, ( 0, 0, 1 ), 0, 1, 4 ); + circle( self.frontworld + ( 0, 0, self.floor ), self.radius, ( 0, 0, 1 ), 0, 1, 4 ); +#/ + } + players = get_players(); + _a1717 = players; + _k1717 = getFirstArrayKey( _a1717 ); + while ( isDefined( _k1717 ) ) + { + player = _a1717[ _k1717 ]; + if ( !isalive( player ) ) + { + } + else + { + self.numplayers++; + if ( distance2d( player.origin, self.origin ) < 1700 ) + { + self.numplayersnear++; + } + playerisinbus = 0; + mover = player getmoverent(); + if ( isDefined( mover ) ) + { + if ( isDefined( mover.targetname ) ) + { + if ( mover.targetname != "the_bus" && mover.targetname != "bus_path_blocker" || mover.targetname == "hatch_clip" && mover.targetname == "ladder_mantle" ) + { + playerisinbus = 1; + } + } + if ( isDefined( mover.equipname ) ) + { + if ( mover.equipname == "riotshield_zm" ) + { + if ( isDefined( mover.isonbus ) && mover.isonbus ) + { + playerisinbus = 1; + } + } + } + if ( isDefined( mover.is_zombie ) && mover.is_zombie && isDefined( mover.isonbus ) && mover.isonbus ) + { + playerisinbus = 1; + } + } + if ( playerisinbus ) + { + self.numplayerson++; + if ( is_player_valid( player ) ) + { + self.numaliveplayersridingbus++; + self.bus_riders_alive[ self.bus_riders_alive.size ] = player; + } + } + ground_ent = player getgroundent(); + if ( player isonladder() ) + { + ground_ent = mover; + } + if ( isDefined( ground_ent ) ) + { + if ( isDefined( ground_ent.is_zombie ) && ground_ent.is_zombie ) + { + player thread zombie_surf( ground_ent ); + break; + } + else + { + if ( playerisinbus && isDefined( player.isonbus ) && !player.isonbus ) + { + bbprint( "zombie_events", "category %s type %s round %d playername %s", "BUS", "player_enter", level.round_number, player.name ); + player thread bus_audio_interior_loop( self ); + player clientnotify( "OBS" ); + player setclientplayerpushamount( 0 ); + player allowsprint( 0 ); + player allowprone( 0 ); + player._allow_sprint = 0; + player._allow_prone = 0; + isdivingtoprone = player getstance() == "prone"; + if ( isdivingtoprone ) + { + player thread playerdelayturnoffdivetoprone(); + break; + } + if ( randomint( 100 ) > 80 && level.automaton.greeting_timer == 0 ) + { + thread automatonspeak( "convo", "player_enter" ); + level.automaton thread greeting_timer(); + } + } + if ( !playerisinbus && isDefined( player.isonbus ) && player.isonbus ) + { + bbprint( "zombie_events", "category %s type %s round %d playername %s", "BUS", "player_exit", level.round_number, player.name ); + self.buyable_weapon setinvisibletoplayer( player ); + player setclientplayerpushamount( 1 ); + player allowsprint( 1 ); + player allowprone( 1 ); + player._allow_sprint = undefined; + player._allow_prone = undefined; + player notify( "left bus" ); + player clientnotify( "LBS" ); + if ( randomint( 100 ) > 80 && level.automaton.greeting_timer == 0 ) + { + thread automatonspeak( "convo", "player_leave" ); + level.automaton thread greeting_timer(); + } + } + player.isonbus = playerisinbus; + player.isonbusroof = player _entityisonroof(); + } + } + if ( isDefined( player.isonbusroof ) && player.isonbusroof ) + { + self.buyable_weapon setinvisibletoplayer( player ); + self.numplayersonroof++; + } + else + { + if ( isDefined( player.isonbus ) && player.isonbus ) + { + self.buyable_weapon setvisibletoplayer( player ); + self.numplayersinsidebus++; + } + } + wait 0,05; + } + _k1717 = getNextArrayKey( _a1717, _k1717 ); + } + wait 0,05; + } +} + +_entityisonroof() +{ + if ( !isDefined( level.roof_trig ) ) + { + level.roof_trig = getent( "bus_roof_watch", "targetname" ); + } + if ( !self.isonbus ) + { + return 0; + } + if ( self istouching( level.roof_trig ) ) + { + return 1; + } + return 0; +} + +greeting_timer() +{ + if ( level.automaton.greeting_timer > 0 ) + { + return; + } + level.automaton.greeting_timer = 1; + wait 20; + level.automaton.greeting_timer = 0; +} + +_updateplayersinsafearea() +{ + players = get_players(); + if ( !isDefined( level._safeareacachevalid ) || !level._safeareacachevalid ) + { + level.playable_areas = getentarray( "player_volume", "script_noteworthy" ); + level.nogas_areas = getentarray( "no_gas", "targetname" ); + level.ambush_areas = getentarray( "ambush_volume", "script_noteworthy" ); + level._safeareacachevaild = 1; + } + p = 0; + while ( p < players.size ) + { + players[ p ].insafearea = _isplayerinsafearea( players[ p ] ); + players[ p ] _playercheckpoison(); + p++; + } +} + +_isplayerinsafearea( player ) +{ + if ( isDefined( player.isonbus ) && player.isonbus ) + { + return level.the_bus.issafe; + } + if ( player _playertouchingsafearea( level.playable_areas ) ) + { + return 1; + } + if ( player _playertouchingsafearea( level.nogas_areas ) ) + { + return 1; + } + if ( flag( "ambush_safe_area_active" ) ) + { + return player _playertouchingsafearea( level.ambush_areas ); + } + return 0; +} + +_playertouchingsafearea( areas ) +{ + i = 0; + while ( i < areas.size ) + { + touching = self istouching( areas[ i ] ); + if ( touching ) + { + return 1; + } + i++; + } + return 0; +} + +_playercheckpoison() +{ + if ( !isalive( self ) || self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return; + } + if ( isDefined( self.poisoned ) && self.poisoned ) + { + return; + } + canbepoisoned = self playercanbepoisoned(); + if ( !canbepoisoned ) + { + return; + } + if ( !isDefined( self.insafearea ) || self.insafearea ) + { + return; + } + self thread _playerpoison(); +} + +playercanbepoisoned() +{ + god_mode = isgodmode( self ); + free_move = self isinmovemode( "ufo", "noclip" ); + zombie_cheat_num = getDvarInt( "zombie_cheat" ); + if ( zombie_cheat_num != 1 && zombie_cheat_num != 2 ) + { + is_invunerable = zombie_cheat_num == 3; + } + if ( !god_mode && !isDefined( free_move ) ) + { + return !is_invunerable; + } +} + +_playerpoison() +{ + self.poisoned = 1; + self startpoisoning(); + self playsound( "evt_gas_cough" ); + wait 1; + damage = 15; + while ( 1 ) + { + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || !isalive( self ) ) + { + self stoppoisoning(); + self.poisoned = 0; + return; + } + canbepoisoned = self playercanbepoisoned(); + if ( self.insafearea || !canbepoisoned ) + { + self stoppoisoning(); + self.poisoned = 0; + return; + } + if ( randomfloat( 100 ) < 60 ) + { + break; + } + self dodamage( damage, self.origin ); + damage += 1; + wait 1; + } +} + +_updateplayersinhubs() +{ + players = get_players(); + hubs = getentarray( "bus_hub", "script_noteworthy" ); + h = 0; + while ( h < hubs.size ) + { + hubs[ h ].active = 0; + p = 0; + while ( p < players.size && !hubs[ h ].active ) + { + hubs[ h ].active = players[ p ] istouching( hubs[ h ] ); + p++; + } + h++; + } +} + +playerdelayturnoffdivetoprone() +{ + self endon( "left bus" ); + wait 1,5; +} + +busgivepowerup( location ) +{ + currentzone = level.zones[ self.zone ]; + if ( isDefined( currentzone.target2 ) ) + { + spawndestent = getent( currentzone.target2, "targetname" ); + if ( isDefined( spawndestent ) ) + { + level thread maps/mp/zombies/_zm_powerups::specific_powerup_drop( "full_ammo", spawndestent.origin ); + level.powerup_drop_count = 0; + } + } +} + +buslightssetup() +{ + self setclientfield( "bus_head_lights", 1 ); +} + +buslightsflash() +{ + self endon( "departing" ); + while ( 1 ) + { + self buslightwaitenabled(); + self setclientfield( "bus_flashing_lights", 1 ); + wait 2,5; + self setclientfield( "bus_flashing_lights", 0 ); + wait 2,5; + } +} + +buslightsbrake() +{ + self buslightwaitenabled(); + self setclientfield( "bus_brake_lights", 1 ); + wait 5; + while ( is_false( self.ismoving ) ) + { + self buslightwaitenabled(); + self setclientfield( "bus_brake_lights", 1 ); + wait 0,8; + self setclientfield( "bus_brake_lights", 0 ); + wait 0,8; + } + self setclientfield( "bus_brake_lights", 0 ); +} + +buslightwaitenabled() +{ + while ( isDefined( self.bus_lights_disabled ) && self.bus_lights_disabled ) + { + wait 0,2; + } +} + +buslightdisable( light_name ) +{ + self.oldlights[ light_name ] = self getclientfield( light_name ); + self setclientfield( light_name, 0 ); +} + +buslightenable( light_name ) +{ + if ( self.oldlights[ light_name ] ) + { + self setclientfield( light_name, 1 ); + } +} + +buslightsignal( turn_signal_side ) +{ + self endon( "pre_power_off" ); + self endon( "power_off" ); + blink = 4; + x = 0; + while ( x < blink ) + { + wait 1; + self setclientfield( "bus_" + turn_signal_side, 1 ); + wait 1; + self setclientfield( "bus_" + turn_signal_side, 0 ); + x++; + } +} + +buslightsdisableall() +{ + if ( !isDefined( self.oldlights ) ) + { + self.oldlights = []; + } + self buslightdisable( "bus_flashing_lights" ); + self buslightdisable( "bus_head_lights" ); + self buslightdisable( "bus_brake_lights" ); + self buslightdisable( "bus_turn_signal_left" ); + self buslightdisable( "bus_turn_signal_right" ); + self.bus_lights_disabled = 1; +} + +buslightsenableall() +{ + self.bus_lights_disabled = 0; + self buslightenable( "bus_flashing_lights" ); + self buslightenable( "bus_head_lights" ); + self buslightenable( "bus_brake_lights" ); + self buslightenable( "bus_turn_signal_left" ); + self buslightenable( "bus_turn_signal_right" ); +} + +busdoorssetup() +{ + self.doorblockers = []; + self.doorblockers = getentarray( "bus_door_blocker", "targetname" ); + doorstrigger = getentarray( "bus_door_trigger", "targetname" ); + i = 0; + while ( i < self.doorblockers.size ) + { + self.doorblockers[ i ].offset = self worldtolocalcoords( self.doorblockers[ i ].origin ); + self.doorblockers[ i ] linkto( self, "", self.doorblockers[ i ].offset, ( 0, 0, 1 ) ); + self.doorblockers[ i ] setmovingplatformenabled( 1 ); + i++; + } + i = 0; + while ( i < doorstrigger.size ) + { + doorstrigger[ i ] enablelinkto(); + doorstrigger[ i ] linkto( self, "", self worldtolocalcoords( doorstrigger[ i ].origin ), ( 0, 0, 1 ) ); + doorstrigger[ i ] setcursorhint( "HINT_NOICON" ); + doorstrigger[ i ] sethintstring( &"ZOMBIE_TRANSIT_OPEN_BUS_DOOR" ); + doorstrigger[ i ] setmovingplatformenabled( 1 ); + doorstrigger[ i ] sethintlowpriority( 1 ); + self thread busdoorthink( doorstrigger[ i ] ); + i++; + } + self maps/mp/zm_transit_openings::busopeningsetenabled( "door", 0 ); +} + +busdoorsopen() +{ + if ( !self.doorsclosed || self.doorsdisabledfortime ) + { + return; + } + self.doorsclosed = 0; + self thread bussetdoornodes( 1 ); + doorstrigger = getentarray( "bus_door_trigger", "targetname" ); + i = 0; + while ( i < self.doorblockers.size ) + { + self.doorblockers[ i ] notsolid(); + self.doorblockers[ i ] playsound( "zmb_bus_door_open" ); + i++; + } + i = 0; + while ( i < doorstrigger.size ) + { + doorstrigger[ i ] sethintstring( &"ZOMBIE_TRANSIT_CLOSE_BUS_DOOR" ); + i++; + } + self bususeanimtree(); + self bususedoor( 1 ); + self maps/mp/zm_transit_openings::busopeningsetenabled( "door", 1 ); +} + +busdoorsclose() +{ + if ( self.doorsclosed || self.doorsdisabledfortime ) + { + return; + } + self.doorsclosed = 1; + self thread bussetdoornodes( 0 ); + level.the_bus showpart( "doors_front_left_2_jnt" ); + level.the_bus showpart( "doors_front_right_2_jnt" ); + level.the_bus showpart( "doors_rear_left_2_jnt" ); + level.the_bus showpart( "doors_rear_right_2_jnt" ); + doorstrigger = getentarray( "bus_door_trigger", "targetname" ); + i = 0; + while ( i < self.doorblockers.size ) + { + self.doorblockers[ i ] solid(); + self.doorblockers[ i ] playsound( "zmb_bus_door_close" ); + i++; + } + i = 0; + while ( i < doorstrigger.size ) + { + doorstrigger[ i ] sethintstring( &"ZOMBIE_TRANSIT_OPEN_BUS_DOOR" ); + i++; + } + self bususeanimtree(); + self bususedoor( 0 ); + self maps/mp/zm_transit_openings::busopeningsetenabled( "door", 0 ); +} + +busdoorsdisablefortime( time ) +{ + doorstrigger = getentarray( "bus_door_trigger", "targetname" ); + i = 0; + while ( i < doorstrigger.size ) + { + doorstrigger[ i ] setinvisibletoall(); + i++; + } + self.doorsdisabledfortime = 1; + wait time; + self.doorsdisabledfortime = 0; + i = 0; + while ( i < doorstrigger.size ) + { + doorstrigger[ i ] setvisibletoall(); + i++; + } +} + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +init_bus_door_anims() +{ + level.bus_door_open_state = %v_zombie_bus_all_doors_open; + level.bus_door_close_state = %v_zombie_bus_all_doors_close; + level.bus_door_open_idle_state = %v_zombie_bus_all_doors_idle_open; + level.bus_door_close_idle_state = %v_zombie_bus_all_doors_idle_closed; +} + +bususeanimtree() +{ + self useanimtree( -1 ); +} + +bususedoor( set ) +{ + self endon( "death" ); + animtime = 1; + if ( set ) + { + self.door_state = set; + self setanim( level.bus_door_open_state, 1, animtime, 1 ); + } + else + { + self.door_state = set; + self playsound( "zmb_bus_door_close" ); + self setanim( level.bus_door_close_state, 1, animtime, 1 ); + } + self notify( "BusUseDoor" ); +} + +busidledoor() +{ + while ( 1 ) + { + notifystring = self waittill_any_return( "departing", "BusUseDoor", "stopping" ); + if ( notifystring == "departing" || notifystring == "BusUseDoor" ) + { + if ( isDefined( self.ismoving ) && self.ismoving && isDefined( self.door_state ) ) + { + wait 1; + if ( self.door_state ) + { + self setanim( level.bus_door_open_idle_state ); + break; + } + else + { + self setanim( level.bus_door_close_idle_state ); + } + } + continue; + } + else + { + if ( notifystring == "stopping" ) + { + } + } + } +} + +init_props_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +init_bus_props_anims() +{ + level.bus_props_start_state = %fxanim_zom_bus_interior_start_anim; + level.bus_props_idle_state = %fxanim_zom_bus_interior_idle_anim; + level.bus_props_end_state = %fxanim_zom_bus_interior_end_anim; +} + +busfxanims() +{ + self.fxanimmodel = spawn( "script_model", self gettagorigin( "tag_body" ) ); + self.fxanimmodel setmodel( "fxanim_zom_bus_interior_mod" ); + self.fxanimmodel linkto( self, "tag_body" ); + self.fxanimmodel useanimtree( -1 ); +} + +busfxanims_start() +{ + if ( !isDefined( self.fxanimmodel ) ) + { + return; + } + self.fxanimmodel setanim( level.bus_props_start_state ); + wait getanimlength( level.bus_props_start_state ); + if ( isDefined( self.ismoving ) && self.ismoving ) + { + self.fxanimmodel setanim( level.bus_props_idle_state ); + } +} + +busfxanims_end() +{ + if ( !isDefined( self.fxanimmodel ) ) + { + return; + } + self.fxanimmodel setanim( level.bus_props_start_state ); +} + +busdoorthink( trigger ) +{ + while ( 1 ) + { + trigger waittill( "trigger", player ); + if ( isDefined( self.force_lock_doors ) && self.force_lock_doors ) + { + continue; + } + if ( self.doorsclosed ) + { + if ( isDefined( level.bus_intro_done ) && !level.bus_intro_done ) + { + thread automatonspeak( "scripted", "discover_bus" ); + level.bus_intro_done = 1; + } + else + { + if ( randomint( 100 ) > 75 && !isDefined( level.automaton.dmgfxorigin ) ) + { + thread automatonspeak( "inform", "doors_open" ); + } + } + self busdoorsopen(); + } + else + { + if ( randomint( 100 ) > 75 && !isDefined( level.automaton.dmgfxorigin ) ) + { + thread automatonspeak( "inform", "doors_close" ); + } + self busdoorsclose(); + } + wait 1; + } +} + +busfueltanksetup() +{ + script_origin = spawn( "script_origin", self.origin + ( -193, 75, 48 ) ); + script_origin.angles = vectorScale( ( 0, 0, 1 ), 180 ); + script_origin linkto( self ); + self.fueltankmodelpoint = script_origin; + script_origin = spawn( "script_origin", self.origin + ( -193, 128, 48 ) ); + script_origin linkto( self ); + self.fueltanktriggerpoint = script_origin; +} + +busdeferredinitplowclip( clip ) +{ + origin = self worldtolocalcoords( clip.origin ); + clip.origin = vectorScale( ( 0, 0, 1 ), 100 ); + wait_for_buildable( "cattlecatcher" ); + trigger = getent( "trigger_plow", "targetname" ); + while ( 1 ) + { + canbreak = 1; + players = get_players(); + _a2655 = players; + _k2655 = getFirstArrayKey( _a2655 ); + while ( isDefined( _k2655 ) ) + { + player = _a2655[ _k2655 ]; + if ( player istouching( trigger ) ) + { + canbreak = 0; + } + _k2655 = getNextArrayKey( _a2655, _k2655 ); + } + if ( canbreak ) + { + break; + } + else + { + wait 0,05; + } + } + self.plow_clip_attached = 1; + clip linkto( self, "", origin, ( 0, 0, 1 ) ); + clip setmovingplatformenabled( 1 ); +} + +busplowupdatesolid() +{ + if ( isDefined( self.cow_catcher_blocker ) ) + { + if ( isDefined( self.ismoving ) && !self.ismoving && isDefined( self.plow_attached ) && self.plow_attached ) + { + self.cow_catcher_blocker solid(); + self.cow_catcher_blocker disconnectpaths(); + return; + } + else + { + self.cow_catcher_blocker notsolid(); + self.cow_catcher_blocker connectpaths(); + } + } +} + +busplowsetup() +{ + clipbrush = getentarray( "plow_clip", "targetname" ); + while ( isDefined( clipbrush ) && clipbrush.size > 0 ) + { + i = 0; + while ( i < clipbrush.size ) + { + self thread busdeferredinitplowclip( clipbrush[ i ] ); + i++; + } + } + level.the_bus.plow_clip = clipbrush; + level.the_bus hidepart( "tag_plow_attach" ); + trigger = getent( "trigger_plow", "targetname" ); + trigger linkto( level.the_bus ); + trigger setmovingplatformenabled( 1 ); + self thread busplowmoveplayeronbuilt(); + self thread busplowmoveplayer(); + self.bussmashtrigger = trigger; + cow_catcher_blocker = getent( "cow_catcher_path_blocker", "targetname" ); + if ( isDefined( cow_catcher_blocker ) ) + { + self.cow_catcher_blocker = cow_catcher_blocker; + if ( !isDefined( self.path_blockers ) ) + { + self.path_blockers = []; + } + self.path_blockers[ self.path_blockers.size ] = cow_catcher_blocker; + self busplowupdatesolid(); + } + player = wait_for_buildable( "cattlecatcher" ); + flag_set( "catcher_attached" ); + self.plow_attached = 1; + self busplowupdatesolid(); + self.plowtrigger = trigger; + level.the_bus showpart( "tag_plow_attach" ); + level.the_bus.upgrades[ "Plow" ].installed = 1; + level.the_bus maps/mp/zm_transit_openings::busopeningsetenabled( "front", 0 ); + player maps/mp/zombies/_zm_buildables::track_placed_buildables( "cattlecatcher" ); +} + +busplowmoveplayeronbuilt() +{ + wait_for_buildable( "cattlecatcher" ); + while ( isDefined( self.plow_clip_attached ) && !self.plow_clip_attached ) + { + self busplowmoveplayerthink(); + wait 0,05; + } +} + +busplowmoveplayer() +{ + while ( 1 ) + { + while ( is_false( self.ismoving ) || isDefined( self.disabled_by_emp ) && self.disabled_by_emp ) + { + wait 0,1; + } + self busplowmoveplayerthink(); + wait 0,05; + } +} + +busplowmoveplayerthink() +{ + if ( !isDefined( level.triggerplow ) ) + { + level.triggerplow = getent( "trigger_plow", "targetname" ); + } + players = get_players(); + _a2797 = players; + _k2797 = getFirstArrayKey( _a2797 ); + while ( isDefined( _k2797 ) ) + { + player = _a2797[ _k2797 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + } + else + { + if ( player istouching( level.triggerplow ) ) + { + rightdistance = distancesquared( player.origin, self gettagorigin( "tag_wheel_front_right" ) ); + leftdistance = distancesquared( player.origin, self gettagorigin( "tag_wheel_front_left" ) ); + bus_dir = undefined; + if ( isDefined( player.is_burning ) && player getstance() == "stand" ) + { + player setstance( "crouch" ); + } + if ( rightdistance < leftdistance ) + { + bus_dir = vectorScale( anglesToForward( self.angles + ( -60, -60, 30 ) ), 512 ); + } + else + { + bus_dir = vectorScale( anglesToForward( self.angles + ( 60, 60, 30 ) ), 512 ); + } + bus_vel = self getvelocity(); + boost_velocity = bus_vel + bus_dir; + player setvelocity( boost_velocity ); + } + } + _k2797 = getNextArrayKey( _a2797, _k2797 ); + } +} + +buspushzombie( zombie, trigger ) +{ + opening = level.the_bus maps/mp/zm_transit_openings::busopeningbyname( "front" ); + if ( isDefined( opening ) && isDefined( opening.zombie ) || opening.zombie != zombie && isDefined( zombie.is_inert ) && zombie.is_inert ) + { + busplowkillzombie( zombie ); + } + else + { + zombie thread zombieattachtobus( level.the_bus, opening, 0 ); + } +} + +busplowkillzombie( zombie ) +{ + zombie.killedbyplow = 1; + if ( isDefined( zombie.busplowkillzombie ) ) + { + zombie thread [[ zombie.busplowkillzombie ]](); + return; + } + if ( is_mature() ) + { + if ( isDefined( level._effect[ "zomb_gib" ] ) ) + { + playfxontag( level._effect[ "zomb_gib" ], zombie, "J_SpineLower" ); + } + } + else + { + if ( isDefined( level._effect[ "spawn_cloud" ] ) ) + { + playfxontag( level._effect[ "spawn_cloud" ], zombie, "J_SpineLower" ); + } + } + zombie thread busplowkillzombieuntildeath(); + wait 1; + if ( isDefined( zombie ) ) + { + zombie hide(); + } + if ( !isDefined( self.upgrades[ "Plow" ].killcount ) ) + { + self.upgrades[ "Plow" ].killcount = 0; + } + self.upgrades[ "Plow" ].killcount++; +} + +busplowkillzombieuntildeath() +{ + self endon( "death" ); + while ( isDefined( self ) && isalive( self ) ) + { + if ( isDefined( self.health ) ) + { + self.marked_for_recycle = 1; + self dodamage( self.health + 666, self.origin, self, self, "none", "MOD_SUICIDE" ); + } + wait 1; + } +} + +bus_roof_watch() +{ + roof_trig = getent( "bus_roof_watch", "targetname" ); + roof_trig enablelinkto(); + roof_trig linkto( self, "", self worldtolocalcoords( roof_trig.origin ), roof_trig.angles + self.angles ); + roof_trig setmovingplatformenabled( 1 ); +} + +busroofjumpoffpositionssetup() +{ + jump_positions = getentarray( "roof_jump_off_positions", "targetname" ); +/# + assert( jump_positions.size > 0 ); +#/ + i = 0; + while ( i < jump_positions.size ) + { + jump_positions[ i ] linkto( self, "", self worldtolocalcoords( jump_positions[ i ].origin ), jump_positions[ i ].angles + self.angles ); + i++; + } +} + +bussideladderssetup() +{ + side_ladders = getentarray( "roof_ladder_outside", "targetname" ); + i = 0; + while ( i < side_ladders.size ) + { + side_ladders[ i ].trigger = getent( side_ladders[ i ].target, "targetname" ); + if ( !isDefined( side_ladders[ i ].trigger ) ) + { + side_ladders[ i ] delete(); + i++; + continue; + } + else + { + side_ladders[ i ] linkto( self, "", self worldtolocalcoords( side_ladders[ i ].origin ), side_ladders[ i ].angles + self.angles ); + side_ladders[ i ].trigger enablelinkto(); + side_ladders[ i ].trigger linkto( self, "", self worldtolocalcoords( side_ladders[ i ].trigger.origin ), side_ladders[ i ].trigger.angles + self.angles ); + self thread bussideladderthink( side_ladders[ i ], side_ladders[ i ].trigger ); + } + i++; + } +} + +bussideladderthink( ladder, trigger ) +{ + if ( 1 ) + { + trigger delete(); + return; + } + trigger setcursorhint( "HINT_NOICON" ); + trigger sethintstring( &"ZOMBIE_TRANSIT_BUS_CLIMB_ROOF" ); + while ( 1 ) + { + trigger waittill( "trigger", player ); + teleport_location = self localtoworldcoords( ladder.script_vector ); + player setorigin( teleport_location ); + trigger setinvisibletoall(); + wait 1; + trigger setvisibletoall(); + } +} + +buspathblockersetup() +{ + self.path_blockers = getentarray( "bus_path_blocker", "targetname" ); + i = 0; + while ( i < self.path_blockers.size ) + { + self.path_blockers[ i ] linkto( self, "", self worldtolocalcoords( self.path_blockers[ i ].origin ), self.path_blockers[ i ].angles + self.angles ); + i++; + } + cow_catcher_blocker = getent( "cow_catcher_path_blocker", "targetname" ); + if ( isDefined( cow_catcher_blocker ) ) + { + cow_catcher_blocker linkto( self, "", self worldtolocalcoords( cow_catcher_blocker.origin ), cow_catcher_blocker.angles + self.angles ); + } + trig = getent( "bus_buyable_weapon1", "script_noteworthy" ); + trig enablelinkto(); + trig linkto( self, "", self worldtolocalcoords( trig.origin ), ( 0, 0, 1 ) ); + trig setinvisibletoall(); + self.buyable_weapon = trig; + level._spawned_wallbuys[ level._spawned_wallbuys.size ] = trig; + weapon_model = getent( trig.target, "targetname" ); + weapon_model linkto( self, "", self worldtolocalcoords( weapon_model.origin ), weapon_model.angles + self.angles ); + weapon_model setmovingplatformenabled( 1 ); + weapon_model._linked_ent = trig; +} + +bussetdoornodes( enable ) +{ + if ( isDefined( self.door_nodes_avoid_linking ) && self.door_nodes_avoid_linking ) + { + return; + } + if ( enable ) + { + if ( !self.door_nodes_linked ) + { + link_nodes( self.front_door_inside, self.front_door ); + link_nodes( self.front_door, self.front_door_inside ); + link_nodes( self.back_door_inside1, self.back_door ); + link_nodes( self.back_door, self.back_door_inside1 ); + link_nodes( self.back_door_inside2, self.back_door ); + link_nodes( self.back_door, self.back_door_inside2 ); + self.door_nodes_linked = 1; + } + } + else + { + if ( self.door_nodes_linked ) + { + unlink_nodes( self.front_door_inside, self.front_door ); + unlink_nodes( self.front_door, self.front_door_inside ); + unlink_nodes( self.back_door_inside1, self.back_door ); + unlink_nodes( self.back_door, self.back_door_inside1 ); + unlink_nodes( self.back_door_inside2, self.back_door ); + unlink_nodes( self.back_door, self.back_door_inside2 ); + self.door_nodes_linked = 0; + } + } +} + +buspathblockerenable() +{ + if ( !isDefined( self.path_blockers ) ) + { + return; + } + if ( self.path_blocking ) + { + return; + } + while ( level.the_bus getspeed() > 0 ) + { + wait 0,1; + } + i = 0; + while ( i < self.path_blockers.size ) + { + self.path_blockers[ i ] disconnectpaths(); + i++; + } + self.link_start = []; + self.link_end = []; + self buslinkdoornodes( "front_door_node" ); + self buslinkdoornodes( "back_door_node" ); + self.path_blocking = 1; +} + +buslinkdoornodes( node_name ) +{ + start_node = getnode( node_name, "targetname" ); + start_node.links = []; + while ( isDefined( start_node ) ) + { + near_nodes = getnodesinradiussorted( start_node.origin, 128, 0, 64, "pathnodes" ); + links = 0; + _a3071 = near_nodes; + _k3071 = getFirstArrayKey( _a3071 ); + while ( isDefined( _k3071 ) ) + { + node = _a3071[ _k3071 ]; + if ( !isDefined( node.target ) || node.target != "the_bus" ) + { + self.link_start[ self.link_start.size ] = start_node; + self.link_end[ self.link_end.size ] = node; + link_nodes( start_node, node ); + link_nodes( node, start_node ); + start_node.links[ start_node.links.size ] = node; + links++; + if ( links == 2 ) + { + return; + } + } + else + { + _k3071 = getNextArrayKey( _a3071, _k3071 ); + } + } + } +} + +busunlinkdoornodes( node_name ) +{ + start_node = getnode( node_name, "targetname" ); + while ( isDefined( start_node ) && isDefined( start_node.links ) ) + { + linked_nodes = start_node.links; + _a3098 = linked_nodes; + _k3098 = getFirstArrayKey( _a3098 ); + while ( isDefined( _k3098 ) ) + { + node = _a3098[ _k3098 ]; + if ( !isDefined( node.target ) || node.target != "the_bus" ) + { + unlink_nodes( start_node, node ); + unlink_nodes( node, start_node ); + } + _k3098 = getNextArrayKey( _a3098, _k3098 ); + } + } +} + +buspathblockerdisable() +{ + if ( !isDefined( self.path_blockers ) ) + { + return; + } + if ( !self.path_blocking ) + { + return; + } + i = 0; + while ( i < self.path_blockers.size ) + { + self.path_blockers[ i ] connectpaths(); + i++; + } + self.link_start = []; + self.link_end = []; + self busunlinkdoornodes( "front_door_node" ); + self busunlinkdoornodes( "back_door_node" ); + self.path_blocking = 0; + self bussetdineropenings( 1 ); + self bussetpoweropenings( 1 ); + self bussettownopenings( 1 ); +} + +bussetupbounds() +{ + self.bounds_origins = getentarray( "bus_bounds_origin", "targetname" ); + i = 0; + while ( i < self.bounds_origins.size ) + { + self.bounds_origins[ i ] linkto( self, "", self worldtolocalcoords( self.bounds_origins[ i ].origin ), self.angles ); + i++; + } +} + +busstartwait() +{ + while ( self getspeed() == 0 ) + { + wait 0,1; + } +} + +busshowleavinghud( time ) +{ + if ( !isDefined( level.bus_leave_hud ) ) + { + level.bus_leave_hud = newhudelem(); + level.bus_leave_hud.color = ( 0, 0, 1 ); + level.bus_leave_hud.fontscale = 4; + level.bus_leave_hud.x = -300; + level.bus_leave_hud.y = 100; + level.bus_leave_hud.alignx = "center"; + level.bus_leave_hud.aligny = "bottom"; + level.bus_leave_hud.horzalign = "center"; + level.bus_leave_hud.vertalign = "middle"; + level.bus_leave_hud.font = "objective"; + level.bus_leave_hud.glowcolor = ( 0,3, 0,6, 0,3 ); + level.bus_leave_hud.glowalpha = 1; + level.bus_leave_hud.foreground = 1; + level.bus_leave_hud.hidewheninmenu = 1; + } + level.bus_leave_hud.alpha = 0,3; + level.bus_leave_hud settimer( time ); + wait time; + level.bus_leave_hud.alpha = 0; +} + +busstartmoving( targetspeed ) +{ + if ( !self.ismoving ) + { + self.ismoving = 1; + self.isstopping = 0; + self thread busexceedchasespeed(); + bbprint( "zombie_events", "%s", "bus_start" ); + self setclientfield( "bus_brake_lights", 0 ); + self buspathblockerdisable(); + self thread busfxanims_start(); + self busplowupdatesolid(); + if ( !flag( "ambush_round" ) ) + { + level.numbusstopssincelastambushround++; + } + } + if ( isDefined( targetspeed ) ) + { + self.targetspeed = targetspeed; + } + self notify( "OnKeysUsed" ); + self thread play_bus_audio( "leaving" ); +} + +busexceedchasespeed() +{ + self notify( "exceed_chase_speed" ); + self endon( "exceed_chase_speed" ); + while ( isDefined( self.ismoving ) && self.ismoving ) + { + if ( self getspeedmph() > 12 ) + { + self.exceed_chase_speed = 1; + return; + } + wait 0,1; + } +} + +busstopwait() +{ + while ( self.ismoving && !self.isstopping ) + { + self.isstopping = 1; + bbprint( "zombie_events", "%s", "bus_stop" ); + while ( self getspeed() > 0 ) + { + wait 0,1; + } + } +} + +busstopmoving( immediatestop ) +{ + if ( self.ismoving ) + { + if ( isDefined( immediatestop ) && immediatestop ) + { + self.immediatespeed = 1; + } + self notify( "stopping" ); + self thread play_bus_audio( "stopping" ); + self.targetspeed = 0; + self setspeedimmediate( self.targetspeed, 30, 30 ); + self.ismoving = 0; + self.isstopping = 0; + self.exceed_chase_speed = 0; + self busplowupdatesolid(); + self thread buslightsbrake(); + self thread buspathblockerenable(); + self thread shakeplayersonbus(); + self thread busfxanims_end(); + } +} + +shakeplayersonbus() +{ + players = get_players(); + _a3289 = players; + _k3289 = getFirstArrayKey( _a3289 ); + while ( isDefined( _k3289 ) ) + { + player = _a3289[ _k3289 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), player.origin + vectorScale( ( 0, 0, 1 ), 32 ), 150 ); + } + _k3289 = getNextArrayKey( _a3289, _k3289 ); + } +} + +busgasadd( percent ) +{ + newgaslevel = level.the_bus.gas + percent; +/# + println( "^2Bus Debug: Old Gas Level is " + newgaslevel ); +#/ + if ( newgaslevel < 0 ) + { + newgaslevel = 0; + } + else + { + if ( newgaslevel > 100 ) + { + newgaslevel = 100; + } + } + level.the_bus.gas = newgaslevel; +/# + println( "^2Bus Debug: New Gas Level is " + newgaslevel ); +#/ +} + +busgasremove( percent ) +{ + busgasadd( percent * -1 ); +} + +busgasempty() +{ + if ( level.the_bus.gas <= 0 ) + { + return 1; + } + return 0; +} + +busrestartzombiespawningaftertime( seconds ) +{ + wait seconds; + maps/mp/zm_transit_utility::try_resume_zombie_spawning(); +} + +busthink() +{ + no_danger = 0; + self thread busupdatechasers(); + self.buyable_weapon notify( "stop_hint_logic" ); + self thread busupdateplayers(); + self thread busupdatenearzombies(); + while ( 1 ) + { + waittillframeend; + self busupdatespeed(); + self busupdateignorewindows(); + if ( self.ismoving ) + { + self busupdatenearequipment(); + } + if ( isDefined( level.bus_zombie_danger ) && !level.bus_zombie_danger || self.numplayersonroof && self.numplayersinsidebus ) + { + no_danger++; + if ( no_danger > 40 ) + { + level thread do_player_bus_zombie_vox( "bus_zom_none", 40, 60 ); + no_danger = 0; + } + } + else + { + no_danger = 0; + } + wait 0,1; + } +} + +zomclimbingvox( old, new ) +{ + if ( new <= old ) + { + return; + } + if ( new == 1 || new == 3 ) + { + level thread do_player_bus_zombie_vox( "bus_zom_climb", 30 ); + } +} + +zomchasingvox() +{ + if ( self.zombies_chasing_bus > 2 ) + { + level thread do_player_bus_zombie_vox( "bus_zom_chase", 15 ); + } +} + +zomonbusvox( old, new ) +{ + if ( new == old ) + { + return; + } + if ( new != 1 && new != 4 && new == 8 && randomint( 100 ) < 20 ) + { + level thread automatonspeak( "inform", "zombie_on_board" ); + } + else + { + if ( new >= 1 ) + { + level thread do_player_bus_zombie_vox( "bus_zom_ent", 25 ); + } + } +} + +zomatwindowvox( old, new ) +{ + if ( new <= old ) + { + return; + } + if ( new != 1 && new != 3 && new == 5 && randomint( 100 ) < 35 ) + { + level thread automatonspeak( "inform", "zombie_at_window" ); + } + else + { + if ( new >= 1 ) + { + level thread do_player_bus_zombie_vox( "bus_zom_atk", 25 ); + } + } +} + +zomonroofvox( old, new ) +{ + if ( new <= old ) + { + return; + } + if ( new != 1 && new != 4 && new == 8 && randomint( 100 ) < 35 ) + { + level thread automatonspeak( "inform", "zombie_on_roof" ); + } + else + { + if ( new >= 1 ) + { + level thread do_player_bus_zombie_vox( "bus_zom_roof", 25 ); + } + } +} + +bussetdineropenings( enable ) +{ + _a3464 = self.openings; + _k3464 = getFirstArrayKey( _a3464 ); + while ( isDefined( _k3464 ) ) + { + opening = _a3464[ _k3464 ]; + if ( opening.bindtag != "window_right_2_jnt" && opening.bindtag != "window_right_3_jnt" || opening.bindtag == "window_left_2_jnt" && opening.bindtag == "window_left_3_jnt" ) + { + opening.enabled = enable; + } + _k3464 = getNextArrayKey( _a3464, _k3464 ); + } +} + +bussetpoweropenings( enable ) +{ + _a3476 = self.openings; + _k3476 = getFirstArrayKey( _a3476 ); + while ( isDefined( _k3476 ) ) + { + opening = _a3476[ _k3476 ]; + if ( opening.bindtag == "window_right_4_jnt" ) + { + opening.enabled = enable; + } + _k3476 = getNextArrayKey( _a3476, _k3476 ); + } +} + +bussettownopenings( enable ) +{ + _a3487 = self.openings; + _k3487 = getFirstArrayKey( _a3487 ); + while ( isDefined( _k3487 ) ) + { + opening = _a3487[ _k3487 ]; + if ( opening.bindtag == "window_right_4_jnt" ) + { + opening.enabled = enable; + } + _k3487 = getNextArrayKey( _a3487, _k3487 ); + } +} + +busgetclosestopening() +{ + enemy = self.favoriteenemy; + closestorigin = undefined; + closestopeningtozombie = undefined; + closestdisttozombie = -1; + closestorigintozombie = undefined; + closestopeningtoplayer = undefined; + closestdisttoplayer = -1; + closestorigintoplayer = undefined; + i = 0; + while ( i < level.the_bus.openings.size ) + { + opening = level.the_bus.openings[ i ]; + if ( !opening.enabled ) + { + i++; + continue; + } + else if ( maps/mp/zm_transit_openings::_isopeningdoor( opening.bindtag ) ) + { + i++; + continue; + } + else jump_origin = maps/mp/zm_transit_openings::_determinejumpfromorigin( opening ); + dist2 = distancesquared( enemy.origin, jump_origin ); + if ( !isDefined( closestopeningtoplayer ) || dist2 < closestdisttoplayer ) + { + closestopeningtoplayer = opening; + closestorigintoplayer = jump_origin; + closestdisttoplayer = dist2; + } + if ( isDefined( opening.zombie ) ) + { + i++; + continue; + } + else + { + dist2 = distancesquared( self.origin, jump_origin ); + if ( !isDefined( closestopeningtozombie ) || dist2 < closestdisttozombie ) + { + closestopeningtozombie = opening; + closestorigintozombie = jump_origin; + closestdisttozombie = dist2; + } + } + i++; + } + if ( isDefined( closestopeningtozombie ) ) + { + closestorigin = closestorigintozombie; + } + else + { + closestorigin = closestorigintoplayer; + } + return closestorigin; +} + +busgetclosestexit() +{ + enemy = self.favoriteenemy; + goal_node = level.the_bus.front_door_inside; + if ( isDefined( enemy ) ) + { + dist_f = distancesquared( enemy.origin, level.the_bus.front_door_inside ); + dist_bl = distancesquared( enemy.origin, level.the_bus.exit_back_l ); + dist_br = distancesquared( enemy.origin, level.the_bus.exit_back_r ); + if ( dist_bl < dist_br ) + { + if ( dist_bl < dist_f ) + { + goal_node = dist_bl; + } + } + else + { + if ( dist_br < dist_f ) + { + goal_node = dist_br; + } + } + } + return goal_node.origin; +} + +enemy_location_override() +{ + enemy = self.favoriteenemy; + location = enemy.origin; + bus = level.the_bus; + if ( isDefined( self.isscreecher ) || self.isscreecher && isDefined( self.is_avogadro ) && self.is_avogadro ) + { + return location; + } + if ( isDefined( self.item ) ) + { + return self.origin; + } + if ( is_true( self.reroute ) ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + if ( isDefined( enemy.isonbus ) && enemy.isonbus && isDefined( self.solo_revive_exit ) && !self.solo_revive_exit ) + { + if ( isDefined( self.isonbus ) && !self.isonbus ) + { + if ( isDefined( bus.ismoving ) && bus.ismoving && isDefined( bus.disabled_by_emp ) && !bus.disabled_by_emp ) + { + self.ignoreall = 1; + if ( isDefined( self.close_to_bus ) && self.close_to_bus && isDefined( bus.istouchingignorewindowsvolume ) && !bus.istouchingignorewindowsvolume ) + { + self.goalradius = 2; + location = self busgetclosestopening(); + location = groundpos_ignore_water_new( location + vectorScale( ( 0, 0, 1 ), 60 ) ); + } + else + { + self.goalradius = 32; + while ( getTime() != bus.chase_pos_time ) + { + bus.chase_pos_time = getTime(); + bus.chase_pos_index = 0; + bus_forward = vectornormalize( anglesToForward( level.the_bus.angles ) ); + bus_right = vectornormalize( anglesToRight( level.the_bus.angles ) ); + bus.chase_pos = []; + bus.chase_pos[ 0 ] = level.the_bus.origin + vectorScale( bus_forward, -144 ); + bus.chase_pos[ 1 ] = bus.chase_pos[ 0 ] + vectorScale( bus_right, 64 ); + bus.chase_pos[ 2 ] = bus.chase_pos[ 0 ] + vectorScale( bus_right, -64 ); + _a3656 = bus.chase_pos; + _k3656 = getFirstArrayKey( _a3656 ); + while ( isDefined( _k3656 ) ) + { + pos = _a3656[ _k3656 ]; + pos = groundpos_ignore_water_new( pos + vectorScale( ( 0, 0, 1 ), 60 ) ); + _k3656 = getNextArrayKey( _a3656, _k3656 ); + } + } + location = bus.chase_pos[ bus.chase_pos_index ]; + bus.chase_pos_index++; + if ( bus.chase_pos_index >= 3 ) + { + bus.chase_pos_index = 0; + } + dist_sq = distancesquared( self.origin, location ); + if ( dist_sq < 2304 ) + { + self.close_to_bus = 1; + } + } + return location; + } + self.close_to_bus = 0; + if ( isDefined( bus.doorsclosed ) && bus.doorsclosed ) + { + self.ignoreall = 1; + self.goalradius = 2; + location = self busgetclosestopening(); + } + else + { + if ( isDefined( enemy.isonbusroof ) && enemy.isonbusroof ) + { + self.ignoreall = 1; + self.goalradius = 2; + location = self busgetclosestopening(); + } + else + { + front_dist = distance2dsquared( enemy.origin, level.the_bus.front_door.origin ); + back_dist = distance2dsquared( enemy.origin, level.the_bus.back_door.origin ); + if ( front_dist < back_dist ) + { + location = level.the_bus.front_door_inside.origin; + } + else + { + location = level.the_bus.back_door_inside1.origin; + } + self.ignoreall = 0; + self.goalradius = 32; + } + } + } + } + return location; +} + +adjust_enemyoverride() +{ + location = self.enemyoverride[ 0 ]; + bus = level.the_bus; + ent = self.enemyoverride[ 1 ]; + if ( isDefined( ent ) ) + { + if ( ent entity_is_on_bus( 1 ) ) + { + if ( isDefined( self.isonbus ) && !self.isonbus ) + { + if ( isDefined( bus.doorsclosed ) && bus.doorsclosed ) + { + self.goalradius = 2; + location = self busgetclosestopening(); + } + } + else + { + self.goalradius = 32; + } + } + } + return location; +} + +attachpoweruptobus( powerup ) +{ + if ( !isDefined( powerup ) || !isDefined( level.the_bus ) ) + { + return; + } + distanceoutsideofbus = 50; + heightofroofpowerup = 60; + heightoffloorpowerup = 25; + originofbus = level.the_bus gettagorigin( "tag_origin" ); + floorofbus = originofbus[ 2 ] + level.the_bus.floor; + adjustup = 0; + adjustdown = 0; + adjustin = 0; + pos = powerup.origin; + posinbus = pointonsegmentnearesttopoint( level.the_bus.frontworld, level.the_bus.backworld, pos ); + posdist2 = distance2dsquared( pos, posinbus ); + if ( posdist2 > ( level.the_bus.radius * level.the_bus.radius ) ) + { + radiusplus = level.the_bus.radius + distanceoutsideofbus; + if ( posdist2 > ( radiusplus * radiusplus ) ) + { + return; + } + adjustin = 1; + } + if ( !adjustin ) + { + bus_front_local = ( 276, 28, 0 ); + bus_front_local_world = level.the_bus localtoworldcoords( bus_front_local ); + bus_front_radius2 = 10000; + front_dist2 = distance2dsquared( powerup.origin, bus_front_local_world ); + if ( front_dist2 < bus_front_radius2 ) + { + adjustin = 1; + } + } + if ( adjustin ) + { + directiontobus = posinbus - pos; + directiontobusn = vectornormalize( directiontobus ); + howfarintobus = distanceoutsideofbus + 10; + powerup.origin += directiontobusn * howfarintobus; + } + poszdelta = powerup.origin[ 2 ] - posinbus[ 2 ]; + if ( poszdelta < ( level.the_bus.floor + heightoffloorpowerup ) ) + { + adjustup = 1; + } + else + { + if ( poszdelta > ( level.the_bus.height - 20 ) ) + { + adjustdown = 1; + } + } + if ( adjustup ) + { + powerup.origin = ( powerup.origin[ 0 ], powerup.origin[ 1 ], floorofbus + heightoffloorpowerup ); + } + else + { + if ( adjustdown ) + { + powerup.origin = ( powerup.origin[ 0 ], powerup.origin[ 1 ], floorofbus + heightofroofpowerup ); + } + } + powerup linkto( level.the_bus, "", level.the_bus worldtolocalcoords( powerup.origin ), powerup.angles - level.the_bus.angles ); +} + +shouldsuppressgibs( zombie ) +{ + if ( !isDefined( zombie ) || !isDefined( level.the_bus ) ) + { + return 0; + } + pos = zombie.origin; + posinbus = pointonsegmentnearesttopoint( level.the_bus.frontworld, level.the_bus.backworld, pos ); + poszdelta = pos[ 2 ] - posinbus[ 2 ]; + if ( poszdelta < ( level.the_bus.floor - 10 ) ) + { + return 0; + } + posdist2 = distance2dsquared( pos, posinbus ); + if ( posdist2 > ( level.the_bus.radius * level.the_bus.radius ) ) + { + return 0; + } + return 1; +} + +bus_bridge_speedcontrol() +{ + while ( 1 ) + { + self waittill( "reached_node", nextpoint ); +/# + if ( getDvarInt( #"583AF524" ) != 0 ) + { + if ( isDefined( nextpoint.target ) ) + { + futurenode = getvehiclenode( nextpoint.target, "targetname" ); + if ( isDefined( futurenode.script_noteworthy ) && futurenode.script_noteworthy == "emp_stop_point" ) + { + player = get_players()[ 0 ]; + player thread maps/mp/zombies/_zm_weap_emp_bomb::emp_detonate( player magicgrenadetype( "emp_grenade_zm", self.origin + vectorScale( ( 0, 0, 1 ), 10 ), ( 0, 0, 1 ), 0,05 ) ); +#/ + } + } + } + if ( isDefined( nextpoint.script_string ) ) + { + if ( nextpoint.script_string == "arrival_slowdown" ) + { + self thread start_stopping_bus(); + } + if ( nextpoint.script_string == "arrival_slowdown_fast" ) + { + self thread start_stopping_bus( 1 ); + } + } + while ( isDefined( nextpoint.script_noteworthy ) ) + { + if ( nextpoint.script_noteworthy == "slow_down" ) + { + self.targetspeed = 10; + if ( isDefined( nextpoint.script_float ) ) + { + self.targetspeed = nextpoint.script_float; + } + self setspeed( self.targetspeed, 80, 5 ); + break; + } + else if ( nextpoint.script_noteworthy == "turn_signal_left" || nextpoint.script_noteworthy == "turn_signal_right" ) + { + self thread buslightsignal( nextpoint.script_noteworthy ); + break; + } + else + { + if ( nextpoint.script_noteworthy == "resume_speed" ) + { + self.targetspeed = 12; + if ( isDefined( nextpoint.script_float ) ) + { + self.targetspeed = nextpoint.script_float; + } + self setspeed( self.targetspeed, 60, 60 ); + break; + } + else if ( nextpoint.script_noteworthy == "emp_stop_point" ) + { + self notify( "reached_emp_stop_point" ); + break; + } + else if ( nextpoint.script_noteworthy == "start_lava" ) + { + playfxontag( level._effect[ "bus_lava_driving" ], self, "tag_origin" ); + break; + } + else if ( nextpoint.script_noteworthy == "stop_lava" ) + { + break; + } + else if ( nextpoint.script_noteworthy == "bus_scrape" ) + { + self playsound( "zmb_bus_car_scrape" ); + break; + } + else if ( nextpoint.script_noteworthy == "arriving" ) + { + self thread begin_arrival_slowdown(); + self thread play_bus_audio( "arriving" ); + level thread do_player_bus_zombie_vox( "bus_stop", 10 ); + self thread buslightsignal( "turn_signal_right" ); + break; + } + else if ( nextpoint.script_noteworthy == "enter_transition" ) + { + playfxontag( level._effect[ "fx_zbus_trans_fog" ], self, "tag_headlights" ); + break; + } + else if ( nextpoint.script_noteworthy == "bridge" ) + { + level thread do_automaton_arrival_vox( "bridge" ); + player_near = 0; + node = getvehiclenode( "bridge_accel_point", "script_noteworthy" ); + while ( isDefined( node ) ) + { + players = get_players(); + _a3956 = players; + _k3956 = getFirstArrayKey( _a3956 ); + while ( isDefined( _k3956 ) ) + { + player = _a3956[ _k3956 ]; + if ( player.isonbus ) + { + } + else + { + if ( distancesquared( player.origin, node.origin ) < 6760000 ) + { + player_near = 1; + } + } + _k3956 = getNextArrayKey( _a3956, _k3956 ); + } + } + if ( player_near ) + { + trig = getent( "bridge_trig", "targetname" ); + trig notify( "trigger" ); + } + break; + } + else + { + while ( nextpoint.script_noteworthy == "depot" ) + { + volume = getent( "depot_lava_pit", "targetname" ); + traverse_volume = getent( "depot_pit_traverse", "targetname" ); + while ( isDefined( volume ) ) + { + zombies = getaiarray( level.zombie_team ); + i = 0; + while ( i < zombies.size ) + { + if ( isDefined( zombies[ i ].depot_lava_pit ) ) + { + if ( zombies[ i ] istouching( volume ) ) + { + zombies[ i ] thread [[ zombies[ i ].depot_lava_pit ]](); + } + i++; + continue; + } + else if ( zombies[ i ] istouching( volume ) ) + { + zombies[ i ] dodamage( zombies[ i ].health + 100, zombies[ i ].origin ); + i++; + continue; + } + else + { + if ( zombies[ i ] istouching( traverse_volume ) ) + { + zombies[ i ] dodamage( zombies[ i ].health + 100, zombies[ i ].origin ); + } + } + i++; + } + } + } + } + } + } + waittillframeend; + } +} + +bus_audio_setup() +{ + if ( !isDefined( self ) ) + { + return; + } + self.engine_ent_1 = spawn( "script_origin", self.origin ); + self.engine_ent_1 linkto( self, "tag_wheel_back_left" ); + self.engine_ent_2 = spawn( "script_origin", self.origin ); + self.engine_ent_2 linkto( self, "tag_wheel_back_left" ); +} + +play_bus_audio( type ) +{ + level notify( "playing_bus_audio" ); + level endon( "playing_bus_audio" ); + if ( isDefined( self.disabled_by_emp ) && self.disabled_by_emp && type != "emp" ) + { + self notify( "stop_bus_audio" ); + self.engine_ent_1 stoploopsound( 0,5 ); + self.engine_ent_2 stoploopsound( 0,5 ); + return; + } + switch( type ) + { + case "grace": + self.engine_ent_1 playloopsound( "zmb_bus_start_idle", 0,05 ); + level.automaton playsound( "zmb_bus_horn_warn" ); + break; + case "leaving": + level.automaton playsound( "zmb_bus_horn_leave" ); + self.engine_ent_2 playloopsound( "zmb_bus_start_move", 0,05 ); + self.engine_ent_1 stoploopsound( 2 ); + wait 7; + if ( isDefined( self.disabled_by_emp ) && !self.disabled_by_emp ) + { + self.engine_ent_1 playloopsound( "zmb_bus_exterior_loop", 2 ); + self.engine_ent_2 stoploopsound( 3 ); + } + break; + case "arriving": + level.automaton playsound( "zmb_bus_horn_leave" ); + break; + case "stopping": + self notify( "stop_bus_audio" ); + level.automaton playsound( "zmb_bus_horn_leave" ); + self.engine_ent_1 stoploopsound( 3 ); + self.engine_ent_2 stoploopsound( 3 ); + self.engine_ent_2 playsound( "zmb_bus_stop_move" ); + self playsound( "zmb_bus_car_scrape" ); + break; + case "emp": + self notify( "stop_bus_audio" ); + self.engine_ent_1 stoploopsound( 0,5 ); + self.engine_ent_2 stoploopsound( 0,5 ); + self.engine_ent_2 playsound( "zmb_bus_emp_shutdown" ); + break; + } +} + +bus_audio_interior_loop( bus ) +{ + self endon( "left bus" ); + while ( !bus.ismoving || isDefined( bus.disabled_by_emp ) && bus.disabled_by_emp ) + { + wait 0,1; + } + self clientnotify( "buslps" ); + self thread bus_audio_turnoff_interior_player( bus ); + self thread bus_audio_turnoff_interior_bus( bus ); +} + +bus_audio_turnoff_interior_player( bus ) +{ + bus endon( "stop_bus_audio" ); + self waittill_any( "left bus", "death", "player_suicide", "bled_out" ); + self clientnotify( "buslpe" ); +} + +bus_audio_turnoff_interior_bus( bus ) +{ + self endon( "left bus" ); + self endon( "death" ); + self endon( "player_suicide" ); + self endon( "bled_out" ); + bus waittill( "stop_bus_audio" ); + self clientnotify( "buslpe" ); +} + +play_lava_audio() +{ + ent_back = spawn( "script_origin", self gettagorigin( "tag_wheel_back_left" ) ); + ent_back linkto( self, "tag_wheel_back_left" ); + ent_front = spawn( "script_origin", self gettagorigin( "tag_wheel_front_right" ) ); + ent_front linkto( self, "tag_wheel_front_right" ); + while ( 1 ) + { + while ( isDefined( self.ismoving ) && !self.ismoving ) + { + wait 1; + } + while ( self maps/mp/zm_transit_lava::object_touching_lava() && self.zone != "zone_station_ext" && self.zone != "zone_pri" ) + { + ent_front playloopsound( "zmb_bus_lava_wheels_loop", 0,5 ); + ent_back playloopsound( "zmb_bus_lava_wheels_loop", 0,5 ); + wait 2; + while ( self maps/mp/zm_transit_lava::object_touching_lava() ) + { + wait 2; + } + } + if ( isDefined( ent_back ) && isDefined( ent_front ) ) + { + ent_front stoploopsound( 1 ); + ent_back stoploopsound( 1 ); + } + wait 2; + } +} + +delete_lava_audio_ents( ent1, ent2 ) +{ + self waittill( "stop_bus_audio" ); + ent1 delete(); + ent2 delete(); +} + +start_stopping_bus( stop_fast ) +{ + if ( isDefined( stop_fast ) && stop_fast ) + { + self setspeed( 4, 15 ); + } + else + { + self setspeed( 4, 5 ); + } +} + +begin_arrival_slowdown() +{ + self setspeed( 5 ); +} + +do_automoton_vox( name ) +{ + if ( !issubstr( name, "vox_" ) ) + { + return; + } + if ( !isDefined( level.stops ) ) + { + level.stops = []; + } + if ( !isDefined( level.stops[ name ] ) ) + { + level.stops[ name ] = 0; + } + level.stops[ name ]++; + if ( level.stops[ name ] > 5 ) + { + level.stops[ name ] = 4; + } + switch( name ) + { + case "vox_enter_tunnel": + level thread automatonspeak( "inform", "near_tunnel" + level.stops[ name ] ); + break; + case "vox_ride_generic": + if ( isDefined( level.stops ) && isDefined( level.stops[ "depot" ] ) && level.stops[ "depot" ] < 1 ) + { + return; + } + level thread automatonspeak( "inform", "ride_generic" ); + break; + case "vox_exit_tunnel": + if ( isDefined( level.tunnel_exit_vox_played ) && !level.tunnel_exit_vox_played ) + { + level thread automatonspeak( "inform", "leave_tunnel" ); + level.tunnel_exit_vox_played = 1; + } + break; + case "vox_cornfield": + level thread automatonspeak( "inform", "near_corn" + level.stops[ name ] ); + break; + case "vox_forest1": + level thread automatonspeak( "inform", "near_forest1_" + level.stops[ name ] ); + break; + case "vox_forest2": + level thread automatonspeak( "inform", "near_forest2_" + level.stops[ name ] ); + break; + } +} + +do_automaton_arrival_vox( destination ) +{ + if ( !isDefined( level.stops ) ) + { + level.stops = []; + } + if ( !isDefined( level.stops[ destination ] ) ) + { + level.stops[ destination ] = 0; + } + if ( destination == "depot" && isDefined( level.bus_intro_done ) && !level.bus_intro_done ) + { + return; + } + level.stops[ destination ]++; + if ( level.stops[ destination ] > 5 ) + { + level.stops[ destination ] = 4; + } + switch( destination ) + { + case "depot": + if ( isDefined( level.bus_intro_done ) && !level.bus_intro_done ) + { + break; + } + else + { + level thread automatonspeak( "inform", "near_station" + level.stops[ destination ] ); + break; + return; + case "diner": + case "farm": + case "power": + case "town": + level thread automatonspeak( "inform", "near_" + destination + level.stops[ destination ] ); + break; + return; + case "bridge": + if ( isDefined( level.collapse_vox_said ) && level.collapse_vox_said ) + { + level thread automatonspeak( "inform", "near_" + destination + level.stops[ destination ] ); + } + break; + return; + } +} +} + +do_player_bus_location_vox( node_info ) +{ + players = get_players(); + players = array_randomize( players ); + valid_player = undefined; + _a4291 = players; + _k4291 = getFirstArrayKey( _a4291 ); + while ( isDefined( _k4291 ) ) + { + player = _a4291[ _k4291 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + valid_player = player; + break; + } + else + { + _k4291 = getNextArrayKey( _a4291, _k4291 ); + } + } + if ( !isDefined( valid_player ) ) + { + return; + } + if ( isDefined( level.bus_zombie_danger ) && level.bus_zombie_danger && !valid_player.talks_in_danger ) + { + return; + } + vo_line = undefined; + if ( issubstr( node_info, "map_in" ) ) + { + if ( !isDefined( level.arrivals ) ) + { + level.arrivals = []; + } + if ( !isDefined( level.arrivals[ node_info ] ) ) + { + level.arrivals[ node_info ] = 0; + } + level.arrivals[ node_info ]++; + if ( level.arrivals[ node_info ] > 4 ) + { + level.arrivals[ node_info ] = 4; + } + vo_line = node_info + level.arrivals[ node_info ]; + } + else + { + vo_line = node_info; + if ( randomint( 100 ) > 75 ) + { + vo_line = "bus_ride"; + } + } + if ( !isDefined( vo_line ) ) + { + return; + } + if ( randomint( 100 ) < 25 ) + { + valid_player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", vo_line ); + } +} + +do_player_bus_zombie_vox( event, chance, timer ) +{ + if ( isDefined( level.doing_bus_zombie_vox ) || level.doing_bus_zombie_vox && !isDefined( event ) ) + { + return; + } + if ( !isDefined( chance ) ) + { + chance = 100; + } + time = 30; + if ( isDefined( timer ) ) + { + time = timer; + } + players = get_players(); + players = array_randomize( players ); + valid_player = undefined; + _a4374 = players; + _k4374 = getFirstArrayKey( _a4374 ); + while ( isDefined( _k4374 ) ) + { + player = _a4374[ _k4374 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + valid_player = player; + break; + } + else + { + _k4374 = getNextArrayKey( _a4374, _k4374 ); + } + } + if ( isDefined( valid_player ) ) + { + valid_player thread do_player_general_vox( "general", event, time, chance ); + level.doing_bus_zombie_vox = 1; + wait 10; + level.doing_bus_zombie_vox = 0; + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_cling.gsc b/zm_transit_patch/maps/mp/zm_transit_cling.gsc new file mode 100644 index 0000000..698726d --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_cling.gsc @@ -0,0 +1,359 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +initializecling() +{ + setupclingtrigger(); +} + +setupclingtrigger() +{ + if ( !isDefined( level.the_bus ) ) + { + return; + } + enablecling(); + triggers = []; + level.cling_triggers = []; + triggers = getentarray( "cling_trigger", "script_noteworthy" ); + i = 0; + while ( i < triggers.size ) + { + level.cling_triggers[ i ] = spawnstruct(); + level.cling_triggers[ i ].trigger = triggers[ i ]; + trigger = level.cling_triggers[ i ].trigger; + trigger sethintstring( "Hold [{+activate}] To Cling To The Bus." ); + trigger setcursorhint( "HINT_NOICON" ); + makevisibletoall( trigger ); + trigger enablelinkto(); + trigger linkto( level.the_bus, "", level.the_bus worldtolocalcoords( trigger.origin ), trigger.angles - level.the_bus.angles ); + trigger thread setclingtriggervisibility( i ); + trigger thread clingtriggerusethink( i ); + level.cling_triggers[ i ].position = getent( trigger.target, "targetname" ); + position = level.cling_triggers[ i ].position; + position linkto( level.the_bus, "", level.the_bus worldtolocalcoords( position.origin ), position.angles - level.the_bus.angles ); + level.cling_triggers[ i ].player = undefined; + i++; + } + disablecling(); +} + +enablecling() +{ + level.cling_enabled = 1; + while ( isDefined( level.cling_triggers ) ) + { + _a65 = level.cling_triggers; + _k65 = getFirstArrayKey( _a65 ); + while ( isDefined( _k65 ) ) + { + struct = _a65[ _k65 ]; + struct.trigger sethintstring( "Hold [{+activate}] To Cling To The Bus." ); + struct.trigger setteamfortrigger( "allies" ); + _k65 = getNextArrayKey( _a65, _k65 ); + } + } +} + +disablecling() +{ + level.cling_enabled = 0; + detachallplayersfromclinging(); + while ( isDefined( level.cling_triggers ) ) + { + _a81 = level.cling_triggers; + _k81 = getFirstArrayKey( _a81 ); + while ( isDefined( _k81 ) ) + { + struct = _a81[ _k81 ]; + struct.trigger sethintstring( "" ); + struct.trigger setteamfortrigger( "none" ); + _k81 = getNextArrayKey( _a81, _k81 ); + } + } +} + +makevisibletoall( trigger ) +{ + players = get_players(); + playerindex = 0; + while ( playerindex < players.size ) + { + trigger setinvisibletoplayer( players[ playerindex ], 0 ); + playerindex++; + } +} + +clingtriggerusethink( positionindex ) +{ + while ( 1 ) + { + self waittill( "trigger", who ); + while ( !level.cling_enabled ) + { + continue; + } + while ( !who usebuttonpressed() ) + { + continue; + } + while ( who in_revive_trigger() ) + { + continue; + } + if ( isDefined( who.is_drinking ) && who.is_drinking == 1 ) + { + continue; + } + while ( isDefined( level.cling_triggers[ positionindex ].player ) ) + { + if ( level.cling_triggers[ positionindex ].player == who ) + { + dettachplayerfrombus( who, positionindex ); + } + } + attachplayertobus( who, positionindex ); + thread detachfrombusonevent( who, positionindex ); + } +} + +setclingtriggervisibility( positionindex ) +{ + while ( 1 ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( level.cling_triggers[ positionindex ].player ) ) + { + is_player_clinging = level.cling_triggers[ positionindex ].player == players[ i ]; + } + no_player_clinging = !isDefined( level.cling_triggers[ positionindex ].player ); + if ( is_player_clinging || no_player_clinging && level.cling_enabled ) + { + self setinvisibletoplayer( players[ i ], 0 ); + i++; + continue; + } + else + { + self setinvisibletoplayer( players[ i ], 1 ); + } + i++; + } + wait 0,1; + } +} + +detachallplayersfromclinging() +{ + positionindex = 0; + while ( positionindex < level.cling_triggers.size ) + { + if ( !isDefined( level.cling_triggers[ positionindex ] ) || !isDefined( level.cling_triggers[ positionindex ].player ) ) + { + positionindex++; + continue; + } + else + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( level.cling_triggers[ positionindex ].player == players[ i ] ) + { + dettachplayerfrombus( players[ i ], positionindex ); + positionindex++; + continue; + } + else + { + i++; + } + } + } + positionindex++; + } +} + +attachplayertobus( player, positionindex ) +{ + turn_angle = 130; + pitch_up = 25; + if ( positionisupgraded( positionindex ) ) + { + turn_angle = 180; + pitch_up = 120; + } + level.cling_triggers[ positionindex ].player = player; + if ( positionisbl( positionindex ) ) + { + player playerlinktodelta( level.cling_triggers[ positionindex ].position, "tag_origin", 1, 180, turn_angle, pitch_up, 120, 1 ); + } + else if ( positionisbr( positionindex ) ) + { + player playerlinktodelta( level.cling_triggers[ positionindex ].position, "tag_origin", 1, turn_angle, 180, pitch_up, 120, 1 ); + } + else + { + level.cling_triggers[ positionindex ].player = undefined; + return; + } + level.cling_triggers[ positionindex ].trigger sethintstring( "Hold [{+activate}] To Let Go Of The Bus." ); + player disableplayerweapons( positionindex ); +} + +positionisbl( positionindex ) +{ + return level.cling_triggers[ positionindex ].position.script_string == "back_left"; +} + +positionisbr( positionindex ) +{ + return level.cling_triggers[ positionindex ].position.script_string == "back_right"; +} + +positionisupgraded( positionindex ) +{ + if ( positionisbl( positionindex ) && isDefined( level.the_bus.upgrades[ "PlatformL" ] ) && !level.the_bus.upgrades[ "PlatformL" ].installed ) + { + if ( positionisbr( positionindex ) && isDefined( level.the_bus.upgrades[ "PlatformR" ] ) ) + { + return level.the_bus.upgrades[ "PlatformR" ].installed; + } + } +} + +dettachplayerfrombus( player, positionindex ) +{ + level.cling_triggers[ positionindex ].trigger sethintstring( "Hold [{+activate}] To Cling To The Bus." ); + if ( !isDefined( level.cling_triggers[ positionindex ].player ) ) + { + return; + } + player unlink(); + level.cling_triggers[ positionindex ].player = undefined; + player enableplayerweapons( positionindex ); + player notify( "cling_dettached" ); +} + +detachfrombusonevent( player, positionindex ) +{ + player endon( "cling_dettached" ); + player waittill_any( "fake_death", "death", "player_downed" ); + dettachplayerfrombus( player, positionindex ); +} + +disableplayerweapons( positionindex ) +{ + weaponinventory = self getweaponslist( 1 ); + self.lastactiveweapon = self getcurrentweapon(); + self.clingpistol = undefined; + self.hadclingpistol = 0; + if ( !positionisupgraded( positionindex ) ) + { + i = 0; + while ( i < weaponinventory.size ) + { + weapon = weaponinventory[ i ]; + if ( weaponclass( weapon ) == "pistol" && isDefined( self.clingpistol ) || weapon == self.lastactiveweapon && self.clingpistol == "m1911_zm" ) + { + self.clingpistol = weapon; + self.hadclingpistol = 1; + } + i++; + } + if ( !isDefined( self.clingpistol ) ) + { + self giveweapon( "m1911_zm" ); + self.clingpistol = "m1911_zm"; + } + self switchtoweapon( self.clingpistol ); + self disableweaponcycling(); + self disableoffhandweapons(); + self allowcrouch( 0 ); + } + self allowlean( 0 ); + self allowsprint( 0 ); + self allowprone( 0 ); +} + +enableplayerweapons( positionindex ) +{ + self allowlean( 1 ); + self allowsprint( 1 ); + self allowprone( 1 ); + if ( !positionisupgraded( positionindex ) ) + { + if ( !self.hadclingpistol ) + { + self takeweapon( "m1911_zm" ); + } + self enableweaponcycling(); + self enableoffhandweapons(); + self allowcrouch( 1 ); + if ( self.lastactiveweapon != "none" && self.lastactiveweapon != "mortar_round" && self.lastactiveweapon != "mine_bouncing_betty" && self.lastactiveweapon != "claymore_zm" ) + { + self switchtoweapon( self.lastactiveweapon ); + return; + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } + } +} + +playerisclingingtobus() +{ + if ( !isDefined( level.cling_triggers ) ) + { + return 0; + } + i = 0; + while ( i < level.cling_triggers.size ) + { + if ( !isDefined( level.cling_triggers[ i ] ) || !isDefined( level.cling_triggers[ i ].player ) ) + { + i++; + continue; + } + else + { + if ( level.cling_triggers[ i ].player == self ) + { + return 1; + } + } + i++; + } + return 0; +} + +_getnumplayersclinging() +{ + num_clinging = 0; + i = 0; + while ( i < level.cling_triggers.size ) + { + if ( isDefined( level.cling_triggers[ i ] ) && isDefined( level.cling_triggers[ i ].player ) ) + { + num_clinging++; + } + i++; + } + return num_clinging; +} + +_getbusattackposition( player ) +{ + pos = ( -208, 0, 48 ); + return level.the_bus localtoworldcoords( pos ); +} diff --git a/zm_transit_patch/maps/mp/zm_transit_distance_tracking.gsc b/zm_transit_patch/maps/mp/zm_transit_distance_tracking.gsc new file mode 100644 index 0000000..d23755f --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_distance_tracking.gsc @@ -0,0 +1,161 @@ +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +zombie_tracking_init() +{ + level.zombie_respawned_health = []; + if ( !isDefined( level.zombie_tracking_dist ) ) + { + level.zombie_tracking_dist = 1500; + } + if ( !isDefined( level.zombie_tracking_wait ) ) + { + level.zombie_tracking_wait = 10; + } + for ( ;; ) + { + while ( 1 ) + { + zombies = get_round_enemy_array(); + if ( !isDefined( zombies ) || isDefined( level.ignore_distance_tracking ) && level.ignore_distance_tracking ) + { + wait level.zombie_tracking_wait; + } + } + else i = 0; + while ( i < zombies.size ) + { + if ( isDefined( zombies[ i ] ) && isDefined( zombies[ i ].ignore_distance_tracking ) && !zombies[ i ].ignore_distance_tracking ) + { + zombies[ i ] thread delete_zombie_noone_looking( level.zombie_tracking_dist ); + } + i++; + } + wait level.zombie_tracking_wait; + } +} + +delete_zombie_noone_looking( how_close ) +{ + self endon( "death" ); + if ( !isDefined( how_close ) ) + { + how_close = 1000; + } + distance_squared_check = how_close * how_close; + too_far_dist = distance_squared_check * 3; + if ( isDefined( level.zombie_tracking_too_far_dist ) ) + { + too_far_dist = level.zombie_tracking_too_far_dist * level.zombie_tracking_too_far_dist; + } + self.inview = 0; + self.player_close = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].sessionstate == "spectator" ) + { + i++; + continue; + } + else if ( isDefined( level.only_track_targeted_players ) ) + { + if ( !isDefined( self.favoriteenemy ) || self.favoriteenemy != players[ i ] ) + { + i++; + continue; + } + } + else + { + can_be_seen = self player_can_see_me( players[ i ] ); + if ( can_be_seen && distancesquared( self.origin, players[ i ].origin ) < too_far_dist ) + { + self.inview++; + } + if ( distancesquared( self.origin, players[ i ].origin ) < distance_squared_check ) + { + self.player_close++; + } + } + i++; + } + wait 0,1; + if ( self.inview == 0 && self.player_close == 0 ) + { + if ( !isDefined( self.animname ) || isDefined( self.animname ) && self.animname != "zombie" ) + { + return; + } + if ( isDefined( self.electrified ) && self.electrified == 1 ) + { + return; + } + if ( isDefined( self.in_the_ground ) && self.in_the_ground == 1 ) + { + return; + } + zombies = getaiarray( "axis" ); + if ( isDefined( self.damagemod ) && self.damagemod == "MOD_UNKNOWN" && self.health < self.maxhealth ) + { + if ( isDefined( self.exclude_distance_cleanup_adding_to_total ) && !self.exclude_distance_cleanup_adding_to_total && isDefined( self.isscreecher ) && !self.isscreecher ) + { + level.zombie_total++; + level.zombie_respawned_health[ level.zombie_respawned_health.size ] = self.health; + } + } + else + { + if ( ( zombies.size + level.zombie_total ) > 24 || ( zombies.size + level.zombie_total ) <= 24 && self.health >= self.maxhealth ) + { + if ( isDefined( self.exclude_distance_cleanup_adding_to_total ) && !self.exclude_distance_cleanup_adding_to_total && isDefined( self.isscreecher ) && !self.isscreecher ) + { + level.zombie_total++; + if ( self.health < level.zombie_health ) + { + level.zombie_respawned_health[ level.zombie_respawned_health.size ] = self.health; + } + } + } + } + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + self notify( "zombie_delete" ); + self delete(); + recalc_zombie_array(); + } +} + +player_can_see_me( player ) +{ + playerangles = player getplayerangles(); + playerforwardvec = anglesToForward( playerangles ); + playerunitforwardvec = vectornormalize( playerforwardvec ); + banzaipos = self.origin; + playerpos = player getorigin(); + playertobanzaivec = banzaipos - playerpos; + playertobanzaiunitvec = vectornormalize( playertobanzaivec ); + forwarddotbanzai = vectordot( playerunitforwardvec, playertobanzaiunitvec ); + if ( forwarddotbanzai >= 1 ) + { + anglefromcenter = 0; + } + else if ( forwarddotbanzai <= -1 ) + { + anglefromcenter = 180; + } + else + { + anglefromcenter = acos( forwarddotbanzai ); + } + playerfov = getDvarFloat( "cg_fov" ); + banzaivsplayerfovbuffer = getDvarFloat( "g_banzai_player_fov_buffer" ); + if ( banzaivsplayerfovbuffer <= 0 ) + { + banzaivsplayerfovbuffer = 0,2; + } + playercanseeme = anglefromcenter <= ( ( playerfov * 0,5 ) * ( 1 - banzaivsplayerfovbuffer ) ); + return playercanseeme; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_ffotd.gsc b/zm_transit_patch/maps/mp/zm_transit_ffotd.gsc new file mode 100644 index 0000000..6b74347 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_ffotd.gsc @@ -0,0 +1,291 @@ +#include maps/mp/zm_transit; +#include maps/mp/zombies/_zm_ffotd; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +main_start() +{ + precachemodel( "collision_wall_256x256x10_standard" ); + precachemodel( "collision_geo_32x32x10_standard" ); + precachemodel( "collision_wall_128x128x10_standard" ); + precachemodel( "collision_wall_64x64x10_standard" ); + precachemodel( "collision_wall_512x512x10_standard" ); + precachemodel( "collision_player_32x32x128" ); + precachemodel( "collision_player_256x256x256" ); + old_roof_trig = getent( "bus_roof_watch", "targetname" ); + level.roof_trig = spawn( "trigger_box", old_roof_trig.origin, 0, 464, 180, 120 ); + level.roof_trig.targetname = "bus_roof_watch"; + old_roof_trig delete(); + if ( isDefined( level.use_swipe_protection ) ) + { + onplayerconnect_callback( ::claymore_watch_swipes ); + } + powerdoors = getentarray( "local_electric_door", "script_noteworthy" ); + _a29 = powerdoors; + _k29 = getFirstArrayKey( _a29 ); + while ( isDefined( _k29 ) ) + { + door = _a29[ _k29 ]; + if ( isDefined( door.door_hold_trigger ) && door.door_hold_trigger == "zombie_door_hold_diner" ) + { + if ( isDefined( door.script_flag ) && door.script_flag == "OnPriDoorYar" ) + { + door.script_flag = undefined; + } + } + _k29 = getNextArrayKey( _a29, _k29 ); + } +} + +main_end() +{ + if ( !is_true( level.optimise_for_splitscreen ) ) + { + maps/mp/zombies/_zm::spawn_kill_brush( ( 33, -450, -90 ), 982, 15 ); + location = level.scr_zm_map_start_location; + type = level.scr_zm_ui_gametype; + collision4 = spawn( "script_model", ( 12240, 8480, -720 ) ); + collision4 setmodel( "collision_wall_64x64x10_standard" ); + collision4.angles = ( 0, 1, 0 ); + collision4 ghost(); + collision5 = spawn( "script_model", ( 8320, -6679, 362 ) ); + collision5 setmodel( "collision_wall_256x256x10_standard" ); + collision5.angles = vectorScale( ( 0, 1, 0 ), 300 ); + collision5 ghost(); + collision6 = spawn( "script_model", ( 8340, -5018, 191 ) ); + collision6 setmodel( "collision_geo_32x32x10_standard" ); + collision6.angles = vectorScale( ( 0, 1, 0 ), 270 ); + collision6 ghost(); + collision7 = spawn( "script_model", ( 8340, -5018, 219 ) ); + collision7 setmodel( "collision_geo_32x32x10_standard" ); + collision7.angles = vectorScale( ( 0, 1, 0 ), 270 ); + collision7 ghost(); + collision8 = spawn( "script_model", ( 8044, -5018, 191 ) ); + collision8 setmodel( "collision_geo_32x32x10_standard" ); + collision8.angles = vectorScale( ( 0, 1, 0 ), 270 ); + collision8 ghost(); + collision9 = spawn( "script_model", ( 8044, -5018, 219 ) ); + collision9 setmodel( "collision_geo_32x32x10_standard" ); + collision9.angles = vectorScale( ( 0, 1, 0 ), 270 ); + collision9 ghost(); + if ( location == "town" && type == "zstandard" ) + { + collision10 = spawn( "script_model", ( 1820, 126, 152 ) ); + collision10 setmodel( "collision_wall_128x128x10_standard" ); + collision10.angles = vectorScale( ( 0, 1, 0 ), 262 ); + collision10 ghost(); + } + collision11 = spawn( "script_model", ( 11216,3, 8188, -432 ) ); + collision11 setmodel( "collision_wall_128x128x10_standard" ); + collision11.angles = vectorScale( ( 0, 1, 0 ), 180 ); + collision11 ghost(); + collision12 = spawn( "script_model", ( -454, 620,25, -1,75 ) ); + collision12 setmodel( "collision_wall_128x128x10_standard" ); + collision12.angles = vectorScale( ( 0, 1, 0 ), 330 ); + collision12 ghost(); + collision13 = spawn( "script_model", ( 11798, 8410, -734 ) ); + collision13 setmodel( "collision_wall_128x128x10_standard" ); + collision13.angles = ( 90, 260,589, -10,311 ); + collision13 ghost(); + collision14 = spawn( "script_model", ( 652, 240, 124 ) ); + collision14 setmodel( "collision_wall_128x128x10_standard" ); + collision14.angles = vectorScale( ( 0, 1, 0 ), 105 ); + collision14 ghost(); + if ( location == "farm" && type == "zgrief" ) + { + collision15 = spawn( "script_model", ( 8052, -5204, 380 ) ); + collision15 setmodel( "collision_wall_64x64x10_standard" ); + collision15.angles = vectorScale( ( 0, 1, 0 ), 180 ); + collision15 ghost(); + } + collision16 = spawn( "script_model", ( -448, 328, 112 ) ); + collision16 setmodel( "collision_wall_512x512x10_standard" ); + collision16.angles = ( 270, 67,822, 22,1776 ); + collision16 ghost(); + collision17 = spawn( "script_model", ( 6040, -5744, 240 ) ); + collision17 setmodel( "collision_player_256x256x256" ); + collision17.angles = vectorScale( ( 0, 1, 0 ), 90 ); + collision17 ghost(); + collision18 = spawn( "script_model", ( -6744, 4184, 64 ) ); + collision18 setmodel( "collision_wall_128x128x10_standard" ); + collision18.angles = vectorScale( ( 0, 1, 0 ), 90 ); + collision18 ghost(); + collision19 = spawn( "script_model", ( -6328, -7168, 264 ) ); + collision19 setmodel( "collision_player_256x256x256" ); + collision19.angles = vectorScale( ( 0, 1, 0 ), 90 ); + collision19 ghost(); + collision20 = spawn( "script_model", ( 9960, 7352, -136 ) ); + collision20 setmodel( "collision_player_256x256x256" ); + collision20.angles = vectorScale( ( 0, 1, 0 ), 90 ); + collision20 ghost(); + collision21 = spawn( "script_model", ( -4656, -7373, 0 ) ); + collision21 setmodel( "collision_player_32x32x128" ); + collision21.angles = vectorScale( ( 0, 1, 0 ), 341,6 ); + collision21 ghost(); + } + apartment_exploit(); + town_truck_exploit(); + farm_porch_exploit(); + power_station_exploit(); + nacht_exploit(); + level.equipment_dead_zone_pos = []; + level.equipment_dead_zone_rad2 = []; + level.equipment_dead_zone_type = []; + level.equipment_dead_zone_pos[ 0 ] = ( -6252,98, -7947,23, 149,125 ); + level.equipment_dead_zone_rad2[ 0 ] = 3600; + level.equipment_dead_zone_pos[ 1 ] = ( -11752, -2515, 288 ); + level.equipment_dead_zone_rad2[ 1 ] = 14400; + level.equipment_dead_zone_type[ 1 ] = "t6_wpn_zmb_shield_world"; + level.equipment_dead_zone_pos[ 2 ] = ( -6664, 4592, -48 ); + level.equipment_dead_zone_rad2[ 2 ] = 2304; + level.equipment_dead_zone_type[ 2 ] = "t6_wpn_zmb_shield_world"; + level.equipment_dead_zone_pos[ 3 ] = ( 7656, -4741, 38 ); + level.equipment_dead_zone_rad2[ 3 ] = 2304; + level.equipment_dead_zone_type[ 3 ] = "t6_wpn_zmb_shield_world"; + level.equipment_dead_zone_pos[ 4 ] = ( -11712, -776, 224 ); + level.equipment_dead_zone_rad2[ 4 ] = 16384; + level.equipment_dead_zone_type[ 4 ] = "t6_wpn_zmb_shield_world"; + level.equipment_dead_zone_pos[ 5 ] = ( -4868, -7713, -42 ); + level.equipment_dead_zone_rad2[ 5 ] = 256; + level.equipment_dead_zone_type[ 5 ] = "t6_wpn_zmb_shield_world"; + level.equipment_safe_to_drop = ::equipment_safe_to_drop_ffotd; +} + +apartment_exploit() +{ + zombie_trigger_origin = ( 994, -1145, 130 ); + zombie_trigger_radius = 32; + zombie_trigger_height = 64; + player_trigger_origin = ( 1068, -1085, 130 ); + player_trigger_radius = 72; + zombie_goto_point = ( 1024, -1024, 136 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); +} + +nacht_exploit() +{ + zombie_trigger_origin = ( 13720, -639, -188 ); + zombie_trigger_radius = 64; + zombie_trigger_height = 128; + player_trigger_origin = ( 13605, -651, -188 ); + player_trigger_radius = 64; + zombie_goto_point = ( 13671, -745, -188 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); +} + +town_truck_exploit() +{ + zombie_trigger_origin = ( 1414, -1921, -42 ); + zombie_trigger_radius = 50; + zombie_trigger_height = 64; + player_trigger_origin = ( 1476, -1776, -42 ); + player_trigger_radius = 76; + zombie_goto_point = ( 1476, -1867, -42 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); +} + +farm_porch_exploit() +{ + zombie_trigger_origin = ( 7864, -6088, 104 ); + zombie_trigger_radius = 85,5; + zombie_trigger_height = 64; + player_trigger_origin = ( 7984, -6128, 168 ); + player_trigger_radius = 44; + zombie_goto_point = ( 7960, -6072, 96 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); + zombie_trigger_origin = ( 7996, -6169, 132 ); + zombie_trigger_radius = 200,1; + zombie_trigger_height = 64; + player_trigger_origin = ( 7893, -6078, 121 ); + player_trigger_radius = 50; + zombie_goto_point = ( 7828, -6052,5, 125 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); +} + +power_station_exploit() +{ + zombie_trigger_origin = ( 11248, 8504, -560 ); + zombie_trigger_radius = 125; + zombie_trigger_height = 64; + player_trigger_origin = ( 11368, 8624, -560 ); + player_trigger_radius = 65; + zombie_goto_point = ( 11352, 8560, -560 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); + zombie_trigger_origin = ( 11168, 8880, -568 ); + zombie_trigger_radius = 78; + zombie_trigger_height = 64; + player_trigger_origin = ( 11048, 8888, -568 ); + player_trigger_radius = 79; + zombie_goto_point = ( 11072, 8912, -568 ); + level thread maps/mp/zombies/_zm_ffotd::path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ); +} + +equipment_safe_to_drop_ffotd( weapon ) +{ + i = 0; + while ( i < level.equipment_dead_zone_pos.size ) + { + if ( distancesquared( level.equipment_dead_zone_pos[ i ], weapon.origin ) < level.equipment_dead_zone_rad2[ i ] ) + { + if ( isDefined( level.equipment_dead_zone_type[ i ] ) || !isDefined( weapon.model ) && level.equipment_dead_zone_type[ i ] == weapon.model ) + { + return 0; + } + } + i++; + } + return self maps/mp/zm_transit::equipment_safe_to_drop( weapon ); +} + +claymore_watch_swipes() +{ + self endon( "disconnect" ); + self notify( "claymore_watch_swipes" ); + self endon( "claymore_watch_swipes" ); + while ( 1 ) + { + self waittill( "weapon_change", weapon ); + if ( is_placeable_mine( weapon ) ) + { + self.mine_damage = 0; + self thread watch_melee_swipes( weapon ); + } + } +} + +watch_melee_swipes( weapname ) +{ + self endon( "weapon_change" ); + self endon( "death" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "melee_swipe", zombie ); + self.mine_damage++; + if ( self.mine_damage > 5 ) + { + self.mine_damage = 0; + ammo = self getweaponammoclip( weapname ); + if ( ammo >= 1 ) + { + self setweaponammoclip( weapname, ammo - 1 ); + if ( ammo == 1 ) + { + self setweaponammoclip( weapname, ammo - 1 ); + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons[ 0 ] ) ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } + break; + } + else + { + self takeweapon( weapname ); + } + } + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_fx.gsc b/zm_transit_patch/maps/mp/zm_transit_fx.gsc new file mode 100644 index 0000000..1fd55fe --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_fx.gsc @@ -0,0 +1,121 @@ +#include maps/mp/_utility; + +main() +{ + precache_createfx_fx(); + precache_scripted_fx(); + maps/mp/createfx/zm_transit_fx::main(); + maps/mp/createart/zm_transit_art::main(); +} + +precache_scripted_fx() +{ + level._effect[ "switch_sparks" ] = loadfx( "env/electrical/fx_elec_wire_spark_burst" ); + level._effect[ "maxis_sparks" ] = loadfx( "maps/zombie/fx_zmb_race_trail_grief" ); + level._effect[ "richtofen_sparks" ] = loadfx( "maps/zombie/fx_zmb_race_trail_neutral" ); + level._effect[ "sq_common_lightning" ] = loadfx( "maps/zombie/fx_zmb_tranzit_sq_lightning_orb" ); + level._effect[ "zapper_light_ready" ] = loadfx( "maps/zombie/fx_zombie_zapper_light_green" ); + level._effect[ "zapper_light_notready" ] = loadfx( "maps/zombie/fx_zombie_zapper_light_red" ); + level._effect[ "lght_marker" ] = loadfx( "maps/zombie/fx_zmb_tranzit_marker" ); + level._effect[ "lght_marker_flare" ] = loadfx( "maps/zombie/fx_zmb_tranzit_marker_fl" ); + level._effect[ "poltergeist" ] = loadfx( "misc/fx_zombie_couch_effect" ); + level._effect[ "zomb_gib" ] = loadfx( "maps/zombie/fx_zmb_tranzit_lava_torso_explo" ); + level._effect[ "fx_headlight" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_headlight" ); + level._effect[ "fx_headlight_lenflares" ] = loadfx( "lens_flares/fx_lf_zmb_tranzit_bus_headlight" ); + level._effect[ "fx_brakelight" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_brakelights" ); + level._effect[ "fx_emergencylight" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_flashing_lights" ); + level._effect[ "fx_turn_signal_right" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_turnsignal_right" ); + level._effect[ "fx_turn_signal_left" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_turnsignal_left" ); + level._effect[ "fx_zbus_trans_fog" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_fog_intersect" ); + level._effect[ "bus_lava_driving" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_fire_driving" ); + level._effect[ "bus_hatch_bust" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bus_hatch_bust" ); + level._effect[ "elec_md" ] = loadfx( "electrical/fx_elec_player_md" ); + level._effect[ "elec_sm" ] = loadfx( "electrical/fx_elec_player_sm" ); + level._effect[ "elec_torso" ] = loadfx( "electrical/fx_elec_player_torso" ); + level._effect[ "blue_eyes" ] = loadfx( "maps/zombie/fx_zombie_eye_single_blue" ); + level._effect[ "lava_burning" ] = loadfx( "env/fire/fx_fire_lava_player_torso" ); + level._effect[ "mc_trafficlight" ] = loadfx( "maps/zombie/fx_zmb_morsecode_traffic_loop" ); + level._effect[ "mc_towerlight" ] = loadfx( "maps/zombie/fx_zmb_morsecode_loop" ); +} + +precache_createfx_fx() +{ + level._effect[ "fx_insects_swarm_md_light" ] = loadfx( "bio/insects/fx_insects_swarm_md_light" ); + level._effect[ "fx_zmb_tranzit_flourescent_flicker" ] = loadfx( "maps/zombie/fx_zmb_tranzit_flourescent_flicker" ); + level._effect[ "fx_zmb_tranzit_flourescent_glow" ] = loadfx( "maps/zombie/fx_zmb_tranzit_flourescent_glow" ); + level._effect[ "fx_zmb_tranzit_flourescent_glow_lg" ] = loadfx( "maps/zombie/fx_zmb_tranzit_flourescent_glow_lg" ); + level._effect[ "fx_zmb_tranzit_flourescent_dbl_glow" ] = loadfx( "maps/zombie/fx_zmb_tranzit_flourescent_dbl_glow" ); + level._effect[ "fx_zmb_tranzit_depot_map_flicker" ] = loadfx( "maps/zombie/fx_zmb_tranzit_depot_map_flicker" ); + level._effect[ "fx_zmb_tranzit_light_bulb_xsm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_bulb_xsm" ); + level._effect[ "fx_zmb_tranzit_light_glow" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_glow" ); + level._effect[ "fx_zmb_tranzit_light_glow_xsm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_glow_xsm" ); + level._effect[ "fx_zmb_tranzit_light_glow_fog" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_glow_fog" ); + level._effect[ "fx_zmb_tranzit_light_depot_cans" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_depot_cans" ); + level._effect[ "fx_zmb_tranzit_light_desklamp" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_desklamp" ); + level._effect[ "fx_zmb_tranzit_light_town_cans" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_town_cans" ); + level._effect[ "fx_zmb_tranzit_light_town_cans_sm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_town_cans_sm" ); + level._effect[ "fx_zmb_tranzit_light_street_tinhat" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_street_tinhat" ); + level._effect[ "fx_zmb_tranzit_street_lamp" ] = loadfx( "maps/zombie/fx_zmb_tranzit_street_lamp" ); + level._effect[ "fx_zmb_tranzit_truck_light" ] = loadfx( "maps/zombie/fx_zmb_tranzit_truck_light" ); + level._effect[ "fx_zmb_tranzit_spark_int_runner" ] = loadfx( "maps/zombie/fx_zmb_tranzit_spark_int_runner" ); + level._effect[ "fx_zmb_tranzit_spark_ext_runner" ] = loadfx( "maps/zombie/fx_zmb_tranzit_spark_ext_runner" ); + level._effect[ "fx_zmb_tranzit_spark_blue_lg_loop" ] = loadfx( "maps/zombie/fx_zmb_tranzit_spark_blue_lg_loop" ); + level._effect[ "fx_zmb_tranzit_spark_blue_sm_loop" ] = loadfx( "maps/zombie/fx_zmb_tranzit_spark_blue_sm_loop" ); + level._effect[ "fx_zmb_tranzit_bar_glow" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bar_glow" ); + level._effect[ "fx_zmb_tranzit_transformer_on" ] = loadfx( "maps/zombie/fx_zmb_tranzit_transformer_on" ); + level._effect[ "fx_zmb_fog_closet" ] = loadfx( "fog/fx_zmb_fog_closet" ); + level._effect[ "fx_zmb_fog_low_300x300" ] = loadfx( "fog/fx_zmb_fog_low_300x300" ); + level._effect[ "fx_zmb_fog_thick_600x600" ] = loadfx( "fog/fx_zmb_fog_thick_600x600" ); + level._effect[ "fx_zmb_fog_thick_1200x600" ] = loadfx( "fog/fx_zmb_fog_thick_1200x600" ); + level._effect[ "fx_zmb_fog_transition_600x600" ] = loadfx( "fog/fx_zmb_fog_transition_600x600" ); + level._effect[ "fx_zmb_fog_transition_1200x600" ] = loadfx( "fog/fx_zmb_fog_transition_1200x600" ); + level._effect[ "fx_zmb_fog_transition_right_border" ] = loadfx( "fog/fx_zmb_fog_transition_right_border" ); + level._effect[ "fx_zmb_tranzit_smk_interior_md" ] = loadfx( "maps/zombie/fx_zmb_tranzit_smk_interior_md" ); + level._effect[ "fx_zmb_tranzit_smk_interior_heavy" ] = loadfx( "maps/zombie/fx_zmb_tranzit_smk_interior_heavy" ); + level._effect[ "fx_zmb_ash_ember_1000x1000" ] = loadfx( "maps/zombie/fx_zmb_ash_ember_1000x1000" ); + level._effect[ "fx_zmb_ash_ember_2000x1000" ] = loadfx( "maps/zombie/fx_zmb_ash_ember_2000x1000" ); + level._effect[ "fx_zmb_ash_rising_md" ] = loadfx( "maps/zombie/fx_zmb_ash_rising_md" ); + level._effect[ "fx_zmb_ash_windy_heavy_sm" ] = loadfx( "maps/zombie/fx_zmb_ash_windy_heavy_sm" ); + level._effect[ "fx_zmb_ash_windy_heavy_md" ] = loadfx( "maps/zombie/fx_zmb_ash_windy_heavy_md" ); + level._effect[ "fx_zmb_lava_detail" ] = loadfx( "maps/zombie/fx_zmb_lava_detail" ); + level._effect[ "fx_zmb_lava_edge_100" ] = loadfx( "maps/zombie/fx_zmb_lava_edge_100" ); + level._effect[ "fx_zmb_lava_50x50_sm" ] = loadfx( "maps/zombie/fx_zmb_lava_50x50_sm" ); + level._effect[ "fx_zmb_lava_100x100" ] = loadfx( "maps/zombie/fx_zmb_lava_100x100" ); + level._effect[ "fx_zmb_lava_river" ] = loadfx( "maps/zombie/fx_zmb_lava_river" ); + level._effect[ "fx_zmb_lava_creek" ] = loadfx( "maps/zombie/fx_zmb_lava_creek" ); + level._effect[ "fx_zmb_lava_crevice_glow_50" ] = loadfx( "maps/zombie/fx_zmb_lava_crevice_glow_50" ); + level._effect[ "fx_zmb_lava_crevice_glow_100" ] = loadfx( "maps/zombie/fx_zmb_lava_crevice_glow_100" ); + level._effect[ "fx_zmb_lava_crevice_smoke_100" ] = loadfx( "maps/zombie/fx_zmb_lava_crevice_smoke_100" ); + level._effect[ "fx_zmb_lava_smoke_tall" ] = loadfx( "maps/zombie/fx_zmb_lava_smoke_tall" ); + level._effect[ "fx_zmb_lava_smoke_pit" ] = loadfx( "maps/zombie/fx_zmb_lava_smoke_pit" ); + level._effect[ "fx_zmb_tranzit_bowling_sign_fog" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bowling_sign_fog" ); + level._effect[ "fx_zmb_tranzit_lava_distort" ] = loadfx( "maps/zombie/fx_zmb_tranzit_lava_distort" ); + level._effect[ "fx_zmb_tranzit_lava_distort_sm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_lava_distort_sm" ); + level._effect[ "fx_zmb_tranzit_lava_distort_detail" ] = loadfx( "maps/zombie/fx_zmb_tranzit_lava_distort_detail" ); + level._effect[ "fx_zmb_tranzit_fire_med" ] = loadfx( "maps/zombie/fx_zmb_tranzit_fire_med" ); + level._effect[ "fx_zmb_tranzit_fire_lrg" ] = loadfx( "maps/zombie/fx_zmb_tranzit_fire_lrg" ); + level._effect[ "fx_zmb_tranzit_smk_column_lrg" ] = loadfx( "maps/zombie/fx_zmb_tranzit_smk_column_lrg" ); + level._effect[ "fx_zmb_papers_windy_slow" ] = loadfx( "maps/zombie/fx_zmb_papers_windy_slow" ); + level._effect[ "fx_zmb_tranzit_god_ray_short_warm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_short_warm" ); + level._effect[ "fx_zmb_tranzit_god_ray_vault" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_vault" ); + level._effect[ "fx_zmb_tranzit_key_glint" ] = loadfx( "maps/zombie/fx_zmb_tranzit_key_glint" ); + level._effect[ "fx_zmb_tranzit_god_ray_interior_med" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_interior_med" ); + level._effect[ "fx_zmb_tranzit_god_ray_interior_long" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_interior_long" ); + level._effect[ "fx_zmb_tranzit_god_ray_depot_cool" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_depot_cool" ); + level._effect[ "fx_zmb_tranzit_god_ray_depot_warm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_depot_warm" ); + level._effect[ "fx_zmb_tranzit_god_ray_tunnel_warm" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_tunnel_warm" ); + level._effect[ "fx_zmb_tranzit_god_ray_pwr_station" ] = loadfx( "maps/zombie/fx_zmb_tranzit_god_ray_pwr_station" ); + level._effect[ "fx_zmb_tranzit_light_safety" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_safety" ); + level._effect[ "fx_zmb_tranzit_light_safety_off" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_safety_off" ); + level._effect[ "fx_zmb_tranzit_light_safety_max" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_safety_max" ); + level._effect[ "fx_zmb_tranzit_light_safety_ric" ] = loadfx( "maps/zombie/fx_zmb_tranzit_light_safety_ric" ); + level._effect[ "fx_zmb_tranzit_bridge_dest" ] = loadfx( "maps/zombie/fx_zmb_tranzit_bridge_dest" ); + level._effect[ "fx_zmb_tranzit_power_pulse" ] = loadfx( "maps/zombie/fx_zmb_tranzit_power_pulse" ); + level._effect[ "fx_zmb_tranzit_power_on" ] = loadfx( "maps/zombie/fx_zmb_tranzit_power_on" ); + level._effect[ "fx_zmb_tranzit_power_rising" ] = loadfx( "maps/zombie/fx_zmb_tranzit_power_rising" ); + level._effect[ "fx_zmb_avog_storm" ] = loadfx( "maps/zombie/fx_zmb_avog_storm" ); + level._effect[ "fx_zmb_avog_storm_low" ] = loadfx( "maps/zombie/fx_zmb_avog_storm_low" ); + level._effect[ "glass_impact" ] = loadfx( "maps/zombie/fx_zmb_tranzit_window_dest_lg" ); + level._effect[ "fx_zmb_tranzit_spark_blue_lg_os" ] = loadfx( "maps/zombie/fx_zmb_tranzit_spark_blue_lg_os" ); + level._effect[ "spawn_cloud" ] = loadfx( "maps/zombie/fx_zmb_race_zombie_spawn_cloud" ); +} diff --git a/zm_transit_patch/maps/mp/zm_transit_gamemodes.gsc b/zm_transit_patch/maps/mp/zm_transit_gamemodes.gsc new file mode 100644 index 0000000..8a2e522 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_gamemodes.gsc @@ -0,0 +1,21 @@ +#include maps/mp/zm_transit; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + add_map_gamemode( "zclassic", ::maps/mp/zm_transit::zclassic_preinit, undefined, undefined ); + add_map_gamemode( "zgrief", ::maps/mp/zm_transit::zgrief_preinit, undefined, undefined ); + add_map_gamemode( "zstandard", ::maps/mp/zm_transit::zstandard_preinit, undefined, undefined ); + add_map_location_gamemode( "zclassic", "transit", ::maps/mp/zm_transit_classic::precache, ::maps/mp/zm_transit_classic::main ); + add_map_location_gamemode( "zstandard", "transit", ::maps/mp/zm_transit_standard_station::precache, ::maps/mp/zm_transit_standard_station::main ); + add_map_location_gamemode( "zstandard", "farm", ::maps/mp/zm_transit_standard_farm::precache, ::maps/mp/zm_transit_standard_farm::main ); + add_map_location_gamemode( "zstandard", "town", ::maps/mp/zm_transit_standard_town::precache, ::maps/mp/zm_transit_standard_town::main ); + add_map_location_gamemode( "zgrief", "transit", ::maps/mp/zm_transit_grief_station::precache, ::maps/mp/zm_transit_grief_station::main ); + add_map_location_gamemode( "zgrief", "farm", ::maps/mp/zm_transit_grief_farm::precache, ::maps/mp/zm_transit_grief_farm::main ); + add_map_location_gamemode( "zgrief", "town", ::maps/mp/zm_transit_grief_town::precache, ::maps/mp/zm_transit_grief_town::main ); +} diff --git a/zm_transit_patch/maps/mp/zm_transit_grief_farm.gsc b/zm_transit_patch/maps/mp/zm_transit_grief_farm.gsc new file mode 100644 index 0000000..f95017b --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_grief_farm.gsc @@ -0,0 +1,98 @@ +#include maps/mp/gametypes_zm/zmeat; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ +} + +farm_treasure_chest_init() +{ + chest1 = getstruct( "farm_chest", "script_noteworthy" ); + level.chests = []; + level.chests[ level.chests.size ] = chest1; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "farm_chest" ); +} + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "farm" ); + init_standard_farm(); + farm_treasure_chest_init(); + level.enemy_location_override_func = ::enemy_location_override; + flag_wait( "initial_blackscreen_passed" ); + level thread maps/mp/zombies/_zm_zonemgr::enable_zone( "zone_far_ext" ); + level thread maps/mp/zombies/_zm_zonemgr::enable_zone( "zone_brn" ); + maps/mp/zombies/_zm_game_module::turn_power_on_and_open_doors(); + flag_wait( "start_zombie_round_logic" ); + wait 1; + level notify( "revive_on" ); + wait_network_frame(); + level notify( "doubletap_on" ); + wait_network_frame(); + level notify( "juggernog_on" ); + wait_network_frame(); + level notify( "sleight_on" ); + wait_network_frame(); +/# + level thread maps/mp/gametypes_zm/zmeat::spawn_level_meat_manager(); +#/ +} + +init_standard_farm() +{ + maps/mp/zombies/_zm_game_module::set_current_game_module( level.game_module_standard_index ); + ents = getentarray(); + _a81 = ents; + _k81 = getFirstArrayKey( _a81 ); + while ( isDefined( _k81 ) ) + { + ent = _a81[ _k81 ]; + if ( isDefined( ent.script_flag ) && ent.script_flag == "OnFarm_enter" ) + { + ent delete(); + } + else + { + if ( isDefined( ent.script_parameters ) ) + { + tokens = strtok( ent.script_parameters, " " ); + remove = 0; + _a92 = tokens; + _k92 = getFirstArrayKey( _a92 ); + while ( isDefined( _k92 ) ) + { + token = _a92[ _k92 ]; + if ( token == "standard_remove" ) + { + remove = 1; + } + _k92 = getNextArrayKey( _a92, _k92 ); + } + if ( remove ) + { + ent delete(); + } + } + } + _k81 = getNextArrayKey( _a81, _k81 ); + } +} + +enemy_location_override( zombie, enemy ) +{ + location = enemy.origin; + if ( is_true( self.reroute ) ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + return location; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_grief_station.gsc b/zm_transit_patch/maps/mp/zm_transit_grief_station.gsc new file mode 100644 index 0000000..54dbbf7 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_grief_station.gsc @@ -0,0 +1,59 @@ +#include maps/mp/gametypes_zm/zmeat; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ + precachemodel( "zm_collision_transit_busdepot_survival" ); +} + +station_treasure_chest_init() +{ + chest1 = getstruct( "depot_chest", "script_noteworthy" ); + level.chests = []; + level.chests[ level.chests.size ] = chest1; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "depot_chest" ); +} + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "station" ); + station_treasure_chest_init(); + level.enemy_location_override_func = ::enemy_location_override; + collision = spawn( "script_model", ( -6896, 4744, 0 ), 1 ); + collision setmodel( "zm_collision_transit_busdepot_survival" ); + collision disconnectpaths(); + flag_wait( "initial_blackscreen_passed" ); + nodes = getnodearray( "classic_only_traversal", "targetname" ); + _a44 = nodes; + _k44 = getFirstArrayKey( _a44 ); + while ( isDefined( _k44 ) ) + { + node = _a44[ _k44 ]; + unlink_nodes( node, getnode( node.target, "targetname" ) ); + _k44 = getNextArrayKey( _a44, _k44 ); + } + level thread maps/mp/zombies/_zm_perks::perk_machine_removal( "specialty_quickrevive", "p_glo_tools_chest_tall" ); + maps/mp/zombies/_zm_game_module::turn_power_on_and_open_doors(); +/# + level thread maps/mp/gametypes_zm/zmeat::spawn_level_meat_manager(); +#/ +} + +enemy_location_override( zombie, enemy ) +{ + location = enemy.origin; + if ( is_true( self.reroute ) ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + return location; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_grief_town.gsc b/zm_transit_patch/maps/mp/zm_transit_grief_town.gsc new file mode 100644 index 0000000..3f5f08b --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_grief_town.gsc @@ -0,0 +1,66 @@ +#include maps/mp/gametypes_zm/zmeat; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_race_utility; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ + precachemodel( "zm_collision_transit_town_survival" ); +} + +town_treasure_chest_init() +{ + chest1 = getstruct( "town_chest", "script_noteworthy" ); + chest2 = getstruct( "town_chest_2", "script_noteworthy" ); + setdvar( "disable_rope", 1 ); + setdvar( "disableLookAtEntityLogic", 1 ); + level.chests = []; + level.chests[ level.chests.size ] = chest1; + level.chests[ level.chests.size ] = chest2; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "town_chest" ); +} + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "town" ); + town_treasure_chest_init(); + level.enemy_location_override_func = ::enemy_location_override; + collision = spawn( "script_model", ( 1363, 471, 0 ), 1 ); + collision setmodel( "zm_collision_transit_town_survival" ); + collision disconnectpaths(); + flag_wait( "initial_blackscreen_passed" ); + maps/mp/zombies/_zm_game_module::turn_power_on_and_open_doors(); + flag_wait( "start_zombie_round_logic" ); + wait 1; + level notify( "revive_on" ); + wait_network_frame(); + level notify( "doubletap_on" ); + wait_network_frame(); + level notify( "marathon_on" ); + wait_network_frame(); + level notify( "juggernog_on" ); + wait_network_frame(); + level notify( "sleight_on" ); + wait_network_frame(); + level notify( "Pack_A_Punch_on" ); +/# + level thread maps/mp/gametypes_zm/zmeat::spawn_level_meat_manager(); +#/ +} + +enemy_location_override( zombie, enemy ) +{ + location = enemy.origin; + if ( is_true( self.reroute ) ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + return location; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_lava.gsc b/zm_transit_patch/maps/mp/zm_transit_lava.gsc new file mode 100644 index 0000000..4b5bb0f --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_lava.gsc @@ -0,0 +1,384 @@ +#include maps/mp/animscripts/zm_death; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +object_touching_lava() +{ + if ( !isDefined( level.lava ) ) + { + level.lava = getentarray( "lava_damage", "targetname" ); + } + if ( !isDefined( level.lava ) || level.lava.size < 1 ) + { + return 0; + } + if ( isDefined( self.lasttouching ) && self istouching( self.lasttouching ) ) + { + return 1; + } + i = 0; + while ( i < level.lava.size ) + { + if ( distancesquared( self.origin, level.lava[ i ].origin ) < 2250000 ) + { + if ( isDefined( level.lava[ i ].target ) ) + { + if ( self istouching( level.lava[ i ].volume ) ) + { + if ( isDefined( level.lava[ i ].script_float ) && level.lava[ i ].script_float <= 0,1 ) + { + return 0; + } + self.lasttouching = level.lava[ i ].volume; + return 1; + } + } + else + { + if ( self istouching( level.lava[ i ] ) ) + { + self.lasttouching = level.lava[ i ]; + return 1; + } + } + } + i++; + } + self.lasttouching = undefined; + return 0; +} + +lava_damage_init() +{ + lava = getentarray( "lava_damage", "targetname" ); + if ( !isDefined( lava ) ) + { + return; + } + array_thread( lava, ::lava_damage_think ); +} + +lava_damage_think() +{ + self._trap_type = ""; + if ( isDefined( self.script_noteworthy ) ) + { + self._trap_type = self.script_noteworthy; + } + if ( isDefined( self.target ) ) + { + self.volume = getent( self.target, "targetname" ); +/# + assert( isDefined( self.volume ), "No volume found for lava target " + self.target ); +#/ + } + while ( 1 ) + { + self waittill( "trigger", ent ); + if ( isDefined( ent.ignore_lava_damage ) && ent.ignore_lava_damage ) + { + continue; + } + while ( isDefined( ent.is_burning ) ) + { + continue; + } + if ( isDefined( self.target ) && !ent istouching( self.volume ) ) + { + continue; + } + if ( isplayer( ent ) ) + { + switch( self._trap_type ) + { + case "fire": + default: + if ( !isDefined( self.script_float ) || self.script_float >= 0,1 ) + { + ent thread player_lava_damage( self ); + } + break; + } + break; + continue; + } + else if ( !isDefined( ent.marked_for_death ) ) + { + switch( self._trap_type ) + { + case "fire": + default: + if ( !isDefined( self.script_float ) || self.script_float >= 0,1 ) + { + ent thread zombie_lava_damage( self ); + } + break; + break; + } + } +} +} + +player_lava_damage( trig ) +{ + self endon( "zombified" ); + self endon( "death" ); + self endon( "disconnect" ); + max_dmg = 15; + min_dmg = 5; + burn_time = 1; + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + return; + } + self thread player_stop_burning(); + if ( isDefined( trig.script_float ) ) + { + max_dmg *= trig.script_float; + min_dmg *= trig.script_float; + burn_time *= trig.script_float; + if ( burn_time >= 1,5 ) + { + burn_time = 1,5; + } + } + if ( !isDefined( self.is_burning ) && is_player_valid( self ) ) + { + self.is_burning = 1; + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_transit_burn", self, burn_time, level.zm_transit_burn_max_duration ); + self notify( "burned" ); + if ( isDefined( trig.script_float ) && trig.script_float >= 0,1 ) + { + self thread player_burning_fx(); + } + if ( !self hasperk( "specialty_armorvest" ) || ( self.health - 100 ) < 1 ) + { + radiusdamage( self.origin, 10, max_dmg, min_dmg ); + wait 0,5; + self.is_burning = undefined; + return; + } + else + { + if ( self hasperk( "specialty_armorvest" ) ) + { + self dodamage( 15, self.origin ); + } + else + { + self dodamage( 1, self.origin ); + } + wait 0,5; + self.is_burning = undefined; + } + } +} + +player_stop_burning() +{ + self notify( "player_stop_burning" ); + self endon( "player_stop_burning" ); + self endon( "death_or_disconnect" ); + self waittill( "zombified" ); + self notify( "stop_flame_damage" ); + maps/mp/_visionset_mgr::vsmgr_deactivate( "overlay", "zm_transit_burn", self ); +} + +zombie_burning_fx() +{ + self endon( "death" ); + if ( isDefined( self.is_on_fire ) && self.is_on_fire ) + { + return; + } + self.is_on_fire = 1; + self thread maps/mp/animscripts/zm_death::on_fire_timeout(); + if ( isDefined( level._effect ) && isDefined( level._effect[ "lava_burning" ] ) ) + { + if ( !self.isdog ) + { + playfxontag( level._effect[ "lava_burning" ], self, "J_SpineLower" ); + self thread zombie_burning_audio(); + } + } + if ( isDefined( level._effect ) && isDefined( level._effect[ "character_fire_death_sm" ] ) ) + { + wait 1; + if ( randomint( 2 ) > 1 ) + { + tagarray = []; + tagarray[ 0 ] = "J_Elbow_LE"; + tagarray[ 1 ] = "J_Elbow_RI"; + tagarray[ 2 ] = "J_Knee_RI"; + tagarray[ 3 ] = "J_Knee_LE"; + tagarray = randomize_array( tagarray ); + playfxontag( level._effect[ "character_fire_death_sm" ], self, tagarray[ 0 ] ); + return; + } + else + { + 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 = randomize_array( tagarray ); + playfxontag( level._effect[ "character_fire_death_sm" ], self, tagarray[ 0 ] ); + } + } +} + +zombie_burning_audio() +{ + self playloopsound( "zmb_fire_loop" ); + self waittill_either( "stop_flame_damage", "death" ); + if ( isDefined( self ) && isalive( self ) ) + { + self stoploopsound( 0,25 ); + } +} + +player_burning_fx() +{ + self endon( "death" ); + if ( isDefined( self.is_on_fire ) && self.is_on_fire ) + { + return; + } + if ( isDefined( self.no_burning_sfx ) && !self.no_burning_sfx ) + { + self thread player_burning_audio(); + } + self.is_on_fire = 1; + self thread maps/mp/animscripts/zm_death::on_fire_timeout(); + if ( isDefined( level._effect ) && isDefined( level._effect[ "character_fire_death_sm" ] ) ) + { + playfxontag( level._effect[ "character_fire_death_sm" ], self, "J_SpineLower" ); + } +} + +player_burning_audio() +{ + fire_ent = spawn( "script_model", self.origin ); + wait_network_frame(); + fire_ent linkto( self ); + fire_ent playloopsound( "evt_plr_fire_loop" ); + self waittill_any( "stop_flame_damage", "stop_flame_sounds", "death", "discoonect" ); + fire_ent delete(); +} + +zombie_lava_damage( trap ) +{ + self endon( "death" ); + zombie_dmg = 1; + if ( isDefined( self.script_float ) ) + { + zombie_dmg *= self.script_float; + } + switch( trap._trap_type ) + { + case "fire": + default: + if ( isDefined( self.animname ) || !isDefined( self.is_on_fire ) && !self.is_on_fire ) + { + if ( level.burning_zombies.size < 6 && zombie_dmg >= 1 ) + { + level.burning_zombies[ level.burning_zombies.size ] = self; + self playsound( "ignite" ); + self thread zombie_burning_fx(); + self thread zombie_burning_watch(); + self thread zombie_burning_dmg(); + self thread zombie_exploding_death( zombie_dmg, trap ); + wait randomfloat( 1,25 ); + } + } + if ( self.health > ( level.zombie_health / 2 ) && self.health > zombie_dmg ) + { + self dodamage( zombie_dmg, self.origin, trap ); + } + break; + } +} + +zombie_burning_watch() +{ + self waittill_any( "stop_flame_damage", "death" ); + arrayremovevalue( level.burning_zombies, self ); +} + +zombie_exploding_death( zombie_dmg, trap ) +{ + self endon( "stop_flame_damage" ); + if ( isDefined( self.isdog ) && self.isdog && isDefined( self.a.nodeath ) ) + { + return; + } + while ( isDefined( self ) && self.health >= zombie_dmg && isDefined( self.is_on_fire ) && self.is_on_fire ) + { + wait 0,5; + } + if ( isDefined( self ) && isDefined( self.is_on_fire ) && self.is_on_fire && isDefined( self.damageweapon ) && self.damageweapon != "tazer_knuckles_zm" || self.damageweapon == "jetgun_zm" && isDefined( self.knuckles_extinguish_flames ) && self.knuckles_extinguish_flames ) + { + return; + } + tag = "J_SpineLower"; + if ( isDefined( self.animname ) && self.animname == "zombie_dog" ) + { + tag = "tag_origin"; + } + if ( is_mature() ) + { + if ( isDefined( level._effect[ "zomb_gib" ] ) ) + { + playfx( level._effect[ "zomb_gib" ], self gettagorigin( tag ) ); + } + } + else + { + if ( isDefined( level._effect[ "spawn_cloud" ] ) ) + { + playfx( level._effect[ "spawn_cloud" ], self gettagorigin( tag ) ); + } + } + self radiusdamage( self.origin, 128, 30, 15, undefined, "MOD_EXPLOSIVE" ); + self ghost(); + if ( isDefined( self.isdog ) && self.isdog ) + { + self hide(); + } + else + { + self delay_thread( 1, ::self_delete ); + } +} + +zombie_burning_dmg() +{ + self endon( "death" ); + damageradius = 25; + damage = 2; + while ( isDefined( self.is_on_fire ) && self.is_on_fire ) + { + eyeorigin = self geteye(); + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( is_player_valid( players[ i ] ) ) + { + playereye = players[ i ] geteye(); + if ( distancesquared( eyeorigin, playereye ) < ( damageradius * damageradius ) ) + { + players[ i ] dodamage( damage, self.origin, self ); + players[ i ] notify( "burned" ); + } + } + i++; + } + wait 1; + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_openings.gsc b/zm_transit_patch/maps/mp/zm_transit_openings.gsc new file mode 100644 index 0000000..7bc575d --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_openings.gsc @@ -0,0 +1,2500 @@ +#include maps/mp/zm_transit_cling; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/animscripts/zm_run; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zm_transit_bus; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/_utility; +#include common_scripts/utility; + +main() +{ + self _businittags(); + self _setupnumattachtable(); + self.openings = []; + x = 1; + while ( x <= 10 ) + { + script_noteworthy = undefined; + switch( x ) + { + case 10: + script_noteworthy = "front"; + break; + case 11: + case 12: + script_noteworthy = "door"; + break; + } + self busaddopening( "tag_entry_point" + x, script_noteworthy ); + x++; + } + self bussetupladder(); + self bussetuproofopening(); + self businitmantle(); + self businitrightandleft(); +} + +busaddopening( tag_name, script_noteworthy ) +{ + index = self.openings.size; + self.openings[ index ] = spawnstruct(); + opening = self.openings[ index ]; + opening.name = script_noteworthy; + opening.enabled = 1; + opening.zombie = undefined; + opening.boards = []; + opening.boardsnum = 0; + opening.blockertrigger = undefined; + opening.zombietrigger = undefined; + opening.rebuildtrigger = undefined; + opening.tagname = tag_name; + opening.bindtag = _busfindclosesttag( self gettagorigin( tag_name ) ); +/# + assert( isDefined( opening.bindtag ) ); +#/ + opening.jumptag = _busgetjumptagfrombindtag( opening.bindtag ); + opening.jumpent = level.the_bus; + opening.roofjoint = _busgetroofjointfrombindtag( opening.bindtag ); + opening.origin = level.the_bus gettagorigin( opening.bindtag ); + opening.angles = self gettagangles( opening.bindtag ); + targets = getentarray( tag_name, "targetname" ); + if ( !isDefined( targets ) ) + { +/# + assert( 0 ); +#/ + return; + } + if ( !is_classic() ) + { + i = 0; + while ( i < targets.size ) + { + if ( targets[ i ] iszbarrier() ) + { + targets[ i ] delete(); + } + i++; + } + return; + } + i = 0; + while ( i < targets.size ) + { + target = targets[ i ]; + if ( target iszbarrier() ) + { + hasbarriers = 1; + if ( isDefined( script_noteworthy ) && script_noteworthy == "front" ) + { + hasbarriers = 0; + } + opening.zbarrier = target; + opening.zbarrier setmovingplatformenabled( 1 ); + while ( hasbarriers ) + { + opening.zbarrier.chunk_health = []; + opening.zbarrier setzbarriercolmodel( "p6_anim_zm_barricade_board_bus_collision" ); + maps/mp/zombies/_zm_powerups::register_carpenter_node( opening, ::post_carpenter_callback ); + j = 0; + while ( j < opening.zbarrier getnumzbarrierpieces() ) + { + opening.zbarrier.chunk_health[ j ] = 0; + j++; + } + } + target.origin = level.the_bus gettagorigin( opening.bindtag ); + } + else if ( target.script_noteworthy == "blocker" ) + { + target delete(); + i++; + continue; + } + else if ( target.script_noteworthy == "rebuild" ) + { + opening.rebuildtrigger = target; + opening.rebuildtrigger enablelinkto(); + opening.rebuildtrigger linkto( self ); + opening.rebuildtrigger setcursorhint( "HINT_NOICON" ); + opening.rebuildtrigger set_hint_string( self, "default_reward_barrier_piece" ); + opening.rebuildtrigger triggerignoreteam(); + opening.rebuildtrigger setinvisibletoall(); + opening.rebuildtrigger setmovingplatformenabled( 1 ); + self thread busopeningrebuildthink( opening ); + i++; + continue; + } + else if ( target.script_noteworthy == "zombie" ) + { + opening.zombietrigger = target; + opening.zombietrigger enablelinkto(); + opening.zombietrigger linkto( self ); + opening.zombietrigger setmovingplatformenabled( 1 ); + opening.zombietrigger setteamfortrigger( level.zombie_team ); + self thread busopeningzombiethink( opening ); + } + target linkto( self, "", self worldtolocalcoords( target.origin ), target.angles - self.angles ); + i++; + } + if ( isDefined( opening.zbarrier ) ) + { + opening blocker_attack_spots(); + } + opening notify( "opening_init_complete" ); +/# + if ( opening.boardsnum != 0 ) + { + assert( opening.boardsnum == opening.boards.size ); + } +#/ +} + +post_carpenter_callback() +{ + if ( isDefined( self.rebuildtrigger ) ) + { + self.rebuildtrigger setinvisibletoall(); + } +} + +businitmantle() +{ + mantlebrush = getentarray( "window_mantle", "targetname" ); + while ( isDefined( mantlebrush ) && mantlebrush.size > 0 ) + { + i = 0; + while ( i < mantlebrush.size ) + { + mantlebrush[ i ] delete(); + i++; + } + } +} + +busattachjumpent( ent, opening ) +{ + jump_origin = self gettagorigin( opening.jumptag ); + jump_angles = self gettagangles( opening.jumptag ); + ent.origin = jump_origin; + ent.angles = jump_angles; + ent linkto( self, "", self worldtolocalcoords( ent.origin ), ent.angles - self.angles ); +} + +busopeningbyname( name ) +{ + i = 0; + while ( i < self.openings.size ) + { + opening = self.openings[ i ]; + if ( isDefined( opening.name ) && opening.name == name ) + { + return opening; + } + i++; + } + return undefined; +} + +busopeningsetenabled( name, enabled ) +{ + i = 0; + while ( i < self.openings.size ) + { + opening = self.openings[ i ]; + if ( isDefined( opening.name ) && opening.name == name ) + { + opening.enabled = enabled; + } + i++; + } +} + +_businittags() +{ + self.openingtags = []; + self.openingtags[ self.openingtags.size ] = "window_right_front_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_front_jnt"; + self.openingtags[ self.openingtags.size ] = "door_front_jnt"; + self.openingtags[ self.openingtags.size ] = "door_rear_jnt"; + self.openingtags[ self.openingtags.size ] = "window_right_1_jnt"; + self.openingtags[ self.openingtags.size ] = "window_right_2_jnt"; + self.openingtags[ self.openingtags.size ] = "window_right_3_jnt"; + self.openingtags[ self.openingtags.size ] = "window_right_4_jnt"; + self.openingtags[ self.openingtags.size ] = "window_right_rear_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_rear_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_1_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_2_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_3_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_4_jnt"; + self.openingtags[ self.openingtags.size ] = "window_left_5_jnt"; +/# + i = 0; + while ( i < self.openingtags.size ) + { + adddebugcommand( "devgui_cmd "Zombies:1/Bus:14/Window Openings:3/Select Tag:1/" + self.openingtags[ i ] + ":" + self.openingtags.size + "" "zombie_devgui attach_tag " + self.openingtags[ i ] + ""\n" ); + i++; +#/ + } +} + +_busfindclosesttag( checkpos ) +{ + closest = undefined; + closestdist = -1; +/# + assert( isDefined( self.openingtags ) ); +#/ + i = 0; + while ( i < self.openingtags.size ) + { + tag = self.openingtags[ i ]; + pos = self gettagorigin( tag ); + dist2 = distancesquared( checkpos, pos ); + if ( !isDefined( closest ) || dist2 < closestdist ) + { + closest = tag; + closestdist = dist2; + } + i++; + } + return closest; +} + +_busgetjumptagfrombindtag( tag ) +{ + jump_tag = undefined; + switch( tag ) + { + case "window_right_1_jnt": + jump_tag = "window_right_1_jmp_jnt"; + break; + case "window_right_2_jnt": + jump_tag = "window_right_2_jmp_jnt"; + break; + case "window_right_3_jnt": + jump_tag = "window_right_3_jmp_jnt"; + break; + case "window_right_4_jnt": + jump_tag = "window_right_4_jmp_jnt"; + break; + case "window_left_1_jnt": + jump_tag = "window_left_1_jmp_jnt"; + break; + case "window_left_2_jnt": + jump_tag = "window_left_2_jmp_jnt"; + break; + case "window_left_3_jnt": + jump_tag = "window_left_3_jmp_jnt"; + break; + case "window_left_4_jnt": + jump_tag = "window_left_4_jmp_jnt"; + break; + case "window_left_5_jnt": + jump_tag = "window_left_5_jmp_jnt"; + break; + case "window_right_rear_jnt": + jump_tag = "window_right_rear_jmp_jnt"; + break; + case "window_left_rear_jnt": + jump_tag = "window_left_rear_jmp_jnt"; + break; + case "window_right_front_jnt": + jump_tag = "window_right_front_jmp_jnt"; + break; + case "window_left_front_jnt": + jump_tag = "window_left_front_jmp_jnt"; + break; + case "door_rear_jnt": + jump_tag = "door_rear_jmp_jnt"; + break; + case "door_front_jnt": + jump_tag = "door_front_jmp_jnt"; + break; + default: + } + return jump_tag; + } +} + +_busgetroofjointfrombindtag( tag ) +{ + roofjoint = undefined; + switch( tag ) + { + case "window_left_1_jnt": + case "window_left_front_jnt": + case "window_right_1_jnt": + case "window_right_front_jnt": + roofjoint = "window_roof_1_jnt"; + break; + case "window_left_2_jnt": + case "window_left_3_jnt": + case "window_left_4_jnt": + case "window_left_5_jnt": + case "window_left_rear_jnt": + case "window_right_2_jnt": + case "window_right_3_jnt": + case "window_right_4_jnt": + case "window_right_rear_jnt": + roofjoint = "window_roof_2_jnt"; + default: + break; + } + return roofjoint; + } +} + +_setupnumattachtable() +{ + level.numattachtable = []; + level.numattachtable[ 0 ] = -1; + level.numattachtable[ 1 ] = 6; + level.numattachtable[ 2 ] = 8; + level.numattachtable[ 3 ] = 10; + level.numattachtable[ 4 ] = -1; +} + +busgetopeningfortag( tagname ) +{ + i = 0; + while ( i < self.openings.size ) + { + if ( self.openings[ i ].bindtag == tagname ) + { + return self.openings[ i ]; + } + i++; + } + return undefined; +} + +zombieanimnotetrackthink( notifystring, chunk, node ) +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( notifystring, notetrack ); + if ( notetrack == "end" ) + { + return; + continue; + } + else if ( notetrack == "board" || notetrack == "destroy_piece" ) + { + node.zbarrier setzbarrierpiecestate( chunk, "opening" ); + if ( isDefined( node.rebuildtrigger ) ) + { + node.rebuildtrigger setvisibletoall(); + } + continue; + } + else + { + while ( notetrack == "fire" ) + { + attackplayers = self zombiegetplayerstoattack(); + while ( attackplayers.size ) + { + i = 0; + while ( i < attackplayers.size ) + { + attackplayers[ i ] dodamage( self.meleedamage, self.origin, self, self, "none", "MOD_MELEE" ); + i++; + } + } + } + } + } +} + +busopeningblockerthink( opening ) +{ + self endon( "intermission" ); + while ( 1 ) + { + opening.blockertrigger waittill( "trigger", player ); + while ( isDefined( opening.zombie ) ) + { + continue; + } + } + self notify( "OnBlockerPlaced" ); +} + +buswatchtriggervisibility( opening ) +{ + self endon( "intermission" ); + opening waittill( "opening_init_complete" ); + if ( !isDefined( opening.zbarrier ) || opening.zbarrier getnumzbarrierpieces() < 1 ) + { + return; + } + if ( !isDefined( level.buswatchtriggervisibility_spread ) ) + { + level.buswatchtriggervisibility_spread = 0; + } + else + { + level.buswatchtriggervisibility_spread++; + wait ( 0,05 * level.buswatchtriggervisibility_spread ); + } + while ( 1 ) + { + if ( no_valid_repairable_boards( opening ) ) + { + opening.rebuildtrigger setinvisibletoall(); + } + else + { + opening.rebuildtrigger setvisibletoall(); + } + wait 1; + } +} + +busopeningrebuildthink( opening ) +{ + self endon( "intermission" ); + self thread buswatchtriggervisibility( opening ); + cost = 10; + if ( isDefined( opening.rebuildtrigger.zombie_cost ) ) + { + cost = opening.rebuildtrigger.zombie_cost; + } + while ( 1 ) + { + opening.rebuildtrigger waittill( "trigger", player ); + players = get_players(); + has_perk = player has_blocker_affecting_perk(); + while ( player_fails_blocker_repair_trigger_preamble( player, players, opening.rebuildtrigger, 0 ) ) + { + continue; + } + while ( all_chunks_intact( opening ) ) + { + continue; + } + while ( no_valid_repairable_boards( opening ) ) + { + continue; + } + chunk = get_random_destroyed_chunk( opening ); + if ( isDefined( player.pers_upgrades_awarded[ "board" ] ) ) + { + self thread replace_chunk( opening, chunk, has_perk, player.pers_upgrades_awarded[ "board" ] ); + } + opening do_post_chunk_repair_delay( has_perk ); + while ( !is_player_valid( player ) ) + { + if ( no_valid_repairable_boards( opening ) ) + { + opening.rebuildtrigger setinvisibletoall(); + } + } + player handle_post_board_repair_rewards( cost ); + if ( no_valid_repairable_boards( opening ) ) + { + opening.rebuildtrigger setinvisibletoall(); + } + } +} + +_determinejumpfromorigin( opening ) +{ + return level.the_bus gettagorigin( opening.jumptag ); +} + +_getsideofbusopeningison( opening_tag ) +{ + side = undefined; + switch( opening_tag ) + { + case "door_front_jnt": + case "door_rear_jnt": + case "window_right_1_jnt": + case "window_right_2_jnt": + case "window_right_3_jnt": + case "window_right_4_jnt": + side = "right"; + break; + case "window_left_1_jnt": + case "window_left_2_jnt": + case "window_left_3_jnt": + case "window_left_4_jnt": + case "window_left_5_jnt": + side = "left"; + break; + case "window_left_front_jnt": + case "window_right_front_jnt": + side = "front"; + break; + case "window_left_rear_jnt": + case "window_right_rear_jnt": + side = "back"; + break; + } + return side; +} + +busopeningzombiethink( opening ) +{ + self endon( "intermission" ); + if ( _isopeningdoor( opening.bindtag ) ) + { + opening.enabled = 0; + return; + } + while ( 1 ) + { + opening.zombietrigger waittill( "trigger", zombie ); + while ( zombie.isdog ) + { + continue; + } + if ( isDefined( zombie.isscreecher ) && zombie.isscreecher ) + { + continue; + } + if ( isDefined( zombie.is_avogadro ) && zombie.is_avogadro ) + { + continue; + } + while ( !isalive( zombie ) ) + { + continue; + } + while ( !opening.enabled ) + { + continue; + } + if ( _isopeningdoor( opening.bindtag ) && self.doorsclosed ) + { + continue; + } + if ( isDefined( zombie.favoriteenemy ) ) + { + enemy_on_roof = zombie.favoriteenemy.isonbusroof; + } + while ( self.ismoving && isDefined( self.disabled_by_emp ) && self.disabled_by_emp && !self.doorsclosed && !enemy_on_roof ) + { + continue; + } + monkey = undefined; + if ( isDefined( zombie.enemyoverride ) ) + { + monkey = zombie.enemyoverride[ 1 ]; + } + if ( isDefined( monkey ) && !monkey maps/mp/zm_transit_bus::entity_is_on_bus( 1 ) ) + { + continue; + } + if ( !isDefined( zombie.favoriteenemy ) || !zombie.favoriteenemy.isonbus ) + { + continue; + } + if ( isDefined( zombie.isonbus ) && zombie.isonbus ) + { + continue; + } + while ( isDefined( zombie.opening ) ) + { + continue; + } + while ( isDefined( opening.zombie ) ) + { + continue; + } + if ( isDefined( zombie.is_inert ) && zombie.is_inert ) + { + continue; + } + if ( isDefined( zombie.cannotattachtobus ) && zombie.cannotattachtobus ) + { + continue; + } + while ( !level.the_bus.ismoving ) + { + jump_origin = _determinejumpfromorigin( opening ); + distance_from_jump_origin2 = distance2dsquared( jump_origin, zombie.origin ); + while ( distance_from_jump_origin2 > 256 ) + { + continue; + } + } + if ( isDefined( zombie.dismount_start ) && zombie.dismount_start ) + { + continue; + } + zombie thread zombieattachtobus( self, opening ); + } +} + +_buscanzombieattach( zombie ) +{ + currentlyattached = 0; + i = 0; + while ( i < self.openings.size ) + { + if ( isDefined( self.openings[ i ].zombie ) ) + { + currentlyattached++; + } + i++; + } + players = get_players(); + maxattach = level.numattachtable[ players.size ]; + if ( maxattach < 0 ) + { + return currentlyattached < maxattach; + } +} + +zombieplayattachedanim( animname ) +{ + self endon( "death" ); + anim_index = self getanimsubstatefromasd( "zm_bus_attached", animname ); + animationid = self getanimfromasd( "zm_bus_attached", anim_index ); + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + start_origin = getstartorigin( tag_origin, tag_angles, animationid ); + start_angles = getstartangles( tag_origin, tag_angles, animationid ); + self animscripted( start_origin, start_angles, "zm_bus_attached", anim_index ); + self zombieanimnotetrackthink( "bus_attached_anim" ); +} + +debugline( frompoint, color, durationframes ) +{ +/# + i = 0; + while ( i < durationframes ) + { + line( frompoint, ( frompoint[ 0 ], frompoint[ 1 ], frompoint[ 2 ] + 50 ), color ); + wait 0,05; + i++; +#/ + } +} + +debugbox( frompoint, color, durationframes ) +{ +/# + i = 0; + while ( i < durationframes ) + { + box( frompoint, ( 0, -1, 0 ), ( 0, -1, 0 ), 0, color ); + wait 0,05; + i++; +#/ + } +} + +_isopeningdoor( opening_tag ) +{ + is_door = 0; + switch( opening_tag ) + { + case "door_front_jnt": + case "door_rear_jnt": + is_door = 1; + break; + default: + } + return is_door; + } +} + +busexitthink( trigger ) +{ + while ( 1 ) + { + trigger waittill( "trigger", zombie ); + if ( isDefined( zombie.is_inert ) && zombie.is_inert ) + { + continue; + } + if ( isDefined( zombie.walk_to_exit ) && !zombie.walk_to_exit ) + { + continue; + } + if ( isDefined( zombie.exiting_window ) && zombie.exiting_window ) + { + continue; + } + going_to_roof = 0; + while ( isDefined( zombie.favoriteenemy ) && zombie.favoriteenemy.isonbusroof == 1 ) + { + going_to_roof = 1; + while ( trigger.substate == 2 ) + { + continue; + } + } + while ( !going_to_roof && isDefined( level.the_bus.doorsclosed ) && !level.the_bus.doorsclosed && zombie.ai_state != "zombieWindowToRoof" ) + { + continue; + } + zombie thread zombieexitwindow( self, trigger, going_to_roof ); + } +} + +zombieexitwindow( bus, trigger, going_to_roof ) +{ + self endon( "death" ); + self.ai_state = "zombieExitWindow"; + self.inert_delay = ::zombieexitwindowdelay; + self.exiting_window = 1; + self linkto( bus, trigger.tag ); + tag_origin = bus gettagorigin( trigger.tag ); + tag_angles = bus gettagangles( trigger.tag ); + exit_anim = "zm_window_exit"; + if ( going_to_roof ) + { + exit_anim = "zm_bus_window2roof"; + } + animstate = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( exit_anim ); + self animscripted( tag_origin, tag_angles, animstate, trigger.substate ); + maps/mp/animscripts/zm_shared::donotetracks( "window_exit_anim" ); + self.exiting_window = undefined; + self.walk_to_exit = undefined; + self unlink(); + self setgoalpos( self.origin ); + self.inert_delay = undefined; + if ( going_to_roof ) + { + return; + } + self animmode( "normal" ); + self orientmode( "face enemy" ); + self.forcemovementscriptstate = 0; + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +zombieexitwindowdelay() +{ + self endon( "death" ); + while ( isDefined( self.exiting_window ) && self.exiting_window ) + { + wait 0,1; + } + while ( 1 ) + { + if ( self.ai_state == "find_flesh" ) + { + break; + } + else + { + wait 0,1; + } + } + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self.inert_delay = undefined; +} + +teleportthreadex( verticaloffset, delay, frames ) +{ + amount = verticaloffset / frames; + if ( amount > 10 ) + { + amount = 10; + } + else + { + if ( amount < -10 ) + { + amount = -10; + } + } + offset = ( 0, 0, amount ); + i = 0; + while ( i < frames ) + { + self teleport( self.origin + offset ); + wait 0,05; + i++; + } +} + +zombieopeningdelay() +{ + self endon( "death" ); + self maps/mp/zombies/_zm_spawner::zombie_history( "opening delay detach " + getTime() ); + while ( isDefined( self.jumpingtowindow ) && self.jumpingtowindow ) + { + while ( 1 ) + { + if ( isDefined( self.jumpingtowindow ) && !self.jumpingtowindow ) + { + break; + } + else + { + wait 0,1; + } + } + } + self zombiedetachfrombus( self.left_or_right ); + while ( 1 ) + { + if ( self.ai_state == "find_flesh" ) + { + break; + } + else + { + wait 0,1; + } + } + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self.inert_delay = undefined; +} + +zombieattachtobus( thebus, opening, removeafterdone ) +{ + self endon( "death" ); + self endon( "removed" ); + self endon( "sonicBoom" ); + level endon( "intermission" ); + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self endon( "detach_on_window" ); + self endon( "exploding" ); + self.ai_state = "zombieAttachToBus"; + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieAttachToBus " + getTime() ); + opening.zombie = self; + self.dont_throw_gib = 1; + self.forcemovementscriptstate = 1; + self.opening = opening; + self.left_or_right = self zombieattachleftorright( thebus ); + self.attachent = level.the_bus; + self.attachtag = self.opening.bindtag; + self linkto( self.attachent, self.attachtag ); + from_front = 0; + from_rear = 0; + self.inert_delay = ::zombieopeningdelay; + if ( _isopeningdoor( opening.bindtag ) ) + { + self animscripted( self.origin, self.angles, "zm_jump_on_bus", 0 ); + if ( opening.bindtag == "door_front_jnt" ) + { + from_front = 1; + } + else + { + from_rear = 1; + } + } + else + { + self.jumpingtowindow = 1; + asd_name = "zm_zbarrier_jump_on_bus"; + side = _getsideofbusopeningison( opening.bindtag ); + if ( isDefined( side ) && side == "front" ) + { + asd_name = "zm_zbarrier_jump_on_bus_front"; + } + animstate = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( asd_name ); + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + self animmode( "noclip" ); + self animscripted( tag_origin, tag_angles, animstate, "jump_window" + self.left_or_right ); + } + self zombieanimnotetrackthink( "jump_on_bus_anim" ); + self animmode( "gravity" ); + self.jumpingtowindow = 0; + if ( isDefined( self.a.gib_ref ) || self.a.gib_ref == "left_arm" && self.a.gib_ref == "right_arm" ) + { + self dodamage( self.health + 666, self.origin ); + self startragdoll(); + self launchragdoll( ( 0, -1, 0 ) ); + opening.zombie = undefined; + } + if ( 1 ) + { + hitpos = self.attachent gettagorigin( self.attachtag ); + hitposinbus = pointonsegmentnearesttopoint( thebus.frontworld, thebus.backworld, hitpos ); + hitdir = vectornormalize( hitposinbus - hitpos ); + hitforce = vectorScale( hitdir, 100 ); + hitpos += vectorScale( ( 0, -1, 0 ), 50 ); + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), hitpos, 150 ); + play_sound_at_pos( "grab_metal_bar", hitpos ); + } + if ( self zombiecanjumponroof( opening ) ) + { + self zombiejumponroof( thebus, opening, removeafterdone, self.left_or_right ); + self zombiesetnexttimetojumponroof(); + self maps/mp/animscripts/zm_run::needsupdate(); + if ( !self.isdog ) + { + self maps/mp/animscripts/zm_run::moverun(); + } + } + else + { + for ( ;; ) + { + while ( 1 ) + { + if ( !isDefined( opening.zbarrier ) || maps/mp/zombies/_zm_spawner::get_attack_spot( opening ) ) + { + break; + } + else + { +/# + println( "Zombie failed to get bus attack spot" ); +#/ + wait 0,5; + } + } + } + while ( !all_chunks_destroyed( opening ) ) + { + if ( zombieshoulddetachfromwindow() ) + { + zombiedetachfrombus( self.left_or_right ); + return; + } + self.onbuswindow = 1; + chunk = get_closest_non_destroyed_chunk( self.origin, opening ); + waited = 0; + if ( isDefined( chunk ) ) + { + waited = 1; + opening.zbarrier setzbarrierpiecestate( chunk, "targetted_by_zombie" ); + opening thread check_zbarrier_piece_for_zombie_death( chunk, opening.zbarrier, self ); + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "teardown", self.animname ); + animstatebase = opening.zbarrier getzbarrierpieceanimstate( chunk ); + animsubstate = "spot_" + self.attacking_spot_index + self.left_or_right + "_piece_" + opening.zbarrier getzbarrierpieceanimsubstate( chunk ); + anim_sub_index = self getanimsubstatefromasd( animstatebase + "_in", animsubstate ); + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + self animscripted( tag_origin, tag_angles, maps/mp/animscripts/zm_utility::append_missing_legs_suffix( animstatebase + "_in" ), anim_sub_index ); + self zombieanimnotetrackthink( "board_tear_bus_anim", chunk, opening ); + while ( opening.zbarrier.chunk_health[ chunk ] >= 0 ) + { + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + self animscripted( tag_origin, tag_angles, maps/mp/animscripts/zm_utility::append_missing_legs_suffix( animstatebase + "_loop" ), anim_sub_index ); + self zombieanimnotetrackthink( "board_tear_bus_anim", chunk, opening ); + opening.zbarrier.chunk_health[ chunk ]--; + + } + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + self animscripted( tag_origin, tag_angles, maps/mp/animscripts/zm_utility::append_missing_legs_suffix( animstatebase + "_out" ), anim_sub_index ); + self zombieanimnotetrackthink( "board_tear_bus_anim", chunk, opening ); + } + tried_attack = self zombietryattackthroughwindow( 1, self.left_or_right ); + if ( !tried_attack && !waited ) + { + wait 0,1; + } + } + self.onbuswindow = undefined; + if ( !_isopeningdoor( opening.bindtag ) ) + { + self zombiekeepattackingthroughwindow( self.left_or_right ); + side = _getsideofbusopeningison( opening.bindtag ); + if ( side == "front" ) + { + from_front = 1; + } + anim_state = "window_climbin"; + if ( from_front ) + { + anim_state += "_front"; + anim_state += self.left_or_right; + } + else if ( from_rear ) + { + anim_state += "_back"; + } + else + { + anim_state += self.left_or_right; + } + min_chance_at_round = 5; + max_chance_at_round = 12; + if ( level.round_number >= min_chance_at_round ) + { + round = min( level.round_number, max_chance_at_round ); + range = max_chance_at_round - min_chance_at_round; + chance = ( 100 / range ) * ( round - min_chance_at_round ); + if ( randomintrange( 0, 100 ) <= chance ) + { + anim_state += "_fast"; + } + } + anim_index = self getanimsubstatefromasd( "zm_zbarrier_climbin_bus", anim_state ); + enter_anim = self getanimfromasd( "zm_zbarrier_climbin_bus", anim_index ); + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + self.climbing_into_bus = 1; + self.entering_bus = 1; + self animmode( "noclip" ); + self animscripted( tag_origin, tag_angles, "zm_zbarrier_climbin_bus", anim_index ); + self zombieanimnotetrackthink( "climbin_bus_anim" ); + self animmode( "gravity" ); + self maps/mp/animscripts/zm_run::needsupdate(); + if ( !self.isdog ) + { + self maps/mp/animscripts/zm_run::moverun(); + } + } + opening.zombie = undefined; + self.opening = undefined; + self unlink(); + self setgoalpos( self.origin ); + } + self reset_attack_spot(); + self.climbing_into_bus = 0; + if ( isDefined( removeafterdone ) && removeafterdone ) + { + self delete(); + return; + } + self.inert_delay = undefined; +} + +zombieattachleftorright( bus ) +{ + tag = self.opening.bindtag; + if ( isDefined( bus.doorsclosed ) && !bus.doorsclosed ) + { + if ( tag != "window_right_1_jnt" || tag == "window_right_2_jnt" && tag == "window_right_3_jnt" ) + { + return "_r"; + } + else + { + if ( tag == "window_right_4_jnt" ) + { + return "_l"; + } + } + } + side = getopeningside( tag ); + while ( isDefined( side ) ) + { + if ( side == "right" ) + { + openings = bus.openingright; + } + else + { + if ( side == "left" ) + { + openings = bus.openingleft; + } + } + _a1332 = openings; + _k1332 = getFirstArrayKey( _a1332 ); + while ( isDefined( _k1332 ) ) + { + opening = _a1332[ _k1332 ]; + if ( opening == self.opening ) + { + } + else + { + if ( isDefined( opening.zombie ) ) + { + return opening.zombie.left_or_right; + } + } + _k1332 = getNextArrayKey( _a1332, _k1332 ); + } + } + left_or_right = "_l"; + if ( randomint( 10 ) > 5 ) + { + left_or_right = "_r"; + } + return left_or_right; +} + +businitrightandleft() +{ + self.openingright = []; + self.openingleft = []; + _a1367 = self.openings; + _k1367 = getFirstArrayKey( _a1367 ); + while ( isDefined( _k1367 ) ) + { + opening = _a1367[ _k1367 ]; + side = getopeningside( opening.bindtag ); + if ( isDefined( side ) ) + { + if ( side == "right" ) + { + self.openingright[ self.openingright.size ] = opening; + break; + } + else + { + if ( side == "left" ) + { + self.openingleft[ self.openingleft.size ] = opening; + } + } + } + _k1367 = getNextArrayKey( _a1367, _k1367 ); + } +} + +getopeningside( tag ) +{ + i = 1; + while ( i <= 4 ) + { + window_tag = "window_right_" + i + "_jnt"; + if ( tag == window_tag ) + { + return "right"; + } + i++; + } + i = 1; + while ( i <= 5 ) + { + window_tag = "window_left_" + i + "_jnt"; + if ( tag == window_tag ) + { + return "left"; + } + i++; + } + return undefined; +} + +zombiegetwindowanimrate() +{ + animrate = 1; + animrateroundscalar = 0; + players = get_players(); + if ( players.size > 1 ) + { + target_rate = 1,5; + target_round = 25; + target_num_players = 4; + rate = ( target_rate - 1 ) / target_round / target_num_players; + animrateroundscalar = rate * players.size; + animrate = 1 + ( animrateroundscalar * level.round_number ); + if ( animrate > target_rate ) + { + animrate = target_rate; + } + } + return animrate; +} + +zombiedetachfrombus( postfix ) +{ + if ( !isDefined( self.opening ) ) + { + return; + } + if ( isDefined( self.opening.zombie ) && self.opening.zombie == self ) + { + self.opening.zombie = undefined; + } + is_right = 0; + if ( postfix == "_r" ) + { + is_right = 1; + } + bindtag = self.opening.bindtag; + side = _getsideofbusopeningison( bindtag ); + tag_origin = level.the_bus gettagorigin( bindtag ); + tag_angles = level.the_bus gettagangles( bindtag ); + self.opening = undefined; + self.isonbusroof = 0; + self.onbuswindow = undefined; + self.ai_state = "zombieDetachFromBus"; + self.entering_bus = 0; + self.isonbus = 0; + asd_name = "zm_window_dismount"; + if ( isDefined( side ) && side == "front" ) + { + asd_name = "zm_front_window_dismount"; + } + animstate = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( asd_name ); + self animscripted( tag_origin, tag_angles, animstate, is_right ); + self.dismount_start = 1; + self thread dismount_timer(); + maps/mp/animscripts/zm_shared::donotetracks( "window_dismount_anim" ); + self unlink(); + self reset_attack_spot(); + self.dismount_start = 0; + self.forcemovementscriptstate = 0; + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); + self.dont_throw_gib = undefined; + self notify( "detach_on_window" ); +} + +dismount_timer() +{ + self endon( "death" ); + wait 1,5; + self.dismount_start = 0; +} + +zombiegetcymbalmonkey() +{ + if ( isDefined( self.monkey_time ) && getTime() < self.monkey_time ) + { + return self.monkey; + } + poi = undefined; + if ( level.cymbal_monkeys.size > 0 ) + { + poi = self get_zombie_point_of_interest( self.origin, level.cymbal_monkeys ); + } + if ( isDefined( poi ) ) + { + self.monkey = poi[ 1 ]; + self.monkey_time = getTime() + 250; + return poi[ 1 ]; + } + return undefined; +} + +zombieshoulddetachfromwindow() +{ + monkey = self zombiegetcymbalmonkey(); + if ( isDefined( monkey ) ) + { + if ( monkey maps/mp/zm_transit_bus::entity_is_on_bus( 1 ) ) + { + return 0; + } + else + { + return 1; + } + } + enemy = self.favoriteenemy; + if ( isDefined( enemy ) && !self.favoriteenemy.isonbus ) + { + return 1; + } + return 0; +} + +zombiecanjumponroof( opening ) +{ + if ( level.the_bus.numplayersonroof == 0 ) + { + if ( all_chunks_destroyed( opening ) ) + { + return 0; + } + if ( isDefined( level.bus_zombie_on_roof ) ) + { + return 0; + } + if ( level.bus_roof_next_time > getTime() ) + { + return 0; + } + } + percentchance = 0; + if ( level.round_number <= 5 ) + { + percentchance = 5; + } + else if ( level.round_number <= 10 ) + { + percentchance = 20; + } + else if ( level.round_number <= 20 ) + { + percentchance = 30; + } + else if ( level.round_number <= 25 ) + { + percentchance = 40; + } + else + { + percentchance = 50; + } + percentofplayersonroof = 1; + if ( level.the_bus.numplayersnear > 0 ) + { + percentofplayersonroof = level.the_bus.numplayersonroof / level.the_bus.numplayersnear; + } + percentofplayersonroof *= 100; + if ( percentchance < percentofplayersonroof ) + { + percentchance = percentofplayersonroof; + } + if ( randomint( 100 ) < percentchance ) + { + return 1; + } + return 0; +} + +zombiesetnexttimetojumponroof() +{ + level.bus_roof_next_time = getTime() + level.bus_roof_min_interval_time + randomint( level.bus_roof_max_interval_time - level.bus_roof_min_interval_time ); +} + +zombiejumponroof( thebus, opening, removeafterdone, postfix ) +{ + level.bus_zombie_on_roof = self; + self.climbing_onto_bus = 1; + self.entering_bus = 1; + self animscripted( self.opening.zbarrier.origin, self.opening.zbarrier.angles, "zm_zbarrier_window_climbup", "window_climbup" + postfix ); + self zombieanimnotetrackthink( "bus_window_climbup" ); + play_sound_at_pos( "grab_metal_bar", self.origin ); + opening.zombie = undefined; + self.opening = undefined; + self unlink(); + self setgoalpos( self.origin ); + self.climbing_onto_bus = 0; + if ( level.the_bus.numplayersonroof > 0 ) + { + level.bus_zombie_on_roof = undefined; + } +} + +bussetupladder() +{ + trigger = getent( "bus_ladder_trigger", "targetname" ); + if ( !isDefined( trigger ) ) + { + return; + } + trigger enablelinkto(); + trigger linkto( level.the_bus ); + trigger setmovingplatformenabled( 1 ); + trigger setinvisibletoall(); + mantlebrush = getentarray( "ladder_mantle", "targetname" ); + while ( isDefined( mantlebrush ) && mantlebrush.size > 0 ) + { + i = 0; + while ( i < mantlebrush.size ) + { + self thread busdeferredinitladdermantle( mantlebrush[ i ] ); + i++; + } + } + thread busladderthink(); +} + +busdeferredinitladdermantle( mantle ) +{ + origin = self worldtolocalcoords( mantle.origin ); + mantle linkto( self, "", origin, ( 0, -1, 0 ) ); + mantle setmovingplatformenabled( 1 ); + wait_for_buildable( "busladder" ); + mantle delete(); +} + +busladderthink() +{ + origin = level.the_bus gettagorigin( "tag_ladder_attach" ); + origin += ( 10, 3, -30 ); + angles = level.the_bus gettagangles( "tag_ladder_attach" ); + angles += vectorScale( ( 0, -1, 0 ), 90 ); + level.the_bus.ladder = spawn( "script_model", origin ); + level.the_bus.ladder.angles = angles; + level.the_bus.ladder setmodel( "com_stepladder_large_closed" ); + level.the_bus.ladder notsolid(); + level.the_bus.ladder linkto( level.the_bus, "tag_ladder_attach" ); + level.the_bus.ladder setmovingplatformenabled( 1 ); + level.the_bus.ladder hide(); + player = wait_for_buildable( "busladder" ); + flag_set( "ladder_attached" ); + level.the_bus.ladder show(); + player maps/mp/zombies/_zm_buildables::track_placed_buildables( "busladder" ); +} + +bussetuproofopening() +{ + level.bus_roof_open = 0; + level.bus_zombie_on_roof = undefined; + level.bus_roof_next_time = 0; + level.bus_roof_min_interval_time = 10000; + level.bus_roof_max_interval_time = 20000; + trigger = getent( "bus_hatch_bottom_trigger", "targetname" ); + if ( !isDefined( trigger ) ) + { + return; + } + trigger enablelinkto(); + trigger linkto( level.the_bus ); + trigger setmovingplatformenabled( 1 ); + self thread bus_hatch_wait(); + self thread bus_hatch_tearin_wait(); + clipbrush = getentarray( "hatch_clip", "targetname" ); + while ( isDefined( clipbrush ) && clipbrush.size > 0 ) + { + i = 0; + while ( i < clipbrush.size ) + { + self thread businithatchclip( clipbrush[ i ] ); + i++; + } + } + mantlebrush = getentarray( "hatch_mantle", "targetname" ); + while ( isDefined( mantlebrush ) && mantlebrush.size > 0 ) + { + i = 0; + while ( i < mantlebrush.size ) + { + self thread busdeferredinithatchmantle( mantlebrush[ i ] ); + i++; + } + } + hatch_location = spawn( "script_origin", level.the_bus localtoworldcoords( ( 227, -1,7, 48 ) ) ); + hatch_location enablelinkto(); + hatch_location linkto( level.the_bus ); + hatch_location setmovingplatformenabled( 1 ); + level.the_bus.hatch_location = hatch_location; +/# + adddebugcommand( "devgui_cmd "Zombies:1/Bus:14/Hatch:4/Allow Traverse:1" "zombie_devgui hatch_available"\n" ); + self thread wait_open_sesame(); +#/ +} + +wait_open_sesame() +{ + level waittill( "open_sesame" ); + self notify( "hatch_mantle_allowed" ); + if ( isDefined( level.bus_tearin_roof ) ) + { + level.bus_tearin_roof hide(); + } + level.the_bus showpart( "tag_hatch_attach_ladder" ); + level.the_bus hidepart( "tag_hatch_pristine" ); + level.the_bus hidepart( "tag_hatch_damaged" ); + level.bus_roof_open = 1; + level.bus_roof_tearing = 0; +} + +bus_hatch_wait() +{ + level.the_bus hidepart( "tag_hatch_attach_ladder" ); + player = wait_for_buildable( "bushatch" ); + flag_set( "hatch_attached" ); + level.the_bus showpart( "tag_hatch_attach_ladder" ); + level.the_bus hidepart( "tag_hatch_pristine" ); + level.the_bus hidepart( "tag_hatch_damaged" ); + level.bus_roof_open = 1; + level.bus_roof_tearing = 0; + self notify( "hatch_mantle_allowed" ); + player maps/mp/zombies/_zm_buildables::track_placed_buildables( "bushatch" ); +} + +bus_hatch_tearin_wait() +{ + self endon( "hatch_mantle_allowed" ); + level.the_bus hidepart( "tag_hatch_damaged" ); + self waittill( "hatch_ripped_open" ); + level.the_bus hidepart( "tag_hatch_pristine" ); + level.the_bus showpart( "tag_hatch_damaged" ); + self notify( "hatch_drop_allowed" ); + playfxontag( level._effect[ "bus_hatch_bust" ], self, "tag_headlights" ); +} + +businithatchclip( clip ) +{ + origin = self worldtolocalcoords( clip.origin ); + clip linkto( self, "", origin, ( 0, -1, 0 ) ); + clip setmovingplatformenabled( 1 ); + self waittill_any( "hatch_mantle_allowed", "hatch_drop_allowed" ); + clip delete(); +} + +busdeferredinithatchmantle( mantle ) +{ + origin = self worldtolocalcoords( mantle.origin ); + mantle.origin = vectorScale( ( 0, -1, 0 ), 100 ); + self waittill( "hatch_mantle_allowed" ); + mantle linkto( self, "", origin, ( 0, -1, 0 ) ); + mantle setmovingplatformenabled( 1 ); +} + +zombieonbusenemy() +{ + new_enemy = undefined; + if ( isDefined( level.the_bus.bus_riders_alive ) && level.the_bus.bus_riders_alive.size > 0 ) + { + new_enemy = getclosest( self.origin, level.the_bus.bus_riders_alive ); + } + if ( isDefined( new_enemy ) && isDefined( self.favoriteenemy ) && isDefined( new_enemy ) && self.favoriteenemy != new_enemy ) + { + if ( isDefined( self.favoriteenemy.isonbus ) && !self.favoriteenemy.isonbus ) + { + self.favoriteenemy = new_enemy; + return; + } + else + { + if ( self.isonbusroof == new_enemy.isonbusroof ) + { + self.favoriteenemy = new_enemy; + } + } + } +} + +zombiemoveonbus() +{ + self endon( "death" ); + self endon( "removed" ); + level endon( "intermission" ); + self notify( "endOnBus" ); + self endon( "endOnBus" ); + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + wait 0,05; + self orientmode( "face enemy" ); + self.goalradius = 32; + self.forcemovementscriptstate = 1; + self.ai_state = "zombieMoveOnBus"; + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieMoveOnBus " + getTime() ); + bus_nodes = getnodearray( "the_bus", "target" ); + while ( 1 ) + { + self zombieonbusenemy(); + if ( !isDefined( self.favoriteenemy ) ) + { + break; + } + else if ( isDefined( self.isonbus ) ) + { + self_on_bus = self.isonbus; + } + if ( isDefined( self.isonbusroof ) ) + { + self_is_on_bus_roof = self.isonbusroof; + } + if ( !self_on_bus ) + { + break; + } + else + { + if ( isDefined( self.is_inert ) && self.is_inert ) + { + self.ignoreall = 1; + while ( isDefined( self.is_inert ) && self.is_inert ) + { + wait 0,1; + } + self.ignoreall = 0; + } + poi_override = 0; + if ( self.forcemovementscriptstate ) + { + monkey = self zombiegetcymbalmonkey(); + if ( isDefined( monkey ) ) + { + poi_override = 1; + self.ignoreall = 1; + self animmode( "normal" ); + self orientmode( "face motion" ); + if ( !level.the_bus maps/mp/zm_transit_bus::busispointinside( monkey.origin ) ) + { + self zombiewalktoexit(); + } + else + { + self setgoalpos( monkey.origin ); + } + break; + } + else + { + self.ignoreall = 0; + self animmode( "gravity" ); + self orientmode( "face enemy" ); + while ( isDefined( level.the_bus.doorsclosed ) && !level.the_bus.doorsclosed ) + { + doorstrigger = getentarray( "bus_door_trigger", "targetname" ); + _a1984 = doorstrigger; + _k1984 = getFirstArrayKey( _a1984 ); + while ( isDefined( _k1984 ) ) + { + trigger = _a1984[ _k1984 ]; + if ( self istouching( trigger ) ) + { + self orientmode( "face motion" ); + break; + } + else + { + _k1984 = getNextArrayKey( _a1984, _k1984 ); + } + } + } + dist_sq = distancesquared( self.favoriteenemy.origin, bus_nodes[ 0 ].origin ); + goal_node = bus_nodes[ 0 ]; + i = 1; + while ( i < bus_nodes.size ) + { + bus_sq = distancesquared( self.favoriteenemy.origin, bus_nodes[ i ].origin ); + if ( bus_sq < dist_sq ) + { + dist_sq = bus_sq; + goal_node = bus_nodes[ i ]; + } + i++; + } + if ( self_is_on_bus_roof ) + { + self.goalradius = 16; + } + else + { + self.goalradius = 32; + } + self setgoalnode( goal_node ); + } + } + enemy = self.favoriteenemy; + if ( isDefined( enemy ) ) + { + enemy_on_bus = enemy.isonbus; + } + if ( enemy_on_bus && isDefined( enemy.isonbusroof ) ) + { + enemy_on_roof = enemy.isonbusroof; + } + if ( !enemy_on_bus && !self_is_on_bus_roof ) + { + monkey = self zombiegetcymbalmonkey(); + if ( !isDefined( monkey ) || !monkey maps/mp/zm_transit_bus::entity_is_on_bus( 1 ) ) + { + self thread zombieexitbus(); + return; + } + } + else + { + if ( enemy_on_bus && self_is_on_bus_roof != enemy_on_roof ) + { + self thread zombieheighttraverse(); + return; + break; + } + else + { + if ( self_is_on_bus_roof && !enemy_on_bus ) + { + self thread zombiejumpoffroof(); + return; + break; + } + else + { + if ( isDefined( poi_override ) && !poi_override ) + { + disttoenemy = distance2d( self.origin, self.favoriteenemy.origin ); + shouldbeinforcemovement = disttoenemy > 32; + if ( !shouldbeinforcemovement && self.forcemovementscriptstate ) + { + self.forcemovementscriptstate = 0; + self animmode( "normal" ); + self orientmode( "face enemy" ); + } + if ( shouldbeinforcemovement && !self.forcemovementscriptstate ) + { + self.forcemovementscriptstate = 1; + self animmode( "gravity" ); + self orientmode( "face enemy" ); + } + } + } + } + } + wait 0,1; + } + } + self animmode( "normal" ); + self orientmode( "face enemy" ); + self.forcemovementscriptstate = 0; + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +zombiewalktoexit() +{ + self endon( "death" ); + bus = level.the_bus; + self.walk_to_exit = 1; + check_pos = self.origin; + enemy = self.favoriteenemy; + if ( isDefined( enemy ) ) + { + check_pos = enemy.origin; + } + if ( !level.the_bus.doorsclosed ) + { + front_dist = distance2dsquared( check_pos, level.the_bus.front_door.origin ); + back_dist = distance2dsquared( check_pos, level.the_bus.back_door.origin ); + link_one = undefined; + link_two = undefined; + door_node = undefined; + door_dist = undefined; + if ( front_dist < back_dist ) + { + door_dist = distance2dsquared( self.origin, level.the_bus.front_door.origin ); + if ( door_dist < 256 ) + { + door_node = level.the_bus.front_door; + } + } + else + { + door_dist = distance2dsquared( self.origin, level.the_bus.back_door.origin ); + if ( door_dist < 256 ) + { + door_node = level.the_bus.back_door; + } + } + if ( isDefined( door_node ) ) + { + if ( isDefined( door_node.links ) ) + { + if ( isDefined( door_node.links[ 0 ] ) ) + { + link_one = door_node.links[ 0 ]; + } + if ( isDefined( door_node.links[ 1 ] ) ) + { + link_two = door_node.links[ 1 ]; + } + } + link_goal = undefined; + if ( isDefined( link_one ) ) + { + link_goal = link_one; + } + if ( isDefined( link_one ) && isDefined( link_two ) ) + { + link_one_dist = distance2dsquared( check_pos, link_one.origin ); + link_two_dist = distance2dsquared( check_pos, link_two.origin ); + link_goal = link_one; + if ( link_two_dist < link_one_dist ) + { + link_goal = link_two; + } + } + if ( isDefined( link_goal ) ) + { + self setgoalnode( link_goal ); + return; + } + } + door_goal = level.the_bus.front_door; + if ( back_dist < front_dist ) + { + door_goal = level.the_bus.back_door; + } + self setgoalnode( door_goal ); + } + else + { + dist_f = distancesquared( check_pos, bus.front_door_inside.origin ); + dist_bl = distancesquared( check_pos, bus.exit_back_l.origin ); + dist_br = distancesquared( check_pos, bus.exit_back_r.origin ); + goal_node = bus.front_door_inside; + if ( dist_bl < dist_br ) + { + if ( dist_bl < dist_f ) + { + goal_node = bus.exit_back_l; + } + } + else + { + if ( dist_br < dist_f ) + { + goal_node = bus.exit_back_r; + } + } + self setgoalnode( goal_node ); + } +} + +zombiewindowtoroof() +{ + self endon( "death" ); + self animmode( "normal" ); + self orientmode( "face motion" ); + self.ai_state = "zombieWindowToRoof"; + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieWindowToRoof " + getTime() ); + while ( 1 ) + { + self zombiewalktowindow(); + if ( isDefined( self.exiting_window ) && self.exiting_window ) + { + break; + } + else + { + if ( isDefined( self.isonbus ) || !self.isonbus && isDefined( self.ai_state == "find_flesh" ) && self.ai_state == "find_flesh" ) + { + return; + } + wait 0,1; + } + } + while ( isDefined( self.exiting_window ) && self.exiting_window ) + { + wait 0,1; + } +} + +zombiewalktowindow() +{ + self endon( "death" ); + bus = level.the_bus; + self.walk_to_exit = 1; + check_pos = self.origin; + dist_f = distancesquared( check_pos, bus.front_door_inside.origin ); + dist_bl = distancesquared( check_pos, bus.exit_back_l.origin ); + goal_node = bus.front_door_inside; + if ( dist_bl < dist_f ) + { + goal_node = bus.exit_back_l; + } + self setgoalnode( goal_node ); +} + +zombieattackplayerclinging( player ) +{ + self endon( "death" ); + level endon( "intermission" ); + self.goalradius = 15; + enemy_clinging = 1; + while ( enemy_clinging ) + { + best_attack_pos = maps/mp/zm_transit_cling::_getbusattackposition( player ); + dist_from_pos2 = distance2dsquared( best_attack_pos, self.origin ); + enemy_origin = player _playergetorigin(); + direction = enemy_origin - self.origin; + direction_angles = vectorToAngle( direction ); + direction_angles = ( direction_angles[ 0 ], direction_angles[ 1 ], 0 ); + if ( dist_from_pos2 > 400 ) + { + self orientmode( "face point", best_attack_pos ); + self setgoalpos( best_attack_pos ); + } + else + { + self zombiescriptedattack( player, direction_angles, ::zombiedamageplayercling ); + } + enemy_clinging = player maps/mp/zm_transit_cling::playerisclingingtobus(); + wait 0,1; + } + self.goalradius = 32; +} + +zombieattackplayeronturret( player ) +{ + self endon( "death" ); + level endon( "intermission" ); + enemy_on_turret = 1; + while ( enemy_on_turret ) + { + enemy_origin = self.favoriteenemy _playergetorigin(); + dist_from_turret2 = distance2dsquared( enemy_origin, self.origin ); + direction = enemy_origin - self.origin; + direction_angles = vectorToAngle( direction ); + direction_angles = ( direction_angles[ 0 ], direction_angles[ 1 ], 0 ); + if ( dist_from_turret2 > 1024 ) + { + self setgoalpos( enemy_origin, direction_angles ); + } + else + { + self zombiescriptedattack( player, direction_angles, ::zombiedamageplayerturret ); + } + wait 0,1; + if ( isDefined( self.favoriteenemy.onbusturret ) && isDefined( self.favoriteenemy.busturret ) ) + { + enemy_on_turret = self.favoriteenemy.onbusturret; + } + } +} + +zombiescriptedattack( player, direction_angles, damage_func ) +{ + self orientmode( "face angle", direction_angles[ 1 ] ); + zombie_attack_anim = self zombiepickunmovingattackanim(); + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", self.animname ); + while ( 1 ) + { + self waittill( "meleeanim", note ); + if ( note == "end" || note == "stop" ) + { + return; + } + else if ( note == "fire" ) + { + if ( isDefined( damage_func ) ) + { + [[ damage_func ]]( player ); + } + } + } +} + +zombiedamageplayerturret( player ) +{ + if ( player.onbusturret ) + { + player dodamage( self.meleedamage, self.origin, self ); + } +} + +zombiedamageplayercling( player ) +{ + if ( player maps/mp/zm_transit_cling::playerisclingingtobus() ) + { + player dodamage( self.meleedamage, self.origin, self ); + } +} + +_playergetorigin() +{ + if ( isDefined( self.onbusturret ) && isDefined( self.busturret ) && self.onbusturret ) + { + turret = self.busturret; + turret_exit = getent( turret.target, "targetname" ); + return turret_exit.origin; + } + return self.origin; +} + +zombiepickunmovingattackanim() +{ + melee_anim = undefined; + if ( self.has_legs ) + { + rand_num = randomint( 4 ); + melee_anim = level._zombie_melee[ self.animname ][ rand_num ]; + } + else if ( self.a.gib_ref == "no_legs" ) + { + melee_anim = random( level._zombie_stumpy_melee[ self.animname ] ); + } + else + { + melee_anim = level._zombie_melee_crawl[ self.animname ][ 0 ]; + } + return melee_anim; +} + +zombieexitbus() +{ + self endon( "death" ); + self endon( "stop_zombieExitBus" ); + level endon( "intermission" ); + self animmode( "normal" ); + self orientmode( "face motion" ); + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieExitBus " + getTime() ); + while ( 1 ) + { + if ( isDefined( self.exiting_window ) && self.exiting_window ) + { + break; + } + else + { + if ( isDefined( self.isonbus ) && !self.isonbus ) + { + self.walk_to_exit = 0; + return; + } + if ( isDefined( self.solo_revive_exit ) && !self.solo_revive_exit ) + { + monkey = undefined; + if ( isDefined( self.enemyoverride ) ) + { + monkey = self.enemyoverride[ 1 ]; + } + ignore_enemy = 0; + if ( isDefined( monkey ) && !monkey maps/mp/zm_transit_bus::entity_is_on_bus( 1 ) ) + { + ignore_enemy = 1; + } + if ( !ignore_enemy ) + { + enemy = self.favoriteenemy; + if ( isDefined( enemy ) ) + { + if ( enemy.isonbus ) + { + self.walk_to_exit = 0; + self thread zombiemoveonbus(); + return; + } + } + } + } + self zombiewalktoexit(); + wait 0,1; + } + } + while ( isDefined( self.exiting_window ) && self.exiting_window ) + { + wait 0,1; + } + self.dont_throw_gib = undefined; + self orientmode( "face enemy" ); + self.forcemovementscriptstate = 0; + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +zombiejumpoffroof() +{ + self endon( "death" ); + self endon( "removed" ); + level endon( "intermission" ); + self animmode( "gravity" ); + self orientmode( "face goal" ); + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieJumpOffRoof " + getTime() ); + while ( 1 ) + { + enemy = self.favoriteenemy; + if ( isDefined( enemy ) ) + { + enemy_on_bus = enemy.isonbus; + } + enemiesonbus = level.the_bus.numaliveplayersridingbus > 0; + if ( isDefined( self.isonbus ) ) + { + selfisonbus = self.isonbus; + } + if ( enemy_on_bus ) + { + self thread zombiemoveonbus(); + return; + } + if ( !selfisonbus ) + { + return; + } + else closest_jump_tag = self zombiegetclosestroofjumptag(); + goal_pos = level.the_bus gettagorigin( closest_jump_tag ); + if ( distance2dsquared( self.origin, goal_pos ) <= 1024 ) + { + self.attachent = level.the_bus; + self.attachtag = closest_jump_tag; + self linkto( self.attachent, self.attachtag, ( 0, -1, 0 ), ( 0, -1, 0 ) ); + wait 0,1; + self zombieplayattachedanim( "jump_down_127" ); + self setgoalpos( self.origin ); + self unlink(); + return; + } + else + { + self setgoalpos( goal_pos ); + self orientmode( "face point", goal_pos ); + wait 0,1; + } + } +} + +zombieheighttraverse() +{ + level endon( "intermission" ); + self endon( "death" ); + self endon( "removed" ); + self endon( "zombieHeightTraverseStop" ); + self animmode( "gravity" ); + self orientmode( "face goal" ); + self.zombie_ladder_stage = 1; + self.goal_local_offset = level.the_bus.ladder_local_offset; + self.goal_local_offset = ( self.goal_local_offset[ 0 ], self.goal_local_offset[ 1 ], level.the_bus.floor ); + self.goal_local_angles = vectorScale( ( 0, -1, 0 ), 90 ); + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieHeightTraverse " + getTime() ); + if ( !isDefined( self.isonbusroof ) || !self.isonbusroof ) + { + bus = level.the_bus; + hatch_dist = distancesquared( self.origin, bus.hatch_location.origin ); + front_dist = distancesquared( self.origin, bus.front_door_inside.origin ); + back_dist = distancesquared( self.origin, bus.exit_back_l.origin ); + closer_to_hatch = 1; + if ( front_dist < hatch_dist || back_dist < hatch_dist ) + { + closer_to_hatch = 0; + } + if ( isDefined( level.bus_roof_open ) && level.bus_roof_open && isDefined( level.bus_roof_tearing ) || level.bus_roof_tearing && !closer_to_hatch ) + { + self zombiewindowtoroof(); + } + else + { + if ( self zombiepathtoladder() ) + { + self zombieclimbtoroof(); + } + } + } + else + { + if ( self zombiepathtoroofopening() ) + { + self zombiejumpdownhatch(); + } + else + { + enemy = self.favoriteenemy; + if ( isDefined( enemy ) && isDefined( enemy.isonbus ) && !enemy.isonbus ) + { + self thread zombiejumpoffroof(); + return; + } + } + } + if ( isDefined( self.isonbus ) && self.isonbus ) + { + self thread zombiemoveonbus(); + } +} + +zombiepathtoladder() +{ + self.goalradius = 2; + while ( isDefined( self.enemy ) && self.enemy.isonbusroof ) + { + if ( !self.isonbus ) + { + self.goalradius = 32; + return 0; + } + goal_dir = anglesToForward( level.the_bus.angles + self.goal_local_angles ); + goal_pos = level.the_bus.hatch_location.origin; + if ( distancesquared( self.origin, goal_pos ) <= 1600 ) + { + self.goalradius = 32; + self.ladder_pos = goal_pos; + return 1; + } + self setgoalpos( goal_pos ); + self orientmode( "face point", goal_pos ); + wait 0,1; + } + self.goalradius = 32; + return 0; +} + +zombiepathtoroofopening() +{ + self.goalradius = 2; + goal_tag = self zombiegetclosestroofopeningjumptag(); + while ( 1 ) + { + self zombieonbusenemy(); + enemy = self.favoriteenemy; + if ( isDefined( enemy ) && isDefined( enemy.isonbusroof ) && enemy.isonbusroof ) + { + break; + } + else + { + if ( isDefined( enemy ) && isDefined( enemy.isonbus ) && !enemy.isonbus ) + { + break; + } + else + { + if ( !self.isonbus ) + { + break; + } + else + { + goal_dir = level.the_bus gettagangles( goal_tag ); + goal_pos = level.the_bus gettagorigin( goal_tag ); + if ( distance2d( self.origin, goal_pos ) <= 32 ) + { + self.goalradius = 32; + return 1; + } + self setgoalpos( goal_pos ); + self orientmode( "face point", goal_pos ); + wait 0,1; + } + } + } + } + self.goalradius = 32; + return 0; +} + +zombiejumpdownhatch() +{ + self endon( "death" ); + self thread zombiejumpdownhatchkilled(); + enemy = self.favoriteenemy; + if ( isDefined( enemy ) && isDefined( enemy.isonbusroof ) && enemy.isonbusroof ) + { + self unlink(); + return; + } + while ( isDefined( level.bus_roof_tearing ) && level.bus_roof_tearing ) + { + wait 0,1; + } + roof_tag = self zombiegetclosestroofopeningjumptag(); + if ( !level.bus_roof_open ) + { + self.inert_delay = ::zombieroofteardelay; + level.bus_roof_open = 1; + level.bus_roof_tearing = 1; + self linkto( level.the_bus, roof_tag ); + tag_origin = level.the_bus gettagorigin( roof_tag ); + tag_angles = level.the_bus gettagangles( roof_tag ); + substate = 1; + if ( roof_tag == "window_roof_2_jnt" ) + { + substate = 2; + } + animstate = "zm_bus_attached"; + self animscripted( tag_origin, tag_angles, animstate, substate ); + maps/mp/animscripts/zm_shared::donotetracks( "bus_attached_anim" ); + self.inert_delay = undefined; + level.bus_roof_tearing = 0; + level.the_bus notify( "hatch_ripped_open" ); + } + self.hatch_jump = 1; + self.inert_delay = ::zombiehatchjumpdelay; + hatch_tag = "tag_hatch_attach_ladder"; + self linkto( level.the_bus, hatch_tag ); + tag_origin = level.the_bus gettagorigin( hatch_tag ); + tag_angles = level.the_bus gettagangles( hatch_tag ); + substate = 0; + if ( roof_tag == "window_roof_1_jnt" ) + { + substate = 1; + } + animstate = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "zm_bus_hatch_jump_down" ); + self animscripted( tag_origin, tag_angles, animstate, substate ); + maps/mp/animscripts/zm_shared::donotetracks( "bus_hatch_jump_anim" ); + self unlink(); + self.hatch_jump = 0; + self.inert_delay = undefined; + self setgoalpos( self.origin ); + level.bus_zombie_on_roof = undefined; +} + +zombiehatchjumpdelay() +{ +/# + iprintln( "hatch delay" ); +#/ + while ( isDefined( self.hatch_jump ) && self.hatch_jump ) + { + wait 0,1; + } +} + +zombieroofteardelay() +{ + self endon( "death" ); + self notify( "zombieHeightTraverseStop" ); + self unlink(); + level.bus_roof_open = 0; + level.bus_roof_tearing = 0; + self.inert_wakeup_override = ::zombierooftearwakeup; +} + +zombierooftearwakeup() +{ + self endon( "death" ); + self.inert_wakeup_override = undefined; + self thread zombieheighttraverse(); +} + +zombiejumpdownhatchkilled() +{ + while ( isDefined( level.bus_roof_tearing ) && level.bus_roof_tearing ) + { + if ( !isDefined( self ) ) + { + level.bus_roof_tearing = 0; + return; + } + else + { + wait 0,1; + } + } +} + +zombieclimbtoroof() +{ + self endon( "death" ); + hatch_tag = "tag_hatch_attach_ladder"; + self linkto( level.the_bus, hatch_tag ); + tag_origin = level.the_bus gettagorigin( hatch_tag ); + tag_angles = level.the_bus gettagangles( hatch_tag ); + hatch_vec = vectornormalize( anglesToForward( tag_angles ) ); + player = self.favoriteenemy; + player_vec = vectornormalize( player.origin - tag_origin ); + substate = 0; + dot = vectordot( hatch_vec, player_vec ); + if ( dot > 0 ) + { + substate = 1; + } + animstate = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "zm_bus_hatch_jump_up" ); + self animscripted( tag_origin, tag_angles, animstate, substate ); + maps/mp/animscripts/zm_shared::donotetracks( "bus_hatch_jump_anim" ); + self unlink(); + self setgoalpos( self.origin ); +} + +zombiegetclosestroofjumptag() +{ + root = "tag_roof_jump_off"; + best = root + "1"; + best_pos = level.the_bus gettagorigin( best ); + best_pos_dist2 = distance2dsquared( self.origin, best_pos ); + i = 1; + while ( i <= 4 ) + { + next_pos = level.the_bus gettagorigin( root + i ); + next_pos_dist2 = distance2dsquared( self.origin, next_pos ); + if ( next_pos_dist2 < best_pos_dist2 ) + { + best = root + i; + best_pos = next_pos; + best_pos_dist2 = next_pos_dist2; + } + i++; + } + return best; +} + +zombiegetclosestroofopeningjumptag() +{ + pos1 = level.the_bus gettagorigin( "window_roof_1_jnt" ); + pos2 = level.the_bus gettagorigin( "window_roof_2_jnt" ); + closest = "window_roof_1_jnt"; + pos1_dist2 = distance2dsquared( self.origin, pos1 ); + pos2_dist2 = distance2dsquared( self.origin, pos2 ); + if ( pos2_dist2 < pos1_dist2 ) + { + closest = "window_roof_2_jnt"; + } + return closest; +} + +zombiegetclosestdoortag() +{ + pos1 = level.the_bus gettagorigin( "door_rear_jnt" ); + pos2 = level.the_bus gettagorigin( "door_front_jnt" ); + closest = "door_rear_jnt"; + pos1_dist2 = distance2dsquared( self.origin, pos1 ); + pos2_dist2 = distance2dsquared( self.origin, pos2 ); + if ( pos2_dist2 < pos1_dist2 ) + { + closest = "door_front_jnt"; + } + return closest; +} + +zombiekeepattackingthroughwindow( left_or_right ) +{ + while ( self zombietryattackthroughwindow( 0, left_or_right ) ) + { + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + asd_name = "zm_zbarrier_window_idle"; + side = _getsideofbusopeningison( self.attachtag ); + if ( side == "front" ) + { + asd_name = "zm_zbarrier_front_window_idle"; + } + self animscripted( tag_origin, tag_angles, asd_name, "window_idle" + left_or_right ); + self zombieanimnotetrackthink( "bus_window_idle" ); + } +} + +zombietryattackthroughwindow( is_random, postfix ) +{ + attackplayers = self zombiegetplayerstoattack(); + if ( attackplayers.size == 0 ) + { + return 0; + } + should_attack = 1; + if ( is_random ) + { + rand = randomint( 100 ); + should_attack = rand < 80; + } + if ( should_attack ) + { + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", self.animname ); + tag_origin = self.attachent gettagorigin( self.attachtag ); + tag_angles = self.attachent gettagangles( self.attachtag ); + asd_name = "zm_zbarrier_window_attack"; + side = _getsideofbusopeningison( self.attachtag ); + if ( isDefined( side ) && side == "front" ) + { + asd_name = "zm_zbarrier_front_window_attack"; + } + self animscripted( tag_origin, tag_angles, asd_name, "window_attack" + postfix ); + self zombieanimnotetrackthink( "bus_window_attack" ); + return 1; + } + return 0; +} + +zombiegetplayerstoattack() +{ + playerstoattack = []; + players = get_players(); + attackrange = 72; + attackrange *= attackrange; + attackheight = 37; + attackheight *= attackheight; + i = 0; + while ( i < players.size ) + { + if ( isDefined( self.opening ) && isDefined( self.opening.rebuildtrigger ) ) + { + if ( players[ i ] istouching( self.opening.rebuildtrigger ) ) + { + playerstoattack[ playerstoattack.size ] = players[ i ]; + } + i++; + continue; + } + else + { + xydist = distance2dsquared( self.origin, players[ i ].origin ); + zdist = self.origin[ 2 ] - players[ i ].origin[ 2 ]; + zdist2 = zdist * zdist; + if ( xydist <= attackrange && zdist2 <= attackheight ) + { + playerstoattack[ playerstoattack.size ] = players[ i ]; + } + } + i++; + } + return playerstoattack; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_power.gsc b/zm_transit_patch/maps/mp/zm_transit_power.gsc new file mode 100644 index 0000000..ec16632 --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_power.gsc @@ -0,0 +1,583 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/_visionset_mgr; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +initializepower() +{ + level thread electricswitch(); + level thread powerevent(); + registerclientfield( "toplayer", "power_rumble", 1, 1, "int" ); + if ( !isDefined( level.vsmgr_prio_visionset_zm_transit_power_high_low ) ) + { + level.vsmgr_prio_visionset_zm_transit_power_high_low = 20; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "visionset", "zm_power_high_low", 1, level.vsmgr_prio_visionset_zm_transit_power_high_low, 7, 1, ::vsmgr_lerp_power_up_down, 0 ); +} + +precache_models() +{ +} + +elecswitchbuildable() +{ + lever = getent( "powerswitch_p6_zm_buildable_pswitch_lever", "targetname" ); + hand = getent( "powerswitch_p6_zm_buildable_pswitch_hand", "targetname" ); + hand linkto( lever ); + hand hide(); + getent( "powerswitch_p6_zm_buildable_pswitch_body", "targetname" ) hide(); + lever hide(); + wait_for_buildable( "powerswitch" ); +} + +electricswitch() +{ + flag_init( "switches_on" ); + level thread wait_for_power(); + trig = getent( "powerswitch_buildable_trigger_power", "targetname" ); + trig setinvisibletoall(); + elecswitchbuildable(); + master_switch = getent( "powerswitch_p6_zm_buildable_pswitch_lever", "targetname" ); + while ( 1 ) + { + trig sethintstring( &"ZOMBIE_ELECTRIC_SWITCH" ); + trig setvisibletoall(); + trig waittill( "trigger", user ); + trig setinvisibletoall(); + master_switch rotateroll( -90, 0,3 ); + master_switch playsound( "zmb_switch_flip" ); + master_switch waittill( "rotatedone" ); + playfx( level._effect[ "switch_sparks" ], getstruct( "elec_switch_fx", "targetname" ).origin ); + master_switch playsound( "zmb_turn_on" ); + level.power_event_in_progress = 1; + level thread power_event_rumble_and_quake(); + flag_set( "switches_on" ); + clientnotify( "pwr" ); + level thread avogadro_show_vox( user ); + level waittill( "power_event_complete" ); + clientnotify( "pwr" ); + flag_set( "power_on" ); + level.power_event_in_progress = 0; + level thread bus_station_pa_vox(); + if ( isDefined( user ) ) + { + user maps/mp/zombies/_zm_stats::increment_client_stat( "power_turnedon", 0 ); + user maps/mp/zombies/_zm_stats::increment_player_stat( "power_turnedon" ); + } + trig sethintstring( &"ZOMBIE_ELECTRIC_SWITCH_OFF" ); + trig setvisibletoall(); + trig waittill( "trigger", user ); + trig setinvisibletoall(); + master_switch rotateroll( 90, 0,3 ); + master_switch playsound( "zmb_switch_flip" ); + master_switch waittill( "rotatedone" ); + level.power_event_in_progress = 1; + level thread power_event_rumble_and_quake(); + flag_clear( "switches_on" ); + level waittill( "power_event_complete" ); + clientnotify( "pwo" ); + flag_clear( "power_on" ); + level.power_event_in_progress = 0; + level.power_cycled = 1; + if ( isDefined( user ) ) + { + user maps/mp/zombies/_zm_stats::increment_client_stat( "power_turnedoff", 0 ); + user maps/mp/zombies/_zm_stats::increment_player_stat( "power_turnedoff" ); + } + } +} + +vsmgr_lerp_power_up_down( player, opt_param_1, opt_param_2 ) +{ + self vsmgr_set_state_active( player, opt_param_1 ); +} + +power_event_vision_set_post_event() +{ + self endon( "end_vision_set_power" ); + level endon( "end_game" ); + self endon( "disconnect" ); + if ( flag( "power_on" ) ) + { + return; + } + level waittill( "power_event_complete" ); + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_power_high_low", self, 0 ); +} + +power_event_vision_set() +{ + self endon( "end_vision_set_power" ); + level endon( "end_game" ); + level endon( "power_event_complete" ); + self endon( "disconnect" ); + if ( flag( "power_on" ) ) + { + return; + } + duration = 2; + startgoal = 1; + endgoal = 0; + self power_event_vision_set_lerp( duration, startgoal, endgoal ); + while ( 1 ) + { + if ( randomint( 100 ) > 50 ) + { + duration = randomintrange( 2, 6 ) / 5; + startgoal = endgoal; + if ( startgoal > 0,6 ) + { + endgoal = randomfloatrange( 0, 0,5 ); + } + else + { + endgoal = 1; + } + self power_event_vision_set_lerp( duration, startgoal, endgoal ); + } + else if ( randomint( 100 ) > 75 ) + { + x = 2; + while ( x > 0 ) + { + duration = 0,2; + startgoal = endgoal; + if ( startgoal > 0,6 ) + { + endgoal = 0; + } + else + { + endgoal = 1; + } + self power_event_vision_set_lerp( duration, startgoal, endgoal ); + x--; + + } + } + else duration = 0,4; + startgoal = endgoal; + if ( startgoal > 0,6 ) + { + endgoal = randomfloatrange( 0, 0,5 ); + } + else + { + endgoal = randomfloatrange( 0,5, 1 ); + } + self power_event_vision_set_lerp( duration, startgoal, endgoal ); + wait 0,05; + } +} + +power_event_vision_set_lerp( duration, startgoal, endgoal ) +{ + self endon( "end_vision_set_power" ); + level endon( "end_game" ); + level endon( "power_event_complete" ); + self endon( "disconnect" ); + incs = int( duration / 0,05 ); + if ( incs == 0 ) + { + incs = 1; + } + incsgoal = ( endgoal - startgoal ) / incs; + currentgoal = startgoal; + i = 0; + while ( i < incs ) + { + currentgoal += incsgoal; + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_power_high_low", self, currentgoal ); + wait 0,05; + i++; + } + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_power_high_low", self, endgoal ); +} + +power_event_rumble_and_quake( power_on ) +{ + level endon( "end_game" ); + while ( isDefined( level.power_event_in_progress ) && level.power_event_in_progress ) + { + players = get_players(); + _a284 = players; + _k284 = getFirstArrayKey( _a284 ); + while ( isDefined( _k284 ) ) + { + player = _a284[ _k284 ]; + if ( !is_player_valid( player ) ) + { + } + else if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) || player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_pcr", 1 ) ) + { + if ( isDefined( player.power_rumble_active ) && !player.power_rumble_active ) + { + player thread power_event_rumble_and_quake_player(); + } + } + else + { + if ( isDefined( player.power_rumble_active ) && player.power_rumble_active ) + { + player setclientfieldtoplayer( "power_rumble", 0 ); + player.power_rumble_active = 0; + } + } + _k284 = getNextArrayKey( _a284, _k284 ); + } + wait 1; + } + players = get_players(); + _a311 = players; + _k311 = getFirstArrayKey( _a311 ); + while ( isDefined( _k311 ) ) + { + player = _a311[ _k311 ]; + player setclientfieldtoplayer( "power_rumble", 0 ); + player notify( "end_vision_set_power" ); + maps/mp/_visionset_mgr::vsmgr_deactivate( "visionset", "zm_power_high_low", player ); + _k311 = getNextArrayKey( _a311, _k311 ); + } +} + +power_event_rumble_and_quake_player() +{ + self endon( "disconnect" ); + self.power_rumble_active = 1; + self setclientfieldtoplayer( "power_rumble", 1 ); + self thread power_event_vision_set(); + self thread power_event_vision_set_post_event(); + while ( !self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) && self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_pcr", 1 ) && isDefined( level.power_event_in_progress ) && level.power_event_in_progress ) + { + wait 1; + } + self.power_rumble_active = 0; + self notify( "end_vision_set_power" ); + self setclientfieldtoplayer( "power_rumble", 0 ); +} + +avogadroreleasefromchamberevent() +{ + exploder( 500 ); + level.zones[ "zone_prr" ].is_spawning_allowed = 0; + level.zones[ "zone_pcr" ].is_spawning_allowed = 0; + level thread killzombiesinpowerstation(); + while ( !flag( "power_on" ) ) + { + waittime = randomfloatrange( 1,5, 4,5 ); + players = get_players(); + _a354 = players; + _k354 = getFirstArrayKey( _a354 ); + while ( isDefined( _k354 ) ) + { + player = _a354[ _k354 ]; + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) ) + { + player setelectrified( waittime - 1 ); + player shellshock( "electrocution", waittime ); + wait 0,05; + } + _k354 = getNextArrayKey( _a354, _k354 ); + } + waittime += 1,5; + level waittill_notify_or_timeout( "power_on", waittime ); + } + players = get_players(); + _a372 = players; + _k372 = getFirstArrayKey( _a372 ); + while ( isDefined( _k372 ) ) + { + player = _a372[ _k372 ]; + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) ) + { + player setelectrified( 0,25 ); + player shellshock( "electrocution", 1,5 ); + wait 0,05; + } + _k372 = getNextArrayKey( _a372, _k372 ); + } + level.zones[ "zone_prr" ].is_spawning_allowed = 1; + level.zones[ "zone_pcr" ].is_spawning_allowed = 1; + stop_exploder( 500 ); +} + +killzombiesinpowerstation() +{ + level endon( "power_on" ); + radiussq = 122500; + while ( 1 ) + { + zombies = getaiarray( level.zombie_team ); + _a401 = zombies; + _k401 = getFirstArrayKey( _a401 ); + while ( isDefined( _k401 ) ) + { + zombie = _a401[ _k401 ]; + if ( !isDefined( zombie ) ) + { + } + else if ( isDefined( zombie.is_avogadro ) && zombie.is_avogadro ) + { + } + else + { + if ( distancesquared( ( 11344, 7590, -729 ), zombie.origin ) < radiussq ) + { + break; + } + else + { + if ( isDefined( zombie ) || zombie maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) && isDefined( zombie.zone_name ) && zombie.zone_name == "zone_prr" ) + { + if ( isDefined( zombie.has_been_damaged_by_player ) && !zombie.has_been_damaged_by_player ) + { + level.zombie_total++; + } + zombie dodamage( zombie.health + 100, zombie.origin ); + wait randomfloatrange( 0,05, 0,15 ); + } + } + } + _k401 = getNextArrayKey( _a401, _k401 ); + } + wait 1; + } +} + +wait_for_power() +{ + while ( 1 ) + { + flag_wait( "power_on" ); + maps/mp/zombies/_zm_perks::perk_unpause_all_perks(); + wait_network_frame(); + level setclientfield( "zombie_power_on", 1 ); + enable_morse_code(); + raisepowerplantgates(); + flag_waitopen( "power_on" ); + level setclientfield( "zombie_power_on", 0 ); + disable_morse_code(); + } +} + +raisepowerplantgates() +{ + gate1 = []; + gate2 = []; + gate1 = getentarray( "security_booth_gate", "targetname" ); + gate2 = getentarray( "security_booth_gate_2", "targetname" ); + while ( isDefined( gate1 ) ) + { + i = 0; + while ( i < gate1.size ) + { + gate1[ i ] thread raisegate( -90 ); + i++; + } + } + while ( isDefined( gate2 ) ) + { + i = 0; + while ( i < gate2.size ) + { + gate2[ i ] thread raisegate( 90 ); + i++; + } + } + level.the_bus notify( "OnPowerOn" ); +} + +raisegate( degrees ) +{ + self rotatepitch( degrees, 4 ); +} + +powerevent() +{ + reactor_core_mover = getent( "core_mover", "targetname" ); + reactor_core_audio = spawn( "script_origin", reactor_core_mover.origin ); + if ( !isDefined( reactor_core_mover ) ) + { + return; + } + thread blockstairs(); + thread linkentitiestocoremover( reactor_core_mover ); + while ( 1 ) + { + flag_wait( "switches_on" ); + thread dropreactordoors(); + thread raisereactordoors(); + power_event_time = 30; + reactor_core_mover playsound( "zmb_power_rise_start" ); + reactor_core_mover playloopsound( "zmb_power_rise_loop", 0,75 ); + reactor_core_mover thread coremove( power_event_time ); + if ( isDefined( level.avogadro ) && isDefined( level.avogadro.state ) && level.avogadro.state == "chamber" ) + { + level thread avogadroreleasefromchamberevent(); + } + wait power_event_time; + reactor_core_mover stoploopsound( 0,5 ); + reactor_core_audio playloopsound( "zmb_power_on_loop", 2 ); + reactor_core_mover playsound( "zmb_power_rise_stop" ); + level notify( "power_event_complete" ); + flag_waitopen( "switches_on" ); + thread dropreactordoors(); + thread raisereactordoors(); + playsoundatposition( "zmb_power_off_quad", ( 0, 0, 0 ) ); + reactor_core_mover playsound( "zmb_power_rise_start" ); + reactor_core_mover playloopsound( "zmb_power_rise_loop", 0,75 ); + reactor_core_mover thread coremove( power_event_time, 1 ); + wait power_event_time; + reactor_core_mover stoploopsound( 0,5 ); + reactor_core_audio stoploopsound( 0,5 ); + reactor_core_mover playsound( "zmb_power_rise_stop" ); + level notify( "power_event_complete" ); + } +} + +corerotate( time ) +{ + self rotateyaw( 180, time ); +} + +coremove( time, down ) +{ + if ( isDefined( down ) && down ) + { + self movez( -160, time ); + } + else + { + self movez( 160, time ); + } +} + +blockstairs() +{ + stairs_blocker = getent( "reactor_core_stairs_blocker", "targetname" ); + if ( !isDefined( stairs_blocker ) ) + { + return; + } + stairs_blocker movez( -128, 1 ); +} + +linkentitiestocoremover( reactor_core_mover ) +{ + core_entities = getentarray( "core_entity", "script_noteworthy" ); + i = 0; + while ( i < core_entities.size ) + { + next_ent = core_entities[ i ]; + if ( next_ent.classname == "trigger_use_touch" ) + { + next_ent enablelinkto(); + } + next_ent linkto( reactor_core_mover, "tag_origin" ); + i++; + } +} + +dropreactordoors() +{ + doors = getentarray( "reactor_core_door", "targetname" ); + if ( doors.size == 0 ) + { + return; + } + i = 0; + while ( i < doors.size ) + { + next_door = doors[ i ]; + next_door movez( -128, 1 ); + next_door disconnectpaths(); + i++; + } +} + +raisereactordoors() +{ + level waittill( "power_event_complete" ); + doors = getentarray( "reactor_core_door", "targetname" ); + if ( doors.size == 0 ) + { + return; + } + i = 0; + while ( i < doors.size ) + { + next_door = doors[ i ]; + next_door movez( 128, 1 ); + next_door connectpaths(); + i++; + } +} + +avogadro_show_vox( user ) +{ + wait 1; + if ( isDefined( user ) ) + { + user thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "power", "power_on" ); + } + wait 8; + players = get_players(); + players = array_randomize( players ); + _a655 = players; + _k655 = getFirstArrayKey( _a655 ); + while ( isDefined( _k655 ) ) + { + player = _a655[ _k655 ]; + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) || player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_pcr", 1 ) ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "power", "power_core" ); + break; + } + else + { + _k655 = getNextArrayKey( _a655, _k655 ); + } + } + wait 15; + players = get_players(); + players = array_randomize( players ); + _a668 = players; + _k668 = getFirstArrayKey( _a668 ); + while ( isDefined( _k668 ) ) + { + player = _a668[ _k668 ]; + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr", 1 ) || player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_pcr", 1 ) ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "avogadro_reveal" ); + return; + } + else + { + _k668 = getNextArrayKey( _a668, _k668 ); + } + } +} + +bus_station_pa_vox() +{ + level endon( "power_off" ); + while ( 1 ) + { + level.station_pa_vox = array_randomize( level.station_pa_vox ); + _a686 = level.station_pa_vox; + _k686 = getFirstArrayKey( _a686 ); + while ( isDefined( _k686 ) ) + { + line = _a686[ _k686 ]; + playsoundatposition( line, ( -6848, 5056, 56 ) ); + wait randomintrange( 12, 15 ); + _k686 = getNextArrayKey( _a686, _k686 ); + } + wait 1; + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_sq.gsc b/zm_transit_patch/maps/mp/zm_transit_sq.gsc new file mode 100644 index 0000000..f93699e --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_sq.gsc @@ -0,0 +1,1600 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zm_transit_utility; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( level.createfx_enabled ) + { + return; + } + if ( isDefined( level.gamedifficulty ) && level.gamedifficulty == 0 ) + { + level thread sq_easy_cleanup(); + return; + } + level.sq_volume = getent( "sq_common_area", "targetname" ); + level.sq_clip = getent( "sq_common_clip", "targetname" ); + register_map_navcard( "navcard_held_zm_transit", "navcard_held_zm_buried" ); + if ( isDefined( level.sq_clip ) ) + { + level.sq_clip connectpaths(); + level.sq_clip trigger_off(); + } + maps/mp/zombies/_zm_spawner::register_zombie_death_event_callback( ::sq_zombie_death_event_response ); + declare_sidequest( "sq", ::init_sidequest, ::sidequest_logic, ::complete_sidequest, ::generic_stage_start, ::generic_stage_complete ); + init_sidequest_vo(); + precache_sidequest_assets(); + level thread survivor_vox(); + level thread avogadro_is_near_tower(); + level thread avogadro_far_from_tower(); + level thread avogadro_stab_watch(); + level thread init_navcard(); + level thread init_navcomputer(); + level.buildable_built_custom_func = ::builable_built_custom_func; + level thread richtofen_sidequest_power_state(); +} + +sq_easy_cleanup() +{ + computer_buildable_trig = getent( "sq_common_buildable_trigger", "targetname" ); + computer_buildable_trig delete(); + sq_buildables = getentarray( "buildable_sq_common", "targetname" ); + _a64 = sq_buildables; + _k64 = getFirstArrayKey( _a64 ); + while ( isDefined( _k64 ) ) + { + item = _a64[ _k64 ]; + item delete(); + _k64 = getNextArrayKey( _a64, _k64 ); + } +} + +init_player_sidequest_stats() +{ + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_started", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_maxis_reset", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_rich_reset", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_rich_stage_1", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_rich_stage_2", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_rich_stage_3", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_rich_complete", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_maxis_stage_1", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_maxis_stage_2", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_maxis_stage_3", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_maxis_complete", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_transit_last_completed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "navcard_held_zm_transit", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "navcard_held_zm_highrise", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "navcard_held_zm_buried", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "navcard_applied_zm_transit", 0 ); +} + +init_sidequest_vo() +{ + level.power_station_zones = []; + level.power_station_zones[ level.power_station_zones.size ] = "zone_trans_6"; + level.power_station_zones[ level.power_station_zones.size ] = "zone_amb_cornfield"; + level.power_station_zones[ level.power_station_zones.size ] = "zone_trans_7"; + level.power_station_zones[ level.power_station_zones.size ] = "zone_pow_ext1"; + level.power_station_zones[ level.power_station_zones.size ] = "zone_prr"; + level.power_station_zones[ level.power_station_zones.size ] = "zone_pcr"; + level.power_station_zones[ level.power_station_zones.size ] = "zone_pow_warehouse"; +} + +init_sidequest() +{ + players = get_players(); +} + +start_transit_sidequest() +{ + if ( level.gamedifficulty == 0 ) + { + return; + } + sidequest_start( "sq" ); +} + +sidequest_logic() +{ + level thread sidequest_main(); + wait_for_buildable( "sq_common" ); + if ( isDefined( level.navcomputer_spawned ) && !level.navcomputer_spawned ) + { + update_sidequest_stats( "sq_transit_started" ); + } + level thread navcomputer_waitfor_navcard(); + if ( flag( "power_on" ) ) + { + level thread richtofensay( "vox_zmba_sidequest_jet_terminal_0" ); + } + hint_said = 0; + while ( !hint_said ) + { + level waittill( "maxi_terminal_vox" ); + if ( flag( "power_on" ) ) + { + hint_said = 1; + } + wait 0,05; + } + maxissay( "vox_maxi_turbine_terminal_0", ( 11360, 8489, -576 ) ); +} + +complete_sidequest() +{ +} + +sidequest_main() +{ + sidequest_init_tracker(); + flag_wait( "start_zombie_round_logic" ); + level.maxcompleted = 0; + level.richcompleted = 0; + players = get_players(); + _a180 = players; + _k180 = getFirstArrayKey( _a180 ); + while ( isDefined( _k180 ) ) + { + player = _a180[ _k180 ]; + player.transit_sq_started = 1; + lastcompleted = player maps/mp/zombies/_zm_stats::get_global_stat( "sq_transit_last_completed" ); + if ( lastcompleted == 1 ) + { + level.richcompleted = 1; + } + else + { + if ( lastcompleted == 2 ) + { + level.maxcompleted = 1; + } + } + _k180 = getNextArrayKey( _a180, _k180 ); + } + if ( level.richcompleted ) + { + clientnotify( "sqrc" ); + wait 1; + } + if ( level.maxcompleted ) + { + clientnotify( "sqmc" ); + wait 1; + } + if ( level.richcompleted && level.maxcompleted ) + { + clientnotify( "sqkl" ); + return; + } + while ( 1 ) + { + level thread maxis_sidequest(); + flag_wait( "power_on" ); + if ( isDefined( level.maxcompleted ) && !level.maxcompleted ) + { + update_sidequest_stats( "sq_transit_maxis_reset" ); + } + if ( isDefined( level.maxis_sq_intro_said ) && !level.maxis_sq_intro_said && isDefined( level.maxcompleted ) && !level.maxcompleted ) + { + wait 2; + level.maxis_sq_intro_said = 1; + level thread maxissay( "vox_maxi_power_on_0", ( 12072, 8496, -704 ), undefined, undefined, 1 ); + } + level thread richtofen_sidequest(); + flag_waitopen( "power_on" ); + if ( isDefined( level.richcompleted ) && !level.richcompleted ) + { + update_sidequest_stats( "sq_transit_rich_reset" ); + } + } +} + +sidequest_init_tracker() +{ + level.sq_progress = []; + level.sq_progress = []; + level.sq_progress[ "maxis" ] = []; + level.sq_progress[ "maxis" ][ "A_turbine_1" ] = 0; + level.sq_progress[ "maxis" ][ "A_turbine_2" ] = 0; + level.sq_progress[ "maxis" ][ "A_complete" ] = 0; + level.sq_progress[ "maxis" ][ "B_complete" ] = 0; + level.sq_progress[ "maxis" ][ "C_turbine_1" ] = 0; + level.sq_progress[ "maxis" ][ "C_screecher_1" ] = 0; + level.sq_progress[ "maxis" ][ "C_turbine_2" ] = 0; + level.sq_progress[ "maxis" ][ "C_screecher_2" ] = 0; + level.sq_progress[ "maxis" ][ "C_complete" ] = 0; + level.sq_progress[ "maxis" ][ "FINISHED" ] = 0; + level.sq_progress[ "rich" ] = []; + level.sq_progress[ "rich" ][ "A_jetgun_built" ] = 0; + level.sq_progress[ "rich" ][ "A_jetgun_tower" ] = 0; + level.sq_progress[ "rich" ][ "A_complete" ] = 0; + level.sq_progress[ "rich" ][ "B_zombies_tower" ] = 0; + level.sq_progress[ "rich" ][ "B_complete" ] = 0; + level.sq_progress[ "rich" ][ "C_screecher_light" ] = 0; + level.sq_progress[ "rich" ][ "C_complete" ] = 0; + level.sq_progress[ "rich" ][ "FINISHED" ] = 0; +/# + if ( getDvarInt( #"113D490F" ) > 0 ) + { + level thread sidequest_debug_tracker(); +#/ + } +} + +sidequest_debug_tracker() +{ +/# + arraymainkeys = getarraykeys( level.sq_progress ); + index = 0; + x = 0; + while ( x < arraymainkeys.size ) + { + arraysubkeys = getarraykeys( level.sq_progress[ arraymainkeys[ x ] ] ); + _a289 = arraysubkeys; + _k289 = getFirstArrayKey( _a289 ); + while ( isDefined( _k289 ) ) + { + key = _a289[ _k289 ]; + hudelem = newhudelem(); + hudelem.alignx = "left"; + hudelem.location = 0; + hudelem.foreground = 1; + hudelem.fontscale = 1,1; + hudelem.sort = 20 - index; + hudelem.alpha = 1; + hudelem.x = 0; + hudelem.y = 60 + ( index * 15 ); + hudelem thread sidequest_debug_tracker_update( arraymainkeys[ x ], key ); + index++; + _k289 = getNextArrayKey( _a289, _k289 ); + } + x++; +#/ + } +} + +sidequest_debug_tracker_update( mainkey, subkey ) +{ +/# + while ( 1 ) + { + value = level.sq_progress[ mainkey ][ subkey ]; + str = ( mainkey + " -- " ) + subkey + ": "; + if ( isDefined( value ) && !isint( value ) && isDefined( value.classname ) ) + { + self settext( str + "[X]" ); + } + else + { + if ( isDefined( value ) ) + { + if ( !isint( value ) && !isDefined( value.classname ) && isDefined( value.targetname ) && value.targetname == "screecher_escape" ) + { + self settext( str + "[X]" ); + } + else + { + self settext( str + value ); + } + break; + } + else + { + self settext( str + "0" ); + } + } + wait 1; +#/ + } +} + +generic_stage_start() +{ + level._stage_active = 1; +} + +generic_stage_complete() +{ + level._stage_active = 0; +} + +maxis_sidequest() +{ + level endon( "power_on" ); + if ( flag( "power_on" ) || isDefined( level.maxcompleted ) && level.maxcompleted ) + { + return; + } + update_sidequest_stats( "sq_transit_maxis_stage_1" ); + level thread maxis_sidequest_a(); + level thread maxis_sidequest_b(); + level thread maxis_sidequest_c(); + level thread avogadro_stunned_vo(); +} + +turbine_power_watcher( player ) +{ + level endon( "end_avogadro_turbines" ); + self endon( "death" ); + self.powered = undefined; + turbine_failed_vo = undefined; + while ( isDefined( self ) ) + { + wait 2; + if ( is_true( player.turbine_power_is_on ) && !is_true( player.turbine_emped ) ) + { + self.powered = 1; + continue; + } + else + { + if ( is_true( player.turbine_emped ) || !is_true( player.turbine_power_is_on ) ) + { + wait 2; + self.powered = 0; + if ( !isDefined( turbine_failed_vo ) ) + { + level thread maxissay( "vox_maxi_turbines_out_0", self.origin ); + turbine_failed_vo = 1; + } + } + } + } +} + +maxis_sidequest_a() +{ + level endon( "power_on" ); + if ( isDefined( level.sq_progress[ "maxis" ][ "B_complete" ] ) && !level.sq_progress[ "maxis" ][ "B_complete" ] ) + { + level.sq_progress[ "maxis" ][ "A_complete" ] = 0; + } + while ( 1 ) + { + players = get_players(); + _a423 = players; + _k423 = getFirstArrayKey( _a423 ); + while ( isDefined( _k423 ) ) + { + player = _a423[ _k423 ]; + if ( isDefined( player.buildableturbine ) && player.buildableturbine istouching( level.sq_volume ) ) + { + level notify( "maxi_terminal_vox" ); + player.buildableturbine thread turbine_watch_cleanup(); + if ( !isDefined( level.sq_progress[ "maxis" ][ "A_turbine_1" ] ) ) + { + level.sq_progress[ "maxis" ][ "A_turbine_1" ] = player.buildableturbine; + level.sq_progress[ "maxis" ][ "A_turbine_1" ] thread turbine_power_watcher( player ); + break; + } + else + { + if ( !isDefined( level.sq_progress[ "maxis" ][ "A_turbine_2" ] ) ) + { + level.sq_progress[ "maxis" ][ "A_turbine_2" ] = player.buildableturbine; + level.sq_progress[ "maxis" ][ "A_turbine_2" ] thread turbine_power_watcher( player ); + } + } + } + _k423 = getNextArrayKey( _a423, _k423 ); + } + if ( get_how_many_progressed_from( "maxis", "A_turbine_1", "A_turbine_2" ) == 1 ) + { + level thread maxissay( "vox_maxi_turbine_1tower_0", ( 7737, -416, -142 ) ); + } + if ( get_how_many_progressed_from( "maxis", "A_turbine_1", "A_turbine_2" ) == 2 ) + { + if ( avogadro_at_tower() ) + { + level thread maxissay( "vox_maxi_turbine_2tower_avo_0", ( 7737, -416, -142 ) ); + } + else + { + level thread maxissay( "vox_maxi_turbine_2tower_0", ( 7737, -416, -142 ) ); + } + update_sidequest_stats( "sq_transit_maxis_stage_2" ); + level thread maxis_sidequest_complete_check( "A_complete" ); + } + level waittill_either( "turbine_deployed", "equip_turbine_zm_cleaned_up" ); + if ( !level.sq_progress[ "maxis" ][ "B_complete" ] ) + { + level.sq_progress[ "maxis" ][ "A_complete" ] = 0; + continue; + } + else + { + } + } +} + +maxis_sidequest_b() +{ + level endon( "power_on" ); + while ( 1 ) + { + level waittill( "stun_avogadro", avogadro ); + if ( isDefined( level.sq_progress[ "maxis" ][ "A_turbine_1" ] ) && is_true( level.sq_progress[ "maxis" ][ "A_turbine_1" ].powered ) && isDefined( level.sq_progress[ "maxis" ][ "A_turbine_2" ] ) && is_true( level.sq_progress[ "maxis" ][ "A_turbine_2" ].powered ) ) + { + if ( isDefined( avogadro ) && avogadro istouching( level.sq_volume ) ) + { + level notify( "end_avogadro_turbines" ); + break; + } + } + else + { + } + } + level notify( "maxis_stage_b" ); + level thread maxissay( "vox_maxi_avogadro_emp_0", ( 7737, -416, -142 ) ); + update_sidequest_stats( "sq_transit_maxis_stage_3" ); + player = get_players(); + player[ 0 ] setclientfield( "sq_tower_sparks", 1 ); + player[ 0 ] setclientfield( "screecher_maxis_lights", 1 ); + level thread maxis_sidequest_complete_check( "B_complete" ); +} + +maxis_sidequest_c() +{ + flag_wait( "power_on" ); + flag_waitopen( "power_on" ); + level endon( "power_on" ); + level.sq_progress[ "maxis" ][ "C_complete" ] = 0; + turbine_1_talked = 0; + turbine_2_talked = 0; + screech_zones = getstructarray( "screecher_escape", "targetname" ); + while ( 1 ) + { + if ( !isDefined( level.sq_progress[ "maxis" ][ "C_turbine_1" ] ) ) + { + } + if ( !isDefined( level.sq_progress[ "maxis" ][ "C_turbine_2" ] ) ) + { + } + players = get_players(); + _a548 = players; + _k548 = getFirstArrayKey( _a548 ); + while ( isDefined( _k548 ) ) + { + player = _a548[ _k548 ]; + while ( isDefined( player.buildableturbine ) ) + { + x = 0; + while ( x < screech_zones.size ) + { + zone = screech_zones[ x ]; + if ( distancesquared( player.buildableturbine.origin, zone.origin ) < ( zone.radius * zone.radius ) ) + { + player.buildableturbine thread turbine_watch_cleanup(); + if ( !isDefined( level.sq_progress[ "maxis" ][ "C_turbine_1" ] ) ) + { + if ( !isDefined( level.sq_progress[ "maxis" ][ "C_screecher_2" ] ) || zone != level.sq_progress[ "maxis" ][ "C_screecher_2" ] ) + { + level.sq_progress[ "maxis" ][ "C_turbine_1" ] = player.buildableturbine; + level.sq_progress[ "maxis" ][ "C_screecher_1" ] = zone; + } + x++; + continue; + } + else + { + if ( !isDefined( level.sq_progress[ "maxis" ][ "C_turbine_2" ] ) ) + { + if ( !isDefined( level.sq_progress[ "maxis" ][ "C_screecher_1" ] ) || zone != level.sq_progress[ "maxis" ][ "C_screecher_1" ] ) + { + level.sq_progress[ "maxis" ][ "C_turbine_2" ] = player.buildableturbine; + level.sq_progress[ "maxis" ][ "C_screecher_2" ] = zone; + } + } + } + } + x++; + } + } + _k548 = getNextArrayKey( _a548, _k548 ); + } + if ( get_how_many_progressed_from( "maxis", "C_turbine_1", "C_turbine_2" ) == 1 ) + { + zone = undefined; + if ( isDefined( level.sq_progress[ "maxis" ][ "C_turbine_1" ] ) ) + { + zone = level.sq_progress[ "maxis" ][ "C_screecher_1" ]; + } + else + { + zone = level.sq_progress[ "maxis" ][ "C_screecher_2" ]; + } + if ( isDefined( zone ) && !turbine_1_talked ) + { + turbine_1_talked = 1; + level thread maxissay( "vox_maxi_turbine_1light_0", zone.origin ); + } + } + if ( get_how_many_progressed_from( "maxis", "C_turbine_1", "C_turbine_2" ) == 2 ) + { + zone = undefined; + if ( isDefined( level.sq_progress[ "maxis" ][ "C_turbine_1" ] ) ) + { + zone = level.sq_progress[ "maxis" ][ "C_screecher_1" ]; + } + else + { + zone = level.sq_progress[ "maxis" ][ "C_screecher_2" ]; + } + if ( isDefined( zone ) ) + { + if ( level.sq_progress[ "maxis" ][ "B_complete" ] && level.sq_progress[ "maxis" ][ "A_complete" ] ) + { + if ( !turbine_2_talked ) + { + level thread maxissay( "vox_maxi_turbine_2light_on_0", zone.origin ); + turbine_2_talked = 1; + } + player = get_players(); + player[ 0 ] setclientfield( "screecher_maxis_lights", 0 ); + level maxis_sidequest_complete_check( "C_complete" ); + return; + break; + } + else + { + level thread maxissay( "vox_maxi_turbine_2light_off_0", zone.origin ); + } + } + } + level waittill_either( "turbine_deployed", "equip_turbine_zm_cleaned_up" ); + level.sq_progress[ "maxis" ][ "C_complete" ] = 0; + } +} + +maxis_sidequest_complete_check( nowcomplete ) +{ + level.sq_progress[ "maxis" ][ nowcomplete ] = 1; + if ( level.sq_progress[ "maxis" ][ "A_complete" ] && level.sq_progress[ "maxis" ][ "B_complete" ] && level.sq_progress[ "maxis" ][ "C_complete" ] ) + { + level maxis_sidequest_complete(); + } +} + +maxis_sidequest_complete() +{ + turbinescriptnoteworthy1 = undefined; + turbinescriptnoteworthy2 = undefined; + if ( isDefined( level.sq_progress[ "maxis" ][ "C_screecher_1" ] ) && isDefined( level.sq_progress[ "maxis" ][ "C_screecher_1" ].script_noteworthy ) ) + { + turbinescriptnoteworthy1 = level.sq_progress[ "maxis" ][ "C_screecher_1" ].script_noteworthy; + } + if ( isDefined( level.sq_progress[ "maxis" ][ "C_screecher_2" ] ) && isDefined( level.sq_progress[ "maxis" ][ "C_screecher_2" ].script_noteworthy ) ) + { + turbinescriptnoteworthy2 = level.sq_progress[ "maxis" ][ "C_screecher_2" ].script_noteworthy; + } + update_sidequest_stats( "sq_transit_maxis_complete" ); + level sidequest_complete( "maxis" ); + level.sq_progress[ "maxis" ][ "FINISHED" ] = 1; + level.maxcompleted = 1; + clientnotify( "sq_kfx" ); + if ( isDefined( level.richcompleted ) && level.richcompleted ) + { + level clientnotify( "sq_krt" ); + } + wait 1; + clientnotify( "sqm" ); + wait 1; + level set_screecher_zone_origin( turbinescriptnoteworthy1 ); + wait 1; + clientnotify( "sq_max" ); + wait 1; + level set_screecher_zone_origin( turbinescriptnoteworthy2 ); + wait 1; + clientnotify( "sq_max" ); + level thread droppowerup( "maxis" ); +} + +richtofen_sidequest() +{ + level endon( "power_turned_off" ); + if ( !flag( "power_on" ) || isDefined( level.richcompleted ) && level.richcompleted ) + { + return; + } + if ( isDefined( level.richtofen_sq_intro_said ) && !level.richtofen_sq_intro_said ) + { + level thread wait_for_richtoffen_intro(); + } + update_sidequest_stats( "sq_transit_rich_stage_1" ); + level thread richtofen_sidequest_a(); + level thread richtofen_sidequest_b(); + level thread richtofen_sidequest_c(); +} + +richtofen_sidequest_power_state() +{ + flag_wait( "power_on" ); + while ( 1 ) + { + flag_waitopen( "power_on" ); + level notify( "power_turned_off" ); + level notify( "power_off" ); + level thread maxissay( "vox_maxi_power_off_0", ( 12072, 8496, -704 ), undefined, undefined, 1 ); + wait 7; + level thread richtofensay( "vox_zmba_sidequest_power_off_0", undefined, 1, 15 ); + flag_wait( "power_on" ); + level thread richtofensay( "vox_zmba_sidequest_emp_off_0", undefined, 1, 15 ); + wait 7; + level thread maxissay( "vox_maxi_emp_off_0", ( 12072, 8496, -704 ), undefined, undefined, 1 ); + } +} + +richtofen_sidequest_a() +{ + level endon( "power_off" ); + level.sq_progress[ "rich" ][ "A_jetgun_built" ] = 0; + level.sq_progress[ "rich" ][ "A_jetgun_tower" ] = 0; + level.sq_progress[ "rich" ][ "A_complete" ] = 0; + ric_fail_out = undefined; + ric_fail_heat = undefined; + if ( isDefined( level.buildables_built[ "jetgun_zm" ] ) && !level.buildables_built[ "jetgun_zm" ] ) + { + wait_for_buildable( "jetgun_zm" ); + } + level.sq_progress[ "rich" ][ "A_jetgun_built" ] = 1; + while ( 1 ) + { + level.sq_volume waittill( "trigger", who ); + if ( isplayer( who ) && isalive( who ) && who getcurrentweapon() == "jetgun_zm" || !isDefined( who.jetgun_heatval ) && who.jetgun_heatval < 1 ) + { + who thread left_sq_area_watcher( level.sq_volume ); + notifystring = who waittill_any_return( "disconnect", "weapon_change", "death", "player_downed", "jetgun_overheated", "left_sg_area" ); + if ( notifystring == "jetgun_overheated" && isDefined( who ) && who istouching( level.sq_volume ) ) + { + self.checking_jetgun_fire = 0; + break; + } + else if ( !isDefined( ric_fail_out ) ) + { + ric_fail_out = 1; + level thread richtofensay( "vox_zmba_sidequest_jet_low_0", undefined, 0, 10 ); + } + self.checking_jetgun_fire = 0; + continue; + } + else + { + if ( isplayer( who ) && isalive( who ) && who getcurrentweapon() == "jetgun_zm" && isDefined( who.jetgun_heatval ) && who.jetgun_heatval > 1 ) + { + if ( !isDefined( ric_fail_heat ) ) + { + ric_fail_heat = 1; + level thread richtofensay( "vox_zmba_sidequest_jet_low_0", undefined, 0, 10 ); + } + } + } + } + level thread richtofensay( "vox_zmba_sidequest_jet_empty_0", undefined, 0, 16 ); + player = get_players(); + player[ 0 ] setclientfield( "screecher_sq_lights", 1 ); + update_sidequest_stats( "sq_transit_rich_stage_2" ); + level thread richtofen_sidequest_complete_check( "A_complete" ); + level.sq_progress[ "rich" ][ "A_jetgun_tower" ] = 1; +} + +left_sq_area_watcher( volume ) +{ + while ( self istouching( volume ) ) + { + wait 0,5; + } + self notify( "left_sg_area" ); +} + +richtofen_sidequest_b() +{ + level endon( "power_off" ); + level.sq_progress[ "rich" ][ "B_zombies_tower" ] = 25; + level thread lure_zombies_to_tower_hint(); + while ( level.sq_progress[ "rich" ][ "B_zombies_tower" ] > 0 ) + { + level waittill( "zombie_died_in_sq_volume" ); + while ( !level.sq_progress[ "rich" ][ "A_complete" ] ) + { + level thread richtofensay( "vox_zmba_sidequest_blow_mag_0" ); + } + level.sq_progress[ "rich" ][ "B_zombies_tower" ]--; + + if ( level.sq_progress[ "rich" ][ "B_zombies_tower" ] > 0 ) + { + } + } + level thread richtofensay( "vox_zmba_sidequest_blow_nomag_0" ); + update_sidequest_stats( "sq_transit_rich_stage_3" ); + level notify( "sq_stage_3complete" ); + level thread richtofen_sidequest_complete_check( "B_complete" ); +} + +lure_zombies_to_tower_hint() +{ + level endon( "power_on" ); + level endon( "sq_stage_3complete" ); + zombie_train = 0; + lure_distance = 722500; + while ( !zombie_train ) + { + zombies = getaiarray(); + counter = 0; + _a881 = zombies; + _k881 = getFirstArrayKey( _a881 ); + while ( isDefined( _k881 ) ) + { + zombie = _a881[ _k881 ]; + if ( distancesquared( zombie.origin, level.sq_volume.origin ) < lure_distance ) + { + counter++; + } + _k881 = getNextArrayKey( _a881, _k881 ); + } + if ( counter >= 5 ) + { + zombie_train = 1; + } + wait 3; + } + level thread richtofensay( "vox_zmba_sidequest_zom_lure_0" ); +} + +richtofen_sidequest_c() +{ + level endon( "power_off" ); + level endon( "richtofen_sq_complete" ); + screech_zones = getstructarray( "screecher_escape", "targetname" ); + level thread screecher_light_hint(); + level thread screecher_light_on_sq(); + level.sq_richtofen_c_screecher_lights = []; + while ( 1 ) + { + level waittill( "safety_light_power_off", screecher_zone ); + while ( !level.sq_progress[ "rich" ][ "A_complete" ] || !level.sq_progress[ "rich" ][ "B_complete" ] ) + { + level thread richtofensay( "vox_zmba_sidequest_emp_nomag_0" ); + } + level.sq_richtofen_c_screecher_lights[ level.sq_richtofen_c_screecher_lights.size ] = screecher_zone; + level.sq_progress[ "rich" ][ "C_screecher_light" ]++; + if ( level.sq_progress[ "rich" ][ "C_screecher_light" ] >= 4 ) + { + break; + } + else + { + if ( isDefined( level.checking_for_richtofen_c_failure ) && !level.checking_for_richtofen_c_failure ) + { + level thread check_for_richtofen_c_failure(); + } + } + } + level thread richtofensay( "vox_zmba_sidequest_4emp_mag_0" ); + level notify( "richtofen_c_complete" ); + player = get_players(); + player[ 0 ] setclientfield( "screecher_sq_lights", 0 ); + level thread richtofen_sidequest_complete_check( "C_complete" ); +} + +check_for_richtofen_c_failure() +{ + if ( isDefined( level.checking_for_richtofen_c_failure ) && !level.checking_for_richtofen_c_failure ) + { + level.checking_for_richtofen_c_failure = 1; + wait 5; + if ( level.sq_progress[ "rich" ][ "C_screecher_light" ] < 4 ) + { + level thread richtofensay( "vox_zmba_sidequest_3emp_mag_0" ); + level.sq_progress[ "rich" ][ "C_screecher_light" ] = 0; + } + level.checking_for_richtofen_c_failure = 0; + } +} + +screecher_light_on_sq() +{ + while ( 1 ) + { + level waittill( "safety_light_power_on", screecher_zone ); + arrayremovevalue( level.sq_richtofen_c_screecher_lights, screecher_zone ); + if ( level.sq_progress[ "rich" ][ "C_screecher_light" ] > 0 ) + { + level.sq_progress[ "rich" ][ "C_screecher_light" ]--; + + } + } +} + +richtofen_sidequest_complete_check( nowcomplete ) +{ + level.sq_progress[ "rich" ][ nowcomplete ] = 1; + if ( level.sq_progress[ "rich" ][ "A_complete" ] && level.sq_progress[ "rich" ][ "B_complete" ] && level.sq_progress[ "rich" ][ "C_complete" ] ) + { + level thread richtofen_sidequest_complete(); + } +} + +richtofen_sidequest_complete() +{ + update_sidequest_stats( "sq_transit_rich_complete" ); + level thread sidequest_complete( "richtofen" ); + level.sq_progress[ "rich" ][ "FINISHED" ] = 1; + level.richcompleted = 1; + clientnotify( "sq_kfx" ); + if ( isDefined( level.maxcompleted ) && level.maxcompleted ) + { + level clientnotify( "sq_kmt" ); + } + wait 1; + clientnotify( "sqr" ); + _a1007 = level.sq_richtofen_c_screecher_lights; + _k1007 = getFirstArrayKey( _a1007 ); + while ( isDefined( _k1007 ) ) + { + zone = _a1007[ _k1007 ]; + level set_screecher_zone_origin( zone.target.script_noteworthy ); + wait 1; + clientnotify( "sq_rich" ); + wait 1; + _k1007 = getNextArrayKey( _a1007, _k1007 ); + } + level thread droppowerup( "richtofen" ); +} + +set_screecher_zone_origin( script_noteworthy ) +{ + if ( !isDefined( script_noteworthy ) ) + { + return; + } + switch( script_noteworthy ) + { + case "cornfield": + clientnotify( "zsc" ); + break; + case "diner": + clientnotify( "zsd" ); + break; + case "forest": + clientnotify( "zsf" ); + break; + case "busdepot": + clientnotify( "zsb" ); + break; + case "bridgedepot": + clientnotify( "zsbd" ); + break; + case "townbridge": + clientnotify( "zsbt" ); + break; + case "huntershack": + clientnotify( "zsh" ); + break; + case "powerstation": + clientnotify( "zsp" ); + break; + } +} + +turbine_watch_cleanup() +{ + if ( isDefined( self.turbine_watch_cleanup ) && self.turbine_watch_cleanup ) + { + return; + } + self.turbine_watch_cleanup = 1; + self waittill( "death" ); + level notify( "equip_turbine_zm_cleaned_up" ); +} + +get_how_many_progressed_from( story, a, b ) +{ + if ( isDefined( level.sq_progress[ story ][ a ] ) || !isDefined( level.sq_progress[ story ][ b ] ) && !isDefined( level.sq_progress[ story ][ a ] ) && isDefined( level.sq_progress[ story ][ b ] ) ) + { + return 1; + } + else + { + if ( isDefined( level.sq_progress[ story ][ a ] ) && isDefined( level.sq_progress[ story ][ b ] ) ) + { + return 2; + } + } + return 0; +} + +sq_zombie_death_event_response() +{ + if ( distancesquared( self.origin, level.sq_volume.origin ) < 176400 && isDefined( self.damagemod ) ) + { + mod = self.damagemod; + if ( mod != "MOD_GRENADE" && mod != "MOD_GRENADE_SPLASH" && mod != "MOD_EXPLOSIVE" && mod != "MOD_EXPLOSIVE_SPLASH" || mod == "MOD_PROJECTILE" && mod == "MOD_PROJECTILE_SPLASH" ) + { + level notify( "zombie_died_in_sq_volume" ); + } + } +} + +update_sidequest_stats( stat_name ) +{ + maxis_complete = 0; + rich_complete = 0; + started = 0; + if ( stat_name == "sq_transit_maxis_complete" ) + { + maxis_complete = 1; + } + else + { + if ( stat_name == "sq_transit_rich_complete" ) + { + rich_complete = 1; + } + } + players = get_players(); + _a1124 = players; + _k1124 = getFirstArrayKey( _a1124 ); + while ( isDefined( _k1124 ) ) + { + player = _a1124[ _k1124 ]; + if ( stat_name == "sq_transit_started" ) + { + player.transit_sq_started = 1; + } + else if ( stat_name == "navcard_applied_zm_transit" ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( level.navcard_needed, 0 ); + thread sq_refresh_player_navcard_hud(); + } + else + { + if ( isDefined( player.transit_sq_started ) && !player.transit_sq_started ) + { + } + } + else + { + if ( rich_complete ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( "sq_transit_last_completed", 1 ); + incrementcounter( "global_zm_total_rich_sq_complete_transit", 1 ); + } + else + { + if ( maxis_complete ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( "sq_transit_last_completed", 2 ); + incrementcounter( "global_zm_total_max_sq_complete_transit", 1 ); + } + } + player maps/mp/zombies/_zm_stats::increment_client_stat( stat_name, 0 ); + } + _k1124 = getNextArrayKey( _a1124, _k1124 ); + } + if ( rich_complete || maxis_complete ) + { + level notify( "transit_sidequest_achieved" ); + } +} + +richtofensay( vox_line, intro, ignore_power_state, time ) +{ + level endon( "end_game" ); + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + if ( isDefined( level.richcompleted ) && level.richcompleted ) + { + return; + } + level endon( "richtofen_c_complete" ); + if ( !isDefined( time ) ) + { + time = 45; + } + while ( isDefined( level.richtofen_talking_to_samuel ) || level.richtofen_talking_to_samuel && isDefined( level.richtofen_sq_intro_said ) && !level.richtofen_sq_intro_said ) + { + wait 1; + } + if ( isDefined( level.rich_sq_player ) && is_player_valid( level.rich_sq_player ) ) + { +/# + iprintlnbold( "Richtoffen Says: " + vox_line ); +#/ + if ( flag( "power_on" ) && !flag( "switches_on" ) && isDefined( ignore_power_state ) && !ignore_power_state ) + { + return; + } + level.rich_sq_player playsoundtoplayer( vox_line, level.rich_sq_player ); + if ( isDefined( level.richtofen_talking_to_samuel ) && !level.richtofen_talking_to_samuel ) + { + level thread richtofen_talking( time ); + } + } +} + +richtofen_talking( time ) +{ + level.rich_sq_player.dontspeak = 1; + level.richtofen_talking_to_samuel = 1; + wait time; + level.richtofen_talking_to_samuel = 0; + if ( isDefined( level.rich_sq_player ) ) + { + level.rich_sq_player.dontspeak = 0; + } +} + +maxissay( line, org, playonent, playonenttag, ignore_power_state ) +{ + level endon( "end_game" ); + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + if ( isDefined( level.maxcompleted ) && level.maxcompleted ) + { + return; + } + if ( !flag( "power_on" ) && flag( "switches_on" ) && isDefined( ignore_power_state ) && !ignore_power_state ) + { + return; + } + while ( isDefined( level.maxis_talking ) && level.maxis_talking ) + { + wait 0,05; + } + level.maxis_talking = 1; +/# + iprintlnbold( "Maxis Says: " + line ); +#/ + if ( isDefined( playonent ) ) + { + playonent playsoundontag( line, playonenttag ); + } + else + { + playsoundatposition( line, org ); + } + wait 10; + level.maxis_talking = 0; +} + +wait_for_richtoffen_intro() +{ + level endon( "intermission" ); + power_occupied = 1; + while ( power_occupied ) + { + inzone = 0; + _a1274 = level.power_station_zones; + _k1274 = getFirstArrayKey( _a1274 ); + while ( isDefined( _k1274 ) ) + { + zone = _a1274[ _k1274 ]; + if ( isDefined( maps/mp/zombies/_zm_zonemgr::player_in_zone( zone ) ) && maps/mp/zombies/_zm_zonemgr::player_in_zone( zone ) ) + { + inzone = 1; + } + _k1274 = getNextArrayKey( _a1274, _k1274 ); + } + if ( !inzone ) + { + power_occupied = 0; + } + wait 0,1; + } + wait 5; + if ( !isDefined( level.rich_sq_player ) || !flag( "power_on" ) && !flag( "switches_on" ) ) + { + return; + } + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + level.rich_sq_player playsoundtoplayer( "vox_zmba_sidequest_power_on_0", level.rich_sq_player ); + richtofen_talking( 45 ); + level.richtofen_sq_intro_said = 1; +} + +survivor_vox() +{ + initiated = 0; + while ( !initiated ) + { + players = get_players(); + _a1314 = players; + _k1314 = getFirstArrayKey( _a1314 ); + while ( isDefined( _k1314 ) ) + { + player = _a1314[ _k1314 ]; + if ( distance2dsquared( player.origin, ( 8000, -6656, 160 ) ) < 1225 ) + { + if ( player usebuttonpressed() ) + { + playsoundatposition( "zmb_zombie_arc", ( 8000, -6656, 160 ) ); + start_time = getTime(); + end_time = start_time + 5000; + while ( player usebuttonpressed() && distance2dsquared( player.origin, ( 8000, -6656, 160 ) ) < 1225 && is_player_valid( player ) ) + { + if ( getTime() > end_time ) + { + initiated = 1; + } + wait 0,05; + } + playsoundatposition( "zmb_buildable_piece_add", ( 8000, -6656, 160 ) ); + } + } + _k1314 = getNextArrayKey( _a1314, _k1314 ); + } + wait 1; + } + playsoundatposition( "zmb_weap_wall", ( 8000, -6656, 160 ) ); + i = -1; + while ( 1 ) + { + players = get_players(); + _a1343 = players; + _k1343 = getFirstArrayKey( _a1343 ); + while ( isDefined( _k1343 ) ) + { + player = _a1343[ _k1343 ]; + if ( distance2dsquared( player.origin, ( 8000, -6656, 160 ) ) < 1225 ) + { + if ( player usebuttonpressed() && is_player_valid( player ) ) + { + if ( flag( "power_on" ) ) + { + if ( i == -1 || i > 4 ) + { + playsoundatposition( "vox_maxi_tv_distress_0", ( 8000, -6656, 160 ) ); + i++; + continue; + } + else + { + if ( i < 4 ) + { + playsoundatposition( level.survivor_vox[ i ], ( 8000, -6656, 160 ) ); + } + } + i++; + } + wait 60; + } + } + _k1343 = getNextArrayKey( _a1343, _k1343 ); + } + wait 1; + } +} + +builable_built_custom_func( buildable ) +{ + if ( buildable.buildable_name == "jetgun_zm" ) + { + if ( flag( "power_on" ) || flag( "switches_on" ) ) + { + level thread richtofensay( "vox_zmba_sidequest_jet_complete_0" ); + level.sq_jetgun_built = 1; + } + } +} + +screecher_light_hint() +{ + level endon( "power_off" ); + level endon( "richtofen_c_complete" ); + while ( !level.sq_progress[ "rich" ][ "A_jetgun_tower" ] ) + { + wait 1; + } + screech_zones = getstructarray( "screecher_escape", "targetname" ); + dist = 122500; + while ( 1 ) + { + count = 0; + players = get_players(); + _a1399 = players; + _k1399 = getFirstArrayKey( _a1399 ); + while ( isDefined( _k1399 ) ) + { + player = _a1399[ _k1399 ]; + _a1401 = screech_zones; + _k1401 = getFirstArrayKey( _a1401 ); + while ( isDefined( _k1401 ) ) + { + zone = _a1401[ _k1401 ]; + if ( distancesquared( player.origin, zone.origin ) < dist ) + { + if ( player maps/mp/zombies/_zm_weapons::has_weapon_or_upgrade( "emp_grenade_zm" ) ) + { + count++; + } + } + _k1401 = getNextArrayKey( _a1401, _k1401 ); + } + _k1399 = getNextArrayKey( _a1399, _k1399 ); + } + if ( count >= players.size ) + { + richtofensay( "vox_zmba_sidequest_near_light_0" ); + return; + } + wait 2; + } +} + +maxi_near_corn_hint() +{ + level endon( "power_on" ); + say_hint = 0; + while ( !say_hint ) + { + players = get_players(); + _a1430 = players; + _k1430 = getFirstArrayKey( _a1430 ); + while ( isDefined( _k1430 ) ) + { + player = _a1430[ _k1430 ]; + if ( !player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_amb_cornfield" ) ) + { + } + else if ( isDefined( player.buildableturbine ) && isDefined( player.buildableturbine.equipment_can_move ) && player.buildableturbine.equipment_can_move && isDefined( player.isonbus ) && player.isonbus ) + { + say_hint = 1; + } + else + { + if ( isDefined( player.buildableturbine ) && isDefined( player.isonbus ) && player.isonbus ) + { + say_hint = 1; + } + } + _k1430 = getNextArrayKey( _a1430, _k1430 ); + } + wait 2; + } + level thread maxissay( "vox_maxi_near_corn_0", undefined, level.automaton, "J_neck" ); +} + +avogadro_far_from_tower() +{ + if ( isDefined( level.maxcompleted ) && level.maxcompleted ) + { + return; + } + level waittill( "power_on" ); + level endon( "power_on" ); + say_hint = 0; + while ( !say_hint ) + { + players = get_players(); + _a1466 = players; + _k1466 = getFirstArrayKey( _a1466 ); + while ( isDefined( _k1466 ) ) + { + player = _a1466[ _k1466 ]; + if ( isDefined( player.isonbus ) && !player.isonbus ) + { + } + else + { + if ( !avogadro_near_tower() && player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_amb_cornfield" ) ) + { + say_hint = 1; + } + } + _k1466 = getNextArrayKey( _a1466, _k1466 ); + } + wait 1; + } + level thread maxissay( "vox_maxi_avogadro_far_0", undefined, level.automaton, "J_neck" ); +} + +avogadro_near_tower() +{ + if ( isDefined( level.avogadro ) && level.avogadro maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_amb_cornfield" ) ) + { + return 1; + } + return 0; +} + +avogadro_stab_watch() +{ + if ( isDefined( level.maxcompleted ) && level.maxcompleted ) + { + return; + } + level waittill( "avogadro_stabbed", avogadro ); + if ( !flag( "power_on" ) ) + { + level thread maxissay( "vox_maxi_avogadro_stab_0", avogadro.origin ); + } +} + +avogadro_is_near_tower() +{ + if ( isDefined( level.maxcompleted ) && level.maxcompleted ) + { + return; + } + level waittill( "power_on" ); + level endon( "power_on" ); + say_hint = 0; + while ( !say_hint ) + { + if ( avogadro_near_tower() ) + { + say_hint = 1; + } + wait 1; + } + level thread maxissay( "vox_maxi_avogadro_near_0", ( 7737, -416, -142 ) ); +} + +avogadro_at_tower() +{ + if ( isDefined( level.avogadro ) && level.avogadro istouching( level.sq_volume ) ) + { + return 1; + } + return 0; +} + +droppowerup( story ) +{ + center_struct = getstruct( "sq_common_tower_fx", "targetname" ); + trace = bullettrace( center_struct.origin, center_struct.origin - vectorScale( ( 0, 0, 0 ), 999999 ), 0, undefined ); + poweruporigin = trace[ "position" ] + vectorScale( ( 0, 0, 0 ), 25 ); + mintime = 240; + maxtime = 720; + while ( 1 ) + { + trail = spawn( "script_model", center_struct.origin ); + trail setmodel( "tag_origin" ); + wait 0,5; + playfxontag( level._effect[ story + "_sparks" ], trail, "tag_origin" ); + trail moveto( poweruporigin, 10 ); + trail waittill( "movedone" ); + level thread droppoweruptemptation( story, poweruporigin ); + wait 1; + trail delete(); + wait randomintrange( mintime, maxtime ); + } +} + +droppoweruptemptation( story, origin ) +{ + powerup = spawn( "script_model", origin ); + powerup endon( "powerup_grabbed" ); + powerup endon( "powerup_timedout" ); + temptation_array = array( "insta_kill", "nuke", "double_points", "carpenter" ); + temptation_index = 0; + first_time = 1; + rotation = 0; + temptation_array = array_randomize( temptation_array ); + while ( isDefined( powerup ) ) + { + powerup maps/mp/zombies/_zm_powerups::powerup_setup( temptation_array[ temptation_index ] ); + if ( first_time ) + { + powerup thread maps/mp/zombies/_zm_powerups::powerup_timeout(); + powerup thread maps/mp/zombies/_zm_powerups::powerup_wobble(); + powerup thread maps/mp/zombies/_zm_powerups::powerup_grab(); + first_time = 0; + } + if ( rotation == 0 ) + { + wait 15; + rotation++; + temptation_index++; + continue; + } + else if ( rotation == 1 ) + { + wait 7,5; + rotation++; + temptation_index++; + continue; + } + else if ( rotation == 2 ) + { + wait 2,5; + rotation++; + temptation_index++; + continue; + } + else + { + wait 1,5; + rotation++; + } + temptation_index++; + if ( temptation_index >= temptation_array.size ) + { + temptation_index = 0; + } + } +} + +init_navcard() +{ + flag_wait( "start_zombie_round_logic" ); + spawn_card = 1; + players = get_players(); + _a1634 = players; + _k1634 = getFirstArrayKey( _a1634 ); + while ( isDefined( _k1634 ) ) + { + player = _a1634[ _k1634 ]; + has_card = does_player_have_map_navcard( player ); + if ( has_card ) + { + player.navcard_grabbed = level.map_navcard; + spawn_card = 0; + } + _k1634 = getNextArrayKey( _a1634, _k1634 ); + } + thread sq_refresh_player_navcard_hud(); + if ( !spawn_card ) + { + return; + } + model = "p6_zm_keycard"; + org = ( -6245, 5479,5, -55,35 ); + angles = ( 0, 0, 0 ); + maps/mp/zombies/_zm_utility::place_navcard( model, level.map_navcard, org, angles ); +} + +init_navcomputer() +{ + flag_wait( "start_zombie_round_logic" ); + spawn_navcomputer = 1; + players = get_players(); + _a1664 = players; + _k1664 = getFirstArrayKey( _a1664 ); + while ( isDefined( _k1664 ) ) + { + player = _a1664[ _k1664 ]; + built_comptuer = player maps/mp/zombies/_zm_stats::get_global_stat( "sq_transit_started" ); + if ( !built_comptuer ) + { + spawn_navcomputer = 0; + break; + } + else + { + _k1664 = getNextArrayKey( _a1664, _k1664 ); + } + } + if ( !spawn_navcomputer ) + { + return; + } + level.navcomputer_spawned = 1; + get_players()[ 0 ] maps/mp/zombies/_zm_buildables::player_finish_buildable( level.sq_buildable.buildablezone ); + while ( isDefined( level.sq_buildable ) && isDefined( level.sq_buildable.model ) ) + { + buildable = level.sq_buildable.buildablezone; + i = 0; + while ( i < buildable.pieces.size ) + { + if ( isDefined( buildable.pieces[ i ].model ) ) + { + buildable.pieces[ i ].model delete(); + maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( buildable.pieces[ i ].unitrigger ); + } + if ( isDefined( buildable.pieces[ i ].part_name ) ) + { + buildable.stub.model notsolid(); + buildable.stub.model show(); + buildable.stub.model showpart( buildable.pieces[ i ].part_name ); + } + i++; + } + } + level thread navcomputer_waitfor_navcard(); +} + +navcomputer_waitfor_navcard() +{ + computer_buildable_trig = getent( "sq_common_buildable_trigger", "targetname" ); + trig_pos = getstruct( "sq_common_key", "targetname" ); + navcomputer_use_trig = spawn( "trigger_radius_use", trig_pos.origin, 0, 48, 48 ); + navcomputer_use_trig setcursorhint( "HINT_NOICON" ); + navcomputer_use_trig sethintstring( &"ZOMBIE_NAVCARD_USE" ); + navcomputer_use_trig triggerignoreteam(); + while ( 1 ) + { + navcomputer_use_trig waittill( "trigger", who ); + if ( isplayer( who ) && is_player_valid( who ) ) + { + if ( does_player_have_correct_navcard( who ) ) + { + navcomputer_use_trig sethintstring( &"ZOMBIE_NAVCARD_SUCCESS" ); + who playsound( "zmb_sq_navcard_success" ); + update_sidequest_stats( "navcard_applied_zm_transit" ); + return; + break; + } + else + { + navcomputer_use_trig sethintstring( &"ZOMBIE_NAVCARD_FAIL" ); + wait 1; + navcomputer_use_trig sethintstring( &"ZOMBIE_NAVCARD_USE" ); + } + } + } +} + +avogadro_stunned_vo() +{ + level endon( "maxis_stage_b" ); + while ( 1 ) + { + level waittill( "stun_avogadro", avogadro ); + if ( avogadro maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr" ) ) + { + level thread maxissay( "vox_maxi_avogadro_stab_0", ( 12072, 8496, -704 ) ); + return; + } + } +} + +sq_refresh_player_navcard_hud() +{ + if ( !isDefined( level.navcards ) ) + { + return; + } + players = get_players(); + _a1759 = players; + _k1759 = getFirstArrayKey( _a1759 ); + while ( isDefined( _k1759 ) ) + { + player = _a1759[ _k1759 ]; + navcard_bits = 0; + i = 0; + while ( i < level.navcards.size ) + { + hasit = player maps/mp/zombies/_zm_stats::get_global_stat( level.navcards[ i ] ); + if ( isDefined( player.navcard_grabbed ) && player.navcard_grabbed == level.navcards[ i ] ) + { + hasit = 1; + } + if ( hasit ) + { + navcard_bits += 1 << i; + } + i++; + } + wait_network_frame(); + player setclientfield( "navcard_held", 0 ); + if ( navcard_bits > 0 ) + { + wait_network_frame(); + player setclientfield( "navcard_held", navcard_bits ); + } + _k1759 = getNextArrayKey( _a1759, _k1759 ); + } +} diff --git a/zm_transit_patch/maps/mp/zm_transit_standard_farm.gsc b/zm_transit_patch/maps/mp/zm_transit_standard_farm.gsc new file mode 100644 index 0000000..49f999d --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_standard_farm.gsc @@ -0,0 +1,95 @@ +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_race_utility; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ +} + +farm_treasure_chest_init() +{ + chest1 = getstruct( "farm_chest", "script_noteworthy" ); + level.chests = []; + level.chests[ level.chests.size ] = chest1; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "farm_chest" ); +} + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "farm" ); + init_standard_farm(); + farm_treasure_chest_init(); + level.enemy_location_override_func = ::enemy_location_override; + flag_wait( "initial_blackscreen_passed" ); + level thread maps/mp/zombies/_zm_zonemgr::enable_zone( "zone_far_ext" ); + level thread maps/mp/zombies/_zm_zonemgr::enable_zone( "zone_brn" ); + maps/mp/zombies/_zm_game_module::turn_power_on_and_open_doors(); + flag_wait( "start_zombie_round_logic" ); + wait 1; + level notify( "revive_on" ); + wait_network_frame(); + level notify( "doubletap_on" ); + wait_network_frame(); + level notify( "juggernog_on" ); + wait_network_frame(); + level notify( "sleight_on" ); + wait_network_frame(); +} + +init_standard_farm() +{ + maps/mp/zombies/_zm_game_module::set_current_game_module( level.game_module_standard_index ); + ents = getentarray(); + _a77 = ents; + _k77 = getFirstArrayKey( _a77 ); + while ( isDefined( _k77 ) ) + { + ent = _a77[ _k77 ]; + if ( isDefined( ent.script_flag ) && ent.script_flag == "OnFarm_enter" ) + { + ent delete(); + } + else + { + if ( isDefined( ent.script_parameters ) ) + { + tokens = strtok( ent.script_parameters, " " ); + remove = 0; + _a88 = tokens; + _k88 = getFirstArrayKey( _a88 ); + while ( isDefined( _k88 ) ) + { + token = _a88[ _k88 ]; + if ( token == "standard_remove" ) + { + remove = 1; + } + _k88 = getNextArrayKey( _a88, _k88 ); + } + if ( remove ) + { + ent delete(); + } + } + } + _k77 = getNextArrayKey( _a77, _k77 ); + } +} + +enemy_location_override( zombie, enemy ) +{ + location = enemy.origin; + if ( is_true( self.reroute ) ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + return location; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_standard_town.gsc b/zm_transit_patch/maps/mp/zm_transit_standard_town.gsc new file mode 100644 index 0000000..b49f73f --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_standard_town.gsc @@ -0,0 +1,64 @@ +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zm_transit_utility; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_race_utility; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ + precachemodel( "zm_collision_transit_town_survival" ); +} + +town_treasure_chest_init() +{ + chest1 = getstruct( "town_chest", "script_noteworthy" ); + chest2 = getstruct( "town_chest_2", "script_noteworthy" ); + level.chests = []; + level.chests[ level.chests.size ] = chest1; + level.chests[ level.chests.size ] = chest2; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "town_chest" ); +} + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "town" ); + town_treasure_chest_init(); + level.enemy_location_override_func = ::enemy_location_override; + collision = spawn( "script_model", ( 1363, 471, 0 ), 1 ); + collision setmodel( "zm_collision_transit_town_survival" ); + collision disconnectpaths(); + flag_wait( "initial_blackscreen_passed" ); + level thread maps/mp/zm_transit_utility::solo_tombstone_removal(); + maps/mp/zombies/_zm_game_module::turn_power_on_and_open_doors(); + flag_wait( "start_zombie_round_logic" ); + wait 1; + level notify( "revive_on" ); + wait_network_frame(); + level notify( "doubletap_on" ); + wait_network_frame(); + level notify( "marathon_on" ); + wait_network_frame(); + level notify( "juggernog_on" ); + wait_network_frame(); + level notify( "sleight_on" ); + wait_network_frame(); + level notify( "tombstone_on" ); + wait_network_frame(); + level notify( "Pack_A_Punch_on" ); +} + +enemy_location_override( zombie, enemy ) +{ + location = enemy.origin; + if ( is_true( self.reroute ) ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + return location; +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_ai_avogadro.gsc b/zm_transit_patch/maps/mp/zombies/_zm_ai_avogadro.gsc new file mode 100644 index 0000000..20be029 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_ai_avogadro.gsc @@ -0,0 +1,1600 @@ +#include maps/mp/zombies/_zm_weap_riotshield; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zm_transit_bus; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_ai_avogadro; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +precache() +{ + precacheshellshock( "electrocution" ); +/# + precachemodel( "fx_axis_createfx" ); +#/ + precache_fx(); +} + +precache_fx() +{ + level._effect[ "avogadro_bolt" ] = loadfx( "maps/zombie/fx_zombie_tesla_bolt_secondary" ); + level._effect[ "avogadro_ascend" ] = loadfx( "maps/zombie/fx_zmb_avog_ascend" ); + level._effect[ "avogadro_ascend_aerial" ] = loadfx( "maps/zombie/fx_zmb_avog_ascend_aerial" ); + level._effect[ "avogadro_descend" ] = loadfx( "maps/zombie/fx_zmb_avog_descend" ); + level._effect[ "avogadro_phase_trail" ] = loadfx( "maps/zombie/fx_zmb_avog_phase_trail" ); + level._effect[ "avogadro_phasing" ] = loadfx( "maps/zombie/fx_zmb_avog_phasing" ); + level._effect[ "avogadro_health_full" ] = loadfx( "maps/zombie/fx_zmb_avog_health_full" ); + level._effect[ "avogadro_health_half" ] = loadfx( "maps/zombie/fx_zmb_avog_health_half" ); + level._effect[ "avogadro_health_low" ] = loadfx( "maps/zombie/fx_zmb_avog_health_low" ); +} + +init() +{ + init_phase_anims(); + init_regions(); + level.avogadro_spawners = getentarray( "avogadro_zombie_spawner", "script_noteworthy" ); + array_thread( level.avogadro_spawners, ::add_spawn_function, ::avogadro_prespawn ); + level.zombie_ai_limit_avogadro = 1; + if ( !isDefined( level.vsmgr_prio_overlay_zm_ai_avogadro_electrified ) ) + { + level.vsmgr_prio_overlay_zm_ai_avogadro_electrified = 75; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_ai_avogadro_electrified", 1, level.vsmgr_prio_overlay_zm_ai_avogadro_electrified, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); + maps/mp/zombies/_zm::register_player_damage_callback( ::avogadro_player_damage_callback ); + level thread avogadro_spawning_logic(); +} + +init_phase_anims() +{ + level.avogadro_phase = []; + level.avogadro_phase[ 0 ] = spawnstruct(); + level.avogadro_phase[ 0 ].animstate = "zm_teleport_forward"; + level.avogadro_phase[ 1 ] = spawnstruct(); + level.avogadro_phase[ 1 ].animstate = "zm_teleport_left"; + level.avogadro_phase[ 2 ] = spawnstruct(); + level.avogadro_phase[ 2 ].animstate = "zm_teleport_right"; + level.avogadro_phase[ 3 ] = spawnstruct(); + level.avogadro_phase[ 3 ].animstate = "zm_teleport_back"; +} + +init_regions() +{ + level.transit_region = []; + level.transit_region[ "bus" ] = spawnstruct(); + level.transit_region[ "diner" ] = spawnstruct(); + level.transit_region[ "farm" ] = spawnstruct(); + level.transit_region[ "cornfield" ] = spawnstruct(); + level.transit_region[ "power" ] = spawnstruct(); + level.transit_region[ "town" ] = spawnstruct(); + level.transit_region[ "bus" ].zones = []; + level.transit_region[ "bus" ].zones[ 0 ] = "zone_pri"; + level.transit_region[ "bus" ].zones[ 1 ] = "zone_station_ext"; + level.transit_region[ "bus" ].exploder = 200; + level.transit_region[ "bus" ].sndorigin = ( -6909, 4531, 396 ); + level.transit_region[ "diner" ].zones = []; + level.transit_region[ "diner" ].zones[ 0 ] = "zone_roadside_west"; + level.transit_region[ "diner" ].zones[ 1 ] = "zone_din"; + level.transit_region[ "diner" ].zones[ 2 ] = "zone_roadside_east"; + level.transit_region[ "diner" ].zones[ 3 ] = "zone_gas"; + level.transit_region[ "diner" ].zones[ 4 ] = "zone_gar"; + level.transit_region[ "diner" ].exploder = 220; + level.transit_region[ "diner" ].sndorigin = ( -5239, -6842, 457 ); + level.transit_region[ "farm" ].zones = []; + level.transit_region[ "farm" ].zones[ 0 ] = "zone_far"; + level.transit_region[ "farm" ].zones[ 1 ] = "zone_far_ext"; + level.transit_region[ "farm" ].zones[ 2 ] = "zone_brn"; + level.transit_region[ "farm" ].zones[ 3 ] = "zone_farm_house"; + level.transit_region[ "farm" ].exploder = 230; + level.transit_region[ "farm" ].sndorigin = ( 7954, -5799, 582 ); + level.transit_region[ "cornfield" ].zones = []; + level.transit_region[ "cornfield" ].zones[ 0 ] = "zone_amb_cornfield"; + level.transit_region[ "cornfield" ].zones[ 1 ] = "zone_cornfield_prototype"; + level.transit_region[ "cornfield" ].exploder = 240; + level.transit_region[ "cornfield" ].sndorigin = ( 10278, -662, 324 ); + level.transit_region[ "power" ].zones = []; + level.transit_region[ "power" ].zones[ 0 ] = "zone_prr"; + level.transit_region[ "power" ].zones[ 1 ] = "zone_pow"; + level.transit_region[ "power" ].zones[ 2 ] = "zone_pcr"; + level.transit_region[ "power" ].zones[ 3 ] = "zone_pow_warehouse"; + level.transit_region[ "power" ].exploder = 250; + level.transit_region[ "power" ].sndorigin = ( 10391, 7604, -70 ); + level.transit_region[ "town" ].zones = []; + level.transit_region[ "town" ].zones[ 0 ] = "zone_tow"; + level.transit_region[ "town" ].zones[ 1 ] = "zone_bar"; + level.transit_region[ "town" ].zones[ 2 ] = "zone_ban"; + level.transit_region[ "town" ].zones[ 3 ] = "zone_ban_vault"; + level.transit_region[ "town" ].zones[ 4 ] = "zone_town_north"; + level.transit_region[ "town" ].zones[ 5 ] = "zone_town_west"; + level.transit_region[ "town" ].zones[ 6 ] = "zone_town_south"; + level.transit_region[ "town" ].zones[ 7 ] = "zone_town_barber"; + level.transit_region[ "town" ].zones[ 8 ] = "zone_town_church"; + level.transit_region[ "town" ].zones[ 9 ] = "zone_town_east"; + level.transit_region[ "town" ].exploder = 260; + level.transit_region[ "town" ].sndorigin = ( 1460, -416, 318 ); +} + +avogadro_prespawn() +{ + self endon( "death" ); + level endon( "intermission" ); + level.avogadro = self; + self.has_legs = 1; + self.no_gib = 1; + self.is_avogadro = 1; + self.ignore_enemy_count = 1; + recalc_zombie_array(); + self.ignore_nuke = 1; + self.ignore_lava_damage = 1; + self.ignore_devgui_death = 1; + self.ignore_electric_trap = 1; + self.ignore_game_over_death = 1; + self.ignore_enemyoverride = 1; + self.ignore_solo_last_stand = 1; + self.ignore_riotshield = 1; + self.allowpain = 0; + self.core_model = getent( "core_model", "targetname" ); + if ( isDefined( self.core_model ) ) + { + if ( !isDefined( self.core_model.angles ) ) + { + self.core_model.angles = ( 0, 0, 1 ); + } + self forceteleport( self.core_model.origin, self.core_model.angles ); + } + self set_zombie_run_cycle( "walk" ); + self animmode( "normal" ); + self orientmode( "face enemy" ); + self maps/mp/zombies/_zm_spawner::zombie_setup_attack_properties(); + self maps/mp/zombies/_zm_spawner::zombie_complete_emerging_into_playable_area(); + self setfreecameralockonallowed( 0 ); + self.zmb_vocals_attack = "zmb_vocals_zombie_attack"; + self.meleedamage = 5; + self.actor_damage_func = ::avogadro_damage_func; + self.non_attacker_func = ::avogadro_non_attacker; + self.anchor = spawn( "script_origin", self.origin ); + self.anchor.angles = self.angles; + self.phase_time = 0; + self.audio_loop_ent = spawn( "script_origin", self.origin ); + self.audio_loop_ent linkto( self, "tag_origin" ); + self.hit_by_melee = 0; + self.damage_absorbed = 0; + self.ignoreall = 1; + self.zombie_init_done = 1; + self notify( "zombie_init_done" ); + self.stun_zombie = ::stun_avogadro; + self.jetgun_fling_func = ::fling_avogadro; + self.jetgun_drag_func = ::drag_avogadro; + self.depot_lava_pit = ::busplowkillzombie; + self.busplowkillzombie = ::busplowkillzombie; + self.region_timer = getTime() + 500; + self.shield = 1; +} + +avogadro_spawning_logic() +{ + level endon( "intermission" ); + if ( level.intermission ) + { + return; + } +/# + if ( getDvarInt( "zombie_cheat" ) == 2 || getDvarInt( "zombie_cheat" ) >= 4 ) + { + return; +#/ + } + spawner = getent( "avogadro_zombie_spawner", "script_noteworthy" ); + if ( !isDefined( spawner ) ) + { +/# + assertmsg( "No avogadro spawner in the map." ); +#/ + return; + } + ai = spawn_zombie( spawner, "avogadro" ); + if ( !isDefined( ai ) ) + { +/# + assertmsg( "Avogadro: failed spawn" ); +#/ + return; + } + ai waittill( "zombie_init_done" ); + core_mover = getent( "core_mover", "targetname" ); + ai linkto( core_mover, "tag_origin" ); + ai.state = "chamber"; + ai setanimstatefromasd( "zm_chamber_idle" ); + ai thread avogadro_think(); + ai thread avogadro_bus_watcher(); +} + +avogadro_think() +{ + while ( 1 ) + { + while ( isDefined( self.in_pain ) && self.in_pain ) + { + wait 0,1; + } + switch( self.state ) + { + case "chamber": + wait_idle(); + break; + case "wait_for_player": + player_look(); + break; + case "idle": + chase_player(); + break; + case "chasing": + chase_update(); + break; + case "chasing_bus": + chase_bus_update(); + break; + case "cloud": + cloud_update(); + break; + case "stay_attached": + attach_update(); + break; + } + wait 0,1; + } +} + +avogadro_bus_watcher() +{ + plow_trigger = getent( "trigger_plow", "targetname" ); + while ( 1 ) + { + while ( self.state == "chasing_bus" || self.state == "attacking_bus" ) + { + wait 0,1; + } + if ( isDefined( level.the_bus ) && isDefined( level.the_bus.ismoving ) && level.the_bus.ismoving && level.the_bus getspeedmph() > 5 ) + { + if ( self istouching( plow_trigger ) ) + { + phase_node = getnode( "back_door_node", "targetname" ); + self avogadro_teleport( phase_node.origin, phase_node.angles, 1 ); + } + } + wait 0,1; + } +} + +busplowkillzombie() +{ + if ( isDefined( self.is_teleport ) && self.is_teleport ) + { + return; + } + phase_node = getnode( "back_door_node", "targetname" ); + self avogadro_teleport( phase_node.origin, phase_node.angles, 1 ); +} + +phase_from_bus() +{ + self ghost(); + self notsolid(); + wait 3; + self show(); + self solid(); + self notify( "phase_from_bus_done" ); +} + +wait_idle() +{ +/# + if ( getDvarInt( #"CFA4158E" ) ) + { + self.state = "wait_for_player"; + self unlink(); +#/ + } + if ( flag( "power_on" ) ) + { + self.state = "wait_for_player"; + self unlink(); + } +} + +player_look() +{ + players = get_players(); + _a427 = players; + _k427 = getFirstArrayKey( _a427 ); + while ( isDefined( _k427 ) ) + { + player = _a427[ _k427 ]; + vec_enemy = self.origin - player.origin; + vec_facing = anglesToForward( player.angles ); + norm_facing = vectornormalize( vec_facing ); + norm_enemy = vectornormalize( vec_enemy ); + dot = vectordot( norm_facing, norm_enemy ); + if ( dot > 0,707 ) + { +/# + avogadro_print( "player spotted" ); +#/ + self avogadro_exit( "chamber" ); + } + _k427 = getNextArrayKey( _a427, _k427 ); + } +/# + if ( getDvarInt( #"CFA4158E" ) ) + { + avogadro_print( "player_look ignored" ); + self avogadro_exit( "chamber" ); +#/ + } +} + +chase_player() +{ + self.state = "chasing"; + self set_zombie_run_cycle( "run" ); + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +chase_update() +{ + if ( self check_bus_attack() ) + { + self chase_bus(); + } + else if ( self check_phase() ) + { + self do_phase(); + } + else + { + if ( self check_range_attack() ) + { + self range_attack(); + } + } + if ( self region_empty() ) + { + self avogadro_exit( "exit_idle" ); + } +} + +check_bus_attack() +{ + if ( isDefined( self.favoriteenemy ) && isDefined( self.favoriteenemy.isonbus ) && self.favoriteenemy.isonbus ) + { + return 1; + } + return 0; +} + +chase_bus() +{ + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self.chase_bus_entry = undefined; + dist_curr = 0; + _a515 = level.the_bus.openings; + _k515 = getFirstArrayKey( _a515 ); + while ( isDefined( _k515 ) ) + { + opening = _a515[ _k515 ]; + if ( !isDefined( self.chase_bus_entry ) ) + { + self.chase_bus_entry = opening; + dist_curr = distance2dsquared( self.origin, level.the_bus gettagorigin( self.chase_bus_entry.tagname ) ); + } + else + { + dist_next = distance2dsquared( self.origin, level.the_bus gettagorigin( opening.tagname ) ); + if ( dist_next < dist_curr ) + { + dist_curr = dist_next; + self.chase_bus_entry = opening; + } + } + _k515 = getNextArrayKey( _a515, _k515 ); + } + self set_zombie_run_cycle( "sprint" ); + self.state = "chasing_bus"; +} + +chase_bus_update() +{ + bus = level.the_bus; + if ( isDefined( bus ) && bus.numplayerson == 0 ) + { + self chase_player(); + return; + } + tag_pos = level.the_bus gettagorigin( self.chase_bus_entry.tagname ); + self setgoalpos( tag_pos ); + if ( bus getspeedmph() > 5 ) + { + self.phase_state = level.avogadro_phase[ 0 ].animstate; + self.phase_substate = 0; + self setfreecameralockonallowed( 0 ); + self.ignoreall = 1; + self thread phase_failsafe(); + self animcustom( ::play_phase_anim ); +/# + avogadro_print( "long phase after bus" ); +#/ + self waittill( "phase_anim_done" ); + self.ignoreall = 0; + self setfreecameralockonallowed( 1 ); + } + dist_sq = distancesquared( self.origin, tag_pos ); + if ( dist_sq < 14400 ) + { + self bus_attack(); + } +} + +bus_attack() +{ + self endon( "stunned" ); + self endon( "stop_bus_attack" ); + bus_attack_struct = []; + bus_attack_struct[ 0 ] = spawnstruct(); + bus_attack_struct[ 0 ].window_tag = "window_left_rear_jnt"; + bus_attack_struct[ 0 ].substate = "bus_attack_back"; + bus_attack_struct[ 1 ] = spawnstruct(); + bus_attack_struct[ 1 ].window_tag = "window_right_front_jnt"; + bus_attack_struct[ 1 ].substate = "bus_attack_front"; + bus_attack_struct[ 2 ] = spawnstruct(); + bus_attack_struct[ 2 ].window_tag = "window_left_2_jnt"; + bus_attack_struct[ 2 ].substate = "bus_attack_left"; + bus_attack_struct[ 3 ] = spawnstruct(); + bus_attack_struct[ 3 ].window_tag = "window_right_3_jnt"; + bus_attack_struct[ 3 ].substate = "bus_attack_right"; + random_attack_struct = array_randomize( bus_attack_struct ); + self.state = "attacking_bus"; + self.bus_attack_time = 0; + self.bus_disabled = 0; + self.ignoreall = 1; + i = 0; + while ( i < 4 ) + { + while ( isDefined( self.in_pain ) && self.in_pain ) + { + wait 0,1; + } + attack_struct = random_attack_struct[ i ]; +/# + window = getDvarInt( #"5628DC9F" ); + if ( window >= 0 ) + { + attack_struct = bus_attack_struct[ window ]; +#/ + } + self bus_disable( attack_struct ); + if ( self.bus_disabled ) + { + break; + } + else + { + i++; + } + } + if ( !self.bus_disabled ) + { + self.shield = 1; + self unlink(); + self avogadro_exit( "bus" ); + } + else + { + level.the_bus thread maps/mp/zm_transit_bus::bus_disabled_by_emp( 30 ); + self attach_to_bus(); + } +} + +attach_to_bus() +{ + self endon( "death" ); + self endon( "stop_health" ); + if ( level.the_bus.numaliveplayersridingbus > 0 ) + { +/# + avogadro_print( "stay_attached " + self.bus_attack_struct.substate ); +#/ + origin = level.the_bus gettagorigin( self.bus_attack_struct.window_tag ); + angles = level.the_bus gettagangles( self.bus_attack_struct.window_tag ); + self show(); + self.shield = 0; + self animscripted( origin, angles, "zm_bus_attack", self.bus_attack_struct.substate ); + self.bus_shock_time = 0; + self.state = "stay_attached"; + return; + } + self detach_from_bus(); +} + +attach_update() +{ + if ( level.the_bus.numaliveplayersridingbus > 0 ) + { + wait 0,1; + self.bus_shock_time += 0,1; + while ( self.bus_shock_time >= 2 ) + { + self.bus_shock_time = 0; + players = get_players(); + _a702 = players; + _k702 = getFirstArrayKey( _a702 ); + while ( isDefined( _k702 ) ) + { + player = _a702[ _k702 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", player, 1, 1 ); + player shellshock( "electrocution", 1 ); + player notify( "avogadro_damage_taken" ); + } + _k702 = getNextArrayKey( _a702, _k702 ); + } + } + return; + } + self detach_from_bus(); +} + +detach_from_bus() +{ + self unlink(); +/# + avogadro_print( "unlinking from bus window" ); +#/ + bus_forward = vectornormalize( anglesToForward( level.the_bus.angles ) ); + unlink_pos = level.the_bus.origin + vectorScale( bus_forward, -144 ); + unlink_pos = groundpos_ignore_water_new( unlink_pos + vectorScale( ( 0, 0, 1 ), 60 ) ); + self.shield = 1; + self avogadro_teleport( unlink_pos, self.angles, 1 ); + self.state = "idle"; + self.ignoreall = 0; +} + +bus_disable_show( time ) +{ + self endon( "death" ); + wait time; + self.shield = 0; + self show(); +} + +bus_disable( bus_attack_struct ) +{ + self endon( "melee_pain" ); + self.bus_attack_struct = bus_attack_struct; + origin = level.the_bus gettagorigin( bus_attack_struct.window_tag ); + angles = level.the_bus gettagangles( bus_attack_struct.window_tag ); + self avogadro_teleport( origin, angles, 0,5, bus_attack_struct.window_tag ); + self linkto( level.the_bus, bus_attack_struct.window_tag ); + bus_disable_show( 0,1 ); + origin = level.the_bus gettagorigin( bus_attack_struct.window_tag ); + angles = level.the_bus gettagangles( bus_attack_struct.window_tag ); + self animscripted( origin, angles, "zm_bus_attack", bus_attack_struct.substate ); +/# + avogadro_print( "bus_disable " + bus_attack_struct.substate ); +#/ + success = 0; + self.mod_melee = 0; + self.bus_shock_time = 0; + level thread maps/mp/zm_transit_bus::do_player_bus_zombie_vox( "avogadro_onbus", 45 ); + while ( 1 ) + { + wait 0,1; + self.bus_attack_time += 0,1; + if ( self.bus_attack_time >= 20 ) + { + self.bus_disabled = 1; + level thread maps/mp/zm_transit_bus::do_player_bus_zombie_vox( "avogadro_stopbus", 45 ); + return; + } + else + { + self.bus_shock_time += 0,1; + while ( self.bus_shock_time >= 2 ) + { + self.bus_shock_time = 0; + players = get_players(); + _a796 = players; + _k796 = getFirstArrayKey( _a796 ); + while ( isDefined( _k796 ) ) + { + player = _a796[ _k796 ]; + if ( isDefined( player.isonbus ) && player.isonbus ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", player, 1, 1 ); + player shellshock( "electrocution", 1 ); + player notify( "avogadro_damage_taken" ); + player thread do_player_general_vox( "general", "avogadro_attack", 30, 45 ); + } + _k796 = getNextArrayKey( _a796, _k796 ); + } + } + if ( level.the_bus.numaliveplayersridingbus == 0 ) + { + self detach_from_bus(); + self notify( "stop_bus_attack" ); + } + } + } +} + +avogadro_exit( from ) +{ + self.state = "exiting"; + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self setfreecameralockonallowed( 0 ); + self.audio_loop_ent stoploopsound( 0,5 ); + self notify( "stop_health" ); + if ( isDefined( self.health_fx ) ) + { + self.health_fx unlink(); + self.health_fx delete(); + } + if ( isDefined( from ) ) + { + if ( from == "bus" ) + { + self playsound( "zmb_avogadro_death_short" ); + playfx( level._effect[ "avogadro_ascend_aerial" ], self.origin ); + self animscripted( self.origin, self.angles, "zm_bus_win" ); + maps/mp/animscripts/zm_shared::donotetracks( "bus_win_anim" ); + } + else if ( from == "chamber" ) + { + self playsound( "zmb_avogadro_death_short" ); + playfx( level._effect[ "avogadro_ascend" ], self.origin ); + self animscripted( self.origin, self.angles, "zm_chamber_out" ); + wait 0,4; + self ghost(); + stop_exploder( 500 ); + } + else + { + self playsound( "zmb_avogadro_death" ); + playfx( level._effect[ "avogadro_ascend" ], self.origin ); + self animscripted( self.origin, self.angles, "zm_exit" ); + maps/mp/animscripts/zm_shared::donotetracks( "exit_anim" ); + } + } + else + { + self playsound( "zmb_avogadro_death" ); + playfx( level._effect[ "avogadro_ascend" ], self.origin ); + self animscripted( self.origin, self.angles, "zm_exit" ); + maps/mp/animscripts/zm_shared::donotetracks( "exit_anim" ); + } + if ( !isDefined( from ) || from != "chamber" ) + { + level thread do_avogadro_flee_vo( self ); + } + self ghost(); + self.hit_by_melee = 0; + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + if ( isDefined( from ) && from == "exit_idle" ) + { + self.return_round = level.round_number + 1; + } + else + { + self.return_round = level.round_number + randomintrange( 2, 5 ); + } + level.next_avogadro_round = self.return_round; + self.state = "cloud"; + self thread cloud_update_fx(); +} + +cloud_update_fx() +{ + self endon( "cloud_fx_end" ); + level endon( "end_game" ); + region = []; + region[ 0 ] = "bus"; + region[ 1 ] = "diner"; + region[ 2 ] = "farm"; + region[ 3 ] = "cornfield"; + region[ 4 ] = "power"; + region[ 5 ] = "town"; + self.current_region = undefined; + if ( !isDefined( self.sndent ) ) + { + self.sndent = spawn( "script_origin", ( 0, 0, 1 ) ); + self.sndent playloopsound( "zmb_avogadro_thunder_overhead" ); + } + cloud_time = getTime(); + vo_counter = 0; + while ( 1 ) + { + if ( getTime() >= cloud_time ) + { + if ( isDefined( self.current_region ) ) + { + exploder_num = level.transit_region[ self.current_region ].exploder; + stop_exploder( exploder_num ); + } + rand_region = array_randomize( region ); + region_str = rand_region[ 0 ]; + if ( !isDefined( self.current_region ) ) + { + region_str = region[ 4 ]; + } +/# + idx = getDvarInt( #"FD251E42" ); + if ( idx >= 0 ) + { + region_str = region[ idx ]; + } + avogadro_print( "clouds in region " + region_str ); +#/ + self.current_region = region_str; + exploder_num = level.transit_region[ region_str ].exploder; + exploder( exploder_num ); + self.sndent moveto( level.transit_region[ region_str ].sndorigin, 3 ); + cloud_time = getTime() + 30000; + } + if ( vo_counter > 50 ) + { + player = self get_player_in_region(); + if ( isDefined( player ) ) + { + if ( isDefined( self._in_cloud ) && self._in_cloud ) + { + player thread do_player_general_vox( "general", "avogadro_above", 90, 10 ); + } + else + { + player thread do_player_general_vox( "general", "avogadro_arrive", 60, 40 ); + } + } + else + { + level thread avogadro_storm_vox(); + } + vo_counter = 0; + } + wait 0,1; + vo_counter++; + } +} + +cloud_update() +{ + self endon( "melee_pain" ); + return_from_cloud = 0; + self._in_cloud = 1; + if ( level.round_number >= self.return_round ) + { +/# + avogadro_print( "return from round" ); +#/ + return_from_cloud = 1; + self._in_cloud = 0; + } + while ( isDefined( return_from_cloud ) && return_from_cloud ) + { +/# + avogadro_print( "time to come back in " + self.current_region ); +#/ + self notify( "cloud_fx_end" ); + new_origin = cloud_find_spawn(); + if ( isDefined( self.sndent ) ) + { + self.sndent delete(); + self.sndent = undefined; + } + if ( !isDefined( new_origin ) ) + { + new_origin = maps/mp/zombies/_zm::check_for_valid_spawn_near_team(); + } + while ( isDefined( new_origin ) ) + { + self thread avogadro_update_health(); + playsoundatposition( "zmb_avogadro_spawn_3d", new_origin ); + self.audio_loop_ent playloopsound( "zmb_avogadro_loop", 0,5 ); + self unlink(); + ground_pos = groundpos_ignore_water_new( new_origin + vectorScale( ( 0, 0, 1 ), 60 ) ); + playfx( level._effect[ "avogadro_descend" ], ground_pos ); + self animscripted( ground_pos, self.anchor.angles, "zm_arrival" ); + maps/mp/animscripts/zm_shared::donotetracks( "arrival_anim" ); + self setfreecameralockonallowed( 1 ); + time_to_leave = getTime() + 30000; + while ( 1 ) + { + if ( getTime() > time_to_leave ) + { +/# + avogadro_print( "enemy never showed - leaving" ); +#/ + self avogadro_exit( "exit_idle" ); + return; + } + if ( self enemy_in_region() ) + { + self.ignoreall = 0; + self.state = "idle"; + return; + } + wait 0,1; + } + } + } +} + +enemy_in_region() +{ + zones = level.transit_region[ self.current_region ].zones; + _a1071 = zones; + _k1071 = getFirstArrayKey( _a1071 ); + while ( isDefined( _k1071 ) ) + { + zone = _a1071[ _k1071 ]; + if ( level.zones[ zone ].is_occupied ) + { + self.ignoreall = 0; + self.state = "idle"; + return 1; + } + _k1071 = getNextArrayKey( _a1071, _k1071 ); + } + return 0; +} + +get_player_in_region() +{ + players = get_players(); + players = array_randomize( players ); + zones = level.transit_region[ self.current_region ].zones; + _a1091 = zones; + _k1091 = getFirstArrayKey( _a1091 ); + while ( isDefined( _k1091 ) ) + { + zone = _a1091[ _k1091 ]; + while ( level.zones[ zone ].is_occupied ) + { + _a1095 = players; + _k1095 = getFirstArrayKey( _a1095 ); + while ( isDefined( _k1095 ) ) + { + player = _a1095[ _k1095 ]; + if ( player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( zone ) ) + { + return player; + } + _k1095 = getNextArrayKey( _a1095, _k1095 ); + } + } + _k1091 = getNextArrayKey( _a1091, _k1091 ); + } + return undefined; +} + +cloud_find_spawn() +{ + zones = level.transit_region[ self.current_region ].zones; + use_points = []; + _a1116 = zones; + _k1116 = getFirstArrayKey( _a1116 ); + while ( isDefined( _k1116 ) ) + { + zone = _a1116[ _k1116 ]; + if ( zone == "zone_pri" ) + { + if ( !level.zones[ zone ].is_occupied ) + { + if ( !flag( "OnPriDoorYar2" ) ) + { +/# + avogadro_print( "zone_pri not occupied and door is closed" ); +#/ + } + } + } + else + { + while ( level.zones[ zone ].is_enabled && level.zones[ zone ].is_spawning_allowed ) + { + locations = level.zones[ zone ].avogadro_locations; + _a1135 = locations; + _k1135 = getFirstArrayKey( _a1135 ); + while ( isDefined( _k1135 ) ) + { + loc = _a1135[ _k1135 ]; + use_points[ use_points.size ] = loc; + _k1135 = getNextArrayKey( _a1135, _k1135 ); + } + } + } + _k1116 = getNextArrayKey( _a1116, _k1116 ); + } + if ( use_points.size > 0 ) + { + use_points = array_randomize( use_points ); + return use_points[ 0 ].origin; + } + return undefined; +} + +avogadro_reveal( show_time ) +{ + self endon( "death" ); + self show(); + wait show_time; + self ghost(); +} + +avogadro_teleport( dest_pos, dest_angles, lerp_time, tag_override ) +{ + self.is_teleport = 1; + self.phase_fx = spawn( "script_model", self.origin ); + self.phase_fx setmodel( "tag_origin" ); + self.phase_fx linkto( self ); + wait 0,1; + playfxontag( level._effect[ "avogadro_phase_trail" ], self.phase_fx, "tag_origin" ); + playfx( level._effect[ "avogadro_phasing" ], self.origin ); + self avogadro_reveal( 0,1 ); + self playsound( "zmb_avogadro_warp_out" ); + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + self.anchor moveto( dest_pos, lerp_time ); + self.anchor waittill( "movedone" ); + self.anchor.origin = dest_pos; + self.anchor.angles = dest_angles; + self unlink(); + wait 0,1; + if ( isDefined( tag_override ) ) + { + dest_pos = level.the_bus gettagorigin( tag_override ); + dest_angles = level.the_bus gettagangles( tag_override ); + } + self forceteleport( dest_pos, dest_angles ); + playfx( level._effect[ "avogadro_phasing" ], self.origin ); + if ( isDefined( self.phase_fx ) ) + { + self.phase_fx delete(); + } + self avogadro_reveal( 0,1 ); + self playsound( "zmb_avogadro_warp_in" ); + self.is_teleport = 0; +} + +check_range_attack() +{ +/# + if ( getDvarInt( #"A40002E9" ) ) + { + return 0; +#/ + } + enemy = self.favoriteenemy; + if ( isDefined( enemy ) ) + { + vec_enemy = enemy.origin - self.origin; + dist_sq = lengthsquared( vec_enemy ); + if ( dist_sq > 14400 && dist_sq < 360000 ) + { + vec_facing = anglesToForward( self.angles ); + norm_facing = vectornormalize( vec_facing ); + norm_enemy = vectornormalize( vec_enemy ); + dot = vectordot( norm_facing, norm_enemy ); + if ( dot > 0,99 ) + { + enemy_eye_pos = enemy geteye(); + eye_pos = self geteye(); + passed = bullettracepassed( eye_pos, enemy_eye_pos, 0, undefined ); + if ( passed ) + { + return 1; + } + } + } + } + return 0; +} + +range_attack() +{ + self endon( "melee_pain" ); + enemy = self.favoriteenemy; + if ( isDefined( enemy ) ) + { + self thread shoot_bolt_wait( "ranged_attack", enemy ); + self show(); + self animscripted( self.origin, self.angles, "zm_ranged_attack_in" ); + maps/mp/animscripts/zm_shared::donotetracks( "ranged_attack" ); + self animscripted( self.origin, self.angles, "zm_ranged_attack_loop" ); + maps/mp/animscripts/zm_shared::donotetracks( "ranged_attack" ); + self animscripted( self.origin, self.angles, "zm_ranged_attack_out" ); + maps/mp/animscripts/zm_shared::donotetracks( "ranged_attack" ); + self.shield = 1; + self thread avogadro_update_health(); + self ghost(); + } +} + +shoot_bolt_wait( animname, enemy ) +{ + self endon( "melee_pain" ); + self waittillmatch( animname ); + return "fire"; + self.shield = 0; + self notify( "stop_health" ); + if ( isDefined( self.health_fx ) ) + { + self.health_fx unlink(); + self.health_fx delete(); + } + self thread shoot_bolt( enemy ); +} + +shoot_bolt( enemy ) +{ + source_pos = self gettagorigin( "tag_weapon_right" ); + target_pos = enemy geteye(); + bolt = spawn( "script_model", source_pos ); + bolt setmodel( "tag_origin" ); + wait 0,1; + self playsound( "zmb_avogadro_attack" ); + fx = playfxontag( level._effect[ "avogadro_bolt" ], bolt, "tag_origin" ); + bolt moveto( target_pos, 0,2 ); + bolt waittill( "movedone" ); + bolt.owner = self; + bolt check_bolt_impact( enemy ); + bolt delete(); +} + +check_bolt_impact( enemy ) +{ + if ( is_player_valid( enemy ) ) + { + enemy_eye_pos = enemy geteye(); + dist_sq = distancesquared( self.origin, enemy_eye_pos ); + if ( dist_sq < 4096 ) + { + passed = bullettracepassed( self.origin, enemy_eye_pos, 0, undefined ); + if ( passed ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", enemy, 1, 1 ); + enemy shellshock( "electrocution", 1 ); + enemy playsoundtoplayer( "zmb_avogadro_electrified", enemy ); + enemy dodamage( 60, enemy.origin ); + enemy notify( "avogadro_damage_taken" ); + } + } + } +} + +region_empty() +{ + if ( getTime() >= self.region_timer ) + { + player = self get_player_in_region(); + if ( isDefined( player ) ) + { + self.region_timer = getTime() + 500; + return 0; + } +/# + debug_dist_sq = 0; +#/ + players = getplayers(); + _a1371 = players; + _k1371 = getFirstArrayKey( _a1371 ); + while ( isDefined( _k1371 ) ) + { + player = _a1371[ _k1371 ]; + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + } + else + { + dist_sq = distancesquared( self.origin, player.origin ); +/# + debug_dist_sq = distance( self.origin, player.origin ); +#/ + if ( dist_sq < 9000000 ) + { + self.region_timer = getTime() + 500; + return 0; + } + } + _k1371 = getNextArrayKey( _a1371, _k1371 ); + } + self.region_timer = getTime() + 500; +/# + avogadro_print( "no one left to kill " + debug_dist_sq ); +#/ + return 1; + } + return 0; +} + +get_random_phase_state() +{ + index = randomint( 4 ); + state = level.avogadro_phase[ index ].animstate; + return state; +} + +check_phase() +{ +/# + if ( getDvarInt( #"CFB33742" ) ) + { + return 0; +#/ + } + if ( getTime() > self.phase_time ) + { + if ( isDefined( self.is_traversing ) && self.is_traversing ) + { + self.phase_time = getTime() + 2000; + return 0; + } + self.phase_state = get_random_phase_state(); + self.phase_substate = randomint( 3 ); + anim_id = self getanimfromasd( self.phase_state, self.phase_substate ); + if ( self maymovefrompointtopoint( self.origin, getanimendpos( anim_id ) ) ) + { + return 1; + } + } + return 0; +} + +do_phase() +{ + self endon( "death" ); + self.state = "phasing"; + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self setfreecameralockonallowed( 0 ); + self.ignoreall = 1; + self thread phase_failsafe(); + self animcustom( ::play_phase_anim ); + self waittill( "phase_anim_done" ); + self.ignoreall = 0; + self setfreecameralockonallowed( 1 ); + self.state = "idle"; +} + +play_phase_anim() +{ + self endon( "death" ); + self endon( "phase_anim_done" ); + self.phase_fx = spawn( "script_model", self.origin ); + self.phase_fx setmodel( "tag_origin" ); + self.phase_fx linkto( self ); + wait 0,05; + playfxontag( level._effect[ "avogadro_phase_trail" ], self.phase_fx, "tag_origin" ); + playfx( level._effect[ "avogadro_phasing" ], self.origin ); + self avogadro_reveal( 0,1 ); + self playsound( "zmb_avogadro_warp_out" ); + self orientmode( "face enemy" ); + self setanimstatefromasd( self.phase_state, self.phase_substate ); + maps/mp/animscripts/zm_shared::donotetracks( "teleport_anim" ); + self.phase_fx delete(); + playfx( level._effect[ "avogadro_phasing" ], self.origin ); + self avogadro_reveal( 0,1 ); + self orientmode( "face default" ); + self playsound( "zmb_avogadro_warp_in" ); + self.phase_time = getTime() + 2000; + self notify( "phase_anim_done" ); +} + +phase_failsafe() +{ + self endon( "phase_anim_done" ); + wait 1; + if ( self.state == "phasing" || self.state == "chasing_bus" ) + { +/# + avogadro_print( "phasing too long, failsafe kicking in" ); +#/ + if ( isDefined( self.phase_fx ) ) + { + self.phase_fx delete(); + } + playfx( level._effect[ "avogadro_phasing" ], self.origin ); + self avogadro_reveal( 0,1 ); + self orientmode( "face default" ); + self playsound( "zmb_avogadro_warp_in" ); + self.phase_time = getTime() + 2000; + self notify( "phase_anim_done" ); + } +} + +avogadro_player_damage_callback( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( isDefined( einflictor ) && isDefined( einflictor.is_avogadro ) && einflictor.is_avogadro ) + { + if ( smeansofdeath == "MOD_MELEE" ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", self, 0,25, 1 ); + self shellshock( "electrocution", 0,25 ); + self notify( "avogadro_damage_taken" ); + self thread do_player_general_vox( "general", "avogadro_attack", 15, 45 ); + } + } + return -1; +} + +avogadro_pain_watcher() +{ + self notify( "stop_pain_watcher" ); + self endon( "stop_pain_watcher" ); + wait 4; + if ( isDefined( self.in_pain ) && self.in_pain ) + { + self.in_pain = 0; +/# + avogadro_print( "in_pain for too long" ); +#/ + } +} + +avogadro_pain( einflictor ) +{ + self endon( "melee_pain" ); + self.in_pain = 1; + self playsound( "zmb_avogadro_pain" ); + self thread avogadro_pain_watcher(); + substate = 0; + origin = self.origin; + angles = self.angles; + animstate = "zm_pain"; + if ( self.state == "attacking_bus" || self.state == "stay_attached" ) + { + tag = self.bus_attack_struct.window_tag; + if ( tag == "window_left_rear_jnt" ) + { + animstate = "zm_bus_back_pain"; + } + else + { + animstate = "zm_bus_pain"; + } + origin = level.the_bus gettagorigin( tag ); + angles = level.the_bus gettagangles( tag ); + } + if ( self.hit_by_melee < 4 ) + { + self thread avogadro_update_health(); + self animscripted( origin, angles, animstate, substate ); + maps/mp/animscripts/zm_shared::donotetracks( "pain_anim" ); + self ghost(); + self.phase_time = getTime() - 1; + if ( self.state == "stay_attached" ) + { + self attach_to_bus(); + } + } + else self notify( "stop_bus_attack" ); + level notify( "avogadro_defeated" ); + if ( isDefined( einflictor ) && isplayer( einflictor ) ) + { + einflictor maps/mp/zombies/_zm_stats::increment_client_stat( "avogadro_defeated", 0 ); + einflictor maps/mp/zombies/_zm_stats::increment_player_stat( "avogadro_defeated" ); + } + if ( flag( "power_on" ) && flag( "switches_on" ) && self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr" ) ) + { +/# + avogadro_print( "come back on power" ); +#/ + self show(); + self.in_pain = 0; +/# + avogadro_print( "pain cleared from zone_prr" ); +#/ + self notify( "stop_pain_watcher" ); + self avogadro_teleport( self.core_model.origin, self.core_model.angles, 1 ); + core_mover = getent( "core_mover", "targetname" ); + self linkto( core_mover, "tag_origin" ); + while ( flag( "power_on" ) ) + { + wait 0,1; + } + self show(); + self.state = "chamber"; + self setanimstatefromasd( "zm_chamber_idle" ); + } + else + { +/# + if ( !flag( "power_on" ) ) + { + avogadro_print( "no power" ); + } + if ( !flag( "switches_on" ) ) + { + avogadro_print( "no switches" ); + } + if ( !self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr" ) ) + { + avogadro_print( "no zone" ); +#/ + } + self show(); + self avogadro_exit(); + } + self.in_pain = 0; +/# + avogadro_print( "pain cleared normal" ); +#/ + self notify( "stop_pain_watcher" ); +} + +avogadro_update_health() +{ + self endon( "death" ); + self notify( "stop_health" ); + self endon( "stop_health" ); + while ( 1 ) + { + self avogadro_update_health_fx(); + wait 0,4; + } +} + +avogadro_update_health_fx() +{ + self endon( "death" ); + if ( !isDefined( self.health_fx ) ) + { + tag_origin = self gettagorigin( "J_SpineUpper" ); + tag_angles = self gettagangles( "J_SpineUpper" ); + self.health_fx = spawn( "script_model", tag_origin ); + self.health_fx.angles = tag_angles; + self.health_fx setmodel( "tag_origin" ); + self.health_fx linkto( self ); + wait 0,1; + } + if ( self.hit_by_melee == 0 ) + { + playfxontag( level._effect[ "avogadro_health_full" ], self.health_fx, "tag_origin" ); + } + else if ( self.hit_by_melee <= 2 ) + { + playfxontag( level._effect[ "avogadro_health_half" ], self.health_fx, "tag_origin" ); + } + else + { + playfxontag( level._effect[ "avogadro_health_low" ], self.health_fx, "tag_origin" ); + } +} + +avogadro_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( self.state == "exiting" || self.state == "phasing" ) + { + return 0; + } + if ( smeansofdeath == "MOD_MELEE" ) + { + if ( isplayer( einflictor ) ) + { + if ( isDefined( einflictor.avogadro_melee_time ) ) + { + } + if ( self.shield ) + { + einflictor.avogadro_melee_time = getTime(); + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", einflictor, 0,25, 1 ); + einflictor shellshock( "electrocution", 0,25 ); + einflictor notify( "avogadro_damage_taken" ); + } + if ( sweapon == "riotshield_zm" ) + { + shield_damage = level.zombie_vars[ "riotshield_fling_damage_shield" ]; + einflictor maps/mp/zombies/_zm_weap_riotshield::player_damage_shield( shield_damage, 0 ); + } + } + if ( !self.shield ) + { + self.shield = 1; + self notify( "melee_pain" ); + if ( sweapon == "tazer_knuckles_zm" ) + { + self.hit_by_melee += 2; + } + else + { + self.hit_by_melee++; + } + self thread avogadro_pain( einflictor ); +/# + avogadro_print( "hit_by_melee: " + self.hit_by_melee ); +#/ + if ( isplayer( einflictor ) ) + { + einflictor thread do_player_general_vox( "general", "avogadro_wound", 30, 35 ); + level notify( "avogadro_stabbed" ); + } + } + else + { +/# + avogadro_print( "shield up, no damage" ); +#/ + } + } + else + { + self update_damage_absorbed( idamage ); + } + return 0; +} + +update_damage_absorbed( damage ) +{ + if ( self.hit_by_melee > 0 ) + { + self.damage_absorbed += damage; + if ( self.damage_absorbed >= 1000 ) + { + self.damage_absorbed = 0; + self.hit_by_melee--; + +/# + avogadro_print( "regen - hit_by_melee: " + self.hit_by_melee ); +#/ + } + } +} + +avogadro_non_attacker( damage, weapon ) +{ + if ( weapon == "zombie_bullet_crouch_zm" ) + { + self update_damage_absorbed( damage ); + } + return 0; +} + +stun_avogadro() +{ + ignore_emp_states = []; + ignore_emp_states[ 0 ] = "phasing"; + ignore_emp_states[ 1 ] = "chamber"; + ignore_emp_states[ 2 ] = "wait_for_player"; + ignore_emp_states[ 3 ] = "exiting"; + ignore_emp_states[ 4 ] = "cloud"; + _a1854 = ignore_emp_states; + _k1854 = getFirstArrayKey( _a1854 ); + while ( isDefined( _k1854 ) ) + { + state = _a1854[ _k1854 ]; + if ( self.state == state ) + { + return; + } + _k1854 = getNextArrayKey( _a1854, _k1854 ); + } + if ( self.hit_by_melee < 4 ) + { +/# + avogadro_print( "stunned during " + self.state ); +#/ + level notify( "stun_avogadro" ); + self notify( "stunned" ); + self notify( "melee_pain" ); + self.hit_by_melee += 4; + self thread avogadro_pain(); + } +} + +fling_avogadro( player ) +{ +} + +drag_avogadro( vdir ) +{ +} + +avogadro_debug_axis() +{ +/# + self endon( "death" ); + while ( 1 ) + { + if ( !isDefined( self.debug_axis ) ) + { + self.debug_axis = spawn( "script_model", self.origin ); + self.debug_axis setmodel( "fx_axis_createfx" ); + } + else + { + self.debug_axis.origin = self.origin; + self.debug_axis.angles = self.angles; + } + wait 0,1; +#/ + } +} + +avogadro_print( str ) +{ +/# + if ( getDvarInt( #"92514885" ) ) + { + iprintln( "avogadro: " + str ); + if ( isDefined( self.debug_msg ) ) + { + self.debug_msg[ self.debug_msg.size ] = str; + if ( self.debug_msg.size > 64 ) + { + self.debug_msg = []; + } + return; + } + else + { + self.debug_msg = []; + self.debug_msg[ self.debug_msg.size ] = str; +#/ + } + } +} + +do_avogadro_flee_vo( avogadro ) +{ + players = get_players(); + _a1944 = players; + _k1944 = getFirstArrayKey( _a1944 ); + while ( isDefined( _k1944 ) ) + { + player = _a1944[ _k1944 ]; + if ( distancesquared( player.origin, avogadro.origin ) < 250000 ) + { + player thread do_player_general_vox( "general", "avogadro_flee", 30, 45 ); + return; + } + _k1944 = getNextArrayKey( _a1944, _k1944 ); + } +} + +avogadro_storm_vox() +{ + if ( isDefined( level.checking_avogadro_storm_vox ) && level.checking_avogadro_storm_vox ) + { + return; + } + level.checking_avogadro_storm_vox = 1; + players = get_players(); + players = array_randomize( players ); + _a1963 = players; + _k1963 = getFirstArrayKey( _a1963 ); + while ( isDefined( _k1963 ) ) + { + player = _a1963[ _k1963 ]; + if ( !player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_tbu" ) && !player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_amb_tunnel" ) && !player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_prr" ) || player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_pcr" ) && player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_pow_warehouse" ) ) + { + } + else + { + player thread do_player_general_vox( "general", "avogadro_storm", 120, 2 ); + } + _k1963 = getNextArrayKey( _a1963, _k1963 ); + } + wait 5; + level.checking_avogadro_storm_vox = 0; +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_ai_screecher.gsc b/zm_transit_patch/maps/mp/zombies/_zm_ai_screecher.gsc new file mode 100644 index 0000000..da96e0d --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_ai_screecher.gsc @@ -0,0 +1,1254 @@ +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_ai_screecher; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +precache() +{ + precacheshader( "fullscreen_claw_left" ); + precacheshader( "fullscreen_claw_right" ); + precacheshader( "fullscreen_claw_bottom" ); + precachemodel( "p6_zm_screecher_hole" ); + precachemodel( "fx_axis_createfx" ); + precachestring( &"ZOMBIE_SCREECHER_ATTACH_FIRST" ); + level._effect[ "screecher_spawn_a" ] = loadfx( "maps/zombie/fx_zmb_screech_hand_dirt_burst" ); + level._effect[ "screecher_spawn_b" ] = loadfx( "maps/zombie/fx_zmb_screech_body_dirt_billowing" ); + level._effect[ "screecher_spawn_c" ] = loadfx( "maps/zombie/fx_zmb_screech_body_dirt_falling" ); + level._effect[ "screecher_hole" ] = loadfx( "maps/zombie/fx_zmb_screecher_hole" ); + level._effect[ "screecher_vortex" ] = loadfx( "maps/zombie/fx_zmb_screecher_vortex" ); + level._effect[ "screecher_death" ] = loadfx( "maps/zombie/fx_zmb_screech_death_ash" ); +} + +init() +{ + level.screecher_spawners = getentarray( "screecher_zombie_spawner", "script_noteworthy" ); + array_thread( level.screecher_spawners, ::add_spawn_function, ::screecher_prespawn ); + level.zombie_ai_limit_screecher = 2; + level.zombie_screecher_count = 0; + if ( !isDefined( level.vsmgr_prio_overlay_zm_ai_screecher_blur ) ) + { + level.vsmgr_prio_overlay_zm_ai_screecher_blur = 50; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_ai_screecher_blur", 1, level.vsmgr_prio_overlay_zm_ai_screecher_blur, 1, 1, ::maps/mp/_visionset_mgr::vsmgr_timeout_lerp_thread_per_player, 0 ); + level thread screecher_spawning_logic(); +/# + level thread screecher_debug(); +#/ + registerclientfield( "actor", "render_third_person", 1, 1, "int" ); + level.near_miss = 0; +} + +screecher_debug() +{ +/# +#/ +} + +screecher_spawning_logic() +{ + level endon( "intermission" ); + if ( level.intermission ) + { + return; + } +/# + if ( getDvarInt( "zombie_cheat" ) == 2 || getDvarInt( "zombie_cheat" ) >= 4 ) + { + return; +#/ + } + if ( level.screecher_spawners.size < 1 ) + { +/# + assertmsg( "No active spawners in the map. Check to see if the zone is active and if it's pointing to spawners." ); +#/ + return; + } + while ( 1 ) + { + while ( !isDefined( level.zombie_screecher_locations ) || level.zombie_screecher_locations.size <= 0 ) + { + wait 0,1; + } + while ( level.zombie_screecher_count >= level.zombie_ai_limit_screecher ) + { + wait 0,1; + } + while ( getDvarInt( #"B0C0D38F" ) ) + { + wait 0,1; + } + if ( !flag( "spawn_zombies" ) ) + { + flag_wait( "spawn_zombies" ); + } + valid_players_in_screecher_zone = 0; + valid_players = []; + while ( valid_players_in_screecher_zone <= 0 ) + { + players = getplayers(); + valid_players_in_screecher_zone = 0; + p = 0; + while ( p < players.size ) + { + if ( is_player_valid( players[ p ] ) && player_in_screecher_zone( players[ p ] ) && !isDefined( players[ p ].screecher ) ) + { + valid_players_in_screecher_zone++; + valid_players[ valid_players.size ] = players[ p ]; + } + p++; + } + if ( players.size == 1 ) + { + if ( is_player_valid( players[ 0 ] ) && !player_in_screecher_zone( players[ 0 ] ) ) + { + level.spawn_delay = 1; + } + } + wait 0,1; + } + if ( !isDefined( level.zombie_screecher_locations ) || level.zombie_screecher_locations.size <= 0 ) + { + continue; + } + valid_players = array_randomize( valid_players ); + player_left_zone = 0; + while ( isDefined( level.spawn_delay ) && level.spawn_delay ) + { +/# + screecher_print( "delay spawning 5 secs" ); +#/ + spawn_points = get_array_of_closest( valid_players[ 0 ].origin, level.zombie_screecher_locations ); + spawn_point = undefined; + if ( spawn_points.size >= 3 ) + { + spawn_point = spawn_points[ 2 ]; + } + else if ( spawn_points.size >= 2 ) + { + spawn_point = spawn_points[ 1 ]; + } + else + { + if ( spawn_points.size >= 1 ) + { + spawn_point = spawn_points[ 0 ]; + } + } + if ( isDefined( spawn_point ) ) + { + playsoundatposition( "zmb_vocals_screecher_spawn", spawn_point.origin ); + } + delay_time = getTime() + 5000; + now_zone = getent( "screecher_spawn_now", "targetname" ); + while ( getTime() < delay_time ) + { + in_zone = 0; + if ( valid_players[ 0 ] istouching( now_zone ) ) + { +/# + screecher_print( "in now zone" ); +#/ + break; + } + else if ( !is_player_valid( valid_players[ 0 ] ) ) + { + break; + } + else if ( player_in_screecher_zone( valid_players[ 0 ] ) ) + { + in_zone = 1; + } + if ( !in_zone ) + { + player_left_zone = 1; + level.spawn_delay = 1; + break; + } + else + { + wait 0,1; + } + } + } + if ( isDefined( player_left_zone ) && player_left_zone ) + { + continue; + } + level.spawn_delay = 0; + spawn_points = get_array_of_closest( valid_players[ 0 ].origin, level.zombie_screecher_locations ); + spawn_point = undefined; + while ( !isDefined( spawn_points ) || spawn_points.size == 0 ) + { + wait 0,1; + } + if ( !isDefined( level.last_spawn ) ) + { + level.last_spawn_index = 0; + level.last_spawn = []; + level.last_spawn[ level.last_spawn_index ] = spawn_points[ 0 ]; + level.last_spawn_index = 1; + spawn_point = spawn_points[ 0 ]; + } + else _a250 = spawn_points; + _k250 = getFirstArrayKey( _a250 ); + while ( isDefined( _k250 ) ) + { + point = _a250[ _k250 ]; + if ( point == level.last_spawn[ 0 ] ) + { + } + else if ( isDefined( level.last_spawn[ 1 ] ) && point == level.last_spawn[ 1 ] ) + { + } + else + { + spawn_point = point; + level.last_spawn[ level.last_spawn_index ] = spawn_point; + level.last_spawn_index++; + if ( level.last_spawn_index > 1 ) + { + level.last_spawn_index = 0; + } + break; + } + _k250 = getNextArrayKey( _a250, _k250 ); + } + if ( !isDefined( spawn_point ) ) + { + spawn_point = spawn_points[ 0 ]; + } + if ( isDefined( level.screecher_spawners ) ) + { + spawner = random( level.screecher_spawners ); + ai = spawn_zombie( spawner, spawner.targetname, spawn_point ); + } + if ( isDefined( ai ) ) + { + ai.spawn_point = spawn_point; + level.zombie_screecher_count++; +/# + screecher_print( "screecher total " + level.zombie_screecher_count ); +#/ + } + wait level.zombie_vars[ "zombie_spawn_delay" ]; + wait 0,1; + } +} + +player_in_screecher_zone( player ) +{ + if ( isDefined( level.is_player_in_screecher_zone ) ) + { + infog = [[ level.is_player_in_screecher_zone ]]( player ); + return infog; + } + return 1; +} + +screecher_should_runaway( player ) +{ + players = get_players(); + if ( players.size == 1 ) + { + if ( level.near_miss == 1 ) + { + level.near_miss = 2; +/# + screecher_print( "runaway from near_miss " + level.near_miss ); +#/ + return 1; + } + } + if ( isDefined( level.screecher_should_runaway ) ) + { + return self [[ level.screecher_should_runaway ]]( player ); + } + return 0; +} + +screecher_get_closest_valid_player( origin, ignore_player ) +{ + valid_player_found = 0; + players = get_players(); + if ( isDefined( level._zombie_using_humangun ) && level._zombie_using_humangun ) + { + players = arraycombine( players, level._zombie_human_array, 0, 0 ); + } + while ( isDefined( ignore_player ) ) + { + i = 0; + while ( i < ignore_player.size ) + { + arrayremovevalue( players, ignore_player[ i ] ); + i++; + } + } + while ( !valid_player_found ) + { + if ( isDefined( level.calc_closest_player_using_paths ) && level.calc_closest_player_using_paths ) + { + player = get_closest_player_using_paths( origin, players ); + } + else + { + player = getclosest( origin, players ); + } + if ( !isDefined( player ) ) + { + return undefined; + } + if ( isDefined( level._zombie_using_humangun ) && level._zombie_using_humangun && isai( player ) ) + { + return player; + } + if ( isDefined( player.screecher ) ) + { + screecher_claimed = player.screecher != self; + } + if ( players.size == 1 && screecher_claimed ) + { + return undefined; + } + while ( is_player_valid( player, 1 ) || !player_in_screecher_zone( player ) && screecher_claimed ) + { + arrayremovevalue( players, player ); + } + return player; + } +} + +zombie_pathing_home() +{ + self endon( "death" ); + self endon( "zombie_acquire_enemy" ); + level endon( "intermission" ); + self setgoalpos( self.startinglocation ); + self waittill( "goal" ); + playfx( level._effect[ "screecher_spawn_b" ], self.origin, ( 0, 0, 1 ) ); + self.no_powerups = 1; + self setfreecameralockonallowed( 0 ); + self animscripted( self.origin, self.angles, "zm_burrow" ); + self playsound( "zmb_screecher_dig" ); + maps/mp/animscripts/zm_shared::donotetracks( "burrow_anim" ); + self delete(); +} + +screecher_find_flesh() +{ + self endon( "death" ); + level endon( "intermission" ); + self endon( "stop_find_flesh" ); + if ( level.intermission ) + { + return; + } + self.helitarget = 1; + self.ignoreme = 0; + self.nododgemove = 1; + self.ignore_player = []; + self zombie_history( "find flesh -> start" ); + self.goalradius = 32; + while ( 1 ) + { + self.favoriteenemy = screecher_get_closest_valid_player( self.origin ); + if ( isDefined( self.favoriteenemy ) ) + { + self thread zombie_pathing(); + } + else + { + self thread screecher_runaway(); + } + self.zombie_path_timer = getTime() + ( randomfloatrange( 1, 3 ) * 1000 ); + while ( getTime() < self.zombie_path_timer ) + { + wait 0,1; + } + self notify( "path_timer_done" ); + self zombie_history( "find flesh -> bottom of loop" ); + debug_print( "Zombie is re-acquiring enemy, ending breadcrumb search" ); + self notify( "zombie_acquire_enemy" ); + } +} + +screecher_prespawn() +{ + self endon( "death" ); + level endon( "intermission" ); + self.startinglocation = self.origin; + self.animname = "screecher_zombie"; + self.audio_type = "screecher"; + self.has_legs = 1; + self.no_gib = 1; + self.isscreecher = 1; + self.ignore_enemy_count = 1; + recalc_zombie_array(); + self.cant_melee = 1; + if ( isDefined( self.spawn_point ) ) + { + spot = self.spawn_point; + if ( !isDefined( spot.angles ) ) + { + spot.angles = ( 0, 0, 1 ); + } + self forceteleport( spot.origin, spot.angles ); + } + self set_zombie_run_cycle( "super_sprint" ); + self setphysparams( 15, 0, 24 ); + self.actor_damage_func = ::screecher_damage_func; + self.deathfunction = ::screecher_death_func; + self.zombie_init_done = 1; + self notify( "zombie_init_done" ); + self.allowpain = 0; + self animmode( "normal" ); + self orientmode( "face enemy" ); + self.forcemovementscriptstate = 0; + self maps/mp/zombies/_zm_spawner::zombie_setup_attack_properties(); + self maps/mp/zombies/_zm_spawner::zombie_complete_emerging_into_playable_area(); + self setfreecameralockonallowed( 0 ); + self.startinglocation = self.origin; + self playsound( "zmb_vocals_screecher_spawn" ); + self thread play_screecher_fx(); + self thread play_screecher_damaged_yelps(); + self thread screecher_rise(); + self thread screecher_cleanup(); + self thread screecher_distance_tracking(); + self.anchor = spawn( "script_origin", self.origin ); + self.attack_time = 0; + self.attack_delay = 1000; + self.attack_delay_base = 1000; + self.attack_delay_offset = 500; + self.meleedamage = 5; + self.ignore_inert = 1; + self.player_score = 0; + self.screecher_score = 0; + if ( isDefined( level.screecher_init_done ) ) + { + self thread [[ level.screecher_init_done ]](); + } +} + +play_screecher_fx() +{ +/# + if ( isDefined( level.screecher_nofx ) && level.screecher_nofx ) + { + return; +#/ + } + playfx( level._effect[ "screecher_spawn_a" ], self.origin, ( 0, 0, 1 ) ); + playfx( level._effect[ "screecher_spawn_b" ], self.origin, ( 0, 0, 1 ) ); + self waittill( "risen" ); + playfx( level._effect[ "screecher_spawn_c" ], self.origin, ( 0, 0, 1 ) ); +} + +play_screecher_damaged_yelps() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "damage", damage, attacker, dir, point, mod ); + if ( isDefined( attacker ) && isplayer( attacker ) ) + { + self playsound( "zmb_vocals_screecher_pain" ); + } + } +} + +play_screecher_breathing_audio() +{ + wait 0,5; + if ( !isDefined( self ) ) + { + return; + } + if ( !isDefined( self.loopsoundent ) ) + { + self.loopsoundent = spawn( "script_origin", self.origin ); + self.loopsoundent linkto( self, "tag_origin" ); + } + self.loopsoundent playloopsound( "zmb_vocals_screecher_breath" ); +} + +screecher_rise() +{ + self endon( "death" ); + self animscripted( self.origin, self.angles, "zm_rise" ); + maps/mp/animscripts/zm_shared::donotetracks( "rise_anim" ); + self notify( "risen" ); + self setfreecameralockonallowed( 1 ); + self.startinglocation = self.origin; + self thread screecher_zombie_think(); + self thread play_screecher_breathing_audio(); +/# +#/ +} + +screecher_zombie_think() +{ + self endon( "death" ); + min_dist = 96; + max_dist = 144; + height_tolerance = 32; + self.state = "chase_init"; + self.isattacking = 0; + self.nextspecial = getTime(); + for ( ;; ) + { + switch( self.state ) + { + case "chase_init": + self screecher_chase(); + break; + case "chase_update": + self screecher_chase_update(); + break; + case "attacking": + self screecher_attacking(); + break; + } + wait 0,1; + } +} + +screecher_chase() +{ + self thread screecher_find_flesh(); + self.state = "chase_update"; +} + +screecher_chase_update() +{ + player = self.favoriteenemy; + if ( isDefined( player ) ) + { + dist = distance2dsquared( self.origin, player.origin ); + if ( dist < 57600 ) + { + self screecher_attack(); + return; + } + if ( self screecher_should_runaway( player ) ) + { + self thread screecher_runaway(); + return; + } + } +} + +screecher_attack() +{ + self endon( "death" ); + player = self.favoriteenemy; + if ( isDefined( player.screecher ) ) + { + return; + } + else + { + player.screecher = self; + } + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self animmode( "nogravity" ); + self playsound( "zmb_vocals_screecher_jump" ); + if ( isDefined( self.loopsoundent ) ) + { + self.loopsoundent delete(); + self.loopsoundent = undefined; + } + self setanimstatefromasd( "zm_jump_up" ); + maps/mp/animscripts/zm_shared::donotetracks( "jump_up_anim" ); + asd_state = self screecher_fly_to_player( player ); + self setplayercollision( 0 ); + self setclientfield( "render_third_person", 1 ); + self linkto( self.favoriteenemy, "tag_origin" ); + self animscripted( self.favoriteenemy.origin, self.favoriteenemy.angles, asd_state ); + maps/mp/animscripts/zm_shared::donotetracks( "jump_land_success_anim" ); + org = self.favoriteenemy gettagorigin( "j_head" ); + angles = self.favoriteenemy gettagangles( "j_head" ); + self forceteleport( org, angles ); + self linkto( self.favoriteenemy, "j_head" ); + self animscripted( self.origin, self.angles, "zm_headpull" ); + self.linked_ent = self.favoriteenemy; + self.linked_ent setmovespeedscale( 0,5 ); + self thread screecher_melee_button_watcher(); + self screecher_start_attack(); +} + +screecher_fly_to_player( player ) +{ + self endon( "death" ); + self setanimstatefromasd( "zm_jump_loop" ); + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + anim_id_back = self getanimfromasd( "zm_jump_land_success_fromback", 0 ); + anim_id_front = self getanimfromasd( "zm_jump_land_success_fromfront", 0 ); + end_time = getTime() + 2500; + dist = undefined; + dist_update = undefined; + while ( end_time > getTime() ) + { + goal_pos_back = getstartorigin( player.origin, player.angles, anim_id_back ); + goal_pos_front = getstartorigin( player.origin, player.angles, anim_id_front ); + dist_back = distancesquared( self.anchor.origin, goal_pos_back ); + dist_front = distancesquared( self.anchor.origin, goal_pos_front ); + goal_pos = goal_pos_back; + goal_ang = getstartangles( player.origin, player.angles, anim_id_back ); + asd_state = "zm_jump_land_success_fromback"; + if ( dist_front < dist_back ) + { + goal_pos = goal_pos_front; + goal_ang = getstartangles( player.origin, player.angles, anim_id_front ); + asd_state = "zm_jump_land_success_fromfront"; + } + facing_vec = goal_pos - self.anchor.origin; + facing_angles = vectorToAngle( facing_vec ); + dist = length( facing_vec ); + if ( !isDefined( dist_update ) ) + { + time = 0,5; + vel = dist / time; + dist_update = vel * 0,1; + } + if ( dist < dist_update ) + { + self.anchor.origin = goal_pos; + self.anchor.angles = goal_ang; + break; + } + else + { + self.anchor.angles = facing_angles; + unit_facing_vec = vectornormalize( facing_vec ); + new_pos = self.anchor.origin + vectorScale( unit_facing_vec, dist_update ); + self.anchor moveto( new_pos, 0,1 ); + wait 0,1; + } + } + return asd_state; +} + +finish_planting_equipment() +{ + while ( self isthrowinggrenade() && is_equipment( self getcurrentweapon() ) ) + { + wait 0,05; + } +} + +screecher_start_attack() +{ + player = self.favoriteenemy; + if ( is_player_valid( player ) ) + { + player playsoundtoplayer( "zmb_screecher_impact", player ); + player finish_planting_equipment(); + player allowprone( 0 ); + player.screecher_weapon = player getcurrentweapon(); + player giveweapon( "screecher_arms_zm" ); + throwing_grenade = 0; + if ( player isthrowinggrenade() ) + { + throwing_grenade = 1; + primaryweapons = player getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + player.screecher_weapon = primaryweapons[ 0 ]; + player forcegrenadethrow(); + player switchtoweaponimmediate( "screecher_arms_zm" ); + } + } + else if ( player.screecher_weapon == "riotshield_zm" ) + { + player switchtoweaponimmediate( "screecher_arms_zm" ); + } + else + { + player switchtoweapon( "screecher_arms_zm" ); + } + player increment_is_drinking(); + wait 0,5; + player clientnotify( "scrStrt" ); + if ( player isthrowinggrenade() && !throwing_grenade ) + { + primaryweapons = player getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + player.screecher_weapon = primaryweapons[ 0 ]; + player forcegrenadethrow(); + player switchtoweaponimmediate( "screecher_arms_zm" ); + } + } + self.state = "attacking"; + self.attack_time = getTime(); + if ( !getDvarInt( #"E7EF8EB7" ) ) + { + player startpoisoning(); + } + self thread screecher_player_down(); + } + else + { + self screecher_detach( player ); + } +} + +screecher_player_down() +{ + self endon( "death" ); + self endon( "runaway" ); + player = self.linked_ent; + player endon( "death" ); + player endon( "disconnect" ); + player waittill( "player_downed" ); + self thread screecher_detach( player ); +} + +screecher_first_seen_hint_think() +{ + if ( !flag( "solo_game" ) ) + { + return; + } + fade_time = 3; + hudelem = self maps/mp/gametypes_zm/_hud_util::createfontstring( "objective", 2 ); + hudelem maps/mp/gametypes_zm/_hud_util::setpoint( "TOP", undefined, 0, 200 ); + hudelem.label = &"ZOMBIE_SCREECHER_ATTACH_FIRST"; + hudelem.sort = 0,5; + hudelem.alpha = 1; + hudelem fadeovertime( fade_time ); + hudelem.alpha = 0; + wait fade_time; + hudelem destroy(); +} + +screecher_attacking() +{ + player = self.favoriteenemy; + if ( !isDefined( player ) ) + { + self thread screecher_detach( player ); + return; + } + if ( isDefined( player.screecher_seen_hint ) && !player.screecher_seen_hint ) + { + player thread screecher_first_seen_hint_think(); + player.screecher_seen_hint = 1; + } + if ( screecher_should_runaway( player ) ) + { + self thread screecher_detach( player ); + player thread do_player_general_vox( "general", "screecher_jumpoff" ); + return; + } + if ( self.attack_time < getTime() ) + { + scratch_score = 5; + players = get_players(); + self.screecher_score += scratch_score; + killed_player = self screecher_check_score(); + if ( player.health > 0 && isDefined( killed_player ) && !killed_player ) + { + self.attack_delay = self.attack_delay_base + randomint( self.attack_delay_offset ); + self.attack_time = getTime() + self.attack_delay; + self thread claw_fx( player, self.attack_delay * 0,001 ); + self playsound( "zmb_vocals_screecher_attack" ); + player playsoundtoplayer( "zmb_screecher_scratch", player ); + player thread do_player_general_vox( "general", "screecher_attack" ); + players = get_players(); + if ( players.size == 1 ) + { + if ( level.near_miss == 0 ) + { + level.near_miss = 1; +/# + screecher_print( "first attack near_miss " + level.near_miss ); +#/ + } + } + } + } +} + +screecher_runaway() +{ + self endon( "death" ); +/# + screecher_print( "runaway" ); +#/ + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self notify( "runaway" ); + self.state = "runaway"; + self.ignoreall = 1; + self setgoalpos( self.startinglocation ); + self waittill( "goal" ); + playfx( level._effect[ "screecher_spawn_b" ], self.origin, ( 0, 0, 1 ) ); + self.no_powerups = 1; + self setfreecameralockonallowed( 0 ); + self animscripted( self.origin, self.angles, "zm_burrow" ); + self playsound( "zmb_screecher_dig" ); + maps/mp/animscripts/zm_shared::donotetracks( "burrow_anim" ); + self delete(); +} + +screecher_detach( player ) +{ + self endon( "death" ); + self.state = "detached"; + if ( !isDefined( self.linked_ent ) ) + { + return; + } +/# + screecher_print( "detach" ); +#/ + if ( isDefined( player ) ) + { + player clientnotify( "scrEnd" ); + if ( isDefined( player.isonbus ) && !player.isonbus ) + { + player allowprone( 1 ); + } + player takeweapon( "screecher_arms_zm" ); + if ( !getDvarInt( #"E7EF8EB7" ) ) + { + player stoppoisoning(); + } + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( player.intermission ) && !player.intermission ) + { + player decrement_is_drinking(); + } + if ( isDefined( player.screecher_weapon ) && player.screecher_weapon != "none" && is_player_valid( player ) && !is_equipment_that_blocks_purchase( player.screecher_weapon ) ) + { + player switchtoweapon( player.screecher_weapon ); + } + else + { + if ( flag( "solo_game" ) && player hasperk( "specialty_quickrevive" ) ) + { + } + else + { + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + primaryweapons = player getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + player switchtoweapon( primaryweapons[ 0 ] ); + } + } + } + } + player.screecher_weapon = undefined; + } + self unlink(); + self setclientfield( "render_third_person", 0 ); + if ( isDefined( self.linked_ent ) ) + { + self.linked_ent.screecher = undefined; + self.linked_ent setmovespeedscale( 1 ); + self.linked_ent = undefined; + } + self.green_light = player.green_light; + self animcustom( ::screecher_jump_down ); + self waittill( "jump_down_done" ); + maps/mp/_visionset_mgr::vsmgr_deactivate( "overlay", "zm_ai_screecher_blur", player ); + self animmode( "normal" ); + self.ignoreall = 1; + self setplayercollision( 1 ); + if ( isDefined( level.screecher_should_burrow ) ) + { + if ( self [[ level.screecher_should_burrow ]]() ) + { +/# + screecher_print( "should burrow" ); +#/ + return; + } + } + self thread screecher_runaway(); +} + +screecher_jump_down() +{ + self endon( "death" ); + self setanimstatefromasd( "zm_headpull_success" ); + wait 0,6; + self notify( "jump_down_done" ); +} + +create_claw_fx_hud( player ) +{ + self.claw_fx = newclienthudelem( player ); + self.claw_fx.horzalign = "fullscreen"; + self.claw_fx.vertalign = "fullscreen"; +} + +choose_claw_fx() +{ + direction = []; + direction[ direction.size ] = "fullscreen_claw_left"; + direction[ direction.size ] = "fullscreen_claw_right"; + direction[ direction.size ] = "fullscreen_claw_bottom"; + direction = array_randomize( direction ); + self.claw_fx setshader( direction[ 0 ], 640, 480 ); + self.claw_fx.alpha = 1; +} + +claw_fx( player, timeout ) +{ + self endon( "death" ); + claw_timeout = 0,25; + if ( !isDefined( self.claw_fx ) ) + { + self create_claw_fx_hud( player ); + } + self choose_claw_fx(); + self.claw_fx fadeovertime( claw_timeout ); + self.claw_fx.alpha = 0; + earthquake( randomfloatrange( 0,4, 0,5 ), claw_timeout, player.origin, 250 ); + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_screecher_blur", player, 0,25 ); +} + +screecher_cleanup() +{ + self waittill( "death", attacker ); + if ( isDefined( attacker ) && isplayer( attacker ) ) + { + if ( isDefined( self.damagelocation ) && isDefined( self.damagemod ) ) + { + level thread maps/mp/zombies/_zm_audio::player_zombie_kill_vox( self.damagelocation, attacker, self.damagemod, self ); + } + } + if ( isDefined( self.loopsoundent ) ) + { + self.loopsoundent delete(); + self.loopsoundent = undefined; + } + player = self.linked_ent; + if ( isDefined( player ) ) + { + player playsound( "zmb_vocals_screecher_death" ); + player setmovespeedscale( 1 ); + maps/mp/_visionset_mgr::vsmgr_deactivate( "overlay", "zm_ai_screecher_blur", player ); + if ( isDefined( player.screecher_weapon ) ) + { + player clientnotify( "scrEnd" ); + if ( isDefined( player.isonbus ) && !player.isonbus ) + { + player allowprone( 1 ); + } + player takeweapon( "screecher_arms_zm" ); + if ( !getDvarInt( #"E7EF8EB7" ) ) + { + player stoppoisoning(); + } + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( player.intermission ) && !player.intermission ) + { + player decrement_is_drinking(); + } + if ( player.screecher_weapon != "none" && is_player_valid( player ) ) + { + player switchtoweapon( player.screecher_weapon ); + } + else + { + primaryweapons = player getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + player switchtoweapon( primaryweapons[ 0 ] ); + } + } + player.screecher_weapon = undefined; + } + } + if ( isDefined( self.claw_fx ) ) + { + self.claw_fx destroy(); + } + if ( isDefined( self.anchor ) ) + { + self.anchor delete(); + } + if ( isDefined( level.screecher_cleanup ) ) + { + self [[ level.screecher_cleanup ]](); + } + if ( level.zombie_screecher_count > 0 ) + { + level.zombie_screecher_count--; + +/# + screecher_print( "screecher total " + level.zombie_screecher_count ); +#/ + } +} + +screecher_distance_tracking() +{ + self endon( "death" ); + while ( 1 ) + { + can_delete = 1; + players = get_players(); + _a1304 = players; + _k1304 = getFirstArrayKey( _a1304 ); + while ( isDefined( _k1304 ) ) + { + player = _a1304[ _k1304 ]; + if ( player.sessionstate == "spectator" ) + { + } + else dist_sq = distancesquared( self.origin, player.origin ); + if ( dist_sq >= 4000000 ) + { + } + else + { + can_see = player maps/mp/zombies/_zm_utility::is_player_looking_at( self.origin, 0,9, 0 ); + if ( can_see || dist_sq < 1000000 ) + { + can_delete = 0; + break; + } + } + else + { + _k1304 = getNextArrayKey( _a1304, _k1304 ); + } + } + if ( can_delete ) + { + self notify( "zombie_delete" ); + if ( isDefined( self.anchor ) ) + { + self.anchor delete(); + } + self delete(); + recalc_zombie_array(); + } + wait 0,1; + } +} + +screecher_melee_button_watcher() +{ + self endon( "death" ); + while ( isDefined( self.linked_ent ) ) + { + player = self.linked_ent; + while ( player meleebuttonpressed() && player ismeleeing() ) + { + self screecher_melee_damage( player ); + while ( player meleebuttonpressed() || player ismeleeing() ) + { + wait 0,05; + } + } + wait 0,05; + } +} + +screecher_melee_damage( player ) +{ + one_player = 0; + melee_score = 0; + if ( player hasweapon( "bowie_knife_zm" ) ) + { + if ( one_player ) + { + melee_score = 30; + } + else + { + melee_score = 10; + } + } + else if ( player hasweapon( "tazer_knuckles_zm" ) ) + { + if ( one_player ) + { + melee_score = 30; + } + else + { + melee_score = 15; + } + } + else if ( one_player ) + { + melee_score = 15; + } + else + { + melee_score = 6; + } + extra_score = 0; + if ( self.screecher_score > 0 && !one_player ) + { + if ( melee_score > self.screecher_score ) + { + extra_score = melee_score - self.screecher_score; + self.screecher_score = 0; + } + else + { + self.screecher_score -= melee_score; + } + } + if ( self.screecher_score <= 0 || one_player ) + { + self.player_score += melee_score; + if ( extra_score > 0 ) + { + self.player_score += extra_score; + } + } + self playsound( "zmb_vocals_screecher_pain" ); + if ( level.zombie_vars[ player.team ][ "zombie_insta_kill" ] ) + { + self.player_score = 30; + } + else + { + player thread do_player_general_vox( "general", "screecher_cut" ); + } +/# + if ( getDvarInt( #"6A65F83E" ) ) + { + self.player_score = 30; +#/ + } + self screecher_check_score(); +} + +screecher_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( isDefined( self.linked_ent ) ) + { + if ( isplayer( einflictor ) && smeansofdeath == "MOD_MELEE" ) + { + return 0; + } + } + return idamage; +} + +screecher_death_func() +{ + self unlink(); + self.noragdoll = 1; + self setanimstatefromasd( "zm_death" ); + maps/mp/animscripts/zm_shared::donotetracks( "death_anim" ); + playfx( level._effect[ "screecher_death" ], self.origin ); + if ( isDefined( self.attacker ) && isplayer( self.attacker ) ) + { + self.attacker maps/mp/zombies/_zm_stats::increment_client_stat( "screechers_killed", 0 ); + self.attacker maps/mp/zombies/_zm_stats::increment_player_stat( "screechers_killed" ); + } + self delete(); + return 1; +} + +screecher_check_score() +{ + if ( self.player_score >= 30 ) + { + player = self.linked_ent; + if ( isDefined( player ) ) + { + player notify( "i_dont_think_they_exist" ); + player maps/mp/zombies/_zm_stats::increment_client_stat( "screecher_minigames_won", 0 ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "screecher_minigames_won" ); + } + self dodamage( self.health + 666, self.origin ); + } + else + { + if ( self.screecher_score >= 15 ) + { +/# + if ( getDvarInt( #"6A65F83E" ) ) + { + return 0; +#/ + } + player = self.linked_ent; + if ( isDefined( player ) ) + { + self.meleedamage = player.health; + player dodamage( player.health, self.origin, self ); + self screecher_detach( player ); + player maps/mp/zombies/_zm_stats::increment_client_stat( "screecher_minigames_lost", 0 ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "screecher_minigames_lost" ); + return 1; + } + } + } +/# + screecher_print( "score: player " + self.player_score + " screecher " + self.screecher_score ); +#/ + return 0; +} + +screecher_debug_axis() +{ +/# + self endon( "death" ); + while ( 1 ) + { + if ( isDefined( self.favoriteenemy ) ) + { + player = self.favoriteenemy; + anim_id = self getanimfromasd( "zm_jump_land_success", 0 ); + org = getstartorigin( player.origin, player.angles, anim_id ); + angles = getstartangles( player.origin, player.angles, anim_id ); + if ( !isDefined( player.bone_fxaxis ) ) + { + player.bone_fxaxis = spawn( "script_model", org ); + player.bone_fxaxis setmodel( "fx_axis_createfx" ); + } + if ( isDefined( player.bone_fxaxis ) ) + { + player.bone_fxaxis.origin = org; + player.bone_fxaxis.angles = angles; + } + } + wait 0,1; +#/ + } +} + +screecher_print( str ) +{ +/# + if ( getDvarInt( #"72C3A9C6" ) ) + { + iprintln( "screecher: " + str + "\n" ); + if ( isDefined( self ) ) + { + if ( isDefined( self.debug_msg ) ) + { + self.debug_msg[ self.debug_msg.size ] = str; + return; + } + else + { + self.debug_msg = []; + self.debug_msg[ self.debug_msg.size ] = str; +#/ + } + } + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_banking.gsc b/zm_transit_patch/maps/mp/zombies/_zm_banking.gsc new file mode 100644 index 0000000..69431c5 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_banking.gsc @@ -0,0 +1,326 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + onplayerconnect_callback( ::onplayerconnect_bank_deposit_box ); + if ( !isDefined( level.ta_vaultfee ) ) + { + level.ta_vaultfee = 100; + } + if ( !isDefined( level.ta_tellerfee ) ) + { + level.ta_tellerfee = 100; + } +} + +main() +{ + if ( !isDefined( level.banking_map ) ) + { + level.banking_map = level.script; + } + level thread bank_teller_init(); + level thread bank_deposit_box(); +} + +bank_teller_init() +{ + level.bank_teller_dmg_trig = getent( "bank_teller_tazer_trig", "targetname" ); + if ( isDefined( level.bank_teller_dmg_trig ) ) + { + level.bank_teller_transfer_trig = getent( level.bank_teller_dmg_trig.target, "targetname" ); + level.bank_teller_powerup_spot = getstruct( level.bank_teller_transfer_trig.target, "targetname" ); + level thread bank_teller_logic(); + level.bank_teller_transfer_trig.origin += vectorScale( ( 0, 0, -1 ), 25 ); + level.bank_teller_transfer_trig trigger_off(); + level.bank_teller_transfer_trig sethintstring( &"ZOMBIE_TELLER_GIVE_MONEY", level.ta_tellerfee ); + } +} + +bank_teller_logic() +{ + level endon( "end_game" ); + while ( 1 ) + { + level.bank_teller_dmg_trig waittill( "damage", damage, attacker, direction, point, type, tagname, modelname, partname, weaponname, blah ); + if ( isDefined( attacker ) && isplayer( attacker ) && damage == 1500 && type == "MOD_MELEE" ) + { + bank_teller_give_money(); + level.bank_teller_transfer_trig trigger_off(); + } + } +} + +bank_teller_give_money() +{ + level endon( "end_game" ); + level endon( "stop_bank_teller" ); + level.bank_teller_transfer_trig trigger_on(); + bank_transfer = undefined; + while ( 1 ) + { + level.bank_teller_transfer_trig waittill( "trigger", player ); + if ( !is_player_valid( player, 0 ) || player.score < ( 1000 + level.ta_tellerfee ) ) + { + continue; + } + if ( !isDefined( bank_transfer ) ) + { + bank_transfer = maps/mp/zombies/_zm_powerups::specific_powerup_drop( "teller_withdrawl", level.bank_teller_powerup_spot.origin + vectorScale( ( 0, 0, -1 ), 40 ) ); + bank_transfer thread stop_bank_teller(); + bank_transfer.value = 0; + } + bank_transfer.value += 1000; + bank_transfer notify( "powerup_reset" ); + bank_transfer thread maps/mp/zombies/_zm_powerups::powerup_timeout(); + player maps/mp/zombies/_zm_score::minus_to_player_score( 1000 + level.ta_tellerfee ); + level notify( "bank_teller_used" ); + } +} + +stop_bank_teller() +{ + level endon( "end_game" ); + self waittill( "death" ); + level notify( "stop_bank_teller" ); +} + +delete_bank_teller() +{ + wait 1; + level notify( "stop_bank_teller" ); + bank_teller_dmg_trig = getent( "bank_teller_tazer_trig", "targetname" ); + bank_teller_transfer_trig = getent( bank_teller_dmg_trig.target, "targetname" ); + bank_teller_dmg_trig delete(); + bank_teller_transfer_trig delete(); +} + +onplayerconnect_bank_deposit_box() +{ + online_game = sessionmodeisonlinegame(); + if ( !online_game ) + { + self.account_value = 0; + } + else + { + self.account_value = self maps/mp/zombies/_zm_stats::get_map_stat( "depositBox", level.banking_map ); + } +} + +bank_deposit_box() +{ + level.bank_deposit_max_amount = 250000; + level.bank_deposit_ddl_increment_amount = 1000; + level.bank_account_max = level.bank_deposit_max_amount / level.bank_deposit_ddl_increment_amount; + level.bank_account_increment = int( level.bank_deposit_ddl_increment_amount / 1000 ); + deposit_triggers = getstructarray( "bank_deposit", "targetname" ); + array_thread( deposit_triggers, ::bank_deposit_unitrigger ); + withdraw_triggers = getstructarray( "bank_withdraw", "targetname" ); + array_thread( withdraw_triggers, ::bank_withdraw_unitrigger ); +} + +bank_deposit_unitrigger() +{ + bank_unitrigger( "bank_deposit", ::trigger_deposit_update_prompt, ::trigger_deposit_think, 5, 5, undefined, 5 ); +} + +bank_withdraw_unitrigger() +{ + bank_unitrigger( "bank_withdraw", ::trigger_withdraw_update_prompt, ::trigger_withdraw_think, 5, 5, undefined, 5 ); +} + +bank_unitrigger( name, prompt_fn, think_fn, override_length, override_width, override_height, override_radius ) +{ + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = self.origin; + if ( isDefined( self.script_angles ) ) + { + unitrigger_stub.angles = self.script_angles; + } + else + { + unitrigger_stub.angles = self.angles; + } + unitrigger_stub.script_angles = unitrigger_stub.angles; + if ( isDefined( override_length ) ) + { + unitrigger_stub.script_length = override_length; + } + else if ( isDefined( self.script_length ) ) + { + unitrigger_stub.script_length = self.script_length; + } + else + { + unitrigger_stub.script_length = 32; + } + if ( isDefined( override_width ) ) + { + unitrigger_stub.script_width = override_width; + } + else if ( isDefined( self.script_width ) ) + { + unitrigger_stub.script_width = self.script_width; + } + else + { + unitrigger_stub.script_width = 32; + } + if ( isDefined( override_height ) ) + { + unitrigger_stub.script_height = override_height; + } + else if ( isDefined( self.script_height ) ) + { + unitrigger_stub.script_height = self.script_height; + } + else + { + unitrigger_stub.script_height = 64; + } + if ( isDefined( override_radius ) ) + { + unitrigger_stub.script_radius = override_radius; + } + else if ( isDefined( self.radius ) ) + { + unitrigger_stub.radius = self.radius; + } + else + { + unitrigger_stub.radius = 32; + } + if ( isDefined( self.script_unitrigger_type ) ) + { + unitrigger_stub.script_unitrigger_type = self.script_unitrigger_type; + } + else + { + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.origin -= anglesToRight( unitrigger_stub.angles ) * ( unitrigger_stub.script_length / 2 ); + } + unitrigger_stub.cursor_hint = "HINT_NOICON"; + unitrigger_stub.targetname = name; + maps/mp/zombies/_zm_unitrigger::unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + unitrigger_stub.prompt_and_visibility_func = prompt_fn; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, think_fn ); +} + +trigger_deposit_update_prompt( player ) +{ + if ( player.score < level.bank_deposit_ddl_increment_amount || player.account_value >= level.bank_account_max ) + { + player show_balance(); + self sethintstring( "" ); + return 0; + } + self sethintstring( &"ZOMBIE_BANK_DEPOSIT_PROMPT", level.bank_deposit_ddl_increment_amount ); + return 1; +} + +trigger_deposit_think() +{ + self endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !is_player_valid( player ) ) + { + continue; + } + if ( player.score >= level.bank_deposit_ddl_increment_amount && player.account_value < level.bank_account_max ) + { + player playsoundtoplayer( "zmb_vault_bank_deposit", player ); + player.score -= level.bank_deposit_ddl_increment_amount; + player.account_value += level.bank_account_increment; + player maps/mp/zombies/_zm_stats::set_map_stat( "depositBox", player.account_value, level.banking_map ); + if ( isDefined( level.custom_bank_deposit_vo ) ) + { + player thread [[ level.custom_bank_deposit_vo ]](); + } + if ( player.account_value >= level.bank_account_max ) + { + self sethintstring( "" ); + } + } + else + { + player thread do_player_general_vox( "general", "exert_sigh", 10, 50 ); + } + player show_balance(); + } +} + +trigger_withdraw_update_prompt( player ) +{ + if ( player.account_value <= 0 ) + { + self sethintstring( "" ); + player show_balance(); + return 0; + } + self sethintstring( &"ZOMBIE_BANK_WITHDRAW_PROMPT", level.bank_deposit_ddl_increment_amount, level.ta_vaultfee ); + return 1; +} + +trigger_withdraw_think() +{ + self endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !is_player_valid( player ) ) + { + continue; + } + if ( player.account_value >= level.bank_account_increment ) + { + player playsoundtoplayer( "zmb_vault_bank_withdraw", player ); + player.score += level.bank_deposit_ddl_increment_amount; + level notify( "bank_withdrawal" ); + player.account_value -= level.bank_account_increment; + player maps/mp/zombies/_zm_stats::set_map_stat( "depositBox", player.account_value, level.banking_map ); + if ( isDefined( level.custom_bank_withdrawl_vo ) ) + { + player thread [[ level.custom_bank_withdrawl_vo ]](); + } + else + { + player thread do_player_general_vox( "general", "exert_laugh", 10, 50 ); + } + player thread player_withdraw_fee(); + if ( player.account_value < level.bank_account_increment ) + { + self sethintstring( "" ); + } + } + else + { + player thread do_player_general_vox( "general", "exert_sigh", 10, 50 ); + } + player show_balance(); + } +} + +player_withdraw_fee() +{ + self endon( "disconnect" ); + wait_network_frame(); + self.score -= level.ta_vaultfee; +} + +show_balance() +{ +/# + iprintlnbold( "DEBUG BANKER: " + self.name + " account worth " + self.account_value ); +#/ +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_equip_electrictrap.gsc b/zm_transit_patch/maps/mp/zombies/_zm_equip_electrictrap.gsc new file mode 100644 index 0000000..b73ef9d --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_equip_electrictrap.gsc @@ -0,0 +1,414 @@ +#include maps/mp/zombies/_zm_traps; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_power; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_electrictrap_zm" ) ) + { + return; + } + level.electrictrap_name = "equip_electrictrap_zm"; + maps/mp/zombies/_zm_equipment::register_equipment( "equip_electrictrap_zm", &"ZOMBIE_EQUIP_ELECTRICTRAP_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_ELECTRICTRAP_HOWTO", "etrap_zm_icon", "electrictrap", undefined, ::transfertrap, ::droptrap, ::pickuptrap, ::placetrap ); + maps/mp/zombies/_zm_equipment::add_placeable_equipment( "equip_electrictrap_zm", "p6_anim_zm_buildable_etrap" ); + level thread onplayerconnect(); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "equip_electrictrap", &"ZOMBIE_EQUIP_ELECTRICTRAP_PICKUP_HINT_STRING" ); + level._effect[ "etrap_on" ] = loadfx( "maps/zombie/fx_zmb_tranzit_electric_trap_on" ); + thread wait_init_damage(); +} + +wait_init_damage() +{ + while ( !isDefined( level.zombie_vars ) || !isDefined( level.zombie_vars[ "zombie_health_start" ] ) ) + { + wait 1; + } + level.etrap_damage = maps/mp/zombies/_zm::ai_zombie_health( 50 ); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread onplayerspawned(); + } +} + +onplayerspawned() +{ + self endon( "disconnect" ); + self thread setupwatchers(); + for ( ;; ) + { + self waittill( "spawned_player" ); + self thread watchelectrictrapuse(); + } +} + +setupwatchers() +{ + self waittill( "weapon_watchers_created" ); + watcher = maps/mp/gametypes_zm/_weaponobjects::getweaponobjectwatcher( "equip_electrictrap" ); + watcher.onspawnretrievetriggers = ::maps/mp/zombies/_zm_equipment::equipment_onspawnretrievableweaponobject; +} + +watchelectrictrapuse() +{ + self notify( "watchElectricTrapUse" ); + self endon( "watchElectricTrapUse" ); + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_placed", weapon, weapname ); + if ( weapname == level.electrictrap_name ) + { + self cleanupoldtrap(); + self.buildableelectrictrap = weapon; + self thread startelectrictrapdeploy( weapon ); + } + } +} + +cleanupoldtrap() +{ + if ( isDefined( self.buildableelectrictrap ) ) + { + if ( isDefined( self.buildableelectrictrap.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildableelectrictrap.stub ); + self.buildableelectrictrap.stub = undefined; + } + self.buildableelectrictrap delete(); + } + if ( isDefined( level.electrap_sound_ent ) ) + { + level.electrap_sound_ent delete(); + level.electrap_sound_ent = undefined; + } +} + +watchforcleanup() +{ + self notify( "etrap_cleanup" ); + self endon( "etrap_cleanup" ); + self waittill_any( "death_or_disconnect", "equip_electrictrap_zm_taken", "equip_electrictrap_zm_pickup" ); + cleanupoldtrap(); +} + +placetrap( origin, angles ) +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "p6_anim_zm_buildable_etrap", "equip_electrictrap_zm", origin, angles ); + if ( isDefined( item ) ) + { + item.owner = self; + item.zombie_attack_callback = ::zombie_attacked_trap; + } + return item; +} + +droptrap() +{ + item = self maps/mp/zombies/_zm_equipment::dropped_equipment_think( "p6_anim_zm_buildable_etrap", "equip_electrictrap_zm", self.origin, self.angles ); + if ( isDefined( item ) ) + { + item.electrictrap_health = self.electrictrap_health; + } + self.electrictrap_health = undefined; + return item; +} + +pickuptrap( item ) +{ + item.owner = self; + self.electrictrap_health = item.electrictrap_health; + item.electrictrap_health = undefined; +} + +transfertrap( fromplayer, toplayer ) +{ + buildableelectrictrap = toplayer.buildableelectrictrap; + electrictrap_health = toplayer.electrictrap_health; + toplayer.buildableelectrictrap = fromplayer.buildableelectrictrap; + toplayer.buildableelectrictrap.original_owner = toplayer; + toplayer notify( "equip_electrictrap_zm_taken" ); + toplayer thread startelectrictrapdeploy( toplayer.buildableelectrictrap ); + toplayer.electrictrap_health = fromplayer.electrictrap_health; + fromplayer.buildableelectrictrap = buildableelectrictrap; + fromplayer notify( "equip_electrictrap_zm_taken" ); + if ( isDefined( fromplayer.buildableelectrictrap ) ) + { + fromplayer thread startelectrictrapdeploy( fromplayer.buildableelectrictrap ); + fromplayer.buildableelectrictrap.original_owner = fromplayer; + fromplayer.buildableelectrictrap.owner = fromplayer; + } + else + { + fromplayer maps/mp/zombies/_zm_equipment::equipment_release( "equip_electrictrap_zm" ); + } + fromplayer.electrictrap_health = electrictrap_health; +} + +startelectrictrapdeploy( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_electrictrap_zm_taken" ); + self thread watchforcleanup(); + electricradius = 45; + if ( !isDefined( self.electrictrap_health ) ) + { + self.electrictrap_health = 60; + } + if ( isDefined( weapon ) ) + { +/# + weapon thread debugelectrictrap( electricradius ); +#/ + if ( isDefined( level.equipment_etrap_needs_power ) && level.equipment_etrap_needs_power ) + { + weapon.power_on = 0; + maps/mp/zombies/_zm_power::add_temp_powered_item( ::trap_power_on, ::trap_power_off, ::trap_in_range, ::maps/mp/zombies/_zm_power::cost_high, 1, weapon.power_on, weapon ); + } + else + { + weapon.power_on = 1; + } + if ( !weapon.power_on ) + { + self iprintlnbold( &"ZOMBIE_NEED_LOCAL_POWER" ); + } + self thread electrictrapthink( weapon, electricradius ); + if ( isDefined( level.equipment_etrap_needs_power ) && !level.equipment_etrap_needs_power ) + { + self thread electrictrapdecay( weapon ); + } + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( weapon ); + weapon waittill( "death" ); + if ( isDefined( level.electrap_sound_ent ) ) + { + level.electrap_sound_ent playsound( "wpn_zmb_electrap_stop" ); + level.electrap_sound_ent delete(); + level.electrap_sound_ent = undefined; + } + self notify( "etrap_cleanup" ); + } +} + +trap_in_range( delta, origin, radius ) +{ + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +trap_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: trap on\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 1; + self.target.power_on_time = getTime(); + self.target notify( "stop_attracting_zombies" ); + if ( !isDefined( level.electrap_sound_ent ) ) + { + level.electrap_sound_ent = spawn( "script_origin", self.target.origin ); + } + level.electrap_sound_ent playsound( "wpn_zmb_electrap_start" ); + level.electrap_sound_ent playloopsound( "wpn_zmb_electrap_loop", 2 ); + self.target thread trapfx(); +} + +trap_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: trap off\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 0; + self.target thread item_attract_zombies(); + if ( isDefined( level.electrap_sound_ent ) ) + { + level.electrap_sound_ent playsound( "wpn_zmb_electrap_stop" ); + level.electrap_sound_ent delete(); + level.electrap_sound_ent = undefined; + } +} + +trapfx() +{ + self endon( "disconnect" ); + while ( isDefined( self ) && isDefined( self.power_on ) && self.power_on ) + { + playfxontag( level._effect[ "etrap_on" ], self, "tag_origin" ); + wait 0,3; + } +} + +zombie_attacked_trap( zombie ) +{ + if ( isDefined( self.power_on ) && self.power_on ) + { + self zap_zombie( zombie ); + } +} + +electrocution_lockout( time ) +{ + level.electrocuting_zombie = 1; + wait time; + level.electrocuting_zombie = 0; +} + +zap_zombie( zombie ) +{ + if ( isDefined( zombie.ignore_electric_trap ) && zombie.ignore_electric_trap ) + { + return; + } + if ( zombie.health > level.etrap_damage ) + { + zombie dodamage( level.etrap_damage, self.origin ); + zombie.ignore_electric_trap = 1; + return; + } + self playsound( "wpn_zmb_electrap_zap" ); + if ( isDefined( level.electrocuting_zombie ) && !level.electrocuting_zombie ) + { + thread electrocution_lockout( 2 ); + zombie thread play_elec_vocals(); + zombie thread maps/mp/zombies/_zm_traps::electroctute_death_fx(); + zombie.is_on_fire = 0; + zombie notify( "stop_flame_damage" ); + } + zombie thread electrictrapkill( self ); +} + +etrap_choke() +{ + if ( !isDefined( level.etrap_choke_count ) ) + { + level.etrap_choke_count = 0; + } + level.etrap_choke_count++; + if ( level.etrap_choke_count >= 5 ) + { + wait 0,05; + level.etrap_choke_count = 0; + } +} + +electrictrapthink( weapon, electricradius ) +{ + weapon endon( "death" ); + radiussquared = electricradius * electricradius; + while ( isDefined( weapon ) ) + { + while ( weapon.power_on && ( getTime() - weapon.power_on_time ) > 2000 ) + { + zombies = getaiarray( level.zombie_team ); + _a354 = zombies; + _k354 = getFirstArrayKey( _a354 ); + while ( isDefined( _k354 ) ) + { + zombie = _a354[ _k354 ]; + if ( !isDefined( zombie ) || !isalive( zombie ) ) + { + } + else + { + if ( isDefined( zombie.ignore_electric_trap ) && zombie.ignore_electric_trap ) + { + break; + } + else + { + if ( distancesquared( weapon.origin, zombie.origin ) < radiussquared ) + { + weapon zap_zombie( zombie ); + wait 0,15; + } + etrap_choke(); + } + } + _k354 = getNextArrayKey( _a354, _k354 ); + } + players = get_players(); + _a373 = players; + _k373 = getFirstArrayKey( _a373 ); + while ( isDefined( _k373 ) ) + { + player = _a373[ _k373 ]; + if ( is_player_valid( player ) && distancesquared( weapon.origin, player.origin ) < radiussquared ) + { + player thread maps/mp/zombies/_zm_traps::player_elec_damage(); + etrap_choke(); + } + etrap_choke(); + _k373 = getNextArrayKey( _a373, _k373 ); + } + } + wait 0,1; + } +} + +electrictrapkill( weapon ) +{ + self endon( "death" ); + wait randomfloatrange( 0,1, 0,4 ); + self dodamage( self.health + 666, self.origin ); +} + +electrictrapdecay( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_electrictrap_zm_taken" ); + while ( isDefined( weapon ) ) + { + if ( weapon.power_on ) + { + self.electrictrap_health--; + + if ( self.electrictrap_health <= 0 ) + { + self cleanupoldtrap(); + self.electrictrap_health = undefined; + self thread maps/mp/zombies/_zm_equipment::equipment_release( "equip_electrictrap_zm" ); + return; + } + } + wait 1; + } +} + +debugelectrictrap( radius ) +{ +/# + while ( isDefined( self ) ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + circle( self.origin, radius, ( 1, 1, 1 ), 0, 1, 1 ); + } + wait 0,05; +#/ + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_equip_turret.gsc b/zm_transit_patch/maps/mp/zombies/_zm_equip_turret.gsc new file mode 100644 index 0000000..f30c1dc --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_equip_turret.gsc @@ -0,0 +1,350 @@ +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_mgturret; +#include maps/mp/zombies/_zm_power; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_turret_zm" ) ) + { + return; + } + precachemodel( "p6_anim_zm_buildable_turret" ); + precacheturret( "zombie_bullet_crouch_zm" ); + level.turret_name = "equip_turret_zm"; + maps/mp/zombies/_zm_equipment::register_equipment( "equip_turret_zm", &"ZOMBIE_EQUIP_TURRET_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_TURRET_HOWTO", "turret_zm_icon", "turret", undefined, ::transferturret, ::dropturret, ::pickupturret, ::placeturret ); + maps/mp/zombies/_zm_equipment::add_placeable_equipment( "equip_turret_zm", "p6_anim_zm_buildable_turret" ); + level thread onplayerconnect(); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "equip_turret", &"ZOMBIE_EQUIP_TURRET_PICKUP_HINT_STRING" ); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread onplayerspawned(); + } +} + +onplayerspawned() +{ + self endon( "disconnect" ); + self thread setupwatchers(); + for ( ;; ) + { + self waittill( "spawned_player" ); + self thread watchturretuse(); + } +} + +setupwatchers() +{ + self waittill( "weapon_watchers_created" ); + watcher = maps/mp/gametypes_zm/_weaponobjects::getweaponobjectwatcher( "equip_turret" ); + watcher.onspawnretrievetriggers = ::maps/mp/zombies/_zm_equipment::equipment_onspawnretrievableweaponobject; +} + +watchturretuse() +{ + self notify( "watchTurretUse" ); + self endon( "watchTurretUse" ); + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_placed", weapon, weapname ); + if ( weapname == level.turret_name ) + { + self cleanupoldturret(); + self.buildableturret = weapon; + self thread startturretdeploy( weapon ); + } + } +} + +cleanupoldturret() +{ + if ( isDefined( self.buildableturret ) ) + { + if ( isDefined( self.buildableturret.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildableturret.stub ); + self.buildableturret.stub = undefined; + } + if ( isDefined( self.buildableturret.turret ) ) + { + if ( isDefined( self.buildableturret.turret.sound_ent ) ) + { + self.buildableturret.turret.sound_ent delete(); + } + self.buildableturret.turret delete(); + } + if ( isDefined( self.buildableturret.sound_ent ) ) + { + self.buildableturret.sound_ent delete(); + self.buildableturret.sound_ent = undefined; + } + self.buildableturret delete(); + self.turret_health = undefined; + } + else + { + if ( isDefined( self.turret ) ) + { + self.turret notify( "stop_burst_fire_unmanned" ); + self.turret delete(); + } + } + self.turret = undefined; + self notify( "turret_cleanup" ); +} + +watchforcleanup() +{ + self notify( "turret_cleanup" ); + self endon( "turret_cleanup" ); + self waittill_any( "death_or_disconnect", "equip_turret_zm_taken", "equip_turret_zm_pickup" ); + cleanupoldturret(); +} + +placeturret( origin, angles ) +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "p6_anim_zm_buildable_turret", "equip_turret_zm", origin, angles ); + if ( isDefined( item ) ) + { + item.owner = self; + } + return item; +} + +dropturret() +{ + item = self maps/mp/zombies/_zm_equipment::dropped_equipment_think( "p6_anim_zm_buildable_turret", "equip_turret_zm", self.origin, self.angles ); + if ( isDefined( item ) ) + { + item.turret_health = self.turret_health; + } + self.turret_health = undefined; + return item; +} + +pickupturret( item ) +{ + item.owner = self; + self.turret_health = item.turret_health; + item.turret_health = undefined; +} + +transferturret( fromplayer, toplayer ) +{ + buildableturret = toplayer.buildableturret; + turret = toplayer.turret; + toplayer.buildableturret = fromplayer.buildableturret; + toplayer.turret = fromplayer.turret; + fromplayer.buildableturret = buildableturret; + fromplayer.turret = turret; + toplayer.buildableturret.original_owner = toplayer; + toplayer notify( "equip_turret_zm_taken" ); + toplayer thread startturretdeploy( toplayer.buildableturret ); + fromplayer notify( "equip_turret_zm_taken" ); + if ( isDefined( fromplayer.buildableturret ) ) + { + fromplayer thread startturretdeploy( fromplayer.buildableturret ); + fromplayer.buildableturret.original_owner = fromplayer; + fromplayer.buildableturret.owner = fromplayer; + } + else + { + fromplayer maps/mp/zombies/_zm_equipment::equipment_release( "equip_turret_zm" ); + } + turret_health = toplayer.turret_health; + toplayer.turret_health = fromplayer.turret_health; + fromplayer.turret_health = turret_health; +} + +startturretdeploy( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turret_zm_taken" ); + self thread watchforcleanup(); + if ( !isDefined( self.turret_health ) ) + { + self.turret_health = 60; + } + if ( isDefined( weapon ) ) + { + weapon hide(); + wait 0,1; + if ( isDefined( weapon.power_on ) && weapon.power_on ) + { + weapon.turret notify( "stop_burst_fire_unmanned" ); + } + if ( !isDefined( weapon ) ) + { + return; + } + if ( isDefined( self.turret ) ) + { + self.turret notify( "stop_burst_fire_unmanned" ); + self.turret notify( "turret_deactivated" ); + self.turret delete(); + } + turret = spawnturret( "misc_turret", weapon.origin, "zombie_bullet_crouch_zm" ); + turret.turrettype = "sentry"; + turret setturrettype( turret.turrettype ); + turret setmodel( "p6_anim_zm_buildable_turret" ); + turret.origin = weapon.origin; + turret.angles = weapon.angles; + turret linkto( weapon ); + turret makeunusable(); + turret.owner = self; + turret setowner( turret.owner ); + turret maketurretunusable(); + turret setmode( "auto_nonai" ); + turret setdefaultdroppitch( 45 ); + turret setconvergencetime( 0,3 ); + turret setturretteam( self.team ); + turret.team = self.team; + turret.damage_own_team = 1; + turret.turret_active = 1; + weapon.turret = turret; + self.turret = turret; + if ( isDefined( level.equipment_turret_needs_power ) && level.equipment_turret_needs_power ) + { + weapon.power_on = 0; + maps/mp/zombies/_zm_power::add_temp_powered_item( ::turret_power_on, ::turret_power_off, ::turret_in_range, ::maps/mp/zombies/_zm_power::cost_high, 1, weapon.power_on, weapon ); + } + else + { + weapon.power_on = 1; + } + if ( weapon.power_on ) + { + turret thread maps/mp/zombies/_zm_mgturret::burst_fire_unmanned(); + } + else + { + self iprintlnbold( &"ZOMBIE_NEED_LOCAL_POWER" ); + } + if ( isDefined( level.equipment_turret_needs_power ) && !level.equipment_turret_needs_power ) + { + self thread turretdecay( weapon ); + } + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( weapon ); + while ( isDefined( weapon ) ) + { + if ( !is_true( weapon.power_on ) ) + { + if ( isDefined( self.buildableturret.sound_ent ) ) + { + self.buildableturret.sound_ent playsound( "wpn_zmb_turret_stop" ); + self.buildableturret.sound_ent delete(); + self.buildableturret.sound_ent = undefined; + } + } + wait 0,1; + } + if ( isDefined( self.buildableturret.sound_ent ) ) + { + self.buildableturret.sound_ent playsound( "wpn_zmb_turret_stop" ); + self.buildableturret.sound_ent delete(); + self.buildableturret.sound_ent = undefined; + } + if ( isDefined( turret ) ) + { + turret notify( "stop_burst_fire_unmanned" ); + turret notify( "turret_deactivated" ); + turret delete(); + } + self.turret = undefined; + self notify( "turret_cleanup" ); + } +} + +turret_in_range( delta, origin, radius ) +{ + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +turret_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: turret on\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 1; + self.target.turret thread maps/mp/zombies/_zm_mgturret::burst_fire_unmanned(); + player = self.target.turret.owner; + if ( !isDefined( player.buildableturret.sound_ent ) ) + { + player.buildableturret.sound_ent = spawn( "script_origin", self.target.turret.origin ); + } + player.buildableturret.sound_ent playsound( "wpn_zmb_turret_start" ); + player.buildableturret.sound_ent playloopsound( "wpn_zmb_turret_loop", 2 ); +} + +turret_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: turret off\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 0; + self.target.turret notify( "stop_burst_fire_unmanned" ); + player = self.target.turret.owner; + if ( isDefined( player.buildableturret.sound_ent ) ) + { + player.buildableturret.sound_ent playsound( "wpn_zmb_turret_stop" ); + player.buildableturret.sound_ent delete(); + player.buildableturret.sound_ent = undefined; + } +} + +turretdecay( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + while ( isDefined( weapon ) ) + { + if ( weapon.power_on ) + { + self.turret_health--; + + if ( self.turret_health <= 0 ) + { + self cleanupoldturret(); + self thread maps/mp/zombies/_zm_equipment::equipment_release( "equip_turret_zm" ); + return; + } + } + wait 1; + } +} + +debugturret( radius ) +{ +/# + while ( isDefined( self ) ) + { + circle( self.origin, radius, ( 1, 1, 1 ), 0, 1, 1 ); + wait 0,05; +#/ + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_game_module_grief.gsc b/zm_transit_patch/maps/mp/zombies/_zm_game_module_grief.gsc new file mode 100644 index 0000000..14a2eba --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_game_module_grief.gsc @@ -0,0 +1,11 @@ +#include maps/mp/zombies/_zm_game_module_utility; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; + +register_game_module() +{ + level.game_module_grief_index = 9; + maps/mp/zombies/_zm_game_module::register_game_module( level.game_module_grief_index, "zgrief", ::onpreinitgametype, ::onpostinitgametype, undefined, ::onspawnzombie, ::onstartgametype ); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_game_module_meat.gsc b/zm_transit_patch/maps/mp/zombies/_zm_game_module_meat.gsc new file mode 100644 index 0000000..e083fb3 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_game_module_meat.gsc @@ -0,0 +1,6 @@ +#include maps/mp/zombies/_zm_game_module_utility; +#include maps/mp/zombies/_zm_game_module_meat_utility; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; diff --git a/zm_transit_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc b/zm_transit_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc new file mode 100644 index 0000000..101f026 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc @@ -0,0 +1,685 @@ +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/gametypes_zm/zmeat; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_game_module_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +award_grenades_for_team( team ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ]._meat_team ) || players[ i ]._meat_team != team ) + { + i++; + continue; + } + else + { + lethal_grenade = players[ i ] get_player_lethal_grenade(); + players[ i ] giveweapon( lethal_grenade ); + players[ i ] setweaponammoclip( lethal_grenade, 4 ); + } + i++; + } +} + +get_players_on_meat_team( team ) +{ + players = get_players(); + players_on_team = []; + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ]._meat_team ) || players[ i ]._meat_team != team ) + { + i++; + continue; + } + else + { + players_on_team[ players_on_team.size ] = players[ i ]; + } + i++; + } + return players_on_team; +} + +get_alive_players_on_meat_team( team ) +{ + players = get_players(); + players_on_team = []; + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ]._meat_team ) || players[ i ]._meat_team != team ) + { + i++; + continue; + } + else + { + if ( players[ i ].sessionstate == "spectator" || players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + i++; + continue; + } + else + { + players_on_team[ players_on_team.size ] = players[ i ]; + } + } + i++; + } + return players_on_team; +} + +init_minigun_ring() +{ + if ( isDefined( level._minigun_ring ) ) + { + return; + } + ring_pos = getstruct( level._meat_location + "_meat_minigun", "script_noteworthy" ); + if ( !isDefined( ring_pos ) ) + { + return; + } + level._minigun_ring = spawn( "script_model", ring_pos.origin ); + level._minigun_ring.angles = ring_pos.angles; + level._minigun_ring setmodel( ring_pos.script_parameters ); + level._minigun_ring_clip = getent( level._meat_location + "_meat_minigun_clip", "script_noteworthy" ); + if ( isDefined( level._minigun_ring_clip ) ) + { + level._minigun_ring_clip linkto( level._minigun_ring ); + } + else + { + iprintlnbold( "BUG: no level._minigun_ring_clip" ); + } + level._minigun_ring_trig = getent( level._meat_location + "_meat_minigun_trig", "targetname" ); + if ( isDefined( level._minigun_ring_trig ) ) + { + level._minigun_ring_trig enablelinkto(); + level._minigun_ring_trig linkto( level._minigun_ring ); + level._minigun_icon = spawn( "script_model", level._minigun_ring_trig.origin ); + level._minigun_icon setmodel( getweaponmodel( "minigun_zm" ) ); + level._minigun_icon linkto( level._minigun_ring ); + level._minigun_icon setclientfield( "ring_glowfx", 1 ); + level thread ring_toss( level._minigun_ring_trig, "minigun" ); + } + else + { + iprintlnbold( "BUG: no level._minigun_ring_trig" ); + } + level._minigun_ring thread move_ring( ring_pos ); + level._minigun_ring thread rotate_ring( 1 ); +} + +init_ammo_ring() +{ + if ( isDefined( level._ammo_ring ) ) + { + return; + } + name = level._meat_location + "_meat_ammo"; + ring_pos = getstruct( name, "script_noteworthy" ); + if ( !isDefined( ring_pos ) ) + { + return; + } + level._ammo_ring = spawn( "script_model", ring_pos.origin ); + level._ammo_ring.angles = ring_pos.angles; + level._ammo_ring setmodel( ring_pos.script_parameters ); + name = level._meat_location + "_meat_ammo_clip"; + level._ammo_ring_clip = getent( name, "script_noteworthy" ); + if ( isDefined( level._ammo_ring_clip ) ) + { + level._ammo_ring_clip linkto( level._ammo_ring ); + } + else + { + iprintlnbold( "BUG: no level._ammo_ring_clip" ); + } + name = level._meat_location + "_meat_ammo_trig"; + level._ammo_ring_trig = getent( name, "targetname" ); + if ( isDefined( level._ammo_ring_clip ) ) + { + level._ammo_ring_trig enablelinkto(); + level._ammo_ring_trig linkto( level._ammo_ring ); + level._ammo_icon = spawn( "script_model", level._ammo_ring_trig.origin ); + level._ammo_icon setmodel( "zombie_ammocan" ); + level._ammo_icon linkto( level._ammo_ring ); + level._ammo_icon setclientfield( "ring_glowfx", 1 ); + level thread ring_toss( level._ammo_ring_trig, "ammo" ); + } + else + { + iprintlnbold( "BUG: no level._ammo_ring_trig" ); + } + level._ammo_ring thread move_ring( ring_pos ); + level._ammo_ring thread rotate_ring( 1 ); +} + +init_splitter_ring() +{ + if ( isDefined( level._splitter_ring ) ) + { + return; + } + ring_pos = getstruct( level._meat_location + "_meat_splitter", "script_noteworthy" ); + if ( !isDefined( ring_pos ) ) + { + return; + } + level._splitter_ring = spawn( "script_model", ring_pos.origin ); + level._splitter_ring.angles = ring_pos.angles; + level._splitter_ring setmodel( ring_pos.script_parameters ); + level._splitter_ring_trig1 = getent( level._meat_location + "_meat_splitter_trig_1", "targetname" ); + level._splitter_ring_trig2 = getent( level._meat_location + "_meat_splitter_trig_2", "targetname" ); + if ( isDefined( level._splitter_ring_trig1 ) && isDefined( level._splitter_ring_trig2 ) ) + { + level._splitter_ring_trig1 enablelinkto(); + level._splitter_ring_trig2 enablelinkto(); + } + else + { + iprintlnbold( "BUG: missing at least one level._splitter_ring_trig" ); + } + level._splitter_ring notsolid(); + level._meat_icon = spawn( "script_model", level._splitter_ring.origin ); + level._meat_icon setmodel( getweaponmodel( get_gamemode_var( "item_meat_name" ) ) ); + level._meat_icon linkto( level._splitter_ring ); + level._meat_icon setclientfield( "ring_glow_meatfx", 1 ); + if ( isDefined( level._splitter_ring_trig1 ) && isDefined( level._splitter_ring_trig2 ) ) + { + level._splitter_ring_trig1 linkto( level._splitter_ring ); + level._splitter_ring_trig2 linkto( level._splitter_ring ); + level thread ring_toss( level._splitter_ring_trig1, "splitter" ); + level thread ring_toss( level._splitter_ring_trig2, "splitter" ); + } + level._splitter_ring thread move_ring( ring_pos ); +} + +ring_toss( trig, type ) +{ + level endon( "end_game" ); + while ( 1 ) + { + while ( isDefined( level._ring_triggered ) && level._ring_triggered ) + { + wait 0,05; + } + if ( isDefined( level.item_meat ) && isDefined( level.item_meat.meat_is_moving ) && level.item_meat.meat_is_moving ) + { + if ( level.item_meat istouching( trig ) ) + { + level thread ring_toss_prize( type, trig ); + level._ring_triggered = 1; + level thread ring_cooldown(); + } + } + wait 0,05; + } +} + +ring_cooldown() +{ + wait 3; + level._ring_triggered = 0; +} + +ring_toss_prize( type, trig ) +{ + switch( type ) + { + case "splitter": + level thread meat_splitter( trig ); + break; + case "minigun": + level thread minigun_prize( trig ); + break; + case "ammo": + level thread ammo_prize( trig ); + break; + } +} + +meat_splitter( trig ) +{ + level endon( "meat_grabbed" ); + level endon( "meat_kicked" ); + while ( isDefined( level.item_meat ) && level.item_meat istouching( trig ) ) + { + wait 0,05; + } + exit_trig = getent( trig.target, "targetname" ); + exit_struct = getstruct( trig.target, "targetname" ); + while ( isDefined( level.item_meat ) && !level.item_meat istouching( exit_trig ) ) + { + wait 0,05; + } + while ( isDefined( level.item_meat ) && level.item_meat istouching( exit_trig ) ) + { + wait 0,05; + } + if ( !isDefined( level.item_meat ) ) + { + return; + } + playfx( level._effect[ "fw_burst" ], exit_trig.origin ); + flare_dir = vectornormalize( anglesToForward( exit_struct.angles ) ); + velocity = vectorScale( flare_dir, randomintrange( 400, 600 ) ); + velocity1 = ( velocity[ 0 ] + 75, velocity[ 1 ] + 75, randomintrange( 75, 125 ) ); + velocity2 = ( velocity[ 0 ] - 75, velocity[ 1 ] - 75, randomintrange( 75, 125 ) ); + velocity3 = ( velocity[ 0 ], velocity[ 1 ], 100 ); + level._fake_meats = []; + level._meat_splitter_activated = 1; + org = exit_trig.origin; + player = get_players()[ 0 ]; + player._spawning_meat = 1; + player endon( "disconnect" ); + thread split_meat( player, org, velocity1, velocity2, velocity ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_ring_splitter", undefined, undefined, 1 ); + wait 0,1; + while ( isDefined( level.splitting_meat ) && level.splitting_meat ) + { + wait 0,05; + } + player._spawning_meat = 0; +} + +split_meat( player, org, vel1, vel2, vel3 ) +{ + level.splitting_meat = 1; + level.item_meat cleanup_meat(); + wait_network_frame(); + level._fake_meats[ level._fake_meats.size ] = player magicgrenadetype( get_gamemode_var( "item_meat_name" ), org, vel1 ); + wait_network_frame(); + level._fake_meats[ level._fake_meats.size ] = player magicgrenadetype( get_gamemode_var( "item_meat_name" ), org, vel2 ); + wait_network_frame(); + level._fake_meats[ level._fake_meats.size ] = player magicgrenadetype( get_gamemode_var( "item_meat_name" ), org, vel3 ); + real_meat = random( level._fake_meats ); + _a330 = level._fake_meats; + _k330 = getFirstArrayKey( _a330 ); + while ( isDefined( _k330 ) ) + { + meat = _a330[ _k330 ]; + if ( real_meat != meat ) + { + meat._fake_meat = 1; + meat thread maps/mp/gametypes_zm/zmeat::delete_on_real_meat_pickup(); + } + else + { + meat._fake_meat = 0; + level.item_meat = meat; + } + _k330 = getNextArrayKey( _a330, _k330 ); + } + level.splitting_meat = 0; +} + +minigun_prize( trig ) +{ + while ( isDefined( level.item_meat ) && level.item_meat istouching( trig ) ) + { + wait 0,05; + } + if ( !isDefined( level.item_meat ) ) + { + return; + } + if ( isDefined( level._minigun_toss_cooldown ) && level._minigun_toss_cooldown ) + { + return; + } + level thread minigun_toss_cooldown(); + if ( !is_player_valid( level._last_person_to_throw_meat ) ) + { + return; + } + level._last_person_to_throw_meat thread maps/mp/zombies/_zm_powerups::powerup_vo( "minigun" ); + level thread maps/mp/zombies/_zm_powerups::minigun_weapon_powerup( level._last_person_to_throw_meat ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_ring_minigun", undefined, undefined, 1 ); +} + +ammo_prize( trig ) +{ + while ( isDefined( level.item_meat ) && level.item_meat istouching( trig ) ) + { + wait 0,05; + } + if ( !isDefined( level.item_meat ) ) + { + return; + } + if ( isDefined( level._ammo_toss_cooldown ) && level._ammo_toss_cooldown ) + { + return; + } + playfx( level._effect[ "poltergeist" ], trig.origin ); + level thread ammo_toss_cooldown(); + level._last_person_to_throw_meat thread maps/mp/zombies/_zm_powerups::powerup_vo( "full_ammo" ); + level thread maps/mp/zombies/_zm_powerups::full_ammo_powerup( undefined, level._last_person_to_throw_meat ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_ring_ammo", undefined, undefined, 1 ); +} + +minigun_toss_cooldown() +{ + level._minigun_toss_cooldown = 1; + if ( isDefined( level._minigun_icon ) ) + { + level._minigun_icon delete(); + } + waittill_any_or_timeout( 120, "meat_end" ); + playfx( level._effect[ "poltergeist" ], level._minigun_ring_trig.origin ); + level._minigun_icon = spawn( "script_model", level._minigun_ring_trig.origin ); + level._minigun_icon setmodel( getweaponmodel( "minigun_zm" ) ); + level._minigun_icon linkto( level._minigun_ring ); + level._minigun_icon setclientfield( "ring_glowfx", 1 ); + level._minigun_toss_cooldown = 0; +} + +ammo_toss_cooldown() +{ + level._ammo_toss_cooldown = 1; + if ( isDefined( level._ammo_icon ) ) + { + level._ammo_icon delete(); + } + waittill_any_or_timeout( 60, "meat_end" ); + playfx( level._effect[ "poltergeist" ], level._ammo_ring_trig.origin ); + level._ammo_icon = spawn( "script_model", level._ammo_ring_trig.origin ); + level._ammo_icon setmodel( "zombie_ammocan" ); + level._ammo_icon linkto( level._ammo_ring ); + level._ammo_icon setclientfield( "ring_glowfx", 1 ); + level._ammo_toss_cooldown = 0; +} + +wait_for_team_death( team ) +{ + level endon( "meat_end" ); + encounters_team = undefined; + while ( 1 ) + { + wait 1; + while ( isDefined( level._checking_for_save ) && level._checking_for_save ) + { + wait 0,1; + } + alive_team_players = get_alive_players_on_meat_team( team ); + while ( alive_team_players.size > 0 ) + { + encounters_team = alive_team_players[ 0 ]._encounters_team; + } + } + if ( !isDefined( encounters_team ) ) + { + return; + } + winning_team = "A"; + if ( encounters_team == "A" ) + { + winning_team = "B"; + } + level notify( "meat_end" ); +} + +check_should_save_player( team ) +{ + if ( !isDefined( level._meat_on_team ) ) + { + return 0; + } + level._checking_for_save = 1; + players = get_players_on_meat_team( team ); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( isDefined( level._last_person_to_throw_meat ) && level._last_person_to_throw_meat == player ) + { + while ( isDefined( level.item_meat.meat_is_moving ) && !level.item_meat.meat_is_moving && isDefined( level._meat_splitter_activated ) || level._meat_splitter_activated && isDefined( level.item_meat.meat_is_flying ) && level.item_meat.meat_is_flying ) + { + if ( level._meat_on_team != player._meat_team ) + { + break; + } + else if ( isDefined( level.item_meat.meat_is_rolling ) && level.item_meat.meat_is_rolling && level._meat_on_team == player._meat_team ) + { + break; + } + else + { + wait 0,05; + } + } + if ( !isDefined( player ) ) + { + level._checking_for_save = 0; + return 0; + } + if ( isDefined( player.last_damage_from_zombie_or_player ) && !player.last_damage_from_zombie_or_player ) + { + level._checking_for_save = 0; + return 0; + } + if ( level._meat_on_team != player._meat_team && isDefined( level._last_person_to_throw_meat ) && level._last_person_to_throw_meat == player ) + { + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + level thread revive_saved_player( player ); + return 1; + } + } + } + i++; + } + level._checking_for_save = 0; + return 0; +} + +watch_save_player() +{ + if ( !isDefined( level._meat_on_team ) ) + { + return 0; + } + if ( !isDefined( level._last_person_to_throw_meat ) || level._last_person_to_throw_meat != self ) + { + return 0; + } + level._checking_for_save = 1; + while ( isDefined( level.splitting_meat ) || level.splitting_meat && isDefined( level.item_meat ) && isDefined( level.item_meat.meat_is_moving ) || level.item_meat.meat_is_moving && isDefined( level.item_meat.meat_is_flying ) && level.item_meat.meat_is_flying ) + { + if ( level._meat_on_team != self._meat_team ) + { + } + else if ( isDefined( level.item_meat ) && isDefined( level.item_meat.meat_is_rolling ) && level.item_meat.meat_is_rolling && level._meat_on_team == self._meat_team ) + { + } + else + { + wait 0,05; + } + } + if ( level._meat_on_team != self._meat_team && isDefined( level._last_person_to_throw_meat ) && level._last_person_to_throw_meat == self ) + { + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + level thread revive_saved_player( self ); + return 1; + } + } + level._checking_for_save = 0; + return 0; +} + +revive_saved_player( player ) +{ + player endon( "disconnect" ); + player iprintlnbold( &"ZOMBIE_PLAYER_SAVED" ); + player playsound( level.zmb_laugh_alias ); + wait 0,25; + playfx( level._effect[ "poltergeist" ], player.origin ); + playsoundatposition( "zmb_bolt", player.origin ); + earthquake( 0,5, 0,75, player.origin, 1000 ); + player thread maps/mp/zombies/_zm_laststand::auto_revive( player ); + player._saved_by_throw++; + level._checking_for_save = 0; +} + +get_game_module_players( player ) +{ + return get_players_on_meat_team( player._meat_team ); +} + +item_meat_spawn( origin ) +{ + org = origin; + player = get_players()[ 0 ]; + player._spawning_meat = 1; + player magicgrenadetype( get_gamemode_var( "item_meat_name" ), org, ( 0, 0, 1 ) ); + playsoundatposition( "zmb_spawn_powerup", org ); + wait 0,1; + player._spawning_meat = undefined; +} + +init_item_meat( gametype ) +{ + if ( gametype == "zgrief" ) + { + set_gamemode_var_once( "item_meat_name", "item_meat_zm" ); + set_gamemode_var_once( "item_meat_model", "t6_wpn_zmb_meat_world" ); + } + else + { + set_gamemode_var_once( "item_meat_name", "item_head_zm" ); + set_gamemode_var_once( "item_meat_model", "t6_wpn_zmb_severedhead_world" ); + } + precacheitem( get_gamemode_var( "item_meat_name" ) ); + set_gamemode_var_once( "start_item_meat_name", get_gamemode_var( "item_meat_name" ) ); + level.meat_weaponidx = getweaponindexfromname( get_gamemode_var( "item_meat_name" ) ); + level.meat_pickupsound = getweaponpickupsound( level.meat_weaponidx ); + level.meat_pickupsoundplayer = getweaponpickupsoundplayer( level.meat_weaponidx ); +} + +meat_intro( launch_spot ) +{ + flag_wait( "start_encounters_match_logic" ); + wait 3; + level thread multi_launch( launch_spot ); + launch_meat( launch_spot ); + drop_meat( level._meat_start_point ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "meat_drop", undefined, undefined, 1 ); +} + +launch_meat( launch_spot ) +{ + level waittill( "launch_meat" ); + spots = getstructarray( launch_spot, "targetname" ); + if ( isDefined( spots ) && spots.size > 0 ) + { + spot = random( spots ); + meat = spawn( "script_model", spot.origin ); + meat setmodel( "tag_origin" ); + wait_network_frame(); + playfxontag( level._effect[ "fw_trail" ], meat, "tag_origin" ); + meat playloopsound( "zmb_souls_loop", 0,75 ); + dest = spot; + while ( isDefined( dest ) && isDefined( dest.target ) ) + { + new_dest = getstruct( dest.target, "targetname" ); + dest = new_dest; + dist = distance( new_dest.origin, meat.origin ); + time = dist / 700; + meat moveto( new_dest.origin, time ); + meat waittill( "movedone" ); + } + meat playsound( "zmb_souls_end" ); + playfx( level._effect[ "fw_burst" ], meat.origin ); + wait randomfloatrange( 0,2, 0,5 ); + meat playsound( "zmb_souls_end" ); + playfx( level._effect[ "fw_burst" ], meat.origin + ( randomintrange( 50, 150 ), randomintrange( 50, 150 ), randomintrange( -20, 20 ) ) ); + wait randomfloatrange( 0,5, 0,75 ); + meat playsound( "zmb_souls_end" ); + playfx( level._effect[ "fw_burst" ], meat.origin + ( randomintrange( -150, -50 ), randomintrange( -150, 50 ), randomintrange( -20, 20 ) ) ); + wait randomfloatrange( 0,5, 0,75 ); + meat playsound( "zmb_souls_end" ); + playfx( level._effect[ "fw_burst" ], meat.origin ); + meat delete(); + } +} + +multi_launch( launch_spot ) +{ + spots = getstructarray( launch_spot, "targetname" ); + if ( isDefined( spots ) && spots.size > 0 ) + { + x = 0; + while ( x < 3 ) + { + i = 0; + while ( i < spots.size ) + { + delay = randomfloatrange( 0,1, 0,25 ); + level thread fake_launch( spots[ i ], delay ); + i++; + } + wait randomfloatrange( 0,25, 0,75 ); + if ( x > 1 ) + { + level notify( "launch_meat" ); + } + x++; + } + } + else wait randomfloatrange( 0,25, 0,75 ); + level notify( "launch_meat" ); +} + +fake_launch( launch_spot, delay ) +{ + wait delay; + wait randomfloatrange( 0,1, 4 ); + meat = spawn( "script_model", launch_spot.origin + ( randomintrange( -60, 60 ), randomintrange( -60, 60 ), 0 ) ); + meat setmodel( "tag_origin" ); + wait_network_frame(); + playfxontag( level._effect[ "fw_trail_cheap" ], meat, "tag_origin" ); + meat playloopsound( "zmb_souls_loop", 0,75 ); + dest = launch_spot; + while ( isDefined( dest ) && isDefined( dest.target ) ) + { + random_offset = ( randomintrange( -60, 60 ), randomintrange( -60, 60 ), 0 ); + new_dest = getstruct( dest.target, "targetname" ); + dest = new_dest; + dist = distance( new_dest.origin + random_offset, meat.origin ); + time = dist / 700; + meat moveto( new_dest.origin + random_offset, time ); + meat waittill( "movedone" ); + } + meat playsound( "zmb_souls_end" ); + playfx( level._effect[ "fw_pre_burst" ], meat.origin ); + meat delete(); +} + +drop_meat( drop_spot ) +{ + meat = spawn( "script_model", drop_spot + vectorScale( ( 0, 0, 1 ), 600 ) ); + meat setmodel( "tag_origin" ); + dist = distance( meat.origin, drop_spot ); + time = dist / 400; + wait 2; + meat moveto( drop_spot, time ); + wait_network_frame(); + playfxontag( level._effect[ "fw_drop" ], meat, "tag_origin" ); + meat waittill( "movedone" ); + playfx( level._effect[ "fw_impact" ], drop_spot ); + level notify( "reset_meat" ); + meat delete(); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_game_module_standard.gsc b/zm_transit_patch/maps/mp/zombies/_zm_game_module_standard.gsc new file mode 100644 index 0000000..e69de29 diff --git a/zm_transit_patch/maps/mp/zombies/_zm_game_module_utility.gsc b/zm_transit_patch/maps/mp/zombies/_zm_game_module_utility.gsc new file mode 100644 index 0000000..7c90b48 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_game_module_utility.gsc @@ -0,0 +1,46 @@ +#include maps/mp/zombies/_zm_game_module_meat; +#include maps/mp/zombies/_zm_game_module_meat_utility; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; + +init_item_meat() +{ + level.item_meat_name = "item_meat_zm"; + precacheitem( level.item_meat_name ); +} + +move_ring( ring ) +{ + positions = getstructarray( ring.target, "targetname" ); + positions = array_randomize( positions ); + level endon( "end_game" ); + while ( 1 ) + { + _a23 = positions; + _k23 = getFirstArrayKey( _a23 ); + while ( isDefined( _k23 ) ) + { + position = _a23[ _k23 ]; + self moveto( position.origin, randomintrange( 30, 45 ) ); + self waittill( "movedone" ); + _k23 = getNextArrayKey( _a23, _k23 ); + } + } +} + +rotate_ring( forward ) +{ + level endon( "end_game" ); + dir = -360; + if ( forward ) + { + dir = 360; + } + while ( 1 ) + { + self rotateyaw( dir, 9 ); + wait 9; + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_melee_weapon.gsc b/zm_transit_patch/maps/mp/zombies/_zm_melee_weapon.gsc new file mode 100644 index 0000000..ed494ee --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_melee_weapon.gsc @@ -0,0 +1,627 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init( weapon_name, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, cost, wallbuy_targetname, hint_string, vo_dialog_id, flourish_fn ) +{ + precacheitem( weapon_name ); + precacheitem( flourish_weapon_name ); + add_melee_weapon( weapon_name, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, cost, wallbuy_targetname, hint_string, vo_dialog_id, flourish_fn ); + melee_weapon_triggers = getentarray( wallbuy_targetname, "targetname" ); + i = 0; + while ( i < melee_weapon_triggers.size ) + { + knife_model = getent( melee_weapon_triggers[ i ].target, "targetname" ); + if ( isDefined( knife_model ) ) + { + knife_model hide(); + } + melee_weapon_triggers[ i ] thread melee_weapon_think( weapon_name, cost, flourish_fn, vo_dialog_id, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name ); + if ( isDefined( level.monolingustic_prompt_format ) && !level.monolingustic_prompt_format ) + { + melee_weapon_triggers[ i ] sethintstring( hint_string, cost ); + if ( getDvarInt( #"1F0A2129" ) && isDefined( level.disable_melee_wallbuy_icons ) && !level.disable_melee_wallbuy_icons ) + { + cursor_hint = "HINT_WEAPON"; + cursor_hint_weapon = weapon_name; + melee_weapon_triggers[ i ] setcursorhint( cursor_hint, cursor_hint_weapon ); + } + else + { + melee_weapon_triggers[ i ] setcursorhint( "HINT_NOICON" ); + } + } + else + { + weapon_display = get_weapon_display_name( weapon_name ); + hint_string = &"ZOMBIE_WEAPONCOSTONLY"; + melee_weapon_triggers[ i ] sethintstring( hint_string, weapon_display, cost ); + if ( getDvarInt( #"1F0A2129" ) && isDefined( level.disable_melee_wallbuy_icons ) && !level.disable_melee_wallbuy_icons ) + { + cursor_hint = "HINT_WEAPON"; + cursor_hint_weapon = weapon_name; + melee_weapon_triggers[ i ] setcursorhint( cursor_hint, cursor_hint_weapon ); + break; + } + else + { + melee_weapon_triggers[ i ] setcursorhint( "HINT_NOICON" ); + } + } + melee_weapon_triggers[ i ] usetriggerrequirelookat(); + i++; + } + melee_weapon_structs = getstructarray( wallbuy_targetname, "targetname" ); + i = 0; + while ( i < melee_weapon_structs.size ) + { + prepare_stub( melee_weapon_structs[ i ].trigger_stub, weapon_name, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, cost, wallbuy_targetname, hint_string, vo_dialog_id, flourish_fn ); + i++; + } + register_melee_weapon_for_level( weapon_name ); + if ( !isDefined( level.ballistic_weapon_name ) ) + { + level.ballistic_weapon_name = []; + } + level.ballistic_weapon_name[ weapon_name ] = ballistic_weapon_name; + if ( !isDefined( level.ballistic_upgraded_weapon_name ) ) + { + level.ballistic_upgraded_weapon_name = []; + } + level.ballistic_upgraded_weapon_name[ weapon_name ] = ballistic_upgraded_weapon_name; +/# + if ( !isDefined( level.zombie_weapons[ weapon_name ] ) ) + { + if ( isDefined( level.devgui_add_weapon ) ) + { + [[ level.devgui_add_weapon ]]( weapon_name, "", weapon_name, cost ); +#/ + } + } +} + +prepare_stub( stub, weapon_name, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, cost, wallbuy_targetname, hint_string, vo_dialog_id, flourish_fn ) +{ + if ( isDefined( stub ) ) + { + if ( isDefined( level.monolingustic_prompt_format ) && !level.monolingustic_prompt_format ) + { + stub.hint_string = hint_string; + if ( getDvarInt( #"1F0A2129" ) && isDefined( level.disable_melee_wallbuy_icons ) && !level.disable_melee_wallbuy_icons ) + { + stub.cursor_hint = "HINT_WEAPON"; + stub.cursor_hint_weapon = weapon_name; + } + else + { + stub.cursor_hint = "HINT_NOICON"; + stub.cursor_hint_weapon = undefined; + } + } + else + { + stub.hint_parm1 = get_weapon_display_name( weapon_name ); + stub.hint_parm2 = cost; + stub.hint_string = &"ZOMBIE_WEAPONCOSTONLY"; + if ( getDvarInt( #"1F0A2129" ) && isDefined( level.disable_melee_wallbuy_icons ) && !level.disable_melee_wallbuy_icons ) + { + stub.cursor_hint = "HINT_WEAPON"; + stub.cursor_hint_weapon = weapon_name; + } + else + { + stub.cursor_hint = "HINT_NOICON"; + stub.cursor_hint_weapon = undefined; + } + } + stub.cost = cost; + stub.weapon_name = weapon_name; + stub.vo_dialog_id = vo_dialog_id; + stub.flourish_weapon_name = flourish_weapon_name; + stub.ballistic_weapon_name = ballistic_weapon_name; + stub.ballistic_upgraded_weapon_name = ballistic_upgraded_weapon_name; + stub.trigger_func = ::melee_weapon_think; + stub.flourish_fn = flourish_fn; + } +} + +add_stub( stub, weapon_name ) +{ + melee_weapon = undefined; + i = 0; + while ( i < level._melee_weapons.size ) + { + if ( level._melee_weapons[ i ].weapon_name == weapon_name ) + { + melee_weapon = level._melee_weapons[ i ]; + break; + } + else + { + i++; + } + } + if ( isDefined( stub ) && isDefined( melee_weapon ) ) + { + prepare_stub( stub, melee_weapon.weapon_name, melee_weapon.flourish_weapon_name, melee_weapon.ballistic_weapon_name, melee_weapon.ballistic_upgraded_weapon_name, melee_weapon.cost, melee_weapon.wallbuy_targetname, melee_weapon.hint_string, melee_weapon.vo_dialog_id, melee_weapon.flourish_fn ); + } +} + +give_melee_weapon_by_name( weapon_name ) +{ + melee_weapon = undefined; + i = 0; + while ( i < level._melee_weapons.size ) + { + if ( level._melee_weapons[ i ].weapon_name == weapon_name ) + { + melee_weapon = level._melee_weapons[ i ]; + break; + } + else + { + i++; + } + } + if ( isDefined( melee_weapon ) ) + { + self thread give_melee_weapon( melee_weapon.vo_dialog_id, melee_weapon.flourish_weapon_name, melee_weapon.weapon_name, melee_weapon.ballistic_weapon_name, melee_weapon.ballistic_upgraded_weapon_name, melee_weapon.flourish_fn, undefined ); + } +} + +add_melee_weapon( weapon_name, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, cost, wallbuy_targetname, hint_string, vo_dialog_id, flourish_fn ) +{ + melee_weapon = spawnstruct(); + melee_weapon.weapon_name = weapon_name; + melee_weapon.flourish_weapon_name = flourish_weapon_name; + melee_weapon.ballistic_weapon_name = ballistic_weapon_name; + melee_weapon.ballistic_upgraded_weapon_name = ballistic_upgraded_weapon_name; + melee_weapon.cost = cost; + melee_weapon.wallbuy_targetname = wallbuy_targetname; + melee_weapon.hint_string = hint_string; + melee_weapon.vo_dialog_id = vo_dialog_id; + melee_weapon.flourish_fn = flourish_fn; + if ( !isDefined( level._melee_weapons ) ) + { + level._melee_weapons = []; + } + level._melee_weapons[ level._melee_weapons.size ] = melee_weapon; +} + +player_can_see_weapon_prompt( weapon_name ) +{ + if ( is_true( level._allow_melee_weapon_switching ) ) + { + return 1; + } + if ( isDefined( self get_player_melee_weapon() ) && self hasweapon( self get_player_melee_weapon() ) ) + { + return 0; + } + return 1; +} + +spectator_respawn_all() +{ + i = 0; + while ( i < level._melee_weapons.size ) + { + self spectator_respawn( level._melee_weapons[ i ].wallbuy_targetname, level._melee_weapons[ i ].weapon_name ); + i++; + } +} + +spectator_respawn( wallbuy_targetname, weapon_name ) +{ + melee_triggers = getentarray( wallbuy_targetname, "targetname" ); + players = get_players(); + i = 0; + while ( i < melee_triggers.size ) + { + melee_triggers[ i ] setvisibletoall(); + while ( isDefined( level._allow_melee_weapon_switching ) && !level._allow_melee_weapon_switching ) + { + j = 0; + while ( j < players.size ) + { + if ( !players[ j ] player_can_see_weapon_prompt( weapon_name ) ) + { + melee_triggers[ i ] setinvisibletoplayer( players[ j ] ); + } + j++; + } + } + i++; + } +} + +trigger_hide_all() +{ + i = 0; + while ( i < level._melee_weapons.size ) + { + self trigger_hide( level._melee_weapons[ i ].wallbuy_targetname ); + i++; + } +} + +trigger_hide( wallbuy_targetname ) +{ + melee_triggers = getentarray( wallbuy_targetname, "targetname" ); + i = 0; + while ( i < melee_triggers.size ) + { + melee_triggers[ i ] setinvisibletoplayer( self ); + i++; + } +} + +has_any_ballistic_knife() +{ + if ( self hasweapon( "knife_ballistic_zm" ) ) + { + return 1; + } + if ( self hasweapon( "knife_ballistic_upgraded_zm" ) ) + { + return 1; + } + i = 0; + while ( i < level._melee_weapons.size ) + { + if ( self hasweapon( level._melee_weapons[ i ].ballistic_weapon_name ) ) + { + return 1; + } + if ( self hasweapon( level._melee_weapons[ i ].ballistic_upgraded_weapon_name ) ) + { + return 1; + } + i++; + } + return 0; +} + +has_upgraded_ballistic_knife() +{ + if ( self hasweapon( "knife_ballistic_upgraded_zm" ) ) + { + return 1; + } + i = 0; + while ( i < level._melee_weapons.size ) + { + if ( self hasweapon( level._melee_weapons[ i ].ballistic_upgraded_weapon_name ) ) + { + return 1; + } + i++; + } + return 0; +} + +give_ballistic_knife( weapon_string, upgraded ) +{ + current_melee_weapon = self get_player_melee_weapon(); + if ( isDefined( current_melee_weapon ) ) + { + if ( upgraded && isDefined( level.ballistic_upgraded_weapon_name ) && isDefined( level.ballistic_upgraded_weapon_name[ current_melee_weapon ] ) ) + { + weapon_string = level.ballistic_upgraded_weapon_name[ current_melee_weapon ]; + } + if ( !upgraded && isDefined( level.ballistic_weapon_name ) && isDefined( level.ballistic_weapon_name[ current_melee_weapon ] ) ) + { + weapon_string = level.ballistic_weapon_name[ current_melee_weapon ]; + } + } + return weapon_string; +} + +change_melee_weapon( weapon_name, current_weapon ) +{ + current_melee_weapon = self get_player_melee_weapon(); + if ( isDefined( current_melee_weapon ) && current_melee_weapon != weapon_name ) + { + self takeweapon( current_melee_weapon ); + unacquire_weapon_toggle( current_melee_weapon ); + } + self set_player_melee_weapon( weapon_name ); + had_ballistic = 0; + had_ballistic_upgraded = 0; + ballistic_was_primary = 0; + primaryweapons = self getweaponslistprimaries(); + i = 0; + while ( i < primaryweapons.size ) + { + primary_weapon = primaryweapons[ i ]; + if ( issubstr( primary_weapon, "knife_ballistic_" ) ) + { + had_ballistic = 1; + if ( primary_weapon == current_weapon ) + { + ballistic_was_primary = 1; + } + self notify( "zmb_lost_knife" ); + self takeweapon( primary_weapon ); + unacquire_weapon_toggle( primary_weapon ); + if ( issubstr( primary_weapon, "upgraded" ) ) + { + had_ballistic_upgraded = 1; + } + } + i++; + } + if ( had_ballistic ) + { + if ( had_ballistic_upgraded ) + { + new_ballistic = level.ballistic_upgraded_weapon_name[ weapon_name ]; + if ( ballistic_was_primary ) + { + current_weapon = new_ballistic; + } + self giveweapon( new_ballistic, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( new_ballistic ) ); + } + else + { + new_ballistic = level.ballistic_weapon_name[ weapon_name ]; + if ( ballistic_was_primary ) + { + current_weapon = new_ballistic; + } + self giveweapon( new_ballistic, 0 ); + } + } + return current_weapon; +} + +melee_weapon_think( weapon_name, cost, flourish_fn, vo_dialog_id, flourish_weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name ) +{ + self.first_time_triggered = 0; + while ( isDefined( self.stub ) ) + { + self endon( "kill_trigger" ); + if ( isDefined( self.stub.first_time_triggered ) ) + { + self.first_time_triggered = self.stub.first_time_triggered; + } + weapon_name = self.stub.weapon_name; + cost = self.stub.cost; + flourish_fn = self.stub.flourish_fn; + vo_dialog_id = self.stub.vo_dialog_id; + flourish_weapon_name = self.stub.flourish_weapon_name; + ballistic_weapon_name = self.stub.ballistic_weapon_name; + ballistic_upgraded_weapon_name = self.stub.ballistic_upgraded_weapon_name; + players = getplayers(); + while ( isDefined( level._allow_melee_weapon_switching ) && !level._allow_melee_weapon_switching ) + { + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] player_can_see_weapon_prompt( weapon_name ) ) + { + self setinvisibletoplayer( players[ i ] ); + } + i++; + } + } + } + for ( ;; ) + { + self waittill( "trigger", player ); + if ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + continue; + } + else if ( player in_revive_trigger() ) + { + wait 0,1; + continue; + } + else if ( player isthrowinggrenade() ) + { + wait 0,1; + continue; + } + else if ( player.is_drinking > 0 ) + { + wait 0,1; + continue; + } + else if ( player hasweapon( weapon_name ) || player has_powerup_weapon() ) + { + wait 0,1; + continue; + } + else + { + if ( player isswitchingweapons() ) + { + wait 0,1; + break; + } + else current_weapon = player getcurrentweapon(); + if ( !is_placeable_mine( current_weapon ) || is_equipment( current_weapon ) && player has_powerup_weapon() ) + { + wait 0,1; + break; + } + else + { + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( player.intermission ) && player.intermission ) + { + wait 0,1; + break; + } + else + { + player_has_weapon = player hasweapon( weapon_name ); + if ( !player_has_weapon ) + { + cost = self.stub.cost; + if ( player maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + cost = int( cost / 2 ); + } + if ( player.score >= cost ) + { + if ( self.first_time_triggered == 0 ) + { + model = getent( self.target, "targetname" ); + if ( isDefined( model ) ) + { + model thread melee_weapon_show( player ); + } + else + { + if ( isDefined( self.clientfieldname ) ) + { + level setclientfield( self.clientfieldname, 1 ); + } + } + self.first_time_triggered = 1; + if ( isDefined( self.stub ) ) + { + self.stub.first_time_triggered = 1; + } + } + player maps/mp/zombies/_zm_score::minus_to_player_score( cost, 1 ); + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %s", player.name, player.score, level.round_number, cost, weapon_name, self.origin, "weapon" ); + player thread give_melee_weapon( vo_dialog_id, flourish_weapon_name, weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, flourish_fn, self ); + } + else + { + play_sound_on_ent( "no_purchase" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "no_money_weapon", undefined, 1 ); + } + break; + } + else + { + if ( isDefined( level._allow_melee_weapon_switching ) && !level._allow_melee_weapon_switching ) + { + self setinvisibletoplayer( player ); + } + } + } + } + } + } +} + +melee_weapon_show( player ) +{ + player_angles = vectorToAngle( player.origin - self.origin ); + player_yaw = player_angles[ 1 ]; + weapon_yaw = self.angles[ 1 ]; + yaw_diff = angleClamp180( player_yaw - weapon_yaw ); + if ( yaw_diff > 0 ) + { + yaw = weapon_yaw - 90; + } + else + { + yaw = weapon_yaw + 90; + } + self.og_origin = self.origin; + self.origin += anglesToForward( ( 0, yaw, 0 ) ) * 8; + wait 0,05; + self show(); + play_sound_at_pos( "weapon_show", self.origin, self ); + time = 1; + self moveto( self.og_origin, time ); +} + +give_melee_weapon( vo_dialog_id, flourish_weapon_name, weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name, flourish_fn, trigger ) +{ + if ( isDefined( flourish_fn ) ) + { + self thread [[ flourish_fn ]](); + } + gun = self do_melee_weapon_flourish_begin( flourish_weapon_name ); + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", vo_dialog_id ); + self waittill_any( "fake_death", "death", "player_downed", "weapon_change_complete" ); + self do_melee_weapon_flourish_end( gun, flourish_weapon_name, weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name ); + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( self.intermission ) && self.intermission ) + { + return; + } + if ( isDefined( level._allow_melee_weapon_switching ) && !level._allow_melee_weapon_switching ) + { + if ( isDefined( trigger ) ) + { + trigger setinvisibletoplayer( self ); + } + self trigger_hide_all(); + } +} + +do_melee_weapon_flourish_begin( flourish_weapon_name ) +{ + self increment_is_drinking(); + self disable_player_move_states( 1 ); + gun = self getcurrentweapon(); + weapon = flourish_weapon_name; + self giveweapon( weapon ); + self switchtoweapon( weapon ); + return gun; +} + +do_melee_weapon_flourish_end( gun, flourish_weapon_name, weapon_name, ballistic_weapon_name, ballistic_upgraded_weapon_name ) +{ +/# + assert( !is_zombie_perk_bottle( gun ) ); +#/ +/# + assert( gun != level.revive_tool ); +#/ + self enable_player_move_states(); + weapon = flourish_weapon_name; + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( self.intermission ) && self.intermission ) + { + self takeweapon( weapon ); + self.lastactiveweapon = "none"; + return; + } + self takeweapon( weapon ); + self giveweapon( weapon_name ); + gun = change_melee_weapon( weapon_name, gun ); + if ( self hasweapon( "knife_zm" ) ) + { + self takeweapon( "knife_zm" ); + } + if ( self is_multiple_drinking() ) + { + self decrement_is_drinking(); + return; + } + else if ( gun == "knife_zm" ) + { + self switchtoweapon( weapon_name ); + self decrement_is_drinking(); + return; + } + else if ( gun != "none" && !is_placeable_mine( gun ) && !is_equipment( gun ) ) + { + self switchtoweapon( gun ); + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } + self waittill( "weapon_change_complete" ); + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( self.intermission ) && !self.intermission ) + { + self decrement_is_drinking(); + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_riotshield.gsc b/zm_transit_patch/maps/mp/zombies/_zm_riotshield.gsc new file mode 100644 index 0000000..a9a1d07 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_riotshield.gsc @@ -0,0 +1,665 @@ +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_weap_riotshield; +#include common_scripts/utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; + +init() +{ + level.riotshield_name = "riotshield_zm"; + level.deployedshieldmodel = []; + level.stowedshieldmodel = []; + level.carriedshieldmodel = []; + level.deployedshieldmodel[ 0 ] = "t6_wpn_zmb_shield_world"; + level.deployedshieldmodel[ 2 ] = "t6_wpn_zmb_shield_dmg1_world"; + level.deployedshieldmodel[ 3 ] = "t6_wpn_zmb_shield_dmg2_world"; + level.stowedshieldmodel[ 0 ] = "t6_wpn_zmb_shield_stow"; + level.stowedshieldmodel[ 2 ] = "t6_wpn_zmb_shield_dmg1_stow"; + level.stowedshieldmodel[ 3 ] = "t6_wpn_zmb_shield_dmg2_stow"; + level.carriedshieldmodel[ 0 ] = "t6_wpn_zmb_shield_world"; + level.carriedshieldmodel[ 2 ] = "t6_wpn_zmb_shield_dmg1_world"; + level.carriedshieldmodel[ 3 ] = "t6_wpn_zmb_shield_dmg2_world"; + level.viewshieldmodel[ 0 ] = "t6_wpn_zmb_shield_view"; + level.viewshieldmodel[ 2 ] = "t6_wpn_zmb_shield_dmg1_view"; + level.viewshieldmodel[ 3 ] = "t6_wpn_zmb_shield_dmg2_view"; + precachemodel( level.stowedshieldmodel[ 0 ] ); + precachemodel( level.stowedshieldmodel[ 2 ] ); + precachemodel( level.stowedshieldmodel[ 3 ] ); + precachemodel( level.carriedshieldmodel[ 0 ] ); + precachemodel( level.carriedshieldmodel[ 2 ] ); + precachemodel( level.carriedshieldmodel[ 3 ] ); + precachemodel( level.viewshieldmodel[ 0 ] ); + precachemodel( level.viewshieldmodel[ 2 ] ); + precachemodel( level.viewshieldmodel[ 3 ] ); + level.riotshield_placement_zoffset = 26; +} + +attachriotshield( model, tag ) +{ + if ( isDefined( self.prev_shield_model ) && isDefined( self.prev_shield_tag ) ) + { + self detachshieldmodel( self.prev_shield_model, self.prev_shield_tag ); + } + self.prev_shield_model = model; + self.prev_shield_tag = tag; + if ( isDefined( self.prev_shield_model ) && isDefined( self.prev_shield_tag ) ) + { + self attachshieldmodel( self.prev_shield_model, self.prev_shield_tag ); + } +} + +removeriotshield() +{ + if ( isDefined( self.prev_shield_model ) && isDefined( self.prev_shield_tag ) ) + { + self detachshieldmodel( self.prev_shield_model, self.prev_shield_tag ); + } + self.prev_shield_model = undefined; + self.prev_shield_tag = undefined; + if ( self getcurrentweapon() != level.riotshield_name ) + { + return; + } + self setheldweaponmodel( 0 ); +} + +setriotshieldviewmodel( modelnum ) +{ + self.prev_shield_viewmodel = modelnum; + if ( self getcurrentweapon() != level.riotshield_name ) + { + return; + } + if ( isDefined( self.prev_shield_viewmodel ) ) + { + self setheldweaponmodel( self.prev_shield_viewmodel ); + } + else + { + self setheldweaponmodel( 0 ); + } +} + +specialriotshieldviewmodel() +{ + if ( self getcurrentweapon() != level.riotshield_name ) + { + return; + } + self setheldweaponmodel( 3 ); +} + +restoreriotshieldviewmodel() +{ + if ( self getcurrentweapon() != level.riotshield_name ) + { + return; + } + if ( isDefined( self.prev_shield_viewmodel ) ) + { + self setheldweaponmodel( self.prev_shield_viewmodel ); + } + else + { + self setheldweaponmodel( 0 ); + } +} + +updateriotshieldmodel() +{ + if ( !isDefined( self.shield_damage_level ) ) + { + if ( isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + } + update = 0; + if ( !isDefined( self.prev_shield_damage_level ) || self.prev_shield_damage_level != self.shield_damage_level ) + { + self.prev_shield_damage_level = self.shield_damage_level; + update = 1; + } + if ( !isDefined( self.prev_shield_placement ) || self.prev_shield_placement != self.shield_placement ) + { + self.prev_shield_placement = self.shield_placement; + update = 1; + } + if ( update ) + { + if ( self.prev_shield_placement == 0 ) + { + self attachriotshield(); + return; + } + else if ( self.prev_shield_placement == 1 ) + { + self attachriotshield( level.carriedshieldmodel[ self.prev_shield_damage_level ], "tag_weapon_left" ); + self setriotshieldviewmodel( self.prev_shield_damage_level ); + return; + } + else if ( self.prev_shield_placement == 2 ) + { + self attachriotshield( level.stowedshieldmodel[ self.prev_shield_damage_level ], "tag_stowed_back" ); + return; + } + else + { + if ( self.prev_shield_placement == 3 ) + { + self attachriotshield(); + if ( isDefined( self.shield_ent ) ) + { + self.shield_ent setmodel( level.deployedshieldmodel[ self.prev_shield_damage_level ] ); + } + } + } + } +} + +updatestandaloneriotshieldmodel() +{ + update = 0; + if ( !isDefined( self.prev_shield_damage_level ) || self.prev_shield_damage_level != self.shield_damage_level ) + { + self.prev_shield_damage_level = self.shield_damage_level; + update = 1; + } + if ( update ) + { + self setmodel( level.deployedshieldmodel[ self.prev_shield_damage_level ] ); + } +} + +watchshieldlaststand() +{ + self endon( "death" ); + self endon( "disconnect" ); + self notify( "watchShieldLastStand" ); + self endon( "watchShieldLastStand" ); + while ( 1 ) + { + self waittill( "weapons_taken_for_last_stand" ); + self.riotshield_hidden = 0; + if ( isDefined( self.hasriotshield ) && self.hasriotshield ) + { + if ( self.prev_shield_placement == 1 || self.prev_shield_placement == 2 ) + { + self.riotshield_hidden = 2; + self.shield_placement = 0; + self updateriotshieldmodel(); + } + } + str_notify = self waittill_any_return( "player_revived", "bled_out" ); + if ( str_notify == "player_revived" ) + { + if ( isDefined( self.riotshield_hidden ) && self.riotshield_hidden > 0 ) + { + self.shield_placement = self.riotshield_hidden; + self updateriotshieldmodel(); + } + } + else + { + self maps/mp/zombies/_zm_weap_riotshield::player_take_riotshield(); + } + self.riotshield_hidden = undefined; + } +} + +trackriotshield() +{ + self endon( "death" ); + self endon( "disconnect" ); + self.hasriotshield = self hasweapon( level.riotshield_name ); + self.hasriotshieldequipped = self getcurrentweapon() == level.riotshield_name; + self.shield_placement = 0; + if ( self.hasriotshield ) + { + if ( self.hasriotshieldequipped ) + { + self.shield_placement = 1; + self updateriotshieldmodel(); + } + else + { + self.shield_placement = 2; + self updateriotshieldmodel(); + } + } + for ( ;; ) + { + self waittill( "weapon_change", newweapon ); + if ( newweapon == level.riotshield_name ) + { + if ( self.hasriotshieldequipped ) + { + continue; + } + else if ( isDefined( self.riotshieldentity ) ) + { + self notify( "destroy_riotshield" ); + } + self.shield_placement = 1; + self updateriotshieldmodel(); + if ( self.hasriotshield ) + { + break; + } + self.hasriotshield = 1; + self.hasriotshieldequipped = 1; + continue; + } + else if ( self ismantling() && newweapon == "none" ) + { + continue; + } + else + { + if ( self.hasriotshieldequipped ) + { +/# + assert( self.hasriotshield ); +#/ + self.hasriotshield = self hasweapon( level.riotshield_name ); + if ( isDefined( self.riotshield_hidden ) && self.riotshield_hidden ) + { + } + else + { + if ( self.hasriotshield ) + { + self.shield_placement = 2; + break; + } + else if ( isDefined( self.shield_ent ) ) + { +/# + assert( self.shield_placement == 3 ); +#/ + break; + } + else + { + self.shield_placement = 0; + } + } + self updateriotshieldmodel(); + self.hasriotshieldequipped = 0; + break; + } + else if ( self.hasriotshield ) + { + if ( !self hasweapon( level.riotshield_name ) ) + { + self.shield_placement = 0; + self updateriotshieldmodel(); + self.hasriotshield = 0; + } + break; + } + else + { + if ( self hasweapon( level.riotshield_name ) ) + { + self.shield_placement = 2; + self updateriotshieldmodel(); + self.hasriotshield = 1; + } + } + } + } +} + +trackequipmentchange() +{ + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_dropped", equipname ); + self notify( "weapon_change" ); + } +} + +updateriotshieldplacement() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "deploy_riotshield" ); + self endon( "start_riotshield_deploy" ); + self endon( "weapon_change" ); + while ( 1 ) + { + placement = self canplaceriotshield( "raise_riotshield" ); + if ( placement[ "result" ] && riotshielddistancetest( placement[ "origin" ] ) ) + { + self restoreriotshieldviewmodel(); + self setplacementhint( 1 ); + } + else + { + self specialriotshieldviewmodel(); + self setplacementhint( 0 ); + } + wait 0,05; + } +} + +startriotshielddeploy() +{ + self notify( "start_riotshield_deploy" ); + self thread updateriotshieldplacement(); + self thread watchriotshielddeploy(); +} + +spawnriotshieldcover( origin, angles ) +{ + shield_ent = spawn( "script_model", origin, 1 ); + shield_ent.angles = angles; + shield_ent setowner( self ); + shield_ent.owner = self; + shield_ent.owner.shield_ent = shield_ent; + shield_ent.isriotshield = 1; + self.shield_placement = 3; + self updateriotshieldmodel(); + shield_ent setscriptmoverflag( 0 ); + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( shield_ent, "destroy_riotshield", 1 ); + maps/mp/zombies/_zm_equipment::destructible_equipment_list_add( shield_ent ); + return shield_ent; +} + +watchriotshielddeploy() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "start_riotshield_deploy" ); + self waittill( "deploy_riotshield", deploy_attempt ); + self restoreriotshieldviewmodel(); + self setplacementhint( 1 ); + placement_hint = 0; + if ( deploy_attempt ) + { + placement = self canplaceriotshield( "deploy_riotshield" ); + if ( placement[ "result" ] && riotshielddistancetest( placement[ "origin" ] ) && self check_plant_position( placement[ "origin" ], placement[ "angles" ] ) ) + { + self doriotshielddeploy( placement[ "origin" ], placement[ "angles" ] ); + } + else + { + placement_hint = 1; + clip_max_ammo = weaponclipsize( level.riotshield_name ); + self setweaponammoclip( level.riotshield_name, clip_max_ammo ); + } + } + else + { + placement_hint = 1; + } + if ( placement_hint ) + { + self setriotshieldfailhint(); + } +} + +check_plant_position( origin, angles ) +{ + if ( isDefined( level.equipment_safe_to_drop ) ) + { + ret = 1; + test_ent = spawn( "script_model", origin ); + test_ent setmodel( level.deployedshieldmodel[ 0 ] ); + test_ent.angles = angles; + if ( !( self [[ level.equipment_safe_to_drop ]]( test_ent ) ) ) + { + ret = 0; + } + test_ent delete(); + return ret; + } + return 1; +} + +doriotshielddeploy( origin, angles ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "start_riotshield_deploy" ); + self notify( "deployed_riotshield" ); + self maps/mp/zombies/_zm_buildables::track_placed_buildables( level.riotshield_name ); + if ( isDefined( self.current_equipment ) && self.current_equipment == level.riotshield_name ) + { + self maps/mp/zombies/_zm_equipment::equipment_to_deployed( level.riotshield_name ); + } + zoffset = level.riotshield_placement_zoffset; + shield_ent = self spawnriotshieldcover( origin + ( 0, 0, zoffset ), angles ); + item_ent = deployriotshield( self, shield_ent ); + primaries = self getweaponslistprimaries(); +/# + assert( isDefined( item_ent ) ); + assert( !isDefined( self.riotshieldretrievetrigger ) ); + assert( !isDefined( self.riotshieldentity ) ); +#/ + self maps/mp/zombies/_zm_weapons::switch_back_primary_weapon( primaries[ 0 ] ); + if ( isDefined( level.equipment_planted ) ) + { + self [[ level.equipment_planted ]]( shield_ent, level.riotshield_name, self ); + } + if ( isDefined( level.equipment_safe_to_drop ) ) + { + if ( !( self [[ level.equipment_safe_to_drop ]]( shield_ent ) ) ) + { + self notify( "destroy_riotshield" ); + shield_ent delete(); + item_ent delete(); + return; + } + } + self.riotshieldretrievetrigger = item_ent; + self.riotshieldentity = shield_ent; + self thread watchdeployedriotshieldents(); + self thread deleteshieldondamage( self.riotshieldentity ); + self thread deleteshieldmodelonweaponpickup( self.riotshieldretrievetrigger ); + self thread deleteriotshieldonplayerdeath(); + self thread watchshieldtriggervisibility( self.riotshieldretrievetrigger ); + self.riotshieldentity thread watchdeployedriotshielddamage(); + return shield_ent; +} + +riotshielddistancetest( origin ) +{ +/# + assert( isDefined( origin ) ); +#/ + min_dist_squared = getDvarFloat( "riotshield_deploy_limit_radius" ); + min_dist_squared *= min_dist_squared; + i = 0; + while ( i < level.players.size ) + { + if ( isDefined( level.players[ i ].riotshieldentity ) ) + { + dist_squared = distancesquared( level.players[ i ].riotshieldentity.origin, origin ); + if ( min_dist_squared > dist_squared ) + { +/# + println( "Shield placement denied! Failed distance check to other riotshields." ); +#/ + return 0; + } + } + i++; + } + return 1; +} + +watchdeployedriotshieldents() +{ +/# + assert( isDefined( self.riotshieldretrievetrigger ) ); + assert( isDefined( self.riotshieldentity ) ); +#/ + riotshieldretrievetrigger = self.riotshieldretrievetrigger; + riotshieldentity = self.riotshieldentity; + self waittill_any( "destroy_riotshield", "disconnect", "riotshield_zm_taken" ); + if ( isDefined( self ) ) + { + self.shield_placement = 0; + self updateriotshieldmodel(); + } + if ( isDefined( riotshieldretrievetrigger ) ) + { + riotshieldretrievetrigger delete(); + } + if ( isDefined( riotshieldentity ) ) + { + riotshieldentity delete(); + } +} + +watchdeployedriotshielddamage() +{ + self endon( "death" ); + damagemax = getDvarInt( "riotshield_deployed_health" ); + self.damagetaken = 0; + while ( 1 ) + { + self.maxhealth = 100000; + self.health = self.maxhealth; + self waittill( "damage", damage, attacker, direction, point, type, tagname, modelname, partname, weaponname, idflags ); + if ( isDefined( level.players_can_damage_riotshields ) && !level.players_can_damage_riotshields ) + { + continue; + } + if ( !isDefined( attacker ) || !isplayer( attacker ) ) + { + continue; + } +/# + if ( isDefined( self.owner ) ) + { + assert( isDefined( self.owner.team ) ); + } +#/ + while ( is_encounter() && attacker.team == self.owner.team && attacker != self.owner ) + { + continue; + } + if ( isDefined( level.riotshield_damage_callback ) ) + { + self.owner [[ level.riotshield_damage_callback ]]( damage, 0 ); + continue; + } + else + { + if ( type == "MOD_MELEE" ) + { + damage *= getDvarFloat( "riotshield_melee_damage_scale" ); + } + else if ( type == "MOD_PISTOL_BULLET" || type == "MOD_RIFLE_BULLET" ) + { + damage *= getDvarFloat( "riotshield_bullet_damage_scale" ); + } + else + { + if ( type != "MOD_GRENADE" && type != "MOD_GRENADE_SPLASH" && type != "MOD_EXPLOSIVE" && type != "MOD_EXPLOSIVE_SPLASH" || type == "MOD_PROJECTILE" && type == "MOD_PROJECTILE_SPLASH" ) + { + damage *= getDvarFloat( "riotshield_explosive_damage_scale" ); + break; + } + else + { + if ( type == "MOD_IMPACT" ) + { + damage *= getDvarFloat( "riotshield_projectile_damage_scale" ); + } + } + } + self.damagetaken += damage; + if ( self.damagetaken >= damagemax ) + { + self damagethendestroyriotshield(); + } + } + } +} + +damagethendestroyriotshield() +{ + self endon( "death" ); + self.owner.riotshieldretrievetrigger delete(); + self notsolid(); + self setclientflag( 14 ); + wait getDvarFloat( "riotshield_destroyed_cleanup_time" ); + self.owner notify( "destroy_riotshield" ); +} + +deleteshieldondamage( shield_ent ) +{ + shield_ent waittill( "death" ); + self notify( "destroy_riotshield" ); +} + +deleteshieldmodelonweaponpickup( shield_trigger ) +{ + shield_trigger waittill( "trigger", player ); + self maps/mp/zombies/_zm_equipment::equipment_from_deployed( level.riotshield_name ); + self notify( "destroy_riotshield" ); + if ( self != player ) + { + if ( isDefined( level.transferriotshield ) ) + { + [[ level.transferriotshield ]]( self, player ); + } + } +} + +watchshieldtriggervisibility( trigger ) +{ + self endon( "death" ); + trigger endon( "death" ); + while ( isDefined( trigger ) ) + { + players = get_players(); + _a759 = players; + _k759 = getFirstArrayKey( _a759 ); + while ( isDefined( _k759 ) ) + { + player = _a759[ _k759 ]; + pickup = 1; + if ( !isDefined( player ) ) + { + } + else + { + if ( isDefined( level.cantransferriotshield ) ) + { + pickup = [[ level.cantransferriotshield ]]( self, player ); + } + if ( !isDefined( trigger ) ) + { + return; + } + if ( pickup ) + { + trigger setvisibletoplayer( player ); + } + else + { + trigger setinvisibletoplayer( player ); + } + wait 0,05; + } + _k759 = getNextArrayKey( _a759, _k759 ); + } + wait 0,05; + } +} + +deleteriotshieldonplayerdeath() +{ + self.riotshieldentity endon( "death" ); + self waittill( "death" ); + self notify( "destroy_riotshield" ); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc new file mode 100644 index 0000000..04f7af6 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc @@ -0,0 +1,308 @@ +#include maps/mp/zombies/_zm_stats; +#include common_scripts/utility; +#include maps/mp/_utility; + +init() +{ + if ( !isDefined( level.ballistic_knife_autorecover ) ) + { + level.ballistic_knife_autorecover = 1; + } + if ( isDefined( level._uses_retrievable_ballisitic_knives ) && level._uses_retrievable_ballisitic_knives == 1 ) + { + precachemodel( "t5_weapon_ballistic_knife_projectile" ); + precachemodel( "t5_weapon_ballistic_knife_blade_retrieve" ); + } +} + +on_spawn( watcher, player ) +{ + player endon( "death" ); + player endon( "disconnect" ); + player endon( "zmb_lost_knife" ); + level endon( "game_ended" ); + self waittill( "stationary", endpos, normal, angles, attacker, prey, bone ); + isfriendly = 0; + if ( isDefined( endpos ) ) + { + retrievable_model = spawn( "script_model", endpos ); + retrievable_model setmodel( "t5_weapon_ballistic_knife_blade_retrieve" ); + retrievable_model setowner( player ); + retrievable_model.owner = player; + retrievable_model.angles = angles; + retrievable_model.name = watcher.weapon; + if ( isDefined( prey ) ) + { + if ( isplayer( prey ) && player.team == prey.team ) + { + isfriendly = 1; + } + else + { + if ( isai( prey ) && player.team == prey.team ) + { + isfriendly = 1; + } + } + if ( !isfriendly ) + { + retrievable_model linkto( prey, bone ); + retrievable_model thread force_drop_knives_to_ground_on_death( player, prey ); + } + else + { + if ( isfriendly ) + { + retrievable_model physicslaunch( normal, ( randomint( 10 ), randomint( 10 ), randomint( 10 ) ) ); + normal = ( 0, 0, 1 ); + } + } + } + watcher.objectarray[ watcher.objectarray.size ] = retrievable_model; + if ( isfriendly ) + { + retrievable_model waittill( "stationary" ); + } + retrievable_model thread drop_knives_to_ground( player ); + if ( isfriendly ) + { + player notify( "ballistic_knife_stationary" ); + } + else + { + player notify( "ballistic_knife_stationary" ); + } + retrievable_model thread wait_to_show_glowing_model( prey ); + } +} + +wait_to_show_glowing_model( prey ) +{ + level endon( "game_ended" ); + self endon( "death" ); + wait 2; + self setmodel( "t5_weapon_ballistic_knife_blade_retrieve" ); +} + +on_spawn_retrieve_trigger( watcher, player ) +{ + player endon( "death" ); + player endon( "disconnect" ); + player endon( "zmb_lost_knife" ); + level endon( "game_ended" ); + player waittill( "ballistic_knife_stationary", retrievable_model, normal, prey ); + if ( !isDefined( retrievable_model ) ) + { + return; + } + trigger_pos = []; + if ( isDefined( prey ) || isplayer( prey ) && isai( prey ) ) + { + trigger_pos[ 0 ] = prey.origin[ 0 ]; + trigger_pos[ 1 ] = prey.origin[ 1 ]; + trigger_pos[ 2 ] = prey.origin[ 2 ] + 10; + } + else + { + trigger_pos[ 0 ] = retrievable_model.origin[ 0 ] + ( 10 * normal[ 0 ] ); + trigger_pos[ 1 ] = retrievable_model.origin[ 1 ] + ( 10 * normal[ 1 ] ); + trigger_pos[ 2 ] = retrievable_model.origin[ 2 ] + ( 10 * normal[ 2 ] ); + } + if ( is_true( level.ballistic_knife_autorecover ) ) + { + trigger_pos[ 2 ] -= 50; + pickup_trigger = spawn( "trigger_radius", ( trigger_pos[ 0 ], trigger_pos[ 1 ], trigger_pos[ 2 ] ), 0, 50, 100 ); + } + else + { + pickup_trigger = spawn( "trigger_radius_use", ( trigger_pos[ 0 ], trigger_pos[ 1 ], trigger_pos[ 2 ] ) ); + pickup_trigger setcursorhint( "HINT_NOICON" ); + } + pickup_trigger.owner = player; + retrievable_model.retrievabletrigger = pickup_trigger; + hint_string = &"WEAPON_BALLISTIC_KNIFE_PICKUP"; + if ( isDefined( hint_string ) ) + { + pickup_trigger sethintstring( hint_string ); + } + else + { + pickup_trigger sethintstring( &"GENERIC_PICKUP" ); + } + pickup_trigger setteamfortrigger( player.team ); + player clientclaimtrigger( pickup_trigger ); + pickup_trigger enablelinkto(); + if ( isDefined( prey ) ) + { + pickup_trigger linkto( prey ); + } + else + { + pickup_trigger linkto( retrievable_model ); + } + if ( isDefined( level.knife_planted ) ) + { + [[ level.knife_planted ]]( retrievable_model, pickup_trigger, prey ); + } + retrievable_model thread watch_use_trigger( pickup_trigger, retrievable_model, ::pick_up, watcher.weapon, watcher.pickupsoundplayer, watcher.pickupsound ); + player thread watch_shutdown( pickup_trigger, retrievable_model ); +} + +debug_print( endpos ) +{ +/# + self endon( "death" ); + while ( 1 ) + { + print3d( endpos, "pickup_trigger" ); + wait 0,05; +#/ + } +} + +watch_use_trigger( trigger, model, callback, weapon, playersoundonuse, npcsoundonuse ) +{ + self endon( "death" ); + self endon( "delete" ); + level endon( "game_ended" ); + max_ammo = weaponmaxammo( weapon ) + 1; + autorecover = is_true( level.ballistic_knife_autorecover ); + while ( 1 ) + { + trigger waittill( "trigger", player ); + while ( !isalive( player ) ) + { + continue; + } + if ( !player isonground() && !is_true( trigger.force_pickup ) ) + { + continue; + } + if ( isDefined( trigger.triggerteam ) && player.team != trigger.triggerteam ) + { + continue; + } + if ( isDefined( trigger.claimedby ) && player != trigger.claimedby ) + { + continue; + } + ammo_stock = player getweaponammostock( weapon ); + ammo_clip = player getweaponammoclip( weapon ); + current_weapon = player getcurrentweapon(); + total_ammo = ammo_stock + ammo_clip; + hasreloaded = 1; + if ( total_ammo > 0 && ammo_stock == total_ammo && current_weapon == weapon ) + { + hasreloaded = 0; + } + if ( total_ammo >= max_ammo || !hasreloaded ) + { + continue; + } + if ( !autorecover && player usebuttonpressed() && !player.throwinggrenade || !player meleebuttonpressed() && is_true( trigger.force_pickup ) ) + { + if ( isDefined( playersoundonuse ) ) + { + player playlocalsound( playersoundonuse ); + } + if ( isDefined( npcsoundonuse ) ) + { + player playsound( npcsoundonuse ); + } + player thread [[ callback ]]( weapon, model, trigger ); + return; + } + else + { + } + } +} + +pick_up( weapon, model, trigger ) +{ + if ( self hasweapon( weapon ) ) + { + current_weapon = self getcurrentweapon(); + if ( current_weapon != weapon ) + { + clip_ammo = self getweaponammoclip( weapon ); + if ( !clip_ammo ) + { + self setweaponammoclip( weapon, 1 ); + } + else + { + new_ammo_stock = self getweaponammostock( weapon ) + 1; + self setweaponammostock( weapon, new_ammo_stock ); + } + } + else + { + new_ammo_stock = self getweaponammostock( weapon ) + 1; + self setweaponammostock( weapon, new_ammo_stock ); + } + } + self maps/mp/zombies/_zm_stats::increment_client_stat( "ballistic_knives_pickedup" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "ballistic_knives_pickedup" ); + model destroy_ent(); + trigger destroy_ent(); +} + +destroy_ent() +{ + if ( isDefined( self ) ) + { + if ( isDefined( self.glowing_model ) ) + { + self.glowing_model delete(); + } + self delete(); + } +} + +watch_shutdown( trigger, model ) +{ + self waittill_any( "death_or_disconnect", "zmb_lost_knife" ); + trigger destroy_ent(); + model destroy_ent(); +} + +drop_knives_to_ground( player ) +{ + player endon( "death" ); + player endon( "zmb_lost_knife" ); + for ( ;; ) + { + level waittill( "drop_objects_to_ground", origin, radius ); + if ( distancesquared( origin, self.origin ) < ( radius * radius ) ) + { + self physicslaunch( ( 0, 0, 1 ), vectorScale( ( 0, 0, 1 ), 5 ) ); + self thread update_retrieve_trigger( player ); + } + } +} + +force_drop_knives_to_ground_on_death( player, prey ) +{ + self endon( "death" ); + player endon( "zmb_lost_knife" ); + prey waittill( "death" ); + self unlink(); + self physicslaunch( ( 0, 0, 1 ), vectorScale( ( 0, 0, 1 ), 5 ) ); + self thread update_retrieve_trigger( player ); +} + +update_retrieve_trigger( player ) +{ + self endon( "death" ); + player endon( "zmb_lost_knife" ); + if ( isDefined( level.custom_update_retrieve_trigger ) ) + { + self [[ level.custom_update_retrieve_trigger ]]( player ); + return; + } + self waittill( "stationary" ); + trigger = self.retrievabletrigger; + trigger.origin = ( self.origin[ 0 ], self.origin[ 1 ], self.origin[ 2 ] + 10 ); + trigger linkto( self ); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_bowie.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_bowie.gsc new file mode 100644 index 0000000..4ad88c6 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_bowie.gsc @@ -0,0 +1,19 @@ +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( isDefined( level.bowie_cost ) ) + { + cost = level.bowie_cost; + } + else + { + cost = 3000; + } + maps/mp/zombies/_zm_melee_weapon::init( "bowie_knife_zm", "zombie_bowie_flourish", "knife_ballistic_bowie_zm", "knife_ballistic_bowie_upgraded_zm", cost, "bowie_upgrade", &"ZOMBIE_WEAPON_BOWIE_BUY", "bowie", undefined ); + maps/mp/zombies/_zm_weapons::add_retrievable_knife_init_name( "knife_ballistic_bowie" ); + maps/mp/zombies/_zm_weapons::add_retrievable_knife_init_name( "knife_ballistic_bowie_upgraded" ); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_claymore.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_claymore.gsc new file mode 100644 index 0000000..47f5b66 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_claymore.gsc @@ -0,0 +1,482 @@ +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !isDefined( level.claymores_max_per_player ) ) + { + level.claymores_max_per_player = 12; + } + trigs = getentarray( "claymore_purchase", "targetname" ); + i = 0; + while ( i < trigs.size ) + { + model = getent( trigs[ i ].target, "targetname" ); + if ( isDefined( model ) ) + { + model hide(); + } + i++; + } + array_thread( trigs, ::buy_claymores ); + level thread give_claymores_after_rounds(); + level.claymores_on_damage = ::satchel_damage; + level.pickup_claymores = ::pickup_claymores; + level.pickup_claymores_trigger_listener = ::pickup_claymores_trigger_listener; + level.claymore_detectiondot = cos( 70 ); + level.claymore_detectionmindist = 20; + level._effect[ "claymore_laser" ] = loadfx( "weapon/claymore/fx_claymore_laser" ); +} + +buy_claymores() +{ + self.zombie_cost = 1000; + self sethintstring( &"ZOMBIE_CLAYMORE_PURCHASE" ); + self setcursorhint( "HINT_WEAPON", "claymore_zm" ); + self endon( "kill_trigger" ); + if ( !isDefined( self.stub ) ) + { + return; + } + if ( isDefined( self.stub ) && !isDefined( self.stub.claymores_triggered ) ) + { + self.stub.claymores_triggered = 0; + } + self.claymores_triggered = self.stub.claymores_triggered; + while ( 1 ) + { + self waittill( "trigger", who ); + while ( who in_revive_trigger() ) + { + continue; + } + while ( who has_powerup_weapon() ) + { + wait 0,1; + } + if ( is_player_valid( who ) ) + { + if ( who.score >= self.zombie_cost ) + { + if ( !who is_player_placeable_mine( "claymore_zm" ) ) + { + play_sound_at_pos( "purchase", self.origin ); + who maps/mp/zombies/_zm_score::minus_to_player_score( self.zombie_cost ); + who thread claymore_setup(); + who thread show_claymore_hint( "claymore_purchased" ); + who thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", "grenade" ); + if ( isDefined( self.stub ) ) + { + self.claymores_triggered = self.stub.claymores_triggered; + } + if ( self.claymores_triggered == 0 ) + { + model = getent( self.target, "targetname" ); + if ( isDefined( model ) ) + { + model thread maps/mp/zombies/_zm_weapons::weapon_show( who ); + } + else + { + if ( isDefined( self.clientfieldname ) ) + { + level setclientfield( self.clientfieldname, 1 ); + } + } + self.claymores_triggered = 1; + if ( isDefined( self.stub ) ) + { + self.stub.claymores_triggered = 1; + } + } + trigs = getentarray( "claymore_purchase", "targetname" ); + i = 0; + while ( i < trigs.size ) + { + trigs[ i ] setinvisibletoplayer( who ); + i++; + } + } + else who thread show_claymore_hint( "already_purchased" ); + break; + } + else + { + who play_sound_on_ent( "no_purchase" ); + who maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "no_money_weapon" ); + } + } + } +} + +claymore_unitrigger_update_prompt( player ) +{ + if ( player is_player_placeable_mine( "claymore_zm" ) ) + { + self sethintstring( "" ); + self setcursorhint( "HINT_NOICON" ); + return 0; + } + self sethintstring( &"ZOMBIE_CLAYMORE_PURCHASE" ); + self setcursorhint( "HINT_WEAPON", "claymore_zm" ); + return 1; +} + +set_claymore_visible() +{ + players = get_players(); + trigs = getentarray( "claymore_purchase", "targetname" ); + while ( 1 ) + { + j = 0; + while ( j < players.size ) + { + while ( !players[ j ] is_player_placeable_mine( "claymore_zm" ) ) + { + i = 0; + while ( i < trigs.size ) + { + trigs[ i ] setinvisibletoplayer( players[ j ], 0 ); + i++; + } + } + j++; + } + wait 1; + players = get_players(); + } +} + +claymore_safe_to_plant() +{ + if ( self.owner.claymores.size >= level.claymores_max_per_player ) + { + return 0; + } + if ( isDefined( level.claymore_safe_to_plant ) ) + { + return self [[ level.claymore_safe_to_plant ]](); + } + return 1; +} + +claymore_wait_and_detonate() +{ + wait 0,1; + self detonate( self.owner ); +} + +claymore_watch() +{ + self endon( "death" ); + self notify( "claymore_watch" ); + self endon( "claymore_watch" ); + while ( 1 ) + { + self waittill( "grenade_fire", claymore, weapname ); + if ( weapname == "claymore_zm" ) + { + claymore.owner = self; + claymore.team = self.team; + self notify( "zmb_enable_claymore_prompt" ); + if ( claymore claymore_safe_to_plant() ) + { + if ( isDefined( level.claymore_planted ) ) + { + self thread [[ level.claymore_planted ]]( claymore ); + } + claymore thread claymore_detonation(); + claymore thread play_claymore_effects(); + self maps/mp/zombies/_zm_stats::increment_client_stat( "claymores_planted" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "claymores_planted" ); + break; + } + else + { + claymore thread claymore_wait_and_detonate(); + } + } + } +} + +claymore_setup() +{ + if ( !isDefined( self.claymores ) ) + { + self.claymores = []; + } + self thread claymore_watch(); + self giveweapon( "claymore_zm" ); + self set_player_placeable_mine( "claymore_zm" ); + self setactionslot( 4, "weapon", "claymore_zm" ); + self setweaponammostock( "claymore_zm", 2 ); +} + +adjust_trigger_origin( origin ) +{ + origin += vectorScale( ( 0, 0, 1 ), 20 ); + return origin; +} + +on_spawn_retrieve_trigger( watcher, player ) +{ + self maps/mp/gametypes_zm/_weaponobjects::onspawnretrievableweaponobject( watcher, player ); + if ( isDefined( self.pickuptrigger ) ) + { + self.pickuptrigger sethintlowpriority( 0 ); + } +} + +pickup_claymores() +{ + player = self.owner; + if ( !player hasweapon( "claymore_zm" ) ) + { + player thread claymore_watch(); + player giveweapon( "claymore_zm" ); + player set_player_placeable_mine( "claymore_zm" ); + player setactionslot( 4, "weapon", "claymore_zm" ); + player setweaponammoclip( "claymore_zm", 0 ); + player notify( "zmb_enable_claymore_prompt" ); + } + else + { + clip_ammo = player getweaponammoclip( self.name ); + clip_max_ammo = weaponclipsize( self.name ); + if ( clip_ammo >= clip_max_ammo ) + { + self destroy_ent(); + player notify( "zmb_disable_claymore_prompt" ); + return; + } + } + self pick_up(); + clip_ammo = player getweaponammoclip( self.name ); + clip_max_ammo = weaponclipsize( self.name ); + if ( clip_ammo >= clip_max_ammo ) + { + player notify( "zmb_disable_claymore_prompt" ); + } + player maps/mp/zombies/_zm_stats::increment_client_stat( "claymores_pickedup" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "claymores_pickedup" ); +} + +pickup_claymores_trigger_listener( trigger, player ) +{ + self thread pickup_claymores_trigger_listener_enable( trigger, player ); + self thread pickup_claymores_trigger_listener_disable( trigger, player ); +} + +pickup_claymores_trigger_listener_enable( trigger, player ) +{ + self endon( "delete" ); + self endon( "death" ); + while ( 1 ) + { + player waittill_any( "zmb_enable_claymore_prompt", "spawned_player" ); + if ( !isDefined( trigger ) ) + { + return; + } + trigger trigger_on(); + trigger linkto( self ); + } +} + +pickup_claymores_trigger_listener_disable( trigger, player ) +{ + self endon( "delete" ); + self endon( "death" ); + while ( 1 ) + { + player waittill( "zmb_disable_claymore_prompt" ); + if ( !isDefined( trigger ) ) + { + return; + } + trigger unlink(); + trigger trigger_off(); + } +} + +shouldaffectweaponobject( object ) +{ + pos = self.origin + vectorScale( ( 0, 0, 1 ), 32 ); + dirtopos = pos - object.origin; + objectforward = anglesToForward( object.angles ); + dist = vectordot( dirtopos, objectforward ); + if ( dist < level.claymore_detectionmindist ) + { + return 0; + } + dirtopos = vectornormalize( dirtopos ); + dot = vectordot( dirtopos, objectforward ); + return dot > level.claymore_detectiondot; +} + +claymore_detonation() +{ + self endon( "death" ); + self waittill_not_moving(); + detonateradius = 96; + damagearea = spawn( "trigger_radius", self.origin + ( 0, 0, 0 - detonateradius ), 4, detonateradius, detonateradius * 2 ); + damagearea setexcludeteamfortrigger( self.team ); + damagearea enablelinkto(); + damagearea linkto( self ); + if ( is_true( self.isonbus ) ) + { + damagearea setmovingplatformenabled( 1 ); + } + self.damagearea = damagearea; + self thread delete_claymores_on_death( self.owner, damagearea ); + self.owner.claymores[ self.owner.claymores.size ] = self; + while ( 1 ) + { + damagearea waittill( "trigger", ent ); + if ( isDefined( self.owner ) && ent == self.owner ) + { + continue; + } + while ( isDefined( ent.pers ) && isDefined( ent.pers[ "team" ] ) && ent.pers[ "team" ] == self.team ) + { + continue; + } + if ( isDefined( ent.ignore_claymore ) && ent.ignore_claymore ) + { + continue; + } + while ( !ent shouldaffectweaponobject( self ) ) + { + continue; + } + if ( ent damageconetrace( self.origin, self ) > 0 ) + { + self playsound( "wpn_claymore_alert" ); + wait 0,4; + if ( isDefined( self.owner ) ) + { + self detonate( self.owner ); + } + else + { + self detonate( undefined ); + } + return; + } + } +} + +delete_claymores_on_death( player, ent ) +{ + self waittill( "death" ); + if ( isDefined( player ) ) + { + arrayremovevalue( player.claymores, self ); + } + wait 0,05; + if ( isDefined( ent ) ) + { + ent delete(); + } +} + +satchel_damage() +{ + self endon( "death" ); + self setcandamage( 1 ); + self.health = 100000; + self.maxhealth = self.health; + attacker = undefined; + while ( 1 ) + { + self waittill( "damage", amount, attacker ); + if ( !isDefined( self ) ) + { + return; + } + self.health = self.maxhealth; + while ( !isplayer( attacker ) ) + { + continue; + } + if ( isDefined( self.owner ) && attacker == self.owner ) + { + continue; + } + while ( isDefined( attacker.pers ) && isDefined( attacker.pers[ "team" ] ) && attacker.pers[ "team" ] != level.zombie_team ) + { + continue; + } + } + if ( level.satchelexplodethisframe ) + { + wait ( 0,1 + randomfloat( 0,4 ) ); + } + else wait 0,05; + if ( !isDefined( self ) ) + { + return; + } + level.satchelexplodethisframe = 1; + thread reset_satchel_explode_this_frame(); + self detonate( attacker ); +} + +reset_satchel_explode_this_frame() +{ + wait 0,05; + level.satchelexplodethisframe = 0; +} + +play_claymore_effects() +{ + self endon( "death" ); + self waittill_not_moving(); + playfxontag( level._effect[ "claymore_laser" ], self, "tag_fx" ); +} + +give_claymores_after_rounds() +{ + while ( 1 ) + { + level waittill( "between_round_over" ); + while ( !level flag_exists( "teleporter_used" ) || !flag( "teleporter_used" ) ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] is_player_placeable_mine( "claymore_zm" ) ) + { + players[ i ] giveweapon( "claymore_zm" ); + players[ i ] set_player_placeable_mine( "claymore_zm" ); + players[ i ] setactionslot( 4, "weapon", "claymore_zm" ); + players[ i ] setweaponammoclip( "claymore_zm", 2 ); + } + i++; + } + } + } +} + +show_claymore_hint( string ) +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( string == "claymore_purchased" ) + { + text = &"ZOMBIE_CLAYMORE_HOWTO"; + } + else + { + text = &"ZOMBIE_CLAYMORE_ALREADY_PURCHASED"; + } + show_equipment_hint_text( text ); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_emp_bomb.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_emp_bomb.gsc new file mode 100644 index 0000000..73a8a86 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_emp_bomb.gsc @@ -0,0 +1,369 @@ +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_power; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !emp_bomb_exists() ) + { + return; + } + set_zombie_var( "emp_stun_range", 600 ); + set_zombie_var( "emp_stun_time", 20 ); + set_zombie_var( "emp_perk_off_range", 420 ); + set_zombie_var( "emp_perk_off_time", 90 ); + precacheshellshock( "frag_grenade_mp" ); +/# + level.zombiemode_devgui_emp_bomb_give = ::player_give_emp_bomb; +#/ + level thread onplayerconnect(); + level._equipment_emp_destroy_fx = loadfx( "weapon/emp/fx_emp_explosion_equip" ); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread watch_for_grenade_throw(); + } +} + +player_give_emp_bomb() +{ + self giveweapon( "emp_grenade_zm" ); + self set_player_tactical_grenade( "emp_grenade_zm" ); +} + +emp_bomb_exists() +{ + return isDefined( level.zombie_weapons[ "emp_grenade_zm" ] ); +} + +watch_for_grenade_throw() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "grenade_fire", grenade, weapname ); + while ( weapname != "emp_grenade_zm" ) + { + continue; + } + grenade.use_grenade_special_bookmark = 1; + grenade.grenade_multiattack_bookmark_count = 1; + grenade.owner = self; + self thread emp_detonate( grenade ); + } +} + +emp_detonate( grenade ) +{ + grenade_owner = undefined; + if ( isDefined( grenade.owner ) ) + { + grenade_owner = grenade.owner; + } + grenade waittill( "explode", grenade_origin ); + emp_radius = level.zombie_vars[ "emp_perk_off_range" ]; + emp_time = level.zombie_vars[ "emp_perk_off_time" ]; + origin = grenade_origin; + if ( !isDefined( origin ) ) + { + return; + } + level notify( "emp_detonate" ); + self thread emp_detonate_zombies( grenade_origin, grenade_owner ); + if ( isDefined( level.custom_emp_detonate ) ) + { + thread [[ level.custom_emp_detonate ]]( grenade_origin ); + } + if ( isDefined( grenade_owner ) ) + { + grenade_owner thread destroyequipment( origin, emp_radius ); + } + players_emped = emp_players( origin, emp_radius ); + disabled_list = maps/mp/zombies/_zm_power::change_power_in_radius( -1, origin, emp_radius ); + wait emp_time; + maps/mp/zombies/_zm_power::revert_power_to_list( 1, origin, emp_radius, disabled_list ); + unemp_players( players_emped ); +} + +emp_detonate_zombies( grenade_origin, grenade_owner ) +{ + zombies = get_array_of_closest( grenade_origin, getaispeciesarray( level.zombie_team, "all" ), undefined, undefined, level.zombie_vars[ "emp_stun_range" ] ); + if ( !isDefined( zombies ) ) + { + return; + } + i = 0; + while ( i < zombies.size ) + { + if ( !isDefined( zombies[ i ] ) || isDefined( zombies[ i ].ignore_inert ) && zombies[ i ].ignore_inert ) + { + i++; + continue; + } + else + { + zombies[ i ].becoming_inert = 1; + } + i++; + } + stunned = 0; + i = 0; + while ( i < zombies.size ) + { + if ( !isDefined( zombies[ i ] ) || isDefined( zombies[ i ].ignore_inert ) && zombies[ i ].ignore_inert ) + { + i++; + continue; + } + else + { + stunned++; + zombies[ i ] thread stun_zombie(); + wait 0,05; + } + i++; + } + if ( stunned >= 10 && isDefined( grenade_owner ) ) + { + grenade_owner notify( "the_lights_of_their_eyes" ); + } +} + +stun_zombie() +{ + self endon( "death" ); + self notify( "stun_zombie" ); + self endon( "stun_zombie" ); + if ( self.health <= 0 ) + { +/# + iprintln( "trying to stun a dead zombie" ); +#/ + return; + } + if ( isDefined( self.stun_zombie ) ) + { + self thread [[ self.stun_zombie ]](); + return; + } + self thread maps/mp/zombies/_zm_ai_basic::start_inert(); +} + +emp_players( origin, radius ) +{ + players_emped = []; + players = get_players(); + rsquared = radius * radius; + _a192 = players; + _k192 = getFirstArrayKey( _a192 ); + while ( isDefined( _k192 ) ) + { + player = _a192[ _k192 ]; + if ( isalive( player ) && distancesquared( origin, player.origin ) < rsquared ) + { + player player_emp_on(); + players_emped[ players_emped.size ] = player; + } + _k192 = getNextArrayKey( _a192, _k192 ); + } + return players_emped; +} + +unemp_players( players_emped ) +{ + _a206 = players_emped; + _k206 = getFirstArrayKey( _a206 ); + while ( isDefined( _k206 ) ) + { + player = _a206[ _k206 ]; + player player_emp_off(); + _k206 = getNextArrayKey( _a206, _k206 ); + } +} + +player_emp_on() +{ + self.empgrenaded = 1; + self setempjammed( 1 ); + self shellshock( "frag_grenade_mp", 2 ); +} + +player_emp_off() +{ + if ( isDefined( self ) ) + { + self stopshellshock(); + self setempjammed( 0 ); + self.empgrenaded = undefined; + } +} + +getwatcherforweapon( weapname ) +{ + if ( !isDefined( self ) ) + { + return undefined; + } + if ( !isplayer( self ) ) + { + return undefined; + } + i = 0; + while ( i < self.weaponobjectwatcherarray.size ) + { + if ( self.weaponobjectwatcherarray[ i ].weapon != weapname ) + { + i++; + continue; + } + else + { + return self.weaponobjectwatcherarray[ i ]; + } + i++; + } + return undefined; +} + +destroyequipment( origin, radius ) +{ + grenades = getentarray( "grenade", "classname" ); + rsquared = radius * radius; + i = 0; + while ( i < grenades.size ) + { + item = grenades[ i ]; + if ( distancesquared( origin, item.origin ) > rsquared ) + { + i++; + continue; + } + else if ( !isDefined( item.name ) ) + { + i++; + continue; + } + else if ( !is_offhand_weapon( item.name ) ) + { + i++; + continue; + } + else watcher = item.owner getwatcherforweapon( item.name ); + if ( !isDefined( watcher ) ) + { + i++; + continue; + } + else + { + watcher thread waitanddetonate( item, 0, self, "emp_grenade_zm" ); + } + i++; + } + equipment = maps/mp/zombies/_zm_equipment::get_destructible_equipment_list(); + i = 0; + while ( i < equipment.size ) + { + item = equipment[ i ]; + if ( !isDefined( item ) ) + { + i++; + continue; + } + else if ( distancesquared( origin, item.origin ) > rsquared ) + { + i++; + continue; + } + else if ( isDefined( item.isriotshield ) && item.isriotshield ) + { + i++; + continue; + } + else + { + waitanddamage( item, 505 ); + } + i++; + } +} + +isempweapon( weaponname ) +{ + if ( isDefined( weaponname ) && weaponname != "emp_mp" || weaponname == "emp_grenade_mp" && weaponname == "emp_grenade_zm" ) + { + return 1; + } + return 0; +} + +waitanddetonate( object, delay, attacker, weaponname ) +{ + object endon( "death" ); + object endon( "hacked" ); + from_emp = isempweapon( weaponname ); + if ( from_emp ) + { + object.stun_fx = 1; + if ( isDefined( level._equipment_emp_destroy_fx ) ) + { + playfx( level._equipment_emp_destroy_fx, object.origin + vectorScale( ( 0, 0, 1 ), 5 ), ( 0, randomfloat( 360 ), 0 ) ); + } + delay = 1,1; + } + if ( delay ) + { + wait delay; + } + if ( isDefined( object.detonated ) && object.detonated == 1 ) + { + return; + } + if ( !isDefined( self.detonate ) ) + { + return; + } + if ( isDefined( attacker ) && isplayer( attacker ) && isDefined( attacker.pers[ "team" ] ) && isDefined( object.owner ) && isDefined( object.owner.pers[ "team" ] ) ) + { + if ( level.teambased ) + { + if ( attacker.pers[ "team" ] != object.owner.pers[ "team" ] ) + { + attacker notify( "destroyed_explosive" ); + } + } + else + { + if ( attacker != object.owner ) + { + attacker notify( "destroyed_explosive" ); + } + } + } + object.detonated = 1; + object [[ self.detonate ]]( attacker, weaponname ); +} + +waitanddamage( object, damage ) +{ + object endon( "death" ); + object endon( "hacked" ); + object.stun_fx = 1; + if ( isDefined( level._equipment_emp_destroy_fx ) ) + { + playfx( level._equipment_emp_destroy_fx, object.origin + vectorScale( ( 0, 0, 1 ), 5 ), ( 0, randomfloat( 360 ), 0 ) ); + } + delay = 1,1; + if ( delay ) + { + wait delay; + } + object maps/mp/zombies/_zm_equipment::item_damage( damage ); +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_riotshield.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_riotshield.gsc new file mode 100644 index 0000000..feb18cf --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_riotshield.gsc @@ -0,0 +1,778 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +init() +{ + maps/mp/zombies/_zm_riotshield::init(); + set_zombie_var( "riotshield_cylinder_radius", 360 ); + set_zombie_var( "riotshield_fling_range", 90 ); + set_zombie_var( "riotshield_gib_range", 90 ); + set_zombie_var( "riotshield_gib_damage", 75 ); + set_zombie_var( "riotshield_knockdown_range", 90 ); + set_zombie_var( "riotshield_knockdown_damage", 15 ); + set_zombie_var( "riotshield_hit_points", 2250 ); + set_zombie_var( "riotshield_fling_damage_shield", 100 ); + set_zombie_var( "riotshield_knockdown_damage_shield", 15 ); + level.riotshield_network_choke_count = 0; + level.riotshield_gib_refs = []; + level.riotshield_gib_refs[ level.riotshield_gib_refs.size ] = "guts"; + level.riotshield_gib_refs[ level.riotshield_gib_refs.size ] = "right_arm"; + level.riotshield_gib_refs[ level.riotshield_gib_refs.size ] = "left_arm"; + level.riotshield_damage_callback = ::player_damage_shield; + level.deployed_riotshield_damage_callback = ::deployed_damage_shield; + level.transferriotshield = ::transferriotshield; + level.cantransferriotshield = ::cantransferriotshield; + maps/mp/zombies/_zm_spawner::register_zombie_damage_callback( ::riotshield_zombie_damage_response ); + maps/mp/zombies/_zm_equipment::register_equipment( "riotshield_zm", &"ZOMBIE_EQUIP_RIOTSHIELD_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_RIOTSHIELD_HOWTO", "riotshield_zm_icon", "riotshield", ::riotshield_activation_watcher_thread, undefined, ::dropshield, ::pickupshield ); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "riotshield", &"ZOMBIE_EQUIP_RIOTSHIELD_PICKUP_HINT_STRING" ); + onplayerconnect_callback( ::onplayerconnect ); +} + +onplayerconnect() +{ + self.player_shield_reset_health = ::player_init_shield_health; + self.player_shield_apply_damage = ::player_damage_shield; + self.player_shield_reset_location = ::player_init_shield_location; + self thread watchriotshielduse(); + self thread watchriotshieldmelee(); + self thread player_watch_laststand(); +} + +dropshield() +{ + self.shield_placement = 0; + self maps/mp/zombies/_zm_riotshield::updateriotshieldmodel(); + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "t6_wpn_zmb_shield_world", "riotshield_zm", self.origin + vectorScale( ( 0, 0, 1 ), 30 ), self.angles ); + if ( isDefined( item ) ) + { + item.shielddamagetaken = self.shielddamagetaken; + item.original_owner = self; + item.owner = undefined; + item.name = level.riotshield_name; + item.isriotshield = 1; + item deployed_damage_shield( 0 ); + item setscriptmoverflag( 0 ); + item.requires_pickup = 1; + item thread watchtoofriendly( self ); + } + self takeweapon( level.riotshield_name ); + return item; +} + +watchtoofriendly( player ) +{ + wait 1; + if ( isDefined( self ) && isDefined( player ) && distance2dsquared( self.origin, player.origin ) < 36 ) + { + if ( isalive( player ) ) + { + player playlocalsound( level.zmb_laugh_alias ); + } + player maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + self deployed_damage_shield( 2000 ); + } +} + +pickupshield( item ) +{ + item.owner = self; + damage = item.shielddamagetaken; + damagemax = level.zombie_vars[ "riotshield_hit_points" ]; + self.shielddamagetaken = damage; + self player_set_shield_health( damage, damagemax ); +} + +placeshield( origin, angles ) +{ + if ( self getcurrentweapon() != level.riotshield_name ) + { + self switchtoweapon( level.riotshield_name ); + self waittill( "weapon_change" ); + } + item = self maps/mp/zombies/_zm_riotshield::doriotshielddeploy( origin, angles ); + if ( isDefined( item ) ) + { + item.origin = self.origin + vectorScale( ( 0, 0, 1 ), 30 ); + item.angles = self.angles; + item.owner = self; + } + return item; +} + +cantransferriotshield( fromplayer, toplayer ) +{ + if ( isDefined( toplayer.screecher_weapon ) ) + { + return 0; + } + if ( isDefined( toplayer.is_drinking ) && toplayer.is_drinking > 0 ) + { + return 0; + } + if ( toplayer maps/mp/zombies/_zm_laststand::player_is_in_laststand() || toplayer in_revive_trigger() ) + { + return 0; + } + if ( toplayer isthrowinggrenade() ) + { + return 0; + } + if ( fromplayer == toplayer ) + { + return 1; + } + if ( toplayer is_player_equipment( level.riotshield_name ) && toplayer.shield_placement != 3 ) + { + return 0; + } + if ( fromplayer.session_team != toplayer.session_team ) + { + return 0; + } + return 1; +} + +transferriotshield( fromplayer, toplayer ) +{ + damage = fromplayer.shielddamagetaken; + toplayer player_take_riotshield(); + fromplayer player_take_riotshield(); + toplayer.shielddamagetaken = damage; + toplayer.shield_placement = 3; + toplayer.shield_damage_level = 0; + toplayer maps/mp/zombies/_zm_equipment::equipment_give( "riotshield_zm" ); + toplayer switchtoweapon( "riotshield_zm" ); + damagemax = level.zombie_vars[ "riotshield_hit_points" ]; + toplayer player_set_shield_health( damage, damagemax ); +} + +player_take_riotshield() +{ + self notify( "destroy_riotshield" ); + if ( self getcurrentweapon() == "riotshield_zm" ) + { + new_primary = ""; + if ( isDefined( self.laststand ) && self.laststand ) + { + new_primary = self.laststandpistol; + self giveweapon( new_primary ); + } + else + { + primaryweapons = self getweaponslistprimaries(); + i = 0; + while ( i < primaryweapons.size ) + { + if ( primaryweapons[ i ] != "riotshield_zm" ) + { + new_primary = primaryweapons[ i ]; + break; + } + else + { + i++; + } + } + if ( new_primary == "" ) + { + self maps/mp/zombies/_zm_weapons::give_fallback_weapon(); + new_primary = "zombie_fists_zm"; + } + } + self switchtoweaponimmediate( new_primary ); + self playsound( "wpn_riotshield_zm_destroy" ); + self waittill( "weapon_change" ); + } + self maps/mp/zombies/_zm_riotshield::removeriotshield(); + self maps/mp/zombies/_zm_equipment::equipment_take( "riotshield_zm" ); + self.hasriotshield = 0; + self.hasriotshieldequipped = 0; +} + +player_watch_laststand() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "entering_last_stand" ); + if ( self getcurrentweapon() == "riotshield_zm" ) + { + new_primary = self.laststandpistol; + self giveweapon( new_primary ); + self switchtoweaponimmediate( new_primary ); + } + } +} + +player_init_shield_health() +{ + retval = self.shielddamagetaken > 0; + self.shielddamagetaken = 0; + self.shield_damage_level = 0; + self maps/mp/zombies/_zm_riotshield::updateriotshieldmodel(); + return retval; +} + +player_init_shield_location() +{ + self.hasriotshield = 1; + self.hasriotshieldequipped = 0; + self.shield_placement = 2; + self maps/mp/zombies/_zm_riotshield::updateriotshieldmodel(); +} + +player_set_shield_health( damage, max_damage ) +{ + shieldhealth = int( ( 100 * ( max_damage - damage ) ) / max_damage ); + if ( shieldhealth >= 50 ) + { + self.shield_damage_level = 0; + } + else if ( shieldhealth >= 25 ) + { + self.shield_damage_level = 2; + } + else + { + self.shield_damage_level = 3; + } + self maps/mp/zombies/_zm_riotshield::updateriotshieldmodel(); +} + +deployed_set_shield_health( damage, max_damage ) +{ + shieldhealth = int( ( 100 * ( max_damage - damage ) ) / max_damage ); + if ( shieldhealth >= 50 ) + { + self.shield_damage_level = 0; + } + else if ( shieldhealth >= 25 ) + { + self.shield_damage_level = 2; + } + else + { + self.shield_damage_level = 3; + } + self maps/mp/zombies/_zm_riotshield::updatestandaloneriotshieldmodel(); +} + +player_damage_shield( idamage, bheld ) +{ + damagemax = level.zombie_vars[ "riotshield_hit_points" ]; + if ( !isDefined( self.shielddamagetaken ) ) + { + self.shielddamagetaken = 0; + } + self.shielddamagetaken += idamage; + if ( self.shielddamagetaken >= damagemax ) + { + if ( bheld || !isDefined( self.shield_ent ) ) + { + self playrumbleonentity( "damage_heavy" ); + earthquake( 1, 0,75, self.origin, 100 ); + } + else + { + if ( isDefined( self.shield_ent ) ) + { + if ( is_true( self.shield_ent.destroy_begun ) ) + { + return; + } + self.shield_ent.destroy_begun = 1; + shield_origin = self.shield_ent.origin; + level thread maps/mp/zombies/_zm_equipment::equipment_disappear_fx( shield_origin, level._riotshield_dissapear_fx ); + wait 1; + playsoundatposition( "wpn_riotshield_zm_destroy", shield_origin ); + } + } + self thread player_take_riotshield(); + } + else + { + if ( bheld ) + { + self playrumbleonentity( "damage_light" ); + earthquake( 0,5, 0,5, self.origin, 100 ); + } + self player_set_shield_health( self.shielddamagetaken, damagemax ); + self playsound( "fly_riotshield_zm_impact_zombies" ); + } +} + +deployed_damage_shield( idamage ) +{ + damagemax = level.zombie_vars[ "riotshield_hit_points" ]; + if ( !isDefined( self.shielddamagetaken ) ) + { + self.shielddamagetaken = 0; + } + self.shielddamagetaken += idamage; + if ( self.shielddamagetaken >= damagemax ) + { + shield_origin = self.origin; + if ( isDefined( self.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.stub ); + } + if ( isDefined( self.original_owner ) ) + { + self.original_owner maps/mp/zombies/_zm_equipment::equipment_take( "riotshield_zm" ); + } + maps/mp/zombies/_zm_equipment::equipment_disappear_fx( shield_origin, level._riotshield_dissapear_fx ); + playsoundatposition( "wpn_riotshield_zm_destroy", shield_origin ); + self_delete(); + } + else + { + self deployed_set_shield_health( self.shielddamagetaken, damagemax ); + } +} + +riotshield_activation_watcher_thread() +{ + self endon( "zombified" ); + self endon( "disconnect" ); + self endon( "riotshield_zm_taken" ); + while ( 1 ) + { + self waittill_either( "riotshield_zm_activate", "riotshield_zm_deactivate" ); + } +} + +watchriotshielduse() +{ + self endon( "death" ); + self endon( "disconnect" ); + self.shielddamagetaken = 0; + self thread maps/mp/zombies/_zm_riotshield::trackriotshield(); + self thread maps/mp/zombies/_zm_riotshield::trackequipmentchange(); + self thread maps/mp/zombies/_zm_riotshield::watchshieldlaststand(); + self thread trackstuckzombies(); + for ( ;; ) + { + self waittill( "raise_riotshield" ); + self thread maps/mp/zombies/_zm_riotshield::startriotshielddeploy(); + } +} + +watchriotshieldmelee() +{ + for ( ;; ) + { + self waittill( "weapon_melee", weapon ); + if ( weapon == level.riotshield_name ) + { + self riotshield_melee(); + } + } +} + +is_riotshield_damage( mod, player, amount ) +{ + if ( mod == "MOD_MELEE" && player hasweapon( level.riotshield_name ) && amount < 10 ) + { + return 1; + } + return 0; +} + +riotshield_damage( amount ) +{ +} + +riotshield_fling_zombie( player, fling_vec, index ) +{ + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( self.ignore_riotshield ) && self.ignore_riotshield ) + { + return; + } + if ( isDefined( self.riotshield_fling_func ) ) + { + self [[ self.riotshield_fling_func ]]( player ); + return; + } + damage = 2500; + self dodamage( damage, player.origin, player, player, "", "MOD_IMPACT" ); + if ( self.health < 1 ) + { + self.riotshield_death = 1; + self startragdoll(); + self launchragdoll( fling_vec ); + } +} + +zombie_knockdown( player, gib ) +{ + damage = level.zombie_vars[ "riotshield_knockdown_damage" ]; + if ( isDefined( level.override_riotshield_damage_func ) ) + { + self [[ level.override_riotshield_damage_func ]]( player, gib ); + } + else + { + if ( gib ) + { + self.a.gib_ref = random( level.riotshield_gib_refs ); + self thread maps/mp/animscripts/zm_death::do_gib(); + } + self dodamage( damage, player.origin, player ); + } +} + +riotshield_knockdown_zombie( player, gib ) +{ + self endon( "death" ); + playsoundatposition( "vox_riotshield_forcehit", self.origin ); + playsoundatposition( "wpn_riotshield_proj_impact", self.origin ); + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( self.riotshield_knockdown_func ) ) + { + self [[ self.riotshield_knockdown_func ]]( player, gib ); + } + else + { + self zombie_knockdown( player, gib ); + } + self dodamage( level.zombie_vars[ "riotshield_knockdown_damage" ], player.origin, player ); + self playsound( "fly_riotshield_forcehit" ); +} + +riotshield_get_enemies_in_range() +{ + view_pos = self geteye(); + zombies = get_array_of_closest( view_pos, get_round_enemy_array(), undefined, undefined, 2 * level.zombie_vars[ "riotshield_knockdown_range" ] ); + if ( !isDefined( zombies ) ) + { + return; + } + knockdown_range_squared = level.zombie_vars[ "riotshield_knockdown_range" ] * level.zombie_vars[ "riotshield_knockdown_range" ]; + gib_range_squared = level.zombie_vars[ "riotshield_gib_range" ] * level.zombie_vars[ "riotshield_gib_range" ]; + fling_range_squared = level.zombie_vars[ "riotshield_fling_range" ] * level.zombie_vars[ "riotshield_fling_range" ]; + cylinder_radius_squared = level.zombie_vars[ "riotshield_cylinder_radius" ] * level.zombie_vars[ "riotshield_cylinder_radius" ]; + forward_view_angles = self getweaponforwarddir(); + end_pos = view_pos + vectorScale( forward_view_angles, level.zombie_vars[ "riotshield_knockdown_range" ] ); +/# + if ( getDvarInt( #"BF480CE9" ) == 2 ) + { + near_circle_pos = view_pos + vectorScale( forward_view_angles, 2 ); + circle( near_circle_pos, level.zombie_vars[ "riotshield_cylinder_radius" ], ( 0, 0, 1 ), 0, 0, 100 ); + line( near_circle_pos, end_pos, ( 0, 0, 1 ), 1, 0, 100 ); + circle( end_pos, level.zombie_vars[ "riotshield_cylinder_radius" ], ( 0, 0, 1 ), 0, 0, 100 ); +#/ + } + i = 0; + while ( i < zombies.size ) + { + if ( !isDefined( zombies[ i ] ) || !isalive( zombies[ i ] ) ) + { + i++; + continue; + } + else + { + test_origin = zombies[ i ] getcentroid(); + test_range_squared = distancesquared( view_pos, test_origin ); + if ( test_range_squared > knockdown_range_squared ) + { + zombies[ i ] riotshield_debug_print( "range", ( 0, 0, 1 ) ); + return; + } + normal = vectornormalize( test_origin - view_pos ); + dot = vectordot( forward_view_angles, normal ); + if ( dot <= 0 ) + { + zombies[ i ] riotshield_debug_print( "dot", ( 0, 0, 1 ) ); + i++; + continue; + } + else radial_origin = pointonsegmentnearesttopoint( view_pos, end_pos, test_origin ); + if ( distancesquared( test_origin, radial_origin ) > cylinder_radius_squared ) + { + zombies[ i ] riotshield_debug_print( "cylinder", ( 0, 0, 1 ) ); + i++; + continue; + } + else if ( zombies[ i ] damageconetrace( view_pos, self ) == 0 ) + { + zombies[ i ] riotshield_debug_print( "cone", ( 0, 0, 1 ) ); + i++; + continue; + } + else if ( test_range_squared < fling_range_squared ) + { + level.riotshield_fling_enemies[ level.riotshield_fling_enemies.size ] = zombies[ i ]; + dist_mult = ( fling_range_squared - test_range_squared ) / fling_range_squared; + fling_vec = vectornormalize( test_origin - view_pos ); + if ( test_range_squared >= 5000 ) + { + fling_vec += vectornormalize( test_origin - radial_origin ); + } + fling_vec = ( fling_vec[ 0 ], fling_vec[ 1 ], abs( fling_vec[ 2 ] ) ); + fling_vec = vectorScale( fling_vec, 100 + ( 100 * dist_mult ) ); + level.riotshield_fling_vecs[ level.riotshield_fling_vecs.size ] = fling_vec; + zombies[ i ] riotshield_debug_print( "fling", ( 0, 0, 1 ) ); + i++; + continue; + } + else + { + level.riotshield_knockdown_enemies[ level.riotshield_knockdown_enemies.size ] = zombies[ i ]; + level.riotshield_knockdown_gib[ level.riotshield_knockdown_gib.size ] = 0; + zombies[ i ] riotshield_debug_print( "knockdown", ( 0, 0, 1 ) ); + } + } + i++; + } +} + +riotshield_network_choke() +{ + level.riotshield_network_choke_count++; + if ( level.riotshield_network_choke_count % 10 ) + { + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + } +} + +riotshield_melee() +{ + if ( !isDefined( level.riotshield_knockdown_enemies ) ) + { + level.riotshield_knockdown_enemies = []; + level.riotshield_knockdown_gib = []; + level.riotshield_fling_enemies = []; + level.riotshield_fling_vecs = []; + } + self riotshield_get_enemies_in_range(); + shield_damage = 0; + level.riotshield_network_choke_count = 0; + i = 0; + while ( i < level.riotshield_fling_enemies.size ) + { + riotshield_network_choke(); + if ( isDefined( level.riotshield_fling_enemies[ i ] ) ) + { + level.riotshield_fling_enemies[ i ] thread riotshield_fling_zombie( self, level.riotshield_fling_vecs[ i ], i ); + shield_damage += level.zombie_vars[ "riotshield_fling_damage_shield" ]; + } + i++; + } + i = 0; + while ( i < level.riotshield_knockdown_enemies.size ) + { + riotshield_network_choke(); + level.riotshield_knockdown_enemies[ i ] thread riotshield_knockdown_zombie( self, level.riotshield_knockdown_gib[ i ] ); + shield_damage += level.zombie_vars[ "riotshield_knockdown_damage_shield" ]; + i++; + } + level.riotshield_knockdown_enemies = []; + level.riotshield_knockdown_gib = []; + level.riotshield_fling_enemies = []; + level.riotshield_fling_vecs = []; + if ( shield_damage ) + { + self player_damage_shield( shield_damage, 0 ); + } +} + +trackstuckzombies() +{ + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "deployed_riotshield" ); + if ( isDefined( self.riotshieldentity ) ) + { + self thread watchstuckzombies(); + } + } +} + +attack_shield( shield ) +{ + self endon( "death" ); + shield.owner endon( "death" ); + shield.owner endon( "disconnect" ); + shield.owner endon( "start_riotshield_deploy" ); + shield.owner endon( "destroy_riotshield" ); + if ( isDefined( self.doing_shield_attack ) && self.doing_shield_attack ) + { + return 0; + } + self.old_origin = self.origin; + if ( getDvar( "zombie_shield_attack_freq" ) == "" ) + { + setdvar( "zombie_shield_attack_freq", "15" ); + } + freq = getDvarInt( "zombie_shield_attack_freq" ); + self.doing_shield_attack = 1; + self.enemyoverride[ 0 ] = shield.origin; + self.enemyoverride[ 1 ] = shield; + wait ( randomint( 100 ) / 100 ); + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", self.animname ); + attackanim = "zm_riotshield_melee"; + if ( !self.has_legs ) + { + attackanim += "_crawl"; + } + self orientmode( "face point", shield.origin ); + self animscripted( self.origin, flat_angle( vectorToAngle( shield.origin - self.origin ) ), attackanim ); + if ( isDefined( shield.owner.player_shield_apply_damage ) ) + { + shield.owner [[ shield.owner.player_shield_apply_damage ]]( 100, 0 ); + } + else + { + shield.owner player_damage_shield( 100, 0 ); + } + self thread attack_shield_stop( shield ); + wait ( randomint( 100 ) / 100 ); + self.doing_shield_attack = 0; + self orientmode( "face default" ); +} + +attack_shield_stop( shield ) +{ + self notify( "attack_shield_stop" ); + self endon( "attack_shield_stop" ); + self endon( "death" ); + shield waittill( "death" ); + self stopanimscripted(); + if ( isDefined( self.doing_shield_attack ) && self.doing_shield_attack ) + { + breachanim = "zm_riotshield_breakthrough"; + if ( !self.has_legs ) + { + breachanim += "_crawl"; + } + self animscripted( self.origin, flat_angle( self.angles ), breachanim ); + } +} + +window_notetracks( msg, player ) +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( msg, notetrack ); + if ( notetrack == "end" ) + { + return; + } + if ( notetrack == "fire" ) + { + player player_damage_shield( 100, 0 ); + } + } +} + +watchstuckzombies() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "start_riotshield_deploy" ); + self endon( "destroy_riotshield" ); + self endon( "deployed_riotshield" ); + level endon( "intermission" ); + self.riotshieldentity maps/mp/zombies/_zm_equipment::item_attract_zombies(); +} + +riotshield_active() +{ + return self maps/mp/zombies/_zm_equipment::is_equipment_active( "riotshield_zm" ); +} + +riotshield_debug_print( msg, color ) +{ +/# + if ( !getDvarInt( #"BF480CE9" ) ) + { + return; + } + if ( !isDefined( color ) ) + { + color = ( 0, 0, 1 ); + } + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 60 ), msg, color, 1, 1, 40 ); +#/ +} + +shield_zombie_attract_func( poi ) +{ +} + +shield_zombie_arrive_func( poi ) +{ + self endon( "death" ); + self endon( "zombie_acquire_enemy" ); + self endon( "path_timer_done" ); + self waittill( "goal" ); + if ( isDefined( poi.owner ) ) + { + poi.owner player_damage_shield( 100, 0 ); + if ( isDefined( poi.owner.player_shield_apply_damage ) ) + { + poi.owner [[ poi.owner.player_shield_apply_damage ]]( 100, 0 ); + } + } +} + +createriotshieldattractor() +{ + self create_zombie_point_of_interest( 50, 8, 0, 1, ::shield_zombie_attract_func, ::shield_zombie_arrive_func ); + self thread create_zombie_point_of_interest_attractor_positions( 4, 15, 15 ); + return get_zombie_point_of_interest( self.origin ); +} + +riotshield_zombie_damage_response( mod, hit_location, hit_origin, player, amount ) +{ + if ( self is_riotshield_damage( mod, player, amount ) ) + { + self riotshield_damage( amount ); + return 1; + } + return 0; +} + +watchriotshieldattractor() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "start_riotshield_deploy" ); + self endon( "destroy_riotshield" ); + self endon( "deployed_riotshield" ); + poi = self.riotshieldentity createriotshieldattractor(); +} + +trackriotshieldattractor() +{ + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "deployed_riotshield" ); + self thread watchriotshieldattractor(); + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc new file mode 100644 index 0000000..48ea6b2 --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc @@ -0,0 +1,120 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + registerclientfield( "toplayer", "tazer_flourish", 1, 1, "int" ); + register_melee_weapon_for_level( "tazer_knuckles_zm" ); + if ( isDefined( level.tazer_cost ) ) + { + cost = level.tazer_cost; + } + else + { + cost = 6000; + } + level.use_tazer_impact_fx = 0; + maps/mp/zombies/_zm_melee_weapon::init( "tazer_knuckles_zm", "zombie_tazer_flourish", "knife_ballistic_no_melee_zm", "knife_ballistic_no_melee_upgraded_zm", cost, "tazer_upgrade", &"ZOMBIE_WEAPON_TAZER_BUY", "tazerknuckles", ::tazer_flourish_fx ); + maps/mp/zombies/_zm_weapons::add_retrievable_knife_init_name( "knife_ballistic_no_melee" ); + maps/mp/zombies/_zm_weapons::add_retrievable_knife_init_name( "knife_ballistic_no_melee_upgraded" ); + maps/mp/zombies/_zm_spawner::add_cusom_zombie_spawn_logic( ::watch_bodily_functions ); + level._effect[ "fx_zmb_taser_vomit" ] = loadfx( "maps/zombie/fx_zmb_taser_vomit" ); + level._effect[ "fx_zmb_taser_flourish" ] = loadfx( "weapon/taser/fx_taser_knuckles_anim_zmb" ); + if ( level.script != "zm_transit" ) + { + level._effect[ "fx_zmb_tazer_impact" ] = loadfx( "weapon/taser/fx_taser_knuckles_impact_zmb" ); + level.use_tazer_impact_fx = 1; + } + level.tazer_flourish_delay = 0,5; +} + +watch_bodily_functions() +{ + if ( isDefined( self.isscreecher ) || self.isscreecher && isDefined( self.is_avogadro ) && self.is_avogadro ) + { + return; + } + while ( isDefined( self ) && isalive( self ) ) + { + self waittill( "damage", amount, attacker, direction_vec, point, type ); + if ( !isDefined( self ) ) + { + return; + } + if ( !isDefined( attacker ) || !isplayer( attacker ) ) + { + continue; + } + while ( type != "MOD_MELEE" ) + { + continue; + } + if ( !attacker hasweapon( "tazer_knuckles_zm" ) || isDefined( self.hasriotshieldequipped ) && self.hasriotshieldequipped ) + { + continue; + } + ch = randomint( 100 ); + if ( ch < 4 ) + { + playfxontag( level._effect[ "fx_zmb_taser_vomit" ], self, "j_neck" ); + } + if ( level.use_tazer_impact_fx ) + { + tags = []; + tags[ 0 ] = "J_Head"; + tags[ 1 ] = "J_Neck"; + playfxontag( level._effect[ "fx_zmb_tazer_impact" ], self, random( tags ) ); + } + } +} + +onplayerconnect() +{ + self thread onplayerspawned(); +} + +onplayerspawned() +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "spawned_player" ); + self thread watchtazerknucklemelee(); + } +} + +watchtazerknucklemelee() +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "weapon_melee", weapon ); + if ( weapon == "tazer_knuckles_zm" ) + { + self tazerknuckle_melee(); + } + } +} + +tazerknuckle_melee() +{ +} + +tazer_flourish_fx() +{ + self waittill( "weapon_change", newweapon ); + if ( newweapon == "zombie_tazer_flourish" ) + { + self endon( "weapon_change" ); + wait level.tazer_flourish_delay; + self thread maps/mp/zombies/_zm_audio::playerexert( "hitmed" ); + self setclientfieldtoplayer( "tazer_flourish", 1 ); + wait_network_frame(); + self setclientfieldtoplayer( "tazer_flourish", 0 ); + } +} diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weapon_locker.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weapon_locker.gsc new file mode 100644 index 0000000..712805a --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weapon_locker.gsc @@ -0,0 +1,338 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +main() +{ + if ( !isDefined( level.weapon_locker_map ) ) + { + level.weapon_locker_map = level.script; + } + level.weapon_locker_online = sessionmodeisonlinegame(); + weapon_lockers = getstructarray( "weapons_locker", "targetname" ); + array_thread( weapon_lockers, ::triggerweaponslockerwatch ); +} + +wl_has_stored_weapondata() +{ + if ( level.weapon_locker_online ) + { + return self has_stored_weapondata( level.weapon_locker_map ); + } + else + { + return isDefined( self.stored_weapon_data ); + } +} + +wl_get_stored_weapondata() +{ + if ( level.weapon_locker_online ) + { + return self get_stored_weapondata( level.weapon_locker_map ); + } + else + { + return self.stored_weapon_data; + } +} + +wl_clear_stored_weapondata() +{ + if ( level.weapon_locker_online ) + { + self clear_stored_weapondata( level.weapon_locker_map ); + } + else + { + self.stored_weapon_data = undefined; + } +} + +wl_set_stored_weapondata( weapondata ) +{ + if ( level.weapon_locker_online ) + { + self set_stored_weapondata( weapondata, level.weapon_locker_map ); + } + else + { + self.stored_weapon_data = weapondata; + } +} + +triggerweaponslockerwatch() +{ + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = self.origin; + if ( isDefined( self.script_angles ) ) + { + unitrigger_stub.angles = self.script_angles; + } + else + { + unitrigger_stub.angles = self.angles; + } + unitrigger_stub.script_angles = unitrigger_stub.angles; + if ( isDefined( self.script_length ) ) + { + unitrigger_stub.script_length = self.script_length; + } + else + { + unitrigger_stub.script_length = 16; + } + if ( isDefined( self.script_width ) ) + { + unitrigger_stub.script_width = self.script_width; + } + else + { + unitrigger_stub.script_width = 32; + } + if ( isDefined( self.script_height ) ) + { + unitrigger_stub.script_height = self.script_height; + } + else + { + unitrigger_stub.script_height = 64; + } + unitrigger_stub.origin -= anglesToRight( unitrigger_stub.angles ) * ( unitrigger_stub.script_length / 2 ); + unitrigger_stub.targetname = "weapon_locker"; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.clientfieldname = "weapon_locker"; + maps/mp/zombies/_zm_unitrigger::unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + unitrigger_stub.prompt_and_visibility_func = ::triggerweaponslockerthinkupdateprompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::triggerweaponslockerthink ); +} + +triggerweaponslockerisvalidweapon( weaponname ) +{ + weaponname = get_base_weapon_name( weaponname, 1 ); + if ( !is_weapon_included( weaponname ) ) + { + return 0; + } + if ( is_offhand_weapon( weaponname ) || is_limited_weapon( weaponname ) ) + { + return 0; + } + return 1; +} + +triggerweaponslockerisvalidweaponpromptupdate( player, weaponname ) +{ + retrievingweapon = player wl_has_stored_weapondata(); + if ( !retrievingweapon ) + { + weaponname = player get_nonalternate_weapon( weaponname ); + if ( !triggerweaponslockerisvalidweapon( weaponname ) ) + { + self sethintstring( &"ZOMBIE_WEAPON_LOCKER_DENY" ); + } + else + { + self sethintstring( &"ZOMBIE_WEAPON_LOCKER_STORE" ); + } + } + else + { + weapondata = player wl_get_stored_weapondata(); + if ( isDefined( level.remap_weapon_locker_weapons ) ) + { + weapondata = remap_weapon( weapondata, level.remap_weapon_locker_weapons ); + } + weapontogive = weapondata[ "name" ]; + primaries = player getweaponslistprimaries(); + maxweapons = get_player_weapon_limit( player ); + weaponname = player get_nonalternate_weapon( weaponname ); + if ( isDefined( primaries ) || primaries.size >= maxweapons && weapontogive == weaponname ) + { + if ( !triggerweaponslockerisvalidweapon( weaponname ) ) + { + self sethintstring( &"ZOMBIE_WEAPON_LOCKER_DENY" ); + return; + } + } + self sethintstring( &"ZOMBIE_WEAPON_LOCKER_GRAB" ); + } +} + +triggerweaponslockerthinkupdateprompt( player ) +{ + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + return 1; +} + +triggerweaponslockerthink() +{ + self.parent_player thread triggerweaponslockerweaponchangethink( self ); + while ( 1 ) + { + self waittill( "trigger", player ); + retrievingweapon = player wl_has_stored_weapondata(); + if ( !retrievingweapon ) + { + curweapon = player getcurrentweapon(); + curweapon = player maps/mp/zombies/_zm_weapons::switch_from_alt_weapon( curweapon ); + while ( !triggerweaponslockerisvalidweapon( curweapon ) ) + { + continue; + } + weapondata = player maps/mp/zombies/_zm_weapons::get_player_weapondata( player ); + player wl_set_stored_weapondata( weapondata ); +/# + assert( curweapon == weapondata[ "name" ], "weapon data does not match" ); +#/ + player takeweapon( curweapon ); + primaries = player getweaponslistprimaries(); + if ( isDefined( primaries[ 0 ] ) ) + { + player switchtoweapon( primaries[ 0 ] ); + } + else + { + player maps/mp/zombies/_zm_weapons::give_fallback_weapon(); + } + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + player playsoundtoplayer( "evt_fridge_locker_close", player ); + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "weapon_storage" ); + } + else + { + curweapon = player getcurrentweapon(); + primaries = player getweaponslistprimaries(); + weapondata = player wl_get_stored_weapondata(); + if ( isDefined( level.remap_weapon_locker_weapons ) ) + { + weapondata = remap_weapon( weapondata, level.remap_weapon_locker_weapons ); + } + weapontogive = weapondata[ "name" ]; + while ( !triggerweaponslockerisvalidweapon( weapontogive ) ) + { + player playlocalsound( level.zmb_laugh_alias ); + player wl_clear_stored_weapondata(); + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + } + curweap_base = maps/mp/zombies/_zm_weapons::get_base_weapon_name( curweapon, 1 ); + weap_base = maps/mp/zombies/_zm_weapons::get_base_weapon_name( weapontogive, 1 ); + while ( player has_weapon_or_upgrade( weap_base ) && weap_base != curweap_base ) + { + self sethintstring( &"ZOMBIE_WEAPON_LOCKER_DENY" ); + wait 3; + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + } + maxweapons = get_player_weapon_limit( player ); + if ( isDefined( primaries ) || primaries.size >= maxweapons && weapontogive == curweapon ) + { + curweapon = player maps/mp/zombies/_zm_weapons::switch_from_alt_weapon( curweapon ); + while ( !triggerweaponslockerisvalidweapon( curweapon ) ) + { + self sethintstring( &"ZOMBIE_WEAPON_LOCKER_DENY" ); + wait 3; + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + } + curweapondata = player maps/mp/zombies/_zm_weapons::get_player_weapondata( player ); + player takeweapon( curweapondata[ "name" ] ); + player maps/mp/zombies/_zm_weapons::weapondata_give( weapondata ); + player wl_clear_stored_weapondata(); + player wl_set_stored_weapondata( curweapondata ); + player switchtoweapon( weapondata[ "name" ] ); + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + } + else + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "wall_withdrawl" ); + player wl_clear_stored_weapondata(); + player maps/mp/zombies/_zm_weapons::weapondata_give( weapondata ); + player switchtoweapon( weapondata[ "name" ] ); + self triggerweaponslockerisvalidweaponpromptupdate( player, player getcurrentweapon() ); + } + level notify( "weapon_locker_grab" ); + player playsoundtoplayer( "evt_fridge_locker_open", player ); + } + wait 0,5; + } +} + +triggerweaponslockerweaponchangethink( trigger ) +{ + self endon( "disconnect" ); + self endon( "death" ); + trigger endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "weapon_change", newweapon ); + trigger triggerweaponslockerisvalidweaponpromptupdate( self, newweapon ); + } +} + +add_weapon_locker_mapping( fromweapon, toweapon ) +{ + if ( !isDefined( level.remap_weapon_locker_weapons ) ) + { + level.remap_weapon_locker_weapons = []; + } + level.remap_weapon_locker_weapons[ fromweapon ] = toweapon; +} + +remap_weapon( weapondata, maptable ) +{ + name = get_base_name( weapondata[ "name" ] ); + att = get_attachment_name( weapondata[ "name" ] ); + if ( isDefined( maptable[ name ] ) ) + { + weapondata[ "name" ] = maptable[ name ]; + name = weapondata[ "name" ]; + if ( is_weapon_upgraded( name ) ) + { + if ( isDefined( att ) && weapon_supports_attachments( name ) ) + { + base = get_base_weapon_name( name, 1 ); + if ( !weapon_supports_this_attachment( base, att ) ) + { + att = random_attachment( base ); + } + weapondata[ "name" ] = weapondata[ "name" ] + "+" + att; + } + else + { + if ( weapon_supports_default_attachment( name ) ) + { + att = default_attachment( name ); + weapondata[ "name" ] = weapondata[ "name" ] + "+" + att; + } + } + } + } + else + { + return weapondata; + } + name = weapondata[ "name" ]; + dw_name = weapondualwieldweaponname( name ); + alt_name = weaponaltweaponname( name ); + if ( name != "none" ) + { + weapondata[ "clip" ] = int( min( weapondata[ "clip" ], weaponclipsize( name ) ) ); + weapondata[ "stock" ] = int( min( weapondata[ "stock" ], weaponmaxammo( name ) ) ); + } + if ( dw_name != "none" ) + { + weapondata[ "lh_clip" ] = int( min( weapondata[ "lh_clip" ], weaponclipsize( dw_name ) ) ); + } + if ( alt_name != "none" ) + { + weapondata[ "alt_clip" ] = int( min( weapondata[ "alt_clip" ], weaponclipsize( alt_name ) ) ); + weapondata[ "alt_stock" ] = int( min( weapondata[ "alt_stock" ], weaponmaxammo( alt_name ) ) ); + } + weapondata[ "dw_name" ] = dw_name; + weapondata[ "alt_name" ] = alt_name; + return weapondata; +} diff --git a/zm_transit_patch/readme.md b/zm_transit_patch/readme.md index 8a5a05a..ad5a877 100644 --- a/zm_transit_patch/readme.md +++ b/zm_transit_patch/readme.md @@ -15,6 +15,54 @@ zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc ### The following scripts compile but cause a minidump or other severe error: +### The following scripts are not checked yet, uploaded to setup a baseline: +``` +zm_transit_patch/maps/mp/gametypes_zm/zmeat.gsc +zm_transit_patch/maps/mp/gametypes_zm/zstandard.gsc + +zm_transit_patch/maps/mp/zombies/_zm_ai_avogadro.gsc +zm_transit_patch/maps/mp/zombies/_zm_ai_screecher.gsc +zm_transit_patch/maps/mp/zombies/_zm_banking.gsc +zm_transit_patch/maps/mp/zombies/_zm_equip_electrictrap.gsc +zm_transit_patch/maps/mp/zombies/_zm_equip_turret.gsc +zm_transit_patch/maps/mp/zombies/_zm_game_module_grief.gsc +zm_transit_patch/maps/mp/zombies/_zm_game_module_meat.gsc +zm_transit_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc +zm_transit_patch/maps/mp/zombies/_zm_game_module_standard.gsc +zm_transit_patch/maps/mp/zombies/_zm_game_module_utility.gsc +zm_transit_patch/maps/mp/zombies/_zm_melee_weapon.gsc +zm_transit_patch/maps/mp/zombies/_zm_riotshield.gsc +zm_transit_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc +zm_transit_patch/maps/mp/zombies/_zm_weap_bowie.gsc +zm_transit_patch/maps/mp/zombies/_zm_weap_claymore.gsc +zm_transit_patch/maps/mp/zombies/_zm_weap_emp_bomb.gsc +zm_transit_patch/maps/mp/zombies/_zm_weap_riotshield.gsc +zm_transit_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc +zm_transit_patch/maps/mp/zombies/_zm_weapon_locker.gsc + +zm_transit_patch/maps/mp/zm_transit.gsc +zm_transit_patch/maps/mp/zm_transit_achievement.gsc +zm_transit_patch/maps/mp/zm_transit_ai_screecher.gsc +zm_transit_patch/maps/mp/zm_transit_ambush.gsc +zm_transit_patch/maps/mp/zm_transit_automaton.gsc +zm_transit_patch/maps/mp/zm_transit_buildables.gsc +zm_transit_patch/maps/mp/zm_transit_bus.gsc +zm_transit_patch/maps/mp/zm_transit_cling.gsc +zm_transit_patch/maps/mp/zm_transit_distance_tracking.gsc +zm_transit_patch/maps/mp/zm_transit_ffotd.gsc +zm_transit_patch/maps/mp/zm_transit_fx.gsc +zm_transit_patch/maps/mp/zm_transit_gamemodes.gsc +zm_transit_patch/maps/mp/zm_transit_grief_farm.gsc +zm_transit_patch/maps/mp/zm_transit_grief_station.gsc +zm_transit_patch/maps/mp/zm_transit_grief_town.gsc +zm_transit_patch/maps/mp/zm_transit_lava.gsc +zm_transit_patch/maps/mp/zm_transit_openings.gsc +zm_transit_patch/maps/mp/zm_transit_power.gsc +zm_transit_patch/maps/mp/zm_transit_sq.gsc +zm_transit_patch/maps/mp/zm_transit_standard_farm.gsc +zm_transit_patch/maps/mp/zm_transit_standard_town.gsc +``` + ### notes: ``` zm_transit_utility.gsc can be recompiled to fix tombstone