diff --git a/zm_buried_patch/maps/mp/gametypes_zm/zcleansed.gsc b/zm_buried_patch/maps/mp/gametypes_zm/zcleansed.gsc new file mode 100644 index 0000000..7713802 --- /dev/null +++ b/zm_buried_patch/maps/mp/gametypes_zm/zcleansed.gsc @@ -0,0 +1,2154 @@ +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_weap_cymbal_monkey; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/gametypes_zm/_globallogic_utils; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm; +#include maps/mp/gametypes_zm/_weapons; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/gametypes_zm/_hud; +#include maps/mp/_utility; + +main() +{ + level.using_zombie_powerups = 1; + level._game_mode_powerup_zombie_grab = ::zcleansed_zombie_powerup_grab; + level._zombiemode_powerup_grab = ::zcleansed_powerup_grab; + level._powerup_timeout_custom_time = ::zcleansed_powerup_custom_time_logic; + level._powerup_grab_check = ::powerup_can_player_grab; + setdvar( "aim_target_player_enabled", 1 ); + maps/mp/gametypes_zm/_zm_gametype::main(); + setscoreboardcolumns( "none", "score", "kills", "downs", "headshots" ); + level.cymbal_monkey_dual_view = 1; + level.onprecachegametype = ::onprecachegametype; + level.onstartgametype = ::onstartgametype; + level.custom_end_screen = ::custom_end_screen; + level._game_module_custom_spawn_init_func = ::maps/mp/gametypes_zm/_zm_gametype::custom_spawn_init_func; + level._game_module_state_update_func = ::maps/mp/zombies/_zm_stats::survival_classic_custom_stat_update; + level._effect[ "human_disappears" ] = loadfx( "maps/zombie/fx_zmb_returned_spawn_puff" ); + level._effect[ "zombie_disappears" ] = loadfx( "maps/zombie/fx_zmb_returned_spawn_puff" ); + level.human_finish_bonus_points = 250; + level.human_bonus_points = 10; + level.zombie_penalty_points = 5; + level.human_bonus_period = 1; + level.zombie_penalty_period = 10; + level.zombie_player_kill_points = 50; + level.human_player_kill_points = 50; + level.human_player_suicide_penalty = 0; + level.score_rank_bonus = array( 1,5, 0,75, 0,5, 0,25 ); + if ( isDefined( level.should_use_cia ) && level.should_use_cia ) + { + level.characterindex = 0; + } + else + { + level.characterindex = 1; + } + level.graceperiodfunc = ::waitforhumanselection; + level.customalivecheck = ::cleansed_alive_check; + level thread onplayerconnect(); + maps/mp/gametypes_zm/_zm_gametype::post_gametype_main( "zcleansed" ); + init_cleansed_powerup_fx(); +} + +onprecachegametype() +{ + level.playersuicideallowed = 1; + level.canplayersuicide = ::canplayersuicide; + level.suicide_weapon = "death_self_zm"; + precacheitem( "death_self_zm" ); + precachemodel( "zombie_pickup_perk_bottle" ); + precache_trophy(); + precacheshader( "faction_cdc" ); + precacheshader( "faction_cia" ); + init_default_zcleansed_powerups(); + maps/mp/zombies/_zm_turned::init(); + level thread maps/mp/gametypes_zm/_zm_gametype::init(); + maps/mp/gametypes_zm/_zm_gametype::rungametypeprecache( "zcleansed" ); + init_cleansed_powerups(); +} + +init_default_zcleansed_powerups() +{ + maps/mp/zombies/_zm_powerups::include_zombie_powerup( "the_cure" ); + maps/mp/zombies/_zm_powerups::include_zombie_powerup( "blue_monkey" ); + maps/mp/zombies/_zm_powerups::add_zombie_powerup( "the_cure", "zombie_pickup_perk_bottle", &"ZOMBIE_POWERUP_MAX_AMMO", ::maps/mp/zombies/_zm_powerups::func_should_never_drop, 0, 0, 1 ); + maps/mp/zombies/_zm_powerups::add_zombie_powerup( "blue_monkey", level.cymbal_monkey_model, &"ZOMBIE_POWERUP_MAX_AMMO", ::maps/mp/zombies/_zm_powerups::func_should_never_drop, 1, 0, 0 ); +} + +init_cleansed_powerup_fx() +{ + level._effect[ "powerup_on_caution" ] = loadfx( "misc/fx_zombie_powerup_on_blue" ); +} + +onstartgametype() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_classic_gametype(); + level thread makefindfleshstructs(); + flag_init( "start_supersprint" ); + level.custom_player_fake_death = ::empty; + level.custom_player_fake_death_cleanup = ::empty; + level.overrideplayerdamage = ::cleanseddamagechecks; + level.playerlaststand_func = ::cleansed_player_laststand; + level.onendgame = ::cleansedonendgame; + level.ontimelimit = ::cleansedontimelimit; + level.powerup_player_valid = ::cleansed_alive_check; + level.nml_zombie_spawners = level.zombie_spawners; + level.dodge_score_highlight = 1; + level.dodge_show_revive_icon = 1; + level.custom_max_zombies = 6; + level.custom_zombie_health = 200; + level.nml_dogs_enabled = 0; + level.timercountdown = 1; + level.initial_spawn = 1; + level.nml_reaction_interval = 2000; + level.nml_min_reaction_dist_sq = 1024; + level.nml_max_reaction_dist_sq = 5760000; + level.min_humans = 1; + level.no_end_game_check = 1; + level.zombie_health = level.zombie_vars[ "zombie_health_start" ]; + level._get_game_module_players = undefined; + level.powerup_drop_count = 0; + level.is_zombie_level = 1; + level.player_becomes_zombie = ::onzombifyplayer; + level.player_kills_player = ::player_kills_player; + set_zombie_var( "zombify_player", 1 ); + set_zombie_var( "penalty_died", 1 ); + set_zombie_var( "penalty_downed", 1 ); + while ( isDefined( level._zcleansed_weapon_progression ) ) + { + i = 0; + while ( i < level._zcleansed_weapon_progression.size ) + { + addguntoprogression( level._zcleansed_weapon_progression[ i ] ); + i++; + } + } + maps/mp/gametypes_zm/_zm_gametype::rungametypemain( "zcleansed", ::zcleansed_logic ); +} + +turnedlog( text ) +{ +/# + println( "TURNEDLOG: " + text + "\n" ); +#/ +} + +cleansed_player_laststand( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ +/# +#/ + self maps/mp/zombies/_zm_score::player_downed_penalty(); + if ( isDefined( attacker ) && isplayer( attacker ) && attacker != self ) + { + if ( isDefined( self.hide_owner ) && self.hide_owner ) + { + attacker notify( "invisible_player_killed" ); + } + } + if ( isDefined( self.is_zombie ) && self.is_zombie && deathanimduration == 0 ) + { + self stopsounds(); + } +} + +cleansed_alive_check( player ) +{ + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( player.nuked ) && !player.nuked && isDefined( player.is_in_process_of_zombify ) || player.is_in_process_of_zombify && isDefined( player.is_in_process_of_humanify ) && player.is_in_process_of_humanify ) + { + return 0; + } + return 1; +} + +cleanseddamagechecks( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( self.is_in_process_of_zombify ) || self.is_in_process_of_zombify && isDefined( self.is_in_process_of_humanify ) && self.is_in_process_of_humanify ) + { + return 0; + } + if ( isDefined( self.nuked ) && self.nuked && eattacker != self.nuker && eattacker != self ) + { + return 0; + } + if ( isDefined( eattacker ) && isplayer( eattacker ) && eattacker != self ) + { + if ( eattacker.team == self.team ) + { + return 0; + } + if ( isDefined( eattacker.is_zombie ) ) + { + if ( isDefined( self.is_zombie ) ) + { + if ( eattacker.is_zombie == self.is_zombie ) + { + return 0; + } + } + } + if ( !cleansed_alive_check( eattacker ) ) + { + return 0; + } + if ( isDefined( self.nuked ) && self.nuked && isDefined( self.nuker ) && eattacker != self.nuker ) + { + return 0; + } + if ( isDefined( self.is_zombie ) && self.is_zombie && sweapon == "cymbal_monkey_zm" && smeansofdeath != "MOD_IMPACT" ) + { + level notify( "killed_by_decoy" ); + idamage = self.health + 666; + } + else + { + self.last_player_attacker = eattacker; + } +/# +#/ + eattacker thread maps/mp/gametypes_zm/_weapons::checkhit( sweapon ); + if ( !eattacker.is_zombie && eattacker maps/mp/zombies/_zm_powerups::is_insta_kill_active() ) + { + idamage = self.health + 666; + } + } + if ( isDefined( eattacker.is_zombie ) && eattacker.is_zombie ) + { + self playsoundtoplayer( "evt_player_swiped", self ); + } + return self maps/mp/zombies/_zm::player_damage_override( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); +} + +custom_end_screen() +{ + players = get_players(); + winner = players[ 0 ]; + _a272 = players; + _k272 = getFirstArrayKey( _a272 ); + while ( isDefined( _k272 ) ) + { + player = _a272[ _k272 ]; + if ( isDefined( winner ) && player.score > winner.score ) + { + winner = player; + } + _k272 = getNextArrayKey( _a272, _k272 ); + } + if ( isDefined( level.last_human_standing ) ) + { + i = 0; + while ( i < players.size ) + { + players[ i ].bonus_msg_hud = newclienthudelem( players[ i ] ); + players[ i ].bonus_msg_hud.alignx = "center"; + players[ i ].bonus_msg_hud.aligny = "middle"; + players[ i ].bonus_msg_hud.horzalign = "center"; + players[ i ].bonus_msg_hud.vertalign = "middle"; + players[ i ].bonus_msg_hud.y -= 130; + if ( players[ i ] issplitscreen() ) + { + players[ i ].bonus_msg_hud.y += 70; + } + players[ i ].bonus_msg_hud.foreground = 1; + players[ i ].bonus_msg_hud.fontscale = 5; + players[ i ].bonus_msg_hud.alpha = 0; + players[ i ].bonus_msg_hud.color = ( 0, 0, 0 ); + players[ i ].bonus_msg_hud.hidewheninmenu = 1; + players[ i ].bonus_msg_hud.font = "default"; + players[ i ].bonus_msg_hud settext( &"ZOMBIE_CLEANSED_SURVIVING_HUMAN_BONUS", level.last_human_standing.name ); + players[ i ].bonus_msg_hud changefontscaleovertime( 0,25 ); + players[ i ].bonus_msg_hud fadeovertime( 0,25 ); + players[ i ].bonus_msg_hud.alpha = 1; + players[ i ].bonus_msg_hud.fontscale = 2; + i++; + } + wait 3,25; + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ].bonus_msg_hud ) ) + { + players[ i ].bonus_msg_hud changefontscaleovertime( 0,5 ); + players[ i ].bonus_msg_hud fadeovertime( 0,5 ); + players[ i ].bonus_msg_hud.alpha = 0; + players[ i ].bonus_msg_hud.fontscale = 5; + } + i++; + } + wait 0,5; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ].bonus_msg_hud ) ) + { + players[ i ].bonus_msg_hud destroy(); + } + players[ i ].game_over_hud = newclienthudelem( players[ i ] ); + players[ i ].game_over_hud.alignx = "center"; + players[ i ].game_over_hud.aligny = "middle"; + players[ i ].game_over_hud.horzalign = "center"; + players[ i ].game_over_hud.vertalign = "middle"; + players[ i ].game_over_hud.y -= 130; + players[ i ].game_over_hud.foreground = 1; + players[ i ].game_over_hud.fontscale = 3; + players[ i ].game_over_hud.alpha = 0; + players[ i ].game_over_hud.color = ( 0, 0, 0 ); + players[ i ].game_over_hud.hidewheninmenu = 1; + players[ i ].game_over_hud settext( &"ZOMBIE_GAME_OVER" ); + players[ i ].game_over_hud fadeovertime( 1 ); + players[ i ].game_over_hud.alpha = 1; + if ( players[ i ] issplitscreen() ) + { + players[ i ].game_over_hud.fontscale = 2; + players[ i ].game_over_hud.y += 40; + } + players[ i ].survived_hud = newclienthudelem( players[ i ] ); + players[ i ].survived_hud.alignx = "center"; + players[ i ].survived_hud.aligny = "middle"; + players[ i ].survived_hud.horzalign = "center"; + players[ i ].survived_hud.vertalign = "middle"; + players[ i ].survived_hud.y -= 100; + players[ i ].survived_hud.foreground = 1; + players[ i ].survived_hud.fontscale = 2; + players[ i ].survived_hud.alpha = 0; + players[ i ].survived_hud.color = ( 0, 0, 0 ); + players[ i ].survived_hud.hidewheninmenu = 1; + if ( players[ i ] issplitscreen() ) + { + players[ i ].survived_hud.fontscale = 1,5; + players[ i ].survived_hud.y += 40; + } + winner_text = &"ZOMBIE_CLEANSED_WIN"; + loser_text = &"ZOMBIE_CLEANSED_LOSE"; + if ( isDefined( level.host_ended_game ) && level.host_ended_game ) + { + players[ i ].survived_hud settext( &"MP_HOST_ENDED_GAME" ); + } + else + { + if ( players[ i ] == winner ) + { + players[ i ].survived_hud settext( winner_text ); + break; + } + else + { + players[ i ].survived_hud settext( loser_text ); + } + } + players[ i ].survived_hud fadeovertime( 1 ); + players[ i ].survived_hud.alpha = 1; + i++; + } +} + +allow_player_movement( allowed ) +{ + level.player_movement_suppressed = !allowed; + _a396 = get_players(); + _k396 = getFirstArrayKey( _a396 ); + while ( isDefined( _k396 ) ) + { + player = _a396[ _k396 ]; + if ( isDefined( player.in_zombify_call ) && !player.in_zombify_call ) + { + player freezecontrolswrapper( level.player_movement_suppressed ); + } + _k396 = getNextArrayKey( _a396, _k396 ); + } +} + +watch_game_start() +{ + level.start_audio_allowed = 1; + level waittill( "cleansed_game_started" ); + level.start_audio_allowed = 0; +} + +listen_to_the_doctor_pregame() +{ + thread watch_game_start(); + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_start_single_0", undefined, undefined, 1, 4 ); + wait 4; + if ( level.start_audio_allowed ) + { + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_start_2", undefined, undefined, 1, 8 ); + wait 8; + } + if ( level.start_audio_allowed ) + { + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_start_3", undefined, undefined, 1, 8 ); + wait 4; + } + if ( level.start_audio_allowed ) + { + level waittill( "cleansed_game_started" ); + } +} + +listen_to_the_doctor_started() +{ + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_cure_found_line", undefined, undefined, 1, 8 ); + wait 8; +} + +listen_to_the_doctor_monkeys() +{ + level endon( "end_game" ); + while ( 1 ) + { + level waittill( "killed_by_decoy", killer, killee ); + while ( !isplayer( killee ) ) + { + continue; + } + if ( isDefined( level.playing_turned_kill_vo ) && level.playing_turned_kill_vo ) + { + continue; + } + if ( isDefined( killer.heard_dr_monkey_killer ) && !killer.heard_dr_monkey_killer ) + { + level.playing_turned_kill_vo = 1; + killer.heard_dr_monkey_killer = 1; + killer thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "dr_monkey_killer", undefined, undefined, 0 ); + } + if ( isDefined( killee.heard_dr_monkey_killee ) && !killee.heard_dr_monkey_killee ) + { + level.playing_turned_kill_vo = 1; + killee.heard_dr_monkey_killee = 1; + wait 0,25; + killee thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "dr_monkey_killee", undefined, undefined, 0 ); + } + if ( isDefined( level.playing_turned_kill_vo ) && level.playing_turned_kill_vo ) + { + wait 8; + level.playing_turned_kill_vo = 0; + } + } +} + +listen_to_the_doctor_human_deaths() +{ + level endon( "end_game" ); + while ( 1 ) + { + level waittill( "killed_by_zombie", killer, killee ); + wait 0,05; + if ( isDefined( level.playing_turned_kill_vo ) && level.playing_turned_kill_vo ) + { + continue; + } + if ( !isDefined( killee.vo_human_killed_chance ) ) + { + killee.vo_human_killed_chance = 24; + } + if ( randomint( 100 ) < killee.vo_human_killed_chance ) + { + level.playing_turned_kill_vo = 1; + killee thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "dr_human_killed", undefined, undefined, 0 ); + killee.vo_human_killed_chance = int( killee.vo_human_killed_chance * 0,5 ); + } + if ( isDefined( level.playing_turned_kill_vo ) && level.playing_turned_kill_vo ) + { + wait 4; + level.playing_turned_kill_vo = 0; + } + } +} + +listen_to_the_doctor_zombie_deaths() +{ + level endon( "end_game" ); + while ( 1 ) + { + level waittill( "killed_by_human", killer, killee ); + wait 0,05; + if ( isDefined( level.playing_turned_kill_vo ) && level.playing_turned_kill_vo ) + { + continue; + } + if ( !isDefined( killer.vo_human_killer_chance ) ) + { + killer.vo_human_killer_chance = 24; + } + if ( randomint( 100 ) < killer.vo_human_killer_chance ) + { + killer.vo_human_killer_chance = int( killer.vo_human_killer_chance * 0,5 ); + level.playing_turned_kill_vo = 1; + killer thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "dr_human_killer", undefined, undefined, 0 ); + } + if ( isDefined( level.playing_turned_kill_vo ) && level.playing_turned_kill_vo ) + { + wait 4; + level.playing_turned_kill_vo = 0; + } + } +} + +listen_to_the_doctor_endgame() +{ + wait 5; + while ( maps/mp/gametypes_zm/_globallogic_utils::gettimeremaining() > 12000 ) + { + wait 1; + } + r = randomint( 3 ); + if ( r == 0 ) + { + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_countdown0", undefined, undefined, 1, 4 ); + } + else if ( r == 1 ) + { + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_countdown1", undefined, undefined, 1, 4 ); + } + else + { + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_countdown2", undefined, undefined, 1, 4 ); + } + while ( maps/mp/gametypes_zm/_globallogic_utils::gettimeremaining() > 500 ) + { + wait 1; + } + level maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_ending", undefined, undefined, 1, 4 ); +} + +anysplitscreen() +{ + _a549 = get_players(); + _k549 = getFirstArrayKey( _a549 ); + while ( isDefined( _k549 ) ) + { + player = _a549[ _k549 ]; + if ( player issplitscreen() ) + { + return 1; + } + _k549 = getNextArrayKey( _a549, _k549 ); + } + return 0; +} + +listen_to_the_doctor() +{ + listen_to_the_doctor_pregame(); + if ( !anysplitscreen() ) + { + listen_to_the_doctor_started(); + thread listen_to_the_doctor_human_deaths(); + thread listen_to_the_doctor_zombie_deaths(); + thread listen_to_the_doctor_monkeys(); + } + thread listen_to_the_doctor_endgame(); +} + +watch_survival_time() +{ + level endon( "end_game" ); + level notify( "new_human_suviving" ); + level endon( "new_human_suviving" ); + self endon( "zombify" ); + wait 10; + if ( !isDefined( self.vo_human_survival_chance ) ) + { + self.vo_human_survival_chance = 24; + } + while ( 1 ) + { + if ( isDefined( level.playing_turned_kill_vo ) && !level.playing_turned_kill_vo ) + { + if ( randomint( 100 ) < self.vo_human_survival_chance ) + { + self.vo_human_survival_chance = int( self.vo_human_survival_chance * 0,25 ); + level.playing_turned_kill_vo = 1; + self thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "dr_survival", undefined, undefined, 0 ); + wait 4; + level.playing_turned_kill_vo = 0; + } + } + wait 5; + } +} + +zcleansed_logic() +{ + setdvar( "player_lastStandBleedoutTime", "0.05" ); + setmatchtalkflag( "DeadChatWithDead", 1 ); + setmatchtalkflag( "DeadChatWithTeam", 1 ); + setmatchtalkflag( "DeadHearTeamLiving", 1 ); + setmatchtalkflag( "DeadHearAllLiving", 1 ); + setmatchtalkflag( "EveryoneHearsEveryone", 1 ); + level.zombie_include_powerups[ "carpenter" ] = 0; + level.noroundnumber = 1; + level._supress_survived_screen = 1; + doors = getentarray( "zombie_door", "targetname" ); + _a621 = doors; + _k621 = getFirstArrayKey( _a621 ); + while ( isDefined( _k621 ) ) + { + door = _a621[ _k621 ]; + door setinvisibletoall(); + _k621 = getNextArrayKey( _a621, _k621 ); + } + level thread maps/mp/zombies/_zm_blockers::open_all_zbarriers(); + level thread delay_box_hide(); + flag_wait( "initial_players_connected" ); + level.gamestarttime = getTime(); + level.gamelengthtime = undefined; + level.custom_spawnplayer = ::respawn_cleansed_player; + allow_player_movement( 0 ); + setup_players(); + flag_wait( "initial_blackscreen_passed" ); + level thread listen_to_the_doctor(); + level thread playturnedmusic(); + level notify( "start_fullscreen_fade_out" ); + wait 1,5; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] thread create_match_start_message( &"ZOMBIE_FIND_THE_CURE", 3 ); + i++; + } + allow_player_movement( 1 ); + spawn_initial_cure_powerup(); + waitforhumanselection(); + level notify( "cleansed_game_started" ); + level thread leaderwatch(); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] thread create_match_start_message( &"ZOMBIE_MOST_TIME_AS_HUMAN_TO_WIN", 3 ); + i++; + } + wait 1,2; + flag_clear( "pregame" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] thread destroystartmsghud(); + i++; + } + registertimelimit( 0, 1440 ); + level.discardtime = getTime() - level.starttime; + level thread watch_for_end_game(); + wait_for_round_end(); + allow_player_movement( 0 ); + wait_network_frame(); + award_round_end_bonus(); + level notify( "end_game" ); +} + +wait_for_round_end() +{ + level endon( "early_game_end" ); + level endon( "normal_game_end" ); + while ( maps/mp/gametypes_zm/_globallogic_utils::gettimeremaining() > 0 ) + { + wait 1; + } +} + +end_game_early() +{ +/# + iprintlnbold( "SOLO GAME - RELEASE ONLY" ); + return; +#/ + level.forcedend = 1; + level notify( "early_game_end" ); + level notify( "end_game" ); +} + +watch_for_end_game() +{ + level waittill( "end_game" ); + registertimelimit( 0, 0 ); + setgameendtime( 0 ); +} + +cleansedontimelimit() +{ + level notify( "normal_game_end" ); +} + +cleansedonendgame( winningteam ) +{ +} + +create_match_start_message( text, duration ) +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self notify( "kill_match_start_message" ); + self endon( "kill_match_start_message" ); + if ( !isDefined( self.match_start_msg_hud ) ) + { + self.match_start_msg_hud = newclienthudelem( self ); + self.match_start_msg_hud.alignx = "center"; + self.match_start_msg_hud.aligny = "middle"; + self.match_start_msg_hud.horzalign = "center"; + self.match_start_msg_hud.vertalign = "middle"; + self.match_start_msg_hud.y -= 130; + self.match_start_msg_hud.fontscale = 5; + self.match_start_msg_hud.foreground = 1; + if ( self issplitscreen() ) + { + self.match_start_msg_hud.y += 70; + } + self.match_start_msg_hud.color = ( 0, 0, 0 ); + self.match_start_msg_hud.hidewheninmenu = 1; + self.match_start_msg_hud.font = "default"; + } + self.match_start_msg_hud settext( text ); + self.match_start_msg_hud changefontscaleovertime( 0,25 ); + self.match_start_msg_hud fadeovertime( 0,25 ); + self.match_start_msg_hud.alpha = 1; + self.match_start_msg_hud.fontscale = 2; + if ( self issplitscreen() ) + { + self.match_start_msg_hud.fontscale = 1,5; + } + wait duration; + if ( !isDefined( self.match_start_msg_hud ) ) + { + return; + } + self.match_start_msg_hud changefontscaleovertime( 0,5 ); + self.match_start_msg_hud fadeovertime( 0,5 ); + self.match_start_msg_hud.alpha = 0; +} + +destroystartmsghud() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + if ( !isDefined( self.match_start_msg_hud ) ) + { + return; + } + self.match_start_msg_hud destroy(); + self.match_start_msg_hud = undefined; +} + +delay_box_hide() +{ + wait 2; + start_chest = getstruct( "start_chest", "script_noteworthy" ); + if ( isDefined( start_chest ) ) + { + start_chest maps/mp/zombies/_zm_magicbox::hide_chest(); + } +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connected", player ); + player thread onplayerlaststand(); + player thread onplayerdisconnect(); + player thread setup_player(); + player thread rewardsthink(); + } +} + +onplayerlaststand() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "player_downed" ); + self takeallweapons(); + } +} + +onplayerdisconnect() +{ + level endon( "end_game" ); + self waittill( "disconnect" ); + if ( get_players().size <= 1 ) + { + end_game_early(); + } + else + { + while ( isDefined( level.ingraceperiod ) && !level.ingraceperiod ) + { + thread checkzombiehumanratio(); + wait 2; + players = get_players(); + _a843 = players; + _k843 = getFirstArrayKey( _a843 ); + while ( isDefined( _k843 ) ) + { + player = _a843[ _k843 ]; + player.nuked = undefined; + _k843 = getNextArrayKey( _a843, _k843 ); + } + } + } +} + +zombie_ramp_up() +{ + self notify( "zombie_ramp_up" ); + self endon( "zombie_ramp_up" ); + self endon( "death_or_disconnect" ); + self endon( "humanify" ); + if ( isDefined( level.cleansed_zombie_round ) ) + { + self.maxhealth = maps/mp/zombies/_zm::ai_zombie_health( level.cleansed_zombie_round ); + } + else + { + self.maxhealth = maps/mp/zombies/_zm::ai_zombie_health( 2 ); + } + self.health = self.maxhealth; +} + +precache_trophy() +{ +} + +create_trophy() +{ +} + +give_trophy() +{ + if ( !self.has_trophy ) + { + self setclientfield( "player_eyes_special", 1 ); + self setclientfield( "player_has_eyes", 0 ); + wait_network_frame(); + if ( cleansed_alive_check( self ) ) + { + self setclientfield( "player_has_eyes", self.is_zombie ); + } + self.has_trophy = 1; + } +} + +remove_trophy() +{ + if ( self.has_trophy ) + { + self setclientfield( "player_eyes_special", 0 ); + self setclientfield( "player_has_eyes", 0 ); + wait_network_frame(); + if ( cleansed_alive_check( self ) ) + { + self setclientfield( "player_has_eyes", self.is_zombie ); + } + self.has_trophy = 0; + } +} + +enthrone( player ) +{ + player endon( "dethrone" ); + player endon( "disconnect" ); + while ( 1 ) + { + if ( cleansed_alive_check( player ) && player.is_zombie ) + { + if ( !player.has_trophy ) + { + player give_trophy(); + } + } + else + { + if ( player.has_trophy ) + { + player remove_trophy(); + } + } + wait 0,1; + } +} + +dethrone( player ) +{ + player notify( "dethrone" ); + player remove_trophy(); +} + +cleansed_set_leader( leader ) +{ + if ( isDefined( leader ) && isDefined( level.cleansed_leader ) ) + { + if ( level.cleansed_leader != leader ) + { + dethrone( level.cleansed_leader ); + level.cleansed_leader = leader; + level thread enthrone( level.cleansed_leader ); + } + return; + } + if ( isDefined( leader ) && !isDefined( level.cleansed_leader ) ) + { + level.cleansed_leader = leader; + level thread enthrone( level.cleansed_leader ); + return; + } + if ( !isDefined( leader ) && isDefined( level.cleansed_leader ) ) + { + if ( isDefined( level.cleansed_leader ) ) + { + dethrone( level.cleansed_leader ); + } + level.cleansed_leader = leader; + return; + } +} + +leaderwatch() +{ + level endon( "early_game_end" ); + level endon( "normal_game_end" ); + create_trophy(); + cleansed_set_leader( undefined ); + while ( 1 ) + { + hiscore = -1; + leader = undefined; + players = get_players(); + _a998 = players; + _k998 = getFirstArrayKey( _a998 ); + while ( isDefined( _k998 ) ) + { + player = _a998[ _k998 ]; + if ( player.score > hiscore ) + { + hiscore = player.score; + } + _k998 = getNextArrayKey( _a998, _k998 ); + } + _a1004 = players; + _k1004 = getFirstArrayKey( _a1004 ); + while ( isDefined( _k1004 ) ) + { + player = _a1004[ _k1004 ]; + if ( player.score >= hiscore ) + { + if ( isDefined( leader ) ) + { + leader = undefined; + break; + } + else + { + leader = player; + } + _k1004 = getNextArrayKey( _a1004, _k1004 ); + } + } + cleansed_set_leader( leader ); + wait 0,25; + } +} + +cover_transition() +{ + self thread fadetoblackforxsec( 0, 0,15, 0,05, 0,1 ); + wait 0,1; +} + +disappear_in_flash( washuman ) +{ + playsoundatposition( "zmb_bolt", self.origin ); + if ( washuman ) + { + playfx( level._effect[ "human_disappears" ], self.origin ); + } + else + { + playfx( level._effect[ "zombie_disappears" ], self.origin ); + } + self ghost(); +} + +humanifyplayer( for_killing ) +{ +/# +#/ + self freezecontrolswrapper( 1 ); + self thread cover_transition(); + self disappear_in_flash( 1 ); + self.team = self.prevteam; + self.pers[ "team" ] = self.prevteam; + self.sessionteam = self.prevteam; + self turnedhuman(); + for_killing waittill_notify_or_timeout( "respawned", 0,75 ); + wait_network_frame(); + checkzombiehumanratio( self ); + self.last_player_attacker = undefined; + self freezecontrolswrapper( level.player_movement_suppressed ); + self thread watch_survival_time(); +/# +#/ +} + +onzombifyplayer() +{ +/# +#/ + if ( isDefined( self.in_zombify_call ) && self.in_zombify_call ) + { + return; + } + self.in_zombify_call = 1; + while ( isDefined( level.in_zombify_call ) && level.in_zombify_call ) + { + wait 0,1; + } + level.in_zombify_call = 1; + self freezecontrolswrapper( 1 ); + if ( isDefined( self.last_player_attacker ) && isplayer( self.last_player_attacker ) && isDefined( self.last_player_attacker.is_zombie ) && self.last_player_attacker.is_zombie ) + { + } + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { +/# +#/ + self check_for_drops( 0 ); + } + else + { + if ( isDefined( self.last_player_attacker ) && isplayer( self.last_player_attacker ) && isDefined( self.last_player_attacker.is_zombie ) && self.last_player_attacker.is_zombie ) + { +/# +#/ + self check_for_drops( 1 ); + self.team = level.zombie_team; + self.pers[ "team" ] = level.zombie_team; + self.sessionteam = level.zombie_team; + self.last_player_attacker thread humanifyplayer( self ); + self.player_was_turned_by = self.last_player_attacker; + } + else + { +/# +#/ + self check_for_drops( 1 ); + self player_suicide(); + checkzombiehumanratio( undefined, self ); + } + } + self setclientfield( "player_has_eyes", 0 ); + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + } + self notify( "zombified" ); + self disappear_in_flash( 0 ); + self cover_transition(); + self notify( "clear_red_flashing_overlay" ); + self.zombification_time = getTime() / 1000; + self.last_player_attacker = undefined; + self maps/mp/zombies/_zm_laststand::laststand_enable_player_weapons(); + self.ignoreme = 1; + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger delete(); + } + self.revivetrigger = undefined; + self reviveplayer(); + self maps/mp/zombies/_zm_turned::turn_to_zombie(); + self freezecontrolswrapper( level.player_movement_suppressed ); + self thread zombie_ramp_up(); + level.in_zombify_call = 0; + self.in_zombify_call = 0; +/# +#/ +} + +playerfakedeath( vdir ) +{ + if ( isDefined( self.is_zombie ) && !self.is_zombie ) + { + self endon( "disconnect" ); + level endon( "game_module_ended" ); + level notify( "fake_death" ); + self notify( "fake_death" ); + self enableinvulnerability(); + self takeallweapons(); + self freezecontrolswrapper( 1 ); + self.ignoreme = 1; + origin = self.origin; + xyspeed = ( 0, 0, 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, 0, 0 ) ); + linker.origin = origin; + linker.angles = angles; + self._fall_down_anchor = linker; + self playerlinkto( linker ); + self playsoundtoplayer( "zmb_player_death_fall", self ); + origin = playerphysicstrace( origin, origin + xyspeed ); + origin += vectorScale( ( 0, 0, 0 ), 52 ); + lerptime = 0,5; + linker moveto( origin, lerptime, lerptime ); + linker rotateto( angles, lerptime, lerptime ); + self freezecontrolswrapper( 1 ); + linker waittill( "movedone" ); + self giveweapon( "death_throe_zm" ); + self switchtoweapon( "death_throe_zm" ); + 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 5; + linker delete(); + self.ignoreme = 0; + self takeweapon( "death_throe_zm" ); + self disableinvulnerability(); + self freezecontrolswrapper( 0 ); + } +} + +onspawnzombie() +{ +} + +makefindfleshstructs() +{ + structs = getstructarray( "spawn_location", "script_noteworthy" ); + _a1258 = structs; + _k1258 = getFirstArrayKey( _a1258 ); + while ( isDefined( _k1258 ) ) + { + struct = _a1258[ _k1258 ]; + struct.script_string = "find_flesh"; + _k1258 = getNextArrayKey( _a1258, _k1258 ); + } +} + +setup_players() +{ +/# + while ( getDvarInt( #"99BF96D1" ) != 0 ) + { + _a1269 = level._turned_zombie_respawnpoints; + _k1269 = getFirstArrayKey( _a1269 ); + while ( isDefined( _k1269 ) ) + { + spawnpoint = _a1269[ _k1269 ]; + text = ""; + color = ( 0, 0, 0 ); + if ( !isDefined( spawnpoint.angles ) ) + { + text = "No Angles Defined"; + color = ( 0, 0, 0 ); + spawnpoint.angles = ( 0, 0, 0 ); + } + _k1269 = getNextArrayKey( _a1269, _k1269 ); +#/ + } + } +} + +setup_player() +{ + hotjoined = flag( "initial_players_connected" ); + flag_wait( "initial_players_connected" ); + wait 0,05; + self ghost(); + self freezecontrolswrapper( 1 ); + self.ignoreme = 0; + self.score = 0; + self.characterindex = level.characterindex; + self takeallweapons(); + self giveweapon( "knife_zm" ); + self give_start_weapon( 1 ); + self.prevteam = self.team; + self.no_revive_trigger = 1; + self.human_score = 0; + self thread player_score_update(); + self.is_zombie = 0; + self.has_trophy = 0; + self.home_team = self.team; + if ( self.home_team == "axis" ) + { + self.home_team = "team3"; + } + self thread wait_turn_to_zombie( hotjoined ); +} + +wait_turn_to_zombie( hot ) +{ + if ( hot ) + { + self thread fadetoblackforxsec( 0, 1,25, 0,05, 0,25 ); + wait 1; + } + self.is_zombie = 0; + self turn_to_zombie(); + self freezecontrolswrapper( level.player_movement_suppressed ); +} + +addguntoprogression( gunname ) +{ + if ( !isDefined( level.gunprogression ) ) + { + level.gunprogression = []; + } + level.gunprogression[ level.gunprogression.size ] = gunname; +} + +check_spawn_cymbal_monkey( origin, weapon ) +{ + chance = -0,05; + if ( !self hasweapon( "cymbal_monkey_zm" ) || self getweaponammoclip( "cymbal_monkey_zm" ) < 1 ) + { + if ( weapon == "cymbal_monkey_zm" || randomfloat( 1 ) < chance ) + { + self notify( "awarded_cymbal_monkey" ); + level.spawned_cymbal_monkey = spawn_cymbalmonkey( origin ); + level.spawned_cymbal_monkey thread delete_spawned_monkey_on_turned( self ); + return 1; + } + } + return 0; +} + +delete_spawned_monkey_on_turned( player ) +{ + wait 1; + while ( isDefined( self ) && isDefined( player.is_zombie ) && !player.is_zombie ) + { + wait_network_frame(); + } + if ( isDefined( self ) ) + { + self maps/mp/zombies/_zm_powerups::powerup_delete(); + self notify( "powerup_timedout" ); + } +} + +rewardsthink() +{ + self endon( "_zombie_game_over" ); + self endon( "disconnect" ); + while ( isDefined( self ) ) + { + self waittill( "killed_a_zombie_player", einflictor, target, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); + if ( isDefined( self.is_zombie ) && !self.is_zombie ) + { + if ( self check_spawn_cymbal_monkey( target.origin, sweapon ) ) + { + target.suppress_drops = 1; + } + } + } +} + +shotgunloadout() +{ + self endon( "_zombie_game_over" ); + self endon( "disconnect" ); + self endon( "bled_out" ); + self endon( "zombify" ); + level.cymbal_monkey_clone_weapon = "rottweil72_zm"; + if ( !self hasweapon( "rottweil72_zm" ) ) + { + self giveweapon( "rottweil72_zm" ); + self switchtoweapon( "rottweil72_zm" ); + } + if ( isDefined( self.is_zombie ) && !self.is_zombie && !self hasweapon( level.start_weapon ) ) + { + if ( !self hasweapon( "knife_zm" ) ) + { + self giveweapon( "knife_zm" ); + } + self give_start_weapon( 0 ); + } + if ( self hasweapon( "rottweil72_zm" ) ) + { + self setweaponammoclip( "rottweil72_zm", 2 ); + self setweaponammostock( "rottweil72_zm", 0 ); + } + if ( self hasweapon( level.start_weapon ) ) + { + self givemaxammo( level.start_weapon ); + } + if ( self hasweapon( self get_player_lethal_grenade() ) ) + { + self getweaponammoclip( self get_player_lethal_grenade() ); + } + else + { + self giveweapon( self get_player_lethal_grenade() ); + } + self setweaponammoclip( self get_player_lethal_grenade(), 2 ); + if ( isDefined( self.random_human ) && !self.random_human ) + { + } +} + +gunprogressionthink() +{ + self endon( "_zombie_game_over" ); + self endon( "disconnect" ); + self endon( "bled_out" ); + self endon( "zombify" ); + counter = 0; + if ( isDefined( level.gunprogression ) && !isDefined( level.cymbal_monkey_clone_weapon ) ) + { + level.cymbal_monkey_clone_weapon = level.gunprogression[ 0 ]; + } + last = level.start_weapon; + if ( !self hasweapon( self get_player_lethal_grenade() ) ) + { + self giveweapon( self get_player_lethal_grenade() ); + } + self setweaponammoclip( self get_player_lethal_grenade(), 2 ); + if ( isDefined( self.random_human ) && !self.random_human ) + { + } + self disableweaponcycling(); + while ( isDefined( self.is_zombie ) && !self.is_zombie ) + { + if ( !isDefined( level.gunprogression[ counter ] ) ) + { + } + else + { + self disableweaponcycling(); + self giveweapon( level.gunprogression[ counter ] ); + self switchtoweapon( level.gunprogression[ counter ] ); + self waittill_notify_or_timeout( "weapon_change_complete", 0,5 ); + if ( isDefined( last ) && self hasweapon( last ) ) + { + self takeweapon( last ); + } + last = level.gunprogression[ counter ]; + while ( 1 ) + { + self waittill( "killed_a_zombie_player", einflictor, target, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); + if ( isDefined( sweapon ) && level.gunprogression[ counter ] == sweapon ) + { + counter++; + continue; + } + else + { + } + } + counter++; + } + } + self giveweapon( level.start_weapon ); + self switchtoweapon( level.start_weapon ); + self waittill( "weapon_change_complete" ); + if ( isDefined( last ) && self hasweapon( last ) ) + { + self takeweapon( last ); + } + while ( 1 ) + { + self waittill( "killed_a_zombie_player", einflictor, target, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); + if ( isDefined( sweapon ) && level.start_weapon == sweapon ) + { + self notify( "gun_game_achievement" ); + return; + } + else } +} + +waitforhumanselection() +{ + level waittill( "initial_human_selected" ); +} + +checkzombiehumanratio( playertomove, playertoignore ) +{ + zombiecount = 0; + humancount = 0; + zombieexist = 0; + humanexist = 0; + earliestzombie = undefined; + earliestzombietime = 99999999; + if ( get_players().size <= 1 ) + { + end_game_early(); + } + while ( isDefined( level.checking_human_zombie_ratio ) && level.checking_human_zombie_ratio ) + { + wait 0,05; + } + level.checking_human_zombie_ratio = 1; + if ( isDefined( playertomove ) ) + { + someonebecominghuman = 0; + players = get_players(); + _a1570 = players; + _k1570 = getFirstArrayKey( _a1570 ); + while ( isDefined( _k1570 ) ) + { + player = _a1570[ _k1570 ]; + if ( isDefined( player.is_in_process_of_humanify ) && player.is_in_process_of_humanify ) + { + someonebecominghuman = 1; + } + _k1570 = getNextArrayKey( _a1570, _k1570 ); + } + if ( isDefined( someonebecominghuman ) && !someonebecominghuman ) + { + playertomove turn_to_human(); + } + level.checking_human_zombie_ratio = 0; + return; + } + players = get_players(); + _a1589 = players; + _k1589 = getFirstArrayKey( _a1589 ); + while ( isDefined( _k1589 ) ) + { + player = _a1589[ _k1589 ]; + if ( isDefined( playertoignore ) && playertoignore == player ) + { + } + else + { + if ( isDefined( player.is_zombie ) && !player.is_zombie && isDefined( player.is_in_process_of_zombify ) && !player.is_in_process_of_zombify ) + { + humancount++; + humanexist = 1; + break; + } + else + { + zombiecount++; + zombieexist = 1; + if ( isDefined( player.zombification_time ) && player.zombification_time < earliestzombietime ) + { + earliestzombie = player; + earliestzombietime = player.zombification_time; + } + } + } + _k1589 = getNextArrayKey( _a1589, _k1589 ); + } + if ( humancount > 1 ) + { + players = get_players( "allies" ); + if ( isDefined( players ) && players.size > 0 ) + { + player = random( players ); + player thread cover_transition(); + player disappear_in_flash( 1 ); +/# +#/ + player turn_to_zombie(); + zombiecount++; + } + } + if ( !humanexist ) + { + players = get_players( level.zombie_team ); + if ( isDefined( players ) && players.size > 0 ) + { + player = random( players ); + player thread cover_transition(); + player disappear_in_flash( 0 ); + player.random_human = 1; +/# +#/ + player turn_to_human(); + player.random_human = 0; + zombiecount--; + + } + } + level.checking_human_zombie_ratio = 0; +} + +get_player_rank() +{ + level.player_score_sort = []; + players = get_players(); + _a1659 = players; + _k1659 = getFirstArrayKey( _a1659 ); + while ( isDefined( _k1659 ) ) + { + player = _a1659[ _k1659 ]; + index = 0; + while ( index < level.player_score_sort.size && player.score < level.player_score_sort[ index ].score ) + { + index++; + } + arrayinsert( level.player_score_sort, player, index ); + _k1659 = getNextArrayKey( _a1659, _k1659 ); + } + index = 0; + while ( index < level.player_score_sort.size ) + { + if ( self == level.player_score_sort[ index ] ) + { + return index; + } + index++; + } +/# + assertmsg( "This should not happen" ); +#/ + return 0; +} + +player_add_score( bonus ) +{ + mult = 1; + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + mult = level.zombie_vars[ level.zombie_team ][ "zombie_point_scalar" ]; + } + else + { + mult = level.zombie_vars[ "allies" ][ "zombie_point_scalar" ]; + } + self maps/mp/zombies/_zm_score::add_to_player_score( bonus * mult ); +} + +player_sub_score( penalty ) +{ + penalty = int( min( self.score, penalty ) ); + self maps/mp/zombies/_zm_score::add_to_player_score( penalty * -1 ); +} + +player_suicide() +{ + self player_sub_score( level.human_player_suicide_penalty ); +/# + if ( get_players().size < 2 ) + { + self.intermission = 0; + thread spawn_initial_cure_powerup(); +#/ + } +} + +player_kills_player( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + score_multiplier = 1; + if ( isDefined( eattacker.is_zombie ) && !eattacker.is_zombie && isDefined( level.zombie_player_kill_points ) ) + { + level notify( "killed_by_human" ); + eattacker player_add_score( int( score_multiplier * level.zombie_player_kill_points ) ); + eattacker maps/mp/zombies/_zm_stats::add_global_stat( "PLAYER_KILLS", 1 ); + if ( smeansofdeath == "MOD_GRENADE" || smeansofdeath == "MOD_GRENADE_SPLASH" ) + { + eattacker maps/mp/zombies/_zm_stats::increment_client_stat( "grenade_kills" ); + eattacker maps/mp/zombies/_zm_stats::increment_player_stat( "grenade_kills" ); + } + } + if ( isDefined( eattacker.is_zombie ) && eattacker.is_zombie && isDefined( level.human_player_kill_points ) ) + { + level notify( "killed_by_zombie" ); + eattacker player_add_score( int( score_multiplier * level.human_player_kill_points ) ); + eattacker maps/mp/zombies/_zm_stats::add_global_stat( "PLAYER_RETURNS", 1 ); + } +} + +award_round_end_bonus() +{ + level notify( "stop_player_scores" ); + wait 0,25; + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "dr_time_line", undefined, undefined, 1 ); + while ( maps/mp/zombies/_zm_laststand::player_any_player_in_laststand() || isDefined( level.in_zombify_call ) && level.in_zombify_call ) + { + wait 0,25; + } + hiscore = -1; + _a1760 = get_players(); + _k1760 = getFirstArrayKey( _a1760 ); + while ( isDefined( _k1760 ) ) + { + player = _a1760[ _k1760 ]; + if ( isDefined( player.is_zombie ) && !player.is_zombie ) + { + player player_add_score( level.human_finish_bonus_points ); + level.last_human_standing = player; + } + if ( player.score > hiscore ) + { + hiscore = player.score; + } + _k1760 = getNextArrayKey( _a1760, _k1760 ); + } + _a1771 = get_players(); + _k1771 = getFirstArrayKey( _a1771 ); + while ( isDefined( _k1771 ) ) + { + player = _a1771[ _k1771 ]; + if ( player.score >= hiscore ) + { + player.team = player.prevteam; + player.pers[ "team" ] = player.prevteam; + player.sessionteam = player.prevteam; + player maps/mp/zombies/_zm_stats::increment_client_stat( "wins" ); + player maps/mp/zombies/_zm_stats::add_client_stat( "losses", -1 ); + player adddstat( "skill_rating", 1 ); + player setdstat( "skill_variance", 1 ); + if ( gamemodeismode( level.gamemode_public_match ) ) + { + player maps/mp/zombies/_zm_stats::add_location_gametype_stat( level.scr_zm_map_start_location, level.scr_zm_ui_gametype, "wins", 1 ); + player maps/mp/zombies/_zm_stats::add_location_gametype_stat( level.scr_zm_map_start_location, level.scr_zm_ui_gametype, "losses", -1 ); + } + } + else + { + player.team = level.zombie_team; + player.pers[ "team" ] = level.zombie_team; + player.sessionteam = level.zombie_team; + player setdstat( "skill_rating", 0 ); + player setdstat( "skill_variance", 1 ); + } + _k1771 = getNextArrayKey( _a1771, _k1771 ); + } +} + +player_score_update() +{ + self endon( "_zombie_game_over" ); + self endon( "disconnect" ); + level endon( "stop_player_scores" ); + waittime = 0,05; + while ( 1 ) + { + self waittill_any_or_timeout( waittime, "zombify", "humanify" ); + if ( isDefined( self._can_score ) && !self._can_score ) + { + continue; + } + if ( isDefined( level.hostmigrationtimer ) && level.hostmigrationtimer ) + { + continue; + } + if ( isDefined( level.ingraceperiod ) && !level.ingraceperiod ) + { + if ( !cleansed_alive_check( self ) ) + { + waittime = 0,05; + break; + } + else if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + waittime = level.zombie_penalty_period; + self player_sub_score( level.zombie_penalty_points ); + break; + } + else + { + waittime = level.human_bonus_period; + self player_add_score( level.human_bonus_points ); + } + } + } +} + +respawn_cleansed_player() +{ + spawnpoint = self maps/mp/zombies/_zm_turned::getspawnpoint(); + self.sessionstate = "playing"; + self allowspectateteam( "freelook", 0 ); + self spawn( spawnpoint.origin, spawnpoint.angles ); + self notify( "stop_flame_damage" ); + self reviveplayer(); + self.nuked = 0; + self.nuker = undefined; + self.suppress_drops = 0; + self.is_burning = 0; + self.is_zombie = 0; + self.ignoreme = 0; + self freezecontrolswrapper( level.player_movement_suppressed ); + self notify( "respawned" ); +} + +zcleansed_zombie_powerup_grab( powerup, zombie_player ) +{ + if ( !cleansed_alive_check( zombie_player ) ) + { + return 0; + } + switch( powerup.powerup_name ) + { + case "the_cure": + level notify( "initial_human_selected" ); + zombie_player freezecontrolswrapper( 1 ); + zombie_player disappear_in_flash( 0 ); + zombie_player turn_to_human(); + players = get_players(); + _a1896 = players; + _k1896 = getFirstArrayKey( _a1896 ); + while ( isDefined( _k1896 ) ) + { + player = _a1896[ _k1896 ]; + if ( player.is_zombie ) + { + player thread zombie_ramp_up(); + } + _k1896 = getNextArrayKey( _a1896, _k1896 ); + } + default: + if ( isDefined( level.cleansed_powerups[ powerup.powerup_name ] ) ) + { + if ( isDefined( level.cleansed_powerups[ powerup.powerup_name ].callback ) ) + { + powerup thread [[ level.cleansed_powerups[ powerup.powerup_name ].callback ]]( zombie_player ); + } + } + } + } +} + +zcleansed_powerup_grab( powerup, player ) +{ + if ( !cleansed_alive_check( player ) ) + { + return 0; + } + switch( powerup.powerup_name ) + { + case "blue_monkey": + player maps/mp/zombies/_zm_weap_cymbal_monkey::player_give_cymbal_monkey(); + player setweaponammoclip( "cymbal_monkey_zm", 1 ); + player notify( "powerup_blue_monkey" ); + break; + default: + if ( isDefined( level.cleansed_powerups[ powerup.powerup_name ] ) ) + { + if ( isDefined( level.cleansed_powerups[ powerup.powerup_name ].callback ) ) + { + powerup thread [[ level.cleansed_powerups[ powerup.powerup_name ].callback ]]( player ); + } + } + } +} + +zcleansed_powerup_custom_time_logic( powerup ) +{ + if ( powerup.powerup_name == "the_cure" ) + { + return 0; + } + return 15; +} + +spawn_initial_cure_powerup() +{ + struct = random( level._turned_powerup_spawnpoints ); + maps/mp/zombies/_zm_powerups::specific_powerup_drop( "the_cure", struct.origin ); +} + +spawn_cymbalmonkey( origin ) +{ + monkey = maps/mp/zombies/_zm_powerups::specific_powerup_drop( "blue_monkey", origin ); + return monkey; +} + +check_for_drops( washuman ) +{ + if ( !isDefined( level.cleansed_kills_for_drops ) ) + { + level.cleansed_kills_for_drops = 0; + } + if ( isDefined( self.nuked ) || self.nuked && isDefined( self.suppress_drops ) && self.suppress_drops ) + { + return; + } + level.cleansed_kills_for_drops++; + chance = ( level.cleansed_kills_for_drops - 2 ) / level.cleansed_kills_for_drops; + if ( chance > 0 ) + { + r = randomfloatrange( 0, 1 ); + if ( r < chance ) + { + self thread drop_powerup( washuman ); + level.cleansed_kills_for_drops = 0; + } + } +} + +add_cleansed_powerup( name, powerupmodel, text, team, zombie_death_frequency, human_death_frequency, callback ) +{ + if ( !isDefined( level.cleansed_powerups ) ) + { + level.cleansed_powerups = []; + } + precachemodel( powerupmodel ); + if ( !isDefined( level.zombie_powerups[ name ] ) ) + { + maps/mp/zombies/_zm_powerups::include_zombie_powerup( name ); + maps/mp/zombies/_zm_powerups::add_zombie_powerup( name, powerupmodel, text, ::maps/mp/zombies/_zm_powerups::func_should_never_drop, 0, team == 2, team == 1 ); + if ( !isDefined( level.statless_powerups ) ) + { + level.statless_powerups = []; + } + level.statless_powerups[ name ] = 1; + } + powerup = spawnstruct(); + powerup.name = name; + powerup.model = powerupmodel; + powerup.team = team; + powerup.callback = callback; + powerup.zfrequency = zombie_death_frequency; + powerup.hfrequency = human_death_frequency; + level.cleansed_powerups[ name ] = powerup; +} + +init_cleansed_powerups() +{ + level._effect[ "powerup_on_solo" ] = loadfx( "misc/fx_zombie_powerup_on_blue" ); + add_cleansed_powerup( "green_nuke", "zombie_bomb", &"ZOMBIE_THIS_IS_A_BUG", 0, 0,4, 0, ::turned_powerup_green_nuke ); + add_cleansed_powerup( "green_double", "zombie_x2_icon", &"ZOMBIE_THIS_IS_A_BUG", 0, 1, 0, ::turned_powerup_green_double ); + add_cleansed_powerup( "green_insta", "zombie_skull", &"ZOMBIE_THIS_IS_A_BUG", 0, 0,1, 0, ::turned_powerup_green_insta ); + add_cleansed_powerup( "green_ammo", "zombie_ammocan", &"ZOMBIE_POWERUP_MAX_AMMO", 0, 1, 0, ::turned_powerup_green_ammo ); + add_cleansed_powerup( "green_monkey", level.cymbal_monkey_model, &"ZOMBIE_THIS_IS_A_BUG", 0, 0,4, 0, ::turned_powerup_green_monkey ); + add_cleansed_powerup( "red_nuke", "zombie_bomb", &"ZOMBIE_THIS_IS_A_BUG", 1, 0, 0,4, ::turned_powerup_red_nuke ); + add_cleansed_powerup( "red_ammo", "zombie_ammocan", &"ZOMBIE_THIS_IS_A_BUG", 1, 0, 1, ::turned_powerup_red_ammo ); + add_cleansed_powerup( "red_double", "zombie_x2_icon", &"ZOMBIE_THIS_IS_A_BUG", 1, 0, 1, ::turned_powerup_red_double ); + add_cleansed_powerup( "yellow_double", "zombie_x2_icon", &"ZOMBIE_THIS_IS_A_BUG", 2, 0,1, 0,1, ::turned_powerup_yellow_double ); + add_cleansed_powerup( "yellow_nuke", "zombie_bomb", &"ZOMBIE_THIS_IS_A_BUG", 2, 0,01, 0,01, ::turned_powerup_yellow_nuke ); + level.cleansed_powerup_history_depth = []; + level.cleansed_powerup_history_depth[ 0 ] = 2; + level.cleansed_powerup_history_depth[ 1 ] = 1; + level.cleansed_powerup_history = []; + level.cleansed_powerup_history[ 0 ] = []; + level.cleansed_powerup_history[ 1 ] = []; + level.cleansed_powerup_history_last = []; + level.cleansed_powerup_history_last[ 0 ] = 0; + level.cleansed_powerup_history_last[ 1 ] = 0; + i = 0; + while ( i < level.cleansed_powerup_history_depth[ 0 ] ) + { + level.cleansed_powerup_history[ 0 ][ i ] = "none"; + level.cleansed_powerup_history[ 1 ][ i ] = "none"; + i++; + } +} + +pick_a_powerup( washuman ) +{ + total = 0; + _a2073 = level.cleansed_powerups; + _k2073 = getFirstArrayKey( _a2073 ); + while ( isDefined( _k2073 ) ) + { + powerup = _a2073[ _k2073 ]; + powerup.recent = 0; + i = 0; + while ( i < level.cleansed_powerup_history_depth[ washuman ] ) + { + if ( level.cleansed_powerup_history[ washuman ][ i ] == powerup.name ) + { + powerup.recent = 1; + } + i++; + } + if ( powerup.recent ) + { + } + else if ( washuman ) + { + total += powerup.hfrequency; + } + else + { + total += powerup.zfrequency; + } + _k2073 = getNextArrayKey( _a2073, _k2073 ); + } + if ( total == 0 ) + { + return undefined; + } + r = randomfloat( total ); + _a2092 = level.cleansed_powerups; + _k2092 = getFirstArrayKey( _a2092 ); + while ( isDefined( _k2092 ) ) + { + powerup = _a2092[ _k2092 ]; + if ( powerup.recent ) + { + } + else + { + if ( washuman ) + { + r -= powerup.hfrequency; + } + else + { + r -= powerup.zfrequency; + } + if ( r <= 0 ) + { + level.cleansed_powerup_history[ washuman ][ level.cleansed_powerup_history_last[ washuman ] ] = powerup.name; + level.cleansed_powerup_history_last[ washuman ]++; + if ( level.cleansed_powerup_history_last[ washuman ] >= level.cleansed_powerup_history_depth[ washuman ] ) + { + level.cleansed_powerup_history_last[ washuman ] = 0; + } + return powerup; + } + } + _k2092 = getNextArrayKey( _a2092, _k2092 ); + } + return undefined; +} + +drop_powerup( washuman ) +{ + powerup = pick_a_powerup( washuman ); + if ( isDefined( powerup ) ) + { + origin = self.origin; + wait 0,25; + maps/mp/zombies/_zm_powerups::specific_powerup_drop( powerup.name, origin ); + } +} + +powerup_can_player_grab( player ) +{ + if ( !cleansed_alive_check( player ) ) + { + return 0; + } + if ( isDefined( level.cleansed_powerups[ self.powerup_name ] ) ) + { + if ( level.cleansed_powerups[ self.powerup_name ].team == 0 && isDefined( player.is_zombie ) && player.is_zombie ) + { + return 0; + } + if ( level.cleansed_powerups[ self.powerup_name ].team == 1 && isDefined( player.is_zombie ) && !player.is_zombie ) + { + return 0; + } + } + else + { + if ( self.zombie_grabbable && isDefined( player.is_zombie ) && !player.is_zombie ) + { + return 0; + } + if ( !self.zombie_grabbable && isDefined( player.is_zombie ) && player.is_zombie ) + { + return 0; + } + } + return 1; +} + +player_nuke_fx() +{ + self endon( "death" ); + self endon( "respawned" ); + self endon( "stop_flame_damage" ); + if ( isDefined( level._effect ) && isDefined( level._effect[ "character_fire_death_torso" ] ) ) + { + if ( !self.isdog ) + { + playfxontag( level._effect[ "character_fire_death_torso" ], self, "J_SpineLower" ); + } + } + if ( isDefined( level._effect ) && isDefined( level._effect[ "character_fire_death_sm" ] ) ) + { + wait 1; + tagarray = []; + tagarray[ 0 ] = "J_Elbow_LE"; + tagarray[ 1 ] = "J_Elbow_RI"; + tagarray[ 2 ] = "J_Knee_RI"; + tagarray[ 3 ] = "J_Knee_LE"; + tagarray = array_randomize( tagarray ); + playfxontag( level._effect[ "character_fire_death_sm" ], self, tagarray[ 0 ] ); + wait 1; + tagarray[ 0 ] = "J_Wrist_RI"; + tagarray[ 1 ] = "J_Wrist_LE"; + if ( isDefined( self.a ) || !isDefined( self.a.gib_ref ) && self.a.gib_ref != "no_legs" ) + { + tagarray[ 2 ] = "J_Ankle_RI"; + tagarray[ 3 ] = "J_Ankle_LE"; + } + tagarray = array_randomize( tagarray ); + playfxontag( level._effect[ "character_fire_death_sm" ], self, tagarray[ 0 ] ); + playfxontag( level._effect[ "character_fire_death_sm" ], self, tagarray[ 1 ] ); + } +} + +player_nuke( player ) +{ + nuke_time = 2; + self.isdog = 0; + self.nuked = 1; + self.nuker = player; + self freezecontrolswrapper( 1 ); + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_transit_burn", self, nuke_time / 2, nuke_time ); + self thread player_nuke_fx(); + wait nuke_time; + if ( isDefined( self ) ) + { + if ( isDefined( player ) ) + { + self dodamage( self.health + 666, player.origin, player, player, "none", "MOD_EXPLOSIVE", 0, "nuke_zm" ); + return; + } + else + { + self.nuked = undefined; + self dodamage( self.health + 666, self.origin, self, self, "none", "MOD_EXPLOSIVE", 0, "nuke_zm" ); + } + } +} + +turned_powerup_green_nuke( player ) +{ + location = self.origin; + playfx( level.zombie_powerups[ "nuke" ].fx, location ); + level thread maps/mp/zombies/_zm_powerups::nuke_flash(); + players = get_players(); + _a2230 = players; + _k2230 = getFirstArrayKey( _a2230 ); + while ( isDefined( _k2230 ) ) + { + target = _a2230[ _k2230 ]; + if ( !cleansed_alive_check( target ) ) + { + } + else if ( isDefined( target.is_zombie ) && target.is_zombie ) + { + target thread player_nuke( player ); + break; + } + _k2230 = getNextArrayKey( _a2230, _k2230 ); + } +} + +turned_powerup_green_double( player ) +{ + level thread maps/mp/zombies/_zm_powerups::double_points_powerup( self, player ); +} + +turned_powerup_green_insta( player ) +{ + level thread maps/mp/zombies/_zm_powerups::insta_kill_powerup( self, player ); +} + +turned_powerup_green_ammo( player ) +{ + level thread maps/mp/zombies/_zm_powerups::full_ammo_powerup( self, player ); + weapon = player getcurrentweapon(); + player givestartammo( weapon ); +} + +turned_powerup_green_monkey( player ) +{ + player maps/mp/zombies/_zm_weap_cymbal_monkey::player_give_cymbal_monkey(); + player setweaponammoclip( "cymbal_monkey_zm", 1 ); + player notify( "powerup_green_monkey" ); +} + +turned_powerup_red_nuke( player ) +{ + location = self.origin; + playfx( level.zombie_powerups[ "nuke" ].fx, location ); + level thread maps/mp/zombies/_zm_powerups::nuke_flash(); + players = get_players(); + _a2278 = players; + _k2278 = getFirstArrayKey( _a2278 ); + while ( isDefined( _k2278 ) ) + { + target = _a2278[ _k2278 ]; + if ( !cleansed_alive_check( target ) ) + { + } + else if ( isDefined( target.is_zombie ) && target.is_zombie ) + { + } + else + { + target thread player_nuke( player ); + } + _k2278 = getNextArrayKey( _a2278, _k2278 ); + } +} + +turned_powerup_red_ammo( player ) +{ + level thread maps/mp/zombies/_zm_powerups::empty_clip_powerup( self ); +} + +turned_powerup_red_double( player ) +{ + level thread maps/mp/zombies/_zm_powerups::double_points_powerup( self, player ); +} + +turned_powerup_yellow_double( player ) +{ + level thread maps/mp/zombies/_zm_powerups::double_points_powerup( self, player ); +} + +turned_powerup_yellow_nuke( player ) +{ + location = self.origin; + playfx( level.zombie_powerups[ "nuke" ].fx, location ); + level thread maps/mp/zombies/_zm_powerups::nuke_flash(); + players = get_players(); + _a2315 = players; + _k2315 = getFirstArrayKey( _a2315 ); + while ( isDefined( _k2315 ) ) + { + target = _a2315[ _k2315 ]; + if ( !cleansed_alive_check( target ) ) + { + } + else + { + if ( isDefined( target.team != player.team ) && target.team != player.team ) + { + target thread player_nuke( player ); + } + } + _k2315 = getNextArrayKey( _a2315, _k2315 ); + } +} + +playturnedmusic() +{ + ent = spawn( "script_origin", ( 0, 0, 0 ) ); + ent thread stopturnedmusic(); + playsoundatposition( "mus_zmb_gamemode_start", ( 0, 0, 0 ) ); + wait 5; + ent playloopsound( "mus_zmb_gamemode_loop", 5 ); +} + +stopturnedmusic() +{ + level waittill( "end_game" ); + self stoploopsound( 1,5 ); + wait 1; + self delete(); +} diff --git a/zm_buried_patch/maps/mp/gametypes_zm/zgrief.gsc b/zm_buried_patch/maps/mp/gametypes_zm/zgrief.gsc new file mode 100644 index 0000000..b95d550 --- /dev/null +++ b/zm_buried_patch/maps/mp/gametypes_zm/zgrief.gsc @@ -0,0 +1,876 @@ +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_weap_cymbal_monkey; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_game_module_meat_utility; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/gametypes_zm/zmeat; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_utility; +#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.custom_spectate_permissions = ::setspectatepermissionsgrief; + 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::grief_custom_stat_update; + level._game_module_player_damage_callback = ::maps/mp/gametypes_zm/_zm_gametype::game_module_player_damage_callback; + level.custom_end_screen = ::custom_end_screen; + level.gamemode_map_postinit[ "zgrief" ] = ::postinit_func; + level._supress_survived_screen = 1; + level.game_module_team_name_override_og_x = 155; + level.prevent_player_damage = ::player_prevent_damage; + level._game_module_player_damage_grief_callback = ::game_module_player_damage_grief_callback; + level._grief_reset_message = ::grief_reset_message; + level._game_module_player_laststand_callback = ::grief_laststand_weapon_save; + level.onplayerspawned_restore_previous_weapons = ::grief_laststand_weapons_return; + level.game_module_onplayerconnect = ::grief_onplayerconnect; + level.game_mode_spawn_player_logic = ::game_mode_spawn_player_logic; + level.game_mode_custom_onplayerdisconnect = ::grief_onplayerdisconnect; + maps/mp/gametypes_zm/_zm_gametype::post_gametype_main( "zgrief" ); +} + +grief_onplayerconnect() +{ + self thread move_team_icons(); + self thread maps/mp/gametypes_zm/zmeat::create_item_meat_watcher(); + self thread zgrief_player_bled_out_msg(); +} + +grief_onplayerdisconnect( disconnecting_player ) +{ + level thread update_players_on_bleedout_or_disconnect( disconnecting_player ); +} + +setspectatepermissionsgrief() +{ + self allowspectateteam( "allies", 1 ); + self allowspectateteam( "axis", 1 ); + self allowspectateteam( "freelook", 0 ); + self allowspectateteam( "none", 1 ); +} + +custom_end_screen() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ].game_over_hud = newclienthudelem( players[ i ] ); + players[ i ].game_over_hud.alignx = "center"; + players[ i ].game_over_hud.aligny = "middle"; + players[ i ].game_over_hud.horzalign = "center"; + players[ i ].game_over_hud.vertalign = "middle"; + players[ i ].game_over_hud.y -= 130; + players[ i ].game_over_hud.foreground = 1; + players[ i ].game_over_hud.fontscale = 3; + players[ i ].game_over_hud.alpha = 0; + players[ i ].game_over_hud.color = ( 1, 1, 1 ); + players[ i ].game_over_hud.hidewheninmenu = 1; + players[ i ].game_over_hud settext( &"ZOMBIE_GAME_OVER" ); + players[ i ].game_over_hud fadeovertime( 1 ); + players[ i ].game_over_hud.alpha = 1; + if ( players[ i ] issplitscreen() ) + { + players[ i ].game_over_hud.fontscale = 2; + players[ i ].game_over_hud.y += 40; + } + players[ i ].survived_hud = newclienthudelem( players[ i ] ); + players[ i ].survived_hud.alignx = "center"; + players[ i ].survived_hud.aligny = "middle"; + players[ i ].survived_hud.horzalign = "center"; + players[ i ].survived_hud.vertalign = "middle"; + players[ i ].survived_hud.y -= 100; + players[ i ].survived_hud.foreground = 1; + players[ i ].survived_hud.fontscale = 2; + players[ i ].survived_hud.alpha = 0; + players[ i ].survived_hud.color = ( 1, 1, 1 ); + players[ i ].survived_hud.hidewheninmenu = 1; + if ( players[ i ] issplitscreen() ) + { + players[ i ].survived_hud.fontscale = 1,5; + players[ i ].survived_hud.y += 40; + } + winner_text = &"ZOMBIE_GRIEF_WIN"; + loser_text = &"ZOMBIE_GRIEF_LOSE"; + if ( level.round_number < 2 ) + { + winner_text = &"ZOMBIE_GRIEF_WIN_SINGLE"; + loser_text = &"ZOMBIE_GRIEF_LOSE_SINGLE"; + } + if ( isDefined( level.host_ended_game ) && level.host_ended_game ) + { + players[ i ].survived_hud settext( &"MP_HOST_ENDED_GAME" ); + } + else + { + if ( isDefined( level.gamemodulewinningteam ) && players[ i ]._encounters_team == level.gamemodulewinningteam ) + { + players[ i ].survived_hud settext( winner_text, level.round_number ); + break; + } + else + { + players[ i ].survived_hud settext( loser_text, level.round_number ); + } + } + players[ i ].survived_hud fadeovertime( 1 ); + players[ i ].survived_hud.alpha = 1; + i++; + } +} + +postinit_func() +{ + level.min_humans = 1; + level.zombie_ai_limit = 24; + level.prevent_player_damage = ::player_prevent_damage; + level.lock_player_on_team_score = 1; + level._zombiemode_powerup_grab = ::meat_stink_powerup_grab; + level.meat_bounce_override = ::meat_bounce_override; + level._zombie_spawning = 0; + level._get_game_module_players = undefined; + level.powerup_drop_count = 0; + level.is_zombie_level = 1; + level._effect[ "meat_impact" ] = loadfx( "maps/zombie/fx_zmb_meat_impact" ); + level._effect[ "spawn_cloud" ] = loadfx( "maps/zombie/fx_zmb_race_zombie_spawn_cloud" ); + level._effect[ "meat_stink_camera" ] = loadfx( "maps/zombie/fx_zmb_meat_stink_camera" ); + level._effect[ "meat_stink_torso" ] = loadfx( "maps/zombie/fx_zmb_meat_stink_torso" ); + include_powerup( "meat_stink" ); + maps/mp/zombies/_zm_powerups::add_zombie_powerup( "meat_stink", "t6_wpn_zmb_meat_world", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_drop_meat, 0, 0, 0 ); + setmatchtalkflag( "DeadChatWithDead", 1 ); + setmatchtalkflag( "DeadChatWithTeam", 1 ); + setmatchtalkflag( "DeadHearTeamLiving", 1 ); + setmatchtalkflag( "DeadHearAllLiving", 1 ); + setmatchtalkflag( "EveryoneHearsEveryone", 1 ); +} + +func_should_drop_meat() +{ + if ( minigun_no_drop() ) + { + return 0; + } + return 1; +} + +minigun_no_drop() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].ignoreme == 1 ) + { + return 1; + } + i++; + } + if ( isDefined( level.meat_on_ground ) && level.meat_on_ground ) + { + return 1; + } + return 0; +} + +grief_game_end_check_func() +{ + return 0; +} + +player_prevent_damage( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( isDefined( eattacker ) && isplayer( eattacker ) && self != eattacker && !eattacker hasperk( "specialty_noname" ) && isDefined( self.is_zombie ) && !self.is_zombie ) + { + return 1; + } + return 0; +} + +game_module_player_damage_grief_callback( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + penalty = 10; + if ( isDefined( eattacker ) && isplayer( eattacker ) && eattacker != self && eattacker.team != self.team && smeansofdeath == "MOD_MELEE" ) + { + self applyknockback( idamage, vdir ); + } +} + +onprecachegametype() +{ + level.playersuicideallowed = 1; + level.canplayersuicide = ::canplayersuicide; + level.suicide_weapon = "death_self_zm"; + precacheitem( "death_self_zm" ); + precacheshellshock( "grief_stab_zm" ); + precacheshader( "faction_cdc" ); + precacheshader( "faction_cia" ); + precacheshader( "waypoint_revive_cdc_zm" ); + precacheshader( "waypoint_revive_cia_zm" ); + level._effect[ "butterflies" ] = loadfx( "maps/zombie/fx_zmb_impact_noharm" ); + level thread maps/mp/zombies/_zm_game_module_meat_utility::init_item_meat( "zgrief" ); + level thread maps/mp/gametypes_zm/_zm_gametype::init(); + maps/mp/gametypes_zm/_zm_gametype::rungametypeprecache( "zgrief" ); +} + +onstartgametype() +{ + level.no_end_game_check = 1; + level._game_module_game_end_check = ::grief_game_end_check_func; + level.round_end_custom_logic = ::grief_round_end_custom_logic; + maps/mp/gametypes_zm/_zm_gametype::setup_classic_gametype(); + maps/mp/gametypes_zm/_zm_gametype::rungametypemain( "zgrief", ::zgrief_main ); +} + +zgrief_main() +{ + level thread maps/mp/zombies/_zm::round_start(); + level thread maps/mp/gametypes_zm/_zm_gametype::kill_all_zombies(); + flag_wait( "initial_blackscreen_passed" ); + level thread maps/mp/zombies/_zm_game_module::wait_for_team_death_and_round_end(); + players = get_players(); + _a302 = players; + _k302 = getFirstArrayKey( _a302 ); + while ( isDefined( _k302 ) ) + { + player = _a302[ _k302 ]; + player.is_hotjoin = 0; + _k302 = getNextArrayKey( _a302, _k302 ); + } + wait 1; + playsoundatposition( "vox_zmba_grief_intro_0", ( 1, 1, 1 ) ); +} + +move_team_icons() +{ + self endon( "disconnect" ); + flag_wait( "initial_blackscreen_passed" ); + wait 0,5; +} + +kill_start_chest() +{ + flag_wait( "initial_blackscreen_passed" ); + wait 2; + start_chest = getstruct( "start_chest", "script_noteworthy" ); + start_chest maps/mp/zombies/_zm_magicbox::hide_chest(); +} + +meat_stink_powerup_grab( powerup, who ) +{ + switch( powerup.powerup_name ) + { + case "meat_stink": + level thread meat_stink( who ); + break; + } +} + +meat_stink( who ) +{ + weapons = who getweaponslist(); + has_meat = 0; + _a353 = weapons; + _k353 = getFirstArrayKey( _a353 ); + while ( isDefined( _k353 ) ) + { + weapon = _a353[ _k353 ]; + if ( weapon == "item_meat_zm" ) + { + has_meat = 1; + } + _k353 = getNextArrayKey( _a353, _k353 ); + } + if ( has_meat ) + { + return; + } + who.pre_meat_weapon = who getcurrentweapon(); + level notify( "meat_grabbed" ); + who notify( "meat_grabbed" ); + who playsound( "zmb_pickup_meat" ); + who increment_is_drinking(); + who giveweapon( "item_meat_zm" ); + who switchtoweapon( "item_meat_zm" ); + who setweaponammoclip( "item_meat_zm", 1 ); +} + +meat_stink_on_ground( position_to_play ) +{ + level.meat_on_ground = 1; + attractor_point = spawn( "script_model", position_to_play ); + attractor_point setmodel( "tag_origin" ); + attractor_point playsound( "zmb_land_meat" ); + wait 0,2; + playfxontag( level._effect[ "meat_stink_torso" ], attractor_point, "tag_origin" ); + attractor_point playloopsound( "zmb_meat_flies" ); + attractor_point create_zombie_point_of_interest( 1536, 32, 10000 ); + attractor_point.attract_to_origin = 1; + attractor_point thread create_zombie_point_of_interest_attractor_positions( 4, 45 ); + attractor_point thread maps/mp/zombies/_zm_weap_cymbal_monkey::wait_for_attractor_positions_complete(); + attractor_point delay_thread( 15, ::self_delete ); + wait 16; + level.meat_on_ground = undefined; +} + +meat_bounce_override( pos, normal, ent ) +{ + if ( isDefined( ent ) && isplayer( ent ) ) + { + if ( !ent maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + level thread meat_stink_player( ent ); + if ( isDefined( self.owner ) ) + { + maps/mp/_demo::bookmark( "zm_player_meat_stink", getTime(), ent, self.owner, 0, self ); + self.owner maps/mp/zombies/_zm_stats::increment_client_stat( "contaminations_given" ); + } + } + } + else + { + players = getplayers(); + closest_player = undefined; + closest_player_dist = 10000; + player_index = 0; + while ( player_index < players.size ) + { + player_to_check = players[ player_index ]; + if ( self.owner == player_to_check ) + { + player_index++; + continue; + } + else if ( player_to_check maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + player_index++; + continue; + } + else + { + distsq = distancesquared( pos, player_to_check.origin ); + if ( distsq < closest_player_dist ) + { + closest_player = player_to_check; + closest_player_dist = distsq; + } + } + player_index++; + } + if ( isDefined( closest_player ) ) + { + level thread meat_stink_player( closest_player ); + if ( isDefined( self.owner ) ) + { + maps/mp/_demo::bookmark( "zm_player_meat_stink", getTime(), closest_player, self.owner, 0, self ); + self.owner maps/mp/zombies/_zm_stats::increment_client_stat( "contaminations_given" ); + } + } + else + { + valid_poi = check_point_in_enabled_zone( pos, undefined, undefined ); + if ( valid_poi ) + { + self hide(); + level thread meat_stink_on_ground( self.origin ); + } + } + playfx( level._effect[ "meat_impact" ], self.origin ); + } + self delete(); +} + +meat_stink_player( who ) +{ + level notify( "new_meat_stink_player" ); + level endon( "new_meat_stink_player" ); + who.ignoreme = 0; + players = get_players(); + _a486 = players; + _k486 = getFirstArrayKey( _a486 ); + while ( isDefined( _k486 ) ) + { + player = _a486[ _k486 ]; + player thread meat_stink_player_cleanup(); + if ( player != who ) + { + player.ignoreme = 1; + } + _k486 = getNextArrayKey( _a486, _k486 ); + } + who thread meat_stink_player_create(); + who waittill_any_or_timeout( 30, "disconnect", "player_downed", "bled_out" ); + players = get_players(); + _a501 = players; + _k501 = getFirstArrayKey( _a501 ); + while ( isDefined( _k501 ) ) + { + player = _a501[ _k501 ]; + player thread meat_stink_player_cleanup(); + player.ignoreme = 0; + _k501 = getNextArrayKey( _a501, _k501 ); + } +} + +meat_stink_player_create() +{ + self maps/mp/zombies/_zm_stats::increment_client_stat( "contaminations_received" ); + self endon( "disconnect" ); + self endon( "death" ); + tagname = "J_SpineLower"; + self.meat_stink_3p = spawn( "script_model", self gettagorigin( tagname ) ); + self.meat_stink_3p setmodel( "tag_origin" ); + self.meat_stink_3p linkto( self, tagname ); + wait 0,5; + playfxontag( level._effect[ "meat_stink_torso" ], self.meat_stink_3p, "tag_origin" ); + self setclientfieldtoplayer( "meat_stink", 1 ); +} + +meat_stink_player_cleanup() +{ + if ( isDefined( self.meat_stink_3p ) ) + { + self.meat_stink_3p unlink(); + self.meat_stink_3p delete(); + } + self setclientfieldtoplayer( "meat_stink", 0 ); +} + +door_close_zombie_think() +{ + self endon( "death" ); + while ( isalive( self ) ) + { + if ( isDefined( self.enemy ) && isplayer( self.enemy ) ) + { + insamezone = 0; + keys = getarraykeys( level.zones ); + i = 0; + while ( i < keys.size ) + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( keys[ i ] ) && self.enemy maps/mp/zombies/_zm_zonemgr::entity_in_zone( keys[ i ] ) ) + { + insamezone = 1; + } + i++; + } + while ( insamezone ) + { + wait 3; + } + nearestzombienode = getnearestnode( self.origin ); + nearestplayernode = getnearestnode( self.enemy.origin ); + if ( isDefined( nearestzombienode ) && isDefined( nearestplayernode ) ) + { + if ( !nodesvisible( nearestzombienode, nearestplayernode ) && !nodescanpath( nearestzombienode, nearestplayernode ) ) + { + self silentlyremovezombie(); + } + } + } + wait 1; + } +} + +silentlyremovezombie() +{ + level.zombie_total++; + playfx( level._effect[ "spawn_cloud" ], self.origin ); + self.skip_death_notetracks = 1; + self.nodeathragdoll = 1; + self dodamage( self.maxhealth * 2, self.origin, self, self, "none", "MOD_SUICIDE" ); + self self_delete(); +} + +zgrief_player_bled_out_msg() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "bled_out" ); + level thread update_players_on_bleedout_or_disconnect( self ); + } +} + +show_grief_hud_msg( msg, msg_parm, offset, cleanup_end_game ) +{ + self endon( "disconnect" ); + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0,05; + } + zgrief_hudmsg = newclienthudelem( self ); + zgrief_hudmsg.alignx = "center"; + zgrief_hudmsg.aligny = "middle"; + zgrief_hudmsg.horzalign = "center"; + zgrief_hudmsg.vertalign = "middle"; + zgrief_hudmsg.y -= 130; + if ( self issplitscreen() ) + { + zgrief_hudmsg.y += 70; + } + if ( isDefined( offset ) ) + { + zgrief_hudmsg.y += offset; + } + zgrief_hudmsg.foreground = 1; + zgrief_hudmsg.fontscale = 5; + zgrief_hudmsg.alpha = 0; + zgrief_hudmsg.color = ( 1, 1, 1 ); + zgrief_hudmsg.hidewheninmenu = 1; + zgrief_hudmsg.font = "default"; + if ( isDefined( cleanup_end_game ) && cleanup_end_game ) + { + level endon( "end_game" ); + zgrief_hudmsg thread show_grief_hud_msg_cleanup(); + } + if ( isDefined( msg_parm ) ) + { + zgrief_hudmsg settext( msg, msg_parm ); + } + else + { + zgrief_hudmsg settext( msg ); + } + zgrief_hudmsg changefontscaleovertime( 0,25 ); + zgrief_hudmsg fadeovertime( 0,25 ); + zgrief_hudmsg.alpha = 1; + zgrief_hudmsg.fontscale = 2; + wait 3,25; + zgrief_hudmsg changefontscaleovertime( 1 ); + zgrief_hudmsg fadeovertime( 1 ); + zgrief_hudmsg.alpha = 0; + zgrief_hudmsg.fontscale = 5; + wait 1; + zgrief_hudmsg notify( "death" ); + if ( isDefined( zgrief_hudmsg ) ) + { + zgrief_hudmsg destroy(); + } +} + +show_grief_hud_msg_cleanup() +{ + self endon( "death" ); + level waittill( "end_game" ); + if ( isDefined( self ) ) + { + self destroy(); + } +} + +grief_reset_message() +{ + msg = &"ZOMBIE_GRIEF_RESET"; + players = get_players(); + if ( isDefined( level.hostmigrationtimer ) ) + { + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0,05; + } + wait 4; + } + _a697 = players; + _k697 = getFirstArrayKey( _a697 ); + while ( isDefined( _k697 ) ) + { + player = _a697[ _k697 ]; + player thread show_grief_hud_msg( msg ); + _k697 = getNextArrayKey( _a697, _k697 ); + } + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "grief_restarted" ); +} + +grief_laststand_weapon_save( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + self.grief_savedweapon_weapons = self getweaponslist(); + self.grief_savedweapon_weaponsammo_stock = []; + self.grief_savedweapon_weaponsammo_clip = []; + self.grief_savedweapon_currentweapon = self getcurrentweapon(); + self.grief_savedweapon_grenades = self get_player_lethal_grenade(); + if ( isDefined( self.grief_savedweapon_grenades ) ) + { + self.grief_savedweapon_grenades_clip = self getweaponammoclip( self.grief_savedweapon_grenades ); + } + self.grief_savedweapon_tactical = self get_player_tactical_grenade(); + if ( isDefined( self.grief_savedweapon_tactical ) ) + { + self.grief_savedweapon_tactical_clip = self getweaponammoclip( self.grief_savedweapon_tactical ); + } + i = 0; + while ( i < self.grief_savedweapon_weapons.size ) + { + self.grief_savedweapon_weaponsammo_clip[ i ] = self getweaponammoclip( self.grief_savedweapon_weapons[ i ] ); + self.grief_savedweapon_weaponsammo_stock[ i ] = self getweaponammostock( self.grief_savedweapon_weapons[ i ] ); + i++; + } + if ( isDefined( self.hasriotshield ) && self.hasriotshield ) + { + self.grief_hasriotshield = 1; + } + if ( self hasweapon( "claymore_zm" ) ) + { + self.grief_savedweapon_claymore = 1; + self.grief_savedweapon_claymore_clip = self getweaponammoclip( "claymore_zm" ); + } + if ( isDefined( self.current_equipment ) ) + { + self.grief_savedweapon_equipment = self.current_equipment; + } +} + +grief_laststand_weapons_return() +{ + if ( isDefined( level.isresetting_grief ) && !level.isresetting_grief ) + { + return 0; + } + if ( !isDefined( self.grief_savedweapon_weapons ) ) + { + return 0; + } + primary_weapons_returned = 0; + _a766 = self.grief_savedweapon_weapons; + index = getFirstArrayKey( _a766 ); + while ( isDefined( index ) ) + { + weapon = _a766[ index ]; + if ( isDefined( self.grief_savedweapon_grenades ) || weapon == self.grief_savedweapon_grenades && isDefined( self.grief_savedweapon_tactical ) && weapon == self.grief_savedweapon_tactical ) + { + } + else + { + if ( isweaponprimary( weapon ) ) + { + if ( primary_weapons_returned >= 2 ) + { + break; + } + else primary_weapons_returned++; + } + if ( weapon == "item_meat_zm" ) + { + break; + } + else + { + self giveweapon( weapon, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + if ( isDefined( self.grief_savedweapon_weaponsammo_clip[ index ] ) ) + { + self setweaponammoclip( weapon, self.grief_savedweapon_weaponsammo_clip[ index ] ); + } + if ( isDefined( self.grief_savedweapon_weaponsammo_stock[ index ] ) ) + { + self setweaponammostock( weapon, self.grief_savedweapon_weaponsammo_stock[ index ] ); + } + } + } + index = getNextArrayKey( _a766, index ); + } + if ( isDefined( self.grief_savedweapon_grenades ) ) + { + self giveweapon( self.grief_savedweapon_grenades ); + if ( isDefined( self.grief_savedweapon_grenades_clip ) ) + { + self setweaponammoclip( self.grief_savedweapon_grenades, self.grief_savedweapon_grenades_clip ); + } + } + if ( isDefined( self.grief_savedweapon_tactical ) ) + { + self giveweapon( self.grief_savedweapon_tactical ); + if ( isDefined( self.grief_savedweapon_tactical_clip ) ) + { + self setweaponammoclip( self.grief_savedweapon_tactical, self.grief_savedweapon_tactical_clip ); + } + } + if ( isDefined( self.current_equipment ) ) + { + self maps/mp/zombies/_zm_equipment::equipment_take( self.current_equipment ); + } + if ( isDefined( self.grief_savedweapon_equipment ) ) + { + self.do_not_display_equipment_pickup_hint = 1; + self maps/mp/zombies/_zm_equipment::equipment_give( self.grief_savedweapon_equipment ); + self.do_not_display_equipment_pickup_hint = undefined; + } + if ( isDefined( self.grief_hasriotshield ) && self.grief_hasriotshield ) + { + if ( isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + } + if ( isDefined( self.grief_savedweapon_claymore ) && self.grief_savedweapon_claymore ) + { + self giveweapon( "claymore_zm" ); + self set_player_placeable_mine( "claymore_zm" ); + self setactionslot( 4, "weapon", "claymore_zm" ); + self setweaponammoclip( "claymore_zm", self.grief_savedweapon_claymore_clip ); + } + primaries = self getweaponslistprimaries(); + _a859 = primaries; + _k859 = getFirstArrayKey( _a859 ); + while ( isDefined( _k859 ) ) + { + weapon = _a859[ _k859 ]; + if ( isDefined( self.grief_savedweapon_currentweapon ) && self.grief_savedweapon_currentweapon == weapon ) + { + self switchtoweapon( weapon ); + return 1; + } + _k859 = getNextArrayKey( _a859, _k859 ); + } + if ( primaries.size > 0 ) + { + self switchtoweapon( primaries[ 0 ] ); + return 1; + } +/# + assert( primaries.size > 0, "GRIEF: There was a problem restoring the weapons" ); +#/ + return 0; +} + +grief_store_player_scores() +{ + players = get_players(); + _a883 = players; + _k883 = getFirstArrayKey( _a883 ); + while ( isDefined( _k883 ) ) + { + player = _a883[ _k883 ]; + player._pre_round_score = player.score; + _k883 = getNextArrayKey( _a883, _k883 ); + } +} + +grief_restore_player_score() +{ + if ( !isDefined( self._pre_round_score ) ) + { + self._pre_round_score = self.score; + } + if ( isDefined( self._pre_round_score ) ) + { + self.score = self._pre_round_score; + self.pers[ "score" ] = self._pre_round_score; + } +} + +game_mode_spawn_player_logic() +{ + if ( flag( "start_zombie_round_logic" ) && !isDefined( self.is_hotjoin ) ) + { + self.is_hotjoin = 1; + return 1; + } + return 0; +} + +update_players_on_bleedout_or_disconnect( excluded_player ) +{ + other_team = undefined; + players = get_players(); + players_remaining = 0; + _a920 = players; + _k920 = getFirstArrayKey( _a920 ); + while ( isDefined( _k920 ) ) + { + player = _a920[ _k920 ]; + if ( player == excluded_player ) + { + } + else if ( player.team == excluded_player.team ) + { + if ( is_player_valid( player ) ) + { + players_remaining++; + } + break; + } + _k920 = getNextArrayKey( _a920, _k920 ); + } + _a937 = players; + _k937 = getFirstArrayKey( _a937 ); + while ( isDefined( _k937 ) ) + { + player = _a937[ _k937 ]; + if ( player == excluded_player ) + { + } + else if ( player.team != excluded_player.team ) + { + other_team = player.team; + if ( players_remaining < 1 ) + { + player thread show_grief_hud_msg( &"ZOMBIE_ZGRIEF_ALL_PLAYERS_DOWN", undefined, undefined, 1 ); + player delay_thread_watch_host_migrate( 2, ::show_grief_hud_msg, &"ZOMBIE_ZGRIEF_SURVIVE", undefined, 30, 1 ); + break; + } + else + { + player thread show_grief_hud_msg( &"ZOMBIE_ZGRIEF_PLAYER_BLED_OUT", players_remaining ); + } + } + _k937 = getNextArrayKey( _a937, _k937 ); + } + if ( players_remaining == 1 ) + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "last_player", excluded_player.team ); + } + if ( !isDefined( other_team ) ) + { + return; + } + if ( players_remaining < 1 ) + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "4_player_down", other_team ); + } + else + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( players_remaining + "_player_left", other_team ); + } +} + +delay_thread_watch_host_migrate( timer, func, param1, param2, param3, param4, param5, param6 ) +{ + self thread _delay_thread_watch_host_migrate_proc( func, timer, param1, param2, param3, param4, param5, param6 ); +} + +_delay_thread_watch_host_migrate_proc( func, timer, param1, param2, param3, param4, param5, param6 ) +{ + self endon( "death" ); + self endon( "disconnect" ); + wait timer; + if ( isDefined( level.hostmigrationtimer ) ) + { + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0,05; + } + wait timer; + } + single_thread( self, func, param1, param2, param3, param4, param5, param6 ); +} + +grief_round_end_custom_logic() +{ + waittillframeend; + if ( isDefined( level.gamemodulewinningteam ) ) + { + level notify( "end_round_think" ); + } +} diff --git a/zm_buried_patch/maps/mp/gametypes_zm/zmeat.gsc b/zm_buried_patch/maps/mp/gametypes_zm/zmeat.gsc new file mode 100644 index 0000000..c4f2ad5 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/gametypes_zm/zstandard.gsc b/zm_buried_patch/maps/mp/gametypes_zm/zstandard.gsc new file mode 100644 index 0000000..95e51ef --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/teams/_teamset_cdc.gsc b/zm_buried_patch/maps/mp/teams/_teamset_cdc.gsc new file mode 100644 index 0000000..62ec842 --- /dev/null +++ b/zm_buried_patch/maps/mp/teams/_teamset_cdc.gsc @@ -0,0 +1,51 @@ + +register() +{ + game[ "teamset" ] = []; + game[ "teamset" ][ "cdc" ] = ::cdc; +} + +level_init() +{ + game[ "allies" ] = "cdc"; + game[ "axis" ] = "cia"; + setdvar( "g_TeamName_Allies", &"ZMUI_CDC_SHORT" ); + setdvar( "g_TeamName_Axis", &"ZMUI_CIA_SHORT" ); + game[ "strings" ][ "allies_win" ] = &"ZM_CDC_WIN_MATCH"; + game[ "strings" ][ "allies_win_round" ] = &"ZM_CDC_WIN_ROUND"; + game[ "strings" ][ "allies_mission_accomplished" ] = &"ZM_CDC_MISSION_ACCOMPLISHED"; + game[ "strings" ][ "allies_eliminated" ] = &"ZM_CDC_ELIMINATED"; + game[ "strings" ][ "allies_forfeited" ] = &"ZM_CDC_FORFEITED"; + game[ "strings" ][ "allies_name" ] = &"ZM_CDC_NAME"; + game[ "music" ][ "spawn_allies" ] = "SPAWN_OPS"; + game[ "music" ][ "victory_allies" ] = "mus_victory_usa"; + game[ "icons" ][ "allies" ] = "faction_cdc"; + game[ "colors" ][ "allies" ] = ( 0, 0, 0 ); + game[ "voice" ][ "allies" ] = "vox_st6_"; + setdvar( "scr_allies", "marines" ); + game[ "strings" ][ "axis_win" ] = &"ZM_CIA_WIN_MATCH"; + game[ "strings" ][ "axis_win_round" ] = &"ZM_CIA_WIN_ROUND"; + game[ "strings" ][ "axis_mission_accomplished" ] = &"ZM_CIA_MISSION_ACCOMPLISHED"; + game[ "strings" ][ "axis_eliminated" ] = &"ZM_CIA_ELIMINATED"; + game[ "strings" ][ "axis_forfeited" ] = &"ZM_CIA_FORFEITED"; + game[ "strings" ][ "axis_name" ] = &"ZM_CIA_NAME"; + game[ "music" ][ "spawn_axis" ] = "SPAWN_RUS"; + game[ "music" ][ "victory_axis" ] = "mus_victory_soviet"; + game[ "icons" ][ "axis" ] = "faction_cia"; + game[ "colors" ][ "axis" ] = ( 0,65, 0,57, 0,41 ); + game[ "voice" ][ "axis" ] = "vox_pmc_"; +} + +cdc() +{ + allies(); + axis(); +} + +allies() +{ +} + +axis() +{ +} diff --git a/zm_buried_patch/maps/mp/zm_buried.gsc b/zm_buried_patch/maps/mp/zm_buried.gsc new file mode 100644 index 0000000..7db1046 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried.gsc @@ -0,0 +1,2517 @@ +#include maps/mp/zm_buried; +#include maps/mp/zombies/_zm_equip_headchopper; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_ai_faller; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_devgui; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zm_buried_classic; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_weap_time_bomb; +#include maps/mp/zm_buried_jail; +#include maps/mp/zombies/_zm_perk_vulture; +#include maps/mp/zombies/_zm_perk_divetonuke; +#include maps/mp/gametypes_zm/_spawning; +#include maps/mp/teams/_teamset_cdc; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zm_buried_buildables; +#include maps/mp/zm_buried_ffotd; +#include maps/mp/zm_buried_distance_tracking; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +gamemode_callback_setup() +{ + maps/mp/zm_buried_gamemodes::init(); +} + +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; + zm_buried_common_init(); + flag_wait( "start_zombie_round_logic" ); +} + +zstandard_preinit() +{ + survival_init(); +} + +zcleansed_preinit() +{ + level._zcleansed_weapon_progression = array( "judge_zm", "srm1216_zm", "hk416_zm", "qcw05_zm", "kard_zm" ); + level.cymbal_monkey_clone_weapon = "srm1216_zm"; + trig_removal = getentarray( "zombie_door", "targetname" ); + _a52 = trig_removal; + _k52 = getFirstArrayKey( _a52 ); + while ( isDefined( _k52 ) ) + { + trig = _a52[ _k52 ]; + if ( isDefined( trig.script_parameters ) && trig.script_parameters == "grief_remove" ) + { + trig delete(); + } + if ( isDefined( trig.script_parameters ) && trig.script_parameters == "zcleansed_remove" ) + { + parts = getentarray( trig.target, "targetname" ); + while ( isDefined( parts ) ) + { + i = 0; + while ( i < parts.size ) + { + parts[ i ] delete(); + i++; + } + } + trig delete(); + } + _k52 = getNextArrayKey( _a52, _k52 ); + } + survival_init(); +} + +zgrief_preinit() +{ + registerclientfield( "toplayer", "meat_stink", 1, 1, "int" ); + zgrief_init(); +} + +zgrief_init() +{ + encounter_init(); + zm_buried_common_init(); + flag_wait( "start_zombie_round_logic" ); + trig_removal = getentarray( "zombie_door", "targetname" ); + _a92 = trig_removal; + _k92 = getFirstArrayKey( _a92 ); + while ( isDefined( _k92 ) ) + { + trig = _a92[ _k92 ]; + if ( isDefined( trig.script_parameters ) && trig.script_parameters == "grief_remove" ) + { + trig delete(); + } + _k92 = getNextArrayKey( _a92, _k92 ); + } +} + +encounter_init() +{ + level.precachecustomcharacters = ::precache_team_characters; + level.givecustomcharacters = ::give_team_characters; +} + +createfx_callback() +{ + ents = getentarray(); + i = 0; + while ( i < ents.size ) + { + if ( ents[ i ].classname != "info_player_start" ) + { + ents[ i ] delete(); + } + i++; + } +} + +zclassic_init() +{ + level.precachecustomcharacters = ::precache_personality_characters; + level.givecustomcharacters = ::give_personality_characters; + level.setupcustomcharacterexerts = ::setup_personality_character_exerts; + level.check_valid_poi = ::check_valid_poi; + level.tear_into_position = ::tear_into_position; + level.tear_into_wait = ::tear_into_wait; + level.melee_miss_func = ::melee_miss_func; + precachemodel( "p6_zm_keycard" ); + zm_buried_common_init(); + level.banking_map = "zm_transit"; + level.weapon_locker_map = "zm_transit"; + level thread maps/mp/zombies/_zm_banking::init(); + level.disable_free_perks_before_power = 1; + maps/mp/zm_buried_sq::sq_buried_clientfield_init(); + flag_wait( "start_zombie_round_logic" ); + level thread maps/mp/zombies/_zm_weapon_locker::main(); + level thread maps/mp/zombies/_zm_banking::main(); + level thread collapsing_catwalk_init(); + level thread maps/mp/zm_buried_distance_tracking::zombie_tracking_init(); + maps/mp/zombies/_zm_weapons::register_zombie_weapon_callback( "lsat_zm", ::player_give_lsat ); +} + +zclassic_preinit() +{ + zclassic_init(); +} + +zmaxis_preinit() +{ + zmaxis_init(); +} + +zmaxis_init() +{ + encounter_init(); + zm_buried_common_init(); + flag_wait( "start_zombie_round_logic" ); +} + +zrichtofen_preinit() +{ + zrichtofen_init(); +} + +zrichtofen_init() +{ + encounter_init(); + zm_buried_common_init(); + flag_wait( "start_zombie_round_logic" ); +} + +zm_buried_common_init() +{ + num_bits = 2; + registerclientfield( "world", "GENERATOR_POWER_STATES", 12000, num_bits, "int" ); + registerclientfield( "world", "GENERATOR_POWER_STATES_COLOR", 12000, 1, "int" ); + registerclientfield( "world", "GENERATOR_POWER_STATES_LERP", 12000, 5, "float" ); + registerclientfield( "world", "cw_fall", 12000, 1, "int" ); + registerclientfield( "world", "maze_fountain_start", 12000, 1, "int" ); + registerclientfield( "world", "sloth_fountain_start", 12000, 1, "int" ); + registerclientfield( "world", "mansion_piano_play", 12000, 1, "int" ); + registerclientfield( "world", "saloon_piano_play", 12000, 1, "int" ); + registerclientfield( "world", "mus_noir_snapshot_loop", 12000, 1, "int" ); + registerclientfield( "world", "mus_zmb_egg_snapshot_loop", 12000, 1, "int" ); + registerclientfield( "toplayer", "sndBackgroundMus", 12000, 3, "int" ); + registerclientfield( "toplayer", "clientfield_underground_lighting", 12000, 1, "int" ); +} + +main() +{ + maps/mp/zm_buried_fx::main(); + level thread maps/mp/zm_buried_ffotd::main_start(); + setdvarint( "sm_sunShadowSmallScriptPS3OnlyEnable", 1 ); + level.disable_fx_zmb_wall_buy_semtex = 1; + level.disable_fx_zmb_tranzit_shield_explo = 1; + level.default_game_mode = "zclassic"; + level.default_start_location = "processing"; + setup_rex_starts(); + level.disable_blackscreen_clientfield = 1; + level.disable_deadshot_clientfield = 1; + level.custom_zombie_player_loadout_init = 1; + maps/mp/zm_buried_buildables::prepare_chalk_weapon_list(); + level.fx_exclude_edge_fog = 1; + level.fx_exclude_tesla_head_light = 1; + level.fx_exclude_default_explosion = 1; + level.fx_exclude_default_eye_glow = 1; + maps/mp/zombies/_zm::init_fx(); + maps/mp/animscripts/zm_death::precache_gib_fx(); + level.zombiemode = 1; + level._no_water_risers = 1; + level._foliage_risers = 1; + maps/mp/zm_buried_amb::main(); + maps/mp/zombies/_zm_ai_ghost::precache_fx(); + maps/mp/zombies/_zm_ai_sloth::precache(); + maps/mp/zm_buried_sq::precache_sq(); + level.level_specific_stats_init = ::init_buried_stats; + maps/mp/zombies/_load::main(); + setdvar( "zombiemode_path_minz_bias", 13 ); + if ( getDvar( "createfx" ) != "" ) + { + return; + } + maps/mp/teams/_teamset_cdc::level_init(); + maps/mp/gametypes_zm/_spawning::level_use_unified_spawning( 1 ); + level.givecustomloadout = ::givecustomloadout; + level.custom_player_fake_death = ::zm_player_fake_death; + level.custom_player_fake_death_cleanup = ::zm_player_fake_death_cleanup; + level.initial_round_wait_func = ::initial_round_wait_func; + level.level_specific_init_powerups = ::add_buried_powerups; + 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_revive_perk = 1; + level.zombiemode_using_sleightofhand_perk = 1; + level.zombiemode_using_additionalprimaryweapon_perk = 1; + level.zombiemode_using_marathon_perk = 1; + if ( is_gametype_active( "zclassic" ) ) + { + maps/mp/zombies/_zm_perk_divetonuke::enable_divetonuke_perk_for_level(); + maps/mp/zombies/_zm_perk_vulture::enable_vulture_perk_for_level(); + } + maps/mp/zm_buried_jail::init_jail_animtree(); + init_persistent_abilities(); + level.register_offhand_weapons_for_level_defaults_override = ::offhand_weapon_overrride; + level.zombiemode_offhand_weapon_give_override = ::offhand_weapon_give_override; + level._zombie_custom_add_weapons = ::custom_add_weapons; + level._allow_melee_weapon_switching = 1; + if ( is_gametype_active( "zclassic" ) ) + { + level.custom_ai_type = []; + level.custom_ai_type[ level.custom_ai_type.size ] = ::maps/mp/zombies/_zm_ai_ghost::init; + level.custom_ai_type[ level.custom_ai_type.size ] = ::maps/mp/zombies/_zm_ai_sloth::init; + level.sloth_enable = 1; + } + level._zmbvoxlevelspecific = ::init_level_specific_audio; + maps/mp/zm_buried_jail::init_jail(); + include_weapons(); + include_powerups(); + include_equipment_for_level(); + init_level_specific_wall_buy_fx(); + registerclientfield( "world", "buried_sq_maxis_eye_glow_override", 12000, 1, "int" ); + registerclientfield( "allplayers", "buried_sq_richtofen_player_eyes_stuhlinger", 12000, 1, "int" ); + registerclientfield( "allplayers", "phd_flopper_effects", 12000, 1, "int" ); + maps/mp/zombies/_zm::init(); + if ( !sessionmodeisonlinegame() ) + { + level.pers_nube_lose_round = 0; + } + maps/mp/zombies/_zm_weap_bowie::init(); + maps/mp/zombies/_zm_weap_cymbal_monkey::init(); + maps/mp/zombies/_zm_weap_claymore::init(); + maps/mp/zombies/_zm_weap_ballistic_knife::init(); + maps/mp/zombies/_zm_weap_slowgun::init(); + level.slowgun_allow_player_paralyze = ::buried_paralyzer_check; + maps/mp/zombies/_zm_weap_tazer_knuckles::init(); + if ( is_gametype_active( "zclassic" ) ) + { + maps/mp/zombies/_zm_weap_time_bomb::init_time_bomb(); + } + level maps/mp/zm_buried_achievement::init(); + precacheitem( "death_throe_zm" ); + if ( level.splitscreen && getDvarInt( "splitscreen_playerCount" ) > 2 ) + { + level.optimise_for_splitscreen = 1; + } + else + { + level.optimise_for_splitscreen = 0; + } + maps/mp/zm_buried_maze::maze_precache(); + maps/mp/zm_buried_maze::init(); + if ( is_gametype_active( "zclassic" ) ) + { + level thread maps/mp/zm_buried_sq::init(); + } + level.zones = []; + level.zone_manager_init_func = ::buried_zone_init; + init_zones[ 0 ] = "zone_start"; + init_zones[ 1 ] = "zone_tunnels_north"; + init_zones[ 2 ] = "zone_tunnels_center"; + init_zones[ 3 ] = "zone_tunnels_south"; + init_zones[ 4 ] = "zone_stables"; + init_zones[ 5 ] = "zone_street_darkeast"; + init_zones[ 6 ] = "zone_street_darkwest"; + init_zones[ 7 ] = "zone_street_lightwest"; + init_zones[ 8 ] = "zone_street_lighteast"; + init_zones[ 9 ] = "zone_underground_bar"; + init_zones[ 10 ] = "zone_bank"; + init_zones[ 11 ] = "zone_general_store"; + init_zones[ 12 ] = "zone_candy_store"; + init_zones[ 13 ] = "zone_candy_store_floor2"; + init_zones[ 14 ] = "zone_toy_store"; + init_zones[ 15 ] = "zone_gun_store"; + init_zones[ 16 ] = "zone_underground_jail"; + init_zones[ 17 ] = "zone_start_lower"; + init_zones[ 18 ] = "zone_tunnels_south2"; + init_zones[ 19 ] = "zone_tunnels_north2"; + init_zones[ 20 ] = "zone_mansion"; + init_zones[ 21 ] = "zone_mansion_lawn"; + 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; + } + level.claymores_max_per_player /= 2; + setdvar( "fx_marks_draw", 0 ); + setdvar( "disable_rope", 1 ); + setdvar( "cg_disableplayernames", 1 ); + setdvar( "disableLookAtEntityLogic", 1 ); + } + else + { + level.zombie_ai_limit = 24; + } + level.speed_change_round = 15; + level.speed_change_max = 5; + level thread bell_watch(); + trigs = getentarray( "force_from_prone", "targetname" ); + array_thread( trigs, ::player_force_from_prone ); + level thread maps/mp/zm_buried_classic::collapsing_holes_init(); + if ( level.scr_zm_ui_gametype == "zcleansed" ) + { + level thread init_turned_zones(); + } + level.calc_closest_player_using_paths = 1; + level.validate_enemy_path_length = ::buried_validate_enemy_path_length; + level.customrandomweaponweights = ::buried_custom_weapon_weights; + level.special_weapon_magicbox_check = ::buried_special_weapon_magicbox_check; + if ( level.scr_zm_ui_gametype == "zclassic" ) + { + level thread init_fountain_zone(); + level thread maps/mp/zm_buried_classic::generator_oil_lamp_control(); + level.ignore_equipment = ::ignore_equipment; + level.ghost_zone_teleport_logic = ::buried_ghost_zone_teleport_logic; + level.ghost_zone_fountain_teleport_logic = ::ghost_zone_fountain_teleport_logic; + maps/mp/zombies/_zm_perk_vulture::add_additional_stink_locations_for_zone( "zone_bank", array( "zone_street_darkwest", "zone_gun_store" ) ); + level thread maps/mp/zombies/_zm::post_main(); + } +/# + execdevgui( "devgui_zombie_buried" ); + level.custom_devgui = ::zombie_buried_devgui; +#/ + level thread maps/mp/zm_buried_ffotd::main_end(); +} + +buried_validate_enemy_path_length( player ) +{ + max_dist = 1296; + d = distancesquared( self.origin, player.origin ); + if ( d <= max_dist ) + { + return 1; + } + return 0; +} + +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_flopper = 1; + level.divetonuke_precache_override_func = ::maps/mp/zombies/_zm_pers_upgrades_functions::divetonuke_precache_override_func; + level.pers_flopper_divetonuke_func = ::maps/mp/zombies/_zm_pers_upgrades_functions::pers_flopper_explode; + level.pers_flopper_network_optimized = 1; + 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_box_weapon = 1; + level.pers_magic_box_firesale = 1; + level.pers_treasure_chest_get_weapons_array_func = ::pers_treasure_chest_get_weapons_array_buried; + level.pers_upgrade_nube = 1; + } +} + +pers_treasure_chest_get_weapons_array_buried() +{ + if ( !isDefined( level.pers_box_weapons ) ) + { + level.pers_box_weapons = []; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "cymbal_monkey_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "ray_gun_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "raygun_mark2_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "slowgun_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "time_bomb_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "tar21_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "hamr_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "srm1216_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "knife_ballistic_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "galil_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "saiga12_zm"; + } +} + +buried_custom_weapon_weights( keys ) +{ + return keys; +} + +buried_special_weapon_magicbox_check( weapon ) +{ + if ( weapon == "ray_gun_zm" ) + { + if ( self has_weapon_or_upgrade( "raygun_mark2_zm" ) ) + { + return 0; + } + } + if ( weapon == "raygun_mark2_zm" ) + { + if ( self has_weapon_or_upgrade( "ray_gun_zm" ) ) + { + return 0; + } + } + while ( weapon == "time_bomb_zm" ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( is_player_valid( players[ i ], undefined, 1 ) && players[ i ] is_player_tactical_grenade( weapon ) ) + { + return 0; + } + i++; + } + } + return 1; +} + +zombie_buried_devgui( cmd ) +{ +/# + cmd_strings = strtok( cmd, " " ); + switch( cmd_strings[ 0 ] ) + { + case "richtofen_street": + level notify( "richtofen_street" ); + break; + case "maxis_street": + level notify( "maxis_street" ); + break; + case "ghost_toggle_force_killable": + if ( !isDefined( level.ghost_force_killable ) ) + { + level.ghost_force_killable = 1; + } + else + { + level.ghost_force_killable = !level.ghost_force_killable; + } + break; + case "ghost_toggle_debug": + if ( !isDefined( level.ghost_debug ) ) + { + level.ghost_debug = 1; + } + else + { + level.ghost_debug = !level.ghost_debug; + } + break; + case "ghost_warp_to_mansion": + if ( isDefined( level.ghost_devgui_warp_to_mansion ) ) + { + [[ level.ghost_devgui_warp_to_mansion ]](); + } + break; + case "ghost_toggle_no_ghost": + if ( isDefined( level.ghost_devgui_toggle_no_ghost ) ) + { + [[ level.ghost_devgui_toggle_no_ghost ]](); + } + break; + case "spawn_vulture_stink": + if ( isDefined( level.vulture_devgui_spawn_stink ) ) + { + [[ level.vulture_devgui_spawn_stink ]](); + } + break; + case "sloth_double_wide": + if ( isDefined( level.sloth_devgui_double_wide ) ) + { + [[ level.sloth_devgui_double_wide ]](); + } + break; + case "sloth_destroy_barricade": + if ( isDefined( level.sloth_devgui_barricade ) ) + { + [[ level.sloth_devgui_barricade ]](); + } + break; + case "sloth_toggle_doors": + if ( !isDefined( level.sloth_debug_doors ) ) + { + level.sloth_debug_doors = 1; + } + else + { + level.sloth_debug_doors = !level.sloth_debug_doors; + } + break; + case "sloth_toggle_buildables": + if ( !isDefined( level.sloth_debug_buildables ) ) + { + level.sloth_debug_buildables = 1; + } + else + { + level.sloth_debug_buildables = !level.sloth_debug_buildables; + } + break; + case "sloth_move_lamp": + if ( isDefined( level.sloth_devgui_move_lamp ) ) + { + [[ level.sloth_devgui_move_lamp ]](); + } + break; + case "sloth_make_crawler": + if ( isDefined( level.sloth_devgui_make_crawler ) ) + { + [[ level.sloth_devgui_make_crawler ]](); + } + break; + case "sloth_teleport": + if ( isDefined( level.sloth_devgui_teleport ) ) + { + [[ level.sloth_devgui_teleport ]](); + } + break; + case "sloth_drink_booze": + if ( isDefined( level.sloth_devgui_booze ) ) + { + [[ level.sloth_devgui_booze ]](); + } + break; + case "sloth_eat_candy": + if ( isDefined( level.sloth_devgui_candy ) ) + { + [[ level.sloth_devgui_candy ]](); + } + break; + case "sloth_context": + if ( isDefined( level.sloth_devgui_context ) ) + { + [[ level.sloth_devgui_context ]](); + } + break; + case "sloth_warp_to_jail": + if ( isDefined( level.sloth_devgui_warp_to_jail ) ) + { + [[ level.sloth_devgui_warp_to_jail ]](); + } + break; + case "lights_on": + level notify( "generator_lights_on" ); + break; + case "sloth_open": + level notify( "open_sloth_barricades" ); + level notify( "courtyard_fountain_open" ); + break; + case "cell_open": + level notify( "cell_open" ); + if ( isDefined( level.jail_open_door ) ) + { + [[ level.jail_open_door ]](); + } + break; + case "cell_close": + level notify( "cell_close" ); + if ( isDefined( level.jail_close_door ) ) + { + [[ level.jail_close_door ]](); + } + break; + case "pick_up_keys": + thread pick_up( "keys_zm" ); + break; + case "pick_up_candy": + if ( isDefined( level.jail_barricade_down ) && !level.jail_barricade_down ) + { + level notify( "jail_barricade_down" ); + wait 0,05; + } + thread pick_up( "candy" ); + break; + case "pick_up_booze": + thread pick_up( "booze" ); + break; + case "bell_ring": + players = get_players(); + bells = getentarray( "church_bell", "targetname" ); + bell_ring( players[ 0 ], bells[ 0 ] ); + break; + case "destroy_sloth_fountain": + level notify( "courtyard_fountain_open" ); + break; + case "destroy_maze_fountain": + level notify( "_destroy_maze_fountain" ); + break; + case "warp_player_to_maze_fountain": + level notify( "warp_player_to_maze_fountain" ); + break; + case "warp_player_to_courtyard_fountain": + level notify( "warp_player_to_courtyard_fountain" ); + break; + case "blue_monkey": + case "green_ammo": + case "green_double": + case "green_insta": + case "green_monkey": + case "green_nuke": + case "red_ammo": + case "red_double": + case "red_nuke": + case "yellow_double": + case "yellow_nuke": + maps/mp/zombies/_zm_devgui::zombie_devgui_give_powerup( cmd_strings[ 0 ], 1 ); + break; + case "slow_test": + maps/mp/zombies/_zm_weap_time_bomb::slow_all_actors(); + thread maps/mp/zombies/_zm_weap_time_bomb::all_actors_resume_speed(); + flag_set( "time_bomb_enemies_restored" ); + case "catwalk_keep": + level notify( "catwalk_collapsed" ); + break; + case "start_ghost_piano": + flag_set( "player_piano_song_active" ); + level notify( "player_can_interact_with_ghost_piano_player" ); + break; + case "ghost_piano_warp_to_mansion_piano": + level notify( "ghost_piano_warp_to_mansion_piano" ); + break; + case "ghost_piano_warp_to_bar": + level notify( "ghost_piano_warp_to_bar" ); + break; + default: + } +#/ + } + } +} + +pick_up( thing ) +{ +/# + players = get_players(); + _a885 = players; + _k885 = getFirstArrayKey( _a885 ); + while ( isDefined( _k885 ) ) + { + player = _a885[ _k885 ]; + if ( isDefined( player player_get_buildable_piece( 1 ) ) && player player_get_buildable_piece( 1 ).buildablename == thing ) + { + } + else + { + candidate_list = []; + _a892 = level.zones; + _k892 = getFirstArrayKey( _a892 ); + while ( isDefined( _k892 ) ) + { + zone = _a892[ _k892 ]; + if ( isDefined( zone.unitrigger_stubs ) ) + { + candidate_list = arraycombine( candidate_list, zone.unitrigger_stubs, 1, 0 ); + } + _k892 = getNextArrayKey( _a892, _k892 ); + } + _a901 = candidate_list; + _k901 = getFirstArrayKey( _a901 ); + while ( isDefined( _k901 ) ) + { + stub = _a901[ _k901 ]; + if ( isDefined( stub.piece ) && stub.piece.buildablename == thing ) + { + player thread maps/mp/zombies/_zm_buildables::player_take_piece( stub.piece ); + break; + } + else + { + _k901 = getNextArrayKey( _a901, _k901 ); + } + } + if ( isDefined( player player_get_buildable_piece( 1 ) ) && player player_get_buildable_piece( 1 ).buildablename == thing ) + { + break; + } + else + { + level notify( "player_purchase_" + thing ); + } + } + _k885 = getNextArrayKey( _a885, _k885 ); +#/ + } +} + +givecustomloadout( takeallweapons, alreadyspawned ) +{ + self giveweapon( "knife_zm" ); + self give_start_weapon( 1 ); +} + +precache_team_characters() +{ + precachemodel( "c_zom_player_cdc_dlc1_fb" ); + precachemodel( "c_zom_hazmat_viewhands" ); + precachemodel( "c_zom_player_cia_dlc1_fb" ); + precachemodel( "c_zom_suit_viewhands" ); +} + +give_team_characters() +{ + self detachall(); + self set_player_is_female( 0 ); + 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_dlc1_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_dlc1_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 ); +} + +initcharacterstartindex() +{ + level.characterstartindex = randomint( 4 ); +} + +precache_personality_characters() +{ + character/c_transit_player_farmgirl::precache(); + character/c_transit_player_oldman::precache(); + character/c_transit_player_engineer::precache(); + character/c_buried_player_reporter_dam::precache(); + precachemodel( "c_zom_farmgirl_viewhands" ); + precachemodel( "c_zom_oldman_viewhands" ); + precachemodel( "c_zom_engineer_viewhands" ); + precachemodel( "c_zom_reporter_viewhands" ); +} + +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_buried_player_reporter_dam::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 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"; +} + +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 ) + { + _a1190 = players; + _k1190 = getFirstArrayKey( _a1190 ); + while ( isDefined( _k1190 ) ) + { + player = _a1190[ _k1190 ]; + 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; + } + } + } + _k1190 = getNextArrayKey( _a1190, _k1190 ); + } + } + else _a1216 = players; + _k1216 = getFirstArrayKey( _a1216 ); + while ( isDefined( _k1216 ) ) + { + player = _a1216[ _k1216 ]; + if ( isDefined( player.characterindex ) ) + { + arrayremovevalue( charindexarray, player.characterindex, 0 ); + } + _k1216 = getNextArrayKey( _a1216, _k1216 ); + } + if ( charindexarray.size > 0 ) + { + return charindexarray[ 0 ]; + } + } + return 0; +} + +zm_player_fake_death_cleanup() +{ + if ( isDefined( self._fall_down_anchor ) ) + { + self._fall_down_anchor delete(); + self._fall_down_anchor = undefined; + } +} + +zm_player_fake_death( vdir ) +{ + level notify( "fake_death" ); + self notify( "fake_death" ); + stance = self getstance(); + self.ignoreme = 1; + self enableinvulnerability(); + self takeallweapons(); + if ( isDefined( self.insta_killed ) && self.insta_killed ) + { + 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; + } +} + +fall_down( vdir, stance ) +{ + self endon( "disconnect" ); + level endon( "game_module_ended" ); + self ghost(); + origin = self.origin; + xyspeed = ( 0, 0, 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, 0, 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" ); + } + self giveweapon( "death_throe_zm" ); + self switchtoweapon( "death_throe_zm" ); + if ( falling ) + { + 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(); +} + +initial_round_wait_func() +{ + flag_wait( "initial_blackscreen_passed" ); +} + +offhand_weapon_overrride() +{ + register_lethal_grenade_for_level( "frag_grenade_zm" ); + level.zombie_lethal_grenade_player_init = "frag_grenade_zm"; + register_tactical_grenade_for_level( "cymbal_monkey_zm" ); + register_tactical_grenade_for_level( "emp_grenade_zm" ); + register_placeable_mine_for_level( "claymore_zm" ); + 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( "equip_turbine_zm" ); + register_equipment_for_level( "equip_springpad_zm" ); + register_equipment_for_level( "equip_subwoofer_zm" ); + register_equipment_for_level( "equip_headchopper_zm" ); + level.zombie_equipment_player_init = undefined; +} + +offhand_weapon_give_override( str_weapon ) +{ + self endon( "death" ); + if ( is_tactical_grenade( str_weapon ) && isDefined( self get_player_tactical_grenade() ) && !self is_player_tactical_grenade( str_weapon ) ) + { + self setweaponammoclip( self get_player_tactical_grenade(), 0 ); + self takeweapon( self get_player_tactical_grenade() ); + } + return 0; +} + +init_buried_stats() +{ + self maps/mp/zm_buried_sq::init_player_sidequest_stats(); + self maps/mp/zm_buried_achievement::init_player_achievement_stats(); +} + +init_level_specific_wall_buy_fx() +{ + level._effect[ "an94_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_an94" ); + level._effect[ "pdw57_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_pdw57" ); + level._effect[ "svu_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_svuas" ); + level._effect[ "lsat_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_lsat" ); + level._effect[ "tazer_knuckles_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_buried_buy_taseknuck" ); + level._effect[ "tazer_knuckles_zm_chalk_fx" ] = loadfx( "maps/zombie/fx_zmb_buried_dyn_taseknuck" ); + level._effect[ "870mcs_zm_chalk_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_dyn_870mcs" ); + level._effect[ "ak74u_zm_chalk_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_dyn_ak74u" ); + level._effect[ "an94_zm_chalk_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_dyn_an94" ); + level._effect[ "pdw57_zm_chalk_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_dyn_pdw57" ); + level._effect[ "svu_zm_chalk_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_dyn_svuas" ); +} + +custom_add_weapons() +{ + gametype = getDvar( "ui_gametype" ); + add_zombie_weapon( "m1911_zm", "m1911_upgraded_zm", &"ZOMBIE_WEAPON_M1911", 50, "", "", undefined ); + add_zombie_weapon( "rnma_zm", "rnma_upgraded_zm", &"ZOMBIE_WEAPON_RNMA", 50, "pickup_six_shooter", "", 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( "pdw57_zm", "pdw57_upgraded_zm", &"ZOMBIE_WEAPON_PDW57", 1000, "smg", "", undefined ); + if ( gametype == "zcleansed" ) + { + add_zombie_weapon( "qcw05_zm", undefined, &"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_smr", "", undefined, 1 ); + add_zombie_weapon( "m16_zm", "m16_gl_upgraded_zm", &"ZOMBIE_WEAPON_M16", 1200, "burstrifle", "", undefined ); + add_zombie_weapon( "tar21_zm", "tar21_upgraded_zm", &"ZOMBIE_WEAPON_TAR21", 50, "wpck_mtar", "", 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, "wpck_m82a1", "", undefined, 1 ); + add_zombie_weapon( "svu_zm", "svu_upgraded_zm", &"ZOMBIE_WEAPON_SVU", 1000, "wpck_svuas", "", undefined, 1 ); + add_zombie_weapon( "lsat_zm", "lsat_upgraded_zm", &"ZOMBIE_WEAPON_LSAT", 2000, "wpck_lsat", "", 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( "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( "an94_zm", "an94_upgraded_zm", &"ZOMBIE_WEAPON_AN94", 1200, "", "", undefined ); + add_zombie_weapon( "cymbal_monkey_zm", undefined, &"ZOMBIE_WEAPON_SATCHEL_2000", 2000, "wpck_monkey", "", undefined, 1 ); + add_zombie_weapon( "ray_gun_zm", "ray_gun_upgraded_zm", &"ZOMBIE_WEAPON_RAYGUN", 10000, "wpck_ray", "", undefined, 1 ); + add_zombie_weapon( "raygun_mark2_zm", "raygun_mark2_upgraded_zm", &"ZOMBIE_WEAPON_RAYGUN_MARK2", 10000, "pickup_raymk2", "", undefined, 1 ); + add_zombie_weapon( "knife_ballistic_zm", "knife_ballistic_upgraded_zm", &"ZOMBIE_WEAPON_KNIFE_BALLISTIC", 10, "wpck_knife", "", undefined, 1 ); + add_zombie_weapon( "knife_ballistic_bowie_zm", "knife_ballistic_bowie_upgraded_zm", &"ZOMBIE_WEAPON_KNIFE_BALLISTIC", 10, "sickle", "", undefined, 1 ); + add_zombie_weapon( "knife_ballistic_no_melee_zm", "knife_ballistic_no_melee_upgraded_zm", &"ZOMBIE_WEAPON_KNIFE_BALLISTIC", 10, "wpck_knife", "", undefined, 1 ); + add_zombie_weapon( "tazer_knuckles_zm", undefined, &"ZOMBIE_WEAPON_TAZER_KNUCKLES", 100, "tazerknuckles", "", undefined ); + add_zombie_weapon( "slowgun_zm", "slowgun_upgraded_zm", &"ZOMBIE_WEAPON_SLOWGUN", 10, "wpck_paralyzer", "", undefined, 1 ); +} + +less_than_normal() +{ + return 0,5; +} + +include_weapons() +{ + gametype = getDvar( "ui_gametype" ); + include_weapon( "knife_zm", 0 ); + include_weapon( "frag_grenade_zm", 0 ); + include_weapon( "claymore_zm", 0 ); + include_weapon( "m1911_zm", 0 ); + include_weapon( "m1911_upgraded_zm", 0 ); + include_weapon( "rnma_zm" ); + include_weapon( "rnma_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 ); + if ( gametype == "zcleansed" ) + { + include_weapon( "qcw05_zm" ); + } + 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( "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( "svu_zm", 0 ); + include_weapon( "svu_upgraded_zm", 0 ); + include_weapon( "lsat_zm", 0 ); + include_weapon( "lsat_upgraded_zm", 0 ); + include_weapon( "hamr_zm" ); + include_weapon( "hamr_upgraded_zm", 0 ); + include_weapon( "pdw57_zm", 0 ); + include_weapon( "pdw57_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( "an94_zm", 0 ); + include_weapon( "an94_upgraded_zm", 0 ); + include_weapon( "cymbal_monkey_zm" ); + include_weapon( "ray_gun_zm" ); + include_weapon( "ray_gun_upgraded_zm", 0 ); + include_weapon( "raygun_mark2_zm", 1 ); + include_weapon( "raygun_mark2_upgraded_zm", 0 ); + include_weapon( "slowgun_zm", 1 ); + include_weapon( "slowgun_upgraded_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_weapon_to_content( "raygun_mark2_zm", "dlc3" ); + add_limited_weapon( "m1911_zm", 0 ); + add_limited_weapon( "knife_ballistic_zm", 1 ); + add_limited_weapon( "slowgun_zm", 1 ); + add_limited_weapon( "slowgun_upgraded_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 ); + add_limited_weapon( "raygun_mark2_zm", 4 ); + add_limited_weapon( "raygun_mark2_upgraded_zm", 4 ); + add_weapon_locker_mapping( "python_zm", "rnma_zm" ); + add_weapon_locker_mapping( "qcw05_zm", "pdw57_zm" ); + add_weapon_locker_mapping( "xm8_zm", "tar21_zm" ); + add_weapon_locker_mapping( "type95_zm", "tar21_zm" ); + add_weapon_locker_mapping( "rpd_zm", "galil_zm" ); + add_weapon_locker_mapping( "python_upgraded_zm", "rnma_upgraded_zm" ); + add_weapon_locker_mapping( "qcw05_upgraded_zm", "pdw57_upgraded_zm" ); + add_weapon_locker_mapping( "xm8_upgraded_zm", "tar21_upgraded_zm" ); + add_weapon_locker_mapping( "type95_upgraded_zm", "tar21_upgraded_zm" ); + add_weapon_locker_mapping( "rpd_upgraded_zm", "galil_upgraded_zm" ); +} + +include_powerups() +{ + include_powerup( "nuke" ); + include_powerup( "insta_kill" ); + include_powerup( "double_points" ); + include_powerup( "full_ammo" ); + include_powerup( "carpenter" ); + include_powerup( "fire_sale" ); + include_powerup( "teller_withdrawl" ); + include_powerup( "free_perk" ); + include_powerup( "insta_kill_ug" ); + include_powerup( "random_weapon" ); +} + +add_buried_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 ); +} + +zombie_init_done() +{ + self.allowpain = 0; + self.zombie_path_bad = 0; + self thread maps/mp/zm_buried_distance_tracking::escaped_zombies_cleanup_init(); +} + +include_equipment_for_level() +{ + level.equipment_subwoofer_needs_power = 1; + include_equipment( "equip_turbine_zm" ); + include_equipment( "equip_springpad_zm" ); + include_equipment( "equip_subwoofer_zm" ); + include_equipment( "equip_headchopper_zm" ); + level.equipment_planted = ::equipment_planted; + level.equipment_safe_to_drop = ::equipment_safe_to_drop; +} + +setup_rex_starts() +{ + add_gametype( "zclassic", ::dummy, "zclassic", ::dummy ); + add_gametype( "zcleansed", ::dummy, "zcleansed", ::dummy ); + add_gametype( "zgrief", ::dummy, "zgrief", ::dummy ); + add_gameloc( "processing", ::dummy, "processing", ::dummy ); + add_gameloc( "street", ::dummy, "street", ::dummy ); +} + +dummy() +{ +} + +buried_zone_init() +{ + flag_init( "always_on" ); + flag_set( "always_on" ); + add_adjacent_zone( "zone_tunnels_center", "zone_tunnels_north", "always_on" ); + add_adjacent_zone( "zone_tunnels_north", "zone_tunnels_north2", "tunnels2courthouse" ); + add_adjacent_zone( "zone_tunnels_south", "zone_tunnels_south2", "tunnel2saloon" ); + add_adjacent_zone( "zone_tunnels_south3", "zone_tunnels_south2", "always_on" ); + add_adjacent_zone( "zone_tunnels_center", "zone_tunnels_south", "always_on" ); + add_adjacent_zone( "zone_street_lightwest", "zone_general_store", "general_store_door1" ); + add_adjacent_zone( "zone_street_lighteast", "zone_general_store", "always_on" ); + add_adjacent_zone( "zone_street_darkwest", "zone_general_store", "general_store_door2" ); + add_adjacent_zone( "zone_street_lightwest", "zone_morgue_upstairs", "always_on" ); + add_adjacent_zone( "zone_street_fountain", "zone_mansion_lawn", "mansion_lawn_door1" ); + add_adjacent_zone( "zone_street_darkwest", "zone_gun_store", "gun_store_door1" ); + add_adjacent_zone( "zone_stables", "zone_street_lightwest", "always_on", 1 ); + add_adjacent_zone( "zone_street_darkwest", "zone_street_darkwest_nook", "darkwest_nook_door1" ); + add_adjacent_zone( "zone_street_darkwest", "zone_general_store", "general_store_door3" ); + add_adjacent_zone( "zone_street_darkwest_nook", "zone_stables", "stables_door2" ); + add_adjacent_zone( "zone_street_darkeast", "zone_underground_bar", "bar_door1" ); + add_adjacent_zone( "zone_street_darkeast", "zone_street_darkeast_nook", "always_on" ); + add_adjacent_zone( "zone_underground_courthouse2", "zone_underground_courthouse", "always_on" ); + add_adjacent_zone( "zone_street_lighteast", "zone_underground_courthouse", "courthouse_door1" ); + add_adjacent_zone( "zone_street_lightwest", "zone_underground_jail", "jail_door1" ); + add_adjacent_zone( "zone_street_lightwest", "zone_street_lightwest_alley", "jail_jugg" ); + add_adjacent_zone( "zone_underground_jail", "zone_underground_jail2", "always_on" ); + add_adjacent_zone( "zone_underground_jail2", "zone_street_lightwest", "always_on" ); + add_adjacent_zone( "zone_street_lighteast", "zone_candy_store", "candy_store_door1" ); + add_adjacent_zone( "zone_candy_store", "zone_candy_store_floor2", "always_on" ); + add_adjacent_zone( "zone_toy_store_floor2", "zone_candy_store_floor2", "always_on" ); + add_adjacent_zone( "zone_toy_store", "zone_toy_store_floor2", "always_on" ); + add_adjacent_zone( "zone_street_darkeast", "zone_toy_store_floor2", "always_on" ); + add_adjacent_zone( "zone_street_darkeast", "zone_toy_store", "candy_store_door2" ); + add_adjacent_zone( "zone_street_lighteast", "zone_candy_store_floor2", "candy2lighteast", 1 ); + add_adjacent_zone( "zone_street_darkeast", "zone_candy_store_floor2", "always_on", 1 ); + add_adjacent_zone( "zone_toy_store_tunnel", "zone_toy_store_floor2", "always_on", 1 ); + add_adjacent_zone( "zone_street_lighteast", "zone_street_fountain", "always_on" ); + add_adjacent_zone( "zone_street_fountain", "zone_church_graveyard", "always_on" ); + add_adjacent_zone( "zone_church_graveyard", "zone_church_main", "church_door1" ); + add_adjacent_zone( "zone_church_main", "zone_church_upstairs", "church_door1" ); + add_adjacent_zone( "zone_gun_store", "zone_tunnel_gun2stables", "gunshop2tunnel" ); + add_adjacent_zone( "zone_tunnel_gun2saloon", "zone_underground_bar", "always_on" ); + add_adjacent_zone( "zone_maze", "zone_mansion_backyard", "mansion_door1", 1 ); + add_adjacent_zone( "zone_maze", "zone_maze_staircase", "mansion_door1", 1 ); + add_adjacent_zone( "zone_stables", "zone_tunnel_gun2stables2", "always_on" ); + add_adjacent_zone( "zone_tunnel_gun2stables2", "zone_tunnel_gun2stables", "always_on" ); +} + +init_turned_zones() +{ + a_zones = array( "zone_street_lighteast", "zone_street_lightwest", "zone_street_darkeast", "zone_street_darkwest", "zone_church_main", "zone_church_upstairs", "zone_mansion", "zone_candy_store", "zone_candy_store_floor2", "zone_underground_courthouse", "zone_underground_jail", "zone_underground_jail2", "zone_toy_store", "zone_toy_store_floor2", "zone_underground_bar", "zone_gun_store", "zone_stables", "zone_bank", "zone_general_store", "zone_morgue_upstairs" ); + _a1796 = a_zones; + _k1796 = getFirstArrayKey( _a1796 ); + while ( isDefined( _k1796 ) ) + { + zone = _a1796[ _k1796 ]; + zone_init( zone ); + enable_zone( zone ); + _k1796 = getNextArrayKey( _a1796, _k1796 ); + } +} + +init_fountain_zone() +{ + flag_wait( "fountain_transport_active" ); + if ( !isDefined( level.snd_ent ) ) + { + level.snd_ent = spawn( "script_origin", ( 4918, 575, 11 ) ); + level.snd_ent playloopsound( "amb_water_vortex", 1 ); + } + zone_volumes = getentarray( "zone_start_lower", "targetname" ); + _a1816 = zone_volumes; + _k1816 = getFirstArrayKey( _a1816 ); + while ( isDefined( _k1816 ) ) + { + zone = _a1816[ _k1816 ]; + zone.script_noteworthy = "player_volume"; + _k1816 = getNextArrayKey( _a1816, _k1816 ); + } +} + +buried_ghost_zone_teleport_logic() +{ + if ( isDefined( level.zombie_ghost_round_states.is_teleporting ) && level.zombie_ghost_round_states.is_teleporting ) + { + return; + } + if ( !isDefined( level.ghost_drop_down_locations ) || level.ghost_drop_down_locations.size < 1 ) + { + return; + } + if ( !isDefined( level.zones[ "zone_start" ] ) || isDefined( level.zones[ "zone_start" ].is_occupied ) && level.zones[ "zone_start" ].is_occupied ) + { + return; + } + if ( !isDefined( level.zones[ "zone_start_lower" ] ) || isDefined( level.zones[ "zone_start_lower" ].is_occupied ) && level.zones[ "zone_start_lower" ].is_occupied ) + { + return; + } + teleport_location_index = 0; + axises = getaiarray( "axis" ); + _a1847 = axises; + _k1847 = getFirstArrayKey( _a1847 ); + while ( isDefined( _k1847 ) ) + { + axis = _a1847[ _k1847 ]; + if ( is_true( axis.is_ghost ) && axis maps/mp/zombies/_zm_ai_ghost::is_in_start_area() ) + { + if ( teleport_location_index == level.ghost_drop_down_locations.size ) + { + teleport_location_index = 0; + } + teleport_location_origin = level.ghost_drop_down_locations[ teleport_location_index ].origin; + teleport_location_angles = level.ghost_drop_down_locations[ teleport_location_index ].angles; + axis forceteleport( teleport_location_origin, teleport_location_angles ); + teleport_location_index++; + } + _k1847 = getNextArrayKey( _a1847, _k1847 ); + } +} + +ghost_zone_fountain_teleport_logic() +{ + if ( isDefined( level.zombie_ghost_round_states.is_teleporting ) && level.zombie_ghost_round_states.is_teleporting ) + { + return; + } + if ( !isDefined( level.ghost_zone_start_lower_locations ) || level.ghost_zone_start_lower_locations.size < 1 ) + { + return; + } + if ( !level.zones[ "zone_start_lower" ].is_occupied ) + { + return; + } + teleport_location_index = 0; + axises = getaiarray( "axis" ); + _a1888 = axises; + _k1888 = getFirstArrayKey( _a1888 ); + while ( isDefined( _k1888 ) ) + { + axis = _a1888[ _k1888 ]; + if ( is_true( axis.is_ghost ) && !axis maps/mp/zombies/_zm_ai_ghost::is_in_start_area() ) + { + if ( isDefined( axis.favoriteenemy ) && axis.favoriteenemy maps/mp/zombies/_zm_ai_ghost::is_in_start_area() ) + { + if ( teleport_location_index == level.ghost_zone_start_lower_locations.size ) + { + teleport_location_index = 0; + } + teleport_location_origin = level.ghost_zone_start_lower_locations[ teleport_location_index ].origin; + teleport_location_angles = level.ghost_zone_start_lower_locations[ teleport_location_index ].angles; + axis forceteleport( teleport_location_origin, teleport_location_angles ); + teleport_location_index++; + } + } + _k1888 = getNextArrayKey( _a1888, _k1888 ); + } +} + +init_level_specific_audio() +{ + level thread establish_mystery_wallbuy_categories(); + level._audio_custom_response_line = ::buried_audio_custom_response_line; + level.oh_shit_vo_cooldown = 0; + level.snd_pers_upgrade_force_variant = 0; + level.pers_upgrade_vo_spoken = 1; + level.snd_pers_upgrade_force_type = "achievement"; + level.custom_banking_vo = 1; + level.custom_buildable_need_part_vo = ::buried_custom_buildable_need_part_vo; + level.custom_buildable_wrong_part_vo = ::buried_custom_buildable_wrong_part_vo; + level.custom_bank_deposit_vo = ::buried_custom_bank_deposit_vo; + level.custom_bank_withdrawl_vo = ::buried_custom_bank_withdrawl_vo; + level.custom_faller_death = ::maps/mp/zombies/_zm_ai_faller::faller_death_ragdoll; + if ( is_classic() ) + { + level.audio_get_mod_type = ::buried_audio_get_mod_type_override; + level.custom_kill_damaged_vo = ::maps/mp/zombies/_zm_audio::custom_kill_damaged_vo; + level.gib_on_damage = ::buried_custom_zombie_gibbed_vo; + level._audio_custom_weapon_check = ::buried_audio_custom_weapon_check; + level._custom_zombie_oh_shit_vox_func = ::buried_custom_zombie_oh_shit_vox; + level.custom_player_track_ammo_count = ::buried_player_track_ammo_count; + onplayerconnect_callback( ::zm_buried_buildable_pickedup_vo ); + level thread ghost_steal_vo_watcher(); + level thread ghost_damage_vo_watcher(); + level thread sloth_first_encounter_vo(); + level thread sloth_crawler_vo(); + } + buried_add_player_dialogue( "player", "general", "no_money_weapon", "nomoney_generic", undefined ); + buried_add_player_dialogue( "player", "general", "no_money_box", "nomoney_generic", undefined ); + buried_add_player_dialogue( "player", "general", "perk_deny", "nomoney_generic", undefined ); + buried_add_player_dialogue( "player", "kill", "closekill", "kill_close", undefined, 15 ); + buried_add_player_dialogue( "player", "kill", "damage", "kill_damaged", undefined, 50 ); + buried_add_player_dialogue( "player", "kill", "headshot", "kill_headshot", "resp_kill_headshot", 25 ); + buried_add_player_dialogue( "player", "kill", "raymk2", "kill_raymk2", undefined, 15 ); + buried_add_player_dialogue( "player", "kill", "paralyzer", "kill_paralyzer", undefined, 15 ); + buried_add_player_dialogue( "player", "kill", "headchopper", "kill_headchopper", undefined, 15 ); + buried_add_player_dialogue( "player", "kill", "subwoofer", "kill_subwoofer", undefined, 15 ); + buried_add_player_dialogue( "player", "kill", "six_shooter", "kill_six_shooter", undefined, 15 ); + buried_add_player_dialogue( "player", "perk", "specialty_armorvest", "perk_jugga", undefined, 100 ); + buried_add_player_dialogue( "player", "perk", "specialty_quickrevive", "perk_revive", undefined, 100 ); + buried_add_player_dialogue( "player", "perk", "specialty_fastreload", "perk_speed", undefined, 100 ); + buried_add_player_dialogue( "player", "perk", "specialty_rof", "perk_doubletap", undefined, 100 ); + buried_add_player_dialogue( "player", "perk", "specialty_longersprint", "perk_stamine", undefined, 100 ); + buried_add_player_dialogue( "player", "perk", "specialty_additionalprimaryweapon", "perk_mule", undefined, 100 ); + buried_add_player_dialogue( "player", "perk", "specialty_nomotionsensor", "perk_vulture", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "revive_up", "heal_revived", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "exert_sigh", "exert_sigh", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "exert_laugh", "exert_laugh", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "pain_high", "pain_high", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pickup", "build_pickup", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_swap", "build_swap", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_add", "build_add", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_final", "build_final", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_wrong_part", "build_wrong_part", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_need_part", "build_need_part", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_hc_final", "build_hc_final", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_bheadchopper_zm", "build_hc_take", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_plc_headchopper_zm", "build_hc_drop", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_wheadchopper_zm", "build_hc_pickup", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_sw_final", "build_sw_final", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_bsubwoofer_zm", "build_sw_take", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_plc_subwoofer_zm", "build_sw_drop", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_wsubwoofer_zm", "build_sw_pickup", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_trb_final", "build_trb_final", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_bturbine", "build_trb_take", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_plc_turbine", "build_trb_drop", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_wturbine", "build_trb_pickup", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_stm_final", "build_stm_final", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_bspringpad_zm", "build_stm_take", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_plc_springpad_zm", "build_stm_drop", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "build_pck_wspringpad_zm", "build_stm_pickup", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "gunshop_chalk_pickup", "gunshop_chalk", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "booze_pickup", "pickup_booze", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "candy_pickup", "pickup_candy", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "key_pickup", "pickup_key", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "first_bersek", "sloth_1st_bottle", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_generic_feed", "sloth_generic_feed", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_retreat_cell", "sloth_retreat_cell", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_clears_path", "sloth_clears_path", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_unlocked", "sloth_unlocked", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_run", "sloth_run", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_encounter", "sloth_encounter", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "sloth_crawler", "sloth_crawler", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "ghost_theft", "ghost_theft", undefined, 25 ); + buried_add_player_dialogue( "player", "general", "ghost_damage", "ghost_damage", undefined, 25 ); + buried_add_player_dialogue( "player", "general", "vulture_stink", "react_stink", "vulture_stink_react", 25 ); + buried_add_player_dialogue( "player", "general", "vulture_stink_react", "response_stink", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "vulture_ammo_drop", "ammo_drop", undefined, 15 ); + buried_add_player_dialogue( "player", "general", "vulture_money_drop", "money_drop", undefined, 15 ); + buried_add_player_dialogue( "player", "general", "throw_bomb", "throw_bomb", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "activate_bomb", "activate_bomb", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "ammo_switch", "ammo_switch", undefined, 100 ); + buried_add_player_dialogue( "player", "power", "power_on", "power_on", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "reboard", "rebuild_boards", undefined, 50 ); + buried_add_player_dialogue( "player", "general", "generic_wall_buy", "generic_wall_buy", undefined, 25 ); + buried_add_player_dialogue( "player", "general", "favorite_wall_buy", "favorite_wall_buy", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "in_maze", "in_maze", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "game_start", "game_start", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "find_town", "find_town", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "stay_topside", "stay_topside", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "fall_down_hole", "fall_down_hole", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "fall_down_hole_response", "fall_response", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "pap_wait", "pap_wait", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "pap_arm", "pap_arm", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "pap_wait2", "pap_wait2", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "pap_arm2", "pap_arm2", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "weapon_storage", "weapon_storage", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "wall_withdrawl", "wall_withdrawl", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "bank_deposit", "bank_deposit", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "bank_withdrawl", "bank_withdrawl", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "achievement", "earn_acheivement", undefined, 100 ); + buried_add_player_dialogue( "player", "quest", "find_secret", "find_secret", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "upgrade", "find_secret", undefined, 100 ); + buried_add_player_dialogue( "player", "general", "invisible_collision", "invisible_collision", undefined, 25 ); + buried_add_player_dialogue( "player", "general", "stuhlinger_possessed", "stuhlinger_2nd_possession_1", undefined, 100 ); +} + +buried_add_player_dialogue( speaker, category, type, alias, response, chance ) +{ + level.vox zmbvoxadd( speaker, category, type, alias, response ); + if ( isDefined( chance ) ) + { + add_vox_response_chance( type, chance ); + } +} + +buried_audio_custom_response_line( player, index, category, type ) +{ + while ( type == "vulture_stink" ) + { + a_players = getplayers(); + arrayremovevalue( a_players, player ); + while ( a_players.size > 0 ) + { + a_closest = get_array_of_closest( player.origin, a_players ); + i = 0; + while ( i < a_closest.size ) + { + if ( isDefined( a_closest[ i ].dontspeak ) && !a_closest[ i ].dontspeak ) + { + if ( isalive( a_closest[ i ] ) ) + { + n_dist = distance2dsquared( player.origin, a_closest[ i ].origin ); + if ( n_dist <= 250000 ) + { + a_closest[ i ] thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "vulture_stink_react" ); + return; + } + } + } + i++; + } + } + } + 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; +} + +buried_audio_get_mod_type_override( impact, mod, weapon, zombie, instakill, dist, player ) +{ + close_dist = 4096; + med_dist = 15376; + far_dist = 75625; + a_str_mod = []; + if ( isDefined( zombie.damageweapon ) && zombie.damageweapon == "cymbal_monkey_zm" ) + { + a_str_mod[ a_str_mod.size ] = "monkey"; + } + if ( weapon == "slowgun_zm" || weapon == "slowgun_upgraded_zm" ) + { + a_str_mod[ a_str_mod.size ] = "paralyzer"; + } + if ( weapon == "rnma_zm" || weapon == "rnma_upgraded_zm" ) + { + a_str_mod[ a_str_mod.size ] = "six_shooter"; + } + if ( is_headshot( weapon, impact, mod ) && dist >= far_dist ) + { + a_str_mod[ a_str_mod.size ] = "headshot"; + } + if ( is_explosive_damage( mod ) && weapon != "ray_gun_zm" && weapon != "ray_gun_upgraded_zm" && weapon != "raygun_mark2_zm" && weapon != "raygun_mark2_upgraded_zm" && isDefined( zombie.is_on_fire ) && !zombie.is_on_fire ) + { + if ( !isinarray( a_str_mod, "monkey" ) ) + { + if ( !instakill ) + { + a_str_mod[ a_str_mod.size ] = "explosive"; + } + else + { + a_str_mod[ a_str_mod.size ] = "weapon_instakill"; + } + } + } + if ( weapon == "ray_gun_zm" || weapon == "ray_gun_upgraded_zm" ) + { + if ( !isinarray( a_str_mod, "monkey" ) ) + { + if ( dist > far_dist ) + { + if ( !instakill ) + { + a_str_mod[ a_str_mod.size ] = "raygun"; + } + else + { + a_str_mod[ a_str_mod.size ] = "weapon_instakill"; + } + } + } + } + if ( weapon == "raygun_mark2_zm" || weapon == "raygun_mark2_upgraded_zm" ) + { + if ( !isinarray( a_str_mod, "monkey" ) ) + { + if ( dist > far_dist ) + { + if ( !instakill ) + { + a_str_mod[ a_str_mod.size ] = "raymk2"; + } + else + { + a_str_mod[ a_str_mod.size ] = "weapon_instakill"; + } + } + } + } + if ( instakill ) + { + if ( mod == "MOD_MELEE" ) + { + a_str_mod[ a_str_mod.size ] = "melee_instakill"; + } + else + { + a_str_mod[ a_str_mod.size ] = "weapon_instakill"; + } + } + if ( mod != "MOD_MELEE" && !zombie.has_legs ) + { + a_str_mod[ a_str_mod.size ] = "crawler"; + } + if ( mod != "MOD_BURNED" && dist < close_dist ) + { + a_str_mod[ a_str_mod.size ] = "closekill"; + } + if ( a_str_mod.size == 0 ) + { + str_mod_final = "default"; + } + else if ( a_str_mod.size == 1 ) + { + str_mod_final = a_str_mod[ 0 ]; + } + else + { + i = 0; + while ( i < a_str_mod.size ) + { + if ( cointoss() ) + { + str_mod_final = a_str_mod[ i ]; + } + i++; + } + str_mod_final = a_str_mod[ randomint( a_str_mod.size ) ]; + } + return str_mod_final; +} + +buried_custom_zombie_gibbed_vo() +{ + self endon( "death" ); + if ( isDefined( self.a.gib_ref ) && isalive( self ) ) + { + if ( self.a.gib_ref != "no_legs" || self.a.gib_ref == "right_leg" && self.a.gib_ref == "left_leg" ) + { + if ( isDefined( self.attacker ) && isplayer( self.attacker ) ) + { + if ( isDefined( self.attacker.crawler_created_vo_cooldown ) && self.attacker.crawler_created_vo_cooldown ) + { + return; + } + rand = randomintrange( 0, 100 ); + if ( rand < 15 ) + { + self.attacker maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "crawl_spawn" ); + self.attacker thread crawler_created_vo_cooldown(); + } + } + return; + } + else + { + if ( isDefined( self.a.gib_ref ) || self.a.gib_ref == "right_arm" && self.a.gib_ref == "left_arm" ) + { + if ( self.has_legs && isalive( self ) ) + { + if ( isDefined( self.attacker ) && isplayer( self.attacker ) ) + { + rand = randomintrange( 0, 100 ); + if ( rand < 7 ) + { + self.attacker create_and_play_dialog( "general", "shoot_arm" ); + } + } + } + } + } + } +} + +crawler_created_vo_cooldown() +{ + self endon( "disconnect" ); + self.crawler_created_vo_cooldown = 1; + wait 30; + self.crawler_created_vo_cooldown = 0; +} + +buried_audio_custom_weapon_check( weapon, magic_box ) +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( magic_box ) && magic_box ) + { + type = self maps/mp/zombies/_zm_weapons::weapon_type_check( weapon ); + return type; + } + if ( flag( "time_bomb_restore_active" ) ) + { + return "crappy"; + } + if ( issubstr( weapon, "upgraded" ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "wpck_pap" ); + return "crappy"; + } + else + { + if ( weapon == "ray_gun_zm" ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", "ray_gun_zm" ); + return "crappy"; + } + else + { + if ( weapon == "raygun_mark2_zm" ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "build_take_raygun" ); + return "crappy"; + } + else + { + while ( isDefined( self.favorite_wall_weapons_list ) ) + { + _a2385 = self.favorite_wall_weapons_list; + _k2385 = getFirstArrayKey( _a2385 ); + while ( isDefined( _k2385 ) ) + { + fav_weapon = _a2385[ _k2385 ]; + if ( weapon == fav_weapon ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "favorite_wall_buy" ); + return "crappy"; + } + _k2385 = getNextArrayKey( _a2385, _k2385 ); + } + } + } + } + } + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "generic_wall_buy" ); + return "crappy"; +} + +buried_custom_zombie_oh_shit_vox() +{ + self endon( "death_or_disconnect" ); + while ( 1 ) + { + wait 1; + if ( isDefined( self.oh_shit_vo_cooldown ) && self.oh_shit_vo_cooldown ) + { + continue; + } + players = get_players(); + zombs = get_round_enemy_array(); + if ( players.size <= 1 ) + { + n_cooldown_time = 20; + } + else + { + n_cooldown_time = 15; + } + n_distance_sq = 62500; + n_zombies = 5; + n_chance = 30; + close_zombs = 0; + i = 0; + while ( i < zombs.size ) + { + if ( isDefined( zombs[ i ].favoriteenemy ) || zombs[ i ].favoriteenemy == self && !isDefined( zombs[ i ].favoriteenemy ) ) + { + if ( distancesquared( zombs[ i ].origin, self.origin ) < n_distance_sq ) + { + close_zombs++; + } + } + i++; + } + if ( close_zombs >= n_zombies ) + { + if ( randomint( 100 ) < n_chance && isDefined( self.isonbus ) && !self.isonbus ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "oh_shit" ); + self thread global_oh_shit_cooldown_timer( n_cooldown_time ); + } + } + } +} + +global_oh_shit_cooldown_timer( n_cooldown_time ) +{ + self endon( "disconnect" ); + self.oh_shit_vo_cooldown = 1; + wait n_cooldown_time; + self.oh_shit_vo_cooldown = 0; +} + +establish_mystery_wallbuy_categories() +{ + level.good_mystery_wallbuy = []; + level.good_mystery_wallbuy[ 0 ] = "ak74u_zm"; + level.good_mystery_wallbuy[ 1 ] = "pdw57_zm"; + level.good_mystery_wallbuy[ 2 ] = "tazer_knuckles_zm"; + level.bad_mystery_wallbuy = []; + level.bad_mystery_wallbuy[ 0 ] = "an94_zm"; + level.bad_mystery_wallbuy[ 1 ] = "svu_zm"; + level.bad_mystery_wallbuy[ 2 ] = "870mcs_zm"; +} + +buried_player_track_ammo_count() +{ + self notify( "stop_ammo_tracking" ); + self endon( "disconnect" ); + self endon( "stop_ammo_tracking" ); + ammolowcount = 0; + ammooutcount = 0; + while ( 1 ) + { + wait 0,5; + weap = self getcurrentweapon(); + while ( isDefined( weap ) || weap == "none" && !can_track_ammo( weap ) ) + { + continue; + } + while ( self getammocount( weap ) > 5 || self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + ammooutcount = 0; + ammolowcount = 0; + } + if ( self getammocount( weap ) > 0 ) + { + if ( ammolowcount < 1 ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ammo_low" ); + ammolowcount++; + } + } + else if ( ammooutcount < 1 ) + { + a_weapons = self getweaponslistprimaries(); + if ( a_weapons.size > 1 ) + { + _a2523 = a_weapons; + _k2523 = getFirstArrayKey( _a2523 ); + while ( isDefined( _k2523 ) ) + { + weapon = _a2523[ _k2523 ]; + if ( weapon == weap ) + { + } + else if ( self getammocount( weapon ) > 0 ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ammo_switch" ); + self.ammo_switch_vo_played = 1; + break; + } + else + { + _k2523 = getNextArrayKey( _a2523, _k2523 ); + } + } + if ( isDefined( self.ammo_switch_vo_played ) && !self.ammo_switch_vo_played ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ammo_out" ); + ammooutcount++; + } + self.ammo_switch_vo_played = 0; + break; + } + else + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ammo_out" ); + ammooutcount++; + } + } + wait 20; + } +} + +zm_buried_buildable_pickedup_vo() +{ + self.buildable_pickedup_timer = 0; +} + +ghost_steal_vo_watcher() +{ + while ( 1 ) + { + level waittill( "ghost_drained_player", player ); + chance = get_response_chance( "ghost_theft" ); + if ( chance > randomintrange( 1, 100 ) ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ghost_theft" ); + } + } +} + +ghost_damage_vo_watcher() +{ + while ( 1 ) + { + level waittill( "ghost_damaged_player", player ); + chance = get_response_chance( "ghost_damage" ); + if ( chance > randomintrange( 1, 100 ) ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ghost_damage" ); + } + } +} + +buried_custom_buildable_need_part_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( self.build_need_part_vo_cooldown ) && !self.build_need_part_vo_cooldown ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "build_need_part" ); + self thread buildable_need_part_vo_cooldown(); + } +} + +buildable_need_part_vo_cooldown() +{ + self endon( "disconnect" ); + self.build_need_part_vo_cooldown = 1; + wait 60; + self.build_need_part_vo_cooldown = 0; +} + +buried_custom_buildable_wrong_part_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( self.build_wrong_part_vo_cooldown ) && !self.build_wrong_part_vo_cooldown ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "build_wrong_part" ); + self thread buildable_wrong_part_vo_cooldown(); + } +} + +buildable_wrong_part_vo_cooldown() +{ + self endon( "disconnect" ); + self.build_wrong_part_vo_cooldown = 1; + wait 60; + self.build_wrong_part_vo_cooldown = 0; +} + +buried_custom_bank_deposit_vo() +{ + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "bank_deposit" ); +} + +buried_custom_bank_withdrawl_vo() +{ + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "bank_withdrawl" ); +} + +sloth_first_encounter_vo() +{ + trigger = getent( "sloth_first_encounter_trigger", "targetname" ); + while ( 1 ) + { + trigger waittill( "trigger", ent ); + if ( isplayer( ent ) ) + { + if ( ent is_player_looking_at( level.sloth.origin, 0,25, 0 ) ) + { + ent thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_encounter" ); + trigger delete(); + return; + } + } + else + { + wait 0,1; + } + } +} + +sloth_crawler_vo() +{ + while ( 1 ) + { + while ( !isDefined( level.sloth ) ) + { + wait 1; + } + while ( level.sloth is_jail_state() ) + { + wait 1; + } + while ( level.sloth.state == "berserk" || level.sloth.state == "crash" ) + { + wait 1; + } + while ( isDefined( level.sloth.carrying_crawler ) && level.sloth.carrying_crawler ) + { + wait 1; + } + while ( isDefined( level.time_bomb_detonation_vo ) && level.time_bomb_detonation_vo ) + { + wait 1; + } + zombies = get_round_enemy_array(); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + while ( isDefined( zombie ) && isDefined( zombie.has_legs ) && !zombie.has_legs ) + { + a_players = getplayers(); + _a2714 = a_players; + _k2714 = getFirstArrayKey( _a2714 ); + while ( isDefined( _k2714 ) ) + { + player = _a2714[ _k2714 ]; + if ( is_player_valid( player ) && isDefined( player.isspeaking ) && !player.isspeaking ) + { + if ( player is_player_looking_at( zombie.origin, 0,25 ) ) + { + if ( distancesquared( player.origin, level.sloth.origin ) < 9000000 ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_crawler" ); + wait 10; + } + } + } + _k2714 = getNextArrayKey( _a2714, _k2714 ); + } + } + i++; + } + wait 1; + } +} + +collapsing_catwalk_init() +{ + level endon( "catwalk_collapsed" ); + trig = getent( "start_platform_trig", "targetname" ); + platform = getent( "start_platform", "targetname" ); + while ( 1 ) + { + trig waittill( "trigger", who ); + if ( isplayer( who ) ) + { + if ( isDefined( who.on_platform ) && !who.on_platform ) + { + trig thread collapsing_platform_watcher( who, platform ); + return; + } + } + } +} + +collapsing_platform_watcher( who, platform ) +{ + who.on_platform = 1; + timed_collapse = 0; + if ( isDefined( platform ) ) + { + platform playsound( "zmb_catwalk_shake" ); + } + jump_blocker_clip = getent( "start_platform_delayed_clip", "targetname" ); + earthquake( 0,3, 3, who.origin, 128 ); + level waittill_notify_or_timeout( "lsat_purchased", 2 ); + if ( isDefined( who ) ) + { + who notify( "platform_collapse" ); + who.on_platform = 0; + } + if ( isDefined( platform ) ) + { + exploder( 410 ); + platform notsolid(); + level setclientfield( "cw_fall", 1 ); + platform playsound( "zmb_catwalk_fall" ); + if ( isDefined( platform.pieces ) ) + { + array_thread( platform.pieces, ::self_delete ); + } + if ( isDefined( platform ) ) + { + platform delete(); + } + } + wait 3; + level notify( "catwalk_collapsed" ); + level.catwalk_collapsed = 1; + if ( isDefined( jump_blocker_clip ) ) + { + jump_blocker_clip delete(); + } + if ( isDefined( self ) ) + { + self delete(); + } +} + +achievement_watcher_lsat_upgrade() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "pap_taken" ); + self notify( "player_upgraded_lsat_from_wall" ); +} + +player_give_lsat() +{ + level notify( "lsat_purchased" ); + if ( isDefined( level.catwalk_collapsed ) && !level.catwalk_collapsed ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "buried_lsat_purchased", 0 ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "buried_lsat_purchased" ); + level.lsat_purchased = 1; + } + self thread achievement_watcher_lsat_upgrade(); + self giveweapon( "lsat_zm" ); + maps/mp/zombies/_zm_weapons::acquire_weapon_toggle( "lsat_zm", self ); + self givestartammo( "lsat_zm" ); + self switchtoweapon( "lsat_zm" ); +} + +bell_watch() +{ + bells = getentarray( "church_bell", "targetname" ); + array_thread( bells, ::bell_watch_ring ); +} + +bell_watch_ring() +{ + self endon( "delete" ); + self setcandamage( 1 ); + while ( 1 ) + { + self waittill( "damage", amount, attacker, direction, point, mod, tagname, modelname, partname, weaponname ); + bell_ring( attacker, self ); + } +} + +bell_ring( player, bell ) +{ + level notify( "bell_rung" ); +/# +#/ + bell playsound( "amb_church_bell" ); +} + +player_force_from_prone() +{ + level endon( "intermission" ); + level endon( "end_game" ); + while ( 1 ) + { + self waittill( "trigger", who ); + if ( isplayer( who ) && who getstance() == "prone" ) + { + who setstance( "crouch" ); + } + wait 0,1; + } +} + +check_valid_poi( valid ) +{ + excludes = getentarray( "cymbal_monkey_exclude", "targetname" ); + while ( isDefined( excludes ) ) + { + _a2921 = excludes; + _k2921 = getFirstArrayKey( _a2921 ); + while ( isDefined( _k2921 ) ) + { + volume = _a2921[ _k2921 ]; + if ( self istouching( volume ) ) + { + return 0; + } + _k2921 = getNextArrayKey( _a2921, _k2921 ); + } + } + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_mansion" ) ) + { + return 0; + } + return valid; +} + +tear_into_position() +{ + asd_name = "zm_zbarrier_board_tear_in"; + substate_index = self.attacking_spot_index * 6; + anim_id = self getanimfromasd( asd_name, substate_index ); + zbarrier = self.first_node.zbarrier; + start_org = getstartorigin( zbarrier.origin, zbarrier.angles, anim_id ); + start_ang = getstartangles( zbarrier.origin, zbarrier.angles, anim_id ); + self setgoalpos( start_org, start_ang ); + self thread tear_into_facing( start_org, start_ang ); +} + +tear_into_facing( start_org, start_ang ) +{ + self endon( "death" ); + facing_dist = 256; + while ( 1 ) + { + dist = distancesquared( self.origin, start_org ); + if ( dist < facing_dist ) + { + break; + } + else + { + wait 0,1; + } + } + self orientmode( "face angle", start_ang[ 1 ] ); +} + +tear_into_wait() +{ + return; +} + +melee_miss_func() +{ + if ( isDefined( self.enemy ) ) + { + if ( isDefined( level.sloth ) ) + { + sloth_dist_sq = distancesquared( self.enemy.origin, level.sloth.origin ); + if ( sloth_dist_sq < 225 ) + { + 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" ); + } + } + } + } +} + +equipment_planted( weapon, equipname, groundfrom ) +{ +} + +equipment_safe_to_drop( weapon ) +{ + if ( isDefined( weapon.model ) && issubstr( weapon.model, "chopper" ) ) + { + if ( maps/mp/zombies/_zm_equip_headchopper::check_headchopper_in_bad_area( weapon.origin ) ) + { + return 0; + } + } + valid_location = check_point_in_enabled_zone( weapon.origin, undefined, undefined ); + if ( isDefined( valid_location ) && !valid_location ) + { + if ( weapon in_playable_area() ) + { + return 1; + } + return 0; + } + return 1; +} + +ignore_equipment( zombie ) +{ + if ( isDefined( zombie.completed_emerging_into_playable_area ) && !zombie.completed_emerging_into_playable_area ) + { + return 1; + } + if ( isDefined( zombie.is_ghost ) && zombie.is_ghost ) + { + return 1; + } + if ( isDefined( zombie.is_sloth ) && zombie.is_sloth ) + { + return 1; + } + if ( isDefined( self.equipname ) && self.equipname == "equip_headchopper_zm" ) + { + if ( isDefined( self.headchopper_kills ) && self.headchopper_kills < 10 ) + { + return 1; + } + else + { + if ( isDefined( zombie.headchopper_last_damage_time ) ) + { + currenttime = getTime(); + if ( ( currenttime - zombie.headchopper_last_damage_time ) <= 2500 ) + { + return 1; + } + } + } + } + return 0; +} + +buried_paralyzer_check() +{ + curr_zone = self get_current_zone(); + if ( isDefined( curr_zone ) ) + { + if ( curr_zone == "zone_mansion" ) + { + return 0; + } + if ( curr_zone == "zone_start" && self.origin[ 2 ] < 1222 ) + { + return 0; + } + } + return 1; +} + +is_courthouse_open() +{ + if ( flag( "courthouse_door1" ) ) + { + return 1; + } + if ( flag( "tunnel2saloon" ) && flag( "tunnels2courthouse" ) ) + { + return 1; + } + return 0; +} + +is_tunnel_open() +{ + if ( flag( "tunnel2saloon" ) ) + { + return 1; + } + if ( flag( "tunnels2courthouse" ) && maps/mp/zm_buried::is_courthouse_open() ) + { + return 1; + } + return 0; +} diff --git a/zm_buried_patch/maps/mp/zm_buried_achievement.gsc b/zm_buried_patch/maps/mp/zm_buried_achievement.gsc new file mode 100644 index 0000000..58f0dc2 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_achievement.gsc @@ -0,0 +1,184 @@ +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +init() +{ + if ( !is_gametype_active( "zclassic" ) ) + { + return; + } + level thread achievement_buried_sidequest(); + level thread achievement_im_your_huckleberry(); + level.achievement_sound_func = ::achievement_sound_func; + onplayerconnect_callback( ::onplayerconnect ); +} + +achievement_sound_func( achievement_name_lower ) +{ + if ( !sessionmodeisonlinegame() ) + { + return; + } + self thread do_player_general_vox( "general", "achievement" ); +} + +init_player_achievement_stats() +{ + if ( !is_gametype_active( "zclassic" ) ) + { + return; + } + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_buried_sidequest", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_ectoplasmic_residue", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_im_your_huckleberry", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_death_from_below", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_candygram", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_awaken_the_gazebo", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_revisionist_historian", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_mazed_and_confused", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_fsirt_against_the_wall", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zm_dlc3_when_the_revolution_comes", 0 ); +} + +onplayerconnect() +{ + self thread achievement_ectoplasmic_residue(); + self thread achievement_death_from_below(); + self thread achievement_candygram(); + self thread achievement_awaken_the_gazebo(); + self thread achievement_revisionist_historian(); + self thread achievement_mazed_and_confused(); + self thread achievement_fsirt_against_the_wall(); + self thread achievement_when_the_revolution_comes(); +} + +achievement_buried_sidequest() +{ + level endon( "end_game" ); + level waittill_any( "sq_richtofen_complete", "sq_maxis_complete" ); +/# +#/ + level giveachievement_wrapper( "ZM_DLC3_BURIED_SIDEQUEST", 1 ); +} + +achievement_im_your_huckleberry() +{ + level endon( "end_game" ); + num_barriers_broken = 0; + while ( 1 ) + { + level waittill( "sloth_breaks_barrier" ); + num_barriers_broken++; + if ( num_barriers_broken >= 8 ) + { + break; + } + else + { + } + } +/# +#/ + level giveachievement_wrapper( "ZM_DLC3_IM_YOUR_HUCKLEBERRY", 1 ); +} + +achievement_ectoplasmic_residue() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "player_received_ghost_round_free_perk" ); +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_ECTOPLASMIC_RESIDUE" ); +} + +achievement_death_from_below() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + num_subwoofer_deaths = 0; + while ( 1 ) + { + self waittill( "zombie_subwoofer_kill" ); + num_subwoofer_deaths++; + if ( num_subwoofer_deaths >= 10 ) + { + break; + } + else + { + } + } +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_DEATH_FROM_BELOW" ); +} + +achievement_candygram() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "player_gives_sloth_candy" ); +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_CANDYGRAM" ); +} + +achievement_awaken_the_gazebo() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + level endon( "bank_withdrawal" ); + level endon( "bank_teller_used" ); + level endon( "weapon_locker_grab" ); + self waittill( "pap_taken" ); + if ( level.round_number > 1 ) + { + return; + } +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_AWAKEN_THE_GAZEBO" ); +} + +achievement_revisionist_historian() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "player_activates_timebomb" ); +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_REVISIONIST_HISTORIAN" ); +} + +achievement_mazed_and_confused() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "player_stayed_in_maze_for_entire_high_level_round" ); +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_MAZED_AND_CONFUSED" ); +} + +achievement_fsirt_against_the_wall() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "player_upgraded_lsat_from_wall" ); +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_FSIRT_AGAINST_THE_WALL" ); +} + +achievement_when_the_revolution_comes() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + self waittill( "player_used_fountain_teleporter" ); +/# +#/ + self giveachievement_wrapper( "ZM_DLC3_WHEN_THE_REVOLUTION_COMES" ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_amb.gsc b/zm_buried_patch/maps/mp/zm_buried_amb.gsc new file mode 100644 index 0000000..3939bb8 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_amb.gsc @@ -0,0 +1,679 @@ +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/_ambientpackage; +#include maps/mp/zm_alcatraz_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +main() +{ + level.sndzombieentcontext = 1; + if ( is_classic() ) + { + thread sndmusicegg(); + thread sndstingersetup(); + onplayerconnect_callback( ::sndtrackers ); + } +} + +sndtrackers() +{ + self thread sndbackgroundmustracker(); +} + +sndstingersetup() +{ + level.sndmusicstingerevent = ::sndplaystinger; + level.sndstinger = spawnstruct(); + level.sndstinger.ent = spawn( "script_origin", ( 0, 0, 0 ) ); + level.sndstinger.queue = 0; + level.sndstinger.isplaying = 0; + level.sndstinger.states = []; + level.sndroundwait = 1; + flag_wait( "start_zombie_round_logic" ); + level sndstingersetupstates(); + level thread sndstingerroundwait(); + level thread sndboardmonitor(); + level thread locationstingerwait(); +} + +sndstingersetupstates() +{ + createstingerstate( "door_open", "mus_event_group_03", 2,5, "ignore" ); + createstingerstate( "boards_gone", "mus_event_group_02", 0,5, "ignore" ); + createstingerstate( "zone_tunnels_center", "mus_event_location_tunnels", 0,75, "queue" ); + createstingerstate( "zone_stables", "mus_event_location_stables", 0,75, "queue" ); + createstingerstate( "zone_underground_courthouse", "mus_event_location_courthouse", 0,75, "queue" ); + createstingerstate( "zone_underground_bar", "mus_event_location_bar", 0,75, "queue" ); + createstingerstate( "zone_toy_store", "mus_event_location_toystore", 0,75, "queue" ); + createstingerstate( "zone_underground_jail", "mus_event_location_jail", 0,75, "queue" ); + createstingerstate( "zone_general_store", "mus_event_location_genstore", 0,75, "queue" ); + createstingerstate( "zone_morgue", "mus_event_location_morgue", 0,75, "queue" ); + createstingerstate( "zone_church_main", "mus_event_location_church", 0,75, "queue" ); + createstingerstate( "zone_mansion_lawn", "mus_event_location_mansionlawn", 0,75, "queue" ); + createstingerstate( "zone_mansion", "mus_event_location_mansion", 0,75, "queue" ); + createstingerstate( "zone_maze", "mus_event_location_maze", 0,75, "queue" ); + createstingerstate( "zone_maze_staircase", "mus_event_location_mazeend", 0,75, "queue" ); + createstingerstate( "zone_candy_store", "mus_event_location_candystore", 0,75, "queue" ); + createstingerstate( "zone_street_lighteast", "mus_event_location_street_east", 0,75, "queue" ); + createstingerstate( "zone_street_lightwest", "mus_event_location_street_west", 0,75, "queue" ); + createstingerstate( "zone_start_lower", "mus_event_location_diamondmine", 0,75, "queue" ); + createstingerstate( "sloth_escape", "mus_event_sloth_breakout", 0, "reject" ); + createstingerstate( "poweron", "mus_event_poweron", 0, "reject" ); + createstingerstate( "sidequest_1", "mus_sidequest_0", 0, "reject" ); + createstingerstate( "sidequest_2", "mus_sidequest_1", 0, "reject" ); + createstingerstate( "sidequest_3", "mus_sidequest_2", 0, "reject" ); + createstingerstate( "sidequest_4", "mus_sidequest_3", 0, "reject" ); + createstingerstate( "sidequest_5", "mus_sidequest_4", 0, "reject" ); + createstingerstate( "sidequest_6", "mus_sidequest_5", 0, "reject" ); + createstingerstate( "sidequest_7", "mus_sidequest_6", 0, "reject" ); + createstingerstate( "sidequest_8", "mus_sidequest_7", 0, "reject" ); +} + +createstingerstate( state, alias, prewait, interrupt ) +{ + s = level.sndstinger; + if ( !isDefined( s.states[ state ] ) ) + { + s.states[ state ] = spawnstruct(); + s.states[ state ].alias = alias; + s.states[ state ].prewait = prewait; + s.states[ state ].interrupt = interrupt; + } +} + +sndboardmonitor() +{ + while ( 1 ) + { + level waittill( "last_board_torn", barrier_origin ); + players = getplayers(); + _a110 = players; + _k110 = getFirstArrayKey( _a110 ); + while ( isDefined( _k110 ) ) + { + player = _a110[ _k110 ]; + if ( distancesquared( player.origin, barrier_origin ) <= 22500 ) + { + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "boards_gone" ); + break; + } + else + { + _k110 = getNextArrayKey( _a110, _k110 ); + } + } + } +} + +locationstingerwait( zone_name, type ) +{ + array = sndlocationsarray(); + sndnorepeats = 3; + numcut = 0; + level.sndlastzone = undefined; + level.sndlocationplayed = 0; + level thread sndlocationbetweenroundswait(); + for ( ;; ) + { + while ( 1 ) + { + level waittill( "newzoneActive", activezone ); + wait 0,1; + while ( !sndlocationshouldplay( array, activezone ) ) + { + continue; + } + if ( is_true( level.sndroundwait ) ) + { + } + } + else while ( is_true( level.sndstinger.isplaying ) ) + { + level thread sndlocationqueue( activezone ); + } + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( activezone ); + level.sndlocationplayed = 1; + array = sndcurrentlocationarray( array, activezone, numcut, sndnorepeats ); + level.sndlastzone = activezone; + if ( numcut >= sndnorepeats ) + { + numcut = 0; + } + else + { + numcut++; + } + level waittill( "between_round_over" ); + while ( is_true( level.sndroundwait ) ) + { + wait 0,1; + } + level.sndlocationplayed = 0; + } +} + +sndlocationsarray() +{ + array = []; + array[ 0 ] = "zone_tunnels_center"; + array[ 1 ] = "zone_church_main"; + array[ 2 ] = "zone_mansion"; + array[ 3 ] = "zone_maze"; + array[ 4 ] = "zone_maze_staircase"; + array[ 5 ] = "zone_street_lightwest"; + array[ 6 ] = "zone_toy_store"; + array[ 7 ] = "zone_candy_store"; + array[ 8 ] = "zone_underground_courthouse"; + array[ 9 ] = "zone_start_lower"; + return array; +} + +sndlocationshouldplay( array, activezone ) +{ + shouldplay = 0; + if ( activezone == "zone_start_lower" && !flag( "fountain_transport_active" ) ) + { + return shouldplay; + } + if ( is_true( level.music_override ) ) + { + return shouldplay; + } + _a197 = array; + _k197 = getFirstArrayKey( _a197 ); + while ( isDefined( _k197 ) ) + { + place = _a197[ _k197 ]; + if ( place == activezone ) + { + shouldplay = 1; + } + _k197 = getNextArrayKey( _a197, _k197 ); + } + if ( shouldplay == 0 ) + { + return shouldplay; + } + playersinlocal = 0; + players = getplayers(); + _a208 = players; + _k208 = getFirstArrayKey( _a208 ); + while ( isDefined( _k208 ) ) + { + player = _a208[ _k208 ]; + if ( player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( activezone ) ) + { + if ( !is_true( player.afterlife ) ) + { + playersinlocal++; + } + } + _k208 = getNextArrayKey( _a208, _k208 ); + } + if ( playersinlocal >= 1 ) + { + shouldplay = 1; + } + else + { + shouldplay = 0; + } + return shouldplay; +} + +sndcurrentlocationarray( current_array, activezone, numcut, max_num_removed ) +{ + if ( numcut >= max_num_removed ) + { + current_array = sndlocationsarray(); + } + _a231 = current_array; + _k231 = getFirstArrayKey( _a231 ); + while ( isDefined( _k231 ) ) + { + place = _a231[ _k231 ]; + if ( place == activezone ) + { + arrayremovevalue( current_array, place ); + break; + } + else + { + _k231 = getNextArrayKey( _a231, _k231 ); + } + } + return current_array; +} + +sndlocationbetweenrounds() +{ + level endon( "newzoneActive" ); + activezones = maps/mp/zombies/_zm_zonemgr::get_active_zone_names(); + _a248 = activezones; + _k248 = getFirstArrayKey( _a248 ); + while ( isDefined( _k248 ) ) + { + zone = _a248[ _k248 ]; + if ( isDefined( level.sndlastzone ) && zone == level.sndlastzone ) + { + } + else + { + players = getplayers(); + _a254 = players; + _k254 = getFirstArrayKey( _a254 ); + while ( isDefined( _k254 ) ) + { + player = _a254[ _k254 ]; + if ( is_true( player.afterlife ) ) + { + } + else + { + if ( player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( zone ) ) + { + wait 0,1; + level notify( "newzoneActive" ); + return; + } + } + _k254 = getNextArrayKey( _a254, _k254 ); + } + } + _k248 = getNextArrayKey( _a248, _k248 ); + } +} + +sndlocationbetweenroundswait() +{ + while ( is_true( level.sndroundwait ) ) + { + wait 0,1; + } + while ( 1 ) + { + level thread sndlocationbetweenrounds(); + level waittill( "between_round_over" ); + while ( is_true( level.sndroundwait ) ) + { + wait 0,1; + } + } +} + +sndlocationqueue( zone ) +{ + level endon( "newzoneActive" ); + while ( is_true( level.sndstinger.isplaying ) ) + { + wait 0,5; + } + level notify( "newzoneActive" ); +} + +sndplaystinger( state, player ) +{ + s = level.sndstinger; + if ( !isDefined( s.states[ state ] ) ) + { + return; + } + interrupt = s.states[ state ].interrupt == "ignore"; + if ( !is_true( s.isplaying ) || is_true( interrupt ) ) + { + if ( interrupt ) + { + wait s.states[ state ].prewait; + playstinger( state, player, 1 ); + } + else if ( !level.sndroundwait ) + { + s.isplaying = 1; + wait s.states[ state ].prewait; + playstinger( state, player, 0 ); + level notify( "sndStingerDone" ); + s.isplaying = 0; + } + else + { + if ( s.states[ state ].interrupt == "queue" ) + { + level thread sndqueuestinger( state, player ); + } + } + return; + } + if ( s.states[ state ].interrupt == "queue" ) + { + level thread sndqueuestinger( state, player ); + } +} + +playstinger( state, player, ignore ) +{ + s = level.sndstinger; + if ( !isDefined( s.states[ state ] ) ) + { + return; + } + if ( is_true( level.music_override ) ) + { + return; + } + if ( is_true( ignore ) ) + { + if ( isDefined( player ) ) + { + player playsoundtoplayer( s.states[ state ].alias, player ); + } + else + { + s.ent playsound( s.states[ state ].alias ); + s.ent thread playstingerstop(); + } + } + else if ( isDefined( player ) ) + { + player playsoundtoplayer( s.states[ state ].alias, player ); + wait 8; + } + else + { + s.ent playsoundwithnotify( s.states[ state ].alias, "sndStingerDone" ); + s.ent thread playstingerstop(); + s.ent waittill( "sndStingerDone" ); + } +} + +sndqueuestinger( state, player ) +{ + s = level.sndstinger; + if ( is_true( s.queue ) ) + { + return; + } + else + { + s.queue = 1; + while ( 1 ) + { + if ( is_true( level.sndroundwait ) || is_true( s.isplaying ) ) + { + wait 0,5; + continue; + } + else + { + } + } + level thread sndplaystinger( state, player ); + s.queue = 0; + } +} + +sndstingerroundwait() +{ + wait 25; + level.sndroundwait = 0; + while ( 1 ) + { + level waittill( "end_of_round" ); + level thread sndstingerroundwait_start(); + } +} + +sndstingerroundwait_start() +{ + level.sndroundwait = 1; + wait 0,05; + level thread sndstingerroundwait_end(); +} + +sndstingerroundwait_end() +{ + level endon( "end_of_round" ); + level waittill( "between_round_over" ); + wait 28; + level.sndroundwait = 0; +} + +playstingerstop() +{ + self endon( "sndStingerDone" ); + level endon( "sndStingerDone" ); + level waittill( "end_of_round" ); + wait 2; + self stopsounds(); +} + +sndbackgroundmustracker() +{ + self endon( "disconnect" ); + self.prevzone = "null"; + self.prevcase = 99; + while ( 1 ) + { + level waittill( "newzoneActive", activezone ); + if ( self.prevzone != activezone ) + { + if ( self maps/mp/zombies/_zm_zonemgr::is_player_in_zone( activezone ) ) + { + self.prevzone = activezone; + switch( activezone ) + { + case "zone_start": + case "zone_start_lower": + if ( self.prevcase != 0 ) + { + self setclientfieldtoplayer( "sndBackgroundMus", 0 ); + self.prevcase = 0; + } + break; + break; + case "zone_mansion": + case "zone_mansion_backyard": + case "zone_mansion_lawn": + case "zone_maze": + case "zone_maze_staircase": + if ( self.prevcase != 2 ) + { + self setclientfieldtoplayer( "sndBackgroundMus", 2 ); + self.prevcase = 2; + } + break; + break; + default: + if ( self.prevcase != 1 ) + { + self setclientfieldtoplayer( "sndBackgroundMus", 1 ); + self.prevcase = 1; + } + break; + break; + } + } + } + } +} + +sndshoulditplay( activezone ) +{ + if ( self.prevzone == activezone ) + { + return 0; + } + if ( !self maps/mp/zombies/_zm_zonemgr::is_player_in_zone( activezone ) ) + { + return 0; + } + return 1; +} + +sndlastlifesetup() +{ + flag_wait( "start_zombie_round_logic" ); + level thread sndlastlife_multi(); +} + +sndlastlife_multi() +{ + level endon( "end_of_round" ); + level thread sndlastlife_multi_reset(); + sndplayersdead = 0; + while ( 1 ) + { + level waittill( "bleed_out" ); + sndplayersdead++; + players = getplayers(); + if ( ( players.size - sndplayersdead ) <= 1 ) + { + last_alive = sndlastlife_multi_getlastplayer(); + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "last_life" ); + return; + } + } +} + +sndlastlife_multi_getlastplayer() +{ + level endon( "end_of_round" ); + wait 0,5; + players = getplayers(); + _a572 = players; + _k572 = getFirstArrayKey( _a572 ); + while ( isDefined( _k572 ) ) + { + dude = _a572[ _k572 ]; + if ( dude.sessionstate == "spectator" ) + { + } + else + { + return dude; + } + _k572 = getNextArrayKey( _a572, _k572 ); + } +} + +sndlastlife_multi_reset() +{ + level waittill( "end_of_round" ); + level thread sndlastlife_multi(); +} + +sndmusicegg() +{ + origins = []; + origins[ 0 ] = ( -1215,63, -499,975, 291,89 ); + origins[ 1 ] = ( 552,009, -342,824, 27,3921 ); + origins[ 2 ] = ( 2827,28, 306,468, 92,783 ); + level.meteor_counter = 0; + level.music_override = 0; + i = 0; + while ( i < origins.size ) + { + level thread sndmusicegg_wait( origins[ i ] ); + i++; + } +} + +sndmusicegg_wait( bottle_origin ) +{ + temp_ent = spawn( "script_origin", bottle_origin ); + temp_ent playloopsound( "zmb_meteor_loop" ); + temp_ent thread maps/mp/zombies/_zm_sidequests::fake_use( "main_music_egg_hit", ::sndmusicegg_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 sndmuseggplay( temp_ent, "mus_zmb_secret_song", 363 ); + level thread easter_egg_song_vo( player ); + } + else + { + wait 1,5; + temp_ent delete(); + } +} + +sndmusicegg_override() +{ + if ( is_true( level.music_override ) ) + { + return 0; + } + return 1; +} + +sndmuseggplay( ent, alias, time ) +{ + level.music_override = 1; + wait 1; + ent playsound( alias ); + level setclientfield( "mus_zmb_egg_snapshot_loop", 1 ); + level thread sndeggmusicwait( time ); + level waittill_either( "end_game", "sndSongDone" ); + ent stopsounds(); + level setclientfield( "mus_zmb_egg_snapshot_loop", 0 ); + wait 0,05; + ent delete(); + level.music_override = 0; +} + +sndeggmusicwait( time ) +{ + level endon( "end_game" ); + wait time; + level notify( "sndSongDone" ); +} + +sndmusicquestendgame( alias, length ) +{ + while ( is_true( level.music_override ) ) + { + wait 1; + } + level.music_override = 1; + level setclientfield( "mus_zmb_egg_snapshot_loop", 1 ); + ent = spawn( "script_origin", ( 0, 0, 0 ) ); + ent playsound( alias ); + wait length; + level setclientfield( "mus_zmb_egg_snapshot_loop", 0 ); + level.music_override = 0; + wait 0,05; + ent delete(); + wait 1; + level thread sndendgamemusicredux( alias, length ); +} + +easter_egg_song_vo( player ) +{ + if ( isalive( player ) ) + { + player thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "quest", "find_secret" ); + } +} + +sndendgamemusicredux( alias, length ) +{ + m_endgame_machine = getstruct( "sq_endgame_machine", "targetname" ); + temp_ent = spawn( "script_origin", m_endgame_machine.origin ); + temp_ent thread maps/mp/zombies/_zm_sidequests::fake_use( "main_music_egg_hit", ::sndmusicegg_override ); + temp_ent playloopsound( "zmb_meteor_loop" ); + temp_ent waittill( "main_music_egg_hit", player ); + temp_ent stoploopsound( 1 ); + level.music_override = 1; + temp_ent playsound( "zmb_endgame_mach_button" ); + level setclientfield( "mus_zmb_egg_snapshot_loop", 1 ); + temp_ent playsound( alias ); + wait length; + level setclientfield( "mus_zmb_egg_snapshot_loop", 0 ); + level.music_override = 0; + wait 0,05; + temp_ent delete(); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_buildables.gsc b/zm_buried_patch/maps/mp/zm_buried_buildables.gsc new file mode 100644 index 0000000..9b81e23 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_buildables.gsc @@ -0,0 +1,1487 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_weap_claymore; +#include maps/mp/zombies/_zm_melee_weapon; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_buildables_pooled; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/_utility; +#include common_scripts/utility; + +prepare_chalk_weapon_list() +{ + level.buildable_wallbuy_weapons = []; + level.buildable_wallbuy_weapons[ 0 ] = "ak74u_zm"; + level.buildable_wallbuy_weapons[ 1 ] = "an94_zm"; + level.buildable_wallbuy_weapons[ 2 ] = "pdw57_zm"; + level.buildable_wallbuy_weapons[ 3 ] = "svu_zm"; + level.buildable_wallbuy_weapons[ 4 ] = "tazer_knuckles_zm"; + level.buildable_wallbuy_weapons[ 5 ] = "870mcs_zm"; + level.buildable_wallbuy_weapon_hints = []; + level.buildable_wallbuy_weapon_hints[ "ak74u_zm" ] = &"ZM_BURIED_WB_AK74U"; + level.buildable_wallbuy_weapon_hints[ "an94_zm" ] = &"ZM_BURIED_WB_AN94"; + level.buildable_wallbuy_weapon_hints[ "pdw57_zm" ] = &"ZM_BURIED_WB_PDW57"; + level.buildable_wallbuy_weapon_hints[ "svu_zm" ] = &"ZM_BURIED_WB_SVU"; + level.buildable_wallbuy_weapon_hints[ "tazer_knuckles_zm" ] = &"ZM_BURIED_WB_TAZER"; + level.buildable_wallbuy_weapon_hints[ "870mcs_zm" ] = &"ZM_BURIED_WB_870MCS"; + level.buildable_wallbuy_pickup_hints = []; + level.buildable_wallbuy_pickup_hints[ "ak74u_zm" ] = &"ZM_BURIED_PU_AK74U"; + level.buildable_wallbuy_pickup_hints[ "an94_zm" ] = &"ZM_BURIED_PU_AN94"; + level.buildable_wallbuy_pickup_hints[ "pdw57_zm" ] = &"ZM_BURIED_PU_PDW57"; + level.buildable_wallbuy_pickup_hints[ "svu_zm" ] = &"ZM_BURIED_PU_SVU"; + level.buildable_wallbuy_pickup_hints[ "tazer_knuckles_zm" ] = &"ZM_BURIED_PU_TAZER"; + level.buildable_wallbuy_pickup_hints[ "870mcs_zm" ] = &"ZM_BURIED_PU_870MCS"; + level.buildable_wallbuy_weapon_models = []; + level.buildable_wallbuy_weapon_angles = []; + _a64 = level.buildable_wallbuy_weapon_models; + _k64 = getFirstArrayKey( _a64 ); + while ( isDefined( _k64 ) ) + { + model = _a64[ _k64 ]; + if ( isDefined( model ) ) + { + precachemodel( model ); + } + _k64 = getNextArrayKey( _a64, _k64 ); + } +} + +init_buildables( buildablesenabledlist ) +{ + registerclientfield( "scriptmover", "buildable_glint_fx", 12000, 1, "int" ); + precacheitem( "chalk_draw_zm" ); + precacheitem( "no_hands_zm" ); + level._effect[ "wallbuy_replace" ] = loadfx( "maps/zombie_buried/fx_buried_booze_candy_spawn" ); + level._effect[ "wallbuy_drawing" ] = loadfx( "maps/zombie/fx_zmb_wall_dyn_chalk_drawing" ); + level.str_buildables_build = &"ZOMBIE_BUILD_SQ_COMMON"; + level.str_buildables_building = &"ZOMBIE_BUILDING_SQ_COMMON"; + level.str_buildables_grab_part = &"ZOMBIE_BUILD_PIECE_GRAB"; + level.str_buildables_swap_part = &"ZOMBIE_BUILD_PIECE_SWITCH"; + level.safe_place_for_buildable_piece = ::safe_place_for_buildable_piece; + level.buildable_slot_count = max( 1, 2 ) + 1; + level.buildable_clientfields = []; + level.buildable_clientfields[ 0 ] = "buildable"; + level.buildable_clientfields[ 1 ] = "buildable" + "_pu"; + level.buildable_piece_counts = []; + level.buildable_piece_counts[ 0 ] = 15; + level.buildable_piece_counts[ 1 ] = 4; + if ( -1 ) + { + level.buildable_clientfields[ 2 ] = "buildable" + "_sq"; + level.buildable_piece_counts[ 2 ] = 13; + } + if ( isinarray( buildablesenabledlist, "sq_common" ) ) + { + add_zombie_buildable( "sq_common", level.str_buildables_build, level.str_buildables_building ); + } + if ( isinarray( buildablesenabledlist, "buried_sq_tpo_switch" ) ) + { + add_zombie_buildable( "buried_sq_tpo_switch", level.str_buildables_build, level.str_buildables_building ); + } + if ( isinarray( buildablesenabledlist, "buried_sq_ghost_lamp" ) ) + { + add_zombie_buildable( "buried_sq_ghost_lamp", level.str_buildables_build, level.str_buildables_building ); + } + if ( isinarray( buildablesenabledlist, "buried_sq_bt_m_tower" ) ) + { + add_zombie_buildable( "buried_sq_bt_m_tower", level.str_buildables_build, level.str_buildables_building ); + } + if ( isinarray( buildablesenabledlist, "buried_sq_bt_r_tower" ) ) + { + add_zombie_buildable( "buried_sq_bt_r_tower", level.str_buildables_build, level.str_buildables_building ); + } + if ( isinarray( buildablesenabledlist, "buried_sq_oillamp" ) ) + { + add_zombie_buildable( "buried_sq_oillamp", level.str_buildables_build, level.str_buildables_building, &"NULL_EMPTY" ); + } + if ( isinarray( buildablesenabledlist, "turbine" ) ) + { + add_zombie_buildable( "turbine", level.str_buildables_build, level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_vox_category( "turbine", "trb" ); + } + if ( isinarray( buildablesenabledlist, "springpad_zm" ) ) + { + add_zombie_buildable( "springpad_zm", level.str_buildables_build, level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_vox_category( "springpad_zm", "stm" ); + } + if ( isinarray( buildablesenabledlist, "subwoofer_zm" ) ) + { + add_zombie_buildable( "subwoofer_zm", level.str_buildables_build, level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_vox_category( "subwoofer_zm", "sw" ); + } + if ( isinarray( buildablesenabledlist, "headchopper_zm" ) ) + { + add_zombie_buildable( "headchopper_zm", level.str_buildables_build, level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_vox_category( "headchopper_zm", "hc" ); + } + if ( isinarray( buildablesenabledlist, "booze" ) ) + { + add_zombie_buildable( "booze", &"ZM_BURIED_LEAVE_BOOZE", level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_piece_vox_category( "booze", "booze" ); + } + if ( isinarray( buildablesenabledlist, "candy" ) ) + { + add_zombie_buildable( "candy", &"ZM_BURIED_LEAVE_CANDY", level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_piece_vox_category( "candy", "candy" ); + } + if ( isinarray( buildablesenabledlist, "chalk" ) ) + { + add_zombie_buildable( "chalk", &"NULL_EMPTY", level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_piece_vox_category( "chalk", "gunshop_chalk", 300 ); + } + if ( isinarray( buildablesenabledlist, "sloth" ) ) + { + add_zombie_buildable( "sloth", &"ZM_BURIED_BOOZE_GV", level.str_buildables_building, &"NULL_EMPTY" ); + } + if ( isinarray( buildablesenabledlist, "keys_zm" ) ) + { + add_zombie_buildable( "keys_zm", &"ZM_BURIED_KEYS_BL", level.str_buildables_building, &"NULL_EMPTY" ); + add_zombie_buildable_piece_vox_category( "keys_zm", "key" ); + } + level thread chalk_host_migration(); +} + +include_buildables( buildablesenabledlist ) +{ + 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, 1 ); + 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, 2 ); + 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, 3 ); + springpad_door = generate_zombie_buildable_piece( "springpad_zm", "p6_zm_buildable_tramplesteam_door", 32, 64, 0, "zom_hud_trample_steam_screen", ::onpickup_common, ::ondrop_common, undefined, "Tag_part_02", undefined, 4 ); + springpad_flag = generate_zombie_buildable_piece( "springpad_zm", "p6_zm_buildable_tramplesteam_bellows", 32, 15, 0, "zom_hud_trample_steam_bellow", ::onpickup_common, ::ondrop_common, undefined, "Tag_part_04", undefined, 5 ); + springpad_motor = generate_zombie_buildable_piece( "springpad_zm", "p6_zm_buildable_tramplesteam_compressor", 32, 15, 0, "zom_hud_trample_steam_compressor", ::onpickup_common, ::ondrop_common, undefined, "Tag_part_01", undefined, 6 ); + springpad_whistle = generate_zombie_buildable_piece( "springpad_zm", "p6_zm_buildable_tramplesteam_flag", 48, 15, 0, "zom_hud_trample_steam_whistle", ::onpickup_common, ::ondrop_common, undefined, "Tag_part_03", undefined, 7 ); + 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, 1, 2 ); + sq_common_meteor = generate_zombie_buildable_piece( "sq_common", "p6_zm_buildable_sq_meteor", 32, 64, 0, "zm_hud_icon_sq_meteor", ::onpickup_common, ::ondrop_common, undefined, "tag_part_04", undefined, 2, 2 ); + 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, 3, 2 ); + 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, 4, 2 ); + sq_lamp_piece = generate_zombie_buildable_piece( "buried_sq_oillamp", "p6_zm_bu_lantern_silver_on", 32, 64, 0, "zm_hud_icon_jetgun_engine", ::onpickup_common, ::ondrop_common, undefined, undefined, undefined, 13, 2 ); + sq_m_tower_vacuum_tube = generate_zombie_buildable_piece( "buried_sq_bt_m_tower", "p6_zm_bu_sq_vaccume_tube", 32, 64, 0, "zm_hud_icon_sq_powerbox", ::onpickup_common, ::ondrop_common, undefined, "j_vaccume_01", undefined, 7, 2 ); + sq_m_tower_battery = generate_zombie_buildable_piece( "buried_sq_bt_m_tower", "p6_zm_bu_sq_buildable_battery", 32, 64, 0, "zm_hud_icon_battery", ::onpickup_common, ::ondrop_common, undefined, "j_battery", undefined, 8, 2 ); + sq_r_tower_crystal = generate_zombie_buildable_piece( "buried_sq_bt_r_tower", "p6_zm_bu_sq_crystal", 96, 64, 0, "zm_hud_icon_sq_powerbox", ::onpickup_common, ::ondrop_common, undefined, "j_crystal_01", undefined, 9, 2 ); + sq_r_tower_satellite = generate_zombie_buildable_piece( "buried_sq_bt_r_tower", "p6_zm_bu_sq_satellite_dish", 32, 64, 0, "zm_hud_icon_sq_powerbox", ::onpickup_common, ::ondrop_common, "j_satellite", undefined, undefined, 10, 2 ); + sq_s_tower_antenna = generate_zombie_buildable_piece( "buried_sq_bt_m_tower", "p6_zm_bu_sq_antenna", 32, 64, 0, "zm_hud_icon_sq_powerbox", ::onpickup_common, ::ondrop_common, undefined, "j_antenna", undefined, 11, 2 ); + sq_s_tower_wire = generate_zombie_buildable_piece( "buried_sq_bt_m_tower", "p6_zm_bu_sq_wire_spool", 32, 64, 0, "zm_hud_icon_sq_powerbox", ::onpickup_common, ::ondrop_common, undefined, "j_wire", undefined, 12, 2 ); + subwoofer_speaker = generate_zombie_buildable_piece( "subwoofer_zm", "t6_wpn_zmb_subwoofer_parts_speaker", 32, 64, 0, "zom_hud_icon_buildable_woof_speaker", ::onpickup_common, ::ondrop_common, undefined, "TAG_SPEAKER", undefined, 8 ); + subwoofer_motor = generate_zombie_buildable_piece( "subwoofer_zm", "t6_wpn_zmb_subwoofer_parts_motor", 48, 15, 0, "zom_hud_icon_buildable_woof_motor", ::onpickup_common, ::ondrop_common, undefined, "TAG_ENGINE", undefined, 9 ); + subwoofer_table = generate_zombie_buildable_piece( "subwoofer_zm", "t6_wpn_zmb_subwoofer_parts_table", 48, 15, 0, "zom_hud_icon_buildable_woof_frame", ::onpickup_common, ::ondrop_common, undefined, "TAG_SPIN", undefined, 11 ); + subwoofer_mount = generate_zombie_buildable_piece( "subwoofer_zm", "t6_wpn_zmb_subwoofer_parts_mount", 32, 15, 0, "zom_hud_icon_buildable_woof_chains", ::onpickup_common, ::ondrop_common, undefined, "TAG_MOUNT", undefined, 10 ); + headchopper_blade = generate_zombie_buildable_piece( "headchopper_zm", "t6_wpn_zmb_chopper_part_blade", 32, 64, 0, "zom_hud_icon_buildable_chop_a", ::onpickup_common, ::ondrop_common, undefined, "TAG_SAW", undefined, 12 ); + headchopper_crank = generate_zombie_buildable_piece( "headchopper_zm", "t6_wpn_zmb_chopper_part_crank", 32, 15, 0, "zom_hud_icon_buildable_chop_b", ::onpickup_common, ::ondrop_common, undefined, "TAG_CRANK", undefined, 13 ); + headchopper_hinge = generate_zombie_buildable_piece( "headchopper_zm", "t6_wpn_zmb_chopper_part_hinge", 32, 15, 0, "zom_hud_icon_buildable_chop_c", ::onpickup_common, ::ondrop_common, undefined, "TAG_GEARS", undefined, 14 ); + headchopper_mount = generate_zombie_buildable_piece( "headchopper_zm", "t6_wpn_zmb_chopper_part_mount", 32, 15, 0, "zom_hud_icon_buildable_chop_d", ::onpickup_common, ::ondrop_common, undefined, "TAG_MOUNT", undefined, 15 ); + bottle = generate_zombie_buildable_piece( "booze", "p6_zm_bu_booze", 32, 64, 2,4, "zom_hud_icon_buildable_sloth_booze", ::onpickup_booze, ::ondrop_booze, undefined, undefined, 0, 1, 1 ); + cane = generate_zombie_buildable_piece( "candy", "p6_zm_bu_sloth_candy_bowl", 32, 64, 2,4, "zom_hud_icon_buildable_sloth_candy", ::onpickup_candy, ::ondrop_candy, undefined, undefined, 0, 2, 1 ); + pencil = generate_zombie_buildable_piece( "chalk", "p6_zm_bu_chalk", 32, 64, 2,4, "zom_hud_icon_buildable_weap_chalk", ::onpickup_common, ::ondrop_chalk, undefined, undefined, 0, 4, 1 ); + key_chain = generate_zombie_buildable_piece( "keys_zm", "p6_zm_bu_sloth_key", 32, 64, 9, "zom_hud_icon_buildable_sloth_key", ::onpickup_keys, ::ondrop_keys, undefined, undefined, 0, 3, 1 ); + if ( isinarray( buildablesenabledlist, "turbine" ) ) + { + 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" ); + } + if ( isinarray( buildablesenabledlist, "springpad_zm" ) ) + { + springpad = spawnstruct(); + springpad.name = "springpad_zm"; + springpad add_buildable_piece( springpad_door ); + springpad add_buildable_piece( springpad_flag ); + springpad add_buildable_piece( springpad_motor ); + springpad add_buildable_piece( springpad_whistle ); + springpad.triggerthink = ::springpadbuildable; + include_buildable( springpad ); + } + if ( isinarray( buildablesenabledlist, "sq_common" ) ) + { + if ( is_sidequest_allowed( "zclassic" ) ) + { + 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" ); + } + } + if ( isinarray( buildablesenabledlist, "buried_sq_oillamp" ) ) + { + if ( is_sidequest_allowed( "zclassic" ) ) + { + sq_oillamp = spawnstruct(); + sq_oillamp.name = "buried_sq_oillamp"; + sq_oillamp add_buildable_piece( sq_lamp_piece ); + sq_oillamp.triggerthink = ::sqoillampbuildable; + include_buildable( sq_oillamp ); + } + } + if ( isinarray( buildablesenabledlist, "buried_sq_bt_m_tower" ) ) + { + if ( is_sidequest_allowed( "zclassic" ) ) + { + sq_m_tower = spawnstruct(); + sq_m_tower.name = "buried_sq_bt_m_tower"; + sq_m_tower add_buildable_piece( sq_m_tower_vacuum_tube ); + sq_m_tower add_buildable_piece( sq_m_tower_battery ); + sq_m_tower add_buildable_piece( sq_s_tower_antenna, undefined, 1 ); + sq_m_tower add_buildable_piece( sq_s_tower_wire, undefined, 1 ); + sq_m_tower.triggerthink = ::sqmtowerbuildable; + sq_m_tower.onuseplantobject = ::onuseplantobject_mtower; + include_buildable( sq_m_tower ); + } + else + { + remove_maxis_tower(); + } + } + if ( isinarray( buildablesenabledlist, "buried_sq_bt_r_tower" ) ) + { + if ( is_sidequest_allowed( "zclassic" ) ) + { + sq_r_tower = spawnstruct(); + sq_r_tower.name = "buried_sq_bt_r_tower"; + sq_r_tower add_buildable_piece( sq_r_tower_crystal ); + sq_r_tower add_buildable_piece( sq_r_tower_satellite ); + sq_r_tower add_buildable_piece( sq_s_tower_antenna, undefined, 1 ); + sq_r_tower add_buildable_piece( sq_s_tower_wire, undefined, 1 ); + sq_r_tower.triggerthink = ::sqrtowerbuildable; + sq_r_tower.onuseplantobject = ::onuseplantobject_rtower; + include_buildable( sq_r_tower ); + } + else + { + remove_ricky_tower(); + } + } + if ( isinarray( buildablesenabledlist, "subwoofer_zm" ) ) + { + subwoofer = spawnstruct(); + subwoofer.name = "subwoofer_zm"; + subwoofer add_buildable_piece( subwoofer_speaker ); + subwoofer add_buildable_piece( subwoofer_motor ); + subwoofer add_buildable_piece( subwoofer_table ); + subwoofer add_buildable_piece( subwoofer_mount ); + subwoofer.triggerthink = ::subwooferbuildable; + include_buildable( subwoofer ); + } + if ( isinarray( buildablesenabledlist, "headchopper_zm" ) ) + { + ent = getent( "buildable_headchopper", "targetname" ); + ent setmodel( "t6_wpn_zmb_chopper" ); + headchopper = spawnstruct(); + headchopper.name = "headchopper_zm"; + headchopper add_buildable_piece( headchopper_blade ); + headchopper add_buildable_piece( headchopper_crank ); + headchopper add_buildable_piece( headchopper_hinge ); + headchopper add_buildable_piece( headchopper_mount ); + headchopper.triggerthink = ::headchopperbuildable; + include_buildable( headchopper ); + } + if ( isinarray( buildablesenabledlist, "booze" ) ) + { + level.booze_model = "p6_zm_bu_sloth_booze_jug"; + precachemodel( level.booze_model ); + bottle.hint_grab = &"ZM_BURIED_BOOZE_G"; + bottle.hint_swap = &"ZM_BURIED_BOOZE_G"; + bottle manage_multiple_pieces( 2 ); + bottle.onspawn = ::piece_spawn_booze; + bottle.onunspawn = ::piece_unspawn_booze; + bottle.ondestroy = ::piece_destroy_booze; + level.booze_piece = bottle; + booze = spawnstruct(); + booze.name = "booze"; + booze.hint_more = &"ZM_BURIED_I_NEED_BOOZE"; + booze.hint_wrong = &"ZM_BURIED_I_SAID_BOOZE"; + booze add_buildable_piece( bottle ); + booze.triggerthink = ::boozebuildable; + booze.onuseplantobject = ::onuseplantobject_booze_and_candy; + include_buildable( booze ); + } + if ( isinarray( buildablesenabledlist, "candy" ) ) + { + level.candy_model = "p6_zm_bu_sloth_candy_bowl"; + precachemodel( level.candy_model ); + cane.hint_grab = &"ZM_BURIED_CANDY_G"; + cane.hint_swap = &"ZM_BURIED_CANDY_G"; + cane manage_multiple_pieces( 1 ); + cane.onspawn = ::piece_spawn_candy; + cane.onunspawn = ::piece_unspawn_candy; + cane.ondestroy = ::piece_destroy_candy; + level.candy_piece = cane; + candy = spawnstruct(); + candy.name = "candy"; + candy.hint_more = &"ZM_BURIED_I_WANT_CANDY"; + candy.hint_wrong = &"ZM_BURIED_THATS_NOT_CANDY"; + candy add_buildable_piece( cane ); + candy.triggerthink = ::candybuildable; + candy.onuseplantobject = ::onuseplantobject_booze_and_candy; + include_buildable( candy ); + } + if ( isinarray( buildablesenabledlist, "sloth" ) ) + { + sloth_buildable = spawnstruct(); + sloth_buildable.name = "sloth"; + sloth_buildable.hint_more = &"NULL_EMPTY"; + sloth_buildable.hint_wrong = &"NULL_EMPTY"; + sloth_buildable add_buildable_piece( bottle ); + sloth_buildable add_buildable_piece( cane ); + sloth_buildable.triggerthink = ::slothbuildable; + sloth_buildable.onuseplantobject = ::onuseplantobject_sloth; + sloth_buildable.snd_build_add_vo_override = ::empty; + include_buildable( sloth_buildable ); + } + if ( isinarray( buildablesenabledlist, "chalk" ) ) + { + pencil.hint_grab = level.str_buildables_grab_part; + pencil.hint_swap = level.str_buildables_swap_part; + pencil.onspawn = ::piece_spawn_chalk; + pencil.ondestroy = ::piece_destroy_chalk; + pencil manage_multiple_pieces( 6, 6 ); + chalk = spawnstruct(); + chalk.name = "chalk"; + chalk.hint_more = &"NULL_EMPTY"; + chalk.hint_wrong = &"NULL_EMPTY"; + chalk add_buildable_piece( pencil ); + chalk.triggerthink = ::chalkbuildable; + chalk.onuseplantobject = ::onuseplantobject_chalk; + if ( isDefined( level.buy_random_wallbuys ) && level.buy_random_wallbuys ) + { + chalk.oncantuse = ::oncantuse_chalk; + } + chalk.onbeginuse = ::onbeginuse_chalk; + chalk.onenduse = ::onenduse_chalk; + include_buildable( chalk ); + } + if ( isinarray( buildablesenabledlist, "keys_zm" ) ) + { + key_chain.onspawn = ::onspawn_keys; + key_chain manage_multiple_pieces( 2 ); + key_chain.hint_grab = &"ZM_BURIED_KEY_G"; + key_chain.hint_swap = &"ZM_BURIED_KEY_G"; + key = spawnstruct(); + key.name = "keys_zm"; + key add_buildable_piece( key_chain ); + key.triggerthink = ::keysbuildable; + key.onuseplantobject = ::onuseplantobject_key; + key.hint_wrong = &"NULL_EMPTY"; + include_buildable( key ); + } + generate_piece_makers(); + level thread maps/mp/zombies/_zm_buildables_pooled::randomize_pooled_buildables( "buried" ); +} + +sqcommonbuildable() +{ + level.sq_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "sq_common_buildable_trigger", "sq_common", "sq_common", "", 1, 0 ); + if ( isDefined( level.sq_buildable ) ) + { + level.sq_buildable.ignore_open_sesame = 1; + } +} + +sqmtowerbuildable() +{ + level.sq_mtower_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "sq_m_tower_buildable_trigger", "buried_sq_bt_m_tower", "buried_sq_bt_m_tower", "", 1, 0 ); + level.sq_mtower_buildable.ignore_open_sesame = 1; +} + +remove_all_ents( named ) +{ + ents = getentarray( named, "targetname" ); + _a516 = ents; + _k516 = getFirstArrayKey( _a516 ); + while ( isDefined( _k516 ) ) + { + ent = _a516[ _k516 ]; + ent delete(); + _k516 = getNextArrayKey( _a516, _k516 ); + } +} + +remove_maxis_tower() +{ + remove_all_ents( "sq_m_tower_buildable_trigger" ); +} + +sqrtowerbuildable() +{ + level.sq_rtower_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "sq_r_tower_buildable_trigger", "buried_sq_bt_r_tower", "buried_sq_bt_r_tower", "", 1, 0 ); + level.sq_rtower_buildable.ignore_open_sesame = 1; +} + +remove_ricky_tower() +{ + remove_all_ents( "guillotine_trigger" ); + remove_all_ents( "ricky_tower_col" ); + remove_all_ents( "sq_r_tower_buildable_trigger" ); +} + +turbinebuildable() +{ + level.turbine_buildable = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "turbine_buildable_trigger", "turbine", "equip_turbine_zm", &"ZOMBIE_EQUIP_TURBINE_PICKUP_HINT_STRING", 1, 1 ); + maps/mp/zombies/_zm_buildables_pooled::add_buildable_to_pool( level.turbine_buildable, "buried" ); +} + +springpadbuildable() +{ + stub = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "springpad_zm_buildable_trigger", "springpad_zm", "equip_springpad_zm", &"ZM_BURIED_EQ_SP_PHS", 1, 1 ); + maps/mp/zombies/_zm_buildables_pooled::add_buildable_to_pool( stub, "buried" ); +} + +subwooferbuildable() +{ + stub = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "subwoofer_zm_buildable_trigger", "subwoofer_zm", "equip_subwoofer_zm", &"ZM_BURIED_EQ_SW_PHS", 1, 1 ); + maps/mp/zombies/_zm_buildables_pooled::add_buildable_to_pool( stub, "buried" ); +} + +headchopperbuildable() +{ + stub = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "headchopper_buildable_trigger", "headchopper_zm", "equip_headchopper_zm", &"ZM_BURIED_EQ_HC_PHS", 1, 1 ); + maps/mp/zombies/_zm_buildables_pooled::add_buildable_to_pool( stub, "buried" ); +} + +boozebuildable() +{ + booze_builds = maps/mp/zombies/_zm_buildables::buildable_trigger_think_array( "booze_buildable_trigger", "booze", "booze", &"ZM_BURIED_BOOZE_G", 1, 0 ); + _a567 = booze_builds; + _k567 = getFirstArrayKey( _a567 ); + while ( isDefined( _k567 ) ) + { + stub = _a567[ _k567 ]; + stub.ignore_open_sesame = 1; + stub.require_look_at = 0; + stub bpstub_set_custom_think_callback( ::bptrigger_think_unbuild_no_return ); + _k567 = getNextArrayKey( _a567, _k567 ); + } +} + +candybuildable() +{ + candy_builds = maps/mp/zombies/_zm_buildables::buildable_trigger_think_array( "candy_buildable_trigger", "candy", "candy", &"ZM_BURIED_CANDY_G", 1, 0 ); + _a579 = candy_builds; + _k579 = getFirstArrayKey( _a579 ); + while ( isDefined( _k579 ) ) + { + stub = _a579[ _k579 ]; + stub.ignore_open_sesame = 1; + stub.require_look_at = 0; + stub bpstub_set_custom_think_callback( ::bptrigger_think_unbuild_no_return ); + _k579 = getNextArrayKey( _a579, _k579 ); + } +} + +sloth_in_armory_near_bench() +{ + return 1; +} + +slothbuildable() +{ +} + +chalkbuildable() +{ + level.chalk_builds = maps/mp/zombies/_zm_buildables::buildable_trigger_think_array( "chalk_buildable_trigger", "chalk", "chalk", level.str_buildables_grab_part, 1, 0 ); + _a630 = level.chalk_builds; + _k630 = getFirstArrayKey( _a630 ); + while ( isDefined( _k630 ) ) + { + stub = _a630[ _k630 ]; + stub.prompt_and_visibility_func = ::chalk_prompt; + stub.script_length = 16; + stub.ignore_open_sesame = 1; + stub.build_weapon = "chalk_draw_zm"; + stub.building_prompt = &"ZM_BURIED_DRAW"; + if ( isDefined( stub.target ) ) + { + wallbuy = getstruct( stub.target, "targetname" ); + stub.origin = wallbuy.origin; + stub.angles = wallbuy.angles; + if ( isDefined( wallbuy.script_location ) ) + { + stub.location = wallbuy.script_location; + } + } + _k630 = getNextArrayKey( _a630, _k630 ); + } +} + +keysbuildable() +{ + door = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "cell_door_trigger", "keys_zm", "keys_zm", "", 1, 3 ); + if ( isDefined( door ) ) + { + door.ignore_open_sesame = 1; + door.prompt_and_visibility_func = ::cell_door_key_prompt; + door.script_unitrigger_type = "unitrigger_radius_use"; + door.radius = 32; + door.test_radius_sq = ( door.radius + 15 ) * ( door.radius + 15 ); + door.building_prompt = &"ZM_BURIED_UNLOCKING"; + thread watch_cell_open_close( door ); + } +} + +safe_place_for_buildable_piece( piece ) +{ + if ( self is_jumping() ) + { + return 0; + } + if ( piece.buildablename == "booze" ) + { + return 0; + } + return 1; +} + +onuseplantobject_mtower( player ) +{ + if ( !isDefined( player player_get_buildable_piece( 2 ) ) ) + { + return; + } + switch( player player_get_buildable_piece( 2 ).modelname ) + { + case "p6_zm_bu_sq_vaccume_tube": + level setclientfield( "sq_gl_b_vt", 1 ); + break; + case "p6_zm_bu_sq_buildable_battery": + level setclientfield( "sq_gl_b_bb", 1 ); + break; + case "p6_zm_bu_sq_antenna": + level setclientfield( "sq_gl_b_a", 1 ); + break; + case "p6_zm_bu_sq_wire_spool": + level setclientfield( "sq_gl_b_ws", 1 ); + break; + } + level notify( "mtower_object_planted" ); +} + +onuseplantobject_rtower( player ) +{ + if ( !isDefined( player player_get_buildable_piece( 2 ) ) ) + { + return; + } + m_tower = getent( "sq_guillotine", "targetname" ); + switch( player player_get_buildable_piece( 2 ).modelname ) + { + case "p6_zm_bu_sq_crystal": + m_tower sq_tower_spawn_attachment( "p6_zm_bu_sq_crystal", "j_crystal_01" ); + break; + case "p6_zm_bu_sq_satellite_dish": + m_tower sq_tower_spawn_attachment( "p6_zm_bu_sq_satellite_dish", "j_satellite" ); + break; + case "p6_zm_bu_sq_antenna": + m_tower sq_tower_spawn_attachment( "p6_zm_bu_sq_antenna", "j_antenna" ); + break; + case "p6_zm_bu_sq_wire_spool": + m_tower sq_tower_spawn_attachment( "p6_zm_bu_sq_wire_spool", "j_spool" ); + break; + } + level notify( "rtower_object_planted" ); +} + +sq_tower_spawn_attachment( str_model, str_tag ) +{ + m_part = spawn( "script_model", self gettagorigin( str_tag ) ); + m_part.angles = self gettagangles( str_tag ); + m_part setmodel( str_model ); +} + +sqoillampbuildable() +{ + level.sq_lamp_generator_unitrig = maps/mp/zombies/_zm_buildables::buildable_trigger_think( "generator_use_trigger", "buried_sq_oillamp", "buried_sq_oillamp", "", 1, 0 ); + if ( isDefined( level.sq_lamp_generator_unitrig ) ) + { + level.sq_lamp_generator_unitrig.ignore_open_sesame = 1; + level.sq_lamp_generator_unitrig.buildablestub_reject_func = ::sq_generator_buildablestub_reject_func; + } +} + +sq_generator_buildablestub_reject_func( player ) +{ + if ( !flag( "ftl_lantern_charged" ) ) + { + return 1; + } + return 0; +} + +ondrop_common( player ) +{ +/# + println( "ZM >> Common part callback onDrop()" ); +#/ + self.piece_owner = undefined; +} + +onpickup_common( player ) +{ +/# + println( "ZM >> Common part callback onPickup()" ); +#/ + self.piece_owner = player; + if ( isDefined( self.buildablename ) ) + { + sound = "zmb_buildable_pickup"; + if ( self.buildablename == "candy" ) + { + sound = "zmb_candy_pickup"; + } + if ( self.buildablename == "booze" ) + { + sound = "zmb_booze_pickup"; + } + if ( self.buildablename == "chalk" ) + { + sound = "zmb_chalk_grab"; + } + player playsound( sound ); + } +} + +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 && isDefined( player player_get_buildable_piece( 0 ) ) && player player_get_buildable_piece( 0 ).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; + } + } +} + +watch_player_purchase( name, piece ) +{ + level endon( "wait_respawn_" + name ); + level endon( "start_of_round" ); + allow_players_purchase( name, 1 ); + level waittill( "player_purchase_" + name, player ); + allow_players_purchase( name, 0 ); + player player_take_piece( piece ); +} + +wait_respawn_candy_booze( piece, name ) +{ + level notify( "wait_respawn_" + name ); + level endon( "wait_respawn_" + name ); + level endon( "player_purchase_" + name ); + level thread watch_player_purchase( name, piece ); + level waittill( "start_of_round" ); + allow_players_purchase( name, 0 ); + piece piece_spawn_at(); +} + +wait_respawn_booze_at_start( piece ) +{ + wait 4; + if ( isDefined( level.jail_barricade_down ) && level.jail_barricade_down ) + { + level thread wait_respawn_candy_booze( piece, "booze" ); + } + else + { + piece piece_spawn_at( piece.start_origin, piece.start_angles ); + } +} + +piece_spawn_booze() +{ + self.model setmodel( level.booze_model ); + playfxontag( level._effect[ "booze_candy_spawn" ], self.model, "tag_origin" ); + self.model setclientfield( "buildable_glint_fx", 1 ); +} + +piece_unspawn_booze() +{ + if ( isDefined( self.model ) ) + { + piece_model = self.model; + self.model = undefined; + piece_model thread destroyglintfx(); + } +} + +piece_destroy_booze() +{ + if ( isDefined( level.jail_barricade_down ) && level.jail_barricade_down ) + { + level thread wait_respawn_candy_booze( self, "booze" ); + } + else + { + level thread wait_respawn_booze_at_start( self ); + } +} + +onpickup_booze( player ) +{ + level notify( "sloth_pickup" ); + onpickup_common( player ); + if ( isDefined( level.jail_barricade_down ) && !level.jail_barricade_down ) + { + if ( !isDefined( level.booze_start_origin ) ) + { + level.booze_start_origin = self.start_origin; + level.booze_start_angles = self.start_angles; + } + } +} + +piece_spawn_candy() +{ + self.model setmodel( level.candy_model ); + playfxontag( level._effect[ "booze_candy_spawn" ], self.model, "tag_origin" ); + self.model setclientfield( "buildable_glint_fx", 1 ); +} + +piece_unspawn_candy() +{ + if ( isDefined( self.model ) ) + { + piece_model = self.model; + self.model = undefined; + piece_model thread destroyglintfx(); + } +} + +piece_destroy_candy() +{ + self.built = 0; + self.building = 0; + level thread wait_respawn_candy_booze( self, "candy" ); +} + +onpickup_candy( player ) +{ + level notify( "sloth_pickup" ); + onpickup_common( player ); +} + +ondrop_booze( player ) +{ + level notify( "sloth_drop" ); + player notify( "sloth_drop" ); + piece = player player_get_buildable_piece( 1 ); + if ( isDefined( piece ) ) + { + piece.model setclientfield( "buildable_glint_fx", 1 ); + } + ondrop_common( player ); + if ( isDefined( level.jail_barricade_down ) && !level.jail_barricade_down ) + { + thread wait_put_piece_back_in_jail( piece, level.booze_start_origin, level.booze_start_angles ); + } +} + +wait_put_piece_back_in_jail( piece, origin, angles ) +{ + if ( isDefined( piece ) ) + { + piece piece_unspawn(); + wait 4; + piece piece_unspawn(); + piece piece_spawn_at( origin, angles ); + } +} + +ondrop_candy( player ) +{ + level notify( "sloth_drop" ); + player notify( "sloth_drop" ); + piece = player player_get_buildable_piece( 1 ); + if ( isDefined( piece ) ) + { + piece.model setclientfield( "buildable_glint_fx", 1 ); + } + ondrop_common( player ); +} + +onuseplantobject_booze_and_candy( player ) +{ + if ( isDefined( self.script_noteworthy ) ) + { + switch( self.script_noteworthy ) + { + case "candy_bench": + player thread candy_bench( self ); + break; + return; + } + } +} + +candy_bench( stub ) +{ + wait 0,2; + level notify( "candy_bench" ); +} + +onuseplantobject_sloth( player ) +{ +} + +piece_spawn_chalk() +{ + if ( !isDefined( self.first_origin ) ) + { + self.first_origin = self.start_origin; + self.first_angles = self.start_angles; + } + self thread piece_spawn_chalk_internal(); +} + +chalk_host_migration() +{ + level endon( "end_game" ); + level notify( "chalk_hostmigration" ); + level endon( "chalk_hostmigration" ); + while ( 1 ) + { + level waittill( "host_migration_end" ); + while ( !isDefined( level.chalk_pieces ) ) + { + continue; + } + _a1103 = level.chalk_pieces; + _k1103 = getFirstArrayKey( _a1103 ); + while ( isDefined( _k1103 ) ) + { + chalk = _a1103[ _k1103 ]; + if ( isDefined( chalk.model ) ) + { + weapon = chalk.script_noteworthy; + fx = level._effect[ "m14_zm_fx" ]; + if ( isDefined( level._effect[ weapon + "_chalk_fx" ] ) ) + { + fx = level._effect[ weapon + "_chalk_fx" ]; + } + if ( isDefined( level.chalk_buildable_pieces_hide ) && !level.chalk_buildable_pieces_hide ) + { + playfxontag( fx, chalk.model, "tag_origin" ); + } + } + wait_network_frame(); + _k1103 = getNextArrayKey( _a1103, _k1103 ); + } + } +} + +piece_spawn_chalk_internal() +{ + weapon = self.script_noteworthy; + if ( isDefined( weapon ) ) + { + if ( !isDefined( level.chalk_pieces ) ) + { + level.chalk_pieces = []; + } + level.chalk_pieces = add_to_array( level.chalk_pieces, self, 0 ); + self.model setmodel( "tag_origin" ); + wait 0,05; + fx = level._effect[ "m14_zm_fx" ]; + if ( isDefined( level._effect[ weapon + "_chalk_fx" ] ) ) + { + fx = level._effect[ weapon + "_chalk_fx" ]; + } + if ( isDefined( level.chalk_buildable_pieces_hide ) && !level.chalk_buildable_pieces_hide ) + { + playfxontag( fx, self.model, "tag_origin" ); + } + else + { + self.model.origin += vectorScale( ( 0, 0, 0 ), 1000 ); + } + if ( isDefined( level.monolingustic_prompt_format ) && level.monolingustic_prompt_format ) + { + self.hint_grab = &"ZM_BURIED_WB"; + self.hint_grab_parm1 = get_weapon_display_name( weapon ); + } + else + { + if ( isDefined( level.buildable_wallbuy_pickup_hints[ weapon ] ) ) + { + self.hint_grab = level.buildable_wallbuy_pickup_hints[ weapon ]; + self.hint_grab_parm1 = undefined; + } + else + { + self.hint_grab = &"ZM_BURIED_WALLBUILD"; + self.hint_grab_parm1 = undefined; + } + } + self.hint_swap = self.hint_grab; + self.hint_swap_parm1 = self.hint_grab_parm1; + if ( getDvarInt( #"1F0A2129" ) ) + { + self.cursor_hint = "HINT_WEAPON"; + self.cursor_hint_weapon = weapon; + } + } +} + +piece_destroy_chalk() +{ + thread wait_unbuild_chalk( self ); +} + +wait_unbuild_chalk( piece ) +{ + wait 0,1; + piece.built = 0; +} + +ondrop_chalk( player ) +{ + self piece_unspawn(); + self piece_spawn_at( self.first_origin, self.first_angles ); +} + +pick_up( thing ) +{ + candidate_list = []; + _a1225 = level.zones; + _k1225 = getFirstArrayKey( _a1225 ); + while ( isDefined( _k1225 ) ) + { + zone = _a1225[ _k1225 ]; + if ( isDefined( zone.unitrigger_stubs ) ) + { + candidate_list = arraycombine( candidate_list, zone.unitrigger_stubs, 1, 0 ); + } + _k1225 = getNextArrayKey( _a1225, _k1225 ); + } + candidate_list = array_randomize( candidate_list ); + _a1235 = candidate_list; + _k1235 = getFirstArrayKey( _a1235 ); + while ( isDefined( _k1235 ) ) + { + stub = _a1235[ _k1235 ]; + if ( isDefined( stub.piece ) && stub.piece.buildablename == thing ) + { + stub.piece piece_unspawn(); + return stub.piece; + } + _k1235 = getNextArrayKey( _a1235, _k1235 ); + } + return undefined; +} + +chalk_prompt( player ) +{ + if ( isDefined( level.buy_random_wallbuys ) && level.buy_random_wallbuys ) + { + if ( isDefined( self.stub.built ) && !self.stub.built ) + { + if ( !isDefined( player player_get_buildable_piece( 1 ) ) || !self.stub.buildablezone buildable_has_piece( player player_get_buildable_piece( 1 ) ) ) + { + self.stub.cost = 1500; + self.stub.hint_parm1 = 1500; + self.stub.hint_string = &"ZM_BURIED_RANDOM_WALLBUY"; + self sethintstring( self.stub.hint_string, self.stub.cost ); + return 1; + } + } + } + can_use = self buildabletrigger_update_prompt( player ); + if ( can_use ) + { + piece = player player_get_buildable_piece( 1 ); + if ( isDefined( piece ) ) + { + weapon = piece.script_noteworthy; + if ( isDefined( weapon ) ) + { + self.stub.hint_string = level.buildable_wallbuy_weapon_hints[ weapon ]; + self sethintstring( self.stub.hint_string ); + } + } + } + return can_use; +} + +buy_random_wallbuy( player, cost ) +{ + temp_piece = undefined; + if ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + return temp_piece; + } + if ( !player can_buy_weapon() ) + { + wait 0,1; + return temp_piece; + } + if ( player has_powerup_weapon() ) + { + wait 0,1; + return temp_piece; + } + if ( player.score >= cost ) + { + temp_piece = player pick_up( "chalk" ); + if ( !isDefined( temp_piece ) ) + { + return temp_piece; + } + player maps/mp/zombies/_zm_score::minus_to_player_score( cost ); + 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, self.zombie_weapon_upgrade, self.origin, "weapon" ); + player maps/mp/zombies/_zm_stats::increment_client_stat( "wallbuy_weapons_purchased" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "wallbuy_weapons_purchased" ); + return temp_piece; + } + player play_sound_on_ent( "no_purchase" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "no_money_weapon" ); + return temp_piece; +} + +onbeginuse_chalk( player ) +{ + player thread player_draw_chalk( self ); +} + +player_draw_chalk( stub ) +{ + self endon( "death" ); + self endon( "stop_action" ); + self notify( "end_chalk_dust" ); + self endon( "end_chalk_dust" ); + origin = stub.origin; + forward = anglesToForward( stub.angles ); + while ( isalive( self ) ) + { + playfx( level._effect[ "wallbuy_drawing" ], origin, forward ); + wait 0,1; + } +} + +onenduse_chalk( team, player, result ) +{ + player notify( "end_chalk_dust" ); +} + +oncantuse_chalk( player ) +{ + if ( self.built ) + { + return; + } + if ( !isDefined( player player_get_buildable_piece( 1 ) ) || !self.buildablezone buildable_has_piece( player player_get_buildable_piece( 1 ) ) ) + { + self.cost = 1500; + piece = buy_random_wallbuy( player, self.cost ); + if ( !isDefined( piece ) ) + { + return; + } + weapon = piece.script_noteworthy; + if ( isDefined( weapon ) ) + { + origin = self.origin; + angles = self.angles; + if ( isDefined( level._effect[ "wallbuy_replace" ] ) ) + { + playfx( level._effect[ "wallbuy_replace" ], origin, anglesToForward( angles ) ); + } + add_dynamic_wallbuy( weapon, self.target, 0 ); + if ( is_melee_weapon( weapon ) ) + { + player maps/mp/zombies/_zm_melee_weapon::give_melee_weapon_by_name( weapon ); + } + else + { + if ( is_lethal_grenade( weapon ) ) + { + player takeweapon( player get_player_lethal_grenade() ); + player set_player_lethal_grenade( weapon ); + } + else + { + if ( weapon == "claymore_zm" ) + { + player thread maps/mp/zombies/_zm_weap_claymore::show_claymore_hint( "claymore_purchased" ); + } + } + player weapon_give( weapon ); + } + if ( !isDefined( level.built_wallbuys ) ) + { + level.built_wallbuys = 0; + } + level.built_wallbuys++; + if ( level.built_wallbuys >= 6 ) + { + level.built_wallbuys = -100; + } + } + self buildablestub_finish_build( player ); + self buildablestub_remove(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self ); + } +} + +onuseplantobject_chalk( entity ) +{ + piece = entity player_get_buildable_piece( 1 ); + if ( isDefined( piece ) ) + { + weapon = piece.script_noteworthy; + if ( isDefined( weapon ) ) + { + origin = self.origin; + angles = self.angles; + if ( isDefined( level._effect[ "wallbuy_replace" ] ) ) + { + playfx( level._effect[ "wallbuy_replace" ], origin, anglesToForward( angles ) ); + } + add_dynamic_wallbuy( weapon, self.target, 1 ); + if ( !isDefined( level.built_wallbuys ) ) + { + level.built_wallbuys = 0; + } + level.built_wallbuys++; + if ( isplayer( entity ) ) + { + entity maps/mp/zombies/_zm_stats::increment_client_stat( "buried_wallbuy_placed", 0 ); + entity maps/mp/zombies/_zm_stats::increment_player_stat( "buried_wallbuy_placed" ); + entity maps/mp/zombies/_zm_stats::increment_client_stat( "buried_wallbuy_placed_" + weapon, 0 ); + entity maps/mp/zombies/_zm_stats::increment_player_stat( "buried_wallbuy_placed_" + weapon ); + } + if ( level.built_wallbuys >= 6 ) + { + if ( isplayer( entity ) ) + { + entity maps/mp/zombies/_zm_score::player_add_points( "build_wallbuy", 2000 ); + } + level.built_wallbuys = -100; + return; + } + else + { + if ( isplayer( entity ) ) + { + entity maps/mp/zombies/_zm_score::player_add_points( "build_wallbuy", 1000 ); + } + } + } + } +} + +onspawn_keys() +{ + if ( isDefined( self.unitrigger ) && isDefined( self.start_origin ) && self.model.origin == self.start_origin ) + { + self.unitrigger.origin_parent = undefined; + self.unitrigger.origin = self.model.origin + vectorScale( ( 0, 0, 0 ), 12 ); + } +} + +onpickup_keys( player ) +{ + onpickup_common( player ); + if ( isDefined( level.jail_barricade_down ) && !level.jail_barricade_down ) + { + if ( !isDefined( level.key_start_origin ) ) + { + level.key_start_origin = self.start_origin + vectorScale( ( 0, 0, 0 ), 6 ); + level.key_start_angles = self.start_angles; + } + } +} + +ondrop_keys( player ) +{ + piece = player player_get_buildable_piece( 1 ); + ondrop_common( player ); + if ( isDefined( level.jail_barricade_down ) && !level.jail_barricade_down ) + { + thread wait_put_piece_back_in_jail( piece, level.key_start_origin, level.key_start_angles ); + } +} + +cell_door_key_prompt( player ) +{ + if ( isDefined( level.cell_open ) && level.cell_open ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + return 0; + } + return self buildabletrigger_update_prompt( player ); +} + +onuseplantobject_key( player ) +{ + level notify( "cell_open" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_unlocked" ); +} + +stub_suspend_buildable( door ) +{ + door.buildablezone.pieces[ 0 ] piece_unspawn(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( door ); +} + +stub_resume_buildable( door ) +{ + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( door, ::buildable_place_think ); +} + +watch_cell_open_close( door ) +{ + level.cell_open = 0; +/# + thread watch_opensesame(); +#/ + while ( 1 ) + { + level waittill( "cell_open" ); + level.cell_open = 1; + wait 0,05; + stub_suspend_buildable( door ); + level waittill( "cell_close" ); + level.cell_open = 0; + stub_resume_buildable( door ); + stub_unbuild_buildable( door, 1 ); + } +} + +watch_opensesame() +{ +/# + level waittill( "open_sesame" ); + level notify( "cell_open" ); +#/ +} + +destroyglintfx() +{ + self setclientfield( "buildable_glint_fx", 0 ); + self ghost(); + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + if ( isDefined( self ) ) + { + self delete(); + } +} + +generate_piece_makers() +{ + level.piece_makers = []; + level.piece_maker_prompts = []; + level.piece_maker_prompts[ "booze" ] = &"ZM_BURIED_BOOZE_B"; + level.piece_maker_prompts[ "candy" ] = &"ZM_BURIED_CANDY_B"; + piece_maker_structs = getstructarray( "piece_purchase", "targetname" ); + _a1586 = piece_maker_structs; + _k1586 = getFirstArrayKey( _a1586 ); + while ( isDefined( _k1586 ) ) + { + pm = _a1586[ _k1586 ]; + piecename = pm.script_noteworthy; + if ( isDefined( piecename ) ) + { + level.piece_makers[ piecename ] = pm piece_maker_unitrigger( "piece_maker", ::piece_maker_update_prompt, ::piece_maker_think ); + level.piece_makers[ piecename ].piecename = piecename; + level.piece_makers[ piecename ].allow_purchase = 0; + level.piece_makers[ piecename ].notify_name = "player_purchase_" + piecename; + if ( isDefined( level.piece_maker_prompts[ piecename ] ) ) + { + level.piece_makers[ piecename ].buy_prompt = level.piece_maker_prompts[ piecename ]; + break; + } + else + { + level.piece_makers[ piecename ].buy_prompt = &"ZM_BURIED_BUY_UNKNOWN_STUFF"; + } + } + _k1586 = getNextArrayKey( _a1586, _k1586 ); + } +} + +allow_players_purchase( name, allow_purchase ) +{ + if ( isDefined( level.piece_makers[ name ] ) ) + { + level.piece_makers[ name ].allow_purchase = allow_purchase; + } +} + +piece_maker_unitrigger( name, prompt_fn, think_fn ) +{ + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = self.origin; + if ( isDefined( self.script_angles ) ) + { + unitrigger_stub.angles = self.script_angles; + } + else if ( isDefined( self.angles ) ) + { + unitrigger_stub.angles = self.angles; + } + else + { + unitrigger_stub.angles = ( 0, 0, 0 ); + } + unitrigger_stub.script_angles = unitrigger_stub.angles; + if ( isDefined( self.script_length ) ) + { + unitrigger_stub.script_length = self.script_length; + } + else + { + unitrigger_stub.script_length = 32; + } + 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; + } + 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 ); + return unitrigger_stub; +} + +piece_maker_update_prompt( player ) +{ + if ( isDefined( self.stub.allow_purchase ) && !self.stub.allow_purchase ) + { + self sethintstring( "" ); + return 0; + } + if ( player.score < 1000 ) + { + self sethintstring( "" ); + return 0; + } + else + { + self sethintstring( self.stub.buy_prompt, 1000 ); + } + return 1; +} + +piece_maker_think() +{ + self endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "trigger", player ); + if ( isDefined( self.stub.allow_purchase ) && !self.stub.allow_purchase ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + continue; + } + if ( player.score >= 1000 ) + { + player.score -= 1000; + level notify( self.stub.notify_name ); + self sethintstring( "" ); + continue; + } + else + { + self playsound( "evt_perk_deny" ); + player thread do_player_general_vox( "general", "exert_sigh", 10, 50 ); + } + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_classic.gsc b/zm_buried_patch/maps/mp/zm_buried_classic.gsc new file mode 100644 index 0000000..f062733 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_classic.gsc @@ -0,0 +1,1861 @@ +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_ai_sloth; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_weap_time_bomb; +#include maps/mp/zombies/_zm_perk_vulture; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm; +#include maps/mp/zm_buried_ee; +#include maps/mp/zm_buried_maze; +#include maps/mp/zm_buried_power; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zm_buried_buildables; +#include maps/mp/zm_buried_fountain; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ + precacheshellshock( "electrocution" ); + if ( getDvar( "createfx" ) != "" ) + { + return; + } + maps/mp/zombies/_zm_ai_ghost::init_animtree(); + level thread lsat_trigger_tweak(); + setup_buildables(); + maps/mp/zombies/_zm_equip_turbine::init( &"ZOMBIE_EQUIP_TURBINE_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_TURBINE_HOWTO" ); + maps/mp/zombies/_zm_equip_turbine::init_animtree(); + maps/mp/zombies/_zm_equip_springpad::init( &"ZM_BURIED_EQ_SP_PHS", &"ZM_BURIED_EQ_SP_HTS" ); + maps/mp/zombies/_zm_equip_subwoofer::init( &"ZM_BURIED_EQ_SW_PHS", &"ZM_BURIED_EQ_SW_HTS" ); + maps/mp/zombies/_zm_equip_headchopper::init( &"ZM_BURIED_EQ_HC_PHS", &"ZM_BURIED_EQ_HC_HTS" ); + level.springpad_attack_delay = 0,2; + maps/mp/zm_buried_fountain::init_fountain(); + level thread perk_vulture_custom_scripts(); +} + +setup_buildables() +{ + classicbuildables = array( "sq_common", "turbine", "springpad_zm", "subwoofer_zm", "headchopper_zm", "booze", "candy", "chalk", "sloth", "keys_zm", "buried_sq_oillamp", "buried_sq_tpo_switch", "buried_sq_ghost_lamp", "buried_sq_bt_m_tower", "buried_sq_bt_r_tower" ); + maps/mp/zm_buried_buildables::include_buildables( classicbuildables ); + maps/mp/zm_buried_buildables::init_buildables( classicbuildables ); +} + +main() +{ + flag_init( "sq_minigame_active" ); + setdvar( "player_sliding_velocity_cap", 80 ); + setdvar( "player_sliding_wishspeed", 800 ); + level.buildables_built[ "pap" ] = 1; + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "processing" ); + maps/mp/zombies/_zm_game_module::set_current_game_module( level.game_module_standard_index ); + if ( !isDefined( level.zombie_include_buildables ) ) + { + setup_buildables(); + } + level thread maps/mp/zombies/_zm_buildables::think_buildables(); + level thread maps/mp/zm_buried_power::electric_switch(); + level thread maps/mp/zm_buried_maze::maze_think(); +/# + level thread setup_temp_sloth_triggers(); + level thread generator_open_sesame(); + level thread fountain_open_sesame(); +#/ + flag_wait( "initial_blackscreen_passed" ); + level thread vo_level_start(); + level thread vo_stay_topside(); + level thread vo_fall_down_hole(); + level thread vo_find_town(); + level thread dart_game_init(); + level thread piano_init(); + level thread sliding_bookcase_init(); + level thread quick_revive_solo_watch(); + level thread zm_treasure_chest_init(); + level thread maps/mp/zm_buried_ee::init_ghost_piano(); + level thread buried_set_underground_lighting(); + exploder( 666 ); + level.zm_traversal_override = ::zm_traversal_override; + level.zm_mantle_over_40_move_speed_override = ::mantle_over_40_move_speed_override; + blockers = getentarray( "main_street_blocker", "targetname" ); + _a116 = blockers; + _k116 = getFirstArrayKey( _a116 ); + while ( isDefined( _k116 ) ) + { + blocker = _a116[ _k116 ]; + blocker disconnectpaths(); + _k116 = getNextArrayKey( _a116, _k116 ); + } + level.insta_kill_triggers = getentarray( "instant_death", "targetname" ); + array_thread( level.insta_kill_triggers, ::squashed_death_init, 0 ); + if ( isDefined( level.sloth ) ) + { + level.sloth.custom_crawler_pickup_func = ::sloth_crawler_pickup_vulture_fx_correction_func; + level.sloth.custom_box_move_func = ::sloth_box_move_show_vulture_fx; + } + maps/mp/zombies/_zm::register_player_damage_callback( ::classic_player_damage_callback ); +} + +vo_level_start() +{ + wait 5; + random( get_players() ) maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "game_start" ); +} + +vo_stay_topside() +{ + flag_wait( "start_zombie_round_logic" ); + level waittill( "between_round_over" ); + wait 4; + players_in_start_area = maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_start", 1 ); + if ( isDefined( players_in_start_area ) && players_in_start_area.size > 0 ) + { + random( players_in_start_area ) maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "stay_topside" ); + } +} + +vo_fall_down_hole() +{ + stables_roof_trigger = spawn( "trigger_radius", ( -1304, -320, 332 ), 0, 128, 128 ); + while ( 1 ) + { + stables_roof_trigger waittill( "trigger", player ); + if ( isplayer( player ) ) + { + level notify( "stables_roof_discovered" ); + level.vo_player_who_discovered_stables_roof = player; + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "fall_down_hole" ); + break; + } + else + { + wait 0,05; + } + } + while ( isDefined( player ) && isDefined( player.isspeaking ) && player.isspeaking ) + { + wait 1; + } + players_in_start_area = maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_start", 1 ); + if ( isDefined( players_in_start_area ) && players_in_start_area.size > 0 ) + { + random( players_in_start_area ) maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "fall_down_hole_response" ); + } + stables_roof_trigger delete(); +} + +vo_find_town() +{ + level waittill( "stables_roof_discovered" ); + while ( 1 ) + { + players_in_town_area = maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_street_lighteast", 1 ); + players_in_town_area = arraycombine( players_in_town_area, maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_street_lightwest", 1 ), 0, 0 ); + if ( isDefined( players_in_town_area ) && players_in_town_area.size > 0 ) + { + random( players_in_town_area ) maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "find_town" ); + return; + } + wait 2; + } +} + +generator_oil_lamp_control() +{ + lignts_on = 0; + level.generator_power_states_color = 0; + while ( 1 ) + { + wait_for_buildable( "oillamp_zm" ); + level.generator_is_active = 1; + level setclientfield( "GENERATOR_POWER_STATES_COLOR", level.generator_power_states_color ); + level setclientfield( "GENERATOR_POWER_STATES", 1 ); + level thread reset_generator_lerp_val(); + exploder( 300 ); + if ( isDefined( level.oil_lamp_power ) ) + { + oil_lamp_power = level.oil_lamp_power; + level.oil_lamp_power = undefined; + } + else + { + oil_lamp_power = 1; + } + if ( !isDefined( level.generator_buildable_full_power_time ) ) + { + level.generator_buildable_full_power_time = 300; + } + full_power_wait_time = level.generator_buildable_full_power_time * oil_lamp_power; + wait full_power_wait_time; + level setclientfield( "GENERATOR_POWER_STATES", 2 ); + level thread lerp_down_generator_light_levels( level.generator_buildable_blinkout_time ); + wait level.generator_buildable_blinkout_time; + level setclientfield( "GENERATOR_POWER_STATES", 0 ); + level.generator_power_states_color = 0; + stop_exploder( 300 ); + level notify( level.str_generator_power_runs_out_notify ); + level.generator_is_active = 0; + wait 0,01; + } +} + +reset_generator_lerp_val() +{ + wait 1; + level setclientfield( "GENERATOR_POWER_STATES_LERP", 1 ); +} + +lerp_down_generator_light_levels( blinkout_time ) +{ + wait_lights1 = blinkout_time * 0,05; + wait_delay1 = blinkout_time * 0,3; + wait_lights2 = blinkout_time * 0,1; + wait_delay2 = blinkout_time * 0,4; + wait_lights3 = blinkout_time * 0,15; + level thread lerp_generator_lights( wait_lights1, 1, 0,84 ); + level waittill( "generator_lerp_done" ); + wait wait_delay1; + level thread lerp_generator_lights( wait_lights2, 0,84, 0,4 ); + level waittill( "generator_lerp_done" ); + wait wait_delay2; + level thread lerp_generator_lights( wait_lights3, 0,4, 0 ); + level waittill( "generator_lerp_done" ); +} + +lerp_generator_lights( total_time, start_val, end_val ) +{ + start_time = getTime(); + end_time = start_time + ( total_time * 1000 ); + lerp_step = 1; + last_lerp = start_time; + while ( 1 ) + { + time = getTime(); + if ( time >= end_time ) + { + break; + } + else + { + dt = ( time - last_lerp ) / 1000; + if ( dt >= lerp_step ) + { + elapsed = time - start_time; + if ( elapsed ) + { + delta = elapsed / ( total_time * 1000 ); + val = lerpfloat( start_val, end_val, delta ); + level setclientfield( "GENERATOR_POWER_STATES_LERP", val ); + } + last_lerp = time; + } + wait 0,01; + } + } + level notify( "generator_lerp_done" ); +} + +collapsing_holes_init() +{ + trigs = getentarray( "hole_breakthrough", "targetname" ); + clientfieldnames = []; + _a398 = trigs; + _k398 = getFirstArrayKey( _a398 ); + while ( isDefined( _k398 ) ) + { + trig = _a398[ _k398 ]; + parts = getentarray( trig.target, "targetname" ); + _a401 = parts; + _k401 = getFirstArrayKey( _a401 ); + while ( isDefined( _k401 ) ) + { + part = _a401[ _k401 ]; + if ( isDefined( part.script_noteworthy ) && part.script_noteworthy == "clip" ) + { + trig.clip = part; + } + else + { + trig.boards = part; + } + _k401 = getNextArrayKey( _a401, _k401 ); + } + if ( isDefined( trig.script_string ) ) + { + clientfieldnames[ trig.script_string ] = 1; + } + _k398 = getNextArrayKey( _a398, _k398 ); + } + keys = getarraykeys( clientfieldnames ); + i = 0; + while ( i < keys.size ) + { + registerclientfield( "world", keys[ i ], 12000, 1, "int" ); + i++; + } + if ( isDefined( trigs ) ) + { + array_thread( trigs, ::collapsing_holes ); + array_thread( trigs, ::tunnel_breach ); + } +} + +collapsing_holes() +{ + self endon( "breached" ); + if ( !isDefined( self ) && !isDefined( self.boards ) ) + { + return; + } + self waittill( "trigger", who ); + if ( is_player_valid( who ) ) + { + if ( isDefined( self.script_string ) ) + { + level setclientfield( self.script_string, 1 ); + note = "none"; + if ( isDefined( self.script_noteworthy ) ) + { + note = self.script_noteworthy; + } +/# + println( "***!!!*** Set client field " + self.script_string + " Associated script_noteworthy " + note ); +#/ + } + if ( isDefined( self.boards ) ) + { + if ( isDefined( self.script_int ) ) + { + exploder( self.script_int ); + } + else + { + playfx( level._effect[ "wood_chunk_destory" ], self.boards.origin ); + } + self thread sndcollapsing(); + self.boards delete(); + if ( isDefined( self.clip ) ) + { + self.clip delete(); + } + self notify( "breached" ); + self delete(); + } + } +} + +sndcollapsing() +{ + if ( !isDefined( self.script_noteworthy ) ) + { + return; + } + if ( self.script_noteworthy == "hole_small_2" ) + { + self playsound( "zmb_floor_collapse" ); + } + else if ( self.script_noteworthy == "hole_small_1" ) + { + self playsound( "zmb_floor_collapse" ); + } + else + { + if ( self.script_noteworthy == "hole_large_1" ) + { + self playsound( "zmb_floor_collapse" ); + } + } +} + +tunnel_breach() +{ + level endon( "intermission" ); + self endon( "breached" ); + if ( !isDefined( self ) && !isDefined( self.boards ) ) + { + return; + } + self.boards.health = 99999; + self.boards setcandamage( 1 ); + self.boards.damage_state = 0; + while ( 1 ) + { + self.boards waittill( "damage", amount, attacker, direction, point, dmg_type, modelname, tagname, partname, weaponname ); + if ( isDefined( weaponname ) && weaponname != "emp_grenade_zm" || weaponname == "ray_gun_zm" && weaponname == "ray_gun_upgraded_zm" ) + { + continue; + } + if ( isDefined( amount ) && amount <= 1 ) + { + continue; + } + if ( isplayer( attacker ) && dmg_type != "MOD_PROJECTILE" && dmg_type != "MOD_PROJECTILE_SPLASH" && dmg_type != "MOD_EXPLOSIVE" && dmg_type != "MOD_EXPLOSIVE_SPLASH" || dmg_type == "MOD_GRENADE" && dmg_type == "MOD_GRENADE_SPLASH" ) + { + if ( self.boards.damage_state == 0 ) + { + self.boards.damage_state = 1; + } + if ( isDefined( self.script_int ) ) + { + exploder( self.script_int ); + } + else + { + playfx( level._effect[ "wood_chunk_destory" ], self.origin ); + } + if ( isDefined( self.script_string ) ) + { + level setclientfield( self.script_string, 1 ); + } + if ( isDefined( self.script_flag ) ) + { + flag_set( self.script_flag ); + } + if ( isDefined( self.clip ) ) + { + self.clip connectpaths(); + self.clip delete(); + } + self.boards delete(); + self notify( "breached" ); + self delete(); + return; + } + } +} + +quick_revive_solo_watch() +{ + machine_triggers = getentarray( "vending_revive", "target" ); + machine_trigger = machine_triggers[ 0 ]; + while ( 1 ) + { + level waittill_any( "solo_revive", "revive_off", "revive_hide" ); + if ( isDefined( machine_trigger.machine ) ) + { + machine_trigger.machine maps/mp/zombies/_zm_equip_headchopper::destroyheadchopperstouching(); + } + } +} + +sliding_bookcase_init() +{ + bookcase_triggers = getentarray( "zombie_sliding_bookcase", "script_noteworthy" ); + _a604 = bookcase_triggers; + _k604 = getFirstArrayKey( _a604 ); + while ( isDefined( _k604 ) ) + { + trig = _a604[ _k604 ]; + trig.doors = []; + targets = getentarray( trig.target, "targetname" ); + _a610 = targets; + _k610 = getFirstArrayKey( _a610 ); + while ( isDefined( _k610 ) ) + { + target = _a610[ _k610 ]; + target notsolid(); + if ( target.classname == "script_brushmodel" ) + { + target connectpaths(); + } + if ( target.classname == "script_model" ) + { + trig thread sliding_bookcase_wobble( target ); + } + target maps/mp/zombies/_zm_blockers::door_classify( trig ); + target.startpos = target.origin; + target.startang = target.angles; + if ( target.classname == "script_brushmodel" ) + { + target solid(); + } + _k610 = getNextArrayKey( _a610, _k610 ); + } + _k604 = getNextArrayKey( _a604, _k604 ); + } + array_thread( bookcase_triggers, ::sliding_bookcase_think ); +} + +sliding_bookcase_think() +{ + while ( 1 ) + { + self waittill( "trigger", who ); + if ( isDefined( who.bookcase_entering_callback ) ) + { + who thread [[ who.bookcase_entering_callback ]]( self.doors[ 0 ] ); + } + self playsound( "zmb_sliding_bookcase_open" ); + while ( isDefined( self.doors[ 0 ].door_moving ) || self.doors[ 0 ].door_moving && isDefined( self._door_open ) && self._door_open ) + { + continue; + } + _a657 = self.doors; + _k657 = getFirstArrayKey( _a657 ); + while ( isDefined( _k657 ) ) + { + piece = _a657[ _k657 ]; + piece thread sliding_bookcase_activate( 1 ); + _k657 = getNextArrayKey( _a657, _k657 ); + } + while ( isDefined( self.doors[ 0 ].door_moving ) || self.doors[ 0 ].door_moving && self sliding_bookcase_occupied() ) + { + wait 0,1; + } + _a667 = self.doors; + _k667 = getFirstArrayKey( _a667 ); + while ( isDefined( _k667 ) ) + { + piece = _a667[ _k667 ]; + piece thread sliding_bookcase_activate( 0 ); + _k667 = getNextArrayKey( _a667, _k667 ); + } + self._door_open = 0; + self playsound( "zmb_sliding_bookcase_close" ); + } +} + +sliding_bookcase_activate( open ) +{ + if ( !isDefined( open ) ) + { + open = 1; + } + if ( isDefined( self.door_moving ) ) + { + return; + } + self.door_moving = 1; + if ( isDefined( self.script_sound ) ) + { + if ( open ) + { + } + } + scale = 1; + speed = 15; + if ( !open ) + { + scale = -1; + speed = 13; + } + switch( self.script_string ) + { + case "move": + if ( isDefined( self.script_vector ) ) + { + vector = vectorScale( self.script_vector, scale ); + movetopos = self.origin; + if ( open ) + { + if ( isDefined( self.startpos ) ) + { + movetopos = self.startpos + vector; + } + else + { + movetopos = self.origin + vector; + } + self._door_open = 1; + } + else + { + if ( isDefined( self.startpos ) ) + { + movetopos = self.startpos; + } + else + { + movetopos = self.origin - vector; + } + self._door_open = 0; + } + dist = distance( self.origin, movetopos ); + time = dist / speed; + q_time = time * 0,25; + if ( q_time > 1 ) + { + q_time = 1; + } + self moveto( movetopos, time, q_time, q_time ); + self thread maps/mp/zombies/_zm_blockers::door_solid_thread(); + } + break; + } +} + +sliding_bookcase_occupied() +{ + is_occupied = 0; + players = get_players(); + _a772 = players; + _k772 = getFirstArrayKey( _a772 ); + while ( isDefined( _k772 ) ) + { + player = _a772[ _k772 ]; + if ( is_occupied > 0 ) + { + break; + } + else + { + if ( player istouching( self ) ) + { + is_occupied++; + } + _k772 = getNextArrayKey( _a772, _k772 ); + } + } + ghosts = getentarray( "ghost_zombie_spawner", "script_noteworthy" ); + _a786 = ghosts; + _k786 = getFirstArrayKey( _a786 ); + while ( isDefined( _k786 ) ) + { + ghost = _a786[ _k786 ]; + if ( is_occupied > 0 ) + { + break; + } + else + { + if ( ghost istouching( self ) ) + { + is_occupied++; + } + _k786 = getNextArrayKey( _a786, _k786 ); + } + } + if ( is_occupied > 0 ) + { + if ( isDefined( self.doors[ 0 ].startpos ) && self.doors[ 0 ].startpos == self.doors[ 0 ].origin ) + { + _a803 = self.doors; + _k803 = getFirstArrayKey( _a803 ); + while ( isDefined( _k803 ) ) + { + piece = _a803[ _k803 ]; + piece thread sliding_bookcase_activate( 1 ); + _k803 = getNextArrayKey( _a803, _k803 ); + } + self._door_open = 1; + } + return 1; + } + return 0; +} + +sliding_bookcase_wobble( model ) +{ + while ( 1 ) + { + if ( isDefined( self.doors[ 0 ].door_moving ) && self.doors[ 0 ].door_moving ) + { + model rotateto( ( randomfloatrange( -2,5, 2,5 ), randomfloatrange( -0,5, 0,5 ), randomfloatrange( -0,5, 0,5 ) ), 0,5, 0,125, 0,125 ); + wait ( 0,5 - 0,125 ); + continue; + } + else + { + if ( isDefined( model.startang ) && model.angles != model.startang ) + { + model rotateto( model.startang, 0,5, 0,125, 0,125 ); + model waittill( "rotatedone" ); + break; + } + else + { + wait 0,5; + } + } + } +} + +dart_game_init() +{ + dart_board = getentarray( "dart_board", "targetname" ); + if ( !isDefined( dart_board ) ) + { + return; + } + _a860 = dart_board; + _k860 = getFirstArrayKey( _a860 ); + while ( isDefined( _k860 ) ) + { + piece = _a860[ _k860 ]; + piece thread dart_game_piece_think(); + _k860 = getNextArrayKey( _a860, _k860 ); + } +} + +dart_game_piece_think() +{ + self setcandamage( 1 ); + while ( 1 ) + { + self waittill( "damage", amount, inflictor, direction, point, type, tagname, modelname, partname, weaponname, idflags ); + if ( isDefined( inflictor ) && isplayer( inflictor ) && dart_game_is_valid_weapon( weaponname ) ) + { + while ( !inflictor dart_game_is_award_valid() ) + { + continue; + } + if ( distance2dsquared( inflictor.origin, self.origin ) > 16384 ) + { + award = 0; + switch( self.script_noteworthy ) + { + case "white_ring": + award = 50; + break; + case "black_ring": + award = 25; + break; + case "bullseye": + award = 100; + break; + } + inflictor dart_game_give_award( award ); + } + } + } +} + +dart_game_is_valid_weapon( weaponname ) +{ + if ( issubstr( weaponname, "knife_ballistic_" ) ) + { + return 1; + } + return 0; +} + +dart_game_is_award_valid() +{ + if ( isDefined( self.dart_round ) && self.dart_round == level.round_number ) + { + if ( isDefined( self.dart_round_score ) && self.dart_round_score >= 200 ) + { + return 0; + } + } + else + { + self.dart_round = level.round_number; + self.dart_round_score = 0; + } + return 1; +} + +dart_game_give_award( award ) +{ + if ( ( self.dart_round_score + award ) > 200 ) + { + award = 200 - self.dart_round_score; + } + self.dart_round_score += award; + self maps/mp/zombies/_zm_score::add_to_player_score( award ); +} + +piano_init() +{ + array_thread( getentarray( "piano_key", "targetname" ), ::pianothink ); + array_thread( getentarray( "piano_damage", "targetname" ), ::pianodamagethink ); +} + +pianothink() +{ + note = self.script_noteworthy; + self usetriggerrequirelookat(); + self sethintstring( &"NULL_EMPTY" ); + self setcursorhint( "HINT_NOICON" ); + for ( ;; ) + { + self waittill( "trigger", who ); + if ( who istouching( self ) ) + { +/# + iprintlnbold( "Playing Piano Key: " + note ); +#/ + self playsound( "zmb_piano_" + note ); + } + } +} + +pianodamagethink() +{ + noise_level = array( "soft", "loud" ); + for ( ;; ) + { + self waittill( "trigger", who ); + type = random( noise_level ); + if ( isDefined( who ) && isplayer( who ) ) + { +/# + iprintlnbold( "Piano Damage: " + type ); +#/ + self playsound( "zmb_piano_damage_" + type ); + } + } +} + +zm_treasure_chest_init() +{ + done = 0; + level.maze_chests = []; + while ( isDefined( level.chests ) && !done ) + { + done = 1; + _a1009 = level.chests; + _k1009 = getFirstArrayKey( _a1009 ); + while ( isDefined( _k1009 ) ) + { + chest = _a1009[ _k1009 ]; + if ( issubstr( chest.script_noteworthy, "maze_chest" ) ) + { + done = 0; + level.maze_chests[ level.maze_chests.size ] = chest; + arrayremovevalue( level.chests, chest ); + break; + } + else + { + _k1009 = getNextArrayKey( _a1009, _k1009 ); + } + } + } + maps/mp/zombies/_zm_magicbox::init_starting_chest_location( "start_chest" ); + trig = getent( "maze_box_trigger", "targetname" ); + if ( isDefined( trig ) ) + { + trig waittill( "trigger", who ); + if ( is_player_valid( who ) ) + { + while ( isDefined( level.maze_chests ) && level.maze_chests.size > 0 ) + { + i = 0; + while ( i < level.maze_chests.size ) + { + level.chests[ level.chests.size ] = level.maze_chests[ i ]; + i++; + } + } + trig delete(); + } + } +} + +generator_open_sesame() +{ +/# + while ( 1 ) + { + level waittill_any( "open_sesame", "generator_lights_on" ); + level.oil_lamp_power = 60; +#/ + } +} + +fountain_open_sesame() +{ +/# + level waittill( "open_sesame" ); + level notify( "courtyard_fountain_open" ); + level notify( "_destroy_maze_fountain" ); +#/ +} + +setup_temp_sloth_triggers() +{ +/# + sloth_triggers = getentarray( "sloth_barricade", "targetname" ); + _a1073 = sloth_triggers; + _k1073 = getFirstArrayKey( _a1073 ); + while ( isDefined( _k1073 ) ) + { + trigger = _a1073[ _k1073 ]; + trigger thread watch_opensesame(); + _k1073 = getNextArrayKey( _a1073, _k1073 ); + } + level waittill_any( "open_sesame", "open_sloth_barricades" ); + level notify( "jail_barricade_down" ); +#/ +} + +watch_opensesame() +{ +/# + self endon( "death" ); + script_flag = self.script_flag; + target = self.target; + level waittill_any( "open_sesame", "open_sloth_barricades" ); + self open_barricade( script_flag, target ); +#/ +} + +open_barricade( script_flag, target ) +{ +/# + if ( isDefined( script_flag ) && level flag_exists( script_flag ) ) + { + flag_set( script_flag ); + } + while ( isDefined( target ) ) + { + barricades = getentarray( target, "targetname" ); + while ( isDefined( barricades ) && barricades.size ) + { + _a1103 = barricades; + _k1103 = getFirstArrayKey( _a1103 ); + while ( isDefined( _k1103 ) ) + { + barricade = _a1103[ _k1103 ]; + if ( isDefined( self.func_no_delete ) ) + { + barricade [[ self.func_no_delete ]](); + } + else + { + barricade delete(); + } + _k1103 = getNextArrayKey( _a1103, _k1103 ); + } + } + } + if ( isDefined( self.func_no_delete ) ) + { + self [[ self.func_no_delete ]](); + } + else + { + self delete(); +#/ + } +} + +perk_vulture_custom_scripts() +{ +} + +zm_traversal_override( traversealias ) +{ + self.no_restart = 0; + if ( is_true( self.is_sloth ) ) + { + node = self getnegotiationstartnode(); + if ( isDefined( node ) ) + { + if ( isDefined( self.buildable_model ) ) + { + if ( isDefined( node.script_parameters ) ) + { + return node.script_parameters; + } + } + if ( isDefined( node.script_string ) ) + { + return node.script_string; + } + } + } + return traversealias; +} + +mantle_over_40_move_speed_override() +{ + traversealias = "barrier_walk"; + if ( is_true( self.is_sloth ) ) + { + return traversealias; + } + switch( self.zombie_move_speed ) + { + case "run_floating": + traversealias = "barrier_run_floating"; + break; + case "walk_floating": + traversealias = "barrier_walk_floating"; + break; + default: +/# + assertmsg( "Zombie move speed of '" + self.zombie_move_speed + "' is not supported for mantle_over_40." ); +#/ + } + return traversealias; +} + +hide_boxes_for_minigame() +{ + if ( isDefined( level.chests ) && isDefined( level.chest_index ) ) + { + chest = level.chests[ level.chest_index ]; + if ( !isDefined( chest ) ) + { + return; + } + if ( isDefined( chest.unitrigger_stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( chest.unitrigger_stub ); + } + if ( isDefined( chest.pandora_light ) ) + { + chest.pandora_light delete(); + } + chest.hidden = 1; + if ( isDefined( chest.zbarrier ) ) + { + i = 0; + while ( i < chest.zbarrier getnumzbarrierpieces() ) + { + chest.zbarrier hidezbarrierpiece( i ); + i++; + } + chest.zbarrier notify( "zbarrier_state_change" ); + chest.zbarrier maps/mp/zombies/_zm_perk_vulture::vulture_perk_shows_mystery_box( 0 ); + } + } + level.disable_firesale_drop = 1; +} + +unhide_boxes_for_minigame() +{ + chest = level.chests[ level.chest_index ]; + if ( !isDefined( chest ) ) + { + return; + } + chest thread [[ level.pandora_fx_func ]](); + chest.zbarrier maps/mp/zombies/_zm_magicbox::set_magic_box_zbarrier_state( "initial" ); + chest.zbarrier maps/mp/zombies/_zm_perk_vulture::vulture_perk_shows_mystery_box( 1 ); + level.disable_firesale_drop = 0; +} + +store_worldstate_for_minigame() +{ + flag_set( "sq_minigame_active" ); + if ( isDefined( level._world_state_stored_for_minigame ) ) + { +/# + assertmsg( "store_worldstate_for_minigame called more than once." ); +#/ + return; + } + flag_set( "time_bomb_stores_door_state" ); + level._world_state_stored_for_minigame = spawnstruct(); + maps/mp/zombies/_zm_weap_time_bomb::_time_bomb_saves_data( 0, level._world_state_stored_for_minigame ); + give_default_minigame_loadout(); + onplayerconnect_callback( ::give_player_minigame_loadout_wrapper ); +} + +restore_worldstate_for_minigame() +{ + if ( !isDefined( level._world_state_stored_for_minigame ) ) + { +/# + assertmsg( "restore_worldstate_for_minigame called with no prior call to store_worldstate_for_minigame." ); +#/ + return; + } + level.timebomb_override_struct = level._world_state_stored_for_minigame; + level.round_spawn_func = ::maps/mp/zombies/_zm::round_spawning; + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_restores_saved_data( 0, level._world_state_stored_for_minigame ); + level thread delay_destroy_timebomb_override_structs(); + blockers = getentarray( "main_street_blocker", "targetname" ); + _a1280 = blockers; + _k1280 = getFirstArrayKey( _a1280 ); + while ( isDefined( _k1280 ) ) + { + blocker = _a1280[ _k1280 ]; + blocker.origin += vectorScale( ( 0, 0, -1 ), 360 ); + blocker disconnectpaths(); + _k1280 = getNextArrayKey( _a1280, _k1280 ); + } + unhide_boxes_for_minigame(); + level setclientfield( "GENERATOR_POWER_STATES", 0 ); + flag_clear( "sq_minigame_active" ); + level notify( "sq_boss_battle_complete" ); +} + +delay_destroy_timebomb_override_structs() +{ + wait 3; + flag_clear( "time_bomb_stores_door_state" ); + level._world_state_stored_for_minigame = undefined; + level.timebomb_override_struct = undefined; +} + +give_default_minigame_loadout() +{ + players = get_players(); + _a1307 = players; + _k1307 = getFirstArrayKey( _a1307 ); + while ( isDefined( _k1307 ) ) + { + player = _a1307[ _k1307 ]; + player give_player_minigame_loadout(); + _k1307 = getNextArrayKey( _a1307, _k1307 ); + } +} + +give_player_minigame_loadout_wrapper() +{ + if ( flag( "sq_minigame_active" ) ) + { + self give_player_minigame_loadout(); + } +} + +give_player_minigame_loadout() +{ + self.dontspeak = 1; + self takeallweapons(); + self maps/mp/zombies/_zm_weapons::weapon_give( "ak74u_zm", 0 ); + self give_start_weapon( 0 ); + self giveweapon( "knife_zm" ); + if ( self hasweapon( self get_player_lethal_grenade() ) ) + { + self getweaponammoclip( self get_player_lethal_grenade() ); + } + else + { + self giveweapon( self get_player_lethal_grenade() ); + } + self setweaponammoclip( self get_player_lethal_grenade(), 2 ); + a_current_perks = self getperks(); + _a1345 = a_current_perks; + _k1345 = getFirstArrayKey( _a1345 ); + while ( isDefined( _k1345 ) ) + { + perk = _a1345[ _k1345 ]; + self notify( perk + "_stop" ); + _k1345 = getNextArrayKey( _a1345, _k1345 ); + } + self.dontspeak = undefined; +} + +minigame_blockers_disable() +{ + a_clip_brushes_full = get_minigame_clip_brushes(); + _a1366 = a_clip_brushes_full; + _k1366 = getFirstArrayKey( _a1366 ); + while ( isDefined( _k1366 ) ) + { + clip_ai = _a1366[ _k1366 ]; + clip_ai notsolid(); + clip_ai connectpaths(); + _k1366 = getNextArrayKey( _a1366, _k1366 ); + } + a_models = get_minigame_blocker_models(); + _a1383 = a_models; + _k1383 = getFirstArrayKey( _a1383 ); + while ( isDefined( _k1383 ) ) + { + model = _a1383[ _k1383 ]; + model thread blocker_model_remove(); + _k1383 = getNextArrayKey( _a1383, _k1383 ); + } + toggle_doors_along_richtofen_street( 0 ); + toggle_door_triggers( 1 ); + a_sloth_barriers = get_minigame_sloth_barriers(); + _a1396 = a_sloth_barriers; + _k1396 = getFirstArrayKey( _a1396 ); + while ( isDefined( _k1396 ) ) + { + barrier = _a1396[ _k1396 ]; + while ( isDefined( barrier.target ) ) + { + a_pieces = getentarray( barrier.target, "targetname" ); + _a1401 = a_pieces; + _k1401 = getFirstArrayKey( _a1401 ); + while ( isDefined( _k1401 ) ) + { + piece = _a1401[ _k1401 ]; + if ( isDefined( piece.is_hidden ) && !piece.is_hidden ) + { + piece maps/mp/zombies/_zm_ai_sloth::hide_sloth_barrier(); + } + _k1401 = getNextArrayKey( _a1401, _k1401 ); + } + } + if ( isDefined( barrier.is_hidden ) && !barrier.is_hidden ) + { + barrier maps/mp/zombies/_zm_ai_sloth::hide_sloth_barrier(); + } + _k1396 = getNextArrayKey( _a1396, _k1396 ); + } +} + +minigame_blockers_enable() +{ + a_clip_brushes_full = get_minigame_clip_brushes(); + _a1429 = a_clip_brushes_full; + _k1429 = getFirstArrayKey( _a1429 ); + while ( isDefined( _k1429 ) ) + { + clip_ai = _a1429[ _k1429 ]; + clip_ai solid(); + clip_ai disconnectpaths(); + _k1429 = getNextArrayKey( _a1429, _k1429 ); + } + a_structs = get_minigame_blocker_structs(); + _a1445 = a_structs; + _k1445 = getFirstArrayKey( _a1445 ); + while ( isDefined( _k1445 ) ) + { + struct = _a1445[ _k1445 ]; + struct thread blocker_model_promote(); + _k1445 = getNextArrayKey( _a1445, _k1445 ); + } + toggle_doors_along_richtofen_street( 1 ); + toggle_door_triggers( 0 ); + a_sloth_barriers = get_minigame_sloth_barriers(); + _a1458 = a_sloth_barriers; + _k1458 = getFirstArrayKey( _a1458 ); + while ( isDefined( _k1458 ) ) + { + barrier = _a1458[ _k1458 ]; + while ( isDefined( barrier.target ) ) + { + a_pieces = getentarray( barrier.target, "targetname" ); + _a1463 = a_pieces; + _k1463 = getFirstArrayKey( _a1463 ); + while ( isDefined( _k1463 ) ) + { + piece = _a1463[ _k1463 ]; + if ( isDefined( piece.is_hidden ) && piece.is_hidden ) + { + piece maps/mp/zombies/_zm_ai_sloth::unhide_sloth_barrier(); + } + _k1463 = getNextArrayKey( _a1463, _k1463 ); + } + } + if ( isDefined( barrier.is_hidden ) && barrier.is_hidden ) + { + barrier maps/mp/zombies/_zm_ai_sloth::unhide_sloth_barrier(); + } + _k1458 = getNextArrayKey( _a1458, _k1458 ); + } +} + +get_minigame_sloth_barriers() +{ + a_barriers_filtered = []; + while ( flag_exists( "sq_minigame_active" ) && flag( "sq_minigame_active" ) ) + { + a_sloth_barriers = getentarray( "sloth_barricade", "targetname" ); + if ( flag( "richtofen_minigame_active" ) || flag( "richtofen_game_complete" ) ) + { + a_blocked_barrier_list = array( "jail" ); + } + else + { + a_blocked_barrier_list = []; + } + i = 0; + while ( i < a_sloth_barriers.size ) + { + if ( isDefined( a_sloth_barriers[ i ].script_location ) && isinarray( a_blocked_barrier_list, a_sloth_barriers[ i ].script_location ) ) + { + a_barriers_filtered[ a_barriers_filtered.size ] = a_sloth_barriers[ i ]; + } + i++; + } + } + return a_barriers_filtered; +} + +get_minigame_blocker_structs() +{ + if ( flag_exists( "sq_minigame_active" ) && flag( "sq_minigame_active" ) ) + { + if ( flag( "richtofen_minigame_active" ) || flag( "richtofen_game_complete" ) ) + { + a_structs = getstructarray( "minigame_richtofen_blocker", "targetname" ); + } + else + { + a_structs = getstructarray( "minigame_maxis_blocker", "script_noteworthy" ); + } + } + else + { + a_structs = getstructarray( "minigame_richtofen_blocker", "targetname" ); + a_structs = arraycombine( a_structs, getstructarray( "minigame_maxis_blocker", "script_noteworthy" ), 0, 0 ); + } + return a_structs; +} + +get_minigame_blocker_models() +{ + if ( flag_exists( "sq_minigame_active" ) && flag( "sq_minigame_active" ) ) + { + if ( flag( "richtofen_minigame_active" ) || flag( "richtofen_game_complete" ) ) + { + a_models = getentarray( "minigame_richtofen_blocker", "targetname" ); + } + else + { + a_models = getentarray( "minigame_maxis_blocker", "script_noteworthy" ); + } + } + else + { + a_models = getentarray( "minigame_richtofen_blocker", "targetname" ); + a_models = arraycombine( a_models, getentarray( "minigame_maxis_blocker", "script_noteworthy" ), 0, 0 ); + } + return a_models; +} + +get_minigame_clip_brushes( str_name_append ) +{ + if ( flag_exists( "sq_minigame_active" ) && flag( "sq_minigame_active" ) ) + { + if ( flag( "richtofen_minigame_active" ) || flag( "richtofen_game_complete" ) ) + { + str_name = "minigame_richtofen_clip"; + str_key = "targetname"; + } + else + { + str_name = "minigame_maxis_clip"; + str_key = "script_noteworthy"; + } + a_clip = getentarray( _append_name( str_name, str_name_append ), str_key ); + } + else + { + a_clip = getentarray( _append_name( "minigame_richtofen_clip", str_name_append ), "targetname" ); + a_clip = arraycombine( a_clip, getentarray( _append_name( "minigame_maxis_clip", str_name_append ), "script_noteworthy" ), 0, 0 ); + } + return a_clip; +} + +_append_name( str_name, str_name_append ) +{ + if ( isDefined( str_name_append ) ) + { + str_name = ( str_name + "_" ) + str_name_append; + } + return str_name; +} + +blocker_model_promote() +{ +/# + assert( isDefined( self.model ), "model not set for minigame blocker at " + self.origin ); +#/ + m_blocker = spawn( "script_model", self.origin + vectorScale( ( 0, 0, -1 ), 100 ) ); + if ( !isDefined( self.angles ) ) + { + self.angles = ( 0, 0, -1 ); + } + m_blocker.angles = self.angles; + m_blocker setmodel( self.model ); + m_blocker.targetname = self.targetname; + m_blocker.script_noteworthy = self.script_noteworthy; + m_blocker movez( 100, 5, 0,5, 0,5 ); + earthquake( 0,3, 5, self.origin + vectorScale( ( 0, 0, -1 ), 100 ), 128 ); +} + +blocker_model_remove() +{ + earthquake( 0,3, 5, self.origin + vectorScale( ( 0, 0, -1 ), 100 ), 128 ); + self movez( -100, 5, 0,5, 0,5 ); + self waittill( "movedone" ); + if ( isDefined( self ) ) + { + self delete(); + } +} + +toggle_doors_along_richtofen_street( b_should_close ) +{ + if ( !isDefined( b_should_close ) ) + { + b_should_close = 1; + } + a_door_names = array( "general_store_door1" ); + a_doors = getentarray( "zombie_door", "targetname" ); + i = 0; + while ( i < a_door_names.size ) + { + j = 0; + while ( j < a_doors.size ) + { + if ( isDefined( a_doors[ j ].script_flag ) && a_doors[ j ].script_flag == a_door_names[ i ] ) + { + if ( b_should_close ) + { + a_doors[ j ] thread close_open_door(); + j++; + continue; + } + else + { + a_doors[ j ] thread open_closed_door(); + } + } + j++; + } + i++; + } +} + +close_open_door() +{ + if ( isDefined( self._door_open ) || self._door_open && isDefined( self.has_been_opened ) && self.has_been_opened ) + { + if ( isDefined( self.is_moving ) && self.is_moving ) + { + self waittill_either( "movedone", "rotatedone" ); + } + i = 0; + while ( i < self.doors.size ) + { + if ( isDefined( self.doors[ i ].og_angles ) ) + { + self.doors[ i ].saved_angles = self.doors[ i ].angles; + if ( isDefined( self.doors[ i ].script_string ) && self.doors[ i ].script_string == "rotate" ) + { + self.doors[ i ] rotateto( self.doors[ i ].og_angles, 0,05, 0, 0 ); + } + self.doors[ i ] solid(); + self.doors[ i ] disconnectpaths(); + self.doors[ i ].closed_by_minigame = 1; + } + i++; + } + self._door_open = 0; + self.has_been_opened = 0; + self.closed_by_minigame = 1; + } +} + +open_closed_door( bignoreminigameflag ) +{ + if ( !isDefined( bignoreminigameflag ) ) + { + bignoreminigameflag = 0; + } + if ( bignoreminigameflag || isDefined( self.closed_by_minigame ) && self.closed_by_minigame ) + { + if ( isDefined( self.is_moving ) && self.is_moving ) + { + self waittill_either( "movedone", "rotatedone" ); + } + i = 0; + while ( i < self.doors.size ) + { + if ( bignoreminigameflag || isDefined( self.doors[ i ].closed_by_minigame ) && self.doors[ i ].closed_by_minigame ) + { + if ( isDefined( self.doors[ i ].script_string ) && self.doors[ i ].script_string == "rotate" ) + { + self.doors[ i ] rotateto( self.doors[ i ].script_angles, 1, 0, 0 ); + } + self.doors[ i ] connectpaths(); + self.doors[ i ] notsolid(); + self.doors[ i ].closed_by_minigame = undefined; + self.doors[ i ].saved_angles = undefined; + } + i++; + } + self.closed_by_minigame = undefined; + self._door_open = 1; + self.has_been_opened = 1; + } +} + +toggle_door_triggers( b_allow_use ) +{ + if ( !isDefined( b_allow_use ) ) + { + b_allow_use = 1; + } + a_triggers = getentarray( "zombie_door", "targetname" ); + i = 0; + while ( i < a_triggers.size ) + { + if ( b_allow_use ) + { + if ( isDefined( a_triggers[ i ].minigame_disabled ) && a_triggers[ i ].minigame_disabled ) + { + a_triggers[ i ] trigger_on(); + a_triggers[ i ].minigame_disabled = undefined; + } + i++; + continue; + } + else + { + a_triggers[ i ] trigger_off(); + a_triggers[ i ].minigame_disabled = 1; + } + i++; + } +} + +minigame_blockers_precache() +{ + a_structs = get_minigame_blocker_structs(); + _a1743 = a_structs; + _k1743 = getFirstArrayKey( _a1743 ); + while ( isDefined( _k1743 ) ) + { + struct = _a1743[ _k1743 ]; +/# + assert( isDefined( struct.model ), "blocker struct is missing model at " + struct.origin ); +#/ + precachemodel( struct.model ); + _k1743 = getNextArrayKey( _a1743, _k1743 ); + } +} + +buried_set_start_area_lighting() +{ + if ( isDefined( self.underground_lighting ) ) + { + self setclientfieldtoplayer( "clientfield_underground_lighting", 0 ); + } + self.underground_lighting = undefined; +} + +squashed_death_init( kill_if_falling ) +{ + while ( 1 ) + { + self waittill( "trigger", who ); + if ( isDefined( who.insta_killed ) && !who.insta_killed ) + { + if ( isplayer( who ) ) + { + who thread insta_kill_player( 1, kill_if_falling ); + break; + } + else + { + if ( isai( who ) ) + { + who dodamage( who.health + 100, who.origin ); + who.insta_killed = 1; + if ( isDefined( who.has_been_damaged_by_player ) && !who.has_been_damaged_by_player ) + { + level.zombie_total++; + } + } + } + } + } +} + +classic_player_damage_callback( e_inflictor, e_attacker, n_damage, n_dflags, str_means_of_death, str_weapon, v_point, v_dir, str_hit_loc, psoffsettime, b_damage_from_underneath, n_model_index, str_part_name ) +{ + if ( isDefined( self.is_in_fountain_transport_trigger ) && self.is_in_fountain_transport_trigger && str_means_of_death == "MOD_FALLING" ) + { + return 0; + } + return n_damage; +} + +insta_kill_player( perks_can_respawn_player, kill_if_falling ) +{ + self endon( "disconnect" ); + if ( isDefined( self.is_in_fountain_transport_trigger ) && self.is_in_fountain_transport_trigger ) + { + return; + } + if ( isDefined( perks_can_respawn_player ) && perks_can_respawn_player == 0 ) + { + if ( self hasperk( "specialty_quickrevive" ) ) + { + self unsetperk( "specialty_quickrevive" ); + } + if ( self hasperk( "specialty_finalstand" ) ) + { + self unsetperk( "specialty_finalstand" ); + } + } + self maps/mp/zombies/_zm_buildables::player_return_piece_to_original_spawn(); + if ( isDefined( self.insta_killed ) && self.insta_killed ) + { + return; + } + if ( isDefined( self.ignore_insta_kill ) ) + { + self.disable_chugabud_corpse = 1; + return; + } + if ( self hasperk( "specialty_finalstand" ) ) + { + self.ignore_insta_kill = 1; + self.disable_chugabud_corpse = 1; + self dodamage( self.health + 1000, ( 0, 0, -1 ) ); + return; + } + if ( is_player_killable( self ) ) + { + self.insta_killed = 1; + in_last_stand = 0; + self notify( "chugabud_effects_cleanup" ); + 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; + found_node = get_insta_kill_spawn_point_from_nodes( self.origin, 400, 2000, 1000, 1 ); + if ( isDefined( found_node ) && found_node ) + { + v_point = level.chugabud_spawn_struct.origin; + v_angles = self.angles; + } + else + { + spawn_points = maps/mp/gametypes_zm/_zm_gametype::get_player_spawns_for_gametype(); + v_point = spawn_points[ 0 ].origin; + v_angles = spawn_points[ 0 ].angles; + } + if ( in_last_stand == 0 ) + { + self dodamage( self.health + 1000, ( 0, 0, -1 ) ); + } + wait 0,5; + self freezecontrols( 1 ); + wait 0,25; + self setorigin( v_point + vectorScale( ( 0, 0, -1 ), 20 ) ); + self.angles = v_angles; + if ( in_last_stand ) + { + flag_set( "instant_revive" ); + self.stopflashingbadlytime = getTime() + 1000; + 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, 0, -1 ) ); + } + } + else + { + self dodamage( self.health + 1000, ( 0, 0, -1 ) ); + wait_network_frame(); + self.bleedout_time = 0; + } + self.insta_killed = 0; + } +} + +get_insta_kill_spawn_point_from_nodes( v_origin, min_radius, max_radius, max_height, ignore_targetted_nodes ) +{ + if ( !isDefined( level.chugabud_spawn_struct ) ) + { + level.chugabud_spawn_struct = spawnstruct(); + } + found_node = undefined; + a_nodes = getnodesinradiussorted( v_origin, max_radius, min_radius, max_height, "pathnodes" ); + while ( isDefined( a_nodes ) && a_nodes.size > 0 ) + { + a_player_volumes = getentarray( "player_volume", "script_noteworthy" ); + index = a_nodes.size - 1; + i = index; + while ( i >= 0 ) + { + n_node = a_nodes[ i ]; + if ( ignore_targetted_nodes == 1 ) + { + if ( isDefined( n_node.target ) ) + { + i--; + continue; + } + } + else + { + if ( !positionwouldtelefrag( n_node.origin ) ) + { + if ( maps/mp/zombies/_zm_utility::check_point_in_enabled_zone( n_node.origin, 1, a_player_volumes ) ) + { + v_start = ( n_node.origin[ 0 ], n_node.origin[ 1 ], n_node.origin[ 2 ] + 30 ); + v_end = ( n_node.origin[ 0 ], n_node.origin[ 1 ], n_node.origin[ 2 ] - 30 ); + trace = bullettrace( v_start, v_end, 0, undefined ); + if ( trace[ "fraction" ] < 1 ) + { + override_abort = 0; + if ( isDefined( level._chugabud_reject_node_override_func ) ) + { + override_abort = [[ level._chugabud_reject_node_override_func ]]( v_origin, n_node ); + } + if ( !override_abort ) + { + found_node = n_node; + break; + } + } + } + } + } + else + { + i--; + + } + } + } + if ( isDefined( found_node ) ) + { + level.chugabud_spawn_struct.origin = found_node.origin; + v_dir = vectornormalize( v_origin - level.chugabud_spawn_struct.origin ); + level.chugabud_spawn_struct.angles = vectorToAngle( v_dir ); + return 1; + } + return 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( self.intermission ) && self.intermission ) + { + return 0; + } + if ( isDefined( checkignoremeflag ) && player.ignoreme ) + { + return 0; + } + return 1; +} + +buried_set_underground_lighting() +{ + e_info_volume = getent( "flashlight_found_info_volume", "targetname" ); + while ( 1 ) + { + a_players = getplayers(); + while ( isDefined( a_players ) ) + { + i = 0; + while ( i < a_players.size ) + { + player = a_players[ i ]; + if ( !isDefined( player.underground_lighting ) ) + { + if ( player istouching( e_info_volume ) ) + { + player setclientfieldtoplayer( "clientfield_underground_lighting", 1 ); + player.underground_lighting = 1; + } + } + i++; + } + } + wait 0,1; + } +} + +lsat_trigger_tweak() +{ + flag_wait_any( "start_zombie_round_logic", "start_encounters_match_logic" ); + wait 0,25; + candidate_list = []; + _a2138 = level.zones; + _k2138 = getFirstArrayKey( _a2138 ); + while ( isDefined( _k2138 ) ) + { + zone = _a2138[ _k2138 ]; + if ( isDefined( zone.unitrigger_stubs ) ) + { + candidate_list = arraycombine( candidate_list, zone.unitrigger_stubs, 1, 0 ); + } + _k2138 = getNextArrayKey( _a2138, _k2138 ); + } + _a2147 = candidate_list; + _k2147 = getFirstArrayKey( _a2147 ); + while ( isDefined( _k2147 ) ) + { + stub = _a2147[ _k2147 ]; + if ( isDefined( stub.weapon_upgrade ) && stub.weapon_upgrade == "lsat_zm" ) + { + stub thread hide_wallbuy(); + } + _k2147 = getNextArrayKey( _a2147, _k2147 ); + } +} + +hide_wallbuy() +{ + level waittill( "lsat_purchased" ); + if ( isDefined( level.catwalk_collapsed ) && level.catwalk_collapsed ) + { + return; + } + maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self ); + wait 5; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self, ::weapon_spawn_think ); +} + +sloth_crawler_pickup_vulture_fx_correction_func() +{ + if ( isDefined( self.is_stink_zombie ) && self.is_stink_zombie && isDefined( self.stink_ent ) ) + { + self maps/mp/zombies/_zm_perk_vulture::vulture_clientfield_actor_clear( "vulture_stink_trail_fx" ); + e_temp = self.stink_ent; + e_temp.origin = self.origin + vectorScale( ( 0, 0, -1 ), 10000 ); + wait_network_frame(); + e_temp maps/mp/zombies/_zm_perk_vulture::vulture_clientfield_scriptmover_set( "vulture_stink_fx" ); + wait_network_frame(); + e_temp.origin = self gettagorigin( "J_SpineLower" ); + e_temp linkto( self, "J_SpineLower" ); + while ( isalive( self ) ) + { + wait_network_frame(); + } + e_temp unlink(); + e_temp maps/mp/zombies/_zm_perk_vulture::vulture_clientfield_scriptmover_clear( "vulture_stink_fx" ); + } +} + +sloth_box_move_show_vulture_fx( b_show_fx ) +{ + if ( isDefined( level.chests ) && level.chests.size > 0 && isDefined( level.chest_index ) ) + { + level.chests[ level.chest_index ].zbarrier maps/mp/zombies/_zm_perk_vulture::vulture_perk_shows_mystery_box( b_show_fx ); + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_distance_tracking.gsc b/zm_buried_patch/maps/mp/zm_buried_distance_tracking.gsc new file mode 100644 index 0000000..3efd402 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_distance_tracking.gsc @@ -0,0 +1,428 @@ +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_zonemgr; +#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 = 1600; + } + if ( !isDefined( level.zombie_tracking_high ) ) + { + level.zombie_tracking_high = 600; + } + if ( !isDefined( level.zombie_tracking_wait ) ) + { + level.zombie_tracking_wait = 0,4; + } + 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 && isDefined( zombies[ i ].ignoreall ) && !zombies[ i ].ignoreall ) + { + zombies[ i ] thread delete_zombie_noone_looking( level.zombie_tracking_dist, level.zombie_tracking_high ); + } + i++; + } + wait level.zombie_tracking_wait; + } +} + +delete_zombie_noone_looking( how_close, how_high ) +{ + self endon( "death" ); + if ( self can_be_deleted_from_buried_special_zones() ) + { + self.inview = 0; + self.player_close = 0; + } + else + { + if ( !isDefined( how_close ) ) + { + how_close = 1000; + } + if ( !isDefined( how_high ) ) + { + how_high = 500; + } + if ( isDefined( self.has_legs ) && !self.has_legs ) + { + how_close *= 1,5; + } + distance_squared_check = how_close * how_close; + height_squared_check = how_high * how_high; + 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(); + _a98 = players; + _k98 = getFirstArrayKey( _a98 ); + while ( isDefined( _k98 ) ) + { + player = _a98[ _k98 ]; + if ( player.sessionstate == "spectator" ) + { + } + else if ( isDefined( player.laststand ) && player.laststand && isDefined( self.favoriteenemy ) && self.favoriteenemy == player ) + { + if ( !self can_zombie_see_any_player() ) + { + self.favoriteenemy = undefined; + self.zombie_path_bad = 1; + self thread escaped_zombies_cleanup(); + } + } + if ( isDefined( level.only_track_targeted_players ) ) + { + if ( !isDefined( self.favoriteenemy ) || self.favoriteenemy != player ) + { + } + } + else + { + can_be_seen = self player_can_see_me( player ); + distance_squared = distancesquared( self.origin, player.origin ); + if ( can_be_seen && distance_squared < too_far_dist ) + { + self.inview++; + } + if ( distance_squared < distance_squared_check && abs( self.origin[ 2 ] - player.origin[ 2 ] ) < how_high ) + { + self.player_close++; + } + } + _k98 = getNextArrayKey( _a98, _k98 ); + } + } + 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; + } + zombies = getaiarray( "axis" ); + 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" ); + if ( isDefined( self.anchor ) ) + { + self.anchor 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; +} + +can_be_deleted_from_buried_special_zones() +{ + if ( self can_be_deleted_from_start_area() ) + { + return 1; + } + if ( self can_be_deleted_from_maze_area() ) + { + return 1; + } + return 0; +} + +can_be_deleted_from_start_area() +{ + start_zones = []; + start_zones[ start_zones.size ] = "zone_start"; + start_zones[ start_zones.size ] = "zone_start_lower"; + return self can_be_deleted_from_area( start_zones ); +} + +can_be_deleted_from_maze_area() +{ + maze_zones = []; + maze_zones[ maze_zones.size ] = "zone_mansion_backyard"; + maze_zones[ maze_zones.size ] = "zone_maze"; + maze_zones[ maze_zones.size ] = "zone_maze_staircase"; + return self can_be_deleted_from_area( maze_zones ); +} + +can_be_deleted_from_area( zone_names ) +{ + self_in_zone = 0; + _a265 = zone_names; + _k265 = getFirstArrayKey( _a265 ); + while ( isDefined( _k265 ) ) + { + zone_name = _a265[ _k265 ]; + if ( isDefined( level.zones[ zone_name ] ) && isDefined( level.zones[ zone_name ].is_occupied ) && level.zones[ zone_name ].is_occupied ) + { + return 0; + } + if ( !self_in_zone && self maps/mp/zombies/_zm_zonemgr::entity_in_zone( zone_name ) ) + { + self_in_zone = 1; + } + _k265 = getNextArrayKey( _a265, _k265 ); + } + if ( self_in_zone ) + { + return 1; + } + return 0; +} + +escaped_zombies_cleanup_init() +{ + self endon( "death" ); + self.zombie_path_bad = 0; + while ( 1 ) + { + if ( !self.zombie_path_bad ) + { + self waittill( "bad_path" ); + } + found_player = undefined; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( is_player_valid( players[ i ] ) && !is_true( players[ i ].is_in_ghost_zone ) && self maymovetopoint( players[ i ].origin, 1 ) ) + { + self.favoriteenemy = players[ i ]; + found_player = 1; + i++; + continue; + } + i++; + } + n_delete_distance = 800; + n_delete_height = 300; + if ( !isDefined( found_player ) && isDefined( self.completed_emerging_into_playable_area ) && self.completed_emerging_into_playable_area ) + { + self thread delete_zombie_noone_looking( n_delete_distance, n_delete_height ); + self.zombie_path_bad = 1; + self escaped_zombies_cleanup(); + } + wait 0,1; + } +} + +escaped_zombies_cleanup() +{ + self endon( "death" ); + s_escape = self get_escape_position(); + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + if ( isDefined( s_escape ) ) + { + self setgoalpos( s_escape.origin ); + self thread check_player_available(); + self waittill_any( "goal", "reaquire_player" ); + } + self.zombie_path_bad = !can_zombie_path_to_any_player(); + wait 0,1; + if ( !self.zombie_path_bad ) + { + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); + } +} + +get_escape_position() +{ + self endon( "death" ); + str_zone = get_current_zone(); + if ( isDefined( str_zone ) ) + { + a_zones = get_adjacencies_to_zone( str_zone ); + a_dog_locations = get_dog_locations_in_zones( a_zones ); + s_farthest = self get_farthest_dog_location( a_dog_locations ); + } + return s_farthest; +} + +check_player_available() +{ + self notify( "_check_player_available" ); + self endon( "_check_player_available" ); + self endon( "death" ); + self endon( "goal" ); + while ( self.zombie_path_bad ) + { + if ( self can_zombie_see_any_player() ) + { + self notify( "reaquire_player" ); + return; + } + wait randomfloatrange( 0,2, 0,5 ); + } + self notify( "reaquire_player" ); +} + +can_zombie_path_to_any_player() +{ + a_players = get_players(); + i = 0; + while ( i < a_players.size ) + { + if ( !is_player_valid( a_players[ i ] ) ) + { + i++; + continue; + } + else if ( is_true( a_players[ i ].is_in_ghost_zone ) ) + { + i++; + continue; + } + else + { + if ( findpath( self.origin, a_players[ i ].origin ) ) + { + return 1; + } + } + i++; + } + return 0; +} + +can_zombie_see_any_player() +{ + a_players = get_players(); + i = 0; + while ( i < a_players.size ) + { + if ( !is_player_valid( a_players[ i ] ) ) + { + i++; + continue; + } + else + { + path_length = 0; + if ( !is_true( a_players[ i ].is_in_ghost_zone ) ) + { + path_length = self calcpathlength( a_players[ i ].origin ); + } + if ( self maymovetopoint( a_players[ i ].origin, 1 ) || path_length != 0 ) + { + return 1; + } + } + i++; + } + return 0; +} + +get_adjacencies_to_zone( str_zone ) +{ + a_adjacencies = []; + a_adjacencies[ 0 ] = str_zone; + a_adjacent_zones = getarraykeys( level.zones[ str_zone ].adjacent_zones ); + i = 0; + while ( i < a_adjacent_zones.size ) + { + if ( level.zones[ str_zone ].adjacent_zones[ a_adjacent_zones[ i ] ].is_connected ) + { + a_adjacencies[ a_adjacencies.size ] = a_adjacent_zones[ i ]; + } + i++; + } + return a_adjacencies; +} + +get_dog_locations_in_zones( a_zones ) +{ + a_dog_locations = []; + _a479 = a_zones; + _k479 = getFirstArrayKey( _a479 ); + while ( isDefined( _k479 ) ) + { + zone = _a479[ _k479 ]; + a_dog_locations = arraycombine( a_dog_locations, level.zones[ zone ].dog_locations, 0, 0 ); + _k479 = getNextArrayKey( _a479, _k479 ); + } + return a_dog_locations; +} + +get_farthest_dog_location( a_dog_locations ) +{ + n_farthest_index = 0; + n_distance_farthest = 0; + i = 0; + while ( i < a_dog_locations.size ) + { + n_distance_sq = distancesquared( self.origin, a_dog_locations[ i ].origin ); + if ( n_distance_sq > n_distance_farthest ) + { + n_distance_farthest = n_distance_sq; + n_farthest_index = i; + } + i++; + } + return a_dog_locations[ n_farthest_index ]; +} diff --git a/zm_buried_patch/maps/mp/zm_buried_ee.gsc b/zm_buried_patch/maps/mp/zm_buried_ee.gsc new file mode 100644 index 0000000..94b8e7f --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_ee.gsc @@ -0,0 +1,222 @@ +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zm_buried_ghost" ); +#using_animtree( "fxanim_props_dlc3" ); + +init_ghost_piano() +{ + t_bullseye = getent( "bullseye", "script_noteworthy" ); + t_chalk_line = getent( "ee_bar_chalk_line_trigger", "targetname" ); + if ( !isDefined( t_bullseye ) || !isDefined( t_chalk_line ) ) + { + return; + } + t_bullseye thread wait_for_valid_damage(); + t_chalk_line thread set_flags_while_players_stand_in_trigger(); + level thread mansion_ghost_plays_piano(); + level thread reward_think(); +/# + level thread devgui_support_ee(); +#/ + flag_init( "player_piano_song_active" ); +} + +init_ee_ghost_piano_flags() +{ + self ent_flag_init( "ee_standing_behind_chalk_line" ); +} + +wait_for_valid_damage() +{ + self setcandamage( 1 ); + while ( 1 ) + { + self waittill( "damage" ); + if ( is_ballistic_knife_variant( str_weapon_name ) ) + { + if ( isDefined( e_inflictor ) && e_inflictor ent_flag_exist( "ee_standing_behind_chalk_line" ) && e_inflictor ent_flag( "ee_standing_behind_chalk_line" ) && !flag( "player_piano_song_active" ) ) + { + level notify( "player_can_interact_with_ghost_piano_player" ); + } + } + } +} + +is_ballistic_knife_variant( str_weapon ) +{ + return issubstr( str_weapon, "knife_ballistic_" ); +} + +set_flags_while_players_stand_in_trigger() +{ + while ( 1 ) + { + self waittill( "trigger", player ); + if ( !player ent_flag_exist( "ee_standing_behind_chalk_line" ) ) + { + player ent_flag_init( "ee_standing_behind_chalk_line" ); + } + if ( !player ent_flag( "ee_standing_behind_chalk_line" ) ) + { + player thread clear_flag_when_player_leaves_trigger( self ); + } + } +} + +clear_flag_when_player_leaves_trigger( trigger ) +{ + self endon( "death_or_disconnect" ); + self ent_flag_set( "ee_standing_behind_chalk_line" ); + while ( self istouching( trigger ) ) + { + wait 0,25; + } + self ent_flag_clear( "ee_standing_behind_chalk_line" ); +} + +player_piano_starts() +{ +/# + iprintln( "player piano tune song start" ); +#/ + flag_set( "player_piano_song_active" ); + level notify( "piano_play" ); + level setclientfield( "mansion_piano_play", 1 ); + level setclientfield( "saloon_piano_play", 1 ); + wait getanimlength( %fxanim_gp_piano_old_anim ); +/# + iprintln( "player piano song done" ); +#/ + level setclientfield( "mansion_piano_play", 0 ); + level setclientfield( "saloon_piano_play", 0 ); + flag_clear( "player_piano_song_active" ); +} + +mansion_ghost_plays_piano() +{ + while ( 1 ) + { + flag_wait( "player_piano_song_active" ); + e_ghost = spawn_and_animate_ghost_pianist(); + flag_waitopen( "player_piano_song_active" ); + e_ghost thread delete_ghost_pianist(); + } +} + +spawn_and_animate_ghost_pianist() +{ + s_anim = getstruct( "ee_mansion_piano_anim_struct", "targetname" ); + e_temp = spawn( "script_model", s_anim.origin ); + e_temp.angles = s_anim.angles; + e_temp setclientfield( "ghost_fx", 3 ); + e_temp setmodel( "c_zom_zombie_buried_ghost_woman_fb" ); + e_temp useanimtree( -1 ); + e_temp setanim( %ai_zombie_ghost_playing_piano ); + e_temp setclientfield( "sndGhostAudio", 1 ); +/# + iprintln( "ghost piano player spawned" ); +#/ + return e_temp; +} + +reward_think() +{ + t_use = getent( "ee_ghost_piano_mansion_use_trigger", "targetname" ); + t_use sethintstring( &"ZM_BURIED_HINT_GHOST_PIANO", 10 ); + t_use setinvisibletoall(); + while ( 1 ) + { + level waittill( "player_can_interact_with_ghost_piano_player", player ); + level thread player_piano_starts(); + if ( !player has_player_received_reward() ) + { + t_use setvisibletoplayer( player ); + t_use thread player_can_use_ghost_piano_trigger( player ); + } + flag_waitopen( "player_piano_song_active" ); + t_use setinvisibletoall(); + level notify( "ghost_piano_reward_unavailable" ); + } +} + +player_can_use_ghost_piano_trigger( player ) +{ + player endon( "death_or_disconnect" ); + level endon( "ghost_piano_reward_unavailable" ); + self waittill( "trigger", user ); + if ( user != player && player.score < 10 && !player has_player_received_reward() ) + { + self give_reward( player ); + } +} + +give_reward( player ) +{ + player maps/mp/zombies/_zm_score::minus_to_player_score( 10 ); + player.got_easter_egg_reward = 1; + self setinvisibletoplayer( player ); + player notify( "player_received_ghost_round_free_perk" ); + free_perk = player maps/mp/zombies/_zm_perks::give_random_perk(); + if ( is_true( level.disable_free_perks_before_power ) ) + { + player thread maps/mp/zombies/_zm_powerups::disable_perk_before_power( free_perk ); + } +/# + iprintln( "player got reward!!" ); +#/ +} + +has_player_received_reward() +{ + return is_true( self.got_easter_egg_reward ); +} + +delete_ghost_pianist() +{ + self setclientfield( "ghost_fx", 5 ); + self playsound( "zmb_ai_ghost_death" ); + wait_network_frame(); + self delete(); +/# + iprintln( "ghost piano player deleted" ); +#/ +} + +devgui_support_ee() +{ + while ( 1 ) + { + str_notify = level waittill_any_return( "ghost_piano_warp_to_mansion_piano", "ghost_piano_warp_to_bar" ); + if ( str_notify == "ghost_piano_warp_to_mansion_piano" ) + { + get_players()[ 0 ] warp_to_struct( "ee_warp_mansion_piano", "targetname" ); + continue; + } + else + { + if ( str_notify == "ghost_piano_warp_to_bar" ) + { + get_players()[ 0 ] warp_to_struct( "ee_warp_bar", "targetname" ); + } + } + } +} + +warp_to_struct( str_value, str_key ) +{ + if ( !isDefined( str_key ) ) + { + str_key = "targetname"; + } + s_warp = getstruct( str_value, str_key ); + self setorigin( s_warp.origin ); + if ( isDefined( s_warp.angles ) ) + { + self setplayerangles( s_warp.angles ); + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_ffotd.gsc b/zm_buried_patch/maps/mp/zm_buried_ffotd.gsc new file mode 100644 index 0000000..d07937b --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_ffotd.gsc @@ -0,0 +1,704 @@ +#include maps/mp/zombies/_zm; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zm_buried; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +main_start() +{ + level thread spawned_collision_ffotd(); + level thread ghost_round_override_init(); + level thread init_push_triggers(); + level thread init_dtp_triggers(); + level thread spawned_slide_push_trigger(); + level thread spawned_slide_prone_trigger(); + level thread spawned_life_triggers(); + onplayerconnect_callback( ::ffotd_player_threads ); +} + +main_end() +{ + if ( is_gametype_active( "zgrief" ) ) + { + level thread zgrief_mode_fix(); + level.check_for_valid_spawn_near_team_callback = ::zgrief_respawn_override; + } + level.zombie_init_done = ::ffotd_zombie_init_done; + level thread bar_spawner_fix(); + level thread maze_blocker_fix(); + level thread door_clip_fix(); + level thread player_respawn_fix(); +} + +ffotd_zombie_init_done() +{ + self maps/mp/zm_buried::zombie_init_done(); + self thread jail_traversal_fix(); +} + +jail_traversal_fix() +{ + self endon( "death" ); + window_pos = ( -837, 496, 8 ); + fix_dist = 64; + while ( 1 ) + { + dist = distancesquared( self.origin, window_pos ); + if ( dist < fix_dist ) + { + node = self getnegotiationstartnode(); + if ( isDefined( node ) ) + { + if ( node.animscript == "zm_jump_down_48" && node.type == "Begin" ) + { + self setphysparams( 25, 0, 72 ); + wait 1; + if ( is_true( self.has_legs ) ) + { + self setphysparams( 15, 0, 72 ); + break; + } + else + { + self setphysparams( 15, 0, 24 ); + } + } + } + } + wait 0,25; + } +} + +ghost_round_override_init() +{ + origin = ( 2593, 562, 290 ); + length = 512; + width = 91; + height = 290; + trig1 = spawn( "trigger_box", origin, 0, length, width, height ); + trig1.angles = vectorScale( ( 0, 0, 0 ), 69 ); + trig1.script_noteworthy = "ghost_round_override"; +} + +zgrief_mode_fix() +{ + speed_trigger = getentarray( "specialty_fastreload", "script_noteworthy" ); + _a98 = speed_trigger; + _k98 = getFirstArrayKey( _a98 ); + while ( isDefined( _k98 ) ) + { + trig = _a98[ _k98 ]; + if ( trig.origin == ( -170,5, -328,25, 174 ) ) + { + trig.origin += vectorScale( ( 0, 0, 0 ), 32 ); + if ( isDefined( trig.clip ) ) + { + trig.clip.origin += vectorScale( ( 0, 0, 0 ), 32 ); + } + if ( isDefined( trig.machine ) ) + { + trig.machine.origin += vectorScale( ( 0, 0, 0 ), 32 ); + } + } + _k98 = getNextArrayKey( _a98, _k98 ); + } +} + +zgrief_respawn_override( revivee, return_struct ) +{ + players = get_players(); + spawn_points = maps/mp/gametypes_zm/_zm_gametype::get_player_spawns_for_gametype(); + grief_initial = getstructarray( "street_standard_player_spawns", "targetname" ); + _a119 = grief_initial; + _k119 = getFirstArrayKey( _a119 ); + while ( isDefined( _k119 ) ) + { + struct = _a119[ _k119 ]; + if ( isDefined( struct.script_int ) && struct.script_int == 2000 ) + { + spawn_points[ spawn_points.size ] = struct; + initial_point = struct; + initial_point.locked = 0; + } + _k119 = getNextArrayKey( _a119, _k119 ); + } + closest_group = undefined; + closest_distance = 100000000; + backup_group = undefined; + backup_distance = 100000000; + if ( spawn_points.size == 0 ) + { + return undefined; + } + i = 0; + while ( i < players.size ) + { + while ( is_player_valid( players[ i ], undefined, 1 ) && players[ i ] != self ) + { + j = 0; + while ( j < spawn_points.size ) + { + if ( isDefined( spawn_points[ j ].script_int ) ) + { + ideal_distance = spawn_points[ j ].script_int; + } + else + { + ideal_distance = 1000; + } + if ( spawn_points[ j ].locked == 0 ) + { + plyr_dist = distancesquared( players[ i ].origin, spawn_points[ j ].origin ); + if ( plyr_dist < ( ideal_distance * ideal_distance ) ) + { + if ( plyr_dist < closest_distance ) + { + closest_distance = plyr_dist; + closest_group = j; + } + j++; + continue; + } + else + { + if ( plyr_dist < backup_distance ) + { + backup_group = j; + backup_distance = plyr_dist; + } + } + } + j++; + } + } + if ( !isDefined( closest_group ) ) + { + closest_group = backup_group; + } + if ( isDefined( closest_group ) ) + { + spawn_location = maps/mp/zombies/_zm::get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); + if ( isDefined( spawn_location ) && !positionwouldtelefrag( spawn_location.origin ) ) + { + if ( isDefined( spawn_location.plyr ) && spawn_location.plyr != revivee getentitynumber() ) + { + i++; + continue; + } + else + { + return spawn_location; + } + } + } + i++; + } + while ( isDefined( initial_point ) ) + { + k = 0; + while ( k < spawn_points.size ) + { + if ( spawn_points[ k ] == initial_point ) + { + closest_group = k; + spawn_location = maps/mp/zombies/_zm::get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); + return spawn_location; + } + k++; + } + } + return undefined; +} + +spawned_slide_prone_trigger() +{ + origin = ( -2820, -412, 1438 ); + length = 216; + width = 216; + height = 108; + trig1 = spawn( "trigger_box", origin, 0, length, width, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.targetname = "force_from_prone"; +} + +spawned_slide_push_trigger() +{ + origin = ( -1416,5, -324, 428,5 ); + length = 111; + width = 394; + height = 189; + trig1 = spawn( "trigger_box", origin, 0, length, width, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.targetname = "push_from_prone"; + trig1.push_player_towards_point = ( -1336, -320, 360 ); + while ( 1 ) + { + trig1 waittill( "trigger", who ); + if ( who getstance() == "prone" && isplayer( who ) ) + { + who setstance( "crouch" ); + } + trig1 thread slide_push_think( who ); + wait 0,1; + } +} + +slide_push_think( who ) +{ + whopos = ( 0, 0, 0 ); + while ( who istouching( self ) ) + { + if ( who.origin == whopos ) + { + who setvelocity( self get_push_vector() ); + } + whopos = who.origin; + wait 2; + } +} + +slide_push_in_trigger( player ) +{ + if ( !player is_player_using_thumbstick() ) + { + player setvelocity( self get_push_vector() ); + } +} + +spawned_life_triggers() +{ + origin = ( 6637, 516, -580 ); + length = 1110; + width = 982; + height = 824; + trig1 = spawn( "trigger_box", origin, 0, length, width, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.script_noteworthy = "life_brush"; +} + +spawned_collision_ffotd() +{ + precachemodel( "collision_geo_64x64x10_slick" ); + precachemodel( "collision_geo_64x64x128_slick" ); + precachemodel( "collision_geo_128x128x10_slick" ); + precachemodel( "collision_geo_64x64x10_standard" ); + precachemodel( "collision_geo_64x64x64_standard" ); + precachemodel( "collision_geo_128x128x10_standard" ); + precachemodel( "collision_geo_128x128x128_standard" ); + precachemodel( "collision_geo_256x256x10_standard" ); + precachemodel( "collision_geo_256x256x256_standard" ); + precachemodel( "p6_zm_bu_rock_strata_column_01" ); + precachemodel( "p6_zm_bu_rock_strata_01" ); + precachemodel( "p6_zm_bu_rock_strata_04" ); + precachemodel( "p6_zm_bu_wood_planks_106x171" ); + flag_wait( "start_zombie_round_logic" ); + if ( isDefined( level.optimise_for_splitscreen ) && !level.optimise_for_splitscreen ) + { + collision1 = spawn( "script_model", ( 3731,5, 736, 6,5 ) ); + collision1 setmodel( "collision_geo_64x64x128_slick" ); + collision1.angles = ( 4,54625, 313,41, -4,78954 ); + collision1 ghost(); + collision2 = spawn( "script_model", ( 34, -1691, 375 ) ); + collision2 setmodel( "collision_geo_256x256x10_standard" ); + collision2.angles = vectorScale( ( 0, 0, 0 ), 3,80002 ); + collision2 ghost(); + collision3 = spawn( "script_model", ( 641, 545, -1,21359 ) ); + collision3 setmodel( "collision_geo_64x64x128_slick" ); + collision3.angles = ( 1,27355, 320,806, -5,38137 ); + collision3 ghost(); + saloon1 = spawn( "script_model", ( 1032,22, -1744,09, 309 ) ); + saloon1 setmodel( "collision_geo_64x64x64_standard" ); + saloon1.angles = vectorScale( ( 0, 0, 0 ), 40,8 ); + saloon1 ghost(); + saloon2 = spawn( "script_model", ( 1005,78, -1766,91, 309 ) ); + saloon2 setmodel( "collision_geo_64x64x64_standard" ); + saloon2.angles = vectorScale( ( 0, 0, 0 ), 40,8 ); + saloon2 ghost(); + gs1 = spawn( "script_model", ( 118,001, -537,037, 236 ) ); + gs1 setmodel( "collision_geo_64x64x64_standard" ); + gs1.angles = vectorScale( ( 0, 0, 0 ), 90 ); + gs1 ghost(); + gs1 thread delete_upon_flag( "general_store_porch_door1" ); + gs2 = spawn( "script_model", ( 117,999, -571,963, 236 ) ); + gs2 setmodel( "collision_geo_64x64x64_standard" ); + gs2.angles = vectorScale( ( 0, 0, 0 ), 90 ); + gs2 ghost(); + gs2 thread delete_upon_flag( "general_store_porch_door1" ); + collision4 = spawn( "script_model", ( 1672, 692, 99 ) ); + collision4 setmodel( "collision_geo_128x128x10_slick" ); + collision4.angles = ( 280,6, 270, 86,6 ); + collision4 ghost(); + cw1 = spawn( "script_model", ( 320, -1988, 116 ) ); + cw1 setmodel( "collision_geo_128x128x128_standard" ); + cw1.angles = ( 0, 0, 0 ); + cw1 ghost(); + rock1 = spawn( "script_model", ( 311, -1945, 104 ) ); + rock1 setmodel( "p6_zm_bu_rock_strata_column_01" ); + rock1.angles = vectorScale( ( 0, 0, 0 ), 90 ); + st1 = spawn( "script_model", ( -736, -2, 25 ) ); + st1 setmodel( "collision_geo_128x128x10_standard" ); + st1.angles = ( 270, 45, 0 ); + st1 ghost(); + ml1 = spawn( "script_model", ( 2831, 440, 405 ) ); + ml1 setmodel( "collision_geo_128x128x128_standard" ); + ml1.angles = ( 0, 0, 0 ); + ml1 ghost(); + ml2 = spawn( "script_model", ( 2831, 680, 420 ) ); + ml2 setmodel( "collision_geo_128x128x128_standard" ); + ml2.angles = ( 0, 0, 0 ); + ml2 ghost(); + mr1 = spawn( "script_model", ( 2380, 1123, 350 ) ); + mr1 setmodel( "collision_geo_256x256x10_standard" ); + mr1.angles = ( 0, 13,8, -90 ); + mr1 ghost(); + th1 = spawn( "script_model", ( 2072, 1168, 360 ) ); + th1 setmodel( "collision_geo_128x128x128_standard" ); + th1.angles = ( 0, 0, 0 ); + th1 ghost(); + th1a = spawn( "script_model", ( 2296, 1088, 400 ) ); + th1a setmodel( "collision_geo_128x128x128_standard" ); + th1a.angles = ( 0, 0, 0 ); + th1a ghost(); + th2 = spawn( "script_model", ( -544, 510, 286 ) ); + th2 setmodel( "collision_geo_256x256x10_standard" ); + th2.angles = ( 0, 7,2, -7,8 ); + th2 ghost(); + th2a = spawn( "script_model", ( -296,95, 537,996, 312,557 ) ); + th2a setmodel( "collision_geo_256x256x10_standard" ); + th2a.angles = ( 347,355, 6,47392, -7,41809 ); + th2a ghost(); + th3 = spawn( "script_model", ( 864, 872, 420 ) ); + th3 setmodel( "collision_geo_256x256x256_standard" ); + th3.angles = ( 0, 0, 0 ); + th3 ghost(); + th4 = spawn( "script_model", ( 2361, 1056, 398 ) ); + th4 setmodel( "collision_geo_256x256x10_standard" ); + th4.angles = vectorScale( ( 0, 0, 0 ), 270 ); + th4 ghost(); + ch1 = spawn( "script_model", ( 1954, 1996, 222 ) ); + ch1 setmodel( "collision_geo_256x256x10_standard" ); + ch1.angles = ( 270, 340, 0,32 ); + ch1 ghost(); + ch2 = spawn( "script_model", ( 1945, 1972, 222 ) ); + ch2 setmodel( "collision_geo_256x256x10_standard" ); + ch2.angles = ( 270, 340, 0,32 ); + ch2 ghost(); + rock1 = spawn( "script_model", ( 3259,54, -189,38, 146,23 ) ); + rock1 setmodel( "p6_zm_bu_rock_strata_column_01" ); + rock1.angles = ( 7,87264, 94,015, 4,57899 ); + rock2 = spawn( "script_model", ( 3351,97, -254,58, 95 ) ); + rock2 setmodel( "p6_zm_bu_rock_strata_01" ); + rock2.angles = vectorScale( ( 0, 0, 0 ), 169,1 ); + yt1 = spawn( "script_model", ( 671, -1412, 214 ) ); + yt1 setmodel( "collision_geo_64x64x10_slick" ); + yt1.angles = ( 62,8, 315, 0 ); + yt1 ghost(); + yt2 = spawn( "script_model", ( 676, -1407, 214 ) ); + yt2 setmodel( "collision_geo_64x64x10_slick" ); + yt2.angles = ( 62,8, 315, 0 ); + yt2 ghost(); + stb1 = spawn( "script_model", ( -807, 59, 127 ) ); + stb1 setmodel( "collision_geo_64x64x10_standard" ); + stb1.angles = vectorScale( ( 0, 0, 0 ), 90 ); + stb1 ghost(); + stb2 = spawn( "script_model", ( -807, 59, 191 ) ); + stb2 setmodel( "collision_geo_64x64x10_standard" ); + stb2.angles = vectorScale( ( 0, 0, 0 ), 90 ); + stb2 ghost(); + stb3 = spawn( "script_model", ( -861, 59, 31 ) ); + stb3 setmodel( "collision_geo_128x128x10_standard" ); + stb3.angles = vectorScale( ( 0, 0, 0 ), 90 ); + stb3 ghost(); + j162 = spawn( "script_model", ( 912, -936, 214 ) ); + j162 setmodel( "collision_geo_128x128x10_standard" ); + j162.angles = ( 0, 0, 0 ); + j162 ghost(); + j156 = spawn( "script_model", ( 434, 1213, 184 ) ); + j156 setmodel( "collision_geo_128x128x10_standard" ); + j156.angles = vectorScale( ( 0, 0, 0 ), 273 ); + j156 ghost(); + j163_1 = spawn( "script_model", ( 1663, 68, 29 ) ); + j163_1 setmodel( "collision_geo_128x128x10_slick" ); + j163_1.angles = vectorScale( ( 0, 0, 0 ), 270 ); + j163_1 ghost(); + j163_2 = spawn( "script_model", ( 1663, 259, 29 ) ); + j163_2 setmodel( "collision_geo_128x128x10_slick" ); + j163_2.angles = vectorScale( ( 0, 0, 0 ), 270 ); + j163_2 ghost(); + j125_1 = spawn( "script_model", ( 2443,65, 1013,54, 236,213 ) ); + j125_1 setmodel( "p6_zm_bu_rock_strata_04" ); + j125_1.angles = ( 13,345, 103,42, -13,4657 ); + j125_3 = spawn( "script_model", ( 2448,7, 852,791, 272,051 ) ); + j125_3 setmodel( "p6_zm_bu_wood_planks_106x171" ); + j125_3.angles = ( 0, 270, 19,4 ); + j125_4 = spawn( "script_model", ( 2313,21, 872,54, 241,01 ) ); + j125_4 setmodel( "p6_zm_bu_wood_planks_106x171" ); + j125_4.angles = ( 0, 0, 0 ); + } +} + +delete_upon_flag( flag_notify ) +{ + level flag_wait( flag_notify ); + self delete(); +} + +init_push_triggers() +{ + ghost_mansion_to_maze_push_trigger_left(); + ghost_mansion_to_maze_push_trigger_right(); + ghost_mansion_from_maze_push_trigger(); + a_push_triggers = getentarray( "push_trigger", "script_noteworthy" ); + array_thread( a_push_triggers, ::push_players_standing_in_trigger_volumes ); +} + +ghost_mansion_to_maze_push_trigger_left() +{ + origin = ( 2656, 689, 183 ); + length = 128; + width = 8; + height = 64; + trig1 = spawn( "trigger_box", origin, 0, width, length, height ); + trig1.angles = vectorScale( ( 0, 0, 0 ), 325,6 ); + trig1.script_noteworthy = "push_trigger"; + trig1.push_player_towards_point = ( 2666, 685, 183 ); +} + +ghost_mansion_to_maze_push_trigger_right() +{ + origin = ( 2592, 453, 183 ); + length = 32; + width = 16; + height = 64; + trig1 = spawn( "trigger_box", origin, 0, width, length, height ); + trig1.angles = vectorScale( ( 0, 0, 0 ), 325,6 ); + trig1.script_noteworthy = "push_trigger"; + trig1.push_player_towards_point = ( 2686, 440, 174 ); +} + +ghost_mansion_from_maze_push_trigger() +{ + origin = ( 3425, 1067, 53 ); + length = 128; + width = 16; + height = 64; + trig1 = spawn( "trigger_box", origin, 0, width, length, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.script_noteworthy = "push_trigger"; + trig1.push_player_towards_point = ( 3337, 1067, 90 ); +} + +push_players_standing_in_trigger_volumes() +{ +/# + assert( isDefined( self.push_player_towards_point ), "push_player_towards_point field is undefined on push_trigger! This is required for the push functionality to work" ); +#/ + while ( 1 ) + { + self waittill( "trigger", player ); + if ( !player is_player_using_thumbstick() ) + { + player setvelocity( self get_push_vector() ); + } + } +} + +is_player_using_thumbstick() +{ + b_using_thumbstick = 1; + v_thumbstick = self getnormalizedmovement(); + if ( length( v_thumbstick ) < 0,3 ) + { + b_using_thumbstick = 0; + } + return b_using_thumbstick; +} + +get_push_vector() +{ + return vectornormalize( self.push_player_towards_point - self.origin ) * 100; +} + +bar_spawner_fix() +{ + bad_pos = ( 459,5, -1984, 84 ); + dist_fix = 64; + bar_spawners = getstructarray( "zone_bar_spawners", "targetname" ); + _a586 = bar_spawners; + _k586 = getFirstArrayKey( _a586 ); + while ( isDefined( _k586 ) ) + { + spawner = _a586[ _k586 ]; + if ( isDefined( spawner.script_string ) && spawner.script_string == "bar2" ) + { + dist = distancesquared( spawner.origin, bad_pos ); + if ( dist < dist_fix ) + { + spawner.origin = ( 459,5, -2020, 84 ); + } + } + _k586 = getNextArrayKey( _a586, _k586 ); + } +} + +player_respawn_fix() +{ + maze_spawners = getstructarray( "maze_spawn_points", "targetname" ); + _a602 = maze_spawners; + _k602 = getFirstArrayKey( _a602 ); + while ( isDefined( _k602 ) ) + { + spawner = _a602[ _k602 ]; + if ( spawner.origin == ( 3469, 1026, 20 ) ) + { + spawner.origin = ( 3509, 1032, 76 ); + } + _k602 = getNextArrayKey( _a602, _k602 ); + } +} + +door_clip_fix() +{ + bank1 = getentarray( "pf728_auto2510", "targetname" ); + i = 0; + while ( i < bank1.size ) + { + if ( isDefined( bank1[ i ].script_noteworthy ) && bank1[ i ].script_noteworthy == "clip" ) + { + bank1[ i ] delete(); + } + i++; + } + bank2 = getentarray( "pf728_auto2507", "targetname" ); + i = 0; + while ( i < bank2.size ) + { + if ( isDefined( bank2[ i ].script_noteworthy ) && bank2[ i ].script_noteworthy == "clip" ) + { + bank2[ i ] delete(); + } + i++; + } +} + +maze_blocker_fix() +{ + node_org = ( 4732, 960, 32 ); + node_target_org = ( 4734, 1198, 32 ); + blocker_node = getnearestnode( node_org ); + blocker_node_target = getnearestnode( node_target_org ); + while ( 1 ) + { + level waittill( "zm_buried_maze_changed" ); + found = 0; + perm_list = level._maze._perms[ level._maze._cur_perm ]; + _a648 = perm_list; + _k648 = getFirstArrayKey( _a648 ); + while ( isDefined( _k648 ) ) + { + blocker = _a648[ _k648 ]; + if ( blocker == "blocker_10" ) + { + found = 1; + if ( isDefined( blocker_node ) && isDefined( blocker_node_target ) ) + { + unlink_nodes( blocker_node, blocker_node_target, 0 ); + unlink_nodes( blocker_node_target, blocker_node, 0 ); + } + } + _k648 = getNextArrayKey( _a648, _k648 ); + } + if ( !found ) + { + if ( isDefined( blocker_node ) && isDefined( blocker_node_target ) ) + { + link_nodes( blocker_node, blocker_node_target, 1 ); + link_nodes( blocker_node_target, blocker_node, 1 ); + } + } + } +} + +time_bomb_takeaway() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "new_tactical_grenade", new_weapon ); + if ( isDefined( new_weapon ) && new_weapon != "time_bomb_zm" && self hasweapon( "time_bomb_detonator_zm" ) ) + { + self takeweapon( "time_bomb_detonator_zm" ); + } + } +} + +ffotd_player_threads() +{ + self thread time_bomb_takeaway(); +} + +init_dtp_triggers() +{ + barn_hay_push_trigger(); + barn_rail_push_trigger(); + church_fence_push_trigger(); + a_push_triggers = getentarray( "push_from_dtp", "script_noteworthy" ); + array_thread( a_push_triggers, ::dtp_push ); +} + +barn_hay_push_trigger() +{ + origin = ( -1137, -190, 188 ); + length = 48; + width = 64; + height = 64; + trig1 = spawn( "trigger_box", origin, 0, width, length, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.script_noteworthy = "push_from_dtp"; + trig1.push_player_towards_point = ( -1137, -264, 200 ); +} + +barn_rail_push_trigger() +{ + origin = ( -1137, -211, 188 ); + length = 32; + width = 128; + height = 64; + trig1 = spawn( "trigger_box", origin, 0, width, length, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.script_noteworthy = "push_from_dtp"; + trig1.push_player_towards_point = ( -1137, -285, 200 ); +} + +church_fence_push_trigger() +{ + origin = ( 900, 1000, 54 ); + length = 64; + width = 192; + height = 64; + trig1 = spawn( "trigger_box", origin, 0, width, length, height ); + trig1.angles = ( 0, 0, 0 ); + trig1.script_noteworthy = "push_from_dtp"; + trig1.push_player_towards_point = ( 929, 943, 64 ); +} + +dtp_push() +{ + pos = ( 0, 0, 0 ); + while ( 1 ) + { + self waittill( "trigger", player ); + if ( pos == player.origin ) + { + if ( player getstance() == "prone" ) + { + player setstance( "crouch" ); + } + player setvelocity( self get_push_vector() ); + } + pos = player.origin; + wait 0,5; + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_fountain.gsc b/zm_buried_patch/maps/mp/zm_buried_fountain.gsc new file mode 100644 index 0000000..bcf148a --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_fountain.gsc @@ -0,0 +1,297 @@ +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_ai_ghost; +#include maps/mp/zm_buried_classic; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +init_fountain() +{ + flag_init( "courtyard_fountain_broken" ); + flag_init( "maze_fountain_broken" ); + flag_init( "fountain_transport_active" ); + level._effect[ "fountain_break" ] = loadfx( "maps/zombie_buried/fx_buried_fountain_break" ); + level._effect[ "fountain_spray" ] = loadfx( "maps/zombie_buried/fx_buried_fountain_spray" ); + level._effect[ "fountain_teleport" ] = loadfx( "maps/zombie_buried/fx_buried_teleport_flash" ); + level thread fountain_setup(); + level thread maze_fountain_collmap(); +} + +fountain_setup() +{ + flag_wait( "initial_blackscreen_passed" ); + fountain_debug_print( "fountain scripts running" ); + level thread set_flag_on_notify( "courtyard_fountain_open", "courtyard_fountain_broken" ); + level thread sloth_fountain_think(); + level thread maze_fountain_think(); + level thread fountain_transport_think(); +/# + level thread debug_warp_player_to_fountain(); +#/ +} + +maze_fountain_collmap() +{ + collmap = getentarray( "maze_fountain_collmap", "targetname" ); + flag_wait( "maze_fountain_broken" ); + array_thread( collmap, ::self_delete ); +} + +sloth_fountain_think() +{ + flag_wait( "courtyard_fountain_broken" ); + level setclientfield( "sloth_fountain_start", 1 ); + s_courtyard_fountain = getstruct( "courtyard_fountain_struct", "targetname" ); + if ( isDefined( s_courtyard_fountain ) ) + { + sound_offset = vectorScale( ( 0, 0, 1 ), 100 ); + sound_ent = spawn( "script_origin", s_courtyard_fountain.origin + sound_offset ); + playfx( level._effect[ "fx_buried_fountain_spray" ], s_courtyard_fountain.origin ); + playfx( level._effect[ "fountain_break" ], s_courtyard_fountain.origin ); + sound_ent playloopsound( "zmb_fountain_spray", 0,2 ); + } + show_maze_fountain_water(); + fountain_debug_print( "courtyard_fountain_broken" ); +} + +set_flag_on_notify( notifystr, strflag ) +{ + if ( notifystr != "death" ) + { + self endon( "death" ); + } + if ( !level.flag[ strflag ] ) + { + self waittill( notifystr ); + flag_set( strflag ); + } +} + +maze_fountain_think() +{ + hide_maze_fountain_water(); + wait_for_maze_fountain_to_be_destroyed(); + destroy_maze_fountain(); + flag_wait( "courtyard_fountain_broken" ); + flag_set( "fountain_transport_active" ); +} + +hide_maze_fountain_water() +{ + t_water = getent( "maze_fountain_water_trigger", "targetname" ); + t_water enablelinkto(); + m_water = getent( "maze_fountain_water", "targetname" ); + t_water linkto( m_water ); + m_water movez( -475, 0,05 ); +} + +show_maze_fountain_water() +{ + m_water = getent( "maze_fountain_water", "targetname" ); + m_water movez( 398, 6 ); + m_water ghost(); + fountain_debug_print( "maze water ready" ); +} + +wait_for_maze_fountain_to_be_destroyed() +{ +/# + level endon( "_destroy_maze_fountain" ); +#/ + t_damage = getent( "maze_fountain_trigger", "targetname" ); + health = 1000; + while ( health > 0 ) + { + t_damage waittill( "damage", damage, attacker, direction, point, type, tagname, modelname, partname, weaponname, idflags ); + if ( damage < 50 ) + { + damage = 0; + } + if ( isDefined( type ) && type != "MOD_EXPLOSIVE" && type != "MOD_EXPLOSIVE_SPLASH" && type != "MOD_GRENADE" && type != "MOD_GRENADE_SPLASH" || type == "MOD_PROJECTILE" && type == "MOD_PROJECTILE_SPLASH" ) + { + health -= damage; + } + } +} + +destroy_maze_fountain() +{ + s_fountain = getstruct( "maze_fountain_struct", "targetname" ); + level setclientfield( "maze_fountain_start", 1 ); + if ( isDefined( s_fountain ) ) + { + playfx( level._effect[ "fountain_break" ], s_fountain.origin ); + } + s_fountain_clip = getent( "maze_fountain_clip", "targetname" ); + s_fountain_clip delete(); + flag_set( "maze_fountain_broken" ); +} + +fountain_transport_think() +{ + t_transporter = getent( "maze_fountain_water_trigger", "targetname" ); + while ( 1 ) + { + t_transporter waittill( "trigger", player ); + if ( !isDefined( player.is_in_fountain_transport_trigger ) || !player.is_in_fountain_transport_trigger ) + { + player.is_in_fountain_transport_trigger = 1; + if ( flag( "fountain_transport_active" ) ) + { + player thread transport_player_to_start_zone(); + break; + } + else + { + player thread delay_transport_check(); + } + } + } +} + +delay_transport_check() +{ + self endon( "death" ); + self endon( "bled_out" ); + wait 1; + self.is_in_fountain_transport_trigger = 0; +} + +transport_player_to_start_zone() +{ + self endon( "death_or_disconnect" ); + fountain_debug_print( "transport player!" ); + if ( !isDefined( level._fountain_transporter ) ) + { + level._fountain_transporter = spawnstruct(); + level._fountain_transporter.index = 0; + level._fountain_transporter.end_points = getstructarray( "fountain_transport_end_location", "targetname" ); + } + self playsoundtoplayer( "zmb_buried_teleport", self ); + self play_teleport_fx(); + self flash_screen_white(); + wait_network_frame(); + if ( level._fountain_transporter.index >= level._fountain_transporter.end_points.size ) + { + level._fountain_transporter.index = 0; + } + tries = 0; + while ( positionwouldtelefrag( level._fountain_transporter.end_points[ level._fountain_transporter.index ].origin ) ) + { + tries++; + if ( tries >= 4 ) + { + tries = 0; + wait 0,05; + } + level._fountain_transporter.index++; + if ( level._fountain_transporter.index >= level._fountain_transporter.end_points.size ) + { + level._fountain_transporter.index = 0; + } + } + self setorigin( level._fountain_transporter.end_points[ level._fountain_transporter.index ].origin ); + self setplayerangles( level._fountain_transporter.end_points[ level._fountain_transporter.index ].angles ); + level._fountain_transporter.index++; + wait_network_frame(); + self play_teleport_fx(); + self thread flash_screen_fade_out(); + self maps/mp/zm_buried_classic::buried_set_start_area_lighting(); + self thread maps/mp/zombies/_zm_ai_ghost::behave_after_fountain_transport( self ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "buried_fountain_transporter_used", 0 ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "buried_fountain_transporter_used" ); + self notify( "player_used_fountain_teleporter" ); + wait_network_frame(); + wait_network_frame(); + self.is_in_fountain_transport_trigger = 0; +} + +play_teleport_fx() +{ + playfx( level._effect[ "fountain_teleport" ], self gettagorigin( "J_SpineLower" ) ); +} + +flash_screen_white() +{ + self endon( "death_or_disconnect" ); + self.hud_transporter_flash = self create_client_hud_elem(); + self.hud_transporter_flash fadeovertime( 0,2 ); + self.hud_transporter_flash.alpha = 1; + wait 0,2; +} + +flash_screen_fade_out() +{ + self.hud_transporter_flash fadeovertime( 0,2 ); + self.hud_transporter_flash.alpha = 0; + wait 0,2; + self.hud_transporter_flash destroy(); + self.hud_transporter_flash = undefined; +} + +create_client_hud_elem() +{ + hud_elem = newclienthudelem( self ); + hud_elem.x = 0; + hud_elem.y = 0; + hud_elem.horzalign = "fullscreen"; + hud_elem.vertalign = "fullscreen"; + hud_elem.foreground = 1; + hud_elem.alpha = 0; + hud_elem.hidewheninmenu = 0; + hud_elem.shader = "white"; + hud_elem setshader( "white", 640, 480 ); + return hud_elem; +} + +debug_warp_player_to_fountain() +{ + while ( 1 ) + { + str_notify = level waittill_any_return( "warp_player_to_maze_fountain", "warp_player_to_courtyard_fountain" ); + if ( str_notify == "warp_player_to_maze_fountain" ) + { + str_warp_point = "teleport_player_to_maze_fountain"; + } + else + { + if ( str_notify == "warp_player_to_courtyard_fountain" ) + { + str_warp_point = "teleport_player_to_courtyard_fountain"; + } + } + _a332 = get_players(); + _k332 = getFirstArrayKey( _a332 ); + while ( isDefined( _k332 ) ) + { + player = _a332[ _k332 ]; + _warp_player_to_maze_fountain( player, str_warp_point ); + wait 0,25; + _k332 = getNextArrayKey( _a332, _k332 ); + } + } +} + +_warp_player_to_maze_fountain( player, str_teleport_point ) +{ + fountain_debug_print( "teleporting player to " + str_teleport_point ); + s_warp = getstruct( str_teleport_point, "targetname" ); + origin = s_warp.origin; + while ( positionwouldtelefrag( origin ) ) + { + wait 0,05; + origin = s_warp.origin + ( randomfloatrange( -64, 64 ), randomfloatrange( -64, 64 ), 0 ); + } + player setorigin( origin ); + player setplayerangles( s_warp.angles ); +} + +fountain_debug_print( str_text ) +{ +/# + if ( getDvarInt( #"AE3F04F6" ) > 0 ) + { + iprintlnbold( str_text ); +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_fx.gsc b/zm_buried_patch/maps/mp/zm_buried_fx.gsc new file mode 100644 index 0000000..f8ab98b --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_fx.gsc @@ -0,0 +1,150 @@ +#include maps/mp/_utility; + +#using_animtree( "fxanim_props_dlc3" ); + +main() +{ + precache_createfx_fx(); + precache_scripted_fx(); + precache_fxanim_props(); + maps/mp/createfx/zm_buried_fx::main(); +} + +precache_scripted_fx() +{ + level._effect[ "switch_sparks" ] = loadfx( "maps/zombie/fx_zmb_pswitch_spark" ); + 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[ "blue_eyes" ] = loadfx( "maps/zombie/fx_zombie_eye_single_blue" ); + level._effect[ "orange_eyes" ] = loadfx( "misc/fx_zombie_eye_single" ); + level._effect[ "player_possessed_eyes" ] = loadfx( "maps/zombie_buried/fx_buried_eye_stulhinger" ); + gametype = getDvar( "ui_gametype" ); + if ( gametype == "zcleansed" ) + { + level._effect[ "blue_eyes_player" ] = loadfx( "maps/zombie/fx_zombie_eye_returned_blue" ); + level._effect[ "lava_burning" ] = loadfx( "env/fire/fx_fire_lava_player_torso" ); + } + if ( isDefined( 0 ) && 0 ) + { + level._effect[ "player_3rd_spotlight_lite" ] = loadfx( "maps/zombie_buried/fx_buried_spot_flkr_lite" ); + level._effect[ "player_3rd_spotlight_med" ] = loadfx( "maps/zombie_buried/fx_buried_spot_flkr_med" ); + level._effect[ "player_3rd_spotlight_high" ] = loadfx( "maps/zombie_buried/fx_buried_spot_flkr_hvy" ); + level._effect[ "oillamp" ] = loadfx( "maps/zombie_buried/fx_buried_glow_lantern" ); + } + level._effect[ "booze_candy_spawn" ] = loadfx( "maps/zombie_buried/fx_buried_booze_candy_spawn" ); + level._effect[ "crusher_sparks" ] = loadfx( "maps/zombie_buried/fx_buried_crusher_sparks" ); + level._effect[ "rise_burst_foliage" ] = loadfx( "maps/zombie/fx_zm_buried_hedge_billow_body" ); + level._effect[ "rise_billow_foliage" ] = loadfx( "maps/zombie/fx_zm_buried_hedge_burst_hand" ); + level._effect[ "rise_dust_foliage" ] = loadfx( "maps/zombie/fx_zm_buried_hedge_dustfall_body" ); + level._effect[ "fx_buried_key_glint" ] = loadfx( "maps/zombie_buried/fx_buried_key_glint" ); + level._effect[ "sq_glow" ] = loadfx( "maps/zombie_buried/fx_buried_glow_lantern_ghost" ); + level._effect[ "vulture_fx_wisp" ] = loadfx( "maps/zombie_buried/fx_buried_richt_whisp_center" ); + level._effect[ "vulture_fx_wisp_orb" ] = loadfx( "maps/zombie_buried/fx_buried_richt_whisp_orbit" ); + level._effect[ "fx_wisp_m" ] = loadfx( "maps/zombie_buried/fx_buried_maxis_whisp_os" ); + level._effect[ "fx_wisp_lg_m" ] = loadfx( "maps/zombie_buried/fx_buried_maxis_whisp_lg_os" ); + level._effect[ "sq_bulb_blue" ] = loadfx( "maps/zombie_buried/fx_buried_eg_blu" ); + level._effect[ "sq_bulb_orange" ] = loadfx( "maps/zombie_buried/fx_buried_eg_orng" ); + level._effect[ "sq_bulb_green" ] = loadfx( "maps/zombie_buried/fx_buried_sq_bulb_green" ); + level._effect[ "sq_bulb_yellow" ] = loadfx( "maps/zombie_buried/fx_buried_sq_bulb_yellow" ); + level._effect[ "sq_ether_amp_trail" ] = loadfx( "maps/zombie_buried/fx_buried_ether_amp_trail" ); + level._effect[ "sq_tower_r" ] = loadfx( "maps/zombie_buried/fx_buried_tower_power_blue" ); + level._effect[ "sq_tower_m" ] = loadfx( "maps/zombie_buried/fx_buried_tower_power_orange" ); + level._effect[ "sq_tower_bolts" ] = loadfx( "maps/zombie_buried/fx_buried_tower_power_bolts" ); + level._effect[ "sq_spark" ] = loadfx( "maps/zombie_buried/fx_buried_spark_gen" ); + level._effect[ "sq_spawn" ] = loadfx( "maps/zombie_buried/fx_buried_time_bomb_spawn" ); + level._effect[ "sq_vulture_orange_eye_glow" ] = loadfx( "misc/fx_zombie_eye_side_quest" ); +} + +precache_createfx_fx() +{ + level._effect[ "fx_buried_ash_blowing" ] = loadfx( "maps/zombie_buried/fx_buried_ash_blowing" ); + level._effect[ "fx_buried_bats_group" ] = loadfx( "maps/zombie_buried/fx_buried_bats_group" ); + level._effect[ "fx_buried_cloud_low" ] = loadfx( "maps/zombie_buried/fx_buried_cloud_low" ); + level._effect[ "fx_buried_conveyor_belt_edge" ] = loadfx( "maps/zombie_buried/fx_buried_conveyor_belt_edge" ); + level._effect[ "fx_buried_dust_ceiling_hole" ] = loadfx( "maps/zombie_buried/fx_buried_dust_ceiling_hole" ); + level._effect[ "fx_buried_dust_edge_100" ] = loadfx( "maps/zombie_buried/fx_buried_dust_edge_100" ); + level._effect[ "fx_buried_dust_edge_xlg" ] = loadfx( "maps/zombie_buried/fx_buried_dust_edge_xlg" ); + level._effect[ "fx_buried_dust_edge_blown" ] = loadfx( "maps/zombie_buried/fx_buried_dust_edge_blown" ); + level._effect[ "fx_buried_dust_flurry" ] = loadfx( "maps/zombie_buried/fx_buried_dust_flurry" ); + level._effect[ "fx_buried_dust_int_25x50" ] = loadfx( "maps/zombie_buried/fx_buried_dust_int_25x50" ); + level._effect[ "fx_buried_dust_motes_xlg" ] = loadfx( "maps/zombie_buried/fx_buried_dust_motes_xlg" ); + level._effect[ "fx_buried_dust_motes_ext_xlg" ] = loadfx( "maps/zombie_buried/fx_buried_dust_motes_ext_xlg" ); + level._effect[ "fx_buried_dust_motes_ext_sm" ] = loadfx( "maps/zombie_buried/fx_buried_dust_motes_ext_sm" ); + level._effect[ "fx_buried_dust_rising_sm" ] = loadfx( "maps/zombie_buried/fx_buried_dust_rising_sm" ); + level._effect[ "fx_buried_dust_rising_md" ] = loadfx( "maps/zombie_buried/fx_buried_dust_rising_md" ); + level._effect[ "fx_buried_dust_tunnel_ceiling" ] = loadfx( "maps/zombie_buried/fx_buried_dust_tunnel_ceiling" ); + level._effect[ "fx_buried_fireplace" ] = loadfx( "maps/zombie_buried/fx_buried_fireplace" ); + level._effect[ "fx_buried_fog_sm" ] = loadfx( "maps/zombie_buried/fx_buried_fog_sm" ); + level._effect[ "fx_buried_fog_md" ] = loadfx( "maps/zombie_buried/fx_buried_fog_md" ); + level._effect[ "fx_buried_glow_kerosene_lamp" ] = loadfx( "maps/zombie_buried/fx_buried_glow_kerosene_lamp" ); + level._effect[ "fx_buried_glow_sconce" ] = loadfx( "maps/zombie_buried/fx_buried_glow_sconce" ); + level._effect[ "fx_buried_god_ray_sm" ] = loadfx( "maps/zombie_buried/fx_buried_god_ray_sm" ); + level._effect[ "fx_buried_godray_church" ] = loadfx( "maps/zombie_buried/fx_buried_godray_church" ); + level._effect[ "fx_buried_godray_ext_sm" ] = loadfx( "maps/zombie_buried/fx_buried_godray_ext_sm" ); + level._effect[ "fx_buried_godray_ext_md" ] = loadfx( "maps/zombie_buried/fx_buried_godray_ext_md" ); + level._effect[ "fx_buried_godray_ext_lg" ] = loadfx( "maps/zombie_buried/fx_buried_godray_ext_lg" ); + level._effect[ "fx_buried_godray_ext_thin" ] = loadfx( "maps/zombie_buried/fx_buried_godray_ext_thin" ); + level._effect[ "fx_buried_insects" ] = loadfx( "maps/zombie_buried/fx_buried_insects" ); + level._effect[ "fx_buried_sand_windy_sm" ] = loadfx( "maps/zombie_buried/fx_buried_sand_windy_sm" ); + level._effect[ "fx_buried_sand_windy_md" ] = loadfx( "maps/zombie_buried/fx_buried_sand_windy_md" ); + level._effect[ "fx_buried_sandstorm_edge" ] = loadfx( "maps/zombie_buried/fx_buried_sandstorm_edge" ); + level._effect[ "fx_buried_sandstorm_distant" ] = loadfx( "maps/zombie_buried/fx_buried_sandstorm_distant" ); + level._effect[ "fx_buried_smk_plume_lg" ] = loadfx( "maps/zombie_buried/fx_buried_smk_plume_lg" ); + level._effect[ "fx_buried_steam_md" ] = loadfx( "maps/zombie_buried/fx_buried_steam_md" ); + level._effect[ "fx_buried_water_dripping" ] = loadfx( "maps/zombie_buried/fx_buried_water_dripping" ); + level._effect[ "fx_buried_water_spilling" ] = loadfx( "maps/zombie_buried/fx_buried_water_spilling" ); + level._effect[ "fx_buried_water_spilling_lg" ] = loadfx( "maps/zombie_buried/fx_buried_water_spilling_lg" ); + level._effect[ "fx_buried_barrier_break" ] = loadfx( "maps/zombie_buried/fx_buried_barrier_break" ); + level._effect[ "fx_buried_barrier_break_sm" ] = loadfx( "maps/zombie_buried/fx_buried_barrier_break_sm" ); + level._effect[ "fx_buried_dest_floor_lg" ] = loadfx( "maps/zombie_buried/fx_buried_dest_floor_lg" ); + level._effect[ "fx_buried_dest_floor_sm" ] = loadfx( "maps/zombie_buried/fx_buried_dest_floor_sm" ); + level._effect[ "fx_buried_dest_platform_lsat" ] = loadfx( "maps/zombie_buried/fx_buried_dest_platform_lsat" ); + level._effect[ "fx_buried_fountain_spray" ] = loadfx( "maps/zombie_buried/fx_buried_fountain_spray" ); + level._effect[ "fx_buried_fountain_swirl" ] = loadfx( "maps/zombie_buried/fx_buried_fountain_swirl" ); + level._effect[ "fx_buried_meteor_sm_runner" ] = loadfx( "maps/zombie_buried/fx_buried_meteor_sm_runner" ); + level._effect[ "fx_buried_meteor_lg_runner" ] = loadfx( "maps/zombie_buried/fx_buried_meteor_lg_runner" ); +} + +precache_fxanim_props() +{ + level.scr_anim[ "fxanim_props" ][ "sheriff_sign" ] = %fxanim_zom_buried_sign_sheriff_anim; + level.scr_anim[ "fxanim_props" ][ "balcony_rope" ] = %fxanim_zom_buried_rope_balcony_anim; + level.scr_anim[ "fxanim_props" ][ "livingstone_sign" ] = %fxanim_zom_buried_sign_livingstone_anim; + level.scr_anim[ "fxanim_props" ][ "livingstone_sign_fast" ] = %fxanim_zom_buried_sign_livingstone_fast_anim; + level.scr_anim[ "fxanim_props" ][ "noose_lrg" ] = %fxanim_zom_buried_noose_lrg_anim; + level.scr_anim[ "fxanim_props" ][ "noose_med" ] = %fxanim_zom_buried_noose_med_anim; + level.scr_anim[ "fxanim_props" ][ "noose_sml" ] = %fxanim_zom_buried_noose_sml_anim; + level.scr_anim[ "fxanim_props" ][ "rope_barn" ] = %fxanim_zom_buried_rope_barn_anim; + level.scr_anim[ "fxanim_props" ][ "lsat_catwalk" ] = %fxanim_zom_buried_catwalk_anim; + level.scr_anim[ "fxanim_props" ][ "sq_orbs" ] = %fxanim_zom_buried_orbs_anim; + level.scr_anim[ "fxanim_props" ][ "endgame_machine_open" ] = %o_zombie_end_game_open; + level.scr_anim[ "fxanim_props" ][ "endgame_machine_close" ] = %o_zombie_end_game_close; + level.scr_anim[ "fxanim_props" ][ "gunsmith_sign" ] = %fxanim_zom_buried_sign_gunsmith_anim; + level.scr_anim[ "fxanim_props" ][ "corrugated_panels" ] = %fxanim_zom_buried_corrugated_panels_anim; + level.scr_anim[ "fxanim_props" ][ "clock_old" ] = %fxanim_gp_clock_old_anim; + level.scr_anim[ "fxanim_props" ][ "chandelier" ] = %fxanim_gp_chandelier_anim; + level.scr_anim[ "fxanim_props" ][ "track_board" ] = %fxanim_zom_buried_track_board_anim; + level.scr_anim[ "fxanim_props" ][ "wood_plank_hole" ] = %fxanim_zom_buried_wood_plank_hole_anim; + level.scr_anim[ "fxanim_props" ][ "wood_plank_bridge" ] = %fxanim_zom_buried_wood_plank_bridge_anim; + level.scr_anim[ "fxanim_props" ][ "drop_start" ] = %fxanim_zom_buried_board_drop_start_anim; + level.scr_anim[ "fxanim_props" ][ "rock_crusher" ] = %fxanim_zom_buried_rock_crusher_anim; + level.scr_anim[ "fxanim_props" ][ "rock_crusher_btm" ] = %fxanim_zom_buried_rock_crusher_btm_anim; + level.scr_anim[ "fxanim_props" ][ "piano_old" ] = %fxanim_gp_piano_old_anim; + level.scr_anim[ "fxanim_props" ][ "general_store_sign" ] = %fxanim_zom_buried_sign_general_store_anim; + level.scr_anim[ "fxanim_props" ][ "tree_vines" ] = %fxanim_zom_buried_tree_vines_anim; + level.scr_anim[ "fxanim_props" ][ "ice_cream_sign" ] = %fxanim_zom_buried_sign_ice_cream_anim; + level.scr_anim[ "fxanim_props" ][ "conveyor" ] = %fxanim_zom_buried_conveyor_anim; + level.scr_anim[ "fxanim_props" ][ "conveyor_lrg" ] = %fxanim_zom_buried_conveyor_lrg_anim; + level.scr_anim[ "fxanim_props" ][ "fountain_grave" ] = %fxanim_zom_buried_fountain_grave_anim; + level.scr_anim[ "fxanim_props" ][ "fountain_maze" ] = %fxanim_zom_buried_fountain_maze_anim; + level.scr_anim[ "fxanim_props" ][ "rocks_church" ] = %fxanim_zom_buried_falling_rocks_church_anim; + level.scr_anim[ "fxanim_props" ][ "rocks_graveyard" ] = %fxanim_zom_buried_falling_rocks_graveyard_anim; + level.scr_anim[ "fxanim_props" ][ "rocks_mansion" ] = %fxanim_zom_buried_falling_rocks_mansion_anim; + level.maze_switch_anim[ "switch_up" ] = %o_zombie_maze_switch_up; + level.maze_switch_anim[ "switch_down" ] = %o_zombie_maze_switch_down; + level.maze_switch_anim[ "switch_neutral" ] = %o_zombie_maze_switch_neutral; + level.scr_anim[ "fxanim_props" ][ "bank_sign" ] = %fxanim_zom_buried_sign_bank_anim; + scriptmodelsuseanimtree( -1 ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_gamemodes.gsc b/zm_buried_patch/maps/mp/zm_buried_gamemodes.gsc new file mode 100644 index 0000000..b5db71c --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_gamemodes.gsc @@ -0,0 +1,284 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zm_buried; +#include maps/mp/gametypes_zm/_zm_gametype; +#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_buried::zclassic_preinit, undefined, undefined ); + add_map_gamemode( "zcleansed", ::maps/mp/zm_buried::zcleansed_preinit, undefined, undefined ); + add_map_gamemode( "zgrief", ::maps/mp/zm_buried::zgrief_preinit, undefined, undefined ); + add_map_location_gamemode( "zclassic", "processing", ::maps/mp/zm_buried_classic::precache, ::maps/mp/zm_buried_classic::main ); + add_map_location_gamemode( "zcleansed", "street", ::maps/mp/zm_buried_turned_street::precache, ::maps/mp/zm_buried_turned_street::main ); + add_map_location_gamemode( "zgrief", "street", ::maps/mp/zm_buried_grief_street::precache, ::maps/mp/zm_buried_grief_street::main ); +} + +deletechalktriggers() +{ + chalk_triggers = getentarray( "chalk_buildable_trigger", "targetname" ); + array_thread( chalk_triggers, ::self_delete ); +} + +deletebuyabledoors() +{ + doors_trigs = getentarray( "zombie_door", "targetname" ); + _a41 = doors_trigs; + _k41 = getFirstArrayKey( _a41 ); + while ( isDefined( _k41 ) ) + { + door = _a41[ _k41 ]; + doors = getentarray( door.target, "targetname" ); + array_thread( doors, ::self_delete ); + _k41 = getNextArrayKey( _a41, _k41 ); + } + array_thread( doors_trigs, ::self_delete ); +} + +deletebuyabledebris( justtriggers ) +{ + debris_trigs = getentarray( "zombie_debris", "targetname" ); + while ( !is_true( justtriggers ) ) + { + _a56 = debris_trigs; + _k56 = getFirstArrayKey( _a56 ); + while ( isDefined( _k56 ) ) + { + trig = _a56[ _k56 ]; + if ( isDefined( trig.script_flag ) ) + { + flag_set( trig.script_flag ); + } + parts = getentarray( trig.target, "targetname" ); + array_thread( parts, ::self_delete ); + _k56 = getNextArrayKey( _a56, _k56 ); + } + } + array_thread( debris_trigs, ::self_delete ); +} + +deleteslothbarricades( justtriggers ) +{ + sloth_trigs = getentarray( "sloth_barricade", "targetname" ); + while ( !is_true( justtriggers ) ) + { + _a77 = sloth_trigs; + _k77 = getFirstArrayKey( _a77 ); + while ( isDefined( _k77 ) ) + { + trig = _a77[ _k77 ]; + if ( isDefined( trig.script_flag ) && level flag_exists( trig.script_flag ) ) + { + flag_set( trig.script_flag ); + } + parts = getentarray( trig.target, "targetname" ); + array_thread( parts, ::self_delete ); + _k77 = getNextArrayKey( _a77, _k77 ); + } + } + array_thread( sloth_trigs, ::self_delete ); +} + +deleteslothbarricade( location ) +{ + sloth_trigs = getentarray( "sloth_barricade", "targetname" ); + _a96 = sloth_trigs; + _k96 = getFirstArrayKey( _a96 ); + while ( isDefined( _k96 ) ) + { + trig = _a96[ _k96 ]; + if ( isDefined( trig.script_location ) && trig.script_location == location ) + { + if ( isDefined( trig.script_flag ) ) + { + flag_set( trig.script_flag ); + } + parts = getentarray( trig.target, "targetname" ); + array_thread( parts, ::self_delete ); + } + _k96 = getNextArrayKey( _a96, _k96 ); + } +} + +spawnmapcollision( collision_model, origin ) +{ + if ( !isDefined( origin ) ) + { + origin = ( 0, 0, 0 ); + } + collision = spawn( "script_model", origin, 1 ); + collision setmodel( collision_model ); + collision disconnectpaths(); +} + +turnperkon( perk ) +{ + level notify( perk + "_on" ); + wait_network_frame(); +} + +disableallzonesexcept( zones ) +{ + _a133 = zones; + _k133 = getFirstArrayKey( _a133 ); + while ( isDefined( _k133 ) ) + { + zone = _a133[ _k133 ]; + level thread maps/mp/zombies/_zm_zonemgr::enable_zone( zone ); + _k133 = getNextArrayKey( _a133, _k133 ); + } + _a140 = level.zones; + zoneindex = getFirstArrayKey( _a140 ); + while ( isDefined( zoneindex ) ) + { + zone = _a140[ zoneindex ]; + should_disable = 1; + _a144 = zones; + _k144 = getFirstArrayKey( _a144 ); + while ( isDefined( _k144 ) ) + { + cleared_zone = _a144[ _k144 ]; + if ( zoneindex == cleared_zone ) + { + should_disable = 0; + } + _k144 = getNextArrayKey( _a144, _k144 ); + } + if ( is_true( should_disable ) ) + { + zone.is_enabled = 0; + zone.is_spawning_allowed = 0; + } + zoneindex = getNextArrayKey( _a140, zoneindex ); + } +} + +remove_adjacent_zone( main_zone, adjacent_zone ) +{ + if ( isDefined( level.zones[ main_zone ].adjacent_zones ) && isDefined( level.zones[ main_zone ].adjacent_zones[ adjacent_zone ] ) ) + { + } + if ( isDefined( level.zones[ adjacent_zone ].adjacent_zones ) && isDefined( level.zones[ adjacent_zone ].adjacent_zones[ main_zone ] ) ) + { + } +} + +builddynamicwallbuy( location, weaponname ) +{ + match_string = ( level.scr_zm_ui_gametype + "_" ) + level.scr_zm_map_start_location; + _a177 = level.chalk_builds; + _k177 = getFirstArrayKey( _a177 ); + while ( isDefined( _k177 ) ) + { + stub = _a177[ _k177 ]; + wallbuy = getstruct( stub.target, "targetname" ); + if ( isDefined( wallbuy.script_location ) && wallbuy.script_location == location ) + { + if ( !isDefined( wallbuy.script_noteworthy ) || issubstr( wallbuy.script_noteworthy, match_string ) ) + { + maps/mp/zombies/_zm_weapons::add_dynamic_wallbuy( weaponname, wallbuy.targetname, 1 ); + thread wait_and_remove( stub, stub.buildablezone.pieces[ 0 ] ); + } + } + _k177 = getNextArrayKey( _a177, _k177 ); + } +} + +buildbuildable( buildable ) +{ + player = get_players()[ 0 ]; + _a197 = level.buildable_stubs; + _k197 = getFirstArrayKey( _a197 ); + while ( isDefined( _k197 ) ) + { + stub = _a197[ _k197 ]; + if ( !isDefined( buildable ) || stub.equipname == buildable ) + { + if ( isDefined( buildable ) || stub.persistent != 3 ) + { + stub maps/mp/zombies/_zm_buildables::buildablestub_finish_build( player ); + stub maps/mp/zombies/_zm_buildables::buildablestub_remove(); + _a206 = stub.buildablezone.pieces; + _k206 = getFirstArrayKey( _a206 ); + while ( isDefined( _k206 ) ) + { + piece = _a206[ _k206 ]; + piece maps/mp/zombies/_zm_buildables::piece_unspawn(); + _k206 = getNextArrayKey( _a206, _k206 ); + } + stub.model notsolid(); + stub.model show(); + return; + } + } + _k197 = getNextArrayKey( _a197, _k197 ); + } +} + +wait_and_remove( stub, piece ) +{ + wait 0,1; + self buildablestub_remove(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( stub ); + piece piece_unspawn(); +} + +generatebuildabletarps() +{ + struct_locations = getstructarray( "buildables_tarp", "targetname" ); + level.buildable_tarps = []; + _a234 = struct_locations; + _k234 = getFirstArrayKey( _a234 ); + while ( isDefined( _k234 ) ) + { + struct = _a234[ _k234 ]; + tarp = spawn( "script_model", struct.origin ); + tarp.angles = struct.angles; + tarp setmodel( "p6_zm_bu_buildable_bench_tarp" ); + tarp.targetname = "buildable_tarp"; + if ( isDefined( struct.script_location ) ) + { + tarp.script_location = struct.script_location; + } + level.buildable_tarps[ level.buildable_tarps.size ] = tarp; + _k234 = getNextArrayKey( _a234, _k234 ); + } +} + +deletebuildabletarp( location ) +{ + _a252 = level.buildable_tarps; + _k252 = getFirstArrayKey( _a252 ); + while ( isDefined( _k252 ) ) + { + tarp = _a252[ _k252 ]; + if ( isDefined( tarp.script_location ) && tarp.script_location == location ) + { + tarp delete(); + } + _k252 = getNextArrayKey( _a252, _k252 ); + } +} + +powerswitchstate( on ) +{ + trigger = getent( "use_elec_switch", "targetname" ); + if ( isDefined( trigger ) ) + { + trigger delete(); + } + master_switch = getent( "elec_switch", "targetname" ); + if ( isDefined( master_switch ) ) + { + master_switch notsolid(); + if ( is_true( on ) ) + { + master_switch rotateroll( -90, 0,3 ); + flag_set( "power_on" ); + } + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_grief_street.gsc b/zm_buried_patch/maps/mp/zm_buried_grief_street.gsc new file mode 100644 index 0000000..14afe47 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_grief_street.gsc @@ -0,0 +1,105 @@ +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zm_buried_buildables; +#include maps/mp/zm_buried_gamemodes; +#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_buried_street_grief" ); + precachemodel( "p6_zm_bu_buildable_bench_tarp" ); + level.chalk_buildable_pieces_hide = 1; + griefbuildables = array( "chalk", "turbine", "springpad_zm", "subwoofer_zm" ); + maps/mp/zm_buried_buildables::include_buildables( griefbuildables ); + maps/mp/zm_buried_buildables::init_buildables( griefbuildables ); + maps/mp/zombies/_zm_equip_turbine::init(); + maps/mp/zombies/_zm_equip_turbine::init_animtree(); + maps/mp/zombies/_zm_equip_springpad::init( &"ZM_BURIED_EQ_SP_PHS", &"ZM_BURIED_EQ_SP_HTS" ); + maps/mp/zombies/_zm_equip_subwoofer::init( &"ZM_BURIED_EQ_SW_PHS", &"ZM_BURIED_EQ_SW_HTS" ); +} + +street_treasure_chest_init() +{ + start_chest = getstruct( "start_chest", "script_noteworthy" ); + court_chest = getstruct( "courtroom_chest1", "script_noteworthy" ); + tunnel_chest = getstruct( "tunnels_chest1", "script_noteworthy" ); + jail_chest = getstruct( "jail_chest1", "script_noteworthy" ); + gun_chest = getstruct( "gunshop_chest", "script_noteworthy" ); + setdvar( "disableLookAtEntityLogic", 1 ); + level.chests = []; + level.chests[ level.chests.size ] = start_chest; + level.chests[ level.chests.size ] = court_chest; + level.chests[ level.chests.size ] = tunnel_chest; + level.chests[ level.chests.size ] = jail_chest; + level.chests[ level.chests.size ] = gun_chest; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "start_chest" ); +} + +main() +{ + level.buildables_built[ "pap" ] = 1; + level.equipment_team_pick_up = 1; + level thread maps/mp/zombies/_zm_buildables::think_buildables(); + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "street" ); + street_treasure_chest_init(); + generatebuildabletarps(); + deletebuildabletarp( "courthouse" ); + deletebuildabletarp( "bar" ); + deletebuildabletarp( "generalstore" ); + deleteslothbarricades(); + powerswitchstate( 1 ); + level.enemy_location_override_func = ::enemy_location_override; + spawnmapcollision( "zm_collision_buried_street_grief" ); + flag_wait( "initial_blackscreen_passed" ); + flag_wait( "start_zombie_round_logic" ); + wait 1; + builddynamicwallbuys(); + buildbuildables(); + turnperkon( "revive" ); + turnperkon( "doubletap" ); + turnperkon( "marathon" ); + turnperkon( "juggernog" ); + turnperkon( "sleight" ); + turnperkon( "additionalprimaryweapon" ); + turnperkon( "Pack_A_Punch" ); +} + +enemy_location_override( zombie, enemy ) +{ + location = enemy.origin; + if ( isDefined( self.reroute ) && self.reroute ) + { + if ( isDefined( self.reroute_origin ) ) + { + location = self.reroute_origin; + } + } + return location; +} + +builddynamicwallbuys() +{ + builddynamicwallbuy( "bank", "beretta93r_zm" ); + builddynamicwallbuy( "bar", "pdw57_zm" ); + builddynamicwallbuy( "church", "ak74u_zm" ); + builddynamicwallbuy( "courthouse", "mp5k_zm" ); + builddynamicwallbuy( "generalstore", "m16_zm" ); + builddynamicwallbuy( "mansion", "an94_zm" ); + builddynamicwallbuy( "morgue", "svu_zm" ); + builddynamicwallbuy( "prison", "claymore_zm" ); + builddynamicwallbuy( "stables", "bowie_knife_zm" ); + builddynamicwallbuy( "stablesroof", "frag_grenade_zm" ); + builddynamicwallbuy( "toystore", "tazer_knuckles_zm" ); + builddynamicwallbuy( "candyshop", "870mcs_zm" ); +} + +buildbuildables() +{ + buildbuildable( "springpad_zm" ); + buildbuildable( "subwoofer_zm" ); + buildbuildable( "turbine" ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_jail.gsc b/zm_buried_patch/maps/mp/zm_buried_jail.gsc new file mode 100644 index 0000000..60cf56b --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_jail.gsc @@ -0,0 +1,62 @@ +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +#using_animtree( "zm_buried_props" ); + +init_jail_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +init_jail_anims() +{ + level.jail_open = %o_zombie_sloth_idle_jail_2_cower_door; + level.jail_open_jumpback = %o_zombie_sloth_idle_jail_2_cower_jumpback_door; + level.jail_close_idle = %o_zombie_sloth_run_into_jail_2_idle_jail; + level.jail_close_cower = %o_zombie_sloth_cower_2_close_door; +} + +jailuseanimtree() +{ + self useanimtree( -1 ); +} + +init_jail() +{ + init_jail_anims(); + level.cell_door = getent( "sloth_cell_door", "targetname" ); + level.cell_door.clip = getent( level.cell_door.target, "targetname" ); + level.cell_door jailuseanimtree(); + level.jail_open_door = ::jail_open_door; + level.jail_close_door = ::jail_close_door; +} + +jail_open_door( jumpback ) +{ + level.cell_door playsound( "zmb_jail_door_open" ); + if ( is_true( jumpback ) ) + { + level.cell_door setanim( level.jail_open_jumpback, 1, 1, 1 ); + } + else + { + level.cell_door setanim( level.jail_open, 1, 1, 1 ); + } + if ( isDefined( level.cell_door.clip ) ) + { + level.cell_door.clip notsolid(); + level.cell_door.clip connectpaths(); + } +} + +jail_close_door() +{ + level.cell_door playsound( "zmb_jail_door_close" ); + level.cell_door setanim( level.jail_close_cower, 1, 1, 1 ); + if ( isDefined( level.cell_door.clip ) ) + { + level.cell_door.clip solid(); + level.cell_door.clip disconnectpaths(); + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_maze.gsc b/zm_buried_patch/maps/mp/zm_buried_maze.gsc new file mode 100644 index 0000000..6d02d01 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_maze.gsc @@ -0,0 +1,578 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_weap_time_bomb; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_equip_headchopper; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +maze_precache() +{ + blocker_locations = getstructarray( "maze_blocker", "targetname" ); + model_list = []; + i = 0; + while ( i < blocker_locations.size ) + { + model_list[ blocker_locations[ i ].model ] = 1; + i++; + } + model_names = getarraykeys( model_list ); + i = 0; + while ( i < model_names.size ) + { + precachemodel( model_names[ i ] ); + i++; + } +} + +maze_nodes_link_unlink_internal( func_ptr, bignorechangeonmigrate ) +{ + i = 0; + while ( i < self.blocked_nodes.size ) + { + j = 0; + while ( j < self.blocked_nodes[ i ].connected_nodes.size ) + { + [[ func_ptr ]]( self.blocked_nodes[ i ], self.blocked_nodes[ i ].connected_nodes[ j ], bignorechangeonmigrate ); + [[ func_ptr ]]( self.blocked_nodes[ i ].connected_nodes[ j ], self.blocked_nodes[ i ], bignorechangeonmigrate ); + j++; + } + i++; + } +} + +link_nodes_for_blocker_location() +{ + self maze_nodes_link_unlink_internal( ::maps/mp/zombies/_zm_utility::link_nodes, 1 ); +} + +unlink_nodes_for_blocker_location() +{ + self maze_nodes_link_unlink_internal( ::maps/mp/zombies/_zm_utility::unlink_nodes, 0 ); +} + +init_maze_clientfields() +{ + blocker_locations = getstructarray( "maze_blocker", "targetname" ); + _a77 = blocker_locations; + _k77 = getFirstArrayKey( _a77 ); + while ( isDefined( _k77 ) ) + { + blocker = _a77[ _k77 ]; + registerclientfield( "world", "maze_blocker_" + blocker.script_noteworthy, 12000, 1, "int" ); + _k77 = getNextArrayKey( _a77, _k77 ); + } +} + +init_maze_permutations() +{ + blocker_locations = getstructarray( "maze_blocker", "targetname" ); + level._maze._blocker_locations = []; + i = 0; + while ( i < blocker_locations.size ) + { + if ( isDefined( blocker_locations[ i ].target ) ) + { + blocker_locations[ i ].blocked_nodes = getnodearray( blocker_locations[ i ].target, "targetname" ); + j = 0; + while ( j < blocker_locations[ i ].blocked_nodes.size ) + { + blocker_locations[ i ].blocked_nodes[ j ].connected_nodes = getnodearray( blocker_locations[ i ].blocked_nodes[ j ].target, "targetname" ); + j++; + } + } + else blocker_locations[ i ].blocked_nodes = []; + level._maze._blocker_locations[ blocker_locations[ i ].script_noteworthy ] = blocker_locations[ i ]; + i++; + } + level._maze._perms = array( array( "blocker_1", "blocker_2", "blocker_3", "blocker_4" ), array( "blocker_5", "blocker_6", "blocker_7", "blocker_8", "blocker_9" ), array( "blocker_1", "blocker_10", "blocker_6", "blocker_4", "blocker_11" ), array( "blocker_1", "blocker_3", "blocker_4", "blocker_12" ), array( "blocker_5", "blocker_6", "blocker_12", "blocker_13" ), array( "blocker_4", "blocker_6", "blocker_14" ) ); + randomize_maze_perms(); + level._maze._active_perm_list = []; +} + +init_maze_blocker_pool() +{ + pool_size = 0; + i = 0; + while ( i < level._maze._perms.size ) + { + if ( level._maze._perms[ i ].size > pool_size ) + { + pool_size = level._maze._perms[ i ].size; + } + i++; + } + level._maze._blocker_pool = []; + i = 0; + while ( i < pool_size ) + { + ent = spawn( "script_model", level._maze.players_in_maze_volume.origin - vectorScale( ( 0, 0, 0 ), 300 ) ); + ent ghost(); + ent.in_use = 0; + level._maze._blocker_pool[ i ] = ent; + i++; + } + level._maze._blocker_pool_num_free = pool_size; +} + +free_blockers_available() +{ + return level._maze._blocker_pool_num_free > 0; +} + +get_free_blocker_model_from_pool() +{ + i = 0; + while ( i < level._maze._blocker_pool.size ) + { + if ( !level._maze._blocker_pool[ i ].in_use ) + { + level._maze._blocker_pool[ i ].in_use = 1; + level._maze._blocker_pool_num_free--; + + return level._maze._blocker_pool[ i ]; + } + i++; + } +/# + assertmsg( "zm_buried_maze : Blocker pool is empty." ); +#/ + return undefined; +} + +return_blocker_model_to_pool( ent ) +{ + ent ghost(); + ent.origin = level._maze.players_in_maze_volume.origin - vectorScale( ( 0, 0, 0 ), 300 ); + ent dontinterpolate(); + ent.in_use = 0; + level._maze._blocker_pool_num_free++; +} + +randomize_maze_perms() +{ + level._maze._perms = array_randomize( level._maze._perms ); + level._maze._cur_perm = 0; +} + +init() +{ + level._maze = spawnstruct(); + level._maze.players_in_maze_volume = getent( "maze_player_volume", "targetname" ); + level._maze.players_can_see_maze_volume = getent( "maze_player_can_see_volume", "targetname" ); + init_maze_clientfields(); + init_maze_permutations(); + init_maze_blocker_pool(); + init_hedge_maze_spawnpoints(); + register_custom_spawner_entry( "hedge_location", ::maze_do_zombie_spawn ); + level thread maze_achievement_watcher(); + level thread vo_in_maze(); +} + +maze_blocker_sinks_thread( blocker ) +{ + self waittill( "lower_" + self.script_noteworthy ); + if ( flag( "start_zombie_round_logic" ) ) + { + level setclientfield( "maze_blocker_" + self.script_noteworthy, 1 ); + } + blocker maps/mp/zombies/_zm_equip_headchopper::destroyheadchopperstouching(); + blocker moveto( self.origin - vectorScale( ( 0, 0, 0 ), 96 ), 1 ); + blocker waittill( "movedone" ); + if ( flag( "start_zombie_round_logic" ) ) + { + level setclientfield( "maze_blocker_" + self.script_noteworthy, 0 ); + } + return_blocker_model_to_pool( blocker ); + self link_nodes_for_blocker_location(); +} + +delay_destroy_corpses_near_blocker() +{ + wait 0,2; + corpses = getcorpsearray(); + while ( isDefined( corpses ) ) + { + _a247 = corpses; + _k247 = getFirstArrayKey( _a247 ); + while ( isDefined( _k247 ) ) + { + corpse = _a247[ _k247 ]; + if ( distancesquared( corpse.origin, self.origin ) < 2304 ) + { + corpse delete(); + } + _k247 = getNextArrayKey( _a247, _k247 ); + } + } +} + +maze_blocker_rises_thread() +{ + blocker = get_free_blocker_model_from_pool(); + self thread maze_blocker_sinks_thread( blocker ); + self unlink_nodes_for_blocker_location(); + blocker.origin = self.origin - vectorScale( ( 0, 0, 0 ), 96 ); + blocker.angles = self.angles; + blocker setmodel( self.model ); + blocker dontinterpolate(); + blocker show(); + wait 0,05; + if ( flag( "start_zombie_round_logic" ) ) + { + level setclientfield( "maze_blocker_" + self.script_noteworthy, 1 ); + } + blocker maps/mp/zombies/_zm_equip_headchopper::destroyheadchopperstouching(); + blocker moveto( self.origin, 0,65 ); + blocker thread delay_destroy_corpses_near_blocker(); + blocker waittill( "movedone" ); + if ( flag( "start_zombie_round_logic" ) ) + { + level setclientfield( "maze_blocker_" + self.script_noteworthy, 0 ); + } +} + +maze_do_perm_change() +{ + level._maze._cur_perm++; + if ( level._maze._cur_perm == level._maze._perms.size ) + { + randomize_maze_perms(); + } + new_perm_list = level._maze._perms[ level._maze._cur_perm ]; + blockers_raise_list = []; + blockers_lower_list = level._maze._active_perm_list; + i = 0; + while ( i < new_perm_list.size ) + { + found = 0; + j = 0; + while ( j < level._maze._active_perm_list.size ) + { + if ( new_perm_list[ i ] == level._maze._active_perm_list[ j ] ) + { + found = 1; + blockers_lower_list[ j ] = ""; + break; + } + else + { + j++; + } + } + if ( !found ) + { + blockers_raise_list[ blockers_raise_list.size ] = new_perm_list[ i ]; + } + i++; + } + level thread raise_new_perm_blockers( blockers_raise_list ); + level thread lower_old_perm_blockers( blockers_lower_list ); + level._maze._active_perm_list = level._maze._perms[ level._maze._cur_perm ]; +} + +raise_new_perm_blockers( list ) +{ + i = 0; + while ( i < list.size ) + { + while ( !free_blockers_available() ) + { + wait 0,1; + } + level._maze._blocker_locations[ list[ i ] ] thread maze_blocker_rises_thread(); + wait 0,25; + i++; + } +} + +lower_old_perm_blockers( list ) +{ + i = 0; + while ( i < list.size ) + { + if ( list[ i ] != "" ) + { + level._maze._blocker_locations[ list[ i ] ] notify( "lower_" + list[ i ] ); + } + wait 0,25; + i++; + } +} + +maze_debug_print( str ) +{ +/# + if ( getDvar( #"55B04A98" ) != "" ) + { + println( "Maze : " + str ); +#/ + } +} + +maze_can_change() +{ + players = getplayers(); + _a384 = players; + _k384 = getFirstArrayKey( _a384 ); + while ( isDefined( _k384 ) ) + { + player = _a384[ _k384 ]; + if ( player.sessionstate != "spectator" && player istouching( level._maze.players_in_maze_volume ) ) + { + maze_debug_print( "Player " + player getentitynumber() + " in maze volume. Maze cannot change." ); + return 0; + } + _k384 = getNextArrayKey( _a384, _k384 ); + } + _a398 = players; + _k398 = getFirstArrayKey( _a398 ); + while ( isDefined( _k398 ) ) + { + player = _a398[ _k398 ]; + if ( player.sessionstate != "spectator" && player istouching( level._maze.players_can_see_maze_volume ) ) + { + if ( player maps/mp/zombies/_zm_utility::is_player_looking_at( level._maze.players_in_maze_volume.origin, 0,5, 0 ) ) + { + maze_debug_print( "Player " + player getentitynumber() + " looking at maze. Maze cannot change." ); + return 0; + } + } + _k398 = getNextArrayKey( _a398, _k398 ); + } + maze_debug_print( "Maze mutating." ); + return 1; +} + +maze_think() +{ + wait 0,1; + while ( 1 ) + { + if ( maze_can_change() ) + { + maze_do_perm_change(); + level notify( "zm_buried_maze_changed" ); + } + wait 10; + } +} + +init_hedge_maze_spawnpoints() +{ + level.maze_hedge_spawnpoints = getstructarray( "custom_spawner_entry hedge_location", "script_noteworthy" ); +} + +maze_do_zombie_spawn( spot ) +{ + self endon( "death" ); + spots = level.maze_hedge_spawnpoints; + spot = undefined; +/# + assert( spots.size > 0, "No spawn locations found" ); +#/ + players_in_maze = maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_maze", 1 ); + if ( isDefined( players_in_maze ) && players_in_maze.size != 0 ) + { + player = random( players_in_maze ); + maxdistance = 256; + if ( randomint( 100 ) > 75 ) + { + maxdistance = 512; + } + closest_spots = get_array_of_closest( player.origin, spots, undefined, undefined, maxdistance ); + favoritespots = []; + _a469 = closest_spots; + _k469 = getFirstArrayKey( _a469 ); + while ( isDefined( _k469 ) ) + { + close_spot = _a469[ _k469 ]; + if ( within_fov( close_spot.origin, close_spot.angles, player.origin, -0,75 ) ) + { + favoritespots[ favoritespots.size ] = close_spot; + } + else + { + if ( randomint( 100 ) > 75 ) + { + favoritespots[ favoritespots.size ] = close_spot; + } + } + _k469 = getNextArrayKey( _a469, _k469 ); + } + if ( isDefined( favoritespots ) && favoritespots.size >= 2 ) + { + spot = random( favoritespots ); + } + else + { + if ( isDefined( closest_spots ) && closest_spots.size > 0 ) + { + spot = random( closest_spots ); + } + } + } + if ( !isDefined( spot ) ) + { + spot = random( spots ); + } + self.spawn_point = spot; + if ( isDefined( spot.target ) ) + { + self.target = spot.target; + } + if ( isDefined( spot.zone_name ) ) + { + self.zone_name = spot.zone_name; + } + if ( isDefined( spot.script_parameters ) ) + { + self.script_parameters = spot.script_parameters; + } + self thread maze_do_zombie_rise( spot ); +} + +maze_do_zombie_rise( spot ) +{ + self endon( "death" ); + self.in_the_ground = 1; + if ( isDefined( self.anchor ) ) + { + self.anchor delete(); + } + self.anchor = spawn( "script_origin", self.origin ); + self.anchor.angles = self.angles; + self linkto( self.anchor ); + if ( !isDefined( spot.angles ) ) + { + spot.angles = ( 0, 0, 0 ); + } + anim_org = spot.origin; + anim_ang = spot.angles; + anim_org += ( 0, 0, 0 ); + self ghost(); + self.anchor moveto( anim_org, 0,05 ); + self.anchor waittill( "movedone" ); + target_org = get_desired_origin(); + if ( isDefined( target_org ) ) + { + anim_ang = vectorToAngle( target_org - self.origin ); + self.anchor rotateto( ( 0, anim_ang[ 1 ], 0 ), 0,05 ); + self.anchor waittill( "rotatedone" ); + } + self unlink(); + if ( isDefined( self.anchor ) ) + { + self.anchor delete(); + } + self thread maps/mp/zombies/_zm_spawner::hide_pop(); + level thread maps/mp/zombies/_zm_spawner::zombie_rise_death( self, spot ); + spot thread maps/mp/zombies/_zm_spawner::zombie_rise_fx( self ); + substate = 0; + if ( self.zombie_move_speed == "walk" ) + { + substate = randomint( 2 ); + } + else + { + substate = 1; + } + self orientmode( "face default" ); + self animscripted( spot.origin, spot.angles, "zm_rise_hedge", substate ); + self notify( "rise_anim_finished" ); + spot notify( "stop_zombie_rise_fx" ); + self.in_the_ground = 0; + self notify( "risen" ); +} + +maze_achievement_watcher() +{ + while ( 1 ) + { + level waittill( "start_of_round" ); + start_maze_achievement_threads(); + level waittill( "end_of_round" ); + check_maze_achievement_threads(); + } +} + +start_maze_achievement_threads() +{ + while ( level.round_number >= 20 ) + { + _a607 = get_players(); + _k607 = getFirstArrayKey( _a607 ); + while ( isDefined( _k607 ) ) + { + player = _a607[ _k607 ]; + player.achievement_player_started_round_in_maze = player is_player_in_zone( "zone_maze" ); + if ( player.achievement_player_started_round_in_maze ) + { + player thread watch_player_in_maze(); + } + else + { + player notify( "_maze_achievement_think_done" ); + } + _k607 = getNextArrayKey( _a607, _k607 ); + } + } +} + +watch_player_in_maze() +{ + self notify( "_maze_achievement_think_done" ); + self endon( "_maze_achievement_think_done" ); + self endon( "death_or_disconnect" ); + self.achievement_player_stayed_in_maze_for_entire_round = 1; + while ( self.achievement_player_stayed_in_maze_for_entire_round ) + { + self.achievement_player_stayed_in_maze_for_entire_round = self is_player_in_zone( "zone_maze" ); + wait randomfloatrange( 0,5, 1 ); + } +} + +check_maze_achievement_threads() +{ + while ( level.round_number >= 20 ) + { + _a643 = get_players(); + _k643 = getFirstArrayKey( _a643 ); + while ( isDefined( _k643 ) ) + { + player = _a643[ _k643 ]; + if ( isDefined( player.achievement_player_started_round_in_maze ) && player.achievement_player_started_round_in_maze && isDefined( player.achievement_player_stayed_in_maze_for_entire_round ) && player.achievement_player_stayed_in_maze_for_entire_round && level._time_bomb.last_round_restored != ( level.round_number - 1 ) && !maps/mp/zombies/_zm_weap_time_bomb::is_time_bomb_round_change() ) + { +/# + iprintlnbold( player.name + " got achievement MAZED AND CONFUSED" ); +#/ + player notify( "player_stayed_in_maze_for_entire_high_level_round" ); + player notify( "_maze_achievement_think_done" ); + } + _k643 = getNextArrayKey( _a643, _k643 ); + } + } +} + +vo_in_maze() +{ + flag_wait( "mansion_door1" ); + nwaittime = 300; + nminwait = 5; + nmaxwait = 10; + while ( 1 ) + { + aplayersinzone = maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_maze", 1 ); + while ( !isDefined( aplayersinzone ) || aplayersinzone.size == 0 ) + { + wait randomint( nminwait, nmaxwait ); + aplayersinzone = maps/mp/zombies/_zm_zonemgr::get_players_in_zone( "zone_maze", 1 ); + } + random( aplayersinzone ) maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "in_maze" ); + nminwait = 13; + nmaxwait = 37; + wait nwaittime; + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_power.gsc b/zm_buried_patch/maps/mp/zm_buried_power.gsc new file mode 100644 index 0000000..d193288 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_power.gsc @@ -0,0 +1,37 @@ +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +electric_switch() +{ + trig = getent( "use_elec_switch", "targetname" ); + master_switch = getent( "elec_switch", "targetname" ); + master_switch notsolid(); + 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 playsound( "zmb_poweron" ); + level delay_thread( 11,8, ::sndpoweronmusicstinger ); + if ( isDefined( user ) ) + { + user thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "power", "power_on" ); + } + level thread maps/mp/zombies/_zm_perks::perk_unpause_all_perks(); + master_switch waittill( "rotatedone" ); + playfx( level._effect[ "switch_sparks" ], master_switch.origin + ( 0, 12, -60 ), anglesToForward( master_switch.angles ) ); + master_switch playsound( "zmb_turn_on" ); + level notify( "electric_door" ); + clientnotify( "power_on" ); + flag_set( "power_on" ); + level setclientfield( "zombie_power_on", 1 ); +} + +sndpoweronmusicstinger() +{ + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "poweron" ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq.gsc b/zm_buried_patch/maps/mp/zm_buried_sq.gsc new file mode 100644 index 0000000..21372a7 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq.gsc @@ -0,0 +1,1763 @@ +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zm_buried_amb; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "fxanim_props" ); +#using_animtree( "fxanim_props_dlc3" ); + +init() +{ + level thread sq_prestart_hide(); + if ( !is_sidequest_allowed( "zclassic" ) ) + { + sq_easy_cleanup(); + return; + } + sq_buried_register_visionset(); + register_map_navcard( "navcard_held_zm_buried", "navcard_held_zm_highrise" ); + ss_buttons = getentarray( "sq_ss_button", "targetname" ); + i = 0; + while ( i < ss_buttons.size ) + { + ss_buttons[ i ] usetriggerrequirelookat(); + ss_buttons[ i ] sethintstring( "" ); + ss_buttons[ i ] setcursorhint( "HINT_NOICON" ); + i++; + } + flag_init( "sq_players_out_of_sync" ); + flag_init( "sq_nav_built" ); + flag_init( "sq_is_ric_tower_built" ); + flag_init( "sq_is_max_tower_built" ); + flag_init( "sq_amplifiers_broken" ); + flag_init( "sq_wisp_success" ); + flag_init( "sq_intro_vo_done" ); + flag_init( "sq_started" ); + sq_assign_signs(); + declare_sidequest( "sq", ::init_sidequest, ::sidequest_logic, ::complete_sidequest, ::generic_stage_start, ::generic_stage_complete ); + maps/mp/zm_buried_sq_bt::init(); + maps/mp/zm_buried_sq_mta::init(); + maps/mp/zm_buried_sq_gl::init(); + maps/mp/zm_buried_sq_ftl::init(); + maps/mp/zm_buried_sq_ll::init(); + maps/mp/zm_buried_sq_ts::init(); + maps/mp/zm_buried_sq_ctw::init(); + maps/mp/zm_buried_sq_tpo::init(); + maps/mp/zm_buried_sq_ip::init(); + maps/mp/zm_buried_sq_ows::init(); + level thread init_navcard(); + level thread init_navcomputer(); + level thread navcomputer_waitfor_navcard(); + level thread sq_metagame(); + onplayerconnect_callback( ::sq_metagame_on_player_connect ); + precache_sidequest_assets(); +/# + level thread setup_sq_debug(); +#/ + level thread end_game_reward_richtofen_wrapper(); + level thread end_game_reward_maxis_wrapper(); + flag_wait( "start_zombie_round_logic" ); + sidequest_start( "sq" ); +} + +precache_sq() +{ + precachemodel( "p6_zm_bu_lantern_silver_on" ); + precachemodel( "p6_zm_bu_ether_amplifier" ); + precachemodel( "p6_zm_bu_ether_amplifier_dmg" ); + precachemodel( "p6_zm_bu_sign_tunnel_bone" ); + precachemodel( "p6_zm_bu_sign_tunnel_consumption" ); + precachemodel( "p6_zm_bu_sign_tunnel_dry" ); + precachemodel( "p6_zm_bu_sign_tunnel_ground" ); + precachemodel( "p6_zm_bu_sign_tunnel_lunger" ); + precachemodel( "p6_zm_bu_gallows" ); + precachemodel( "p6_zm_bu_guillotine" ); + precachemodel( "p6_zm_bu_end_game_machine" ); + precachemodel( "p6_zm_bu_button" ); + precachemodel( "p6_zm_bu_sign_tunnel_bone_code" ); + precachemodel( "p6_zm_bu_sign_tunnel_consump_code" ); + precachemodel( "p6_zm_bu_sign_tunnel_dry_code" ); + precachemodel( "p6_zm_bu_sign_tunnel_ground_code" ); + precachemodel( "p6_zm_bu_sign_tunnel_lunger_code" ); + precachemodel( "p6_zm_bu_maze_switch_red" ); + precachemodel( "p6_zm_bu_maze_switch_green" ); + precachemodel( "p6_zm_bu_maze_switch_blue" ); + precachemodel( "p6_zm_bu_maze_switch_yellow" ); + precachemodel( "p6_zm_bu_target" ); + precachemodel( "fxanim_zom_buried_orbs_mod" ); + precachevehicle( "heli_quadrotor2_zm" ); +} + +sq_prestart_hide() +{ +} + +sq_buried_clientfield_init() +{ + registerclientfield( "actor", "buried_sq_maxis_ending_update_eyeball_color", 12000, 1, "int" ); + registerclientfield( "scriptmover", "AmplifierShaderConstant", 12000, 5, "float" ); + registerclientfield( "scriptmover", "vulture_wisp", 12000, 1, "int" ); + registerclientfield( "world", "vulture_wisp_orb_count", 12000, 3, "int" ); + registerclientfield( "world", "sq_tpo_special_round_active", 12000, 1, "int" ); + registerclientfield( "world", "buried_sq_maxis_ending", 12000, 1, "int" ); + registerclientfield( "world", "buried_sq_richtofen_ending", 12000, 1, "int" ); + registerclientfield( "world", "sq_gl_b_vt", 12000, 1, "int" ); + registerclientfield( "world", "sq_gl_b_bb", 12000, 1, "int" ); + registerclientfield( "world", "sq_gl_b_a", 12000, 1, "int" ); + registerclientfield( "world", "sq_gl_b_ws", 12000, 1, "int" ); + registerclientfield( "world", "sq_ctw_m_t_l", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_animate", 12000, 1, "int" ); + registerclientfield( "world", "buried_sq_egm_bulb_0", 12000, 1, "int" ); + registerclientfield( "world", "buried_sq_egm_bulb_1", 12000, 1, "int" ); + registerclientfield( "world", "buried_sq_egm_bulb_2", 12000, 1, "int" ); + registerclientfield( "world", "buried_sq_egm_0_0", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_0_1", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_0_2", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_1_0", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_1_1", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_1_2", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_2_0", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_2_1", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_2_2", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_3_0", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_3_1", 12000, 2, "int" ); + registerclientfield( "world", "buried_sq_egm_3_2", 12000, 2, "int" ); + registerclientfield( "scriptmover", "buried_sq_bp_set_lightboard", 13000, 1, "int" ); + registerclientfield( "world", "buried_sq_bp_light_01", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_02", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_03", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_04", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_05", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_06", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_07", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_08", 13000, 2, "int" ); + registerclientfield( "world", "buried_sq_bp_light_09", 13000, 2, "int" ); +} + +sq_buried_register_visionset() +{ + vsmgr_register_info( "visionset", "cheat_bw", 12000, 17, 1, 1 ); +} + +sq_easy_cleanup() +{ + computer_buildable_trig = getent( "sq_common_buildable_trigger", "targetname" ); + computer_buildable_trig delete(); + sq_buildables = getentarray( "buildable_sq_common", "targetname" ); + _a194 = sq_buildables; + _k194 = getFirstArrayKey( _a194 ); + while ( isDefined( _k194 ) ) + { + item = _a194[ _k194 ]; + item delete(); + _k194 = getNextArrayKey( _a194, _k194 ); + } + t_generator = getent( "generator_use_trigger", "targetname" ); + if ( isDefined( t_generator ) ) + { + t_generator delete(); + } + gallow_col = getentarray( "gallow_col", "targetname" ); + _a206 = gallow_col; + _k206 = getFirstArrayKey( _a206 ); + while ( isDefined( _k206 ) ) + { + collmap = _a206[ _k206 ]; + collmap connectpaths(); + collmap delete(); + _k206 = getNextArrayKey( _a206, _k206 ); + } +} + +init_player_sidequest_stats() +{ + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_buried_started", 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_buried", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_buried_maxis_reset", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_buried_rich_reset", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_buried_rich_complete", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_buried_maxis_complete", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sq_buried_last_completed", 0 ); +} + +init_sidequest() +{ + sq_spawn_props(); + players = get_players(); + thread sq_refresh_player_navcard_hud(); + level.maxcompleted = 0; + level.richcompleted = 0; + level.m_sq_start_sign = undefined; + _a245 = players; + _k245 = getFirstArrayKey( _a245 ); + while ( isDefined( _k245 ) ) + { + player = _a245[ _k245 ]; + player.buried_sq_started = 1; + lastcompleted = player maps/mp/zombies/_zm_stats::get_global_stat( "sq_buried_last_completed" ); + if ( lastcompleted == 1 ) + { + level.richcompleted = 1; + } + else + { + if ( lastcompleted == 2 ) + { + level.maxcompleted = 1; + } + } + _k245 = getNextArrayKey( _a245, _k245 ); + } + level waittill( "buildables_setup" ); + if ( level.richcompleted ) + { + if ( !level.maxcompleted ) + { + playfx_on_tower( "sq_tower_bolts" ); + } + else + { + flag_set( "sq_players_out_of_sync" ); + } + playfx_on_tower( "sq_tower_r" ); + a_model_names = array( "p6_zm_bu_sq_crystal", "p6_zm_bu_sq_satellite_dish" ); + a_pieces = level.sq_rtower_buildable.buildablezone.pieces; + sq_delete_tower_pieces( a_model_names, a_pieces ); + } + if ( level.maxcompleted ) + { + if ( !level.richcompleted ) + { + playfx_on_tower( "sq_tower_bolts" ); + } + playfx_on_tower( "sq_tower_m" ); + a_model_names = array( "p6_zm_bu_sq_vaccume_tube", "p6_zm_bu_sq_buildable_battery" ); + a_pieces = level.sq_mtower_buildable.buildablezone.pieces; + sq_delete_tower_pieces( a_model_names, a_pieces ); + } +} + +sq_delete_tower_pieces( a_model_names, a_pieces ) +{ + _a301 = a_pieces; + _k301 = getFirstArrayKey( _a301 ); + while ( isDefined( _k301 ) ) + { + piece = _a301[ _k301 ]; + _a303 = a_model_names; + _k303 = getFirstArrayKey( _a303 ); + while ( isDefined( _k303 ) ) + { + str_model = _a303[ _k303 ]; + if ( piece.modelname == str_model ) + { + piece maps/mp/zombies/_zm_buildables::piece_unspawn(); + } + _k303 = getNextArrayKey( _a303, _k303 ); + } + _k301 = getNextArrayKey( _a301, _k301 ); + } +} + +sq_metagame_clear_tower_pieces() +{ + a_model_names = array( "p6_zm_bu_sq_crystal", "p6_zm_bu_sq_satellite_dish", "p6_zm_bu_sq_vaccume_tube", "p6_zm_bu_sq_buildable_battery", "p6_zm_bu_sq_antenna", "p6_zm_bu_sq_wire_spool" ); + a_pieces = level.sq_rtower_buildable.buildablezone.pieces; + sq_delete_tower_pieces( a_model_names, a_pieces ); + a_pieces = level.sq_mtower_buildable.buildablezone.pieces; + sq_delete_tower_pieces( a_model_names, a_pieces ); + players = get_players(); + _a327 = players; + _k327 = getFirstArrayKey( _a327 ); + while ( isDefined( _k327 ) ) + { + player = _a327[ _k327 ]; + piece = player maps/mp/zombies/_zm_buildables::player_get_buildable_piece( 2 ); + if ( !isDefined( piece ) ) + { + } + else + { + _a335 = a_model_names; + _k335 = getFirstArrayKey( _a335 ); + while ( isDefined( _k335 ) ) + { + str_model = _a335[ _k335 ]; + if ( piece.modelname == str_model ) + { + player maps/mp/zombies/_zm_buildables::player_destroy_piece( piece ); + } + _k335 = getNextArrayKey( _a335, _k335 ); + } + } + _k327 = getNextArrayKey( _a327, _k327 ); + } +} + +sq_spawn_props() +{ + sq_spawn_model_at_struct( "sq_guillotine", "p6_zm_bu_guillotine" ); +} + +sq_spawn_model_at_struct( str_struct, str_model ) +{ + s_struct = getstruct( str_struct, "targetname" ); + if ( !isDefined( s_struct ) ) + { + return undefined; + } + m_prop = spawn( "script_model", s_struct.origin ); + m_prop.angles = s_struct.angles; + m_prop setmodel( str_model ); + m_prop.targetname = str_struct; + return m_prop; +} + +generic_stage_start() +{ +/# + level thread cheat_complete_stage(); +#/ + level._stage_active = 1; +} + +cheat_complete_stage() +{ + level endon( "reset_sundial" ); + while ( 1 ) + { + if ( getDvar( "cheat_sq" ) != "" ) + { + if ( isDefined( level._last_stage_started ) ) + { + setdvar( "cheat_sq", "" ); + stage_completed( "sq", level._last_stage_started ); + } + } + wait 0,1; + } +} + +sidequest_logic() +{ + level thread watch_nav_computer_built(); + if ( isDefined( level.maxcompleted ) && level.maxcompleted && isDefined( level.richcompleted ) && level.richcompleted ) + { + flag_set( "sq_intro_vo_done" ); + return; + } + stage_start( "sq", "bt" ); + level waittill( "sq_bt_over" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_1" ); + stage_start( "sq", "mta" ); + level waittill( "sq_mta_over" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_2" ); + stage_start( "sq", "gl" ); + level waittill( "sq_gl_over" ); + stage_start( "sq", "ftl" ); + level waittill( "sq_ftl_over" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_3" ); + stage_start( "sq", "ll" ); + level waittill( "sq_ll_over" ); + while ( !flag( "sq_wisp_success" ) ) + { + stage_start( "sq", "ts" ); + level waittill( "sq_ts_over" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_4" ); + stage_start( "sq", "ctw" ); + level waittill( "sq_ctw_over" ); + } + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_5" ); + stage_start( "sq", "tpo" ); + level waittill( "sq_tpo_over" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_6" ); + stage_start( "sq", "ip" ); + level waittill( "sq_ip_over" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_7" ); + stage_start( "sq", "ows" ); + level waittill( "sq_ows_over" ); + delay_thread( 0,75, ::snddelayedsidequest8 ); + level notify( "buried_sidequest_achieved" ); + if ( flag( "sq_is_max_tower_built" ) ) + { + str_fx = "sq_tower_m"; + level.buried_sq_maxis_complete = 1; + level notify( "sq_maxis_complete" ); + update_sidequest_stats( "sq_buried_maxis_complete" ); + } + else + { + str_fx = "sq_tower_r"; + level.buried_sq_richtofen_complete = 1; + level notify( "sq_richtofen_complete" ); + update_sidequest_stats( "sq_buried_rich_complete" ); + } + playfx_on_tower( str_fx, 1 ); + level thread sq_give_player_rewards(); + flag_clear( "sq_started" ); + sq_metagame_reset_machine(); +} + +playfx_on_tower( str_fx, delete_old ) +{ + if ( !isDefined( delete_old ) ) + { + delete_old = 0; + } + a_fx_spots = getentarray( "sq_complete_tower_fx", "targetname" ); + while ( delete_old ) + { + _a486 = a_fx_spots; + _k486 = getFirstArrayKey( _a486 ); + while ( isDefined( _k486 ) ) + { + m_fx_spot = _a486[ _k486 ]; + m_fx_spot delete(); + _k486 = getNextArrayKey( _a486, _k486 ); + } + } + s_spot = getstruct( "sq_end_smoke", "targetname" ); + m_fx_spot = spawn( "script_model", s_spot.origin ); + m_fx_spot.angles = s_spot.angles; + m_fx_spot setmodel( "tag_origin" ); + m_fx_spot.targetname = "sq_complete_tower_fx"; + if ( delete_old ) + { + playfx( level._effect[ str_fx ], s_spot.origin, anglesToForward( s_spot.angles ) ); + } + else + { + playfxontag( level._effect[ str_fx ], m_fx_spot, "tag_origin" ); + } +} + +snddelayedsidequest8() +{ + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sidequest_8" ); +} + +sq_give_player_rewards() +{ + players = get_players(); + _a518 = players; + _k518 = getFirstArrayKey( _a518 ); + while ( isDefined( _k518 ) ) + { + player = _a518[ _k518 ]; + player thread sq_give_player_all_perks(); + _k518 = getNextArrayKey( _a518, _k518 ); + } +} + +sq_give_player_all_perks() +{ + machines = getentarray( "zombie_vending", "targetname" ); + perks = []; + i = 0; + while ( i < machines.size ) + { + if ( machines[ i ].script_noteworthy == "specialty_weapupgrade" ) + { + i++; + continue; + } + else + { + perks[ perks.size ] = machines[ i ].script_noteworthy; + } + i++; + } + _a539 = perks; + _k539 = getFirstArrayKey( _a539 ); + while ( isDefined( _k539 ) ) + { + perk = _a539[ _k539 ]; + if ( isDefined( self.perk_purchased ) && self.perk_purchased == perk ) + { + } + else + { + if ( self hasperk( perk ) || self maps/mp/zombies/_zm_perks::has_perk_paused( perk ) ) + { + break; + } + else + { + self maps/mp/zombies/_zm_perks::give_perk( perk, 0 ); + wait 0,25; + } + } + _k539 = getNextArrayKey( _a539, _k539 ); + } + self._retain_perks = 1; + self thread watch_for_respawn(); +} + +watch_for_respawn() +{ + self endon( "disconnect" ); + self waittill_either( "spawned_player", "player_revived" ); + wait_network_frame(); + self sq_give_player_all_perks(); + self setmaxhealth( level.zombie_vars[ "zombie_perk_juggernaut_health" ] ); +} + +watch_nav_computer_built() +{ + if ( isDefined( level.navcomputer_spawned ) && !level.navcomputer_spawned ) + { + wait_for_buildable( "sq_common" ); + } + flag_set( "sq_nav_built" ); + if ( isDefined( level.navcomputer_spawned ) && !level.navcomputer_spawned ) + { + update_sidequest_stats( "sq_buried_started" ); + } +} + +sq_assign_signs() +{ + a_signs = getstructarray( "sq_tunnel_sign", "targetname" ); + _a587 = a_signs; + _k587 = getFirstArrayKey( _a587 ); + while ( isDefined( _k587 ) ) + { + s_sign = _a587[ _k587 ]; + m_sign = spawn( "script_model", s_sign.origin ); + m_sign.angles = s_sign.angles; + m_sign.target = s_sign.target; + m_sign.targetname = "sq_tunnel_sign"; + m_sign setmodel( s_sign.model ); + _k587 = getNextArrayKey( _a587, _k587 ); + } + a_signs = getentarray( "sq_tunnel_sign", "targetname" ); + a_sign_keys = array_randomize( getarraykeys( a_signs ) ); + a_max_signs = array( a_signs[ a_sign_keys[ 0 ] ], a_signs[ a_sign_keys[ 1 ] ], a_signs[ a_sign_keys[ 2 ] ] ); + a_ric_signs = array( a_signs[ a_sign_keys[ 3 ] ], a_signs[ a_sign_keys[ 4 ] ], a_max_signs[ 0 ] ); + _a603 = a_max_signs; + _k603 = getFirstArrayKey( _a603 ); + while ( isDefined( _k603 ) ) + { + m_sign = _a603[ _k603 ]; + m_sign.is_max_sign = 1; + _k603 = getNextArrayKey( _a603, _k603 ); + } + _a607 = a_ric_signs; + _k607 = getFirstArrayKey( _a607 ); + while ( isDefined( _k607 ) ) + { + m_sign = _a607[ _k607 ]; + m_sign.is_ric_sign = 1; + _k607 = getNextArrayKey( _a607, _k607 ); + } +} + +generic_stage_complete() +{ + level._stage_active = 0; +} + +complete_sidequest() +{ + level thread sidequest_done(); +} + +sidequest_done() +{ +} + +init_navcard() +{ + flag_wait( "start_zombie_round_logic" ); + spawn_card = 1; + players = get_players(); + _a644 = players; + _k644 = getFirstArrayKey( _a644 ); + while ( isDefined( _k644 ) ) + { + player = _a644[ _k644 ]; + has_card = does_player_have_map_navcard( player ); + if ( has_card ) + { + player.navcard_grabbed = level.map_navcard; + spawn_card = 0; + } + _k644 = getNextArrayKey( _a644, _k644 ); + } + thread sq_refresh_player_navcard_hud(); + if ( !spawn_card ) + { + return; + } + model = "p6_zm_keycard"; + org = ( 2990, 287,75, 123,75 ); + angles = vectorScale( ( 1, 1, 0 ), 71,99 ); + 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(); + _a674 = players; + _k674 = getFirstArrayKey( _a674 ); + while ( isDefined( _k674 ) ) + { + player = _a674[ _k674 ]; + built_comptuer = player maps/mp/zombies/_zm_stats::get_global_stat( "sq_buried_started" ); + if ( !built_comptuer ) + { + spawn_navcomputer = 0; + break; + } + else + { + _k674 = getNextArrayKey( _a674, _k674 ); + } + } + 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++; + } + } +} + +navcomputer_waitfor_navcard() +{ + flag_wait( "sq_nav_built" ); + spawn_trigger = 1; + players = get_players(); + _a718 = players; + _k718 = getFirstArrayKey( _a718 ); + while ( isDefined( _k718 ) ) + { + player = _a718[ _k718 ]; + card_swiped = player maps/mp/zombies/_zm_stats::get_global_stat( "navcard_applied_zm_buried" ); + if ( card_swiped ) + { + spawn_trigger = 0; + break; + } + else + { + _k718 = getNextArrayKey( _a718, _k718 ); + } + } + if ( !spawn_trigger ) + { + return; + } + 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_buried" ); + who.navcard_grabbed = undefined; + wait 1; + navcomputer_use_trig delete(); + sq_metagame_reset_machine(); + return; + break; + } + else + { + navcomputer_use_trig sethintstring( &"ZOMBIE_NAVCARD_FAIL" ); + who playsound( "zmb_sq_navcard_fail" ); + wait 1; + navcomputer_use_trig sethintstring( &"ZOMBIE_NAVCARD_USE" ); + } + } + } +} + +update_sidequest_stats( stat_name ) +{ + maxis_complete = 0; + rich_complete = 0; + started = 0; + if ( stat_name == "sq_buried_maxis_complete" ) + { + maxis_complete = 1; + } + else + { + if ( stat_name == "sq_buried_rich_complete" ) + { + rich_complete = 1; + } + } + players = get_players(); + _a785 = players; + _k785 = getFirstArrayKey( _a785 ); + while ( isDefined( _k785 ) ) + { + player = _a785[ _k785 ]; + if ( stat_name == "sq_buried_started" ) + { + player.buried_sq_started = 1; + } + else if ( stat_name == "navcard_applied_zm_buried" ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( level.navcard_needed, 0 ); + thread sq_refresh_player_navcard_hud(); + } + else + { + if ( isDefined( player.buried_sq_started ) && !player.buried_sq_started ) + { + } + } + else + { + if ( rich_complete ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( "sq_buried_last_completed", 1 ); + incrementcounter( "global_zm_total_rich_sq_complete_buried", 1 ); + } + else + { + if ( maxis_complete ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( "sq_buried_last_completed", 2 ); + incrementcounter( "global_zm_total_max_sq_complete_buried", 1 ); + } + } + player maps/mp/zombies/_zm_stats::increment_client_stat( stat_name, 0 ); + } + _k785 = getNextArrayKey( _a785, _k785 ); + } + if ( rich_complete || maxis_complete ) + { + level notify( "buried_sidequest_achieved" ); + } +} + +sq_refresh_player_navcard_hud_internal() +{ + self endon( "disconnect" ); + navcard_bits = 0; + i = 0; + while ( i < level.navcards.size ) + { + hasit = self maps/mp/zombies/_zm_stats::get_global_stat( level.navcards[ i ] ); + if ( isDefined( self.navcard_grabbed ) && self.navcard_grabbed == level.navcards[ i ] ) + { + hasit = 1; + } + if ( hasit ) + { + navcard_bits += 1 << i; + } + i++; + } + wait_network_frame(); + self setclientfield( "navcard_held", 0 ); + if ( navcard_bits > 0 ) + { + wait_network_frame(); + self setclientfield( "navcard_held", navcard_bits ); + } +} + +sq_refresh_player_navcard_hud() +{ + if ( !isDefined( level.navcards ) ) + { + return; + } + players = get_players(); + _a854 = players; + _k854 = getFirstArrayKey( _a854 ); + while ( isDefined( _k854 ) ) + { + player = _a854[ _k854 ]; + player thread sq_refresh_player_navcard_hud_internal(); + _k854 = getNextArrayKey( _a854, _k854 ); + } +} + +richtofensay( vox_line, time, play_in_3d ) +{ + level endon( "end_game" ); + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + if ( isDefined( level.richcompleted ) && level.richcompleted && isDefined( level.metagame_sq_complete ) && !level.metagame_sq_complete ) + { + return; + } + level endon( "richtofen_c_complete" ); + if ( !isDefined( time ) ) + { + time = 2; + } + while ( isDefined( level.richtofen_talking_to_samuel ) && level.richtofen_talking_to_samuel ) + { + wait 1; + } +/# + iprintlnbold( "Richtoffen Says: " + vox_line ); +#/ + while ( isDefined( level.rich_sq_player ) && isDefined( level.rich_sq_player.isspeaking ) && level.rich_sq_player.isspeaking ) + { + wait 0,05; + } + if ( !isDefined( level.rich_sq_player ) || !is_player_valid( level.rich_sq_player ) ) + { + return; + } + if ( isDefined( level.metagame_sq_richtofen_complete ) && level.metagame_sq_richtofen_complete ) + { + stuhlingerpossessed(); + delay_thread( time, ::stuhlingerpossessed, 0 ); + } + if ( isDefined( play_in_3d ) && play_in_3d ) + { + level.rich_sq_player playsound( vox_line ); + } + else + { + 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( vox_line, m_spot_override, b_wait_for_nearby_speakers ) +{ + level endon( "end_game" ); + level endon( "intermission" ); + if ( !isDefined( level.m_maxis_vo_spot ) ) + { + s_spot = getstruct( "maxis_vo_spot", "targetname" ); + level.m_maxis_vo_spot = spawn( "script_model", s_spot.origin ); + level.m_maxis_vo_spot setmodel( "tag_origin" ); + } + if ( isDefined( level.maxcompleted ) && level.maxcompleted && isDefined( level.metagame_sq_complete ) && !level.metagame_sq_complete ) + { + return; + } + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + while ( isDefined( level.maxis_talking ) && level.maxis_talking ) + { + wait 0,05; + } + level.maxis_talking = 1; +/# + iprintlnbold( "Maxis Says: " + vox_line ); +#/ + m_vo_spot = level.m_maxis_vo_spot; + if ( isDefined( m_spot_override ) ) + { + m_vo_spot = m_spot_override; + } + while ( isDefined( b_wait_for_nearby_speakers ) && b_wait_for_nearby_speakers ) + { + nearbyplayers = get_array_of_closest( m_vo_spot.origin, get_players(), undefined, undefined, 256 ); + while ( isDefined( nearbyplayers ) && nearbyplayers.size > 0 ) + { + _a990 = nearbyplayers; + _k990 = getFirstArrayKey( _a990 ); + while ( isDefined( _k990 ) ) + { + player = _a990[ _k990 ]; + while ( isDefined( player ) && isDefined( player.isspeaking ) && player.isspeaking ) + { + wait 0,05; + } + _k990 = getNextArrayKey( _a990, _k990 ); + } + } + } + level thread maxissayvoplay( m_vo_spot, vox_line ); + level waittill( "MaxisSay_vo_finished" ); +} + +maxissayvoplay( m_vo_spot, vox_line ) +{ + m_vo_spot playsoundwithnotify( vox_line, "sound_done" + vox_line ); + m_vo_spot waittill( "sound_done" + vox_line ); + level.maxis_talking = 0; + level notify( "MaxisSay_vo_finished" ); +} + +setup_sq_debug() +{ +/# + while ( !isDefined( level.custom_devgui ) ) + { + wait 1; + } + if ( getDvarInt( #"5256118F" ) > 0 ) + { + execdevgui( "devgui_zombie_buried_sq" ); + if ( isDefined( level.custom_devgui ) ) + { + temp = level.custom_devgui; + } + level.custom_devgui = []; + level.custom_devgui[ level.custom_devgui.size ] = ::devgui_sq; + if ( isDefined( temp ) ) + { + level.custom_devgui[ level.custom_devgui.size ] = temp; + } + thread zombie_devgui_player_sq_commands(); +#/ + } +} + +zombie_devgui_player_sq_commands() +{ +/# + flag_wait( "start_zombie_round_logic" ); + wait 1; + players = get_players(); + level.sq_players = players; + i = 0; + while ( i < players.size ) + { + ip1 = i + 1; + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Transit:1/Held" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_TRANSIT; set zombie_devgui nc_on" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Transit:1/Not Held" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_TRANSIT; set zombie_devgui nc_off" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Transit:1/Applied" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_TRANSIT; set zombie_devgui nc_app" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Transit:1/Not Applied" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_TRANSIT; set zombie_devgui nc_napp" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Transit:1/None:0" "set dg_sq_player " + ip1 + "; set dg_sq_map TRANSIT; set zombie_devgui comp_0" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Transit:1/Maxis:1" "set dg_sq_player " + ip1 + "; set dg_sq_map TRANSIT; set zombie_devgui comp_2" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Transit:1/Ricky:2" "set dg_sq_player " + ip1 + "; set dg_sq_map TRANSIT; set zombie_devgui comp_1" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Highrise:2/Held" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_HIGHRISE; set zombie_devgui nc_on" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Highrise:2/Not Held" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_HIGHRISE; set zombie_devgui nc_off" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Highrise:2/Applied" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_HIGHRISE; set zombie_devgui nc_app" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Highrise:2/Not Applied" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_HIGHRISE; set zombie_devgui nc_napp" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Highrise:2/None:0" "set dg_sq_player " + ip1 + "; set dg_sq_map HIGHRISE; set zombie_devgui comp_0" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Highrise:2/Maxis:1" "set dg_sq_player " + ip1 + "; set dg_sq_map HIGHRISE; set zombie_devgui comp_2" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Highrise:2/Ricky:2" "set dg_sq_player " + ip1 + "; set dg_sq_map HIGHRISE; set zombie_devgui comp_1" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Buried:3/Held" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_BURIED; set zombie_devgui nc_on" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Buried:3/Not Held" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_BURIED; set zombie_devgui nc_off" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Buried:3/Applied" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_BURIED; set zombie_devgui nc_app" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Navcard:1/Buried:3/NotApplied" "set dg_sq_player " + ip1 + "; set dg_sq_map ZM_BURIED; set zombie_devgui nc_napp" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Buried:3/None:0" "set dg_sq_player " + ip1 + "; set dg_sq_map BURIED; set zombie_devgui comp_0" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Buried:3/Maxis:1" "set dg_sq_player " + ip1 + "; set dg_sq_map BURIED; set zombie_devgui comp_2" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Buried/SQ:1/Players:1/" + players[ i ].name + "/Completed:2/Buried:3/Ricky:2" "set dg_sq_player " + ip1 + "; set dg_sq_map BURIED; set zombie_devgui comp_1" \n" ); + i++; +#/ + } +} + +devgui_sq( cmd ) +{ +/# + cmd_strings = strtok( cmd, " " ); + b_found_entry = 1; + switch( cmd_strings[ 0 ] ) + { + case "sq_tpo_warp": + warp_to_struct_position( "sq_debug_warp_tpo" ); + break; + case "sq_tpo_give_item": + level notify( "sq_tpo_give_item" ); + break; + case "sq_set_maxis": + set_side_maxis(); + break; + case "sq_set_richtofen": + set_side_richtofen(); + break; + case "sq_ts_quicktest": + set_sq_ts_quickset(); + break; + case "sq_ows_start": + set_sq_ows_start(); + break; + case "sq_ll_show_code": + set_sq_ll_show_code(); + break; + case "sq_ending_richtofen": + level notify( "end_game_reward_starts_richtofen" ); + break; + case "sq_ending_maxis": + level notify( "end_game_reward_starts_maxis" ); + break; + case "sq_complete_current": + stage_completed( "sq", level._last_stage_started ); + break; + case "comp_0": + case "comp_1": + case "comp_2": + case "nc_app": + case "nc_napp": + case "nc_off": + case "nc_on": + pindex = getDvarInt( #"DAD9AAFF" ); + if ( !isDefined( pindex ) || pindex < 1 ) + { + pindex = 1; + } + sq_player = level.sq_players[ pindex - 1 ]; + sq_level = getDvar( #"2685E710" ); + sq_set_stat( sq_player, sq_level, cmd_strings[ 0 ] ); + break; + case "sq_start_stage_bt": + case "sq_start_stage_ftl": + case "sq_start_stage_gl": + case "sq_start_stage_ip": + case "sq_start_stage_ll": + case "sq_start_stage_mta": + case "sq_start_stage_ows": + case "sq_start_stage_tpo": + case "sq_start_stage_ts": + skip_to_sq_stage( cmd_strings[ 0 ] ); + break; + default: + b_found_entry = 0; + break; + } + return b_found_entry; +#/ +} + +sq_set_stat( sq_player, sq_level, sq_cmd ) +{ +/# + switch( sq_cmd ) + { + case "nc_on": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "NAVCARD_HELD_" + sq_level, 1 ); + break; + case "nc_off": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "NAVCARD_HELD_" + sq_level, 0 ); + break; + case "nc_app": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "NAVCARD_APPLIED_" + sq_level, 1 ); + break; + case "nc_napp": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "NAVCARD_APPLIED_" + sq_level, 0 ); + break; + case "comp_0": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "SQ_" + sq_level + "_LAST_COMPLETED", 0 ); + break; + case "comp_1": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "SQ_" + sq_level + "_LAST_COMPLETED", 1 ); + break; + case "comp_2": + sq_player maps/mp/zombies/_zm_stats::set_global_stat( "SQ_" + sq_level + "_LAST_COMPLETED", 2 ); + break; + } +#/ +} + +warp_to_struct_position( str_value, str_key ) +{ + if ( !isDefined( str_key ) ) + { + str_key = "targetname"; + } + a_warp_structs = getstructarray( str_value, str_key ); + a_players = get_players(); +/# + assert( a_warp_structs.size > a_players.size, "warp_to_struct_position found more players than structs for '" + str_key + "' = '" + str_value + "'! Add more structs to fix this" ); +#/ + i = 0; + while ( i < a_players.size ) + { + a_players[ i ] setorigin( a_warp_structs[ i ].origin ); + a_players[ i ] setplayerangles( a_warp_structs[ i ].angles ); + i++; + } +} + +set_side_richtofen() +{ + flag_set( "sq_is_ric_tower_built" ); + flag_clear( "sq_is_max_tower_built" ); +} + +set_side_maxis() +{ + flag_set( "sq_is_max_tower_built" ); + flag_clear( "sq_is_ric_tower_built" ); +} + +set_sq_ts_quickset() +{ + flag_set( "sq_ts_quicktest" ); +} + +set_sq_ows_start() +{ + flag_set( "sq_ows_start" ); +} + +set_sq_ll_show_code() +{ + maps/mp/zm_buried_sq_ll::sq_ll_show_code(); +} + +sq_debug_print_vo( str_vo ) +{ + temp_str = "" + str_vo; +/# + iprintln( temp_str ); +#/ + a_words = strtok( str_vo, " " ); + n_wait = a_words.size * 0,25; + wait n_wait; +} + +sq_metagame() +{ + level endon( "sq_metagame_player_connected" ); + flag_wait( "sq_intro_vo_done" ); + if ( flag( "sq_started" ) ) + { + level waittill( "buried_sidequest_achieved" ); + } + level thread sq_metagame_turn_off_watcher(); + is_blue_on = 0; + is_orange_on = 0; + m_endgame_machine = getstruct( "sq_endgame_machine", "targetname" ); + a_tags = []; + a_tags[ 0 ][ 0 ] = "TAG_LIGHT_1"; + a_tags[ 0 ][ 1 ] = "TAG_LIGHT_2"; + a_tags[ 0 ][ 2 ] = "TAG_LIGHT_3"; + a_tags[ 1 ][ 0 ] = "TAG_LIGHT_4"; + a_tags[ 1 ][ 1 ] = "TAG_LIGHT_5"; + a_tags[ 1 ][ 2 ] = "TAG_LIGHT_6"; + a_tags[ 2 ][ 0 ] = "TAG_LIGHT_7"; + a_tags[ 2 ][ 1 ] = "TAG_LIGHT_8"; + a_tags[ 2 ][ 2 ] = "TAG_LIGHT_9"; + a_tags[ 3 ][ 0 ] = "TAG_LIGHT_10"; + a_tags[ 3 ][ 1 ] = "TAG_LIGHT_11"; + a_tags[ 3 ][ 2 ] = "TAG_LIGHT_12"; + a_stat = []; + a_stat[ 0 ] = "sq_transit_last_completed"; + a_stat[ 1 ] = "sq_highrise_last_completed"; + a_stat[ 2 ] = "sq_buried_last_completed"; + a_stat_nav = []; + a_stat_nav[ 0 ] = "navcard_applied_zm_transit"; + a_stat_nav[ 1 ] = "navcard_applied_zm_highrise"; + a_stat_nav[ 2 ] = "navcard_applied_zm_buried"; + a_stat_nav_held = []; + a_stat_nav_held[ 0 ] = "navcard_applied_zm_transit"; + a_stat_nav_held[ 1 ] = "navcard_applied_zm_highrise"; + a_stat_nav_held[ 2 ] = "navcard_applied_zm_buried"; + bulb_on = []; + bulb_on[ 0 ] = 0; + bulb_on[ 1 ] = 0; + bulb_on[ 2 ] = 0; + level.n_metagame_machine_lights_on = 0; + flag_wait( "start_zombie_round_logic" ); + sq_metagame_clear_lights(); + players = get_players(); + player_count = players.size; +/# + if ( getDvarInt( "zombie_cheat" ) >= 1 ) + { + player_count = 4; +#/ + } + n_player = 0; + while ( n_player < player_count ) + { + n_stat = 0; + while ( n_stat < a_stat.size ) + { + if ( isDefined( players[ n_player ] ) ) + { + n_stat_value = players[ n_player ] maps/mp/zombies/_zm_stats::get_global_stat( a_stat[ n_stat ] ); + n_stat_nav_value = players[ n_player ] maps/mp/zombies/_zm_stats::get_global_stat( a_stat_nav[ n_stat ] ); + } +/# + if ( getDvarInt( "zombie_cheat" ) >= 1 ) + { + n_stat_value = getDvarInt( "zombie_cheat" ); + n_stat_nav_value = getDvarInt( "zombie_cheat" ); +#/ + } + if ( n_stat_value == 1 ) + { + m_endgame_machine sq_metagame_machine_set_light( n_player, n_stat, "sq_bulb_blue" ); + is_blue_on = 1; + } + else + { + if ( n_stat_value == 2 ) + { + m_endgame_machine sq_metagame_machine_set_light( n_player, n_stat, "sq_bulb_orange" ); + is_orange_on = 1; + } + } + if ( n_stat_nav_value ) + { + level setclientfield( "buried_sq_egm_bulb_" + n_stat, 1 ); + bulb_on[ n_stat ] = 1; + } + n_stat++; + } + n_player++; + } + if ( level.n_metagame_machine_lights_on == 12 ) + { + if ( is_blue_on && is_orange_on ) + { + return; + } + else + { + if ( bulb_on[ 0 ] || !bulb_on[ 1 ] && !bulb_on[ 2 ] ) + { + return; + } + } + } + else + { + return; + } + m_endgame_machine.activate_trig = spawn( "trigger_radius", m_endgame_machine.origin, 0, 128, 72 ); + m_endgame_machine.activate_trig waittill( "trigger" ); + m_endgame_machine.activate_trig delete(); + m_endgame_machine.activate_trig = undefined; + level setclientfield( "buried_sq_egm_animate", 1 ); + m_endgame_machine.endgame_trig = spawn( "trigger_radius_use", m_endgame_machine.origin, 0, 16, 16 ); + m_endgame_machine.endgame_trig setcursorhint( "HINT_NOICON" ); + m_endgame_machine.endgame_trig sethintstring( &"ZM_BURIED_SQ_EGM_BUT" ); + m_endgame_machine.endgame_trig triggerignoreteam(); + m_endgame_machine.endgame_trig usetriggerrequirelookat(); + m_endgame_machine.endgame_trig waittill( "trigger" ); + m_endgame_machine.endgame_trig delete(); + m_endgame_machine.endgame_trig = undefined; + level thread sq_metagame_clear_tower_pieces(); + playsoundatposition( "zmb_endgame_mach_button", m_endgame_machine.origin ); + players = get_players(); + _a1405 = players; + _k1405 = getFirstArrayKey( _a1405 ); + while ( isDefined( _k1405 ) ) + { + player = _a1405[ _k1405 ]; + i = 0; + while ( i < a_stat.size ) + { + player maps/mp/zombies/_zm_stats::set_global_stat( a_stat[ i ], 0 ); + player maps/mp/zombies/_zm_stats::set_global_stat( a_stat_nav_held[ i ], 0 ); + player maps/mp/zombies/_zm_stats::set_global_stat( a_stat_nav[ i ], 0 ); + i++; + } + _k1405 = getNextArrayKey( _a1405, _k1405 ); + } + sq_metagame_clear_lights(); + if ( is_orange_on ) + { + level notify( "end_game_reward_starts_maxis" ); + } + else + { + level notify( "end_game_reward_starts_richtofen" ); + } +} + +sq_metagame_clear_lights() +{ + level setclientfield( "buried_sq_egm_animate", 0 ); + level setclientfield( "buried_sq_egm_bulb_0", 0 ); + level setclientfield( "buried_sq_egm_bulb_1", 0 ); + level setclientfield( "buried_sq_egm_bulb_2", 0 ); + level setclientfield( "buried_sq_egm_0_0", 0 ); + level setclientfield( "buried_sq_egm_0_1", 0 ); + level setclientfield( "buried_sq_egm_0_2", 0 ); + level setclientfield( "buried_sq_egm_1_0", 0 ); + level setclientfield( "buried_sq_egm_1_1", 0 ); + level setclientfield( "buried_sq_egm_1_2", 0 ); + level setclientfield( "buried_sq_egm_2_0", 0 ); + level setclientfield( "buried_sq_egm_2_1", 0 ); + level setclientfield( "buried_sq_egm_2_2", 0 ); + level setclientfield( "buried_sq_egm_3_0", 0 ); + level setclientfield( "buried_sq_egm_3_1", 0 ); + level setclientfield( "buried_sq_egm_3_2", 0 ); +} + +sq_metagame_on_player_connect() +{ + sq_metagame_reset_machine(); +} + +sq_metagame_turn_off_watcher() +{ + flag_wait( "sq_started" ); + sq_metagame_clear_lights(); + sq_metagame_reset_machine(); +} + +sq_metagame_reset_machine() +{ + level notify( "sq_metagame_player_connected" ); + m_endgame_machine = getstruct( "sq_endgame_machine", "targetname" ); + if ( isDefined( m_endgame_machine.activate_trig ) ) + { + m_endgame_machine.activate_trig delete(); + m_endgame_machine.activate_trig = undefined; + } + if ( isDefined( m_endgame_machine.endgame_trig ) ) + { + m_endgame_machine.endgame_trig delete(); + m_endgame_machine.endgame_trig = undefined; + } + level thread sq_metagame(); +} + +sq_metagame_machine_set_light( n_player, n_stat, str_fx ) +{ + level.n_metagame_machine_lights_on++; + fxcolorbit = 1; + if ( str_fx == "sq_bulb_orange" ) + { + fxcolorbit = 2; + } + level setclientfield( "buried_sq_egm_" + n_player + "_" + n_stat, fxcolorbit ); +} + +stuhlingerpossessed( bool ) +{ + if ( !isDefined( level.rich_sq_player ) ) + { + return; + } + if ( !isDefined( bool ) || bool ) + { +/# + println( "Stuhlinger Possessed" ); +#/ + level.rich_sq_player setclientfield( "buried_sq_richtofen_player_eyes_stuhlinger", 1 ); + } + else + { +/# + println( "Stuhlinger Freed From Possessed" ); +#/ + level.rich_sq_player setclientfield( "buried_sq_richtofen_player_eyes_stuhlinger", 0 ); + } +} + +reward_maxis_vo() +{ + m_endgame_machine = getstruct( "sq_endgame_machine", "targetname" ); + m_endgame_machine_ent = spawn( "script_origin", m_endgame_machine.origin ); + maxissay( "vox_maxi_end_game_maxis_wins_0", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_maxis_wins_1", m_endgame_machine_ent ); + maxissay( "vox_maxi_end_game_maxis_wins_2", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_maxis_wins_3", m_endgame_machine_ent ); + maxissay( "vox_maxi_end_game_maxis_wins_4", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_maxis_wins_5", m_endgame_machine_ent ); + maxissay( "vox_maxi_end_game_maxis_wins_6", m_endgame_machine_ent ); + m_endgame_machine_ent delete(); +} + +reward_richtofen_vo() +{ + m_endgame_machine = getstruct( "sq_endgame_machine", "targetname" ); + m_endgame_machine_ent = spawn( "script_origin", m_endgame_machine.origin ); + maxissay( "vox_zmba_end_game_richtofen_wins_0", m_endgame_machine_ent ); + maxissay( "vox_maxi_end_game_richtofen_wins_1", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_richtofen_wins_2", m_endgame_machine_ent ); + maxissay( "vox_maxi_end_game_richtofen_wins_3", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_richtofen_wins_4", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_richtofen_wins_5", m_endgame_machine_ent ); + maxissay( "vox_maxi_end_game_richtofen_wins_6", m_endgame_machine_ent ); + maxissay( "vox_zmba_end_game_richtofen_wins_7", m_endgame_machine_ent ); + m_endgame_machine_ent delete(); +} + +vo_stuhlingerpossessed() +{ + play_in_3d = 1; + richtofensay( "vox_zmba_stuhlinger_1st_possession_1_0", 10, play_in_3d ); + wait 2; + richtofensay( "vox_zmba_stuhlinger_1st_possession_2_0", 12, play_in_3d ); + wait 3; + richtofensay( "vox_zmba_stuhlinger_1st_possession_3_0", 7, play_in_3d ); + wait 4; + richtofensay( "vox_zmba_stuhlinger_1st_possession_4_0", 5, play_in_3d ); + wait 3; + if ( isDefined( level.rich_sq_player ) ) + { + while ( isDefined( level.rich_sq_player ) && isDefined( level.rich_sq_player.isspeaking ) && level.rich_sq_player.isspeaking ) + { + wait 1; + } + richtofensay( "vox_plr_1_stuhlinger_2nd_possession_1_0", 4, !play_in_3d ); + } + wait 4; + richtofensay( "vox_zmba_stuhlinger_2nd_possession_2_0", 8, play_in_3d ); + wait 2; + richtofensay( "vox_zmba_stuhlinger_2nd_possession_3_0", 12, play_in_3d ); + wait 1; + richtofensay( "vox_zmba_stuhlinger_2nd_possession_5_0", 9, play_in_3d ); + noldvo = -1; + while ( 1 ) + { + wait randomintrange( 120, 480 ); + nvo = randomintrange( 1, 8 ); + while ( noldvo == nvo ) + { + nvo = randomintrange( 1, 8 ); + } + noldvo = nvo; + switch( nvo ) + { + case 1: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_1_0", 5, play_in_3d ); + break; + continue; + case 2: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_2_0", 7, play_in_3d ); + break; + continue; + case 3: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_3_0", 9, play_in_3d ); + break; + continue; + case 4: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_4_0", 12, play_in_3d ); + break; + continue; + case 5: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_5_0", 7, play_in_3d ); + break; + continue; + case 6: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_6_0", 8, play_in_3d ); + break; + continue; + case 7: + richtofensay( "vox_zmba_stuhlinger_3rd_possession_7_0", 8, play_in_3d ); + break; + continue; + } + } +} + +end_game_reward_richtofen_wrapper() +{ + level waittill( "end_game_reward_starts_richtofen" ); + level.metagame_sq_complete = 1; + level.metagame_sq_richtofen_complete = 1; + end_game_reward_richtofen(); +} + +end_game_reward_richtofen() +{ + if ( isDefined( level.rich_sq_player ) ) + { + level.rich_sq_player.dontspeak = 1; + } + meteors_stop_falling(); + run_richtofen_earthquake(); + level thread maps/mp/zm_buried_amb::sndmusicquestendgame( "mus_richtofens_delight", 98 ); + wait 2; + reward_richtofen_vo(); + level thread vo_stuhlingerpossessed(); + mule_kick_allows_4_weapons(); + permanent_fire_sale(); +} + +run_richtofen_earthquake() +{ + level setclientfield( "buried_sq_richtofen_ending", 1 ); + wait 12; +} + +meteors_stop_falling() +{ + stop_exploder( 666 ); +} + +mule_kick_allows_4_weapons() +{ + _a1697 = get_players(); + _k1697 = getFirstArrayKey( _a1697 ); + while ( isDefined( _k1697 ) ) + { + player = _a1697[ _k1697 ]; + if ( !isDefined( player._retain_perks_array ) ) + { + player._retain_perks_array = []; + } + if ( !player hasperk( "specialty_additionalprimaryweapon" ) ) + { + player maps/mp/zombies/_zm_perks::give_perk( "specialty_additionalprimaryweapon", 0 ); + } + player._retain_perks_array[ "specialty_additionalprimaryweapon" ] = 1; + _k1697 = getNextArrayKey( _a1697, _k1697 ); + } + level.additionalprimaryweapon_limit = 4; +} + +permanent_fire_sale() +{ + level.zombie_vars[ "zombie_powerup_fire_sale_on" ] = 1; + level thread maps/mp/zombies/_zm_powerups::toggle_fire_sale_on(); + level.disable_firesale_drop = 1; + wait 1; + level notify( "powerup fire sale" ); + level notify( "firesale_over" ); +} + +end_game_reward_maxis_wrapper() +{ + level waittill( "end_game_reward_starts_maxis" ); + level setclientfield( "buried_sq_maxis_eye_glow_override", 1 ); + level.metagame_sq_complete = 1; + level.metagame_sq_maxis_complete = 1; + end_game_reward_maxis(); +} + +end_game_reward_maxis() +{ + run_maxis_earthquake(); + level.allowzmbannouncer = 0; + level.zmb_laugh_alias = "zmb_laugh_child"; + level.sndfiresalemusoff = 1; + level thread maps/mp/zm_buried_amb::sndmusicquestendgame( "mus_samanthas_desire", 98 ); + wait 2; + reward_maxis_vo(); + setup_richtofen_possessed_zombies(); +} + +setup_richtofen_possessed_zombies() +{ + level._sq_m_possessed_zombie_vo = array( "vox_zmba_zombie_possession_1_0", "vox_zmba_zombie_possession_3_0", "vox_zmba_zombie_possession_4_0", "vox_zmba_zombie_possession_6_0", "vox_zmba_zombie_possession_8_0", "vox_zmba_zombie_possession_9_0", "vox_zmba_zombie_possession_10_0", "vox_zmba_zombie_possession_11_0", "vox_zmba_zombie_possession_12_0", "vox_zmba_zombie_possession_13_0" ); + maps/mp/zombies/_zm_spawner::add_cusom_zombie_spawn_logic( ::sq_maxis_ending_spawn_func ); +} + +run_maxis_earthquake() +{ + level setclientfield( "buried_sq_maxis_ending", 1 ); +} + +sq_maxis_ending_spawn_func() +{ + if ( isDefined( self.is_ghost ) && self.is_ghost ) + { + return; + } + if ( can_spawn_richtofen_zombie() ) + { + self make_richtofen_zombie(); + } +} + +can_spawn_richtofen_zombie() +{ + if ( !isDefined( level.sq_richtofen_zombie ) ) + { + level.sq_richtofen_zombie = spawnstruct(); + level.sq_richtofen_zombie.spawned = 0; + level.sq_richtofen_zombie.last_killed_time = 0; + } + b_richtofen_zombie_active = level.sq_richtofen_zombie.spawned; + b_cooldown_up = ( ( getTime() - level.sq_richtofen_zombie.last_killed_time ) * 0,001 ) > 30; + if ( !b_richtofen_zombie_active ) + { + b_can_spawn_richtofen_zombie = b_cooldown_up; + } + return b_can_spawn_richtofen_zombie; +} + +make_richtofen_zombie() +{ + self endon( "death" ); + level.sq_richtofen_zombie.spawned = 1; + self setclientfield( "buried_sq_maxis_ending_update_eyeball_color", 1 ); + self thread richtofen_zombie_watch_death(); + self waittill( "completed_emerging_into_playable_area" ); + self thread richtofen_zombie_vo_watcher(); + self.deathfunction_old = self.deathfunction; + self.deathfunction = ::richtofen_zombie_deathfunction_override; +} + +richtofen_zombie_deathfunction_override() +{ + if ( isDefined( self.turning_into_ghost ) && !self.turning_into_ghost ) + { + self force_random_powerup_drop(); + if ( isDefined( self.attacker ) ) + { + self.attacker maps/mp/zombies/_zm_score::add_to_player_score( 500 ); + } + } + return self [[ self.deathfunction_old ]](); +} + +force_random_powerup_drop() +{ + self.no_powerups = 1; + level maps/mp/zombies/_zm_powerups::specific_powerup_drop( maps/mp/zombies/_zm_powerups::get_valid_powerup(), self.origin ); +} + +richtofen_zombie_vo_watcher() +{ + self endon( "death" ); + players = get_players(); + can_see = 0; + while ( !can_see ) + { + wait 2; + _a1850 = players; + _k1850 = getFirstArrayKey( _a1850 ); + while ( isDefined( _k1850 ) ) + { + player = _a1850[ _k1850 ]; + if ( distance2dsquared( self.origin, player.origin ) < 262144 && sighttracepassed( self gettagorigin( "tag_eye" ), player.origin, 0, undefined ) ) + { + can_see = 1; + } + _k1850 = getNextArrayKey( _a1850, _k1850 ); + } + } + str_vox = randomint( level._sq_m_possessed_zombie_vo.size ); + self playsound( level._sq_m_possessed_zombie_vo[ str_vox ] ); +} + +richtofen_zombie_watch_death() +{ + while ( isDefined( self ) && isalive( self ) ) + { +/# + if ( getDvarInt( #"5256118F" ) > 0 ) + { + debugstar( self.origin, 5, ( 1, 1, 0 ) ); +#/ + } + wait 0,25; + } + richtofen_zombie_clear(); +} + +richtofen_zombie_clear() +{ + level.sq_richtofen_zombie.last_killed_time = getTime(); + level.sq_richtofen_zombie.spawned = 0; +} + +skip_to_sq_stage( str_cmd ) +{ + str_stage_name = getsubstr( str_cmd, 15 ); + a_stages = get_sq_stages_in_order(); + _a1897 = a_stages; + _k1897 = getFirstArrayKey( _a1897 ); + while ( isDefined( _k1897 ) ) + { + str_stage = _a1897[ _k1897 ]; + if ( str_stage == str_stage_name ) + { + break; + } + else + { + if ( str_stage == "ctw" ) + { + flag_set( "sq_wisp_success" ); + wait_network_frame(); + } + level notify( "sq_" + str_stage + "_over" ); + stage_completed( "sq", str_stage ); + wait_network_frame(); + _k1897 = getNextArrayKey( _a1897, _k1897 ); + } + } + if ( level._zombie_sidequests[ "sq" ].stages[ str_stage_name ].completed ) + { + stage_start( "sq", str_stage_name ); + } +} + +get_sq_stages_in_order() +{ + a_keys = getarraykeys( level._zombie_sidequests[ "sq" ].stages ); + a_stages_ordered = []; + i = 0; + while ( i < a_keys.size ) + { + j = 0; + while ( j < a_keys.size ) + { + if ( level._zombie_sidequests[ "sq" ].stages[ a_keys[ j ] ].stage_number == i ) + { + a_stages_ordered[ a_stages_ordered.size ] = a_keys[ j ]; + i++; + continue; + } + else + { + j++; + } + } + i++; + } + return a_stages_ordered; +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_bt.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_bt.gsc new file mode 100644 index 0000000..949a2fa --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_bt.gsc @@ -0,0 +1,208 @@ +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + declare_sidequest_stage( "sq", "bt", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + flag_init( "sq_player_underground" ); + level thread stage_vo(); + level thread stage_start_watcher(); + level._cur_stage_name = "bt"; + clientnotify( "bt" ); +} + +stage_vo() +{ + level waittill( "start_of_round" ); + level thread stage_vo_watch_underground(); + wait 5; + maxissay( "vox_maxi_sidequest_maxis_start_1_0" ); + maxissay( "vox_maxi_sidequest_maxis_start_2_0" ); + maxissay( "vox_maxi_sidequest_maxis_start_3_0" ); + maxissay( "vox_maxi_sidequest_maxis_start_4_0" ); + maxissay( "vox_maxi_sidequest_maxis_start_5_0" ); + flag_wait( "sq_player_underground" ); + level.m_maxis_vo_spot.origin = ( -728, -344, 280 ); + while ( isDefined( level.vo_player_who_discovered_stables_roof ) && is_true( level.vo_player_who_discovered_stables_roof.isspeaking ) ) + { + wait 0,05; + } + maxissay( "vox_maxi_sidequest_town_0" ); + maxissay( "vox_maxi_sidequest_town_1" ); + wait 1; + level thread stage_vo_watch_gallows(); + if ( !level.richcompleted ) + { + if ( isDefined( level.rich_sq_player ) ) + { + level.rich_sq_player.dontspeak = 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 1 ); + } + richtofensay( "vox_zmba_sidequest_zmba_start_1_0", 3 ); + if ( isDefined( level.rich_sq_player ) ) + { + while ( isDefined( level.rich_sq_player ) || is_true( level.rich_sq_player.isspeaking ) && is_true( level.rich_sq_player.dontspeak ) ) + { + wait 1; + } + level.rich_sq_player.dontspeak = 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 1 ); + level.rich_sq_player playsoundwithnotify( "vox_plr_1_respond_richtofen_0", "sound_done_vox_plr_1_respond_richtofen_0" ); + level.rich_sq_player waittill( "sound_done_vox_plr_1_respond_richtofen_0" ); + wait 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 0 ); + } + richtofensay( "vox_zmba_sidequest_zmba_start_3_0", 4 ); + if ( isDefined( level.rich_sq_player ) ) + { + while ( isDefined( level.rich_sq_player ) || is_true( level.rich_sq_player.isspeaking ) && is_true( level.rich_sq_player.dontspeak ) ) + { + wait 1; + } + level.rich_sq_player.dontspeak = 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 1 ); + level.rich_sq_player playsoundwithnotify( "vox_plr_1_respond_richtofen_1", "sound_done_vox_plr_1_respond_richtofen_1" ); + level.rich_sq_player waittill( "sound_done_vox_plr_1_respond_richtofen_1" ); + wait 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 0 ); + } + richtofensay( "vox_zmba_sidequest_zmba_start_5_0", 12 ); + richtofensay( "vox_zmba_sidequest_zmba_start_6_0", 8 ); + if ( isDefined( level.rich_sq_player ) ) + { + while ( isDefined( level.rich_sq_player ) || is_true( level.rich_sq_player.isspeaking ) && is_true( level.rich_sq_player.dontspeak ) ) + { + wait 1; + } + level.rich_sq_player.dontspeak = 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 1 ); + level.rich_sq_player playsoundwithnotify( "vox_plr_1_respond_richtofen_2", "sound_done_vox_plr_1_respond_richtofen_2" ); + level.rich_sq_player waittill( "sound_done_vox_plr_1_respond_richtofen_2" ); + wait 1; + level.rich_sq_player setclientfieldtoplayer( "isspeaking", 0 ); + } + richtofensay( "vox_zmba_sidequest_town_0", 6 ); + richtofensay( "vox_zmba_sidequest_town_1", 6 ); + } + flag_set( "sq_intro_vo_done" ); + level thread stage_vo_nag(); + level thread stage_vo_watch_guillotine(); +} + +stage_vo_nag() +{ + level endon( "sq_is_max_tower_built" ); + level endon( "sq_is_ric_tower_built" ); + level endon( "end_game_reward_starts_maxis" ); + level endon( "end_game_reward_starts_richtofen" ); + s_struct = getstruct( "sq_gallows", "targetname" ); + m_maxis_vo_spot = spawn( "script_model", s_struct.origin ); + m_maxis_vo_spot setmodel( "tag_origin" ); + i = 0; + while ( i < 5 ) + { + level waittill( "end_of_round" ); + maxissay( "vox_maxi_sidequest_nag_" + i, m_maxis_vo_spot ); + richtofensay( "vox_zmba_sidequest_nag_" + i, 10 ); + i++; + } +} + +stage_vo_watch_guillotine() +{ + level endon( "sq_bt_over" ); + level endon( "end_game_reward_starts_maxis" ); + level endon( "end_game_reward_starts_richtofen" ); + s_struct = getstruct( "sq_guillotine", "targetname" ); + trigger = spawn( "trigger_radius", s_struct.origin, 0, 128, 72 ); + trigger waittill( "trigger" ); + trigger delete(); + richtofensay( "vox_zmba_sidequest_gallows_0", 9 ); + richtofensay( "vox_zmba_sidequest_gallows_1", 12 ); + level waittill( "rtower_object_planted" ); + richtofensay( "vox_zmba_sidequest_parts_0", 9 ); + level waittill( "rtower_object_planted" ); + richtofensay( "vox_zmba_sidequest_parts_1", 3 ); + level waittill( "rtower_object_planted" ); + richtofensay( "vox_zmba_sidequest_parts_2", 5 ); + level waittill( "rtower_object_planted" ); + richtofensay( "vox_zmba_sidequest_parts_3", 11 ); +} + +stage_vo_watch_gallows() +{ + level endon( "sq_bt_over" ); + level endon( "end_game_reward_starts_maxis" ); + level endon( "end_game_reward_starts_richtofen" ); + s_struct = getstruct( "sq_gallows", "targetname" ); + trigger = spawn( "trigger_radius", s_struct.origin, 0, 128, 72 ); + trigger waittill( "trigger" ); + trigger delete(); + m_maxis_vo_spot = spawn( "script_model", s_struct.origin ); + m_maxis_vo_spot setmodel( "tag_origin" ); + if ( flag( "sq_intro_vo_done" ) ) + { + maxissay( "vox_maxi_sidequest_gallows_0", m_maxis_vo_spot ); + } + i = 0; + while ( i < 4 ) + { + level waittill( "mtower_object_planted" ); + if ( flag( "sq_intro_vo_done" ) ) + { + maxissay( "vox_maxi_sidequest_parts_" + i, m_maxis_vo_spot, 1 ); + } + wait_network_frame(); + i++; + } + m_maxis_vo_spot delete(); +} + +stage_vo_watch_underground() +{ + trigger_wait( "sq_player_underground", "targetname" ); + flag_set( "sq_player_underground" ); +} + +stage_start_watcher() +{ + level waittill_either( "mtower_object_planted", "rtower_object_planted" ); + flag_set( "sq_started" ); +} + +stage_logic() +{ +/# + iprintlnbold( "BT Started" ); +#/ + level thread wait_for_maxis_tower(); + level thread wait_for_richtofen_tower(); + flag_wait_any( "sq_is_max_tower_built", "sq_is_ric_tower_built" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +wait_for_maxis_tower() +{ + level endon( "sq_is_ric_tower_built" ); + wait_for_buildable( "buried_sq_bt_m_tower" ); + flag_set( "sq_is_max_tower_built" ); +} + +wait_for_richtofen_tower() +{ + level endon( "sq_is_max_tower_built" ); + wait_for_buildable( "buried_sq_bt_r_tower" ); + flag_set( "sq_is_ric_tower_built" ); +} + +exit_stage( success ) +{ +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_ctw.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_ctw.gsc new file mode 100644 index 0000000..aa5a403 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_ctw.gsc @@ -0,0 +1,428 @@ +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "sq_wisp_failed" ); + flag_init( "sq_m_wisp_weak" ); + level.sq_ctw_m_tubes_lit = 0; + declare_sidequest_stage( "sq", "ctw", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + flag_clear( "sq_wisp_failed" ); + level._cur_stage_name = "ctw"; + clientnotify( "ctw" ); +} + +stage_logic() +{ +/# + iprintlnbold( "CTW Started" ); +#/ + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread stage_vo_max(); + ctw_max_start_wisp(); + } + else + { + level thread stage_vo_ric(); + ctw_ric_start_wisp(); + } + flag_wait_any( "sq_wisp_success", "sq_wisp_failed" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +stage_vo_max() +{ + level endon( "sq_wisp_failed" ); + while ( !isDefined( level.vh_wisp ) ) + { + wait 1; + } + level.vh_wisp endon( "delete" ); + maxissay( "vox_maxi_sidequest_ctw_0", level.e_sq_sign_attacker ); + maxissay( "vox_maxi_sidequest_ctw_1", level.e_sq_sign_attacker ); + wait 15; + maxissay( "vox_maxis_sidequest_ctw_4", level.e_sq_sign_attacker ); +} + +stage_vo_ric() +{ + level endon( "sq_wisp_failed" ); + richtofensay( "vox_zmba_sidequest_ctw_0", 12 ); + richtofensay( "vox_zmba_sidequest_ctw_1", 8 ); + level waittill( "sq_ctw_zombie_powered_up" ); + richtofensay( "vox_zmba_sidequest_ctw_3", 8 ); +} + +wisp_move_from_sign_to_start( s_start ) +{ + self.origin = level.m_sq_start_sign.origin - vectorScale( ( 1, 0, 0 ), 20 ); + self moveto( s_start.origin, 2, 0,5, 0,5 ); + self waittill( "movedone" ); + wait 1; +} + +ctw_ric_start_wisp() +{ + if ( !isDefined( level.m_sq_start_sign ) ) + { + return; + } + s_start = getstruct( level.m_sq_start_sign.target, "targetname" ); + m_wisp = getent( "sq_wisp", "targetname" ); + m_wisp setclientfield( "vulture_wisp", 1 ); + m_wisp wisp_move_from_sign_to_start( s_start ); + m_wisp thread ctw_ric_move_wisp( s_start ); +} + +ctw_ric_move_wisp( s_current ) +{ + self endon( "ctw_wisp_timeout" ); + self setclientfield( "vulture_wisp", 0 ); + self.origin = s_current.origin; + wait_network_frame(); + self setclientfield( "vulture_wisp", 1 ); + self thread ctw_ric_watch_wisp_timeout(); + ctw_ric_watch_wisp_dist(); + s_current = ctw_ric_get_next_wisp_struct( s_current ); + self endon( "ctw_wisp_moved" ); + self ctw_ric_power_towers(); + flag_set( "sq_wisp_success" ); +} + +ctw_ric_get_next_wisp_struct( s_current ) +{ + if ( !isDefined( s_current.target ) ) + { + return undefined; + } + a_structs = getstructarray( s_current.target, "targetname" ); + return array_randomize( a_structs )[ 0 ]; +} + +ctw_ric_watch_wisp_timeout() +{ + self endon( "ctw_wisp_moved" ); + wait 12; + flag_set( "sq_wisp_failed" ); + self setclientfield( "vulture_wisp", 0 ); + self notify( "ctw_wisp_timeout" ); +} + +ctw_ric_watch_wisp_dist( s_current ) +{ + self endon( "ctw_wisp_timeout" ); + is_near_wisp = 0; + while ( !is_near_wisp ) + { + players = getplayers(); + _a185 = players; + _k185 = getFirstArrayKey( _a185 ); + while ( isDefined( _k185 ) ) + { + player = _a185[ _k185 ]; + if ( !player hasperk( "specialty_nomotionsensor" ) ) + { + } + else + { + if ( distancesquared( player.origin, self.origin ) < 4096 ) + { + is_near_wisp = 1; + } + } + _k185 = getNextArrayKey( _a185, _k185 ); + } + wait 0,1; + } + self notify( "ctw_wisp_moved" ); +} + +ctw_ric_power_towers() +{ + m_tower = getent( "sq_guillotine", "targetname" ); + level setclientfield( "vulture_wisp_orb_count", 1 ); + wait_network_frame(); + level setclientfield( "vulture_wisp_orb_count", 0 ); + wait 2; + v_guillotine_spot = self.origin; + self.origin = m_tower gettagorigin( "j_crystal_01" ); + m_tower thread ctw_ric_guillotine_glow( v_guillotine_spot ); + i = 0; + while ( i < 5 ) + { + wait 3; + e_powered_zombie = undefined; + while ( !isDefined( e_powered_zombie ) ) + { + wait 1; + a_zombies = ctw_find_zombies_for_powerup( self.origin, 512, m_tower ); + e_powered_zombie = array_randomize( a_zombies )[ 0 ]; + } + level notify( "stop_ctw_ric_guillotine_glow" ); + e_powered_zombie ctw_power_up_ric_zombie( m_tower.m_glow ); + e_powered_zombie waittill( "death" ); + level setclientfield( "vulture_wisp_orb_count", i + 1 ); + m_tower ctw_return_wisp_to_guillotine( v_guillotine_spot, e_powered_zombie.origin ); + i++; + } +} + +ctw_ric_guillotine_glow( v_spot ) +{ + level endon( "stop_ctw_ric_guillotine_glow" ); + if ( !isDefined( self.m_glow ) ) + { + self.m_glow = spawn( "script_model", v_spot ); + self.m_glow setmodel( "tag_origin" ); + } + while ( 1 ) + { + playfxontag( level._effect[ "vulture_fx_wisp" ], self.m_glow, "tag_origin" ); + wait 0,25; + self.m_glow playloopsound( "zmb_sq_wisp_loop_guillotine" ); + } +} + +ctw_power_up_ric_zombie( m_wisp ) +{ + wait_network_frame(); + v_to_zombie = vectornormalize( self gettagorigin( "J_SpineLower" ) - m_wisp.origin ); + v_move_spot = m_wisp.origin + ( v_to_zombie * 32 ); + m_wisp.origin = v_move_spot; + self ctw_power_up_zombie(); +} + +ctw_return_wisp_to_guillotine( v_spot, v_start ) +{ + self.m_glow.origin = v_start; + self thread ctw_ric_guillotine_glow( v_start ); + wait_network_frame(); + v_to_tower = vectornormalize( v_spot - self.m_glow.origin ); + v_move_spot = self.m_glow.origin + ( v_to_tower * 32 ); + self.m_glow.origin = v_move_spot; + self.m_glow.origin = v_spot; +} + +ctw_max_start_wisp() +{ + nd_start = getvehiclenode( level.m_sq_start_sign.target, "targetname" ); + vh_wisp = spawnvehicle( "tag_origin", "wisp_ai", "heli_quadrotor2_zm", nd_start.origin, nd_start.angles ); + vh_wisp makevehicleunusable(); + level.vh_wisp = vh_wisp; + vh_wisp.n_sq_max_energy = 30; + vh_wisp.n_sq_energy = vh_wisp.n_sq_max_energy; + vh_wisp thread ctw_max_wisp_play_fx(); + vh_wisp_mover = spawn( "script_model", vh_wisp.origin ); + vh_wisp_mover setmodel( "tag_origin" ); + vh_wisp linkto( vh_wisp_mover ); + vh_wisp_mover wisp_move_from_sign_to_start( nd_start ); + vh_wisp unlink(); + vh_wisp_mover delete(); + vh_wisp attachpath( nd_start ); + vh_wisp startpath(); + vh_wisp thread ctw_max_success_watch(); + vh_wisp thread ctw_max_fail_watch(); + vh_wisp thread ctw_max_wisp_enery_watch(); + wait_network_frame(); + flag_wait_any( "sq_wisp_success", "sq_wisp_failed" ); + vh_wisp cancelaimove(); + vh_wisp clearvehgoalpos(); + vh_wisp delete(); + if ( isDefined( level.vh_wisp ) ) + { + level.vh_wisp delete(); + } +} + +ctw_max_wisp_play_fx() +{ + self playloopsound( "zmb_sq_wisp_loop" ); + while ( isDefined( self ) ) + { + playfxontag( level._effect[ "fx_wisp_m" ], self, "tag_origin" ); + if ( !flag( "sq_m_wisp_weak" ) ) + { + playfxontag( level._effect[ "fx_wisp_lg_m" ], self, "tag_origin" ); + } + wait 0,3; + } +} + +ctw_max_success_watch() +{ + self endon( "death" ); + self waittill( "reached_end_node" ); +/# + iprintlnbold( "Wisp Success!" ); +#/ + flag_set( "sq_wisp_success" ); + level thread ctw_light_tube(); +} + +ctw_light_tube() +{ + level.sq_ctw_m_tubes_lit++; + level setclientfield( "sq_ctw_m_t_l", level.sq_ctw_m_tubes_lit ); +} + +ctw_max_fail_watch() +{ + self endon( "death" ); + wait 1; + n_starter_dist = distancesquared( self.origin, level.e_sq_sign_attacker.origin ); + a_players = getplayers(); + _a382 = a_players; + _k382 = getFirstArrayKey( _a382 ); + while ( isDefined( _k382 ) ) + { + player = _a382[ _k382 ]; + if ( distancesquared( self.origin, player.origin ) < 16384 ) + { +/# + iprintlnbold( "Too Close to Wisp" ); +#/ + } + _k382 = getNextArrayKey( _a382, _k382 ); + } + a_zombies = ctw_find_zombies_for_powerup( self.origin, 256 ); + array_thread( a_zombies, ::ctw_power_up_zombie ); + if ( a_zombies.size ) + { + self.n_sq_energy += 10; + if ( self.n_sq_energy > 30 ) + { + self.n_sq_energy = 30; + } + } + else + { + self.n_sq_energy--; + + } + if ( self.n_sq_energy <= 15 && !flag( "sq_m_wisp_weak" ) ) + { + flag_set( "sq_m_wisp_weak" ); + } + else + { + if ( self.n_sq_energy > 15 && flag( "sq_m_wisp_weak" ) ) + { + flag_clear( "sq_m_wisp_weak" ); + } + } +/# + iprintlnbold( self.n_sq_energy ); +#/ + level thread ctw_max_fail_vo(); + flag_set( "sq_wisp_failed" ); +} + +ctw_max_fail_vo() +{ + maxissay( "vox_maxi_sidequest_ctw_8", level.e_sq_sign_attacker ); +} + +ctw_max_wisp_enery_watch() +{ + self endon( "death" ); + while ( 1 ) + { + if ( self.n_sq_energy <= 0 ) + { + flag_set( "sq_wisp_failed" ); + } + wait 1; + } +} + +debug_origin() +{ +/# + self endon( "death" ); + while ( 1 ) + { + debugstar( self.origin, 1, ( 1, 0, 0 ) ); + wait 0,05; +#/ + } +} + +ctw_find_zombies_for_powerup( v_origin, n_radius, m_ignore ) +{ + if ( !isDefined( m_ignore ) ) + { + m_ignore = undefined; + } + a_zombies = getaispeciesarray( level.zombie_team, "zombie" ); + n_radius_sq = n_radius * n_radius; + a_near_zombies = []; + _a473 = a_zombies; + _k473 = getFirstArrayKey( _a473 ); + while ( isDefined( _k473 ) ) + { + e_zombie = _a473[ _k473 ]; + if ( distancesquared( e_zombie.origin, v_origin ) < n_radius_sq && !isDefined( e_zombie.sq_wisp_powered ) ) + { + if ( sighttracepassed( v_origin, e_zombie gettagorigin( "J_SpineLower" ), 1, m_ignore ) ) + { + a_near_zombies[ a_near_zombies.size ] = e_zombie; + } + } + _k473 = getNextArrayKey( _a473, _k473 ); + } + return a_near_zombies; +} + +ctw_power_up_zombie() +{ + level notify( "sq_ctw_zombie_powered_up" ); + self.sq_wisp_powered = 1; + n_oldhealth = self.maxhealth; + self.maxhealth *= 2; + if ( self.maxhealth < n_oldhealth ) + { + self.maxhealth = n_oldhealth; + } + self.health = self.maxhealth; + if ( self.zombie_move_speed != "sprint" ) + { + self set_zombie_run_cycle( "sprint" ); + self.zombie_move_speed_original = self.zombie_move_speed; + } + if ( flag( "sq_is_max_tower_built" ) ) + { + str_fx = "fx_wisp_m"; + } + else + { + str_fx = "vulture_fx_wisp"; + } + self thread ctw_power_up_zombie_m_fx( str_fx ); +} + +ctw_power_up_zombie_m_fx( str_fx ) +{ + self endon( "delete" ); + self endon( "death" ); + while ( isDefined( self ) && isalive( self ) ) + { + playfxontag( level._effect[ str_fx ], self, "J_Wrist_RI" ); + wait 0,25; + playfxontag( level._effect[ str_fx ], self, "J_Wrist_LE" ); + wait 0,25; + self playloopsound( "zmb_sq_wisp_possess" ); + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_ftl.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_ftl.gsc new file mode 100644 index 0000000..308a46a --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_ftl.gsc @@ -0,0 +1,216 @@ +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zm_buried_sq_ftl; +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "ftl_lantern_charged" ); + declare_sidequest_stage( "sq", "ftl", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + level.sq_ftl_lantern_fuel = 0; + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread stage_vo_max(); + } + else + { + level thread stage_vo_ric(); + } + level._cur_stage_name = "ftl"; + clientnotify( "ftl" ); +} + +stage_logic() +{ +/# + iprintlnbold( "FTL Started" ); +#/ + if ( flag( "sq_is_max_tower_built" ) ) + { + max_fill_lantern_watcher(); + } + else + { + ric_fill_lantern_watcher(); + } + flag_wait( "ftl_lantern_charged" ); + if ( flag( "sq_is_max_tower_built" ) ) + { + thread stage_vo_filled_max(); + } + else + { + thread stage_vo_filled_ric(); + } + sq_ftl_show_marker(); + wait_for_buildable( "buried_sq_oillamp" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +stage_vo_max() +{ + sq_ftl_maxis_vo_on_holder( "vox_maxi_sidequest_pl_0" ); + sq_ftl_maxis_vo_on_holder( "vox_maxi_sidequest_pl_1" ); + sq_ftl_maxis_vo_on_holder( "vox_maxi_sidequest_pl_3" ); + level waittill( "sq_ftl_lantern_inc" ); + sq_ftl_maxis_vo_on_holder( "vox_maxi_sidequest_pl_2" ); +} + +sq_ftl_maxis_vo_on_holder( str_vox ) +{ + player = sq_ftl_get_lantern_holder(); + if ( isDefined( player ) ) + { + maxissay( str_vox, player ); + } +} + +sq_ftl_show_marker() +{ + m_marker = getent( "sq_lantern_symbol", "targetname" ); + m_marker.origin += vectorScale( ( 0, 0, 1 ), 2 ); + level.sq_lamp_generator_unitrig.origin = level.sq_lamp_generator_unitrig.realorigin; +} + +sq_ftl_get_lantern_holder() +{ + players = get_players(); + _a107 = players; + _k107 = getFirstArrayKey( _a107 ); + while ( isDefined( _k107 ) ) + { + player = _a107[ _k107 ]; + if ( isDefined( player player_get_buildable_piece( 2 ) ) && isDefined( player player_get_buildable_piece( 2 ).buildablename == "sq_ghost_lamp" ) ) + { + return player; + } + _k107 = getNextArrayKey( _a107, _k107 ); + } +} + +stage_vo_filled_max() +{ + maps/mp/zm_buried_sq_ftl::sq_ftl_maxis_vo_on_holder( "vox_maxi_sidequest_ll_0" ); +} + +stage_vo_ric() +{ + richtofensay( "vox_zmba_sidequest_pl_0", 12 ); + level waittill( "sq_ftl_lantern_inc" ); + richtofensay( "vox_zmba_sidequest_pl_1", 6 ); +} + +stage_vo_filled_ric() +{ + richtofensay( "vox_zmba_sidequest_ll_0", 10 ); + richtofensay( "vox_zmba_sidequest_ll_1", 7 ); +} + +max_fill_lantern_watcher() +{ + a_zombies = getaispeciesarray( level.zombie_team, "zombie" ); + array_thread( a_zombies, ::max_lantern_zombie_death_watcher ); + maps/mp/zombies/_zm_spawner::add_custom_zombie_spawn_logic( ::max_lantern_zombie_death_watcher ); +} + +max_lantern_zombie_death_watcher() +{ + level endon( "ftl_lantern_charged" ); + if ( flag( "ftl_lantern_charged" ) ) + { + return; + } + self waittill( "death", attacker ); + if ( !isDefined( attacker ) || isplayer( attacker ) ) + { + return; + } + players = getplayers(); + _a164 = players; + _k164 = getFirstArrayKey( _a164 ); + while ( isDefined( _k164 ) ) + { + player = _a164[ _k164 ]; + if ( isDefined( player player_get_buildable_piece( 2 ) ) && isDefined( player player_get_buildable_piece( 2 ).buildablename == "sq_ghost_lamp" ) ) + { + if ( isDefined( self ) && distancesquared( player.origin, self.origin ) < 65536 ) + { + player ftl_lantern_increment(); + } + } + _k164 = getNextArrayKey( _a164, _k164 ); + } +} + +ric_fill_lantern_watcher() +{ + a_axis = getaiarray( "axis" ); + a_ghost = []; + _a183 = a_axis; + _k183 = getFirstArrayKey( _a183 ); + while ( isDefined( _k183 ) ) + { + e_axis = _a183[ _k183 ]; + if ( is_true( e_axis.is_ghost ) ) + { + a_ghost[ a_ghost.size ] = e_axis; + } + _k183 = getNextArrayKey( _a183, _k183 ); + } + array_thread( a_ghost, ::ric_lantern_ghost_death_watcher ); + a_ghost_spawners = getspawnerarray( "ghost_zombie_spawner", "script_noteworthy" ); + array_thread( a_ghost_spawners, ::add_spawn_function, ::ric_lantern_ghost_death_watcher ); +} + +ric_lantern_ghost_death_watcher() +{ + level endon( "ftl_lantern_charged" ); + if ( flag( "ftl_lantern_charged" ) ) + { + return; + } + self waittill( "death", attacker ); + players = getplayers(); + _a210 = players; + _k210 = getFirstArrayKey( _a210 ); + while ( isDefined( _k210 ) ) + { + player = _a210[ _k210 ]; + if ( isDefined( player player_get_buildable_piece( 2 ) ) && isDefined( player player_get_buildable_piece( 2 ).buildablename == "sq_ghost_lamp" ) ) + { + if ( isDefined( self ) && distancesquared( player.origin, self.origin ) < 65536 ) + { + player ftl_lantern_increment(); + } + } + _k210 = getNextArrayKey( _a210, _k210 ); + } +} + +ftl_lantern_increment() +{ + level.sq_ftl_lantern_fuel++; + level notify( "sq_ftl_lantern_inc" ); + self playsound( "zmb_lantern_fill_" + level.sq_ftl_lantern_fuel ); +/# + iprintlnbold( "Fuel Level: " + level.sq_ftl_lantern_fuel ); +#/ + if ( level.sq_ftl_lantern_fuel >= 10 ) + { + self playsound( "zmb_lantern_fill_done" ); + flag_set( "ftl_lantern_charged" ); + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_gl.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_gl.gsc new file mode 100644 index 0000000..5054f1e --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_gl.gsc @@ -0,0 +1,257 @@ +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "sq_gl_lantern_aquired" ); + declare_sidequest_stage( "sq", "gl", ::init_stage, ::stage_logic, ::exit_stage ); + level thread sq_gl_setup_buildable_trig(); +} + +sq_gl_setup_buildable_trig() +{ + while ( !isDefined( level.sq_lamp_generator_unitrig ) ) + { + wait 1; + } + level.sq_lamp_generator_unitrig.realorigin = level.sq_lamp_generator_unitrig.origin; + level.sq_lamp_generator_unitrig.origin += vectorScale( ( 0, 0, 1 ), 10000 ); +} + +init_stage() +{ + s_start = getstruct( "sq_ghost_lamp_start", "script_noteworthy" ); + gl_lantern_spawn( s_start ); + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread stage_vo_max(); + } + else + { + level thread stage_vo_ric(); + } + level._cur_stage_name = "gl"; + clientnotify( "gl" ); +} + +stage_logic() +{ +/# + iprintlnbold( "GL Started" ); +#/ + s_start = getstruct( "sq_ghost_lamp_start", "script_noteworthy" ); + gl_lantern_move( s_start ); + flag_wait( "sq_gl_lantern_aquired" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +stage_vo_max() +{ + level waittill( "lantern_crashing" ); + maxissay( "vox_maxi_sidequest_gl_2", level.vh_lantern ); +} + +stage_vo_ric() +{ + richtofensay( "vox_zmba_sidequest_gl_0", 8 ); + level waittill( "lantern_crashing" ); + richtofensay( "vox_zmba_sidequest_gl_1", 6 ); +} + +gl_lantern_spawn( s_start ) +{ + level.vh_lantern = spawnvehicle( "tag_origin", "ghost_lantern_ai", "heli_quadrotor2_zm", s_start.origin, ( 0, 0, 1 ) ); + level.vh_lantern makevehicleunusable(); + level.vh_lantern setneargoalnotifydist( 128 ); + level.vh_lantern.m_lantern = spawn( "script_model", level.vh_lantern.origin ); + level.vh_lantern.m_lantern setmodel( "p6_zm_bu_lantern_silver_on" ); + level.vh_lantern.m_lantern linkto( level.vh_lantern, "tag_origin" ); + playfxontag( level._effect[ "sq_glow" ], level.vh_lantern.m_lantern, "tag_origin" ); + level.vh_lantern.m_lantern playsound( "zmb_sq_glantern_impact" ); + level.vh_lantern.m_lantern playloopsound( "zmb_sq_glantern_full_loop_3d" ); + level.vh_lantern thread gl_lantern_damage_watcher(); + wait_network_frame(); +} + +gl_lantern_delete() +{ + if ( isDefined( level.vh_lantern ) ) + { + if ( isDefined( level.vh_lantern.m_lantern ) ) + { + level.vh_lantern.m_lantern delete(); + } + if ( isDefined( level.vh_lantern.t_pickup ) ) + { + level.vh_lantern.t_pickup delete(); + } + level.vh_lantern cancelaimove(); + level.vh_lantern clearvehgoalpos(); + if ( isDefined( level.vh_lantern.m_link ) ) + { + level.vh_lantern.m_link delete(); + } + level.vh_lantern delete(); + } +} + +gl_lantern_move( s_current ) +{ + level endon( "lantern_crashing" ); + while ( 1 ) + { + s_current = gl_lantern_get_next_struct( s_current ); + if ( flag( "sq_is_max_tower_built" ) ) + { + if ( randomint( 100 ) < 50 ) + { + s_current = level.vh_lantern gl_lantern_teleport(); + } + } + level.vh_lantern gl_lantern_move_to_struct( s_current ); + } +} + +gl_lantern_get_next_struct( s_current ) +{ + a_struct_links = []; + a_target_structs = getstructarray( s_current.target, "targetname" ); + while ( isDefined( s_current.script_string ) ) + { + a_names = strtok( s_current.script_string, " " ); + _a171 = a_names; + _k171 = getFirstArrayKey( _a171 ); + while ( isDefined( _k171 ) ) + { + str_name = _a171[ _k171 ]; + a_new_structs = getstructarray( str_name, "targetname" ); + a_target_structs = arraycombine( a_target_structs, a_new_structs, 0, 0 ); + _k171 = getNextArrayKey( _a171, _k171 ); + } + } + return array_randomize( a_target_structs )[ 0 ]; +} + +gl_lantern_move_to_struct( s_goto ) +{ + self endon( "death" ); + self endon( "delete" ); + self setvehgoalpos( s_goto.origin, 1 ); + self pathvariableoffset( vectorScale( ( 0, 0, 1 ), 128 ), 1 ); + self waittill_either( "goal", "near_goal" ); +} + +gl_lantern_teleport() +{ + self notify( "lantern_teleporting" ); + playfx( level._effect[ "fx_wisp_lg_m" ], self.origin ); + playsoundatposition( "zmb_sq_glantern_impact", self.origin ); + gl_lantern_delete(); + a_path_spots = getstructarray( "sq_ghost_lamp_path", "script_noteworthy" ); + s_teleport_spot = array_randomize( a_path_spots )[ 0 ]; + gl_lantern_spawn( s_teleport_spot ); + return s_teleport_spot; +} + +gl_lantern_damage_watcher() +{ + self.m_lantern endon( "delete" ); + self.m_lantern setcandamage( 1 ); + while ( 1 ) + { + self.m_lantern waittill( "damage", amount, attacker, dir, point, dmg_type ); + if ( dmg_type == "MOD_GRENADE" || dmg_type == "MOD_GRENADE_SPLASH" ) + { + break; + } + else + { + } + } + self.m_lantern playsound( "zmb_sq_glantern_impact" ); + self gl_lantern_crash_movement(); + self thread gl_lantern_pickup_watch(); + self thread gl_lantern_stop_spin_on_land(); + level thread gl_lantern_respawn_wait(); + level waittill( "gl_lantern_respawn" ); + if ( isDefined( self.m_lantern ) ) + { + s_start_spot = gl_lantern_teleport(); + gl_lantern_move( s_start_spot ); + } +} + +gl_lantern_stop_spin_on_land() +{ + self endon( "delete" ); + while ( isDefined( self ) && length( self.velocity ) > 3 ) + { + wait 0,1; + } + if ( isDefined( self ) ) + { + self.m_link = spawn( "script_model", self.origin ); + self.m_link setmodel( "tag_origin" ); + self linkto( self.m_link ); + } +} + +gl_lantern_respawn_wait() +{ + wait 30; + level notify( "gl_lantern_respawn" ); +} + +gl_lantern_pickup_watch() +{ + self endon( "lantern_teleporting" ); + self.t_pickup = spawn( "trigger_radius_use", self.origin, 0, 48, 32 ); + self.t_pickup setcursorhint( "HINT_NOICON" ); + self.t_pickup sethintstring( &"ZM_BURIED_SQ_LANTERN_G" ); + self.t_pickup triggerignoreteam(); + self.t_pickup enablelinkto(); + self.t_pickup linkto( self ); + self.t_pickup waittill( "trigger", player ); + player player_take_piece( level.zombie_buildables[ "buried_sq_oillamp" ].buildablepieces[ 0 ] ); + piece = player player_get_buildable_piece( 2 ); + if ( isDefined( piece ) ) + { + piece.sq_is_ghost_lamp = 1; + piece.start_origin = vectorScale( ( 0, 0, 1 ), 512 ); + piece.start_angles = ( 0, 0, 1 ); + } + self.t_pickup delete(); + self.m_lantern delete(); + self delete(); + flag_set( "sq_gl_lantern_aquired" ); +} + +gl_lantern_crash_movement() +{ + level notify( "lantern_crashing" ); + self cancelaimove(); + self clearvehgoalpos(); + self setphysacceleration( vectorScale( ( 0, 0, 1 ), 800 ) ); + hitdir = ( 0, 0, 1 ); + side_dir = vectorcross( hitdir, ( 0, 0, 1 ) ); + side_dir_mag = randomfloatrange( -100, 100 ); + side_dir_mag += sign( side_dir_mag ) * 80; + side_dir *= side_dir_mag; + self setvehvelocity( self.velocity + vectorScale( ( 0, 0, 1 ), 100 ) + vectornormalize( side_dir ) ); + ang_vel = self getangularvelocity(); + ang_vel = ( ang_vel[ 0 ] * 0,3, ang_vel[ 1 ], ang_vel[ 2 ] * 0,3 ); + yaw_vel = randomfloatrange( 0, 210 ) * sign( ang_vel[ 1 ] ); + yaw_vel += sign( yaw_vel ) * 180; + ang_vel += ( randomfloatrange( -1, 1 ), yaw_vel, randomfloatrange( -1, 1 ) ); + self setangularvelocity( ang_vel ); + self.crash_accel = randomfloatrange( 75, 110 ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_ip.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_ip.gsc new file mode 100644 index 0000000..8e74a8a --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_ip.gsc @@ -0,0 +1,420 @@ +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "fxanim_props_dlc3" ); + +init() +{ + flag_init( "sq_ip_puzzle_complete" ); + level.sq_bp_buttons = []; + s_lightboard = getstruct( "zm_sq_lightboard", "targetname" ); + s_lightboard sq_bp_spawn_board(); + declare_sidequest_stage( "sq", "ip", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread stage_vo_max(); + } + else + { + level thread stage_vo_ric(); + } + level._cur_stage_name = "ip"; + clientnotify( "ip" ); +} + +stage_vo_max() +{ + s_struct = getstruct( "sq_gallows", "targetname" ); + trigger = spawn( "trigger_radius", s_struct.origin, 0, 128, 72 ); + m_maxis_vo_spot = spawn( "script_model", s_struct.origin ); + m_maxis_vo_spot setmodel( "tag_origin" ); + maxissay( "vox_maxi_sidequest_ip_0", m_maxis_vo_spot ); + maxissay( "vox_maxi_sidequest_ip_1", m_maxis_vo_spot ); + m_lightboard = getent( "sq_bp_board", "targetname" ); + trigger = spawn( "trigger_radius", m_lightboard.origin, 0, 128, 72 ); + trigger waittill( "trigger" ); + maxissay( "vox_maxi_sidequest_ip_2", m_lightboard ); + maxissay( "vox_maxi_sidequest_ip_3", m_lightboard ); +} + +stage_vo_ric() +{ + richtofensay( "vox_zmba_sidequest_ip_0", 10 ); + richtofensay( "vox_zmba_sidequest_ip_1", 5,5 ); + richtofensay( "vox_zmba_sidequest_ip_2", 8 ); + richtofensay( "vox_zmba_sidequest_ip_3", 11 ); + if ( !isDefined( level.rich_sq_player ) ) + { + return; + } + while ( !level.rich_sq_player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_maze" ) ) + { + wait 1; + } + richtofensay( "vox_zmba_sidequest_ip_4", 8 ); +} + +stage_logic() +{ +/# + iprintlnbold( "IP Started" ); +#/ + if ( flag( "sq_is_max_tower_built" ) ) + { + a_button_structs = getstructarray( "sq_bp_button", "targetname" ); + array_thread( a_button_structs, ::sq_bp_spawn_trigger ); + m_lightboard = getent( "sq_bp_board", "targetname" ); + m_lightboard setclientfield( "buried_sq_bp_set_lightboard", 1 ); + while ( !flag( "sq_ip_puzzle_complete" ) ) + { + sq_bp_start_puzzle_lights(); + sq_bp_delete_green_lights(); + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + } + } + else sq_ml_spawn_levers(); + a_levers = getentarray( "sq_ml_lever", "targetname" ); + array_thread( a_levers, ::sq_ml_spawn_trigger ); + level thread sq_ml_puzzle_logic(); + flag_wait( "sq_ip_puzzle_complete" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +sq_bp_spawn_trigger() +{ + level endon( "sq_ip_puzzle_complete" ); + self.trig = spawn( "trigger_radius_use", self.origin, 0, 16, 16 ); + self.trig setcursorhint( "HINT_NOICON" ); + self.trig sethintstring( &"ZM_BURIED_SQ_BUT_U" ); + self.trig triggerignoreteam(); + self.trig usetriggerrequirelookat(); + while ( 1 ) + { + self.trig waittill( "trigger" ); + self.trig sethintstring( "" ); + level thread sq_bp_button_pressed( self.script_string, self.trig ); + wait 1; + self.trig sethintstring( &"ZM_BURIED_SQ_BUT_U" ); + } +} + +sq_bp_spawn_board() +{ + m_board = spawn( "script_model", self.origin ); + m_board.angles = self.angles; + m_board setmodel( "p6_zm_bu_bulb_puzzle_machine" ); + m_board.targetname = "sq_bp_board"; +} + +sq_bp_button_pressed( str_tag, trig ) +{ + if ( isDefined( level.str_sq_bp_active_light ) ) + { + if ( level.str_sq_bp_active_light == str_tag ) + { + trig playsound( "zmb_sq_bell_yes" ); + sq_bp_light_on( str_tag, "green" ); + level notify( "sq_bp_correct_button" ); + } + else + { + trig playsound( "zmb_sq_bell_no" ); + level notify( "sq_bp_wrong_button" ); + m_light = sq_bp_light_on( str_tag, "yellow" ); + } + } + else + { + m_light = sq_bp_light_on( str_tag, "yellow" ); + trig playsound( "zmb_sq_bell_no" ); + } + wait 1; + if ( isDefined( m_light ) ) + { + level setclientfield( m_light, 0 ); + } +} + +sq_bp_start_puzzle_lights() +{ + level endon( "sq_bp_wrong_button" ); + level endon( "sq_bp_timeout" ); + a_button_structs = getstructarray( "sq_bp_button", "targetname" ); + a_tags = []; + _a190 = a_button_structs; + _k190 = getFirstArrayKey( _a190 ); + while ( isDefined( _k190 ) ) + { + m_button = _a190[ _k190 ]; + a_tags[ a_tags.size ] = m_button.script_string; + _k190 = getNextArrayKey( _a190, _k190 ); + } + a_tags = array_randomize( a_tags ); + m_lightboard = getent( "sq_bp_board", "targetname" ); + if ( !isDefined( level.t_start ) ) + { + level.t_start = spawn( "trigger_radius_use", m_lightboard.origin, 0, 16, 16 ); + } + level.t_start setcursorhint( "HINT_NOICON" ); + level.t_start sethintstring( &"ZM_BURIED_SQ_SWIT_U" ); + level.t_start triggerignoreteam(); + level.t_start usetriggerrequirelookat(); + level.t_start waittill( "trigger" ); + level.t_start delete(); + _a210 = a_tags; + _k210 = getFirstArrayKey( _a210 ); + while ( isDefined( _k210 ) ) + { + str_tag = _a210[ _k210 ]; + wait_network_frame(); + wait_network_frame(); + level thread sq_bp_set_current_bulb( str_tag ); + level waittill( "sq_bp_correct_button" ); + _k210 = getNextArrayKey( _a210, _k210 ); + } + flag_set( "sq_ip_puzzle_complete" ); + a_button_structs = getstructarray( "sq_bp_button", "targetname" ); + _a221 = a_button_structs; + _k221 = getFirstArrayKey( _a221 ); + while ( isDefined( _k221 ) ) + { + s_button = _a221[ _k221 ]; + if ( isDefined( s_button.trig ) ) + { + s_button.trig delete(); + } + _k221 = getNextArrayKey( _a221, _k221 ); + } +} + +sq_bp_set_current_bulb( str_tag ) +{ + level endon( "sq_bp_correct_button" ); + level endon( "sq_bp_wrong_button" ); + level endon( "sq_bp_timeout" ); + if ( isDefined( level.m_sq_bp_active_light ) ) + { + level.str_sq_bp_active_light = ""; + } + level.m_sq_bp_active_light = sq_bp_light_on( str_tag, "yellow" ); + level.str_sq_bp_active_light = str_tag; + wait 10; + level notify( "sq_bp_timeout" ); +} + +sq_bp_delete_green_lights() +{ + a_button_structs = getstructarray( "sq_bp_button", "targetname" ); + _a251 = a_button_structs; + _k251 = getFirstArrayKey( _a251 ); + while ( isDefined( _k251 ) ) + { + m_button = _a251[ _k251 ]; + str_clientfield = "buried_sq_bp_" + m_button.script_string; + level setclientfield( str_clientfield, 0 ); + _k251 = getNextArrayKey( _a251, _k251 ); + } + if ( isDefined( level.m_sq_bp_active_light ) ) + { + level.str_sq_bp_active_light = ""; + } +} + +sq_bp_light_on( str_tag, str_color ) +{ + str_clientfield = "buried_sq_bp_" + str_tag; + n_color = 1; + if ( str_color == "green" ) + { + n_color = 2; + } + level setclientfield( str_clientfield, 0 ); + wait_network_frame(); + level setclientfield( str_clientfield, n_color ); + return str_clientfield; +} + +debug_tag( str_tag ) +{ +/# + self endon( "death" ); + while ( 1 ) + { + debugstar( self gettagorigin( str_tag ), 1, ( 0, 1, 0 ) ); + wait 0,05; +#/ + } +} + +sq_ml_spawn_lever( n_index ) +{ + m_lever = spawn( "script_model", ( 0, 1, 0 ) ); + m_lever setmodel( self.model ); + m_lever.targetname = "sq_ml_lever"; + while ( 1 ) + { + v_spot = self.origin; + v_angles = self.angles; + if ( isDefined( level._maze._active_perm_list[ n_index ] ) ) + { + is_flip = randomint( 2 ); + s_spot = getstruct( level._maze._active_perm_list[ n_index ], "script_noteworthy" ); + v_right = anglesToRight( s_spot.angles ); + v_offset = vectornormalize( v_right ) * 2; + if ( is_flip ) + { + v_offset *= -1; + } + v_spot = s_spot.origin + vectorScale( ( 0, 1, 0 ), 48 ) + v_offset; + v_angles = s_spot.angles + vectorScale( ( 0, 1, 0 ), 90 ); + if ( is_flip ) + { + v_angles = s_spot.angles - vectorScale( ( 0, 1, 0 ), 90 ); + } + } + m_lever.origin = v_spot; + m_lever.angles = v_angles; +/# + m_lever thread sq_ml_show_lever_debug( v_spot, n_index ); +#/ + level waittill( "zm_buried_maze_changed" ); + } +} + +sq_ml_show_lever_debug( v_spot, n_index ) +{ + level endon( "zm_buried_maze_changed" ); +/# + while ( 1 ) + { + line( self.origin, v_spot, ( 0, 1, 0 ) ); + print3d( self.origin, "" + n_index, ( 0, 1, 0 ), 1, 2 ); + wait 0,05; +#/ + } +} + +sq_ml_spawn_trigger() +{ + v_right = anglesToForward( self.angles ); + v_offset = vectornormalize( v_right ) * 8; + self.trig = spawn( "trigger_box_use", self.origin - v_offset, 0, 16, 16, 16 ); + self.trig enablelinkto(); + self.trig linkto( self ); + self.trig setcursorhint( "HINT_NOICON" ); + self.trig sethintstring( &"ZM_BURIED_SQ_SWIT_U" ); + self.trig triggerignoreteam(); + self.trig usetriggerrequirelookat(); + self.is_flipped = 0; + self useanimtree( -1 ); + while ( 1 ) + { + self.trig waittill( "trigger" ); + self setanim( level.maze_switch_anim[ "switch_down" ] ); + self.trig sethintstring( "" ); + self.is_flipped = 1; + self.n_flip_number = level.sq_ml_curr_lever; + level.sq_ml_curr_lever++; + self.trig playsound( "zmb_sq_maze_switch" ); + level waittill( "sq_ml_reset_levers" ); + self setanim( level.maze_switch_anim[ "switch_up" ] ); + self.trig sethintstring( &"ZM_BURIED_SQ_SWIT_U" ); + self.is_flipped = 0; + } +} + +sq_ml_spawn_levers() +{ + if ( maps/mp/zombies/_zm_zonemgr::player_in_zone( "zone_maze" ) ) + { + level waittill( "zm_buried_maze_changed" ); + } + a_lever_structs = getstructarray( "sq_maze_lever", "targetname" ); + i = 0; + while ( i < a_lever_structs.size ) + { + a_lever_structs[ i ] thread sq_ml_spawn_lever( i ); + i++; + } +} + +sq_ml_puzzle_logic() +{ + a_levers = getentarray( "sq_ml_lever", "targetname" ); + level.sq_ml_curr_lever = 0; + a_levers = array_randomize( a_levers ); + i = 0; + while ( i < a_levers.size ) + { + a_levers[ i ].n_lever_order = i; + i++; + } + while ( 1 ) + { + level.sq_ml_curr_lever = 0; + sq_ml_puzzle_wait_for_levers(); + n_correct = 0; + _a424 = a_levers; + _k424 = getFirstArrayKey( _a424 ); + while ( isDefined( _k424 ) ) + { + m_lever = _a424[ _k424 ]; + if ( m_lever.n_flip_number == m_lever.n_lever_order ) + { + playfxontag( level._effect[ "sq_spark" ], m_lever, "tag_origin" ); + n_correct++; + m_lever playsound( "zmb_sq_maze_correct_spark" ); + } + _k424 = getNextArrayKey( _a424, _k424 ); + } +/# + iprintlnbold( "Levers Correct: " + n_correct ); +#/ + if ( n_correct == a_levers.size ) + { + flag_set( "sq_ip_puzzle_complete" ); + } + level waittill( "zm_buried_maze_changed" ); + level notify( "sq_ml_reset_levers" ); + wait 1; + } +} + +sq_ml_puzzle_wait_for_levers() +{ + a_levers = getentarray( "sq_ml_lever", "targetname" ); + are_all_flipped = 0; + while ( !are_all_flipped ) + { + are_all_flipped = 1; + _a458 = a_levers; + _k458 = getFirstArrayKey( _a458 ); + while ( isDefined( _k458 ) ) + { + m_lever = _a458[ _k458 ]; + if ( m_lever.is_flipped == 0 ) + { + are_all_flipped = 0; + } + _k458 = getNextArrayKey( _a458, _k458 ); + } + wait 1; + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_ll.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_ll.gsc new file mode 100644 index 0000000..15f4025 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_ll.gsc @@ -0,0 +1,102 @@ +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "sq_ll_generator_on" ); + declare_sidequest_stage( "sq", "ll", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + level._cur_stage_name = "ll"; + clientnotify( "ll" ); +} + +stage_logic() +{ +/# + iprintlnbold( "LL Started" ); +#/ + if ( !isDefined( level.generator_power_states_color ) ) + { + level.generator_power_states_color = 0; + } + sq_ll_show_code(); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +sq_ll_show_code() +{ + a_spots = getstructarray( "sq_code_pos", "targetname" ); + a_signs = getentarray( "sq_tunnel_sign", "targetname" ); + a_codes = []; + _a50 = a_signs; + _k50 = getFirstArrayKey( _a50 ); + while ( isDefined( _k50 ) ) + { + m_sign = _a50[ _k50 ]; + if ( flag( "sq_is_max_tower_built" ) ) + { + if ( isDefined( m_sign.is_max_sign ) ) + { + a_codes[ a_codes.size ] = m_sign.model + "_code"; + } + } + else + { + if ( isDefined( m_sign.is_ric_sign ) ) + { + a_codes[ a_codes.size ] = m_sign.model + "_code"; + } + } + _k50 = getNextArrayKey( _a50, _k50 ); + } + i = 0; + while ( i < a_codes.size ) + { + if ( a_codes[ i ] == "p6_zm_bu_sign_tunnel_consumption_code" ) + { + a_codes[ i ] = "p6_zm_bu_sign_tunnel_consump_code"; + } + i++; + } + i = 0; + while ( i < a_codes.size ) + { + m_code = spawn( "script_model", a_spots[ i ].origin ); + m_code.angles = a_spots[ i ].angles; + m_code setmodel( a_codes[ i ] ); + i++; + } + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread sq_ll_show_code_vo_max(); + } + else + { + level thread sq_ll_show_code_vo_ric(); + } +} + +exit_stage( success ) +{ +} + +sq_ll_show_code_vo_max() +{ + a_signs = getentarray( "sq_tunnel_sign", "targetname" ); + maxissay( "vox_maxi_sidequest_signs_0", a_signs[ 0 ] ); + maxissay( "vox_maxi_sidequest_signs_1", a_signs[ 0 ] ); +} + +sq_ll_show_code_vo_ric() +{ + richtofensay( "vox_zmba_sidequest_signs_0", 7 ); + richtofensay( "vox_zmba_sidequest_signs_1", 10 ); + richtofensay( "vox_zmba_sidequest_signs_2", 9 ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_mta.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_mta.gsc new file mode 100644 index 0000000..5a61bb6 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_mta.gsc @@ -0,0 +1,204 @@ +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "sq_amplifiers_on" ); + a_amp_structs = getstructarray( "sq_amplifier_spot" ); + _a16 = a_amp_structs; + _k16 = getFirstArrayKey( _a16 ); + while ( isDefined( _k16 ) ) + { + s_amp_spot = _a16[ _k16 ]; + m_amplifier = spawn( "script_model", s_amp_spot.origin ); + m_amplifier thread mta_amplifier_init(); + _k16 = getNextArrayKey( _a16, _k16 ); + } + declare_sidequest_stage( "sq", "mta", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + a_amplifiers = getentarray( "sq_amplifier", "targetname" ); + array_thread( a_amplifiers, ::mta_amplifier_found_watcher ); + level thread stage_vo_max(); + level thread stage_vo_ric(); + level._cur_stage_name = "mta"; + clientnotify( "mta" ); +} + +stage_logic() +{ +/# + iprintlnbold( "MTA Started" ); +#/ + flag_wait_any( "sq_amplifiers_on", "sq_amplifiers_broken" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +stage_vo_max() +{ + level thread stage_vo_max_amp_broken(); + level waittill( "mta_amp_found", amp ); + maxissay( "vox_maxi_sidequest_amp_0", amp ); + maxissay( "vox_maxi_sidequest_amp_1", amp ); +} + +stage_vo_max_amp_broken() +{ + level waittill( "mta_amp_broken", amp ); + maxissay( "vox_maxi_sidequest_amp_2", amp ); + level waittill( "mta_amp_broken", amp ); + maxissay( "vox_maxi_sidequest_amp_3", amp ); + level waittill( "mta_amp_broken", amp ); + maxissay( "vox_maxi_sidequest_amp_4", amp ); + level waittill( "mta_amp_broken", amp ); + maxissay( "vox_maxi_sidequest_amp_5", amp ); + maxissay( "vox_maxi_sidequest_gl_0", amp ); + maxissay( "vox_maxi_sidequest_gl_1", amp ); +} + +stage_vo_ric() +{ + level thread stage_vo_ric_amp_amplified(); + level waittill( "mta_amp_found_by_sam" ); + richtofensay( "vox_zmba_sidequest_amp_0", 10 ); + richtofensay( "vox_zmba_sidequest_amp_1", 7 ); +} + +stage_vo_ric_amp_amplified() +{ + level waittill( "mta_amp_amplified" ); + richtofensay( "vox_zmba_sidequest_amp_2", 6 ); + richtofensay( "vox_zmba_sidequest_amp_3", 4 ); +} + +mta_amplifier_found_watcher() +{ + self endon( "damaged_by_subwoofer" ); + self endon( "amplifier_filled" ); + if ( self.amplifier_state != "base" ) + { + return; + } + trigger = spawn( "trigger_radius", self.origin, 0, 128, 72 ); + trigger waittill( "trigger", who ); + if ( isDefined( level.rich_sq_player ) && who == level.rich_sq_player ) + { + level notify( "mta_amp_found_by_sam" ); + } + else + { + level notify( "mta_amp_found" ); + } +} + +mta_amplifier_init() +{ + self setmodel( "p6_zm_bu_ether_amplifier" ); + self.targetname = "sq_amplifier"; + self.script_noteworthy = "subwoofer_target"; + self.amplifier_state = "base"; + self playloopsound( "zmb_sq_amplifier_empty_loop", 1 ); + self setcandamage( 1 ); + self thread mta_amplifier_subwoofer_watch(); + self mta_amplifier_damage_watch(); +} + +mta_amplifier_subwoofer_watch() +{ + self waittill( "damaged_by_subwoofer" ); +/# + iprintlnbold( "Amplifier Broken" ); +#/ + self.amplifier_state = "broken"; + self setmodel( "p6_zm_bu_ether_amplifier_dmg" ); + self stoploopsound( 0,1 ); + self playsound( "zmb_sq_amplifier_destroy" ); + level notify( "mta_amp_broken" ); + mta_check_all_amplifier_states(); +} + +mta_amplifier_damage_watch() +{ + self endon( "damaged_by_subwoofer" ); + n_slowgun_count = 0; + while ( 1 ) + { + self waittill( "damage", n_damage, e_attacker, v_direction, v_point, str_type, str_tag, str_model, str_part, str_weapon ); + if ( str_weapon == "slowgun_zm" || str_weapon == "slowgun_upgraded_zm" ) + { + n_slowgun_count++; + shader_amount = linear_map( n_slowgun_count, 0, 25, 0, 1 ); + self setclientfield( "AmplifierShaderConstant", shader_amount ); + if ( n_slowgun_count >= 25 ) + { +/# + iprintlnbold( "Amplifier Filled" ); +#/ + self thread mta_amplifier_filled_fx(); + self.amplifier_state = "filled"; + self playsound( "zmb_sq_amplifier_fill" ); + self playloopsound( "zmb_sq_amplifier_full_loop", 1 ); + self notify( "amplifier_filled" ); + level notify( "mta_amp_amplified" ); + break; + } + } + else + { + wait_network_frame(); + } + } + mta_check_all_amplifier_states(); +} + +mta_amplifier_filled_fx() +{ + while ( 1 ) + { + playfx( level._effect[ "sq_ether_amp_trail" ], self.origin + vectorScale( ( 0, 0, 1 ), 46 ) ); + wait 1; + } +} + +mta_check_all_amplifier_states() +{ + is_all_broken = 1; + is_all_filled = 1; + a_amplifiers = getentarray( "sq_amplifier", "targetname" ); + _a226 = a_amplifiers; + _k226 = getFirstArrayKey( _a226 ); + while ( isDefined( _k226 ) ) + { + m_amplifier = _a226[ _k226 ]; + if ( m_amplifier.amplifier_state != "filled" ) + { + is_all_filled = 0; + } + if ( m_amplifier.amplifier_state != "broken" ) + { + is_all_broken = 0; + } + _k226 = getNextArrayKey( _a226, _k226 ); + } + if ( is_all_filled ) + { + flag_set( "sq_amplifiers_on" ); + } + else + { + if ( is_all_broken ) + { + flag_set( "sq_amplifiers_broken" ); + } + } +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_ows.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_ows.gsc new file mode 100644 index 0000000..7ce94ab --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_ows.gsc @@ -0,0 +1,223 @@ +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "sq_ows_start" ); + flag_init( "sq_ows_target_missed" ); + flag_init( "sq_ows_success" ); + declare_sidequest_stage( "sq", "ows", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread stage_vo_max(); + } + else + { + level thread stage_vo_ric(); + } + level._cur_stage_name = "ows"; + clientnotify( "ows" ); +} + +stage_vo_max() +{ + m_lightboard = getent( "sq_bp_board", "targetname" ); + maxissay( "vox_maxi_sidequest_ip_4", m_lightboard ); +} + +stage_vo_ric() +{ + richtofensay( "vox_zmba_sidequest_ip_5", 8 ); + richtofensay( "vox_zmba_sidequest_ip_6", 8 ); + richtofensay( "vox_zmba_sidequest_ip_7", 11 ); +} + +stage_logic() +{ +/# + iprintlnbold( "OWS Started" ); +#/ + while ( !flag( "sq_ows_success" ) ) + { + level thread ows_fountain_wait(); + flag_wait( "sq_ows_start" ); + ows_targets_start(); + flag_clear( "sq_ows_start" ); + } + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +ows_fountain_wait() +{ + level endon( "sq_ows_start" ); + s_fountain_spot = getstruct( "sq_ows_fountain", "targetname" ); + t_fountain = spawn( "trigger_radius_use", s_fountain_spot.origin, 0, 55, 64 ); + t_fountain setcursorhint( "HINT_NOICON" ); + t_fountain sethintstring( &"ZM_BURIED_SQ_FOUNT_U" ); + t_fountain triggerignoreteam(); + t_fountain usetriggerrequirelookat(); + t_fountain waittill( "trigger" ); + t_fountain playsound( "zmb_sq_coin_toss" ); + t_fountain delete(); + flag_set( "sq_ows_start" ); +} + +ows_targets_start() +{ + n_cur_second = 0; + flag_clear( "sq_ows_target_missed" ); + level thread sndsidequestowsmusic(); + a_sign_spots = getstructarray( "otw_target_spot", "script_noteworthy" ); + while ( n_cur_second < 40 ) + { + a_spawn_spots = ows_targets_get_cur_spots( n_cur_second ); + if ( isDefined( a_spawn_spots ) && a_spawn_spots.size > 0 ) + { + ows_targets_spawn( a_spawn_spots ); + } + wait 1; + n_cur_second++; + } + if ( !flag( "sq_ows_target_missed" ) ) + { + flag_set( "sq_ows_success" ); + playsoundatposition( "zmb_sq_target_success", ( 0, 0, 0 ) ); + } + else + { + playsoundatposition( "zmb_sq_target_fail", ( 0, 0, 0 ) ); + } + level notify( "sndEndOWSMusic" ); +} + +ows_targets_get_cur_spots( n_time ) +{ + a_target_spots = getstructarray( "otw_target_spot", "script_noteworthy" ); + a_to_spawn = []; + str_time = "" + n_time; + _a133 = a_target_spots; + _k133 = getFirstArrayKey( _a133 ); + while ( isDefined( _k133 ) ) + { + s_spot = _a133[ _k133 ]; + if ( isDefined( s_spot.script_string ) ) + { + a_spawn_times = strtok( s_spot.script_string, " " ); + if ( isinarray( a_spawn_times, str_time ) ) + { + a_to_spawn[ a_to_spawn.size ] = s_spot; + } + } + _k133 = getNextArrayKey( _a133, _k133 ); + } + return a_to_spawn; +} + +ows_targets_spawn( a_spawn_spots ) +{ + _a151 = a_spawn_spots; + _k151 = getFirstArrayKey( _a151 ); + while ( isDefined( _k151 ) ) + { + s_spot = _a151[ _k151 ]; + m_target = spawn( "script_model", s_spot.origin ); + m_target.angles = s_spot.angles; + m_target setmodel( "p6_zm_bu_target" ); + m_target ghost(); + wait_network_frame(); + m_target show(); + playfxontag( level._effect[ "sq_spawn" ], m_target, "tag_origin" ); + m_target playsound( "zmb_sq_target_spawn" ); + if ( isDefined( s_spot.target ) ) + { + m_target thread ows_target_move( s_spot.target ); + } + m_target thread ows_target_think(); + m_target thread sndhit(); + m_target thread sndtime(); + _k151 = getNextArrayKey( _a151, _k151 ); + } +} + +ows_target_think() +{ + self setcandamage( 1 ); + self thread ows_target_delete_timer(); + self waittill_either( "ows_target_timeout", "damage" ); + if ( isDefined( self.m_linker ) ) + { + self unlink(); + self.m_linker delete(); + } + self rotatepitch( -90, 0,15, 0,05, 0,05 ); + self waittill( "rotatedone" ); + self delete(); +} + +ows_target_move( str_target ) +{ + s_target = getstruct( str_target, "targetname" ); + self.m_linker = spawn( "script_model", self.origin ); + self.m_linker.angles = self.angles; + self linkto( self.m_linker ); + self.m_linker moveto( s_target.origin, 4, 0,05, 0,05 ); +} + +ows_target_delete_timer() +{ + self endon( "death" ); + wait 4; + self notify( "ows_target_timeout" ); + flag_set( "sq_ows_target_missed" ); +/# + iprintlnbold( "missed target! step failed. target @ " + self.origin ); +#/ +} + +sndsidequestowsmusic() +{ + while ( is_true( level.music_override ) ) + { + wait 0,1; + } + level.music_override = 1; + level setclientfield( "mus_zmb_egg_snapshot_loop", 1 ); + ent = spawn( "script_origin", ( 0, 0, 0 ) ); + ent playloopsound( "mus_sidequest_ows" ); + level waittill( "sndEndOWSMusic" ); + level setclientfield( "mus_zmb_egg_snapshot_loop", 0 ); + level.music_override = 0; + ent stoploopsound( 4 ); + if ( !flag( "sq_ows_success" ) ) + { + wait 0,5; + ent playsound( "mus_sidequest_0" ); + } + wait 3,5; + ent delete(); +} + +sndhit() +{ + self endon( "ows_target_timeout" ); + self waittill( "damage" ); + self playsound( "zmb_sq_target_hit" ); +} + +sndtime() +{ + self endon( "zmb_sq_target_hit" ); + self waittill( "ows_target_timeout" ); + self playsound( "zmb_sq_target_flip" ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_tpo.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_tpo.gsc new file mode 100644 index 0000000..1d8dae7 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_tpo.gsc @@ -0,0 +1,696 @@ +#include maps/mp/zm_buried_buildables; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_weap_time_bomb; +#include maps/mp/zm_buried_sq; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zm_buried_props" ); + +init() +{ + declare_sidequest_stage( "sq", "tpo", ::init_stage, ::stage_logic, ::exit_stage ); + flag_init( "sq_tpo_time_bomb_in_valid_location" ); + flag_init( "sq_tpo_players_in_position_for_time_warp" ); + flag_init( "sq_tpo_special_round_active" ); + flag_init( "sq_tpo_found_item" ); + flag_init( "sq_tpo_generator_powered" ); + flag_init( "sq_wisp_saved_with_time_bomb" ); + flag_init( "sq_tpo_stage_started" ); + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_save( ::time_bomb_saves_wisp_state ); + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_restore( ::time_bomb_restores_wisp_state ); +/# + level thread debug_give_piece(); +#/ + level._effect[ "sq_tpo_time_bomb_fx" ] = loadfx( "maps/zombie_buried/fx_buried_ghost_drain" ); + level.sq_tpo = spawnstruct(); + level thread setup_buildable_switch(); +} + +init_stage() +{ + if ( flag( "sq_is_max_tower_built" ) ) + { + level thread stage_vo_max(); + } + else + { + level thread stage_vo_ric(); + } + level._cur_stage_name = "tpo"; + clientnotify( "tpo" ); +} + +stage_vo_max() +{ + s_struct = getstruct( "sq_gallows", "targetname" ); + m_maxis_vo_spot = spawn( "script_model", s_struct.origin ); + m_maxis_vo_spot setmodel( "tag_origin" ); + maxissay( "vox_maxi_sidequest_ctw_5", m_maxis_vo_spot ); + maxissay( "vox_maxi_sidequest_ctw_6", m_maxis_vo_spot ); + maxissay( "vox_maxi_sidequest_ctw_7", m_maxis_vo_spot ); + m_maxis_vo_spot delete(); +} + +stage_vo_ric() +{ + richtofensay( "vox_zmba_sidequest_ctw_4", 10 ); + richtofensay( "vox_zmba_sidequest_step8_0", 11 ); + richtofensay( "vox_zmba_sidequest_step8_1", 6 ); + richtofensay( "vox_zmba_sidequest_step8_2", 6 ); + level waittill( "sq_tpo_special_round_started" ); + wait 2; + richtofensay( "vox_zmba_sidequest_step8_3", 6 ); + level waittill( "sq_tpo_special_round_ended" ); + richtofensay( "vox_zmba_sidequest_step8_6", 4 ); +} + +stage_logic() +{ +/# + iprintlnbold( "TPO Started" ); +#/ + flag_set( "sq_tpo_stage_started" ); + if ( flag( "sq_is_ric_tower_built" ) ) + { + stage_logic_richtofen(); + } + else if ( flag( "sq_is_max_tower_built" ) ) + { + stage_logic_maxis(); + } + else + { +/# + assertmsg( "SQ TPO: no sidequest side picked!" ); +#/ + } +/# + iprintlnbold( "TPO done" ); +#/ + stage_completed( "sq", level._cur_stage_name ); +} + +stage_logic_richtofen() +{ + level endon( "sq_tpo_generator_powered" ); +/# + iprintlnbold( "TPO: Richtofen started" ); +#/ + e_time_bomb_volume = getent( "sq_tpo_timebomb_volume", "targetname" ); + flag_clear( "sq_tpo_time_bomb_in_valid_location" ); + if ( isDefined( level.time_bomb_save_data ) && isDefined( level.time_bomb_save_data.time_bomb_model ) && isDefined( level.time_bomb_save_data.time_bomb_model.sq_location_valid ) ) + { + level waittill( "new_time_bomb_set" ); + } + b_time_bomb_in_valid_location = level.time_bomb_save_data.time_bomb_model istouching( e_time_bomb_volume ); + level.time_bomb_save_data.time_bomb_model.sq_location_valid = b_time_bomb_in_valid_location; + playfxontag( level._effect[ "sq_tpo_time_bomb_fx" ], level.time_bomb_save_data.time_bomb_model, "tag_origin" ); + flag_set( "sq_tpo_time_bomb_in_valid_location" ); + level thread sq_tpo_check_players_in_time_bomb_volume( e_time_bomb_volume ); + wait_for_time_bomb_to_be_detonated_or_thrown_again(); + level notify( "sq_tpo_stop_checking_time_bomb_volume" ); + if ( flag( "time_bomb_restore_active" ) ) + { + if ( flag( "sq_tpo_players_in_position_for_time_warp" ) ) + { + special_round_start(); + level notify( "sq_tpo_special_round_started" ); + start_item_hunt_with_timeout( 60 ); + special_round_end(); + level notify( "sq_tpo_special_round_ended" ); + } + } + wait_network_frame(); +} + +stage_logic_maxis() +{ +/# + iprintlnbold( "TPO: Maxis started" ); +#/ + flag_wait( "sq_wisp_saved_with_time_bomb" ); + while ( !flag( "sq_wisp_success" ) ) + { + stage_start( "sq", "ts" ); + level waittill( "sq_ts_over" ); + stage_start( "sq", "ctw" ); + level waittill( "sq_ctw_over" ); + } + level._cur_stage_name = "tpo"; +} + +sq_tpo_check_players_in_time_bomb_volume( e_volume ) +{ + level endon( "sq_tpo_stop_checking_time_bomb_volume" ); + while ( 1 ) + { + b_players_ready = _are_all_players_in_time_bomb_volume( e_volume ); + level._time_bomb.functionality_override = b_players_ready; + if ( b_players_ready ) + { + flag_set( "sq_tpo_players_in_position_for_time_warp" ); + } + else + { + flag_clear( "sq_tpo_players_in_position_for_time_warp" ); + } + wait 0,25; + } +} + +_are_all_players_in_time_bomb_volume( e_volume ) +{ + n_required_players = 4; + a_players = get_players(); +/# + if ( getDvarInt( #"5256118F" ) > 0 ) + { + n_required_players = a_players.size; +#/ + } + n_players_in_position = 0; + _a239 = a_players; + _k239 = getFirstArrayKey( _a239 ); + while ( isDefined( _k239 ) ) + { + player = _a239[ _k239 ]; + if ( player istouching( e_volume ) ) + { + n_players_in_position++; + } + _k239 = getNextArrayKey( _a239, _k239 ); + } + b_all_in_valid_position = n_players_in_position == n_required_players; + return b_all_in_valid_position; +} + +wait_for_time_bomb_to_be_detonated_or_thrown_again() +{ + level endon( "new_time_bomb_set" ); + flag_wait( "time_bomb_restore_active" ); +} + +special_round_start() +{ +/# + iprintlnbold( "SPECIAL ROUND START" ); +#/ + flag_set( "sq_tpo_special_round_active" ); + level.sq_tpo.times_searched = 0; + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_saves_data( 0 ); + flag_clear( "time_bomb_detonation_enabled" ); + fake_time_warp(); + level thread sndsidequestnoirmusic(); + make_super_zombies( 1 ); + level thread spawn_zombies_after_time_bomb_round_killed(); + a_players = get_players(); + _a279 = a_players; + _k279 = getFirstArrayKey( _a279 ); + while ( isDefined( _k279 ) ) + { + player = _a279[ _k279 ]; + vsmgr_activate( "visionset", "cheat_bw", player ); + _k279 = getNextArrayKey( _a279, _k279 ); + } + level setclientfield( "sq_tpo_special_round_active", 1 ); +} + +make_super_zombies( b_toggle ) +{ + if ( b_toggle ) + { + n_round = 115; + level thread watch_for_time_bombs( n_round ); + } + else + { + n_round = level.round_number; + level notify( "super_zombies_end" ); + } + level.zombie_total = n_round; + ai_calculate_health( n_round ); + level.zombie_move_speed = n_round * level.zombie_vars[ "zombie_move_speed_multiplier" ]; +} + +watch_for_time_bombs( n_round ) +{ + level notify( "super_zombies_end" ); + level endon( "super_zombies_end" ); + while ( 1 ) + { + level waittill_any( "time_bomb_detonation_complete", "start_of_round" ); + level.zombie_total = n_round; + ai_calculate_health( n_round ); + level.zombie_move_speed = n_round * level.zombie_vars[ "zombie_move_speed_multiplier" ]; + } +} + +spawn_zombies_after_time_bomb_round_killed() +{ + flag_wait( "time_bomb_round_killed" ); + flag_set( "spawn_zombies" ); +} + +fake_time_warp() +{ + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_destroy_hud_elem(); + maps/mp/zombies/_zm_weap_time_bomb::_time_bomb_show_overlay(); + maps/mp/zombies/_zm_weap_time_bomb::_time_bomb_kill_all_active_enemies(); + playsoundatposition( "zmb_timebomb_timechange_2d_sq", ( 0, 0, 0 ) ); + maps/mp/zombies/_zm_weap_time_bomb::_time_bomb_hide_overlay(); +} + +special_round_end() +{ +/# + iprintlnbold( "SPECIAL ROUND END" ); +#/ + level setclientfield( "sq_tpo_special_round_active", 0 ); + level notify( "sndEndNoirMusic" ); + make_super_zombies( 0 ); + level._time_bomb.functionality_override = 0; + flag_set( "time_bomb_detonation_enabled" ); + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_restores_saved_data(); + a_players = get_players(); + _a356 = a_players; + _k356 = getFirstArrayKey( _a356 ); + while ( isDefined( _k356 ) ) + { + player = _a356[ _k356 ]; + vsmgr_deactivate( "visionset", "cheat_bw", player ); + player notify( "search_done" ); + _k356 = getNextArrayKey( _a356, _k356 ); + } + clean_up_special_round(); + flag_clear( "sq_tpo_special_round_active" ); +} + +clean_up_special_round() +{ + a_models = getentarray( "sq_tpo_corpse_model", "targetname" ); + _a370 = a_models; + _k370 = getFirstArrayKey( _a370 ); + while ( isDefined( _k370 ) ) + { + model = _a370[ _k370 ]; + model _delete_unitrigger(); + model delete(); + _k370 = getNextArrayKey( _a370, _k370 ); + } +} + +_delete_unitrigger() +{ + if ( isDefined( self.unitrigger ) ) + { + self.unitrigger.registered = 0; + } + if ( isDefined( self.unitrigger.trigger ) ) + { + if ( isDefined( self.unitrigger.trigger.stub ) ) + { + self.unitrigger.trigger maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger.trigger.stub ); + return; + } + else + { + self.trigger notify( "kill_trigger" ); + self.trigger delete(); + } + } +} + +start_item_hunt_with_timeout( n_timeout ) +{ + setup_random_corpse_positions(); + level delay_notify( "sq_tpo_item_hunt_done", n_timeout ); +/# + iprintlnbold( "ITEM HUNT STARTED" ); +#/ + level waittill( "sq_tpo_item_hunt_done" ); +} + +exit_stage( success ) +{ +} + +debug_give_piece() +{ + while ( 1 ) + { + level waittill( "sq_tpo_give_item" ); + get_players()[ 0 ] give_player_sq_tpo_switch(); + } +} + +get_randomized_corpse_list() +{ + a_corpses = array( "c_zom_player_farmgirl_fb", "c_zom_player_oldman_fb", "c_zom_player_reporter_dam_fb", "c_zom_player_engineer_fb" ); + a_corpses = array_randomize( a_corpses ); + return a_corpses; +} + +setup_random_corpse_positions() +{ + a_corpse_models = get_randomized_corpse_list(); + a_corpse_structs = array_randomize( getstructarray( "sq_tpo_corpse_spawn_location", "targetname" ) ); + i = 0; + while ( i < a_corpse_models.size ) + { + a_corpse_structs[ i ] promote_to_corpse_model( a_corpse_models[ i ] ); + a_corpse_structs[ i ] thread _debug_show_location(); + i++; + } +} + +_debug_show_location() +{ +/# + level endon( "sq_tpo_item_hunt_done" ); + while ( 1 ) + { + if ( getDvarInt( #"5256118F" ) > 0 ) + { + debugstar( self.origin, 20, ( 0, 0, 0 ) ); + } + wait 1; +#/ + } +} + +promote_to_corpse_model( str_model ) +{ + v_spawn_point = groundtrace( self.origin + vectorScale( ( 0, 0, 0 ), 10 ), self.origin + vectorScale( ( 0, 0, 0 ), 300 ), 0, undefined )[ "position" ]; + self.corpse_model = spawn( "script_model", v_spawn_point ); + self.corpse_model.angles = self.angles; + self.corpse_model setmodel( str_model ); + self.corpse_model.targetname = "sq_tpo_corpse_model"; + self _pose_corpse(); + self.corpse_model.unitrigger = setup_unitrigger( &"ZM_BURIED_SQ_SCH", ::unitrigger_think ); +} + +_pose_corpse() +{ +/# + assert( isDefined( self.script_noteworthy ), "sq_tpo_corpse_spawn_location at " + self.origin + " is missing script_noteworthy! This is required to set deadpose" ); +#/ + switch( self.script_noteworthy ) + { + case "deadpose_1": + anim_pose = %pb_gen_m_floor_armdown_onback_deathpose; + break; + case "deadpose_2": + anim_pose = %pb_gen_m_floor_armdown_onfront_deathpose; + break; + case "deadpose_3": + anim_pose = %pb_gen_m_floor_armover_onrightside_deathpose; + break; + case "deadpose_4": + anim_pose = %pb_gen_m_floor_armrelaxed_onleftside_deathpose; + break; + case "deadpose_5": + anim_pose = %pb_gen_m_floor_armspread_legaskew_onback_deathpose; + break; + case "deadpose_6": + anim_pose = %pb_gen_m_floor_armspreadwide_legspread_onback_deathpose; + break; + case "deadpose_7": + anim_pose = %pb_gen_m_floor_armstomach_onrightside_deathpose; + break; + case "deadpose_8": + anim_pose = %pb_gen_m_floor_armstretched_onleftside_deathpose; + break; + case "deadpose_9": + anim_pose = %pb_gen_m_wall_armcraddle_leanleft_deathpose; + break; + case "deadpose_10": + anim_pose = %pb_gen_m_wall_legin_armcraddle_hunchright_deathpose; + break; + case "deadpose_11": + anim_pose = %pb_gen_m_wall_legspread_armdown_leanleft_deathpose; + break; + case "deadpose_12": + anim_pose = %pb_gen_m_floor_armsopen_onback_deathpose; + break; + case "deadpose_13": + anim_pose = %pb_gen_m_floor_armstomach_onback_deathpose; + break; + default: +/# + assertmsg( "sq_tpo_corpse_struct with script_noteworthy '" + self.script_noteworthy + "' is not supported by existing anim list!" ); +#/ + break; + } + self.corpse_model useanimtree( -1 ); + self.corpse_model setanim( anim_pose, 1, 0,05, 1 ); +} + +setup_unitrigger( str_hint, func_update ) +{ + radius = 32; + script_height = 32; + script_width = 0; + script_length = undefined; + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = self.origin + vectorScale( ( 0, 0, 0 ), 10 ); + unitrigger_stub.script_length = 13,5; + unitrigger_stub.script_width = script_width; + unitrigger_stub.script_height = script_height; + unitrigger_stub.radius = radius; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + unitrigger_stub.hint_string = str_hint; + unitrigger_stub.script_unitrigger_type = "unitrigger_radius_use"; + unitrigger_stub.require_look_at = 1; + unitrigger_stub.prompt_and_visibility_func = ::piecetrigger_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, func_update ); + return unitrigger_stub; +} + +piecetrigger_update_prompt( player ) +{ + can_use = self.stub piecestub_update_prompt( player ); + self setinvisibletoplayer( player, !can_use ); + self sethintstring( self.stub.hint_string ); + return can_use; +} + +piecestub_update_prompt( player ) +{ + return 1; +} + +unitrigger_killed() +{ + self waittill( "kill_trigger" ); + self _delete_progress_bar(); +} + +unitrigger_think() +{ + self endon( "kill_trigger" ); + self thread unitrigger_killed(); + b_trigger_used = 0; + while ( !b_trigger_used ) + { + self waittill( "trigger", player ); + b_progress_bar_done = 0; + n_frame_count = 0; + while ( player usebuttonpressed() && !b_progress_bar_done ) + { + if ( !isDefined( self.progress_bar ) ) + { + self.progress_bar = player createprimaryprogressbar(); + self.progress_bar_text = player createprimaryprogressbartext(); + self.progress_bar_text settext( &"ZM_BURIED_SQ_SEARCHING" ); + self thread _kill_progress_bar(); + } + n_progress_amount = n_frame_count / 30; + self.progress_bar updatebar( n_progress_amount ); + n_frame_count++; + if ( n_progress_amount == 1 ) + { + b_progress_bar_done = 1; + } + wait 0,05; + } + self _delete_progress_bar(); + if ( b_progress_bar_done ) + { + b_trigger_used = 1; + } + } + if ( b_progress_bar_done ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + if ( item_is_on_corpse() ) + { + iprintlnbold( &"ZM_BURIED_SQ_FND" ); + player give_player_sq_tpo_switch(); + } + else + { + iprintlnbold( &"ZM_BURIED_SQ_NFND" ); + } + self thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.stub ); + } +} + +give_player_sq_tpo_switch() +{ + self player_take_piece( level.zombie_buildables[ "buried_sq_tpo_switch" ].buildablepieces[ 0 ] ); + flag_set( "sq_tpo_found_item" ); + level.sq_tpo_unitrig.origin = level.sq_tpo_unitrig.realorigin; +} + +item_is_on_corpse() +{ + if ( !isDefined( level.sq_tpo.times_searched ) ) + { + level.sq_tpo.times_searched = 0; + } + switch( level.sq_tpo.times_searched ) + { + case 0: + n_chance = 1; + break; + case 1: + n_chance = 15; + break; + case 2: + n_chance = 33; + break; + case 3: + n_chance = 100; + break; + } + if ( randomint( 100 ) > ( 100 - n_chance ) ) + { + b_found_item = !flag( "sq_tpo_found_item" ); + } + level.sq_tpo.times_searched++; + return b_found_item; +} + +_delete_progress_bar() +{ + if ( isDefined( self.progress_bar ) ) + { + self.progress_bar destroyelem(); + self.progress_bar_text destroyelem(); + self.progress_bar = undefined; + } +} + +_kill_progress_bar() +{ + self endon( "death" ); + self endon( "disconnect" ); + self waittill( "search_done" ); + self _delete_progress_bar(); +} + +setup_buildable_switch() +{ + s_switch_piece = generate_zombie_buildable_piece( "buried_sq_tpo_switch", "p6_zm_buildable_pswitch_lever_handed", 32, 64, 2,4, "zom_icon_trap_switch_handle", ::onpickup_switch, ::ondrop_switch, undefined, undefined, 0, 5, 2 ); + s_switch_piece.hint_grab = level.str_buildables_grab_part; + s_switch_piece.hint_swap = level.str_buildables_swap_part; + s_switch_piece manage_multiple_pieces( 1 ); + s_switch_piece.onspawn = ::onspawn_switch; + s_switch = spawnstruct(); + s_switch.name = "buried_sq_tpo_switch"; + s_switch add_buildable_piece( s_switch_piece ); + s_switch.triggerthink = ::triggerthink_switch; + s_switch.onuseplantobject = ::onuseplantobject_switch; + include_buildable( s_switch ); + while ( !isDefined( level.sq_tpo_unitrig ) ) + { + wait 1; + } + level.sq_tpo_unitrig.realorigin = level.sq_tpo_unitrig.origin; + level.sq_tpo_unitrig.origin += vectorScale( ( 0, 0, 0 ), 10000 ); +} + +onuseplantobject_switch( player ) +{ + flag_set( "sq_tpo_generator_powered" ); +} + +onpickup_switch( player ) +{ + maps/mp/zm_buried_buildables::onpickup_common( player ); +} + +ondrop_switch( player ) +{ + maps/mp/zm_buried_buildables::ondrop_common( player ); +} + +onspawn_switch( player ) +{ +} + +triggerthink_switch() +{ + if ( isDefined( getent( "guillotine_trigger", "targetname" ) ) ) + { + str_trigger_generator_name = "guillotine_trigger"; + level.sq_tpo_unitrig = maps/mp/zombies/_zm_buildables::buildable_trigger_think( str_trigger_generator_name, "buried_sq_tpo_switch", "none", "", 1, 0 ); + level.sq_tpo_unitrig.ignore_open_sesame = 1; + level.sq_tpo_unitrig.buildablestub_reject_func = ::guillotine_trigger_reject_func; + } +} + +guillotine_trigger_reject_func( player ) +{ + b_should_reject = 0; + if ( flag( "sq_tpo_special_round_active" ) ) + { + b_should_reject = 1; + } + return b_should_reject; +} + +time_bomb_saves_wisp_state() +{ + if ( !isDefined( self.sq_data ) ) + { + self.sq_data = spawnstruct(); + } + self.sq_data.wisp_stage_complete = flag( "sq_wisp_success" ); +} + +time_bomb_restores_wisp_state() +{ + if ( isDefined( self.sq_data ) && isDefined( self.sq_data.wisp_stage_complete ) && !self.sq_data.wisp_stage_complete && flag( "sq_tpo_stage_started" ) ) + { + flag_clear( "sq_wisp_success" ); + flag_clear( "sq_wisp_failed" ); + flag_set( "sq_wisp_saved_with_time_bomb" ); + } +} + +sndsidequestnoirmusic() +{ + if ( is_true( level.music_override ) ) + { + return; + } + level.music_override = 1; + level setclientfield( "mus_noir_snapshot_loop", 1 ); + ent = spawn( "script_origin", ( 0, 0, 0 ) ); + ent playloopsound( "mus_sidequest_noir" ); + level waittill( "sndEndNoirMusic" ); + level setclientfield( "mus_noir_snapshot_loop", 0 ); + level.music_override = 0; + ent stoploopsound( 2 ); + wait 2; + ent delete(); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_sq_ts.gsc b/zm_buried_patch/maps/mp/zm_buried_sq_ts.gsc new file mode 100644 index 0000000..5013321 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_sq_ts.gsc @@ -0,0 +1,152 @@ +#include maps/mp/zombies/_zm_sidequests; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + flag_init( "sq_ts_quicktest" ); + declare_sidequest_stage( "sq", "ts", ::init_stage, ::stage_logic, ::exit_stage ); +} + +init_stage() +{ + a_signs = getentarray( "sq_tunnel_sign", "targetname" ); + _a18 = a_signs; + _k18 = getFirstArrayKey( _a18 ); + while ( isDefined( _k18 ) ) + { + m_sign = _a18[ _k18 ]; + m_sign setcandamage( 1 ); + m_sign thread ts_sign_damage_watch(); + _k18 = getNextArrayKey( _a18, _k18 ); + } + level._cur_stage_name = "ts"; + clientnotify( "ts" ); +} + +stage_logic() +{ +/# + iprintlnbold( "TS Started" ); +#/ + level waittill( "sq_sign_damaged" ); + wait_network_frame(); + stage_completed( "sq", level._cur_stage_name ); +} + +exit_stage( success ) +{ +} + +ts_sign_damage_watch() +{ + level endon( "sq_sign_damaged" ); + self ts_sign_deactivate(); + while ( 1 ) + { + self waittill( "damage", n_damage, e_attacker, v_direction, v_point, str_type, str_tag, str_model, str_part, str_weapon ); + if ( flag( "sq_ts_quicktest" ) ) + { + level.m_sq_start_sign = self; + level.e_sq_sign_attacker = e_attacker; + level notify( "sq_sign_damaged" ); + } + if ( ts_is_bowie_knife( str_weapon ) || ts_is_galvaknuckles( str_weapon ) ) + { + if ( self.ts_sign_activated ) + { + self thread ts_sign_deactivate(); + } + else + { + self thread ts_sign_activate(); + } + ts_sign_check_all_activated( e_attacker, self ); + } + } +} + +ts_sign_activate() +{ + self.ts_sign_activated = 1; + while ( !isDefined( self.fx_ent ) ) + { + v_forward = anglesToForward( self.angles ); + v_offset = vectornormalize( v_forward ) * 2; + self.fx_ent = spawn( "script_model", ( self.origin - vectorScale( ( 0, 0, 1 ), 20 ) ) + v_offset ); + self.fx_ent.angles = anglesToForward( self.angles ); + self.fx_ent setmodel( "tag_origin" ); + self.fx_ent playsound( "zmb_sq_wisp_spawn" ); + self.fx_ent playloopsound( "zmb_sq_wisp_wall_loop" ); + while ( isDefined( self.fx_ent ) ) + { + playfxontag( level._effect[ "sq_ether_amp_trail" ], self.fx_ent, "tag_origin" ); + wait 0,3; + } + } +} + +ts_sign_deactivate() +{ + self.ts_sign_activated = 0; + if ( isDefined( self.fx_ent ) ) + { + self.fx_ent stoploopsound( 2 ); + self.fx_ent delete(); + } +} + +ts_sign_check_all_activated( e_attacker, m_last_touched ) +{ + a_signs = getentarray( "sq_tunnel_sign", "targetname" ); + a_signs_active = []; + is_max_complete = 1; + is_ric_complete = 1; + _a125 = a_signs; + _k125 = getFirstArrayKey( _a125 ); + while ( isDefined( _k125 ) ) + { + m_sign = _a125[ _k125 ]; + if ( m_sign.ts_sign_activated ) + { + a_signs_active[ a_signs_active.size ] = m_sign; + if ( !is_true( m_sign.is_max_sign ) ) + { + is_max_complete = 0; + } + if ( !is_true( m_sign.is_ric_sign ) ) + { + is_ric_complete = 0; + } + } + _k125 = getNextArrayKey( _a125, _k125 ); + } + if ( a_signs_active.size == 3 ) + { + if ( is_max_complete || is_ric_complete ) + { + level.m_sq_start_sign = m_last_touched; + level.e_sq_sign_attacker = e_attacker; + level notify( "sq_sign_damaged" ); + } + } +} + +ts_is_bowie_knife( str_weapon ) +{ + if ( str_weapon != "knife_ballistic_bowie_zm" || str_weapon == "knife_ballistic_bowie_upgraded_zm" && str_weapon == "bowie_knife_zm" ) + { + return 1; + } + return 0; +} + +ts_is_galvaknuckles( str_weapon ) +{ + if ( str_weapon == "tazer_knuckles_zm" ) + { + return 1; + } + return 0; +} diff --git a/zm_buried_patch/maps/mp/zm_buried_standard.gsc b/zm_buried_patch/maps/mp/zm_buried_standard.gsc new file mode 100644 index 0000000..e3ef7e0 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_standard.gsc @@ -0,0 +1,26 @@ +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ +} + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "processing" ); + maps/mp/zombies/_zm_game_module::set_current_game_module( level.game_module_standard_index ); + flag_wait( "initial_blackscreen_passed" ); + zm_treasure_chest_init(); +} + +zm_treasure_chest_init() +{ + chest1 = getstruct( "start_chest", "script_noteworthy" ); + level.chests = []; + level.chests[ level.chests.size ] = chest1; + maps/mp/zombies/_zm_magicbox::treasure_chest_init( "start_chest" ); +} diff --git a/zm_buried_patch/maps/mp/zm_buried_turned_street.gsc b/zm_buried_patch/maps/mp/zm_buried_turned_street.gsc new file mode 100644 index 0000000..7605876 --- /dev/null +++ b/zm_buried_patch/maps/mp/zm_buried_turned_street.gsc @@ -0,0 +1,64 @@ +#include maps/mp/gametypes_zm/zcleansed; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/_visionset_mgr; +#include maps/mp/zm_buried_gamemodes; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +precache() +{ + precachemodel( "zm_collision_buried_street_turned" ); + precachemodel( "p6_zm_bu_buildable_bench_tarp" ); + character/c_zom_zombie_buried_saloongirl_mp::precache(); + precachemodel( "c_zom_buried_zombie_sgirl_viewhands" ); + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_transit_burn", 1, 21, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); +} + +main() +{ + flag_init( "sloth_blocker_towneast" ); + level.custom_zombie_player_loadout = ::custom_zombie_player_loadout; + getspawnpoints(); + maps/mp/gametypes_zm/_zm_gametype::setup_standard_objects( "street" ); + generatebuildabletarps(); + deletechalktriggers(); + deleteslothbarricade( "candystore_alley" ); + deleteslothbarricades( 1 ); + deletebuyabledebris( 1 ); + powerswitchstate( 1 ); + level.cleansed_loadout = getgametypesetting( "cleansedLoadout" ); + if ( level.cleansed_loadout ) + { + level.humanify_custom_loadout = ::maps/mp/gametypes_zm/zcleansed::gunprogressionthink; + level.cleansed_zombie_round = 5; + } + else + { + level.humanify_custom_loadout = ::maps/mp/gametypes_zm/zcleansed::shotgunloadout; + level.cleansed_zombie_round = 2; + } + spawnmapcollision( "zm_collision_buried_street_turned" ); + flag_wait( "initial_blackscreen_passed" ); + flag_wait( "start_zombie_round_logic" ); + flag_set( "power_on" ); + clientnotify( "pwr" ); +} + +custom_zombie_player_loadout() +{ + self character/c_zom_zombie_buried_saloongirl_mp::main(); + self setviewmodel( "c_zom_buried_zombie_sgirl_viewhands" ); +} + +getspawnpoints() +{ + level._turned_zombie_spawners = getentarray( "game_mode_spawners", "targetname" ); + level._turned_zombie_spawnpoints = getstructarray( "street_turned_zombie_spawn", "targetname" ); + level._turned_zombie_respawnpoints = getstructarray( "street_turned_player_respawns", "targetname" ); + level._turned_powerup_spawnpoints = getstructarray( "street_turned_powerups", "targetname" ); +} + +onendgame() +{ +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_ghost.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_ghost.gsc new file mode 100644 index 0000000..8a0fd9f --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_ghost.gsc @@ -0,0 +1,2977 @@ +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_weap_time_bomb; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zombies/_zm_weap_slowgun; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_ai_ghost; +#include maps/mp/zombies/_zm_ai_ghost_ffotd; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zm_buried_ghost" ); + +precache() +{ +} + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +precache_fx() +{ + if ( !isDefined( level.ghost_effects ) ) + { + level.ghost_effects = []; + level.ghost_effects[ 1 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_death" ); + level.ghost_effects[ 2 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_drain" ); + level.ghost_effects[ 3 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_spawn" ); + level.ghost_effects[ 4 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_trail" ); + level.ghost_effects[ 5 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_evaporation" ); + level.ghost_impact_effects[ 1 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_impact" ); + } +} + +init() +{ + maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_init_start(); + register_client_fields(); + flag_init( "spawn_ghosts" ); + if ( !init_ghost_spawners() ) + { + return; + } + init_ghost_zone(); + init_ghost_sounds(); + init_ghost_script_move_path_data(); + level.zombie_ai_limit_ghost = 4; + level.zombie_ai_limit_ghost_per_player = 1; + level.zombie_ghost_count = 0; + level.ghost_health = 100; + level.zombie_ghost_round_states = spawnstruct(); + level.zombie_ghost_round_states.any_player_in_ghost_zone = 0; + level.zombie_ghost_round_states.active_zombie_locations = []; + level.is_ghost_round_started = ::is_ghost_round_started; + level.zombie_ghost_round_states.is_started = 0; + level.zombie_ghost_round_states.is_first_ghost_round_finished = 0; + level.zombie_ghost_round_states.current_ghost_round_number = 0; + level.zombie_ghost_round_states.next_ghost_round_number = 0; + level.zombie_ghost_round_states.presentation_stage_1_started = 0; + level.zombie_ghost_round_states.presentation_stage_2_started = 0; + level.zombie_ghost_round_states.presentation_stage_3_started = 0; + level.zombie_ghost_round_states.is_teleporting = 0; + level.zombie_ghost_round_states.round_count = 0; + level thread ghost_round_presentation_think(); + if ( isDefined( level.ghost_round_think_override_func ) ) + { + level thread [[ level.ghost_round_think_override_func ]](); + } + else + { + level thread ghost_round_think(); + } + level thread player_in_ghost_zone_monitor(); + if ( isDefined( level.ghost_zone_spawning_think_override_func ) ) + { + level thread [[ level.ghost_zone_spawning_think_override_func ]](); + } + else + { + level thread ghost_zone_spawning_think(); + } + level thread ghost_vox_think(); + init_time_bomb_ghost_rounds(); +/# + level.force_no_ghost = 0; + level.ghost_devgui_toggle_no_ghost = ::devgui_toggle_no_ghost; + level.ghost_devgui_warp_to_mansion = ::devgui_warp_to_mansion; +#/ + maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_init_end(); +} + +init_ghost_spawners() +{ + level.ghost_spawners = getentarray( "ghost_zombie_spawner", "script_noteworthy" ); + if ( level.ghost_spawners.size == 0 ) + { + return 0; + } + array_thread( level.ghost_spawners, ::add_spawn_function, ::prespawn ); + _a131 = level.ghost_spawners; + _k131 = getFirstArrayKey( _a131 ); + while ( isDefined( _k131 ) ) + { + spawner = _a131[ _k131 ]; + if ( spawner.targetname == "female_ghost" ) + { + level.female_ghost_spawner = spawner; + } + _k131 = getNextArrayKey( _a131, _k131 ); + } + return 1; +} + +init_ghost_script_move_path_data() +{ + level.ghost_script_move_sin = []; + degree = 0; + while ( degree < 360 ) + { + level.ghost_script_move_sin[ level.ghost_script_move_sin.size ] = sin( degree ); + degree += 15; + } +} + +init_ghost_sounds() +{ + level.ghost_vox = []; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_0"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_1"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_2"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_3"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_4"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_5"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_6"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_7"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_8"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_9"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_10"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_11"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_12"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_13"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_14"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_15"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_16"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_17"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_18"; + level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_19"; +} + +init_ghost_zone() +{ + level.ghost_start_area = getent( "ghost_start_area", "targetname" ); + level.ghost_zone_door_clips = getentarray( "ghost_zone_door_clip", "targetname" ); + enable_ghost_zone_door_ai_clips(); + level.ghost_zone_start_lower_locations = getstructarray( "ghost_zone_start_lower_location", "targetname" ); + level.ghost_drop_down_locations = getstructarray( "ghost_start_zone_spawners", "targetname" ); + level.ghost_front_standing_locations = getstructarray( "ghost_front_standing_location", "targetname" ); + level.ghost_back_standing_locations = getstructarray( "ghost_back_standing_location", "targetname" ); + level.ghost_front_flying_out_path_starts = getstructarray( "ghost_front_flying_out_path_start", "targetname" ); + level.ghost_back_flying_out_path_starts = getstructarray( "ghost_back_flying_out_path_start", "targetname" ); + level.ghost_gazebo_pit_volume = getent( "sloth_pack_volume", "targetname" ); + level.ghost_gazebo_pit_perk_pos = getstruct( "ghost_gazebo_pit_perk_pos", "targetname" ); + level.ghost_entry_room_to_mansion = "ghost_to_maze_zone_1"; + level.ghost_entry_room_to_maze = "ghost_to_maze_zone_5"; + level.ghost_rooms = []; + a_rooms = getentarray( "ghost_zone", "script_noteworthy" ); + _a216 = a_rooms; + _k216 = getFirstArrayKey( _a216 ); + while ( isDefined( _k216 ) ) + { + room = _a216[ _k216 ]; + str_targetname = room.targetname; + if ( !isDefined( level.ghost_rooms[ str_targetname ] ) ) + { + level.ghost_rooms[ str_targetname ] = spawnstruct(); + level.ghost_rooms[ str_targetname ].ghost_spawn_locations = []; + level.ghost_rooms[ str_targetname ].volumes = []; + level.ghost_rooms[ str_targetname ].name = str_targetname; + if ( issubstr( str_targetname, "from_maze" ) ) + { + level.ghost_rooms[ str_targetname ].from_maze = 1; + break; + } + else + { + if ( issubstr( str_targetname, "to_maze" ) ) + { + level.ghost_rooms[ str_targetname ].to_maze = 1; + } + } + } +/# + assert( isDefined( room.target ), "ghost zone with targetname '" + str_targetname + "' is missing spawner target! This is used to pair zones with spawners." ); +#/ + a_ghost_spawn_locations = getstructarray( room.target, "targetname" ); + level.ghost_rooms[ str_targetname ].ghost_spawn_locations = arraycombine( a_ghost_spawn_locations, level.ghost_rooms[ str_targetname ].ghost_spawn_locations, 0, 0 ); + level.ghost_rooms[ str_targetname ].volumes[ level.ghost_rooms[ str_targetname ].volumes.size ] = room; + if ( isDefined( room.script_string ) ) + { + level.ghost_rooms[ str_targetname ].next_room_names = strtok( room.script_string, " " ); + } + if ( isDefined( room.script_parameters ) ) + { + level.ghost_rooms[ str_targetname ].previous_room_names = strtok( room.script_parameters, " " ); + } + if ( isDefined( room.script_flag ) ) + { + level.ghost_rooms[ str_targetname ].flag = room.script_flag; + } + _k216 = getNextArrayKey( _a216, _k216 ); + } +} + +register_client_fields() +{ + registerclientfield( "actor", "ghost_impact_fx", 12000, 1, "int" ); + registerclientfield( "actor", "ghost_fx", 12000, 3, "int" ); + registerclientfield( "actor", "sndGhostAudio", 12000, 3, "int" ); + registerclientfield( "scriptmover", "ghost_fx", 12000, 3, "int" ); + registerclientfield( "scriptmover", "sndGhostAudio", 12000, 3, "int" ); + registerclientfield( "world", "ghost_round_light_state", 12000, 1, "int" ); +} + +is_player_fully_claimed( player ) +{ + result = 0; + if ( isDefined( player.ghost_count ) && player.ghost_count >= level.zombie_ai_limit_ghost_per_player ) + { + result = 1; + } + return result; +} + +ghost_zone_spawning_think() +{ + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + if ( !isDefined( level.female_ghost_spawner ) ) + { +/# + assertmsg( "No female ghost spawner in the map. Check to see if the zone is active and if it's pointing to spawners." ); +#/ + return; + } + while ( 1 ) + { + while ( level.zombie_ghost_count >= level.zombie_ai_limit_ghost ) + { + wait 0,1; + } + valid_player_count = 0; + valid_players = []; + while ( valid_player_count < 1 ) + { + players = getplayers(); + valid_player_count = 0; + _a319 = players; + _k319 = getFirstArrayKey( _a319 ); + while ( isDefined( _k319 ) ) + { + player = _a319[ _k319 ]; + if ( is_player_valid( player ) && !is_player_fully_claimed( player ) ) + { + if ( isDefined( player.is_in_ghost_zone ) || player.is_in_ghost_zone && is_ghost_round_started() && isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone ) + { + valid_player_count++; + valid_players[ valid_players.size ] = player; + } + } + _k319 = getNextArrayKey( _a319, _k319 ); + } + wait 0,1; + } + valid_players = array_randomize( valid_players ); + spawn_point = get_best_spawn_point( valid_players[ 0 ] ); + while ( !isDefined( spawn_point ) ) + { + wait 0,1; + } +/# + while ( isDefined( level.force_no_ghost ) && level.force_no_ghost ) + { + wait 0,1; +#/ + } + ghost_ai = undefined; + if ( isDefined( level.female_ghost_spawner ) ) + { + ghost_ai = spawn_zombie( level.female_ghost_spawner, level.female_ghost_spawner.targetname, spawn_point ); + } + else + { +/# + assertmsg( "No female ghost spawner in the map." ); +#/ + return; + } + if ( isDefined( ghost_ai ) ) + { + ghost_ai setclientfield( "ghost_fx", 3 ); + ghost_ai.spawn_point = spawn_point; + ghost_ai.is_ghost = 1; + ghost_ai.is_spawned_in_ghost_zone = 1; + ghost_ai.find_target = 1; + level.zombie_ghost_count++; +/# + ghost_print( "ghost total " + level.zombie_ghost_count ); +#/ + } + else + { +/# + assertmsg( "Female ghost: failed spawn" ); +#/ + return; + } + wait 0,1; + } +} + +is_player_in_ghost_room( player, room ) +{ + _a392 = room.volumes; + _k392 = getFirstArrayKey( _a392 ); + while ( isDefined( _k392 ) ) + { + volume = _a392[ _k392 ]; + if ( player istouching( volume ) ) + { + return 1; + } + _k392 = getNextArrayKey( _a392, _k392 ); + } + return 0; +} + +is_player_in_ghost_rooms( player, room_names ) +{ + result = 0; + while ( isDefined( room_names ) ) + { + _a408 = room_names; + _k408 = getFirstArrayKey( _a408 ); + while ( isDefined( _k408 ) ) + { + room_name = _a408[ _k408 ]; + next_room = level.ghost_rooms[ room_name ]; + if ( is_player_in_ghost_room( player, next_room ) ) + { + player.current_ghost_room_name = next_room.name; + result = 1; + break; + } + else + { + _k408 = getNextArrayKey( _a408, _k408 ); + } + } + } + return result; +} + +player_in_ghost_zone_monitor() +{ + level endon( "intermission" ); + if ( level.intermission ) + { + return; + } + while ( 1 ) + { + while ( isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone ) + { + players = getplayers(); + _a437 = players; + _k437 = getFirstArrayKey( _a437 ); + while ( isDefined( _k437 ) ) + { + player = _a437[ _k437 ]; + if ( is_player_valid( player ) && isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone ) + { + if ( isDefined( player.current_ghost_room_name ) ) + { + current_room = level.ghost_rooms[ player.current_ghost_room_name ]; +/# + _a448 = current_room.ghost_spawn_locations; + _k448 = getFirstArrayKey( _a448 ); + while ( isDefined( _k448 ) ) + { + ghost_location = _a448[ _k448 ]; + draw_debug_star( ghost_location.origin, ( 1, 1, 1 ), 2 ); + _k448 = getNextArrayKey( _a448, _k448 ); + } + _a452 = current_room.volumes; + _k452 = getFirstArrayKey( _a452 ); + while ( isDefined( _k452 ) ) + { + volume = _a452[ _k452 ]; + draw_debug_box( volume.origin, vectorScale( ( 1, 1, 1 ), 5 ), vectorScale( ( 1, 1, 1 ), 5 ), volume.angles[ 1 ], vectorScale( ( 1, 1, 1 ), 0,5 ), 2 ); + _k452 = getNextArrayKey( _a452, _k452 ); +#/ + } + if ( is_player_in_ghost_room( player, current_room ) ) + { + player.current_ghost_room_name = current_room.name; + break; + } + else if ( is_player_in_ghost_rooms( player, current_room.next_room_names ) ) + { + break; + } + else if ( is_player_in_ghost_rooms( player, current_room.previous_room_names ) ) + { + break; + } + else } + else player.current_ghost_room_name = level.ghost_entry_room_to_mansion; + } + _k437 = getNextArrayKey( _a437, _k437 ); + } + } + wait 0,1; + } +} + +is_any_player_near_point( target, spawn_pos ) +{ + players = getplayers(); + _a493 = players; + _k493 = getFirstArrayKey( _a493 ); + while ( isDefined( _k493 ) ) + { + player = _a493[ _k493 ]; + if ( target != player && is_player_valid( player ) ) + { + dist_squared = distancesquared( player.origin, spawn_pos ); + if ( dist_squared < ( 84 * 84 ) ) + { + return 1; + } + } + _k493 = getNextArrayKey( _a493, _k493 ); + } + return 0; +} + +is_in_start_area() +{ + if ( isDefined( level.ghost_start_area ) && self istouching( level.ghost_start_area ) ) + { + return 1; + } + return 0; +} + +get_best_spawn_point( player ) +{ + spawn_point = undefined; + if ( isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone ) + { + if ( isDefined( player.current_ghost_room_name ) ) + { + min_distance_squared = 9600 * 9600; + selected_locations = []; + current_ghost_room_name = player.current_ghost_room_name; + _a530 = level.ghost_rooms[ current_ghost_room_name ].ghost_spawn_locations; + _k530 = getFirstArrayKey( _a530 ); + while ( isDefined( _k530 ) ) + { + ghost_location = _a530[ _k530 ]; + player_eye_pos = player geteyeapprox(); + line_of_sight = sighttracepassed( player_eye_pos, ghost_location.origin, 0, self ); + if ( isDefined( line_of_sight ) && !line_of_sight ) + { + if ( !self is_any_player_near_point( player, ghost_location.origin ) ) + { + selected_locations[ selected_locations.size ] = ghost_location; + } + } + _k530 = getNextArrayKey( _a530, _k530 ); + } + if ( selected_locations.size > 0 ) + { + selected_location = selected_locations[ randomint( selected_locations.size ) ]; +/# + draw_debug_line( player.origin, selected_location.origin, ( 1, 1, 1 ), 10, 0 ); +#/ + return selected_location; + } + } + } + else + { + if ( is_ghost_round_started() && isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone ) + { + if ( isDefined( player.current_ghost_room_name ) && player.current_ghost_room_name == level.ghost_entry_room_to_maze ) + { + random_index = randomint( level.ghost_back_standing_locations.size ); + return level.ghost_back_standing_locations[ random_index ]; + } + else + { + if ( player is_in_start_area() ) + { + random_index = randomint( level.ghost_zone_start_lower_locations.size ); + return level.ghost_zone_start_lower_locations[ random_index ]; + } + else + { + random_index = randomint( level.ghost_front_standing_locations.size ); + return level.ghost_front_standing_locations[ random_index ]; + } + } + } + } + return undefined; +} + +check_players_in_ghost_zone() +{ + result = 0; + players = getplayers(); + _a589 = players; + _k589 = getFirstArrayKey( _a589 ); + while ( isDefined( _k589 ) ) + { + player = _a589[ _k589 ]; + if ( is_player_valid( player, 0, 1 ) && player_in_ghost_zone( player ) ) + { + result = 1; + } + _k589 = getNextArrayKey( _a589, _k589 ); + } + return result; +} + +player_in_ghost_zone( player ) +{ + result = 0; + if ( isDefined( level.is_player_in_ghost_zone ) ) + { + result = [[ level.is_player_in_ghost_zone ]]( player ); + } + player.is_in_ghost_zone = result; + return result; +} + +ghost_vox_think() +{ + level endon( "end_game" ); + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + while ( 1 ) + { + ghosts = get_current_ghosts(); + while ( ghosts.size > 0 ) + { + _a628 = ghosts; + _k628 = getFirstArrayKey( _a628 ); + while ( isDefined( _k628 ) ) + { + ghost = _a628[ _k628 ]; + if ( isDefined( ghost.favoriteenemy ) && isDefined( ghost.favoriteenemy.ghost_talking ) && !ghost.favoriteenemy.ghost_talking ) + { + ghost thread ghost_talk_to_target( ghost.favoriteenemy ); + } + _k628 = getNextArrayKey( _a628, _k628 ); + } + } + wait randomintrange( 2, 6 ); + } +} + +ghost_talk_to_target( player ) +{ + self endon( "death" ); + level endon( "intermission" ); + vox_index = randomint( level.ghost_vox.size ); + vox_line = level.ghost_vox[ vox_index ]; + self playsoundtoplayer( vox_line, player ); + player.ghost_talking = 1; + wait 6; + player.ghost_talking = 0; +} + +prespawn() +{ + self endon( "death" ); + level endon( "intermission" ); + self maps/mp/zombies/_zm_ai_ghost_ffotd::prespawn_start(); + self.startinglocation = self.origin; + self.animname = "ghost_zombie"; + self.audio_type = "ghost"; + self.has_legs = 1; + self.no_gib = 1; + self.ignore_enemy_count = 1; + self.ignore_equipment = 1; + self.ignore_claymore = 0; + self.force_killable_timer = 0; + self.noplayermeleeblood = 1; + self.paralyzer_hit_callback = ::paralyzer_callback; + self.paralyzer_slowtime = 0; + self.paralyzer_score_time_ms = getTime(); + self.ignore_slowgun_anim_rates = undefined; + self.reset_anim = ::ghost_reset_anim; + self.custom_springpad_fling = ::ghost_springpad_fling; + self.bookcase_entering_callback = ::bookcase_entering_callback; + self.ignore_subwoofer = 1; + self.ignore_headchopper = 1; + self.ignore_spring_pad = 1; + recalc_zombie_array(); + self setphysparams( 15, 0, 72 ); + self.cant_melee = 1; + if ( isDefined( self.spawn_point ) ) + { + spot = self.spawn_point; + if ( !isDefined( spot.angles ) ) + { + spot.angles = ( 1, 1, 1 ); + } + self forceteleport( spot.origin, spot.angles ); + } + self set_zombie_run_cycle( "run" ); + self setanimstatefromasd( "zm_move_run" ); + self.actor_damage_func = ::ghost_damage_func; + self.deathfunction = ::ghost_death_func; + self.maxhealth = level.ghost_health; + self.health = level.ghost_health; + self.zombie_init_done = 1; + self notify( "zombie_init_done" ); + self.allowpain = 0; + self.ignore_nuke = 1; + self animmode( "normal" ); + self orientmode( "face enemy" ); + self bloodimpact( "none" ); + self disableaimassist(); + self.forcemovementscriptstate = 0; + self maps/mp/zombies/_zm_spawner::zombie_setup_attack_properties(); + if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone ) + { + self.pathenemyfightdist = 0; + } + self maps/mp/zombies/_zm_spawner::zombie_complete_emerging_into_playable_area(); + self setfreecameralockonallowed( 0 ); + self.startinglocation = self.origin; + if ( isDefined( level.ghost_custom_think_logic ) ) + { + self [[ level.ghost_custom_think_logic ]](); + } + self.bad_path_failsafe = ::maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_bad_path_failsafe; + self thread ghost_think(); + self.attack_time = 0; + self.ignore_inert = 1; + self.subwoofer_burst_func = ::subwoofer_burst_func; + self.subwoofer_fling_func = ::subwoofer_fling_func; + self.subwoofer_knockdown_func = ::subwoofer_knockdown_func; + self maps/mp/zombies/_zm_ai_ghost_ffotd::prespawn_end(); +} + +bookcase_entering_callback( bookcase_door ) +{ + self endon( "death" ); + while ( 1 ) + { + if ( isDefined( bookcase_door._door_open ) && bookcase_door._door_open ) + { + if ( isDefined( bookcase_door.door_moving ) && bookcase_door.door_moving ) + { + self.need_wait = 1; + wait 2,1; + self.need_wait = 0; + } + else + { + self.need_wait = 0; + } + return; + } + else self.need_wait = 1; + wait 0,1; + } +} + +ghost_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( sweapon == "equip_headchopper_zm" ) + { + self.damageweapon_name = sweapon; + self check_zombie_damage_callbacks( smeansofdeath, shitloc, vpoint, eattacker, idamage ); + self.damageweapon_name = undefined; + } + if ( idamage >= self.health ) + { + self.killed_by = eattacker; + self thread prepare_to_die(); + } + self thread set_impact_effect(); + return idamage; +} + +set_impact_effect() +{ + self endon( "death" ); + self setclientfield( "ghost_impact_fx", 1 ); + wait_network_frame(); + self setclientfield( "ghost_impact_fx", 0 ); +} + +prepare_to_die() +{ + qrate = self getclientfield( "anim_rate" ); + if ( qrate < 0,8 ) + { + self.ignore_slowgun_anim_rates = 1; + self setclientfield( "anim_rate", 1 ); + qrate = self getclientfield( "anim_rate" ); + self setentityanimrate( qrate ); + self.slowgun_anim_rate = qrate; + wait_network_frame(); + self setclientfield( "anim_rate", 0,8 ); + qrate = self getclientfield( "anim_rate" ); + self setentityanimrate( qrate ); + wait_network_frame(); + ghost_reset_anim(); + } +} + +ghost_reset_anim() +{ + if ( !isDefined( self ) ) + { + return; + } + animstate = self getanimstatefromasd(); + substate = self getanimsubstatefromasd(); + if ( animstate == "zm_death" ) + { + self setanimstatefromasd( "zm_death_no_restart", substate ); + } + else + { + self maps/mp/zombies/_zm_weap_slowgun::reset_anim(); + } +} + +wait_ghost_ghost( time ) +{ + wait time; + if ( isDefined( self ) ) + { + self ghost(); + } +} + +ghost_death_func() +{ + if ( get_current_ghost_count() == 0 ) + { + level.ghost_round_last_ghost_origin = self.origin; + } + self stoploopsound( 1 ); + self playsound( "zmb_ai_ghost_death" ); + self setclientfield( "ghost_impact_fx", 1 ); + self setclientfield( "ghost_fx", 1 ); + self thread prepare_to_die(); + if ( isDefined( self.extra_custom_death_logic ) ) + { + self thread [[ self.extra_custom_death_logic ]](); + } + qrate = self getclientfield( "anim_rate" ); + self setanimstatefromasd( "zm_death" ); + self thread wait_ghost_ghost( self getanimlengthfromasd( "zm_death", 0 ) ); + maps/mp/animscripts/zm_shared::donotetracks( "death_anim" ); + if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone ) + { + level.zombie_ghost_count--; + + if ( isDefined( self.favoriteenemy ) ) + { + if ( isDefined( self.favoriteenemy.ghost_count ) && self.favoriteenemy.ghost_count > 0 ) + { + self.favoriteenemy.ghost_count--; + + } + } + } + player = undefined; + if ( is_player_valid( self.attacker ) ) + { + give_player_rewards( self.attacker ); + player = self.attacker; + } + else + { + if ( isDefined( self.attacker ) && is_player_valid( self.attacker.owner ) ) + { + give_player_rewards( self.attacker.owner ); + player = self.attacker.owner; + } + } + if ( isDefined( player ) ) + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_ghost_killed", 0 ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_ghost_killed" ); + } + self delete(); + return 1; +} + +subwoofer_burst_func( weapon ) +{ + self dodamage( self.health + 666, weapon.origin ); +} + +subwoofer_fling_func( weapon, fling_vec ) +{ + self dodamage( self.health + 666, weapon.origin ); +} + +subwoofer_knockdown_func( weapon, gib ) +{ +} + +ghost_think() +{ + self endon( "death" ); + level endon( "intermission" ); + if ( isDefined( level.ghost_round_presentation_ghost ) && level.ghost_round_presentation_ghost == self ) + { + return; + } + if ( isDefined( level.ghost_custom_think_func_logic ) ) + { + shouldwait = self [[ level.ghost_custom_think_func_logic ]](); + if ( shouldwait ) + { + self waittill( "ghost_custom_think_done", find_flesh_struct_string ); + } + } + self.ignore_slowgun_anim_rates = undefined; + self maps/mp/zombies/_zm_weap_slowgun::set_anim_rate( 1 ); + self setclientfield( "slowgun_fx", 0 ); + self setclientfield( "sndGhostAudio", 1 ); + self init_thinking(); + if ( isDefined( self.need_script_move ) && self.need_script_move ) + { + self start_script_move(); + } + else + { + if ( isDefined( self.is_spawned_in_ghost_zone ) && !self.is_spawned_in_ghost_zone && isDefined( self.respawned_by_time_bomb ) && !self.respawned_by_time_bomb ) + { + self start_spawn(); + } + else + { + self start_chase(); + } + } + if ( isDefined( self.bad_path_failsafe ) ) + { + self thread [[ self.bad_path_failsafe ]](); + } + while ( 1 ) + { + switch( self.state ) + { + case "script_move_update": + self script_move_update(); + break; + case "chase_update": + self chase_update(); + break; + case "drain_update": + self drain_update(); + break; + case "runaway_update": + self runaway_update(); + break; + case "evaporate_update": + self evaporate_update(); + break; + case "wait_update": + self wait_update(); + break; + } + wait 0,1; + } +} + +start_spawn() +{ + self animscripted( self.origin, self.angles, "zm_spawn" ); + self maps/mp/animscripts/zm_shared::donotetracks( "spawn_anim" ); + self start_chase(); +} + +init_thinking() +{ + self thread find_flesh(); +} + +find_flesh() +{ + self endon( "death" ); + level endon( "intermission" ); + self endon( "stop_find_flesh" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + self.nododgemove = 1; + self.ignore_player = []; + self zombie_history( "ghost find flesh -> start" ); + self.goalradius = 32; + while ( 1 ) + { + if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone ) + { + if ( isDefined( self.find_target ) && self.find_target ) + { + self.favoriteenemy = get_closest_valid_player( self.origin ); + self.find_target = 0; + } + } + else + { + self.favoriteenemy = get_closest_valid_player( self.origin ); + } + if ( isDefined( self.favoriteenemy ) ) + { + self thread zombie_pathing(); + } + else + { + if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone ) + { + self.find_target = 1; + } + } + 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( "ghost find flesh -> path timer done" ); + debug_print( "Zombie is re-acquiring enemy, ending breadcrumb search" ); + self notify( "zombie_acquire_enemy" ); + } +} + +get_closest_valid_player( origin ) +{ + valid_player_found = 0; + players = get_players(); + while ( !valid_player_found ) + { + player = get_closest_player( origin, players ); + if ( !isDefined( player ) ) + { + return undefined; + } + if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone ) + { + player_claimed_fully = is_player_fully_claimed( player ); + if ( players.size == 1 && player_claimed_fully ) + { + return undefined; + } + while ( is_player_valid( player, 1 ) && !is_ghost_round_started() && isDefined( player.is_in_ghost_zone ) || !player.is_in_ghost_zone && player_claimed_fully ) + { + arrayremovevalue( players, player ); + } + if ( isDefined( player.is_in_ghost_zone ) && !player.is_in_ghost_zone && !player is_in_start_area() ) + { + self.need_script_move = 1; + } + if ( !isDefined( player.ghost_count ) ) + { + player.ghost_count = 1; + } + else + { + player.ghost_count += 1; + } + } + else + { + while ( !is_player_valid( player, 1 ) ) + { + arrayremovevalue( players, player ); + } + } + return player; + } +} + +get_closest_player( origin, players ) +{ + min_length_to_player = 9999999; + player_to_return = undefined; + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + length_to_player = get_path_length_to_enemy( player ); + if ( length_to_player == 0 ) + { + i++; + continue; + } + else + { + if ( length_to_player < min_length_to_player ) + { + min_length_to_player = length_to_player; + player_to_return = player; + } + } + i++; + } + if ( !isDefined( player_to_return ) ) + { + player_to_return = getclosest( origin, players ); + } + return player_to_return; +} + +does_fall_into_pap_hole() +{ + if ( self istouching( level.ghost_gazebo_pit_volume ) ) + { + self forceteleport( level.ghost_gazebo_pit_perk_pos.origin, ( 1, 1, 1 ) ); + wait 0,1; + return 1; + } + return 0; +} + +start_script_move() +{ + self.script_mover = spawn( "script_origin", self.origin ); + self.script_mover.angles = self.angles; + self linkto( self.script_mover ); + self.state = "script_move_update"; + self setclientfield( "ghost_fx", 4 ); + player = self.favoriteenemy; + if ( is_player_valid( player ) ) + { + start_location = undefined; + if ( isDefined( player.current_ghost_room_name ) && player.current_ghost_room_name == level.ghost_entry_room_to_maze ) + { + start_location = level.ghost_back_flying_out_path_starts[ 0 ]; + } + else + { + start_location = level.ghost_front_flying_out_path_starts[ 0 ]; + } + self.script_move_target_node = self get_best_flying_target_node( player, start_location.origin ); + } + self.script_move_sin_index = 0; +} + +get_best_flying_target_node( player, start_loc ) +{ + nearest_node = getnearestnode( player.origin ); + nodes = getnodesinradiussorted( player.origin, 540, 180, 60, "Path" ); + if ( !isDefined( nearest_node ) && nodes.size > 0 ) + { + nearest_node = nodes[ 0 ]; + } + selected_node = nearest_node; + max_distance_squared = 0; + start_pos = ( player.origin[ 0 ], player.origin[ 1 ], player.origin[ 2 ] + 60 ); + i = nodes.size - 1; + while ( i >= 0 ) + { + node = nodes[ i ]; + end_pos = ( node.origin[ 0 ], node.origin[ 1 ], node.origin[ 2 ] + 60 ); + line_of_sight = sighttracepassed( start_pos, end_pos, 0, player ); + if ( isDefined( line_of_sight ) && line_of_sight ) + { + draw_debug_star( node.origin, ( 1, 1, 1 ), 100 ); + if ( is_within_view_2d( node.origin, player.origin, player.angles, 0,86 ) ) + { + selected_node = node; + break; + } + else + { + selected_node = node; + } + i--; + + } + } + return selected_node; +} + +script_move_update() +{ + if ( isDefined( self.is_traversing ) && self.is_traversing ) + { + return; + } + player = self.favoriteenemy; + if ( is_player_valid( player ) && isDefined( self.script_move_target_node ) ) + { + desired_angles = vectorToAngle( vectornormalize( player.origin - self.origin ) ); + distance_squared = distancesquared( self.origin, self.script_move_target_node.origin ); + if ( distance_squared < 24 ) + { + self.script_mover.angles = desired_angles; + self remove_script_mover(); + wait_network_frame(); + self setclientfield( "ghost_fx", 3 ); + self setclientfield( "sndGhostAudio", 1 ); + wait_network_frame(); + self start_chase(); + return; + } + draw_debug_star( self.script_move_target_node.origin, ( 1, 1, 1 ), 1 ); + target_node_pos = self.script_move_target_node.origin + vectorScale( ( 1, 1, 1 ), 36 ); + distance_squared_to_target_node_pos = distancesquared( self.origin, target_node_pos ); + moved_distance_during_interval = 80; + if ( distance_squared_to_target_node_pos <= ( moved_distance_during_interval * moved_distance_during_interval ) ) + { + target_point = self.script_move_target_node.origin; + self.script_mover moveto( target_point, 0,1, 0, 0,1 ); + self.script_mover waittill( "movedone" ); + self.script_mover.angles = desired_angles; + } + else + { + distance_squared_to_player = distancesquared( self.origin, player.origin ); + if ( distance_squared_to_player < 540 && isDefined( self.script_mover.search_target_node_again ) && !self.script_mover.search_target_node_again ) + { + self get_best_flying_target_node( player, self.script_move_target_node.origin ); + self.script_mover.search_target_node_again = 1; + } + if ( self.script_move_sin_index >= level.ghost_script_move_sin.size ) + { + self.script_move_sin_index = 0; + } + move_dir = target_node_pos - self.origin; + move_dir = vectornormalize( move_dir ); + target_point = self.origin + ( ( move_dir * 800 ) * 0,1 ); + x_offset = level.ghost_script_move_sin[ self.script_move_sin_index ] * 6; + z_offset = level.ghost_script_move_sin[ self.script_move_sin_index ] * 12; + target_point += ( x_offset, 0, z_offset ); + self.script_move_sin_index++; + self.script_mover moveto( target_point, 0,1 ); + self.script_mover.angles = desired_angles; + draw_debug_star( target_point, ( 1, 1, 1 ), 1 ); + } + } + else + { + self remove_script_mover(); + self start_evaporate( 1 ); + } +} + +remove_script_mover() +{ + if ( isDefined( self.script_mover ) ) + { + self dontinterpolate(); + self unlink(); + self.script_mover delete(); + } +} + +start_chase() +{ + self set_zombie_run_cycle( "run" ); + self setanimstatefromasd( "zm_move_run" ); + self.state = "chase_update"; + self setclientfield( "ghost_fx", 4 ); +} + +chase_update() +{ + if ( isDefined( self.is_traversing ) && self.is_traversing ) + { + return; + } + player = self.favoriteenemy; + if ( is_player_valid( player ) ) + { + if ( self should_runaway( player ) ) + { + self start_runaway(); + return; + } + if ( self does_fall_into_pap_hole() ) + { + self dodamage( self.health + 666, self.origin ); + return; + } + if ( self need_wait() ) + { + self start_wait(); + return; + } + ghost_check_point = self.origin + ( 0, 0, 60 ); + player_eye_pos = player geteyeapprox(); + line_of_sight = sighttracepassed( ghost_check_point, player_eye_pos, 0, self ); + if ( isDefined( line_of_sight ) && line_of_sight && can_drain_points( self.origin, player.origin ) ) + { + self start_drain(); + return; + } + distsquared = distancesquared( self.origin, player.origin ); + if ( distsquared > ( 300 * 300 ) ) + { + if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone && isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone && isDefined( player.current_ghost_room_name ) ) + { + current_room = level.ghost_rooms[ player.current_ghost_room_name ]; + if ( isDefined( current_room.flag ) && current_room.flag != "no_cleanup" || self is_in_close_rooms( current_room ) && self is_in_room( current_room ) && !self is_following_room_path( player, current_room ) ) + { + set_chase_status( "run" ); + } + else + { + self start_evaporate( 1 ); + } + } + else + { + set_chase_status( "run" ); + if ( distsquared > ( 9600 * 9600 ) ) + { + teleport_location = level.ghost_front_flying_out_path_starts[ 0 ]; + self forceteleport( teleport_location.origin, ( 1, 1, 1 ) ); + } + } + } + else if ( distsquared > ( 144 * 144 ) ) + { + set_chase_status( "run" ); + } + else + { + set_chase_status( "walk" ); + } + } + else + { + self set_zombie_run_cycle( "run" ); + if ( self getanimstatefromasd() != "zm_move_run" ) + { + self setanimstatefromasd( "zm_move_run" ); + } + self start_runaway(); + } +} + +need_wait() +{ + if ( isDefined( self.need_wait ) ) + { + return self.need_wait; + } +} + +start_wait() +{ + self setanimstatefromasd( "zm_idle" ); + self setclientfield( "ghost_fx", 4 ); + self.state = "wait_update"; +} + +wait_update() +{ + if ( isDefined( self.is_traversing ) && self.is_traversing ) + { + return; + } + player = self.favoriteenemy; + if ( is_player_valid( player ) ) + { + ghost_check_point = self.origin + ( 0, 0, 60 ); + player_eye_pos = player geteyeapprox(); + line_of_sight = sighttracepassed( ghost_check_point, player_eye_pos, 0, self ); + if ( isDefined( line_of_sight ) && line_of_sight && can_drain_points( self.origin, player.origin ) ) + { + self start_drain(); + return; + } + if ( !self need_wait() ) + { + self start_chase(); + } + } + else + { + self set_zombie_run_cycle( "run" ); + if ( self getanimstatefromasd() != "zm_move_run" ) + { + self setanimstatefromasd( "zm_move_run" ); + } + self setclientfield( "ghost_fx", 4 ); + self start_runaway(); + } +} + +start_evaporate( need_deletion ) +{ + self setclientfield( "ghost_fx", 5 ); + wait 0,1; + if ( isDefined( need_deletion ) && need_deletion ) + { + level.zombie_ghost_count--; + + if ( isDefined( self.favoriteenemy ) ) + { + if ( isDefined( self.favoriteenemy.ghost_count ) && self.favoriteenemy.ghost_count > 0 ) + { + self.favoriteenemy.ghost_count--; + + } + } + self delete(); + } + else + { + self.state = "evaporate_update"; + self ghost(); + self notsolid(); + } +} + +should_be_deleted_during_evaporate_update( player ) +{ + if ( isDefined( self.is_spawned_in_ghost_zone ) && !self.is_spawned_in_ghost_zone ) + { + return 0; + } + if ( !isDefined( player ) ) + { + return 1; + } + if ( isDefined( player.sessionstate ) || player.sessionstate == "spectator" && player.sessionstate == "intermission" ) + { + return 1; + } + return 0; +} + +evaporate_update() +{ + player = self.favoriteenemy; + if ( should_be_deleted_during_evaporate_update( player ) ) + { + if ( level.zombie_ghost_count > 0 ) + { + level.zombie_ghost_count--; + + } + self delete(); + } + else + { + if ( is_player_valid( player ) ) + { + self solid(); + self show(); + self start_chase(); + } + } +} + +is_within_capsule( point, origin, angles, radius, range ) +{ + forward_dir = vectornormalize( anglesToForward( angles ) ); + start = origin + ( forward_dir * radius ); + end = start + ( forward_dir * range ); + point_intersect = pointonsegmentnearesttopoint( start, end, point ); + distance_squared = distancesquared( point_intersect, point ); + if ( distance_squared <= ( radius * radius ) ) + { + return 1; + } + return 0; +} + +is_within_view_2d( point, origin, angles, fov_cos ) +{ + dot = get_dot_production_2d( point, origin, angles ); + if ( dot > fov_cos ) + { + return 1; + } + return 0; +} + +get_dot_production_2d( point, origin, angles ) +{ + forward_dir = anglesToForward( angles ); + forward_dir = ( forward_dir[ 0 ], forward_dir[ 1 ], 0 ); + forward_dir = vectornormalize( forward_dir ); + to_point_dir = point - origin; + to_point_dir = ( to_point_dir[ 0 ], to_point_dir[ 1 ], 0 ); + to_point_dir = vectornormalize( to_point_dir ); + return vectordot( forward_dir, to_point_dir ); +} + +is_in_room( room ) +{ + _a1702 = room.volumes; + _k1702 = getFirstArrayKey( _a1702 ); + while ( isDefined( _k1702 ) ) + { + volume = _a1702[ _k1702 ]; + if ( self istouching( volume ) ) + { + return 1; + } + _k1702 = getNextArrayKey( _a1702, _k1702 ); + } + return 0; +} + +is_in_rooms( room_names ) +{ + _a1715 = room_names; + _k1715 = getFirstArrayKey( _a1715 ); + while ( isDefined( _k1715 ) ) + { + room_name = _a1715[ _k1715 ]; + room = level.ghost_rooms[ room_name ]; + if ( self is_in_room( room ) ) + { + return 1; + } + _k1715 = getNextArrayKey( _a1715, _k1715 ); + } + return 0; +} + +is_in_next_rooms( room ) +{ + if ( self is_in_rooms( room.next_room_names ) ) + { + return 1; + } + return 0; +} + +is_in_close_rooms( room ) +{ + _a1742 = room.next_room_names; + _k1742 = getFirstArrayKey( _a1742 ); + while ( isDefined( _k1742 ) ) + { + next_room_name = _a1742[ _k1742 ]; + next_room = level.ghost_rooms[ next_room_name ]; + if ( self is_in_rooms( next_room.next_room_names ) ) + { + return 1; + } + _k1742 = getNextArrayKey( _a1742, _k1742 ); + } + if ( self is_in_rooms( room.next_room_names ) ) + { + return 1; + } + return 0; +} + +is_following_room_path( player, room ) +{ + if ( isDefined( room.volumes[ 0 ].script_angles ) ) + { + dot = get_dot_production_2d( player.origin, self.origin, room.volumes[ 0 ].script_angles ); + if ( dot > 0 ) + { + return 1; + } + } + return 0; +} + +can_drain_points( self_pos, target_pos ) +{ + if ( isDefined( self.force_killable ) && self.force_killable ) + { + return 0; + } + dist = distancesquared( self_pos, target_pos ); + if ( dist < ( 60 * 60 ) ) + { + return 1; + } + return 0; +} + +set_chase_status( move_speed ) +{ + self setclientfield( "ghost_fx", 4 ); + if ( self.zombie_move_speed != move_speed ) + { + self set_zombie_run_cycle( move_speed ); + self setanimstatefromasd( "zm_move_" + move_speed ); + } +} + +start_drain() +{ + self setanimstatefromasd( "zm_drain" ); + self setclientfield( "ghost_fx", 2 ); + self.state = "drain_update"; +} + +drain_update() +{ + if ( isDefined( self.is_traversing ) && self.is_traversing ) + { + return; + } + player = self.favoriteenemy; + if ( is_player_valid( player ) ) + { + if ( can_drain_points( self.origin, player.origin ) ) + { + if ( self getanimstatefromasd() != "zm_drain" ) + { + self setanimstatefromasd( "zm_drain" ); + } + self orientmode( "face enemy" ); + if ( isDefined( self.is_draining ) && !self.is_draining ) + { + self thread drain_player( player ); + } + } + else + { + self start_chase(); + } + } + else + { + self set_zombie_run_cycle( "run" ); + if ( self getanimstatefromasd() != "zm_move_run" ) + { + self setanimstatefromasd( "zm_move_run" ); + } + self setclientfield( "ghost_fx", 4 ); + self start_runaway(); + } +} + +drain_player( player ) +{ + self endon( "death" ); + self.is_draining = 1; + player_drained = 0; + points_to_drain = 2000; + if ( player.score < points_to_drain ) + { + if ( player.score > 0 ) + { + points_to_drain = player.score; + } + else + { + points_to_drain = 0; + } + } + if ( points_to_drain > 0 ) + { + player maps/mp/zombies/_zm_score::minus_to_player_score( points_to_drain ); + player_drained = 1; + player playsoundtoplayer( "zmb_ai_ghost_money_drain", player ); + level notify( "ghost_drained_player" ); + } + else + { + if ( player.health > 0 && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + player dodamage( 25, self.origin, self ); + player_drained = 1; + level notify( "ghost_damaged_player" ); + } + } + if ( player_drained ) + { + give_player_rewards( player ); + player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_ghost_drained_player", 0 ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_ghost_drained_player" ); + wait 2; + } + self.is_draining = 0; +} + +should_runaway( player ) +{ + result = 0; + if ( !is_ghost_round_started() && isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone && isDefined( player.is_in_ghost_zone ) && !player.is_in_ghost_zone ) + { + path_lenth = self getpathlength(); + if ( path_lenth == 0 ) + { + result = 1; + } + } + return result; +} + +start_runaway() +{ + wait 2; + self.state = "runaway_update"; + self setgoalpos( self.startinglocation ); + self set_chase_status( "run" ); +} + +does_reach_runaway_goal() +{ + result = 0; + dist_squared = distancesquared( self.origin, self.startinglocation ); + if ( dist_squared < ( 60 * 60 ) ) + { + result = 1; + } + return result; +} + +runaway_update() +{ + if ( isDefined( self.is_traversing ) && self.is_traversing ) + { + return; + } + player = self.favoriteenemy; + if ( is_player_valid( player ) || is_ghost_round_started() && isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone ) + { + self.state = "chase_update"; + return; + } + if ( self does_fall_into_pap_hole() ) + { + self dodamage( self.health + 666, self.origin ); + return; + } + if ( self does_reach_runaway_goal() ) + { + should_delete = 1; + if ( is_ghost_round_started() || isDefined( self.is_spawned_in_ghost_zone ) && !self.is_spawned_in_ghost_zone ) + { + should_delete = 0; + } + self start_evaporate( should_delete ); + } + else + { + self setgoalpos( self.startinglocation ); +/# + draw_debug_star( self.startinglocation, ( 1, 1, 1 ), 1 ); + draw_debug_line( self.origin, self.startinglocation, ( 1, 1, 1 ), 1, 0 ); +#/ + } +} + +paralyzer_callback( player, upgraded ) +{ + if ( isDefined( self.ignore_slowgun_anim_rates ) && self.ignore_slowgun_anim_rates ) + { + return; + } + if ( upgraded ) + { + self setclientfield( "slowgun_fx", 5 ); + } + else + { + self setclientfield( "slowgun_fx", 1 ); + } + self maps/mp/zombies/_zm_weap_slowgun::zombie_slow_for_time( 0,3, 0 ); +} + +ghost_springpad_fling( weapon, attacker ) +{ + self dodamage( self.health + 666, self.origin ); + weapon.springpad_kills++; +} + +ghost_print( str ) +{ +/# + if ( getDvarInt( #"151B6F17" ) ) + { + iprintln( "ghost: " + 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; +#/ + } + } + } +} + +ghost_round_think() +{ + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + for ( ;; ) + { + while ( 1 ) + { + level.zombie_ghost_round_states.any_player_in_ghost_zone = check_players_in_ghost_zone(); + if ( can_start_ghost_round() ) + { + if ( ghost_round_start_conditions_met() ) + { + start_ghost_round(); + break; + } + else + { + wait 0,1; + } + } + while ( 1 ) + { + if ( can_end_ghost_round() ) + { + wait 0,5; + end_ghost_round(); + break; + } + else + { + level.zombie_ghost_round_states.any_player_in_ghost_zone = check_players_in_ghost_zone(); + if ( isDefined( level.ghost_zone_teleport_logic ) ) + { + [[ level.ghost_zone_teleport_logic ]](); + } + if ( isDefined( level.ghost_zone_fountain_teleport_logic ) ) + { + [[ level.ghost_zone_fountain_teleport_logic ]](); + } + wait 0,1; + } + } + } + else check_sending_away_zombie_followers(); + wait 0,1; + } +} + +ghost_round_start_conditions_met() +{ + if ( isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone ) + { + b_conditions_met = !is_ghost_round_started(); + } + if ( isDefined( level.force_ghost_round_start ) || level.force_ghost_round_start && is_ghost_round_started() ) + { + b_conditions_met = 1; + } + return b_conditions_met; +} + +can_start_ghost_round() +{ +/# + if ( isDefined( level.force_no_ghost ) && level.force_no_ghost ) + { + return 0; +#/ + } + result = 0; + if ( isDefined( level.zombie_ghost_round_states ) ) + { + if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) || !level.zombie_ghost_round_states.is_first_ghost_round_finished && level.round_number >= level.zombie_ghost_round_states.next_ghost_round_number ) + { + result = 1; + } + } + if ( isDefined( level.force_ghost_round_start ) && level.force_ghost_round_start ) + { + result = 1; + } + return result; +} + +set_ghost_round_number() +{ + if ( isDefined( level.zombie_ghost_round_states ) ) + { + level.zombie_ghost_round_states.current_ghost_round_number = level.round_number; + level.zombie_ghost_round_states.next_ghost_round_number = level.round_number + randomintrange( 4, 6 ); + } +} + +is_ghost_round_started() +{ + if ( isDefined( level.zombie_ghost_round_states ) ) + { + return level.zombie_ghost_round_states.is_started; + } + return 0; +} + +start_ghost_round() +{ + level.zombie_ghost_round_states.is_started = 1; + level.zombie_ghost_round_states.round_count++; + flag_clear( "spawn_zombies" ); + flag_set( "spawn_ghosts" ); + disable_ghost_zone_door_ai_clips(); + clear_all_active_zombies(); + set_ghost_round_number(); + increase_ghost_health(); + ghost_round_presentation_reset(); + wait 0,5; + level thread sndghostroundmus(); + level thread outside_ghost_zone_spawning_think(); + level thread player_moving_speed_scale_think(); + if ( !flag( "time_bomb_restore_active" ) ) + { + level.force_ghost_round_start = undefined; + } + maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_round_start(); +} + +increase_ghost_health() +{ + if ( level.zombie_ghost_round_states.round_count == 1 ) + { + new_health = level.ghost_health + 300; + if ( level.round_number > 5 ) + { + new_health = int( 1600 * ( level.round_number / 20 ) ); + } + level.ghost_health = new_health; + } + else if ( level.zombie_ghost_round_states.round_count == 2 ) + { + level.ghost_health += 500; + } + else if ( level.zombie_ghost_round_states.round_count == 3 ) + { + level.ghost_health += 400; + } + else + { + if ( level.zombie_ghost_round_states.round_count == 4 ) + { + level.ghost_health = 1600; + } + } + if ( level.ghost_health > 1600 ) + { + level.ghost_health = 1600; + } +} + +enable_ghost_zone_door_ai_clips() +{ + while ( isDefined( level.ghost_zone_door_clips ) && level.ghost_zone_door_clips.size > 0 ) + { + _a2256 = level.ghost_zone_door_clips; + _k2256 = getFirstArrayKey( _a2256 ); + while ( isDefined( _k2256 ) ) + { + door_clip = _a2256[ _k2256 ]; + door_clip solid(); + door_clip disconnectpaths(); + _k2256 = getNextArrayKey( _a2256, _k2256 ); + } + } +} + +disable_ghost_zone_door_ai_clips() +{ + while ( isDefined( level.ghost_zone_door_clips ) && level.ghost_zone_door_clips.size > 0 ) + { + _a2269 = level.ghost_zone_door_clips; + _k2269 = getFirstArrayKey( _a2269 ); + while ( isDefined( _k2269 ) ) + { + door_clip = _a2269[ _k2269 ]; + door_clip notsolid(); + door_clip connectpaths(); + _k2269 = getNextArrayKey( _a2269, _k2269 ); + } + } +} + +clear_all_active_zombies() +{ + zombies = get_round_enemy_array(); + while ( isDefined( zombies ) ) + { + level.zombie_ghost_round_states.round_zombie_total = level.zombie_total + zombies.size; + _a2288 = zombies; + _k2288 = getFirstArrayKey( _a2288 ); + while ( isDefined( _k2288 ) ) + { + zombie = _a2288[ _k2288 ]; + if ( isDefined( zombie.is_ghost ) && !zombie.is_ghost ) + { + spawn_point = spawnstruct(); + spawn_point.origin = zombie.origin; + spawn_point.angles = zombie.angles; + if ( isDefined( zombie.completed_emerging_into_playable_area ) && !zombie.completed_emerging_into_playable_area ) + { + if ( isDefined( zombie.spawn_point ) && isDefined( zombie.spawn_point.script_string ) ) + { + no_barrier_target = zombie.spawn_point.script_string == "find_flesh"; + } + if ( no_barrier_target ) + { + if ( isDefined( zombie.spawn_point.script_noteworthy ) && zombie.spawn_point.script_noteworthy == "faller_location" ) + { + ground_pos = groundpos_ignore_water_new( zombie.spawn_point.origin ); + spawn_point.origin = ground_pos; + } + } + else + { + origin = zombie.origin; + desired_origin = zombie get_desired_origin(); + if ( isDefined( desired_origin ) ) + { + origin = desired_origin; + } + nodes = get_array_of_closest( origin, level.exterior_goals, undefined, 1 ); + if ( nodes.size > 0 ) + { + spawn_point.origin = nodes[ 0 ].neg_end.origin; + spawn_point.angles = nodes[ 0 ].neg_end.angles; + } + } + } + else + { + if ( isDefined( level.sloth ) && isDefined( level.sloth.crawler ) && zombie == level.sloth.crawler ) + { + spawn_point.origin = level.sloth.origin; + spawn_point.angles = level.sloth.angles; + } + } + level.zombie_ghost_round_states.active_zombie_locations[ level.zombie_ghost_round_states.active_zombie_locations.size ] = spawn_point; + zombie.nodeathragdoll = 1; + zombie.turning_into_ghost = 1; + if ( isalive( zombie ) ) + { + zombie dodamage( zombie.health + 666, zombie.origin ); + } + } + _k2288 = getNextArrayKey( _a2288, _k2288 ); + } + } +} + +reset_ghost_round_states() +{ + if ( !isDefined( level.zombie_ghost_round_states.round_zombie_total ) ) + { + level.zombie_ghost_round_states.round_zombie_total = 0; + } + level.zombie_ghost_round_states.is_started = 0; + if ( should_restore_zombie_total() ) + { + if ( level.zombie_ghost_round_states.round_zombie_total > 0 ) + { + level.zombie_total = level.zombie_ghost_round_states.round_zombie_total; + } + } + level.zombie_ghost_round_states.round_zombie_total = 0; + level.zombie_ghost_round_states.active_zombie_locations = []; + if ( is_false( level.zombie_ghost_round_states.is_first_ghost_round_finished ) ) + { + level.zombie_ghost_round_states.is_first_ghost_round_finished = 1; + } +} + +should_restore_zombie_total() +{ + if ( flag( "time_bomb_restore_active" ) ) + { + if ( flag( "time_bomb_restore_active" ) ) + { + return maps/mp/zombies/_zm_weap_time_bomb::get_time_bomb_saved_round_type() == "ghost"; + } + } +} + +can_end_ghost_round() +{ + if ( isDefined( level.force_ghost_round_end ) && level.force_ghost_round_end ) + { + return 1; + } + if ( isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && !level.zombie_ghost_round_states.any_player_in_ghost_zone && get_current_ghost_count() <= 0 ) + { + return 1; + } + return 0; +} + +end_ghost_round() +{ + reset_ghost_round_states(); + if ( should_last_ghost_drop_powerup() ) + { + trace = groundtrace( level.ghost_round_last_ghost_origin + vectorScale( ( 1, 1, 1 ), 10 ), level.ghost_round_last_ghost_origin + vectorScale( ( 1, 1, 1 ), 150 ), 0, undefined, 1 ); + power_up_origin = trace[ "position" ]; + powerup = level thread maps/mp/zombies/_zm_powerups::specific_powerup_drop( "free_perk", power_up_origin ); + if ( isDefined( powerup ) ) + { + powerup.ghost_powerup = 1; + } + level.ghost_round_last_ghost_origin_last = level.ghost_round_last_ghost_origin; + level.ghost_round_last_ghost_origin = undefined; + } + level setclientfield( "ghost_round_light_state", 0 ); + enable_ghost_zone_door_ai_clips(); + level notify( "ghost_round_end" ); + if ( isDefined( level.force_ghost_round_end ) && level.force_ghost_round_end ) + { + level.force_ghost_round_end = undefined; + return; + } + flag_set( "spawn_zombies" ); + flag_clear( "spawn_ghosts" ); + maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_round_end(); +} + +should_last_ghost_drop_powerup() +{ + if ( flag( "time_bomb_restore_active" ) ) + { + return 0; + } + if ( !isDefined( level.ghost_round_last_ghost_origin ) ) + { + return 0; + } + return 1; +} + +sndghostroundmus() +{ + level endon( "ghost_round_end" ); + ent = spawn( "script_origin", ( 1, 1, 1 ) ); + level.sndroundwait = 1; + ent thread sndghostroundmus_end(); + ent endon( "sndGhostRoundEnd" ); + ent playsound( "mus_ghost_round_start" ); + wait 11; + ent playloopsound( "mus_ghost_round_loop", 3 ); +} + +sndghostroundmus_end() +{ + level waittill( "ghost_round_end" ); + self notify( "sndGhostRoundEnd" ); + self stoploopsound( 1 ); + self playsoundwithnotify( "mus_ghost_round_over", "stingerDone" ); + self waittill( "stingerDone" ); + self delete(); + level.sndroundwait = 0; +} + +sndghostroundready() +{ + level notify( "sndGhostRoundReady" ); + level endon( "sndGhostRoundReady" ); + mansion = ( 2830, 555, 436 ); + while ( 1 ) + { + level waittill( "between_round_over" ); + if ( level.zombie_ghost_round_states.next_ghost_round_number == level.round_number ) + { + playsoundatposition( "zmb_ghost_round_srt", mansion ); + ent = spawn( "script_origin", mansion ); + ent playloopsound( "zmb_ghost_round_lp", 3 ); + ent thread sndghostroundready_stoplp(); + break; + } + else + { + } + } + wait 15; + level notify( "sndStopRoundReadyLp" ); +} + +sndghostroundready_stoplp() +{ + level waittill_either( "sndStopRoundReadyLp", "sndGhostRoundReady" ); + self stoploopsound( 3 ); + wait 3; + self delete(); +} + +check_sending_away_zombie_followers() +{ + if ( flag_exists( "time_bomb_restore_active" ) && flag( "time_bomb_restore_active" ) ) + { + return; + } + players = getplayers(); + valid_player_in_ghost_zone_count = 0; + valid_player_count = 0; + _a2522 = players; + _k2522 = getFirstArrayKey( _a2522 ); + while ( isDefined( _k2522 ) ) + { + player = _a2522[ _k2522 ]; + if ( is_player_valid( player ) ) + { + valid_player_count++; + if ( isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone ) + { + valid_player_in_ghost_zone_count++; + break; + } + else + { + player.zombie_followers_sent_away = 0; + } + } + _k2522 = getNextArrayKey( _a2522, _k2522 ); + } + if ( valid_player_count > 0 && valid_player_in_ghost_zone_count == valid_player_count ) + { + if ( flag( "spawn_zombies" ) ) + { + flag_clear( "spawn_zombies" ); + } + zombies = get_round_enemy_array(); + _a2561 = zombies; + _k2561 = getFirstArrayKey( _a2561 ); + while ( isDefined( _k2561 ) ) + { + zombie = _a2561[ _k2561 ]; + if ( is_true( zombie.completed_emerging_into_playable_area ) && !is_true( zombie.zombie_path_bad ) ) + { + zombie notify( "bad_path" ); + } + _k2561 = getNextArrayKey( _a2561, _k2561 ); + } + } + else if ( !flag( "spawn_zombies" ) ) + { + flag_set( "spawn_zombies" ); + } +} + +send_away_zombie_follower( player ) +{ + self endon( "death" ); + dist_zombie = 0; + dist_player = 0; + dest = 0; + awaydir = self.origin - player.origin; + awaydir = ( awaydir[ 0 ], awaydir[ 1 ], 0 ); + awaydir = vectornormalize( awaydir ); + endpos = self.origin + vectorScale( awaydir, 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++; + } + } + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + if ( isDefined( locs[ dest ] ) ) + { + self setgoalpos( locs[ dest ].origin ); + } + wait 5; + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +outside_ghost_zone_spawning_think() +{ + level endon( "intermission" ); + if ( level.intermission ) + { + return; + } + level endon( "ghost_round_end" ); + if ( !isDefined( level.female_ghost_spawner ) ) + { +/# + assertmsg( "No female ghost spawner in the map." ); +#/ + return; + } + while ( isDefined( level.zombie_ghost_round_states.active_zombie_locations ) ) + { + i = 0; + while ( i < level.zombie_ghost_round_states.active_zombie_locations.size ) + { + if ( i >= 20 ) + { + return; + } + spawn_point = level.zombie_ghost_round_states.active_zombie_locations[ i ]; + ghost_ai = spawn_zombie( level.female_ghost_spawner, level.female_ghost_spawner.targetname, spawn_point ); + if ( isDefined( ghost_ai ) ) + { + ghost_ai setclientfield( "ghost_fx", 3 ); + ghost_ai.spawn_point = spawn_point; + ghost_ai.is_ghost = 1; + } + else + { +/# + assertmsg( "female ghost outside ghost zone: failed spawn" ); +#/ + return; + } + wait randomfloat( 0,3 ); + wait_network_frame(); + i++; + } + } +} + +get_current_ghost_count() +{ + ghost_count = 0; + ais = getaiarray( level.zombie_team ); + _a2673 = ais; + _k2673 = getFirstArrayKey( _a2673 ); + while ( isDefined( _k2673 ) ) + { + ai = _a2673[ _k2673 ]; + if ( isDefined( ai.is_ghost ) && ai.is_ghost ) + { + ghost_count++; + } + _k2673 = getNextArrayKey( _a2673, _k2673 ); + } + return ghost_count; +} + +get_current_ghosts() +{ + ghosts = []; + ais = getaiarray( level.zombie_team ); + _a2688 = ais; + _k2688 = getFirstArrayKey( _a2688 ); + while ( isDefined( _k2688 ) ) + { + ai = _a2688[ _k2688 ]; + if ( isDefined( ai.is_ghost ) && ai.is_ghost ) + { + ghosts[ ghosts.size ] = ai; + } + _k2688 = getNextArrayKey( _a2688, _k2688 ); + } + return ghosts; +} + +set_player_moving_speed_scale( player, move_speed_scale ) +{ + if ( isDefined( player ) ) + { + player setmovespeedscale( move_speed_scale ); + } +} + +player_moving_speed_scale_think() +{ + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + level endon( "ghost_round_end" ); + while ( 1 ) + { + players = get_players(); + _a2723 = players; + _k2723 = getFirstArrayKey( _a2723 ); + while ( isDefined( _k2723 ) ) + { + player = _a2723[ _k2723 ]; + if ( !is_player_valid( player, undefined, 1 ) ) + { + } + else if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + set_player_moving_speed_scale( player, 1 ); + } + else + { + if ( isDefined( player.ghost_next_drain_time_left ) ) + { + player.ghost_next_drain_time_left -= 0,1; + } + player_slow_down = 0; + ais = getaiarray( level.zombie_team ); + _a2743 = ais; + _k2743 = getFirstArrayKey( _a2743 ); + while ( isDefined( _k2743 ) ) + { + ai = _a2743[ _k2743 ]; + if ( isDefined( ai.is_ghost ) && ai.is_ghost && can_drain_points( ai.origin, player.origin ) ) + { + player_slow_down = 1; + set_player_moving_speed_scale( player, 0,5 ); + if ( isDefined( player.ghost_next_drain_time_left ) && player.ghost_next_drain_time_left < 0 && isDefined( ai.favoriteenemy ) && player != ai.favoriteenemy ) + { + give_player_rewards( player ); + points_to_drain = 2000; + if ( player.score < points_to_drain ) + { + if ( player.score > 0 ) + { + points_to_drain = player.score; + break; + } + else + { + points_to_drain = 0; + } + } + if ( points_to_drain > 0 ) + { + player maps/mp/zombies/_zm_score::minus_to_player_score( points_to_drain ); + player playsoundtoplayer( "zmb_ai_ghost_money_drain", player ); + } + else + { + if ( player.health > 0 && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + player dodamage( 25, ai.origin, ai ); + } + } + player.ghost_next_drain_time_left = 2; + } + break; + } + else + { + _k2743 = getNextArrayKey( _a2743, _k2743 ); + } + } + if ( player_slow_down == 0 ) + { + set_player_moving_speed_scale( player, 1 ); + } + } + _k2723 = getNextArrayKey( _a2723, _k2723 ); + } + wait 0,1; + } +} + +give_player_rewards( player ) +{ + if ( player is_player_placeable_mine( "claymore_zm" ) ) + { + claymore_count = player getweaponammostock( "claymore_zm" ) + 1; + if ( claymore_count >= 2 ) + { + claymore_count = 2; + player notify( "zmb_disable_claymore_prompt" ); + } + player setweaponammostock( "claymore_zm", claymore_count ); + } + else + { + lethal_grenade_name = player get_player_lethal_grenade(); + if ( player hasweapon( lethal_grenade_name ) ) + { + lethal_grenade_count = player getweaponammoclip( lethal_grenade_name ) + 1; + if ( lethal_grenade_count > 4 ) + { + lethal_grenade_count = 4; + } + player setweaponammoclip( lethal_grenade_name, lethal_grenade_count ); + } + } +} + +set_player_current_ghost_zone( player, ghost_zone_name ) +{ + if ( isDefined( player ) ) + { + player.current_ghost_room_name = ghost_zone_name; + } +} + +can_start_ghost_round_presentation() +{ +/# + if ( isDefined( level.force_no_ghost ) && level.force_no_ghost ) + { + return 0; +#/ + } + if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) && level.zombie_ghost_round_states.is_first_ghost_round_finished ) + { + if ( level.round_number < ( level.zombie_ghost_round_states.current_ghost_round_number + 4 ) ) + { + return 0; + } + } + if ( is_ghost_round_started() ) + { + return 0; + } + if ( flag( "time_bomb_round_killed" ) && !flag( "time_bomb_enemies_restored" ) ) + { + return 0; + } + return 1; +} + +can_start_ghost_round_presentation_stage_1() +{ + if ( isDefined( level.zombie_ghost_round_states.presentation_stage_1_started ) && level.zombie_ghost_round_states.presentation_stage_1_started ) + { + return 0; + } + return 1; +} + +can_start_ghost_round_presentation_stage_2() +{ + if ( isDefined( level.zombie_ghost_round_states.presentation_stage_2_started ) && level.zombie_ghost_round_states.presentation_stage_2_started ) + { + return 0; + } + if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) && level.zombie_ghost_round_states.is_first_ghost_round_finished ) + { + if ( level.round_number < ( ( level.zombie_ghost_round_states.current_ghost_round_number + 4 ) + 1 ) ) + { + return 0; + } + } + return 1; +} + +can_start_ghost_round_presentation_stage_3() +{ + if ( isDefined( level.zombie_ghost_round_states.presentation_stage_3_started ) && level.zombie_ghost_round_states.presentation_stage_3_started ) + { + return 0; + } + if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) && level.zombie_ghost_round_states.is_first_ghost_round_finished ) + { + if ( level.round_number < ( ( level.zombie_ghost_round_states.current_ghost_round_number + 4 ) + 2 ) ) + { + return 0; + } + } + return 1; +} + +get_next_spot_during_ghost_round_presentation() +{ + if ( isDefined( level.current_ghost_window_index ) ) + { + standing_location_index = randomint( level.ghost_front_standing_locations.size ); + while ( standing_location_index == level.current_ghost_window_index ) + { + standing_location_index = randomint( level.ghost_front_standing_locations.size ); + } + level.current_ghost_window_index = standing_location_index; + } + else + { + level.current_ghost_window_index = 1; + } + return level.ghost_front_standing_locations[ level.current_ghost_window_index ]; +} + +spawn_ghost_round_presentation_ghost() +{ + spawn_point = get_next_spot_during_ghost_round_presentation(); + ghost = spawn( "script_model", spawn_point.origin ); + ghost.angles = spawn_point.angles; + ghost setmodel( "c_zom_zombie_buried_ghost_woman_fb" ); + if ( isDefined( ghost ) ) + { + ghost.spawn_point = spawn_point; + ghost.for_ghost_round_presentation = 1; + level.ghost_round_presentation_ghost = ghost; + } + else + { +/# + assertmsg( "ghost round presentation ghost: failed spawn" ); +#/ + return; + } + wait 0,5; + ghost useanimtree( -1 ); + ghost setanim( %ai_zombie_ghost_idle ); + ghost.script_mover = spawn( "script_origin", ghost.origin ); + ghost.script_mover.angles = ghost.angles; + ghost linkto( ghost.script_mover ); + ghost setclientfield( "sndGhostAudio", 1 ); +} + +ghost_round_presentation_think() +{ + level endon( "intermission" ); + if ( isDefined( level.intermission ) && level.intermission ) + { + return; + } + if ( !isDefined( level.sndmansionent ) ) + { + level.sndmansionent = spawn( "script_origin", ( 2830, 555, 436 ) ); + } + flag_wait( "start_zombie_round_logic" ); + while ( 1 ) + { + if ( can_start_ghost_round_presentation() ) + { + if ( can_start_ghost_round_presentation_stage_1() ) + { + level.zombie_ghost_round_states.presentation_stage_1_started = 1; + spawn_ghost_round_presentation_ghost(); + if ( isDefined( level.ghost_round_presentation_ghost ) ) + { + level.ghost_round_presentation_ghost thread ghost_switch_windows(); + } + } + if ( can_start_ghost_round_presentation_stage_2() ) + { + level.zombie_ghost_round_states.presentation_stage_2_started = 1; + level.sndmansionent playloopsound( "zmb_ghost_round_lp_quiet", 3 ); + level setclientfield( "ghost_round_light_state", 1 ); + } + if ( can_start_ghost_round_presentation_stage_3() ) + { + level.zombie_ghost_round_states.presentation_stage_3_started = 1; + level.sndmansionent playloopsound( "zmb_ghost_round_lp_loud", 3 ); + if ( isDefined( level.ghost_round_presentation_ghost ) ) + { + level.ghost_round_presentation_ghost thread ghost_round_presentation_sound(); + } + } + } + wait 0,1; + } +} + +ghost_switch_windows() +{ + level endon( "intermission" ); + self endon( "death" ); + while ( 1 ) + { + next_spot = get_next_spot_during_ghost_round_presentation(); + self setclientfield( "ghost_fx", 5 ); + self setclientfield( "sndGhostAudio", 0 ); + self ghost(); + self.script_mover moveto( next_spot.origin, 1 ); + self.script_mover waittill( "movedone" ); + self.script_mover.origin = next_spot.origin; + self.script_mover.angles = next_spot.angles; + self setclientfield( "ghost_fx", 3 ); + self setclientfield( "sndGhostAudio", 1 ); + self show(); + wait 6; + } +} + +ghost_round_presentation_sound() +{ + level endon( "intermission" ); + self endon( "death" ); + while ( 1 ) + { + players = getplayers(); + _a3071 = players; + _k3071 = getFirstArrayKey( _a3071 ); + while ( isDefined( _k3071 ) ) + { + player = _a3071[ _k3071 ]; + if ( is_player_valid( player ) ) + { + vox_index = randomint( level.ghost_vox.size ); + vox_line = level.ghost_vox[ vox_index ]; + self playsoundtoplayer( vox_line, player ); + } + _k3071 = getNextArrayKey( _a3071, _k3071 ); + } + wait randomintrange( 2, 6 ); + } +} + +ghost_round_presentation_reset() +{ + if ( isDefined( level.sndmansionent ) ) + { + level.sndmansionent stoploopsound( 3 ); + } + if ( isDefined( level.ghost_round_presentation_ghost ) ) + { + level.ghost_round_presentation_ghost.skip_death_notetracks = 1; + level.ghost_round_presentation_ghost.nodeathragdoll = 1; + level.ghost_round_presentation_ghost setclientfield( "ghost_fx", 5 ); + wait_network_frame(); + level.ghost_round_presentation_ghost delete(); + level.ghost_round_presentation_ghost = undefined; + } + level.zombie_ghost_round_states.presentation_stage_1_started = 0; + level.zombie_ghost_round_states.presentation_stage_2_started = 0; + level.zombie_ghost_round_states.presentation_stage_3_started = 0; +} + +behave_after_fountain_transport( player ) +{ + wait 1; + if ( isDefined( player ) ) + { + set_player_current_ghost_zone( player, undefined ); + level.zombie_ghost_round_states.is_teleporting = 1; + ais = getaiarray( level.zombie_team ); + ghost_teleport_point_index = 0; + ais_need_teleported = []; + _a3133 = ais; + _k3133 = getFirstArrayKey( _a3133 ); + while ( isDefined( _k3133 ) ) + { + ai = _a3133[ _k3133 ]; + if ( isDefined( ai.is_ghost ) && ai.is_ghost && isDefined( ai.favoriteenemy ) && ai.favoriteenemy == player ) + { + ais_need_teleported[ ais_need_teleported.size ] = ai; + } + _k3133 = getNextArrayKey( _a3133, _k3133 ); + } + _a3141 = ais_need_teleported; + _k3141 = getFirstArrayKey( _a3141 ); + while ( isDefined( _k3141 ) ) + { + ai_need_teleported = _a3141[ _k3141 ]; + if ( ghost_teleport_point_index == level.ghost_zone_start_lower_locations.size ) + { + ghost_teleport_point_index = 0; + } + teleport_point_origin = level.ghost_zone_start_lower_locations[ ghost_teleport_point_index ].origin; + teleport_point_angles = level.ghost_zone_start_lower_locations[ ghost_teleport_point_index ].angles; + ai_need_teleported forceteleport( teleport_point_origin, teleport_point_angles ); + ghost_teleport_point_index++; + wait_network_frame(); + _k3141 = getNextArrayKey( _a3141, _k3141 ); + } + wait 1; + level.zombie_ghost_round_states.is_teleporting = 0; + } +} + +init_time_bomb_ghost_rounds() +{ + register_time_bomb_enemy( "ghost", ::is_ghost_round, ::save_ghost_data, ::time_bomb_respawns_ghosts ); + level.ghost_custom_think_logic = ::time_bomb_ghost_respawn_think; + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_save( ::time_bomb_global_data_save_ghosts ); + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_restore( ::time_bomb_global_data_restore_ghosts ); + level._time_bomb.custom_funcs_get_enemies = ::time_bomb_custom_get_enemy_func; + maps/mp/zombies/_zm_weap_time_bomb::register_time_bomb_enemy_save_filter( "zombie", ::is_ghost ); +} + +is_ghost() +{ + if ( isDefined( self.is_ghost )return !self.is_ghost; +} + +is_ghost_round() +{ + return flag( "spawn_ghosts" ); +} + +save_ghost_data( s_data ) +{ + s_data.origin = self.origin; + s_data.angles = self.angles; + s_data.is_ghost = self.is_ghost; + s_data.spawn_point = self.spawn_point; + if ( level.zombie_ghost_round_states.any_player_in_ghost_zone ) + { + s_data.is_spawned_in_ghost_zone = self.is_spawned_in_ghost_zone; + } + else + { + s_data.is_spawned_in_ghost_zone = 0; + } + s_data.is_spawned_in_ghost_zone_actual = self.is_spawned_in_ghost_zone; + s_data.find_target = self.find_target; + s_data.favoriteenemy = self.favoriteenemy; + s_data.ignore_timebomb_slowdown = self.ignore_timebomb_slowdown; +} + +time_bomb_respawns_ghosts( save_struct ) +{ + flag_clear( "spawn_ghosts" ); + ghost_round_presentation_reset(); + level.force_ghost_round_end = 1; + level.force_ghost_round_start = 1; + level waittill( "ghost_round_end" ); + level thread respawn_ghosts_outside_mansion( save_struct ); + level thread _respawn_ghost_failsafe(); + if ( !save_struct.custom_data.ghost_data.round_first_done ) + { + level.zombie_ghost_round_states.is_first_ghost_round_finished = 0; + } + flag_wait( "time_bomb_enemies_restored" ); + level.force_ghost_round_end = undefined; + level.force_ghost_round_start = undefined; + level.zombie_ghost_round_states.is_started = save_struct.custom_data.ghost_data.round_started; +} + +respawn_ghosts_outside_mansion( save_struct ) +{ + a_spawns_outside_mansion = []; + i = 0; + while ( i < save_struct.enemies.size ) + { + if ( isDefined( save_struct.enemies[ i ].is_spawned_in_ghost_zone ) && !save_struct.enemies[ i ].is_spawned_in_ghost_zone ) + { + a_spawns_outside_mansion[ a_spawns_outside_mansion.size ] = save_struct.enemies[ i ]; + } + i++; + } + level.zombie_ghost_round_states.active_zombie_locations = a_spawns_outside_mansion; + save_struct.total_respawns = a_spawns_outside_mansion.size; +} + +time_bomb_custom_get_enemy_func() +{ + a_enemies = []; + a_valid_enemies = []; + a_enemies = getaispeciesarray( level.zombie_team, "all" ); + i = 0; + while ( i < a_enemies.size ) + { + if ( isDefined( a_enemies[ i ].ignore_enemy_count ) && a_enemies[ i ].ignore_enemy_count && isDefined( a_enemies[ i ].is_ghost ) || !a_enemies[ i ].is_ghost && isDefined( level.ghost_round_presentation_ghost ) && level.ghost_round_presentation_ghost == a_enemies[ i ] ) + { + i++; + continue; + } + else + { + a_valid_enemies[ a_valid_enemies.size ] = a_enemies[ i ]; + } + i++; + } + return a_valid_enemies; +} + +time_bomb_global_data_save_ghosts() +{ + s_temp = spawnstruct(); + s_temp.ghost_count = level.zombie_ghost_count; + s_temp.round_started = level.zombie_ghost_round_states.is_started; + s_temp.round_first_done = level.zombie_ghost_round_states.is_first_ghost_round_finished; + s_temp.round_next = level.zombie_ghost_round_states.next_ghost_round_number; + s_temp.zombie_total = level.zombie_ghost_round_states.round_zombie_total; + self.ghost_data = s_temp; +} + +time_bomb_global_data_restore_ghosts() +{ + level.zombie_ghost_count = 0; + level.zombie_ghost_round_states.is_started = self.ghost_data.round_started; + level.zombie_ghost_round_states.is_first_ghost_round_finished = self.ghost_data.round_first_done; + level.zombie_ghost_round_states.next_ghost_round_number = self.ghost_data.round_next; + level.zombie_ghost_round_states.round_zombie_total = self.ghost_data.zombie_total; + _a3311 = get_players(); + _k3311 = getFirstArrayKey( _a3311 ); + while ( isDefined( _k3311 ) ) + { + player = _a3311[ _k3311 ]; + player.ghost_count = 0; + _k3311 = getNextArrayKey( _a3311, _k3311 ); + } +} + +time_bomb_ghost_respawn_think() +{ + if ( flag( "time_bomb_round_killed" ) && !flag( "time_bomb_enemies_restored" ) ) + { + if ( isDefined( level.timebomb_override_struct ) ) + { + save_struct = level.timebomb_override_struct; + } + else + { + save_struct = level.time_bomb_save_data; + } + if ( !isDefined( save_struct.respawn_counter ) ) + { + save_struct.respawn_counter = 0; + } + n_index = save_struct.respawn_counter; + save_struct.respawn_counter++; + if ( save_struct.enemies.size > 0 && isDefined( save_struct.enemies ) && n_index < save_struct.enemies.size ) + { + while ( isDefined( save_struct.enemies[ n_index ] ) && isDefined( save_struct.enemies[ n_index ].is_spawned_in_ghost_zone ) && save_struct.enemies[ n_index ].is_spawned_in_ghost_zone ) + { + save_struct.respawn_counter++; + n_index = save_struct.respawn_counter; + } + if ( isDefined( save_struct.enemies[ n_index ] ) ) + { + self _restore_ghost_data( save_struct, n_index ); + } + } + if ( save_struct.respawn_counter >= save_struct.enemies.size || save_struct.enemies.size == 0 ) + { + flag_set( "time_bomb_enemies_restored" ); + level.zombie_ghost_round_states.active_zombie_locations = []; + } + flag_wait( "time_bomb_enemies_restored" ); + self thread restore_ghost_failsafe(); + } +} + +restore_ghost_failsafe() +{ + self endon( "death" ); + wait randomfloatrange( 2, 3 ); + if ( !isDefined( self.state ) ) + { + self.respawned_by_time_bomb = 1; + self thread ghost_think(); + } + else + { + if ( isDefined( level.ghost_round_presentation_ghost ) && level.ghost_round_presentation_ghost == self ) + { + ghost_round_presentation_reset(); + wait_network_frame(); + self thread ghost_think(); + } + } + self.passed_failsafe = 1; +} + +_restore_ghost_data( save_struct, n_index ) +{ + s_data = save_struct.enemies[ n_index ]; + playfxontag( level._effect[ "time_bomb_respawns_enemy" ], self, "J_SpineLower" ); + self.origin = s_data.origin; + self.angles = s_data.angles; + self.is_ghost = s_data.is_ghost; + self.spawn_point = s_data.spawn_point; + self.is_spawned_in_ghost_zone = s_data.is_spawned_in_ghost_zone; + self.find_target = s_data.find_target; + if ( isDefined( s_data.favoriteenemy ) ) + { + self.favoriteenemy = s_data.favoriteenemy; + } + self.ignore_timebomb_slowdown = 1; + self setgoalpos( self.origin ); +} + +_respawn_ghost_failsafe() +{ + n_counter = 0; + while ( !flag( "time_bomb_enemies_restored" ) && n_counter < 20 ) + { + if ( get_current_actor_count() >= level.zombie_ai_limit || isDefined( level.time_bomb_save_data.total_respawns ) && level.time_bomb_save_data.total_respawns == 0 ) + { + flag_set( "time_bomb_enemies_restored" ); + } + n_counter++; + wait 0,5; + } + flag_set( "time_bomb_enemies_restored" ); +} + +devgui_warp_to_mansion() +{ +/# + player = gethostplayer(); + player setorigin( ( 2324, 560, 148 ) ); + player setplayerangles( ( 1, 1, 1 ) ); +#/ +} + +devgui_toggle_no_ghost() +{ +/# + level.force_no_ghost = !level.force_no_ghost; +#/ +} + +draw_debug_line( from, to, color, time, depth_test ) +{ +/# + if ( isDefined( level.ghost_debug ) && level.ghost_debug ) + { + if ( !isDefined( time ) ) + { + time = 1000; + } + line( from, to, color, 1, depth_test, time ); +#/ + } +} + +draw_debug_star( origin, color, time ) +{ +/# + if ( isDefined( level.ghost_debug ) && level.ghost_debug ) + { + if ( !isDefined( time ) ) + { + time = 1000; + } + if ( !isDefined( color ) ) + { + color = ( 1, 1, 1 ); + } + debugstar( origin, time, color ); +#/ + } +} + +draw_debug_box( origin, mins, maxs, yaw, color, time ) +{ +/# + if ( isDefined( level.ghost_debug ) && level.ghost_debug ) + { + if ( !isDefined( time ) ) + { + time = 1000; + } + if ( !isDefined( color ) ) + { + color = ( 1, 1, 1 ); + } + box( origin, mins, maxs, yaw, color, 1, 0, 1 ); +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_ghost_ffotd.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_ghost_ffotd.gsc new file mode 100644 index 0000000..5eab1d3 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_ghost_ffotd.gsc @@ -0,0 +1,333 @@ +#include maps/mp/zombies/_zm_ai_ghost; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zm_buried; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +ghost_init_start() +{ + level ghost_bad_path_init(); + level.is_player_in_ghost_zone = ::is_player_in_ghost_zone; + level ghost_bad_spawn_zone_init(); + level.ghost_round_start_monitor_time = 10; +} + +ghost_init_end() +{ + disable_traversal_clip_around_mansion(); +} + +prespawn_start() +{ +} + +prespawn_end() +{ +} + +ghost_round_start() +{ + level thread ghost_teleport_to_playable_area(); +} + +ghost_round_end() +{ + disable_traversal_clip_around_mansion(); +} + +is_player_in_ghost_zone( player ) +{ + result = 0; + if ( !isDefined( level.ghost_zone_overrides ) ) + { + level.ghost_zone_overrides = getentarray( "ghost_round_override", "script_noteworthy" ); + } + is_player_in_override_trigger = 0; + while ( isDefined( level.zombie_ghost_round_states ) && !is_true( level.zombie_ghost_round_states.is_started ) ) + { + _a86 = level.ghost_zone_overrides; + _k86 = getFirstArrayKey( _a86 ); + while ( isDefined( _k86 ) ) + { + trigger = _a86[ _k86 ]; + if ( player istouching( trigger ) ) + { + is_player_in_override_trigger = 1; + break; + } + else + { + _k86 = getNextArrayKey( _a86, _k86 ); + } + } + } + curr_zone = player get_current_zone(); + if ( !is_player_in_override_trigger && isDefined( curr_zone ) && curr_zone == "zone_mansion" ) + { + result = 1; + } + return result; +} + +ghost_bad_path_init() +{ + level.bad_zones = []; + level.bad_zones[ 0 ] = spawnstruct(); + level.bad_zones[ 0 ].name = "zone_underground_courthouse"; + level.bad_zones[ 0 ].adjacent = []; + level.bad_zones[ 0 ].adjacent[ 0 ] = "zone_underground_courthouse2"; + level.bad_zones[ 0 ].adjacent[ 1 ] = "zone_tunnels_north2"; + level.bad_zones[ 0 ].ignore_func = ::maps/mp/zm_buried::is_courthouse_open; + level.bad_zones[ 1 ] = spawnstruct(); + level.bad_zones[ 1 ].name = "zone_underground_courthouse2"; + level.bad_zones[ 1 ].adjacent = []; + level.bad_zones[ 1 ].adjacent[ 0 ] = "zone_underground_courthouse"; + level.bad_zones[ 1 ].adjacent[ 1 ] = "zone_tunnels_north2"; + level.bad_zones[ 1 ].ignore_func = ::maps/mp/zm_buried::is_courthouse_open; + level.bad_zones[ 2 ] = spawnstruct(); + level.bad_zones[ 2 ].name = "zone_tunnels_north2"; + level.bad_zones[ 2 ].adjacent = []; + level.bad_zones[ 2 ].adjacent[ 0 ] = "zone_underground_courthouse2"; + level.bad_zones[ 2 ].adjacent[ 1 ] = "zone_underground_courthouse"; + level.bad_zones[ 2 ].flag = "tunnels2courthouse"; + level.bad_zones[ 2 ].flag_adjacent = "zone_tunnels_north"; + level.bad_zones[ 2 ].ignore_func = ::maps/mp/zm_buried::is_courthouse_open; + level.bad_zones[ 3 ] = spawnstruct(); + level.bad_zones[ 3 ].name = "zone_tunnels_north"; + level.bad_zones[ 3 ].adjacent = []; + level.bad_zones[ 3 ].adjacent[ 0 ] = "zone_tunnels_center"; + level.bad_zones[ 3 ].flag = "tunnels2courthouse"; + level.bad_zones[ 3 ].flag_adjacent = "zone_tunnels_north2"; + level.bad_zones[ 3 ].ignore_func = ::maps/mp/zm_buried::is_tunnel_open; + level.bad_zones[ 4 ] = spawnstruct(); + level.bad_zones[ 4 ].name = "zone_tunnels_center"; + level.bad_zones[ 4 ].adjacent = []; + level.bad_zones[ 4 ].adjacent[ 0 ] = "zone_tunnels_north"; + level.bad_zones[ 4 ].adjacent[ 1 ] = "zone_tunnels_south"; + level.bad_zones[ 4 ].ignore_func = ::maps/mp/zm_buried::is_tunnel_open; + level.bad_zones[ 5 ] = spawnstruct(); + level.bad_zones[ 5 ].name = "zone_tunnels_south"; + level.bad_zones[ 5 ].adjacent = []; + level.bad_zones[ 5 ].adjacent[ 0 ] = "zone_tunnels_center"; + level.bad_zones[ 5 ].ignore_func = ::maps/mp/zm_buried::is_tunnel_open; +} + +ghost_bad_path_failsafe() +{ + self endon( "death" ); + self notify( "stop_bad_path_failsafe" ); + self endon( "stop_bad_path_failsafe" ); + self thread non_ghost_round_failsafe(); + while ( 1 ) + { + player = self.favoriteenemy; + if ( isDefined( player ) ) + { + in_bad_zone = 0; + _a174 = level.bad_zones; + _k174 = getFirstArrayKey( _a174 ); + while ( isDefined( _k174 ) ) + { + zone = _a174[ _k174 ]; + if ( isDefined( zone.ignore_func ) ) + { + if ( level [[ zone.ignore_func ]]() ) + { + break; + } + } + else if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( zone.name ) ) + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( zone.name ) ) + { + break; + } + else ghost_is_adjacent = 0; + _a192 = zone.adjacent; + _k192 = getFirstArrayKey( _a192 ); + while ( isDefined( _k192 ) ) + { + adjacent = _a192[ _k192 ]; + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( adjacent ) ) + { + ghost_is_adjacent = 1; + break; + } + else + { + _k192 = getNextArrayKey( _a192, _k192 ); + } + } + if ( isDefined( zone.flag ) && flag( zone.flag ) ) + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( zone.flag_adjacent ) ) + { + ghost_is_adjacent = 1; + } + } + if ( !ghost_is_adjacent ) + { + in_bad_zone = 1; + break; + } + } + else + { + _k174 = getNextArrayKey( _a174, _k174 ); + } + } + if ( in_bad_zone ) + { + nodes = getnodesinradiussorted( player.origin, 540, 180, 60, "Path" ); + if ( nodes.size > 0 ) + { + node = nodes[ randomint( nodes.size ) ]; + } + else + { + node = getnearestnode( player.origin ); + } + if ( isDefined( node ) ) + { + while ( 1 ) + { + if ( !is_true( self.is_traversing ) ) + { + break; + } + else + { + wait 0,1; + } + } + self forceteleport( node.origin, ( 0, 0, 0 ) ); + } + } + } + wait 0,25; + } +} + +non_ghost_round_failsafe() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "bad_path" ); + if ( self.state == "runaway_update" ) + { + if ( !maps/mp/zombies/_zm_ai_ghost::is_ghost_round_started() && is_true( self.is_spawned_in_ghost_zone ) ) + { + self maps/mp/zombies/_zm_ai_ghost::start_evaporate( 1 ); + return; + } + } + wait 0,25; + } +} + +disable_traversal_clip_around_mansion() +{ + while ( isDefined( level.ghost_zone_door_clips ) && level.ghost_zone_door_clips.size > 0 ) + { + _a276 = level.ghost_zone_door_clips; + _k276 = getFirstArrayKey( _a276 ); + while ( isDefined( _k276 ) ) + { + door_clip = _a276[ _k276 ]; + door_clip notsolid(); + _k276 = getNextArrayKey( _a276, _k276 ); + } + } +} + +ghost_bad_spawn_zone_init() +{ + level.ghost_bad_spawn_zones = []; + level.ghost_bad_spawn_zones[ 0 ] = "zone_mansion_backyard"; + level.ghost_bad_spawn_zones[ 1 ] = "zone_maze"; + level.ghost_bad_spawn_zones[ 2 ] = "zone_maze_staircase"; +} + +can_use_mansion_back_flying_out_node( zone_name ) +{ + if ( zone_name == "zone_mansion_backyard" ) + { + return 1; + } + if ( zone_name == "zone_maze" ) + { + return 1; + } + if ( zone_name == "zone_maze_staircase" ) + { + return 1; + } + return 0; +} + +ghost_teleport_to_playable_area() +{ + level endon( "intermission" ); + if ( level.intermission ) + { + return; + } + level endon( "ghost_round_end" ); + monitor_time = 0; + while ( 1 ) + { + ghosts = get_current_ghosts(); + _a332 = ghosts; + _k332 = getFirstArrayKey( _a332 ); + while ( isDefined( _k332 ) ) + { + ghost = _a332[ _k332 ]; + while ( !is_true( self.is_spawned_in_ghost_zone ) && !is_true( self.is_teleported_in_bad_zone ) ) + { + _a336 = level.ghost_bad_spawn_zones; + _k336 = getFirstArrayKey( _a336 ); + while ( isDefined( _k336 ) ) + { + bad_spawn_zone_name = _a336[ _k336 ]; + if ( ghost maps/mp/zombies/_zm_zonemgr::entity_in_zone( bad_spawn_zone_name ) ) + { + if ( is_player_valid( ghost.favoriteenemy ) ) + { + destination_node = ghost maps/mp/zombies/_zm_ai_ghost::get_best_flying_target_node( ghost.favoriteenemy ); + if ( isDefined( destination_node ) ) + { + ghost forceteleport( destination_node.origin, ( 0, 0, 0 ) ); + self.is_teleported_in_bad_zone = 1; + } + } + if ( !is_true( self.is_teleported_in_bad_zone ) ) + { + if ( can_use_mansion_back_flying_out_node( bad_spawn_zone_name ) ) + { + ghost forceteleport( level.ghost_back_flying_out_path_starts[ 0 ].origin, ( 0, 0, 0 ) ); + } + else + { + ghost forceteleport( level.ghost_front_flying_out_path_starts[ 0 ].origin, ( 0, 0, 0 ) ); + } + self.is_teleported_in_bad_zone = 1; + } + } + _k336 = getNextArrayKey( _a336, _k336 ); + } + } + _k332 = getNextArrayKey( _a332, _k332 ); + } + monitor_time += 0,1; + if ( monitor_time > level.ghost_round_start_monitor_time ) + { + return; + } + else + { + wait 0,1; + } + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth.gsc new file mode 100644 index 0000000..5c95136 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth.gsc @@ -0,0 +1,4593 @@ +#include maps/mp/zombies/_zm_weap_time_bomb; +#include maps/mp/zombies/_zm_weap_slowgun; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/animscripts/zm_run; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_equip_headchopper; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_ai_sloth; +#include maps/mp/zombies/_zm_ai_sloth_ffotd; +#include maps/mp/zombies/_zm_ai_sloth_utility; +#include maps/mp/zombies/_zm_ai_sloth_magicbox; +#include maps/mp/zombies/_zm_ai_sloth_crawler; +#include maps/mp/zombies/_zm_ai_sloth_buildables; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +precache() +{ +/# + precachemodel( "fx_axis_createfx" ); +#/ + level.small_magic_box = "p6_anim_zm_bu_magic_box_sml"; + level.small_turbine = "p6_anim_zm_bu_turbine_sml"; + precachemodel( level.small_magic_box ); + precachemodel( level.small_turbine ); + precache_fx(); + level._effect[ "barrier_break" ] = loadfx( "maps/zombie_buried/fx_buried_barrier_break" ); + level._effect[ "fx_buried_sloth_building" ] = loadfx( "maps/zombie_buried/fx_buried_sloth_building" ); + level._effect[ "fx_buried_sloth_box_slam" ] = loadfx( "maps/zombie_buried/fx_buried_sloth_box_slam" ); + level._effect[ "fx_buried_sloth_drinking" ] = loadfx( "maps/zombie_buried/fx_buried_sloth_drinking" ); + level._effect[ "fx_buried_sloth_eating" ] = loadfx( "maps/zombie_buried/fx_buried_sloth_eating" ); + level._effect[ "fx_buried_sloth_glass_brk" ] = loadfx( "maps/zombie_buried/fx_buried_sloth_glass_brk" ); + level._effect[ "fx_buried_sloth_powerup_cycle" ] = loadfx( "maps/zombie_buried/fx_buried_sloth_powerup_cycle" ); +} + +precache_fx() +{ +} + +init() +{ + register_sloth_client_fields(); + flag_init( "sloth_blocker_towneast" ); + level.sloth_spawners = getentarray( "sloth_zombie_spawner", "script_noteworthy" ); + array_thread( level.sloth_spawners, ::add_spawn_function, ::sloth_prespawn ); + level thread sloth_spawning_logic(); + level thread init_roam_points(); + level thread init_barricades(); + level thread init_interiors(); + level thread init_teleport_points(); + level thread init_candy_context(); + level thread init_build_buildables(); + level thread init_wallbuys(); + level thread init_generator(); + level thread init_fetch_buildables(); + level thread jail_cell_watcher(); + level thread init_hunched_volume(); + level thread init_crash_triggers(); + level thread watch_bar_couch(); + sloth_time_bomb_setup(); + level.wait_for_sloth = ::wait_for_sloth; + level.ignore_stop_func = ::ignore_stop_func; + level thread sloth_ffotd_init(); +/# + level.sloth_devgui_teleport = ::sloth_devgui_teleport; + level.sloth_devgui_booze = ::sloth_devgui_booze; + level.sloth_devgui_candy = ::sloth_devgui_candy; + level.sloth_devgui_warp_to_jail = ::sloth_devgui_warp_to_jail; + level.sloth_devgui_move_lamp = ::sloth_devgui_move_lamp; + level.sloth_devgui_make_crawler = ::sloth_devgui_make_crawler; + level.sloth_devgui_barricade = ::sloth_devgui_barricade; + level.sloth_devgui_context = ::sloth_devgui_context; + level.sloth_devgui_double_wide = ::sloth_devgui_double_wide; + level thread sloth_debug_doors(); + level thread sloth_debug_barricade(); +#/ +} + +register_sloth_client_fields() +{ + registerclientfield( "actor", "actor_is_sloth", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_berserk", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_ragdoll_zombie", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_vomit", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_buildable", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_drinking", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_eating", 12000, 1, "int" ); + registerclientfield( "actor", "sloth_glass_brk", 12000, 1, "int" ); +} + +init_interiors() +{ + level.interiors = []; + level.interiors[ level.interiors.size ] = "zone_underground_jail"; + level.interiors[ level.interiors.size ] = "zone_underground_jail2"; + level.interiors[ level.interiors.size ] = "zone_underground_courthouse"; + level.interiors[ level.interiors.size ] = "zone_underground_bar"; + level.interiors[ level.interiors.size ] = "zone_morgue"; + level.interiors[ level.interiors.size ] = "zone_morgue_upstairs"; + level.interiors[ level.interiors.size ] = "zone_church_main"; + level.interiors[ level.interiors.size ] = "zone_church_upstairs"; + level.interiors[ level.interiors.size ] = "zone_stables"; + level.interiors[ level.interiors.size ] = "zone_bank"; + level.interiors[ level.interiors.size ] = "zone_candy_store"; + level.interiors[ level.interiors.size ] = "zone_candy_store_floor2"; + level.interiors[ level.interiors.size ] = "zone_toy_store"; + level.interiors[ level.interiors.size ] = "zone_toy_store_floor2"; + level.interiors[ level.interiors.size ] = "zone_general_store"; + level.interiors[ level.interiors.size ] = "zone_gun_store"; + level.interiors[ level.interiors.size ] = "zone_tunnels_north"; + level.interiors[ level.interiors.size ] = "zone_tunnels_north2"; + level.interiors[ level.interiors.size ] = "zone_tunnels_center"; + level.interiors[ level.interiors.size ] = "zone_tunnel_gun2stables"; + level.interiors[ level.interiors.size ] = "zone_tunnel_gun2saloon"; + level thread setup_door_markers(); +} + +init_teleport_points() +{ + level.maze_depart = getstructarray( "sloth_to_maze_begin", "targetname" ); + level.maze_arrive = getstructarray( "sloth_to_maze_end", "targetname" ); + level.courtyard_depart = getstructarray( "sloth_from_maze_begin", "targetname" ); + level.courtyard_arrive = getstructarray( "sloth_from_maze_end", "targetname" ); + level.maze_to_mansion = getstructarray( "sloth_maze_to_mansion", "targetname" ); +} + +sloth_init_roam_point() +{ + _a171 = level.roam_points; + _k171 = getFirstArrayKey( _a171 ); + while ( isDefined( _k171 ) ) + { + point = _a171[ _k171 ]; + if ( point.script_noteworthy == "zone_street_lightwest" ) + { + self.current_roam = point; + return; + } + _k171 = getNextArrayKey( _a171, _k171 ); + } +} + +watch_double_wide() +{ + self endon( "death" ); + level.double_wide_volume = getentarray( "ignore_double_wide", "targetname" ); + while ( 1 ) + { + self.ignore_double_wide = 0; + _a194 = level.double_wide_volume; + _k194 = getFirstArrayKey( _a194 ); + while ( isDefined( _k194 ) ) + { + volume = _a194[ _k194 ]; + if ( self istouching( volume ) ) + { + self.ignore_double_wide = 1; + } + _k194 = getNextArrayKey( _a194, _k194 ); + } + if ( isDefined( level.double_wide_override ) ) + { + self [[ level.double_wide_override ]](); + } + wait 0,2; + } +} + +watch_interiors() +{ + self endon( "death" ); + while ( 1 ) + { + self.is_inside = 0; + i = 0; + while ( i < level.sloth_doors.size ) + { + door_flag = level.sloth_doors[ i ].script_flag; + if ( isDefined( door_flag ) ) + { + if ( flag( door_flag ) ) + { + dist = distancesquared( self.origin, level.sloth_doors[ i ].origin ); + if ( dist < 14400 ) + { + self.is_inside = 1; + break; + } + } + } + else + { + i++; + } + } + i = 0; + while ( i < level.sloth_hunched_structs.size ) + { + dist = distancesquared( self.origin, level.sloth_hunched_structs[ i ].origin ); + if ( dist < 14400 ) + { + self.is_inside = 1; + break; + } + else + { + i++; + } + } + while ( !self.is_inside ) + { + i = 0; + while ( i < level.interiors.size ) + { + name = level.interiors[ i ]; + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( name ) ) + { + self.is_inside = 1; + break; + } + else + { + i++; + } + } + } + if ( !self.is_inside ) + { + if ( self istouching( level.hunched_volume ) ) + { + self.is_inside = 1; + } + } + if ( isDefined( level.interior_override ) ) + { + self [[ level.interior_override ]](); + } + self sloth_update_double_wide(); + wait 0,1; + } +} + +sloth_update_double_wide() +{ +/# + if ( is_true( level.devgui_double_wide ) ) + { + return; +#/ + } + if ( is_true( self.ignore_double_wide ) || self.is_inside ) + { + if ( self.using_double_wide ) + { + self.using_double_wide = 0; + setdvar( "zombie_double_wide_checks", 0 ); + self setphysparams( 15, 0, 73 ); +/# + setdvarint( "scr_sloth_debug_width", 15 ); + setdvarint( "scr_sloth_debug_height", 73 ); + self.debug_width = getDvarInt( #"2443DFBB" ); + self.debug_height = getDvarInt( #"897C9AB4" ); +#/ + } + } + else + { + if ( !self.using_double_wide ) + { + self.using_double_wide = 1; + setdvar( "zombie_double_wide_checks", 1 ); + self setphysparams( 25, 0, 73 ); +/# + setdvarint( "scr_sloth_debug_width", 25 ); + setdvarint( "scr_sloth_debug_height", 73 ); + self.debug_width = getDvarInt( #"2443DFBB" ); + self.debug_height = getDvarInt( #"897C9AB4" ); +#/ + } + } +} + +watch_zombies() +{ + self endon( "death" ); + level endon( "maxis_minigame_start" ); + while ( 1 ) + { + all_far = 1; + zombies = get_round_enemy_array(); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + dist = distancesquared( self.origin, zombie.origin ); + if ( dist <= 3600 ) + { + self.near_zombies = 1; + all_far = 0; + i++; + continue; + } + else + { + if ( dist <= 14400 ) + { + all_far = 0; + } + } + i++; + } + if ( all_far ) + { + self.near_zombies = 0; + } + wait 0,2; + } +} + +watch_player_zombies() +{ + self endon( "death" ); + self notify( "stop_player_watch" ); + self endon( "stop_player_watch" ); + level endon( "maxis_minigame_start" ); + while ( 1 ) + { + while ( isDefined( self.candy_player ) ) + { + self.target_zombies = []; + zombies = get_round_enemy_array(); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + if ( !is_true( zombie.completed_emerging_into_playable_area ) ) + { + i++; + continue; + } + else if ( is_true( zombie.is_traversing ) ) + { + i++; + continue; + } + else z_delta = abs( self.candy_player.origin[ 2 ] - zombie.origin[ 2 ] ); + if ( z_delta > 120 ) + { + i++; + continue; + } + else + { + dist = distancesquared( self.candy_player.origin, zombie.origin ); + if ( dist <= 57600 ) + { + self.target_zombies[ self.target_zombies.size ] = zombie; + } + } + i++; + } + } + wait 0,2; + } +} + +watch_subwoofers() +{ + self endon( "death" ); + level endon( "maxis_minigame_start" ); + while ( 1 ) + { + self.subwoofer = undefined; + equipment = maps/mp/zombies/_zm_equipment::get_destructible_equipment_list(); + _a425 = equipment; + _k425 = getFirstArrayKey( _a425 ); + while ( isDefined( _k425 ) ) + { + item = _a425[ _k425 ]; + if ( isDefined( item.equipname ) && item.equipname == "equip_subwoofer_zm" ) + { + if ( is_true( item.power_on ) ) + { +/# + self sloth_debug_context( item, sqrt( 32400 ) ); +#/ + dist = distancesquared( self.origin, item.origin ); + if ( dist < 32400 ) + { + self.subwoofer = item; + } + } + } + _k425 = getNextArrayKey( _a425, _k425 ); + } + wait 0,2; + } +} + +watch_stink() +{ + self endon( "death" ); + level endon( "maxis_minigame_start" ); + while ( 1 ) + { + self.stink = undefined; + has_perk = 0; + players = getplayers(); + _a462 = players; + _k462 = getFirstArrayKey( _a462 ); + while ( isDefined( _k462 ) ) + { + player = _a462[ _k462 ]; + if ( player hasperk( "specialty_nomotionsensor" ) ) + { + has_perk = 1; + break; + } + else + { + _k462 = getNextArrayKey( _a462, _k462 ); + } + } + while ( has_perk && isDefined( level.perk_vulture ) ) + { + while ( isDefined( level.perk_vulture.zombie_stink_array ) && level.perk_vulture.zombie_stink_array.size > 0 ) + { + _a475 = level.perk_vulture.zombie_stink_array; + _k475 = getFirstArrayKey( _a475 ); + while ( isDefined( _k475 ) ) + { + stink = _a475[ _k475 ]; +/# + self sloth_debug_context( stink, 70 ); +#/ + dist = distancesquared( self.origin, stink.origin ); + if ( dist < 4900 ) + { + self.stink = stink; + } + _k475 = getNextArrayKey( _a475, _k475 ); + } + } + } + wait 0,2; + } +} + +watch_pack_volume() +{ + volume = getent( "sloth_pack_volume", "targetname" ); + while ( isDefined( volume ) ) + { + while ( 1 ) + { + if ( self istouching( volume ) ) + { + self sloth_teleport_to_maze(); + } + wait 0,1; + } + } +} + +watch_jail_door() +{ + self endon( "death" ); + while ( 1 ) + { + level waittill( "cell_open" ); + if ( isDefined( level.jail_open_door ) ) + { + level thread [[ level.jail_open_door ]]( self.got_booze ); + } + } +} + +sloth_teleport_to_maze() +{ + points = array_randomize( level.maze_arrive ); +/# + sloth_print( "teleporting to maze" ); +#/ + self forceteleport( points[ 0 ].origin ); + if ( self.state == "berserk" ) + { + self sloth_set_state( "crash", 0 ); + } + wait 0,1; +} + +is_towneast_open() +{ + if ( flag( "sloth_blocker_towneast" ) ) + { + return 1; + } + if ( is_general_store_open() ) + { + return 1; + } + if ( is_candy_store_open() ) + { + return 1; + } + return 0; +} + +is_maze_open() +{ + if ( flag( "mansion_lawn_door1" ) ) + { + return 1; + } + return 0; +} + +is_general_store_open() +{ + if ( !flag( "general_store_door1" ) || flag( "general_store_door2" ) && flag( "general_store_door3" ) ) + { + return 1; + } + return 0; +} + +is_candy_store_open() +{ + if ( flag( "candy_store_door1" ) || flag( "candy2lighteast" ) ) + { + return 1; + } + return 0; +} + +is_bar_open() +{ + if ( flag( "bar_door1" ) ) + { + return 1; + } + if ( is_true( level.bar_couch ) ) + { + return 1; + } + return 0; +} + +watch_bar_couch() +{ + self endon( "stop_watch_bar_couch" ); + bar_couch_pos = ( 1021, -1754, 172 ); + bar_couch_trigger = undefined; + debris_triggers = getentarray( "zombie_debris", "targetname" ); + _a631 = debris_triggers; + _k631 = getFirstArrayKey( _a631 ); + while ( isDefined( _k631 ) ) + { + trigger = _a631[ _k631 ]; + dist = distancesquared( trigger.origin, bar_couch_pos ); + if ( dist < 4096 ) + { + bar_couch_trigger = trigger; + break; + } + else + { + _k631 = getNextArrayKey( _a631, _k631 ); + } + } + if ( isDefined( bar_couch_trigger ) ) + { + bar_couch_trigger waittill( "trigger" ); +/# + sloth_print( "bar couch bought" ); +#/ + level.bar_couch = 1; + } +} + +sloth_behind_mansion() +{ + _a656 = level.maze_arrive; + _k656 = getFirstArrayKey( _a656 ); + while ( isDefined( _k656 ) ) + { + point = _a656[ _k656 ]; + dist = distancesquared( self.origin, point.origin ); + if ( dist < 360000 ) + { + return 1; + } + _k656 = getNextArrayKey( _a656, _k656 ); + } + if ( self behind_mansion_zone() ) + { + return 1; + } + return 0; +} + +behind_mansion_zone() +{ + behind_zones = []; + behind_zones[ behind_zones.size ] = "zone_mansion_backyard"; + behind_zones[ behind_zones.size ] = "zone_maze"; + behind_zones[ behind_zones.size ] = "zone_maze_staircase"; + _a680 = behind_zones; + _k680 = getFirstArrayKey( _a680 ); + while ( isDefined( _k680 ) ) + { + zone = _a680[ _k680 ]; + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( zone ) ) + { + return 1; + } + _k680 = getNextArrayKey( _a680, _k680 ); + } + return 0; +} + +setup_door_markers() +{ + level.sloth_doors = []; + level.sloth_hunched_structs = getstructarray( "hunched_struct", "targetname" ); + idx = 0; + doors = getentarray( "zombie_door", "targetname" ); + _a702 = doors; + _k702 = getFirstArrayKey( _a702 ); + while ( isDefined( _k702 ) ) + { + door = _a702[ _k702 ]; + level.sloth_doors[ idx ] = spawnstruct(); + level.sloth_doors[ idx ].origin = door.origin; + level.sloth_doors[ idx ].script_flag = door.script_flag; + idx++; + _k702 = getNextArrayKey( _a702, _k702 ); + } + barricades = getentarray( "sloth_barricade", "targetname" ); + _a714 = barricades; + _k714 = getFirstArrayKey( _a714 ); + while ( isDefined( _k714 ) ) + { + barricade = _a714[ _k714 ]; + if ( isDefined( barricade.script_noteworthy ) && barricade.script_noteworthy == "door" ) + { + level.sloth_doors[ idx ] = spawnstruct(); + level.sloth_doors[ idx ].origin = barricade.origin; + level.sloth_doors[ idx ].script_flag = barricade.script_flag; + if ( barricade.script_flag == "jail_door1" ) + { + level.jail_door = level.sloth_doors[ idx ]; +/# + level.jail_barricade = barricade; +#/ + } + idx++; + } + _k714 = getNextArrayKey( _a714, _k714 ); + } +} + +init_roam_points() +{ + level.roam_points = getnodearray( "sloth_roam", "targetname" ); +} + +init_barricades() +{ + triggers = getentarray( "sloth_barricade", "targetname" ); + level.barricade_ents = []; + _a749 = triggers; + _k749 = getFirstArrayKey( _a749 ); + while ( isDefined( _k749 ) ) + { + trigger = _a749[ _k749 ]; + trigger thread watch_barricade(); + level.barricade_ents[ level.barricade_ents.size ] = trigger.target; + _k749 = getNextArrayKey( _a749, _k749 ); + } +} + +watch_barricade() +{ + self endon( "death" ); + self endon( "maxis_minigame_opens_barricade" ); + if ( isDefined( self.script_string ) ) + { + should_delete = self.script_string != "no_delete"; + } + if ( !should_delete ) + { + self.func_no_delete = ::hide_sloth_barrier; + } + while ( 1 ) + { + self waittill( "trigger", who ); + if ( isDefined( level.sloth ) && who == level.sloth && who.state == "berserk" ) + { + should_break = is_true( who.run_berserk ); + } +/# + if ( isplayer( who ) && is_true( level.devgui_break ) ) + { + level.devgui_break = 0; + should_break = 1; +#/ + } + if ( should_break ) + { + if ( !isplayer( who ) ) + { + who sloth_set_state( "crash", 1 ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "sloth_escape" ); + } + if ( isDefined( who.booze_player ) ) + { + who.booze_player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_sloth_booze_break_barricade", 0 ); + who.booze_player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_sloth_booze_break_barricade" ); + reward_dist = distance( who.berserk_start_org, who.origin ); + points = int( reward_dist / 10 ) * 10; + who.booze_player maps/mp/zombies/_zm_score::add_to_player_score( points ); + who.booze_player thread sloth_clears_path_vo(); + who.booze_player = undefined; + } + if ( isDefined( self.script_flag ) && level flag_exists( self.script_flag ) ) + { +/# + sloth_print( "flag_set " + self.script_flag ); +#/ + flag_set( self.script_flag ); + if ( self.script_flag == "jail_door1" ) + { + level notify( "jail_barricade_down" ); + } + } + if ( isDefined( self.script_noteworthy ) ) + { + if ( self.script_noteworthy == "courtyard_fountain" ) + { + level notify( "courtyard_fountain_open" ); + } + } + if ( isDefined( self.script_int ) ) + { + exploder( self.script_int ); + } + pieces = getentarray( self.target, "targetname" ); + _a831 = pieces; + _k831 = getFirstArrayKey( _a831 ); + while ( isDefined( _k831 ) ) + { + piece = _a831[ _k831 ]; + if ( should_delete ) + { + piece delete(); + } + else + { + piece hide_sloth_barrier(); + } + _k831 = getNextArrayKey( _a831, _k831 ); + } + self thread maps/mp/zombies/_zm_equip_headchopper::destroyheadchopperstouching( 0 ); + self playsound( "zmb_sloth_barrier_break" ); + level notify( "sloth_breaks_barrier" ); + if ( should_delete ) + { + self delete(); + } + else + { + self hide_sloth_barrier(); + } + return; + } + } +} + +sloth_clears_path_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + wait 2; + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_clears_path" ); +} + +hide_sloth_barrier() +{ + self.is_hidden = 1; + self notsolid(); + self ghost(); + if ( isDefined( self.script_noteworthy ) && self.script_noteworthy == "clip" ) + { + self connectpaths(); + } +} + +unhide_sloth_barrier() +{ + self.is_hidden = 0; + self solid(); + self show(); + if ( isDefined( self.script_noteworthy ) && self.script_noteworthy == "clip" ) + { + self disconnectpaths(); + } +} + +is_barricade_ent( ent ) +{ + i = 0; + while ( i < level.barricade_ents.size ) + { + if ( isDefined( ent.targetname ) ) + { + if ( ent.targetname == level.barricade_ents[ i ] ) + { + return 1; + } + } + i++; + } + return 0; +} + +jail_cell_watcher() +{ + level.jail_cell_volume = getent( "jail_cell_volume", "targetname" ); +} + +init_hunched_volume() +{ + level.hunched_volume = getent( "hunched_volume", "targetname" ); +} + +init_crash_triggers() +{ + level.crash_triggers = getentarray( "crash_trigger", "targetname" ); + _a935 = level.crash_triggers; + _k935 = getFirstArrayKey( _a935 ); + while ( isDefined( _k935 ) ) + { + trigger = _a935[ _k935 ]; + trigger thread watch_crash_trigger(); + _k935 = getNextArrayKey( _a935, _k935 ); + } +} + +watch_crash_trigger() +{ + while ( 1 ) + { + self waittill( "trigger", who ); + if ( who == level.sloth && who.state == "berserk" ) + { +/# + sloth_print( "crash trigger" ); +#/ + who setclientfield( "sloth_berserk", 0 ); + who sloth_set_state( "crash", 0 ); + } + } +} + +bell_ring() +{ + level endon( "maxis_minigame_start" ); + while ( 1 ) + { + level waittill( "bell_rung" ); + if ( isDefined( level.sloth ) ) + { + } + } +} + +wait_for_sloth( wait_state ) +{ + level endon( "ignore_wait" ); + sloth = level.sloth; + if ( isDefined( sloth ) ) + { + sloth.bench = self; + if ( wait_state == "gunshop_arrival" ) + { + while ( 1 ) + { + if ( sloth.state == "gunshop_candy" ) + { + break; + } + else + { + wait 0,1; + } + } + } + else if ( wait_state == "gunshop_table" ) + { + sloth waittill( "table_eat_done" ); + } + } +} + +wait_for_timeout() +{ + level endon( "candy_bench" ); + if ( isDefined( self.bench ) ) + { + self.bench waittill( "weap_bench_off" ); + self.bench = undefined; + self stop_action(); + self sloth_set_state( "roam" ); + } +} + +wait_for_candy() +{ + if ( isDefined( self.bench ) ) + { + self.bench endon( "weap_bench_off" ); + } + level waittill( "candy_bench" ); + self sloth_set_state( "table_eat" ); +} + +init_build_buildables() +{ + level.sloth_buildables = []; + level.sloth_buildables[ level.sloth_buildables.size ] = "riotshield_zm"; + level.sloth_buildables[ level.sloth_buildables.size ] = "turret"; + level.sloth_buildables[ level.sloth_buildables.size ] = "raygun"; + level.sloth_buildables[ level.sloth_buildables.size ] = "electric_trap"; + level.sloth_buildables[ level.sloth_buildables.size ] = "turbine"; + level.sloth_buildables[ level.sloth_buildables.size ] = "springpad_zm"; + level.sloth_buildables[ level.sloth_buildables.size ] = "subwoofer_zm"; + level.sloth_buildables[ level.sloth_buildables.size ] = "headchopper_zm"; + level.sloth_buildable_zones = []; + level waittill( "buildables_setup" ); + wait 0,1; + _a1058 = level.sloth_buildables; + _k1058 = getFirstArrayKey( _a1058 ); + while ( isDefined( _k1058 ) ) + { + sloth_buildable = _a1058[ _k1058 ]; + _a1060 = level.buildable_stubs; + _k1060 = getFirstArrayKey( _a1060 ); + while ( isDefined( _k1060 ) ) + { + stub = _a1060[ _k1060 ]; + if ( stub.buildablezone.buildable_name == sloth_buildable ) + { + level.sloth_buildable_zones[ level.sloth_buildable_zones.size ] = stub.buildablezone; + } + _k1060 = getNextArrayKey( _a1060, _k1060 ); + } + _k1058 = getNextArrayKey( _a1058, _k1058 ); + } +} + +init_wallbuys() +{ + level waittill( "buildables_setup" ); + level.sloth_wallbuy_stubs = []; + _a1079 = level.buildable_stubs; + _k1079 = getFirstArrayKey( _a1079 ); + while ( isDefined( _k1079 ) ) + { + stub = _a1079[ _k1079 ]; + if ( isDefined( stub.in_zone ) && stub.in_zone == "zone_mansion" ) + { + } + else + { + if ( stub.buildablezone.buildable_name == "chalk" ) + { + level.sloth_wallbuy_stubs[ level.sloth_wallbuy_stubs.size ] = stub; + } + } + _k1079 = getNextArrayKey( _a1079, _k1079 ); + } + level.gunshop_zone = getent( "sloth_candyzone_gunshop", "targetname" ); +} + +init_generator() +{ + level waittill( "buildables_setup" ); + level.generator_zones = []; + _a1104 = level.buildable_stubs; + _k1104 = getFirstArrayKey( _a1104 ); + while ( isDefined( _k1104 ) ) + { + stub = _a1104[ _k1104 ]; + if ( stub.buildablezone.buildable_name == "oillamp_zm" ) + { + level.generator_zones[ level.generator_zones.size ] = stub.buildablezone; + } + _k1104 = getNextArrayKey( _a1104, _k1104 ); + } +} + +init_fetch_buildables() +{ + power_items = []; + power_items[ power_items.size ] = "turret"; + power_items[ power_items.size ] = "electric_trap"; + power_items[ power_items.size ] = "subwoofer_zm"; + level.power_zones = []; + level waittill( "buildables_setup" ); + wait 0,1; + _a1129 = level.buildable_stubs; + _k1129 = getFirstArrayKey( _a1129 ); + while ( isDefined( _k1129 ) ) + { + stub = _a1129[ _k1129 ]; + _a1131 = power_items; + _k1131 = getFirstArrayKey( _a1131 ); + while ( isDefined( _k1131 ) ) + { + item = _a1131[ _k1131 ]; + if ( stub.buildablezone.buildable_name == item ) + { + level.power_zones[ level.power_zones.size ] = stub.buildablezone; + } + else + { + if ( stub.buildablezone.buildable_name == "turbine" ) + { + level.turbine_zone = stub.buildablezone; + } + } + _k1131 = getNextArrayKey( _a1131, _k1131 ); + } + _k1129 = getNextArrayKey( _a1129, _k1129 ); + } +} + +init_candy_context() +{ + register_candy_context( "protect", 95, ::protect_condition, ::protect_start, ::protect_update, ::protect_action ); + register_candy_context( "build_buildable", 40, ::build_buildable_condition, ::common_context_start, ::common_context_update, ::build_buildable_action, ::build_buildable_interrupt ); + register_candy_context( "wallbuy", 80, ::wallbuy_condition, ::common_context_start, ::common_context_update, ::wallbuy_action, ::wallbuy_interrupt ); + register_candy_context( "fetch_buildable", 50, ::fetch_buildable_condition, ::fetch_buildable_start, ::common_context_update, ::fetch_buildable_action, ::fetch_buildable_interrupt ); + register_candy_context( "box_lock", 65, ::box_lock_condition, ::common_context_start, ::common_context_update, ::box_lock_action ); + register_candy_context( "box_move", 70, ::box_move_condition, ::common_context_start, ::common_context_update, ::box_move_action, ::box_move_interrupt ); + register_candy_context( "box_spin", 75, ::box_spin_condition, ::common_context_start, ::common_context_update, ::box_spin_action ); + register_candy_context( "powerup_cycle", 30, ::powerup_cycle_condition, ::common_context_start, ::common_context_update, ::powerup_cycle_action ); + register_candy_context( "crawler", 85, ::crawler_condition, ::common_context_start, ::common_context_update, ::crawler_action ); +} + +register_candy_context( name, priority, func_condition, func_start, func_update, func_action, func_interrupt ) +{ + if ( !isDefined( level.candy_context ) ) + { + level.candy_context = []; + } + level.candy_context[ name ] = spawnstruct(); + level.candy_context[ name ].name = name; + level.candy_context[ name ].priority = priority; + level.candy_context[ name ].condition = func_condition; + level.candy_context[ name ].start = func_start; + level.candy_context[ name ].update = func_update; + level.candy_context[ name ].action = func_action; + level.candy_context[ name ].interrupt = func_interrupt; +} + +unregister_candy_context( name ) +{ + remove_context = undefined; + if ( !isDefined( level.candy_context ) || level.candy_context.size == 0 ) + { + return; + } + _a1188 = level.candy_context; + _k1188 = getFirstArrayKey( _a1188 ); + while ( isDefined( _k1188 ) ) + { + context = _a1188[ _k1188 ]; + if ( context.name == name ) + { + remove_context = context; + break; + } + else + { + _k1188 = getNextArrayKey( _a1188, _k1188 ); + } + } + if ( isDefined( remove_context ) ) + { + arrayremovevalue( level.candy_context, remove_context, 1 ); +/# + sloth_print( remove_context.name + " removed from candy context" ); +#/ + } +} + +sloth_grab_powerup() +{ + i = 0; + while ( i < level.active_powerups.size ) + { + powerup = level.active_powerups[ i ]; + dist = distancesquared( powerup.origin, self.origin ); + if ( dist < 9216 ) + { + if ( isDefined( self.follow_player ) ) + { + self.follow_player.ignore_range_powerup = powerup; + } + } + i++; + } +} + +sloth_prespawn() +{ + self endon( "death" ); + level endon( "intermission" ); + level.sloth = self; + if ( !isDefined( level.possible_slowgun_targets ) ) + { + level.possible_slowgun_targets = []; + } + level.possible_slowgun_targets[ level.possible_slowgun_targets.size ] = self; + self sloth_init_update_funcs(); + self sloth_init_start_funcs(); + self.has_legs = 1; + self.no_gib = 1; + self.nododgemove = 1; + self.is_sloth = 1; + self.ignore_enemy_count = 1; + recalc_zombie_array(); + self setphysparams( 15, 0, 73 ); +/# + setdvarint( "scr_sloth_debug_width", 15 ); + setdvarint( "scr_sloth_debug_height", 73 ); + self.debug_width = getDvarInt( #"2443DFBB" ); + self.debug_height = getDvarInt( #"897C9AB4" ); + self thread sloth_devgui_update_phys_params(); +#/ + 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.paralyzer_hit_callback = ::sloth_paralyzed; + self.paralyzer_slowtime = 0; + self.allowpain = 0; + self.jail_start = getstruct( "sloth_idle_pos", "targetname" ); + self forceteleport( self.jail_start.origin, self.jail_start.angles ); + self.gunshop = getstruct( "sloth_gunshop", "targetname" ); + self set_zombie_run_cycle( "walk" ); + self.locomotion = "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"; + if ( !isDefined( self.sndent ) ) + { + origin = self gettagorigin( "J_neck" ); + self.sndent = spawn( "script_origin", origin ); + self.sndent linkto( self, "J_neck" ); + } + self.meleedamage = 5; + self.ignoreall = 1; + self.ignoreme = 1; + self.ignore_spring_pad = 1; + self.ignore_headchopper = 1; + self thread create_candy_booze_trigger(); + self.zombie_init_done = 1; + self notify( "zombie_init_done" ); + self.needs_action = 1; + self.actor_damage_func = ::sloth_damage_func; + self.non_attacker_func = ::sloth_non_attacker; + self.set_anim_rate = ::sloth_set_anim_rate; + self.reset_anim = ::sloth_reset_anim; + self sloth_set_traverse_funcs(); + self disableaimassist(); + self.goalradius = 16; + self pushplayer( 1 ); + self.anchor = spawn( "script_origin", self.origin ); + self.anchor.angles = self.angles; + self.is_inside = 1; + self.near_zombies = 0; + self.aiteam = "allies"; + self.using_double_wide = 0; + self thread sloth_init_roam_point(); + self thread watch_double_wide(); + self thread watch_interiors(); + self thread watch_zombies(); + self thread watch_stink(); + self thread watch_pack_volume(); + self thread watch_jail_door(); + self thread watch_crash_pos(); + self.headbang_time = getTime(); + self.smell_time = getTime(); + self.leg_pain_time = getTime(); + self.to_maze = 1; + self.from_maze = 0; + self.damage_taken = 0; + self setclientfield( "actor_is_sloth", 1 ); +/# + self thread sloth_debug_buildables(); +#/ + self thread sloth_ffotd_prespawn(); +} + +sloth_set_traverse_funcs() +{ + self.pre_traverse = ::sloth_pre_traverse; + self.post_traverse = ::sloth_post_traverse; +} + +sloth_pre_traverse() +{ + if ( !self is_jail_state() ) + { + if ( self.state == "context" ) + { + if ( isDefined( self.buildable_model ) ) + { + self setanimstatefromasd( "zm_sling_equipment" ); + self maps/mp/animscripts/zm_shared::donotetracks( "sling_equipment_anim" ); + } + else + { + if ( is_true( self.box_model_visible ) ) + { + self setanimstatefromasd( "zm_sling_magicbox" ); + self maps/mp/animscripts/zm_shared::donotetracks( "sling_magicbox_anim" ); + } + } + return; + } + else + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.gift_trigger ); + } + } +} + +sloth_post_traverse() +{ + if ( !self is_jail_state() ) + { + if ( self.state == "context" ) + { + if ( isDefined( self.buildable_model ) ) + { + self setanimstatefromasd( "zm_unsling_equipment" ); + self maps/mp/animscripts/zm_shared::donotetracks( "unsling_equipment_anim" ); + } + else + { + if ( is_true( self.box_model_visible ) ) + { + self setanimstatefromasd( "zm_unsling_magicbox" ); + self maps/mp/animscripts/zm_shared::donotetracks( "unsling_magicbox_anim" ); + } + } + return; + } + else + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + } + } +} + +sloth_spawning_logic() +{ + level endon( "intermission" ); + if ( level.intermission ) + { + return; + } +/# + if ( getDvarInt( "zombie_cheat" ) == 2 || getDvarInt( "zombie_cheat" ) >= 4 ) + { + return; +#/ + } +/# + for ( ;; ) + { + while ( !is_true( level.sloth_enable ) ) + { + wait 0,2; + } +#/ + } + spawner = getent( "sloth_zombie_spawner", "script_noteworthy" ); + if ( !isDefined( spawner ) ) + { +/# + assertmsg( "No sloth spawner in the map." ); +#/ + return; + } + ai = spawn_zombie( spawner, "sloth" ); + if ( !isDefined( ai ) ) + { +/# + assertmsg( "Sloth: failed spawn" ); +#/ + return; + } + ai waittill( "zombie_init_done" ); + ai sloth_set_state( "jail_idle" ); + ai thread sloth_think(); +/# +#/ + level._sloth_ai = ai; +} + +sloth_init_update_funcs() +{ + self.update_funcs = []; + self.update_funcs[ "jail_idle" ] = ::update_jail_idle; + self.update_funcs[ "jail_cower" ] = ::update_jail_cower; + self.update_funcs[ "jail_open" ] = ::update_jail_open; + self.update_funcs[ "jail_run" ] = ::update_jail_run; + self.update_funcs[ "jail_wait" ] = ::update_jail_wait; + self.update_funcs[ "jail_close" ] = ::update_jail_close; + self.update_funcs[ "player_idle" ] = ::update_player_idle; + self.update_funcs[ "roam" ] = ::update_roam; + self.update_funcs[ "follow" ] = ::update_follow; + self.update_funcs[ "mansion" ] = ::update_mansion; + self.update_funcs[ "berserk" ] = ::update_berserk; + self.update_funcs[ "eat" ] = ::update_eat; + self.update_funcs[ "crash" ] = ::update_crash; + self.update_funcs[ "gunshop_run" ] = ::update_gunshop_run; + self.update_funcs[ "gunshop_candy" ] = ::update_gunshop_candy; + self.update_funcs[ "table_eat" ] = ::update_table_eat; + self.update_funcs[ "headbang" ] = ::update_headbang; + self.update_funcs[ "smell" ] = ::update_smell; + self.update_funcs[ "context" ] = ::update_context; + self.locomotion_func = ::update_locomotion; +} + +sloth_think() +{ + self endon( "death" ); + while ( 1 ) + { + self [[ self.update_funcs[ self.state ] ]](); + wait 0,1; + } +} + +update_jail_idle() +{ + if ( is_true( self.open_jail ) ) + { + level notify( "cell_open" ); + self.open_jail = 0; + } + if ( is_true( level.cell_open ) ) + { + self stop_action(); + self sloth_set_state( "jail_cower" ); + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + } +} + +update_jail_cower() +{ + if ( is_true( self.got_booze ) && is_true( level.cell_open ) ) + { + player = self get_player_to_follow(); + if ( isDefined( player ) ) + { + self sloth_set_state( "follow", player ); + return; + } + } +} + +update_jail_open() +{ + if ( self.needs_action ) + { + self sloth_set_state( "jail_cower" ); + } +} + +update_jail_run() +{ + if ( self.needs_action ) + { + self sloth_set_state( "jail_wait" ); + } +} + +update_jail_wait() +{ + players = get_players(); + _a1584 = players; + _k1584 = getFirstArrayKey( _a1584 ); + while ( isDefined( _k1584 ) ) + { + player = _a1584[ _k1584 ]; + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_underground_jail" ) ) + { + if ( is_holding_candybooze( player ) ) + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + self sloth_set_state( "follow", player ); + } + return; + } + _k1584 = getNextArrayKey( _a1584, _k1584 ); + } + _a1597 = players; + _k1597 = getFirstArrayKey( _a1597 ); + while ( isDefined( _k1597 ) ) + { + player = _a1597[ _k1597 ]; + if ( is_player_valid( player ) ) + { + dist = distancesquared( player.origin, level.jail_door.origin ); + if ( dist < 32400 ) + { + return; + } + } + _k1597 = getNextArrayKey( _a1597, _k1597 ); + } + if ( self.needs_action ) + { + self sloth_set_state( "jail_close" ); + } +} + +update_jail_close() +{ + if ( self.needs_action ) + { + self sloth_set_state( "jail_idle" ); + } +} + +update_player_idle() +{ + if ( self sloth_is_pain() ) + { + return; + } + if ( self sloth_is_traversing() ) + { + return; + } + if ( isDefined( self.follow_player ) ) + { + player = self.follow_player; + if ( is_true( player.is_in_ghost_zone ) || !sloth_on_same_side( player ) ) + { + self sloth_set_state( "mansion" ); + return; + } + if ( is_holding_candybooze( self.follow_player ) ) + { + player_dist = distancesquared( self.origin, self.follow_player.origin ); + if ( player_dist > 20736 ) + { + self sloth_set_state( "follow", self.follow_player ); + return; + } + } + else + { + self sloth_set_state( "roam" ); + return; + } + self orientmode( "face point", self.follow_player.origin ); + gimme_anim = undefined; + if ( is_holding( self.follow_player, "booze" ) ) + { + gimme_anim = "zm_gimme_booze"; + } + else + { + if ( is_holding( self.follow_player, "candy" ) ) + { + gimme_anim = "zm_gimme_candy"; + } + } + if ( !is_true( self.damage_accumulating ) ) + { + self action_player_idle( gimme_anim ); + } + } + else + { + self sloth_set_state( "roam" ); + } +} + +update_locomotion() +{ + should_run = getTime() < self.leg_pain_time; + if ( should_run ) + { + self sloth_check_ragdolls(); + if ( self.zombie_move_speed == "run" ) + { + if ( self.is_inside ) + { + self set_zombie_run_cycle( "run_hunched" ); + self.locomotion = "run_hunched"; + } + } + else if ( self.zombie_move_speed == "run_hunched" ) + { + if ( !self.is_inside ) + { + self set_zombie_run_cycle( "run" ); + self.locomotion = "run"; + } + } + else if ( self.is_inside ) + { + self set_zombie_run_cycle( "run_hunched" ); + self.locomotion = "run_hunched"; + } + else + { + self set_zombie_run_cycle( "run" ); + self.locomotion = "run"; + } + } + else if ( self.zombie_move_speed == "run" || self.zombie_move_speed == "run_hunched" ) + { + if ( self.is_inside ) + { + self set_zombie_run_cycle( "walk_hunched" ); + self.locomotion = "walk_hunched"; + } + else if ( self.near_zombies ) + { + self set_zombie_run_cycle( "walk_scared" ); + self.locomotion = "walk_scared"; + } + else + { + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + } + } + else + { + if ( self.zombie_move_speed == "walk" ) + { + if ( self.is_inside ) + { + self set_zombie_run_cycle( "walk_hunched" ); + self.locomotion = "walk_hunched"; + } + else + { + if ( self.near_zombies ) + { + self set_zombie_run_cycle( "walk_scared" ); + self.locomotion = "walk_scared"; + } + } + return; + } + else if ( self.zombie_move_speed == "walk_scared" ) + { + if ( self.is_inside ) + { + self set_zombie_run_cycle( "walk_hunched" ); + self.locomotion = "walk_hunched"; + } + else + { + if ( !self.near_zombies ) + { + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + } + } + return; + } + else + { + if ( self.zombie_move_speed == "walk_hunched" ) + { + if ( !self.is_inside ) + { + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + } + } + } + } +} + +update_roam() +{ + if ( self sloth_is_pain() ) + { + return; + } + self.ignore_timebomb_slowdown = 0; + if ( isDefined( self.locomotion_func ) ) + { + self [[ self.locomotion_func ]](); + } + player = self get_player_to_follow(); + if ( isDefined( player ) ) + { + self sloth_set_state( "follow", player ); + return; + } + if ( isDefined( self.mansion_goal ) ) + { + self setgoalpos( self.mansion_goal.origin ); + dist = distancesquared( self.origin, self.mansion_goal.origin ); + if ( dist < 1024 ) + { + self action_teleport_to_courtyard(); + self stop_action(); + return; + } + } + if ( self should_smell() ) + { + self sloth_set_state( "smell" ); + return; + } + if ( is_true( self.needs_action ) ) + { + points = array_randomize( level.roam_points ); + self thread action_roam_point( points[ 0 ] ); + } +} + +get_player_to_follow() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( is_holding_candybooze( player ) ) + { + return player; + } + i++; + } +} + +should_headbang() +{ + if ( self sloth_is_traversing() ) + { + return 0; + } + if ( isDefined( self.subwoofer ) ) + { + if ( getTime() > self.headbang_time ) + { + return 1; + } + } + return 0; +} + +should_smell() +{ + if ( self sloth_is_traversing() ) + { + return 0; + } + if ( isDefined( self.stink ) ) + { + if ( getTime() > self.smell_time ) + { + return 1; + } + } + return 0; +} + +update_follow() +{ + if ( self sloth_is_pain() ) + { + return; + } + if ( isDefined( self.locomotion_func ) ) + { + self [[ self.locomotion_func ]](); + } + if ( self should_smell() ) + { + self sloth_set_state( "smell" ); + return; + } + player = self.follow_player; + if ( isDefined( player ) ) + { + if ( is_holding_candybooze( player ) ) + { + player_dist = distancesquared( self.origin, player.origin ); + if ( is_true( player.is_in_ghost_zone ) || !sloth_on_same_side( player ) ) + { + self sloth_set_state( "mansion" ); + } + else + { + if ( player_dist < 8100 ) + { + self sloth_set_state( "player_idle" ); + } + else + { + self action_player_follow( player ); + } + } + return; + } + else + { + self sloth_set_state( "roam" ); + } + } +} + +sloth_on_same_side( player ) +{ + if ( self sloth_behind_mansion() ) + { + if ( player behind_mansion_zone() ) + { + return 1; + } + } + else + { + if ( !player behind_mansion_zone() ) + { + return 1; + } + } + return 0; +} + +update_mansion() +{ + player = self.follow_player; + if ( isDefined( player ) ) + { + if ( is_holding_candybooze( player ) ) + { + if ( is_true( player.is_in_ghost_zone ) ) + { + name = player.current_ghost_room_name; + if ( isDefined( name ) ) + { + room = level.ghost_rooms[ name ]; + if ( is_true( room.to_maze ) ) + { + self.to_maze = 1; + self.from_maze = 0; + } + else + { + if ( is_true( room.from_maze ) ) + { + self.to_maze = 0; + self.from_maze = 1; + } + } + } + } + else if ( self sloth_on_same_side( player ) ) + { + self sloth_set_state( "follow", player ); + return; + } + if ( self sloth_behind_mansion() ) + { + self.to_maze = 0; + self.from_maze = 1; + } + else + { + self.to_maze = 1; + self.from_maze = 0; + } + if ( isDefined( self.teleporting ) ) + { + if ( self.teleporting == "to_maze" ) + { + if ( self sloth_behind_mansion() ) + { + self.teleporting = undefined; + } + } + else + { + if ( self.teleporting == "to_courtyard" ) + { + if ( !self sloth_behind_mansion() ) + { + self.teleporting = undefined; + } + } + } + return; + } + if ( is_true( self.to_maze ) && !self sloth_behind_mansion() ) + { + self action_navigate_mansion( level.maze_depart, level.maze_arrive ); + } + else + { + if ( is_true( self.from_maze ) && self sloth_behind_mansion() ) + { + self action_navigate_mansion( level.courtyard_depart, level.courtyard_arrive ); + } + } + return; + } + else + { + self sloth_set_state( "roam" ); + } + } +} + +update_drink() +{ + if ( is_true( self.needs_action ) ) + { + self sloth_set_state( "berserk" ); + } +} + +sloth_check_ragdolls( ignore_zombie ) +{ + non_ragdoll = 0; + zombies = getaispeciesarray( level.zombie_team, "all" ); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + if ( is_true( zombie.is_sloth ) ) + { + i++; + continue; + } + else if ( isDefined( ignore_zombie ) && zombie == ignore_zombie ) + { + i++; + continue; + } + else + { + if ( isDefined( self.crawler ) && zombie == self.crawler ) + { + i++; + continue; + } + else + { + if ( self is_facing( zombie ) ) + { + dist = distancesquared( self.origin, zombie.origin ); + if ( dist < 4096 ) + { + if ( !self sloth_ragdoll_zombie( zombie ) ) + { + if ( !is_true( self.no_gib ) && ( non_ragdoll % 3 ) == 0 ) + { + zombie.force_gib = 1; + zombie.a.gib_ref = random( array( "guts", "right_arm", "left_arm", "head" ) ); + zombie thread maps/mp/animscripts/zm_death::do_gib(); + } + non_ragdoll++; + zombie dodamage( zombie.health * 10, zombie.origin ); + zombie playsound( "zmb_ai_sloth_attack_impact" ); + zombie.noragdoll = 1; + zombie.nodeathragdoll = 1; + level.zombie_total++; + } + if ( isDefined( self.target_zombie ) && self.target_zombie == zombie ) + { + self.target_zombie = undefined; + } + } + } + } + } + i++; + } +} + +sloth_ragdoll_zombie( zombie ) +{ + if ( !isDefined( self.ragdolls ) ) + { + self.ragdolls = 0; + } + if ( self.ragdolls < 4 ) + { + self.ragdolls++; + zombie dodamage( zombie.health * 10, zombie.origin ); + zombie playsound( "zmb_ai_sloth_attack_impact" ); + zombie startragdoll(); + zombie setclientfield( "sloth_ragdoll_zombie", 1 ); + level.zombie_total++; + self thread sloth_ragdoll_wait(); + return 1; + } + return 0; +} + +sloth_ragdoll_wait() +{ + self endon( "death" ); + wait 1; + if ( self.ragdolls > 0 ) + { + self.ragdolls--; + + } +} + +sloth_kill_zombie( zombie ) +{ + if ( !self sloth_ragdoll_zombie( zombie ) ) + { + if ( !is_true( self.no_gib ) ) + { + zombie.force_gib = 1; + zombie.a.gib_ref = random( array( "guts", "right_arm", "left_arm", "head" ) ); + zombie thread maps/mp/animscripts/zm_death::do_gib(); + } + zombie dodamage( zombie.health * 10, zombie.origin ); + zombie playsound( "zmb_ai_sloth_attack_impact" ); + } +} + +update_berserk() +{ + if ( !is_true( self.run_berserk ) ) + { + return; + } + self sloth_grab_powerup(); + self sloth_check_ragdolls(); + self.ignore_timebomb_slowdown = 1; + start = self.origin + vectorScale( ( 0, 1, 0 ), 39 ); + facing = anglesToForward( self.angles ); + end = start + ( facing * 48 ); + crash = 0; + trace = physicstrace( start, end, vectorScale( ( 0, 1, 0 ), 15 ), vectorScale( ( 0, 1, 0 ), 15 ), self ); +/# + if ( getDvarInt( #"B6252E7C" ) == 2 ) + { + line( start, end, ( 0, 1, 0 ), 1, 0, 100 ); +#/ + } + if ( isDefined( trace[ "entity" ] ) ) + { + hit_ent = trace[ "entity" ]; + if ( is_true( hit_ent.is_zombie ) ) + { + return; + } + else if ( isplayer( hit_ent ) ) + { + if ( !is_true( self.slowing ) ) + { + hit_ent dodamage( hit_ent.health, hit_ent.origin ); +/# + sloth_print( "hit player" ); +#/ + } + return; + } + else if ( is_barricade_ent( hit_ent ) ) + { +/# + if ( isDefined( hit_ent.targetname ) ) + { + sloth_print( "hit barricade ent " + hit_ent.targetname ); +#/ + } + return; + } + else + { +/# + if ( isDefined( hit_ent.targetname ) ) + { + sloth_print( "hit " + hit_ent.targetname ); +#/ + } + if ( isDefined( hit_ent.targetname ) && hit_ent.targetname == "sloth_fountain_clip" ) + { + fountain = getent( "courtyard_fountain", "script_noteworthy" ); + if ( isDefined( fountain ) ) + { + fountain notify( "trigger" ); + return; + } + } + crash = 1; + } + } + if ( isDefined( trace[ "fraction" ] ) && trace[ "fraction" ] < 1 ) + { + crash = 1; + } + if ( getTime() > ( self.berserk_time + 500 ) ) + { + dist = distancesquared( self.origin, self.berserk_org ); + if ( dist < 900 ) + { +/# + sloth_print( "BERSERK FAILSAFE!!!" ); +#/ + crash = 1; + } + self.berserk_org = self.origin; + self.berserk_time = getTime(); + } + if ( crash && self.state != "crash" ) + { + self setclientfield( "sloth_berserk", 0 ); + self sloth_set_state( "crash", 0 ); + } +} + +update_eat() +{ + if ( is_true( self.needs_action ) ) + { + self setclientfield( "sloth_eating", 0 ); + if ( isDefined( self.candy_model ) ) + { + self.candy_model ghost(); + } + context = self check_contextual_actions(); + if ( isDefined( context ) ) + { + if ( isDefined( self.candy_player ) ) + { + self.candy_player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_sloth_candy_" + context.name, 0 ); + self.candy_player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_sloth_candy_" + context.name ); + self.candy_player thread sloth_feed_vo(); + } + self sloth_set_state( "context", context ); + return; + } + self sloth_set_state( "roam" ); + } +} + +update_crash() +{ + if ( is_true( self.needs_action ) ) + { + self.reset_asd = undefined; + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + self notify( "stop_berserk" ); + self sloth_set_state( "roam" ); + } +} + +update_gunshop_run() +{ + if ( is_true( self.needs_action ) ) + { + self sloth_set_state( "gunshop_candy" ); + } +} + +update_gunshop_candy() +{ +} + +update_table_eat() +{ + if ( is_true( self.needs_action ) ) + { + self sloth_set_state( "roam" ); + } +} + +update_headbang() +{ + if ( getTime() > self.headbang_time ) + { + self.headbang_time = getTime() + 30000; + self stop_action(); + self sloth_set_state( "roam" ); + } +} + +update_smell() +{ + if ( is_true( self.needs_action ) ) + { + self.smell_time = getTime() + 30000; + self sloth_set_state( "roam" ); + } +} + +update_context() +{ + self [[ self.context.update ]](); +} + +sloth_init_start_funcs() +{ + self.start_funcs = []; + self.start_funcs[ "jail_idle" ] = ::start_jail_idle; + self.start_funcs[ "jail_cower" ] = ::start_jail_cower; + self.start_funcs[ "jail_open" ] = ::start_jail_open; + self.start_funcs[ "jail_run" ] = ::start_jail_run; + self.start_funcs[ "jail_wait" ] = ::start_jail_wait; + self.start_funcs[ "jail_close" ] = ::start_jail_close; + self.start_funcs[ "player_idle" ] = ::start_player_idle; + self.start_funcs[ "roam" ] = ::start_roam; + self.start_funcs[ "follow" ] = ::start_follow; + self.start_funcs[ "mansion" ] = ::start_mansion; + self.start_funcs[ "berserk" ] = ::start_berserk; + self.start_funcs[ "eat" ] = ::start_eat; + self.start_funcs[ "crash" ] = ::start_crash; + self.start_funcs[ "gunshop_run" ] = ::start_gunshop_run; + self.start_funcs[ "gunshop_candy" ] = ::start_gunshop_candy; + self.start_funcs[ "table_eat" ] = ::start_table_eat; + self.start_funcs[ "headbang" ] = ::start_headbang; + self.start_funcs[ "smell" ] = ::start_smell; + self.start_funcs[ "context" ] = ::start_context; +} + +sloth_set_state( state, param2 ) +{ + if ( isDefined( self.start_funcs[ state ] ) ) + { + result = 0; + if ( isDefined( param2 ) ) + { + result = self [[ self.start_funcs[ state ] ]]( param2 ); + } + else + { + result = self [[ self.start_funcs[ state ] ]](); + } + if ( result == 1 ) + { + self.state = state; +/# + sloth_print( "change state to " + self.state ); +#/ + } + } +} + +start_jail_idle() +{ + self thread action_jail_idle(); + self thread sndchangebreathingstate( "breathe" ); + return 1; +} + +start_jail_cower() +{ + self thread action_jail_cower( self.got_booze ); + self thread sndchangebreathingstate( "scared" ); + return 1; +} + +start_jail_close() +{ + self thread action_jail_close(); + self thread sndchangebreathingstate( "breathe" ); + return 1; +} + +start_jail_open() +{ + self thread action_jail_open(); + return 1; +} + +is_jail_state() +{ + states = []; + states[ states.size ] = "jail_idle"; + states[ states.size ] = "jail_cower"; + states[ states.size ] = "jail_open"; + states[ states.size ] = "jail_run"; + states[ states.size ] = "jail_wait"; + states[ states.size ] = "jail_close"; + _a2505 = states; + _k2505 = getFirstArrayKey( _a2505 ); + while ( isDefined( _k2505 ) ) + { + state = _a2505[ _k2505 ]; + if ( self.state == state ) + { + return 1; + } + _k2505 = getNextArrayKey( _a2505, _k2505 ); + } + return 0; +} + +start_jail_run( do_pain ) +{ + if ( self is_jail_state() ) + { + return 0; + } + if ( self.state == "berserk" || self.state == "crash" ) + { + return 0; + } + if ( self sloth_is_traversing() ) + { + return 0; + } + if ( self.state == "gunshop_candy" || self.state == "table_eat" ) + { + if ( isDefined( self.bench ) ) + { + if ( isDefined( level.weapon_bench_reset ) ) + { + self.bench [[ level.weapon_bench_reset ]](); + } + } + } + self stop_action(); + self thread sndchangebreathingstate( "scared" ); + self thread action_jail_run( self.jail_start.origin, do_pain ); + if ( self.state == "context" ) + { + if ( isDefined( self.context.interrupt ) ) + { + self [[ self.context.interrupt ]](); + } + } + self sloth_init_roam_point(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.gift_trigger ); + return 1; +} + +start_jail_wait() +{ + self stopanimscripted(); + self action_jail_wait(); + self thread sndchangebreathingstate( "scared" ); + return 1; +} + +start_player_idle( lock ) +{ + if ( self sloth_is_traversing() ) + { + return 0; + } + if ( self.state == "jail_cower" ) + { + return 0; + } + if ( is_true( lock ) ) + { + self orientmode( "face default" ); + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + } + gimme_anim = undefined; + if ( is_holding( self.follow_player, "booze" ) ) + { + gimme_anim = "zm_gimme_booze"; + } + else + { + if ( is_holding( self.follow_player, "candy" ) ) + { + gimme_anim = "zm_gimme_candy"; + } + } + if ( !is_true( self.damage_accumulating ) ) + { + self action_player_idle( gimme_anim ); + } + self thread sndchangebreathingstate( "happy" ); + return 1; +} + +check_behind_mansion() +{ + if ( self sloth_behind_mansion() ) + { +/# + sloth_print( "get back to mansion first" ); +#/ + near = ( 3652, -500, 20 ); + _a2627 = level.maze_to_mansion; + _k2627 = getFirstArrayKey( _a2627 ); + while ( isDefined( _k2627 ) ) + { + point = _a2627[ _k2627 ]; + dist = distance( point.origin, near ); + if ( dist < 10 ) + { + self.mansion_goal = point; + } + _k2627 = getNextArrayKey( _a2627, _k2627 ); + } + } + else self.mansion_goal = undefined; +} + +start_roam() +{ + self stop_action(); + self thread sndchangebreathingstate( "breathe", "happy" ); + self maps/mp/animscripts/zm_run::needsupdate(); + self.follow_player = undefined; + self.candy_player = undefined; + self check_behind_mansion(); + return 1; +} + +start_follow( player ) +{ + self stop_action(); + self thread sndchangebreathingstate( "happy" ); + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + self.follow_player = player; + self.current_roam = undefined; + return 1; +} + +start_mansion() +{ + self stop_action(); + self thread sndchangebreathingstate( "scared" ); + self maps/mp/animscripts/zm_run::needsupdate(); + self.can_follow = 0; + return 1; +} + +start_berserk( player ) +{ + self thread remove_gift_trigger( 0,1 ); + if ( !is_true( self.got_booze ) ) + { + self.got_booze = 1; + } + self.booze_player = player; + self.berserk_start_org = self.origin; + self.berserk_org = self.origin; + self.booze_player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_sloth_booze_given", 0 ); + self.booze_player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_sloth_booze_given" ); + self setclientfield( "sloth_berserk", 1 ); + player thread sloth_feed_vo(); + closest = self get_facing_barricade(); + if ( !isDefined( closest ) ) + { +/# + sloth_print( "failed to get barricade assist, try player" ); +#/ + closest = player get_facing_barricade( 1 ); + if ( isDefined( closest ) ) + { + self.aim_barricade = closest; + } + } + self.run_berserk = 0; + self action_berserk( self.follow_player ); + self thread sndchangebreathingstate( "angry" ); + return 1; +} + +sloth_feed_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( level.sloth_has_been_given_booze ) && !level.sloth_has_been_given_booze ) + { + level.sloth_has_been_given_booze = 1; + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "first_bersek" ); + } + else + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_generic_feed" ); + } +} + +sloth_debug_barricade() +{ +/# + while ( 1 ) + { + player = gethostplayer(); + while ( !isDefined( player ) ) + { + wait 1; + } + while ( getDvarInt( #"B6252E7C" ) != 3 ) + { + wait 1; + } + closest = player get_facing_barricade( 1 ); + wait 1; +#/ + } +} + +get_facing_barricade( ignore_segment_dist ) +{ + max_dist = 144000000; + closest = undefined; + closest_dot = 0; + closest_dot_position = 0; + closest_dot_facing = 0; + closest_segment_point = undefined; + if ( isplayer( self ) ) + { + angles = self getplayerangles(); + vec_forward = vectornormalize( anglesToForward( flat_angle( angles ) ) ); + } + else + { + angles = self.angles; + vec_forward = vectornormalize( anglesToForward( flat_angle( angles ) ) ) * -1; + } + triggers = getentarray( "sloth_barricade", "targetname" ); + i = 0; + while ( i < triggers.size ) + { + barricade = triggers[ i ]; + if ( isDefined( barricade ) ) + { + if ( isDefined( barricade.script_noteworthy ) && barricade.script_noteworthy == "courtyard_fountain" ) + { + i++; + continue; + } + else + { + ground_pos = groundpos( barricade.origin ); + start = ( self.origin[ 0 ], self.origin[ 1 ], ground_pos[ 2 ] ); + barricade_dist = distance( ground_pos, start ); + if ( barricade_dist > 900 ) + { + i++; + continue; + } + else segment_length = barricade_dist * 2; + end = start + ( vec_forward * segment_length ); + segment_point = pointonsegmentnearesttopoint( start, end, ground_pos ); + vec_barricade = vectornormalize( anglesToForward( barricade.angles ) ) * -1; + dot_barricade = vectordot( vec_forward, vec_barricade ); + if ( dot_barricade < 0,707 ) + { + i++; + continue; + } + else vec_position = vectornormalize( ground_pos - start ); + dot_position = vectordot( vec_position, vec_barricade ); + if ( dot_position < 0,707 ) + { + i++; + continue; + } + else dot_facing_pos = vectordot( vec_position, vec_forward ); + dist = distancesquared( ground_pos, segment_point ); + if ( !is_true( ignore_segment_dist ) ) + { + if ( dist > 10000 ) + { + i++; + continue; + } + } + else + { + if ( dist < max_dist ) + { + max_dist = dist; + closest = barricade; + closest_segment_point = segment_point; + closest_dot = dot_barricade; + closest_dot_position = dot_position; + closest_dot_facing = dot_facing_pos; + } + } + } + } + i++; + } + if ( isDefined( closest ) ) + { + ground_pos = groundpos( closest.origin ); +/# + if ( getDvarInt( #"B6252E7C" ) == 3 ) + { + line( closest_segment_point, ground_pos, ( 0, 1, 0 ), 1, 0, 60 ); +#/ + } + dist = distancesquared( closest_segment_point, ground_pos ); + self.aim_barricade = closest; + barricade_dist = distance( self.origin, ground_pos ); +/# + if ( getDvarInt( #"B6252E7C" ) == 3 ) + { + line( self.origin, ground_pos, ( 0, 1, 0 ), 1, 0, 60 ); +#/ + } + } + return closest; +} + +barricade_assist() +{ + max_dist = 144000000; + closest = undefined; + closest_dot = 0; + closest_segment_point = undefined; + vec_forward = vectornormalize( anglesToForward( self.angles ) ); + vec_backward = vec_forward * -1; + triggers = getentarray( "sloth_barricade", "targetname" ); + i = 0; + while ( i < triggers.size ) + { + barricade = triggers[ i ]; + if ( isDefined( barricade ) ) + { + ground_pos = groundpos( barricade.origin ); + barricade_dist = distance( ground_pos, self.origin ); + segment_length = barricade_dist * 2; + sloth_start = self.origin; + sloth_end = self.origin + ( vec_backward * segment_length ); + segment_point = pointonsegmentnearesttopoint( sloth_start, sloth_end, ground_pos ); + dist = distancesquared( ground_pos, segment_point ); + if ( dist < max_dist ) + { + max_dist = dist; + closest = barricade; + closest_segment_point = segment_point; + } + } + i++; + } + if ( isDefined( closest ) ) + { + ground_pos = groundpos( closest.origin ); +/# + if ( getDvarInt( #"B6252E7C" ) == 2 ) + { + line( closest_segment_point, ground_pos, ( 0, 1, 0 ), 1, 0, 500 ); +#/ + } + dist = distancesquared( closest_segment_point, ground_pos ); + if ( dist < 10000 ) + { + self.aim_barricade = closest; + } +/# + sloth_print( "dist: " + sqrt( dist ) + " max_dist: " + sqrt( max_dist ) ); +#/ +/# + if ( getDvarInt( #"B6252E7C" ) == 2 ) + { + line( self.origin, ground_pos, ( 0, 1, 0 ), 1, 0, 500 ); +#/ + } + } +} + +start_eat( player ) +{ + self thread remove_gift_trigger( 0,1 ); + self.candy_player = player; + self.candy_player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_sloth_candy_given", 0 ); + self.candy_player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_sloth_candy_given" ); + self thread watch_player_zombies(); + twr_origin = self gettagorigin( "tag_weapon_right" ); + twr_angles = self gettagangles( "tag_weapon_right" ); + if ( !isDefined( self.candy_model ) ) + { + self.candy_model = spawn( "script_model", twr_origin ); + self.candy_model.angles = twr_angles; + self.candy_model setmodel( level.candy_model ); + self.candy_model linkto( self, "tag_weapon_right" ); + } + else + { + self.candy_model show(); + } + self setclientfield( "sloth_eating", 1 ); + self thread action_animscripted( "zm_eat_candy", "eat_candy_anim" ); + return 1; +} + +start_crash( barricade ) +{ + if ( self.state == "crash" ) + { + return 0; + } + if ( barricade ) + { + self.reset_asd = "zm_barricade"; + self thread action_anim( "zm_barricade", "crash_anim" ); + } + else + { + self.reset_asd = "zm_crash"; + self thread action_anim( "zm_crash", "crash_anim" ); + } + self thread sndchangebreathingstate( "happy" ); +/# + if ( isDefined( self.debug_berserk ) ) + { + elapsed = ( getTime() - self.debug_berserk ) / 1000; + dist = distance( self.origin, self.debug_berserk_org ); + sloth_print( ( "berserk dist = " + dist + " elapsed = " + elapsed + " rate = " ) + ( dist / elapsed ) ); +#/ + } + return 1; +} + +start_gunshop_run() +{ + if ( self.state == "follow" || self.state == "roam" ) + { + self thread action_gunshop_run(); + self thread sndchangebreathingstate( "breathe", "happy" ); + return 1; + } + return 0; +} + +start_gunshop_candy() +{ + self thread wait_for_timeout(); + self thread wait_for_candy(); + self thread action_gunshop_candy(); + self thread sndchangebreathingstate( "happy" ); + return 1; +} + +start_table_eat() +{ + self stop_action(); + self thread action_table_eat(); + return 1; +} + +start_headbang() +{ + self stop_action(); + self.headbang_time = getTime() + 10000; + self thread action_headbang(); + self thread sndchangebreathingstate( "happy" ); + return 1; +} + +start_smell() +{ + self stop_action(); + self thread action_smell(); + self thread sndchangebreathingstate( "breathe", "happy" ); + return 1; +} + +start_context( context ) +{ + self stop_action(); + self thread sndchangebreathingstate( "happy", "angry" ); + self.ignore_common_run = 0; + self.context = context; + self [[ context.start ]](); + return 1; +} + +remove_gift_trigger( delay ) +{ + if ( isDefined( delay ) ) + { + wait delay; + } + while ( 1 ) + { + if ( isDefined( self.gift_trigger ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.gift_trigger ); + return; + } + wait 0,1; + } +} + +action_jail_idle() +{ + self endon( "stop_action" ); + self.needs_action = 0; + self setgoalpos( self.origin ); + while ( 1 ) + { + self animscripted( self.jail_start.origin, self.jail_start.angles, "zm_jail_idle" ); + maps/mp/animscripts/zm_shared::donotetracks( "jail_idle_anim" ); + } +} + +action_jail_cower( jumpback ) +{ + cower_trans = "zm_jail_2_cower"; + cower_idle = "zm_cower_idle"; + if ( is_true( jumpback ) ) + { + cower_trans = "zm_jail_2_cower_jumpback"; + cower_idle = "zm_cower_jumpback_idle"; + } + self.needs_action = 0; + self animscripted( self.jail_start.origin, self.jail_start.angles, cower_trans ); + maps/mp/animscripts/zm_shared::donotetracks( "jail_2_cower_anim" ); + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + self setgoalpos( self.origin ); + self setanimstatefromasd( cower_idle ); +} + +action_jail_open() +{ + self.needs_action = 0; + self animscripted( self.jail_start.origin, self.jail_start.angles, "zm_jail_open" ); + maps/mp/animscripts/zm_shared::donotetracks( "jail_open_anim" ); + self.needs_action = 1; +} + +action_jail_close() +{ + self.needs_action = 0; + if ( isDefined( level.jail_close_door ) ) + { + level thread [[ level.jail_close_door ]](); + } + self animscripted( self.jail_start.origin, self.jail_start.angles, "zm_cower_2_close" ); + self blend_notetracks( "cower_2_close_anim" ); + level notify( "cell_close" ); + self.needs_action = 1; +} + +action_jail_wait() +{ + self.needs_action = 0; + self setgoalpos( self.origin ); + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + self setanimstatefromasd( "zm_cower_jumpback_idle" ); + self.needs_action = 1; +} + +action_teleport_to_courtyard() +{ +/# + sloth_print( "teleport to courtyard" ); +#/ + points = array_randomize( level.courtyard_arrive ); + self forceteleport( points[ 0 ].origin ); + self.mansion_goal = undefined; +} + +finish_pain() +{ + self endon( "death" ); + self endon( "pain_done" ); + while ( 1 ) + { + anim_state = self getanimstatefromasd(); + if ( anim_state != "zm_pain" && anim_state != "zm_pain_no_restart" ) + { +/# + sloth_print( "pain was interrupted" ); +#/ + self setanimstatefromasd( "zm_pain_no_restart" ); + } + wait 0,1; + } +} + +action_jail_run( pos, do_pain ) +{ + self.needs_action = 0; + if ( isDefined( self.candy_model ) ) + { + self.candy_model ghost(); + } + if ( isDefined( self.booze_model ) ) + { + self.booze_model ghost(); + } + if ( is_true( do_pain ) ) + { + if ( !self sloth_is_traversing() && !is_true( self.is_pain ) ) + { + self.is_pain = 1; + self setanimstatefromasd( "zm_pain" ); + self.reset_asd = "zm_pain"; + self thread finish_pain(); + maps/mp/animscripts/zm_shared::donotetracks( "pain_anim" ); + self notify( "pain_done" ); + self.is_pain = 0; + } + } + while ( 1 ) + { + if ( !self sloth_is_pain() ) + { + break; + } + else + { + wait 0,1; + } + } + self.reset_asd = undefined; + self animmode( "normal" ); + self set_zombie_run_cycle( "run_wounded" ); + self.locomotion = "run_wounded"; + self thread sloth_retreat_vo(); + self check_behind_mansion(); + if ( isDefined( self.mansion_goal ) ) + { + self setgoalpos( self.mansion_goal.origin ); + self waittill( "goal" ); + self action_teleport_to_courtyard(); + } + self setgoalpos( pos ); + self waittill( "goal" ); + self animscripted( self.jail_start.origin, self.jail_start.angles, "zm_run_into_jail_cower" ); + self blend_notetracks( "run_into_jail_cower_anim" ); + self.needs_action = 1; +} + +sloth_retreat_vo() +{ + wait 1; + a_players = getplayers(); + a_closest = get_array_of_closest( self.origin, a_players ); + i = 0; + while ( i < a_closest.size ) + { + if ( isDefined( a_closest[ i ].dontspeak ) && !a_closest[ i ].dontspeak ) + { + if ( isalive( a_closest[ i ] ) ) + { + a_closest[ i ] thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_retreat_cell" ); + } + } + i++; + } +} + +action_roam_point( point ) +{ + self endon( "death" ); + self notify( "stop_action" ); + self endon( "stop_action" ); + self.needs_action = 0; + if ( isDefined( self.current_roam ) ) + { + if ( point.script_noteworthy != self.current_roam.script_noteworthy ) + { +/# + sloth_print( "using sloth_mover " + self.current_roam.script_noteworthy ); +#/ + sub_goal_array = getstructarray( self.current_roam.script_noteworthy, "script_noteworthy" ); + _a3338 = sub_goal_array; + _k3338 = getFirstArrayKey( _a3338 ); + while ( isDefined( _k3338 ) ) + { + sg = _a3338[ _k3338 ]; + if ( isDefined( sg.targetname ) && sg.targetname == "player_respawn_point" ) + { + } + else + { + sub_goal = sg; + } + _k3338 = getNextArrayKey( _a3338, _k3338 ); + } + ground_pos = groundpos( sub_goal.origin ); + self sloth_check_turn( ground_pos, 0 ); + self setgoalpos( ground_pos ); + self waittill( "goal" ); + sub_goal_next = getstruct( sub_goal.target, "targetname" ); + ground_pos = groundpos( sub_goal_next.origin ); + self sloth_check_turn( ground_pos, 0 ); + self setgoalpos( ground_pos ); + self waittill( "goal" ); + } + } + self sloth_check_turn( point.origin, 0 ); + self setgoalnode( point ); + self waittill( "goal" ); + self.current_roam = point; + self.needs_action = 1; +} + +action_player_idle( gimme_anim ) +{ + self.needs_action = 0; + self setgoalpos( self.origin ); + if ( isDefined( gimme_anim ) ) + { + self setanimstatefromasd( gimme_anim ); + } + else + { + self setanimstatefromasd( "zm_player_idle" ); + } +} + +action_navigate_mansion( depart_points, arrive_points ) +{ + if ( !isDefined( self.teleport ) ) + { + points = array_randomize( depart_points ); + i = 0; + while ( i < points.size ) + { + end = i + 1; + if ( end == points.size ) + { + end = 0; + } + points[ i ].next = points[ end ]; + i++; + } + self.teleport = points[ 0 ]; + self setgoalpos( self.teleport.origin ); + } + else + { + dist = distancesquared( self.origin, self.teleport.origin ); + if ( dist < 1024 ) + { + if ( self player_can_see_sloth() ) + { +/# + sloth_print( "player can see sloth, try another spot" ); +#/ + self.teleport = self.teleport.next; + self setgoalpos( self.teleport.origin ); + return; + } + if ( depart_points[ 0 ].targetname == level.maze_depart[ 0 ].targetname ) + { +/# + sloth_print( "teleport to maze" ); +#/ + self.teleporting = "to_maze"; + } + else + { +/# + sloth_print( "teleport to courtyard" ); +#/ + self.teleporting = "to_courtyard"; + } + arrive = array_randomize( arrive_points ); + self forceteleport( arrive[ 0 ].origin ); + self setgoalpos( arrive[ 0 ].origin ); + self.teleport = undefined; + self.teleport_time = getTime(); + } + } +} + +player_can_see_sloth() +{ + players = get_players(); + _a3447 = players; + _k3447 = getFirstArrayKey( _a3447 ); + while ( isDefined( _k3447 ) ) + { + player = _a3447[ _k3447 ]; + if ( player.sessionstate == "spectator" ) + { + } + else + { + if ( player is_player_looking_at( self.origin, 0,7, 0, undefined ) ) + { + return 1; + } + } + _k3447 = getNextArrayKey( _a3447, _k3447 ); + } + return 0; +} + +sloth_check_turn( pos, dot_limit ) +{ + if ( !isDefined( dot_limit ) ) + { + dot_limit = -0,707; + } + self endon( "death" ); + if ( !isDefined( self.locomotion ) ) + { +/# + sloth_print( "tried turn but no locomotion defined" ); +#/ + return; + } + if ( is_true( self.is_turning ) ) + { + return; + } + vec_forward = vectornormalize( anglesToForward( self.angles ) ); + vec_goal = vectornormalize( pos - self.origin ); + dot = vectordot( vec_forward, vec_goal ); + if ( dot < dot_limit ) + { + turn_asd = "zm_sloth_" + self.locomotion + "_turn_180"; + if ( !self hasanimstatefromasd( turn_asd ) ) + { +/# + sloth_print( "no turn for " + turn_asd ); +#/ + return; + return; + } + else + { + self.is_turning = 1; + self animcustom( ::sloth_do_turn_anim ); + anim_length = self getanimlengthfromasd( turn_asd, 0 ); + self waittill_notify_or_timeout( "turn_anim_done", anim_length ); + self.is_turning = 0; + } + } +} + +sloth_do_turn_anim() +{ + self endon( "death" ); + self endon( "stop_action" ); + turn_asd = "zm_sloth_" + self.locomotion + "_turn_180"; +/# + sloth_print( turn_asd ); +#/ + self setanimstatefromasd( turn_asd ); + if ( isDefined( self.crawler ) ) + { + turn_crawler_asd = "zm_crawler_crawlerhold_walk"; + if ( self.is_inside ) + { + turn_crawler_asd += "_hunched"; + } + turn_crawler_asd += "_turn_180"; + self.crawler setanimstatefromasd( turn_crawler_asd ); + } + maps/mp/animscripts/zm_shared::donotetracks( "sloth_turn_180_anim" ); + self notify( "turn_anim_done" ); + self.is_turning = 0; +} + +action_player_follow( player ) +{ + origin = player.origin; + if ( is_true( player.slowgun_flying ) ) + { + ground_ent = player getgroundent(); + if ( !isDefined( ground_ent ) ) + { + ground_pos = groundpos( player.origin ); + node = getnearestnode( ground_pos ); + if ( !isDefined( node ) ) + { + node = getnearestnode( self.origin ); + } + if ( isDefined( node ) ) + { + origin = node.origin; + } + } + } + self setgoalpos( origin ); +} + +action_player_ask( gimme_anim ) +{ + self endon( "stop_action" ); + if ( !isDefined( gimme_anim ) ) + { + self.needs_action = 1; + return; + } + self.needs_action = 0; + self setanimstatefromasd( gimme_anim ); + maps/mp/animscripts/zm_shared::donotetracks( "gimme_anim" ); + self.needs_action = 1; +} + +action_berserk( player ) +{ + self.needs_action = 0; + self animcustom( ::custom_berserk ); +} + +action_anim( asd_name, notify_name ) +{ + self endon( "death" ); + self.needs_action = 0; + self setanimstatefromasd( asd_name ); + maps/mp/animscripts/zm_shared::donotetracks( notify_name ); + self.needs_action = 1; +} + +action_animscripted( asd_name, notify_name, origin, angles ) +{ + self endon( "death" ); + org = self.origin; + ang = self.angles; + if ( isDefined( origin ) ) + { + org = origin; + } + if ( isDefined( angles ) ) + { + ang = angles; + } + self.needs_action = 0; + self animscripted( org, ang, asd_name ); + maps/mp/animscripts/zm_shared::donotetracks( notify_name ); + self.needs_action = 1; +} + +custom_berserk() +{ + self endon( "death" ); + self setanimstatefromasd( "zm_drink_booze" ); + twr_origin = self gettagorigin( "tag_weapon_right" ); + twr_angles = self gettagangles( "tag_weapon_right" ); + if ( !isDefined( self.booze_model ) ) + { + self.booze_model = spawn( "script_model", twr_origin ); + self.booze_model.angles = twr_angles; + self.booze_model setmodel( level.booze_model ); + self.booze_model linkto( self, "tag_weapon_right" ); + } + else + { + self.booze_model show(); + } + self thread booze_wait(); + self setclientfield( "sloth_drinking", 1 ); + self blend_notetracks( "drink_booze_anim" ); + if ( isDefined( self.aim_barricade ) ) + { +/# + if ( isDefined( self.aim_barricade.script_noteworthy ) ) + { + sloth_print( "aiming at: " + self.aim_barricade.script_noteworthy ); +#/ + } + self orientmode( "face point", self.aim_barricade.origin ); + } + self setanimstatefromasd( "zm_drink_booze_aim" ); + self setclientfield( "sloth_glass_brk", 0 ); + self setclientfield( "sloth_drinking", 0 ); + self thread kill_near_zombies(); + self blend_notetracks( "drink_booze_aim_anim" ); + self notify( "stop_kill_near_zombies" ); + if ( isDefined( self.aim_barricade ) ) + { + self orientmode( "face default" ); + self.aim_barricade = undefined; + } + self.berserk_time = getTime(); + self.run_berserk = 1; + self animmode( "gravity" ); + self setanimstatefromasd( "zm_move_run_berserk" ); + self.reset_asd = "zm_move_run_berserk"; + if ( isDefined( self.booze_player ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sloth_run" ); + } +/# + self.debug_berserk = getTime(); + self.debug_berserk_org = self.origin; +#/ + self waittill( "stop_berserk" ); + self animmode( "normal" ); + self.run_berserk = 0; + self.needs_action = 1; +} + +blend_notetracks( animname ) +{ + self endon( "death" ); + self waittillmatch( animname ); + return "blend"; +} + +kill_near_zombies() +{ + self endon( "death" ); + self endon( "stop_kill_near_zombies" ); + gibbed = 0; + zombies = getaispeciesarray( level.zombie_team, "all" ); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + if ( is_true( zombie.is_sloth ) ) + { + i++; + continue; + } + else + { + dist = distancesquared( self.origin, zombie.origin ); + if ( dist < 4096 ) + { + if ( !is_true( self.no_gib ) && ( gibbed % 3 ) == 0 ) + { + zombie.force_gib = 1; + zombie.a.gib_ref = random( array( "guts", "right_arm", "left_arm", "head" ) ); + zombie thread maps/mp/animscripts/zm_death::do_gib(); + } + gibbed++; + zombie dodamage( zombie.health * 10, zombie.origin ); + zombie.noragdoll = 1; + zombie.nodeathragdoll = 1; + level.zombie_total++; + } + } + i++; + } +} + +booze_wait() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "drink_booze_anim", note ); + if ( note == "hitground" || note == "end" ) + { + self setclientfield( "sloth_glass_brk", 1 ); + if ( isDefined( self.booze_model ) ) + { + self.booze_model ghost(); + } + return; + } + else + { + } + } +} + +action_gunshop_run() +{ + self endon( "death" ); + self.needs_action = 0; + self set_zombie_run_cycle( "run" ); + self.locomotion = "run"; + self setgoalpos( self.gunshop.origin ); + self waittill( "goal" ); + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + self.needs_action = 1; +} + +action_gunshop_candy() +{ + self endon( "death" ); + self endon( "stop_action" ); + self.needs_action = 0; + self setgoalpos( self.origin ); + while ( 1 ) + { + self animscripted( self.origin, self.angles, "zm_player_idle" ); + maps/mp/animscripts/zm_shared::donotetracks( "player_idle_anim" ); + } +} + +action_table_eat() +{ + self endon( "death" ); + self endon( "stop_action" ); + asd = "zm_eat_candy_storage_table"; + table_org = self.origin; + align_org = self.origin; + align_angles = self.angles; + if ( isDefined( self.bench ) ) + { + table = getent( self.bench.target, "targetname" ); + anim_id = self getanimfromasd( asd, 0 ); + table_org = getstartorigin( table.origin, table.angles, anim_id ); + align_org = table.origin; + align_angles = table.angles; + } + self.needs_action = 0; + self setgoalpos( table_org ); + self waittill( "goal" ); + self animscripted( align_org, align_angles, asd ); + maps/mp/animscripts/zm_shared::donotetracks( "eat_candy_storage_table_anim" ); + self notify( "table_eat_done" ); + self.needs_action = 1; +} + +action_headbang() +{ + self endon( "death" ); + self endon( "stop_action" ); + self.needs_action = 0; + self setgoalpos( self.origin ); + while ( 1 ) + { + self animscripted( self.origin, self.angles, "zm_headbang" ); + maps/mp/animscripts/zm_shared::donotetracks( "headbang_anim" ); + } +} + +action_smell() +{ + self endon( "death" ); + self endon( "stop_action" ); + self.needs_action = 0; + self setgoalpos( self.origin ); + self animscripted( self.origin, self.angles, "zm_smell_react" ); + maps/mp/animscripts/zm_shared::donotetracks( "smell_react_anim" ); + self.needs_action = 1; +} + +stop_action() +{ + self notify( "stop_action" ); + self.is_turning = 0; + self.teleport = undefined; + self.needs_action = 1; + self stopanimscripted(); + self unlink(); + self orientmode( "face default" ); +} + +check_contextual_actions() +{ + context = undefined; + keys = getarraykeys( level.candy_context ); + i = 0; + while ( i < keys.size ) + { + if ( self [[ level.candy_context[ keys[ i ] ].condition ]]() ) + { + if ( isDefined( context ) ) + { + if ( level.candy_context[ keys[ i ] ].priority < context.priority ) + { + context = level.candy_context[ keys[ i ] ]; + } + i++; + continue; + } + else + { + context = level.candy_context[ keys[ i ] ]; + } + } + i++; + } + return context; +} + +common_context_start() +{ +/# + sloth_print( self.context.name ); +#/ + self.context_done = 0; + self thread [[ self.context.action ]](); +} + +common_context_update() +{ + if ( is_true( self.context_done ) ) + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + self orientmode( "face default" ); + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + self sloth_set_state( "roam" ); + } + else + { + if ( !is_true( self.ignore_common_run ) ) + { + self common_context_run( "run" ); + } + anim_state = self getanimstatefromasd(); + if ( anim_state == "zm_move_run" || anim_state == "zm_move_run_hunched" ) + { + self sloth_check_ragdolls(); + } + } +} + +common_context_run( move_run ) +{ + if ( self.is_inside ) + { + move_run += "_hunched"; + } + if ( self.zombie_move_speed != move_run ) + { + self set_zombie_run_cycle( move_run ); + self.locomotion = move_run; + } + else + { + if ( is_true( self.was_idle ) ) + { + self.was_idle = 0; + self maps/mp/animscripts/zm_run::needsupdate(); + } + } +} + +common_context_action() +{ + self common_context_run( "run" ); +} + +protect_condition() +{ + return 1; +} + +protect_start() +{ +/# + sloth_print( "protect " + self.candy_player.name ); +#/ + self.protect_time = getTime(); + self thread protect_action(); + self thread sndchangebreathingstate( "angry" ); +} + +protect_update() +{ + if ( !is_true( self.candy_player.is_in_ghost_zone ) || ( getTime() - self.protect_time ) > 45000 && should_ignore_candybooze( self.candy_player ) ) + { + if ( isDefined( self.target_zombie ) ) + { + self.target_zombie = undefined; + } + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + self notify( "stop_player_watch" ); + self set_zombie_run_cycle( "walk" ); + self.locomotion = "walk"; + self sloth_set_state( "roam" ); + self orientmode( "face default" ); + } +} + +protect_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self setclientfield( "sloth_berserk", 0 ); + if ( !isDefined( level.sloth_protect ) ) + { + level.sloth_protect = 1; + } + else + { + level.sloth_protect++; + } + while ( 1 ) + { + if ( !isDefined( self.target_zombie ) || self.target_zombie.health <= 0 ) + { + if ( self.target_zombies.size > 0 ) + { + closest = undefined; + closest_dist = undefined; + i = 0; + while ( i < self.target_zombies.size ) + { + zombie = self.target_zombies[ i ]; + if ( zombie.health > 0 ) + { + dist = distancesquared( self.candy_player.origin, zombie.origin ); + if ( !isDefined( closest ) || dist < closest_dist ) + { + closest = zombie; + closest_dist = dist; + } + } + i++; + } + if ( isDefined( closest ) ) + { + self.target_zombie = closest; + } + } + } + if ( isDefined( self.target_zombie ) ) + { + dist = distancesquared( self.origin, self.target_zombie.origin ); + if ( dist < 4096 ) + { + self sloth_check_turn( self.target_zombie.origin, -0,923 ); + self.anchor.origin = self.origin; + self.anchor.angles = flat_angle( vectorToAngle( self.target_zombie.origin - self.origin ) ); + self animscripted( self.anchor.origin, self.anchor.angles, "zm_melee_attack" ); + maps/mp/animscripts/zm_shared::donotetracks( "melee_attack", ::sloth_melee_notetracks ); + self.target_zombie = undefined; + } + else + { + self sloth_check_turn( self.target_zombie.origin, -0,923 ); + self setgoalpos( self.target_zombie.origin ); + self common_context_run( "run_frantic" ); + self sloth_check_ragdolls( self.target_zombie ); +/# + if ( getDvarInt( #"B6252E7C" ) == 2 ) + { + line( self.origin, self.target_zombie.origin, ( 0, 1, 0 ), 1, 0, 6 ); +#/ + } + } + } + else dist = distancesquared( self.origin, self.candy_player.origin ); + if ( dist < 32400 && !self sloth_is_traversing() ) + { + self setgoalpos( self.origin ); + self setanimstatefromasd( "zm_idle_protect" ); + self.was_idle = 1; + } + else + { + self sloth_check_turn( self.candy_player.origin, -0,923 ); + self setgoalpos( self.candy_player.origin ); + self common_context_run( "run_frantic" ); + self sloth_check_ragdolls( self.target_zombie ); + } + wait 0,1; + } +} + +sloth_melee_notetracks( note ) +{ + if ( note != "j_wrist_ri" || note == "j_wrist_le" && note == "j_ball_ri" ) + { + if ( isDefined( self.target_zombie ) ) + { + playfxontag( level._effect[ "headshot_nochunks" ], self.target_zombie, "j_head" ); + self sloth_kill_zombie( self.target_zombie ); + } + self sloth_check_ragdolls( self.target_zombie ); + } +} + +lamp_condition() +{ + if ( !isDefined( level.oillamp ) ) + { + return 0; + } + if ( !isDefined( level.oillamp.unitrigger ) || is_true( level.oillamp.built ) ) + { + return 0; + } + i = 0; + while ( i < level.generator_zones.size ) + { + zone = level.generator_zones[ i ]; + dist = distancesquared( zone.stub.origin, self.origin ); + if ( dist < 14400 ) + { + self.buildable_zone = zone; + return 1; + } + i++; + } + return 0; +} + +lamp_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self set_zombie_run_cycle( "run" ); + self.locomotion = "run"; + self maps/mp/animscripts/zm_run::needsupdate(); + self.oillamp = level.oillamp; + lamp_gone = 0; + while ( 1 ) + { + if ( self.oillamp != level.oillamp ) + { +/# + sloth_print( "lamp moved" ); +#/ + self.oillamp = level.oillamp; + } + if ( isDefined( self.oillamp.unitrigger ) && !is_true( self.oillamp.built ) ) + { + self setgoalpos( self.oillamp.unitrigger.origin ); + dist = distancesquared( self.oillamp.unitrigger.origin, self.origin ); + if ( dist < 4096 ) + { + break; + } + else } + else lamp_gone = 1; + break; + wait 0,1; + } + if ( lamp_gone ) + { +/# + sloth_print( "lamp is gone" ); +#/ + self.context_done = 1; + return; + } +/# + sloth_print( "got lamp" ); +#/ + self.oillamp maps/mp/zombies/_zm_buildables::piece_unspawn(); + self action_animscripted( "zm_wallbuy_remove", "wallbuy_remove_anim" ); + stub = self.buildable_zone.stub; + vec_right = vectornormalize( anglesToRight( stub.angles ) ); + ground_pos = stub.origin - ( vec_right * 60 ); + ground_pos = groundpos( ground_pos ); + self setgoalpos( ground_pos ); + self waittill( "goal" ); + generator_angle = vectorToAngle( vec_right ); + self orientmode( "face angle", generator_angle[ 1 ] ); + wait 0,75; + self action_animscripted( "zm_wallbuy_add", "wallbuy_add_anim" ); + self player_set_buildable_piece( self.oillamp, 1 ); + self maps/mp/zombies/_zm_buildables::player_build( self.buildable_zone ); +/# + sloth_print( "placed lamp" ); +#/ + self.context_done = 1; +} + +powerup_cycle_condition() +{ + while ( level.active_powerups.size > 0 ) + { + _a4262 = level.active_powerups; + _k4262 = getFirstArrayKey( _a4262 ); + while ( isDefined( _k4262 ) ) + { + powerup = _a4262[ _k4262 ]; + ground_pos = groundpos( powerup.origin ); +/# + self sloth_debug_context( powerup, sqrt( 32400 ) ); +#/ + dist = distancesquared( self.origin, ground_pos ); + if ( dist < 32400 ) + { + self.active_powerup = powerup; + self.active_powerup notify( "powerup_reset" ); + self.active_powerup show(); + return 1; + } + _k4262 = getNextArrayKey( _a4262, _k4262 ); + } + } + return 0; +} + +powerup_cycle_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self common_context_action(); +/# + level.zombie_devgui_power = 0; +#/ + if ( isDefined( self.active_powerup ) ) + { + powerup_pos = groundpos( self.active_powerup.origin ); + dest_pos = powerup_pos; + too_close = 0; + dist = distancesquared( self.origin, powerup_pos ); + if ( dist < 2116 ) + { + too_close = 1; +/# + sloth_print( "too close to powerup: " + sqrt( dist ) ); +#/ + vec_forward = vectornormalize( anglesToForward( self.angles ) ); + dest_pos = groundpos( self.active_powerup.origin + ( vec_forward * 100 ) ); + } + self setgoalpos( dest_pos ); + time_started = getTime(); + while ( 1 ) + { + dist = distancesquared( self.origin, powerup_pos ); + if ( too_close ) + { + self orientmode( "face point", powerup_pos ); + if ( dist > 2500 ) + { + self setgoalpos( self.origin ); + if ( is_facing( self.active_powerup ) ) + { + break; + } + } + else if ( ( getTime() - time_started ) > 3000 ) + { +/# + sloth_print( "couldn't get away" ); +#/ + break; + } + else } + else if ( dist < 3136 ) + { + self setgoalpos( self.origin ); + break; + } + else + { + wait 0,1; + } + } + if ( isDefined( self.active_powerup ) ) + { + if ( !too_close ) + { + self sloth_face_object( self.active_powerup, "point", powerup_pos ); + } + } + if ( isDefined( self.active_powerup ) ) + { + self.anchor.origin = self.origin; + self.anchor.angles = flat_angle( vectorToAngle( powerup_pos - self.origin ) ); + self animscripted( self.anchor.origin, self.anchor.angles, "zm_cycle_powerup" ); + maps/mp/animscripts/zm_shared::donotetracks( "cycle_powerup_anim", ::powerup_change ); + } + } + self.context_done = 1; +} + +powerup_change( note ) +{ + if ( note == "change" ) + { + if ( isDefined( self.active_powerup ) ) + { + playfx( level._effect[ "fx_buried_sloth_powerup_cycle" ], self.active_powerup.origin ); + powerup = maps/mp/zombies/_zm_powerups::get_valid_powerup(); + struct = level.zombie_powerups[ powerup ]; + if ( self.active_powerup.powerup_name == struct.powerup_name ) + { + powerup = maps/mp/zombies/_zm_powerups::get_valid_powerup(); + struct = level.zombie_powerups[ powerup ]; + } + self.active_powerup setmodel( struct.model_name ); + self.active_powerup.powerup_name = struct.powerup_name; + self.active_powerup.hint = struct.hint; + self.active_powerup.solo = struct.solo; + self.active_powerup.caution = struct.caution; + self.active_powerup.zombie_grabbable = struct.zombie_grabbable; + self.active_powerup.func_should_drop_with_regular_powerups = struct.func_should_drop_with_regular_powerups; + self.active_powerup thread maps/mp/zombies/_zm_powerups::powerup_timeout(); + if ( isDefined( struct.fx ) ) + { + self.active_powerup.fx = struct.fx; + } + } + } +} + +dance_condition() +{ + if ( isDefined( level.sloth_protect ) ) + { + next_protect = level.sloth_protect + 1; + if ( ( next_protect % 3 ) == 0 ) + { + return 1; + } + } + return 0; +} + +dance_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self common_context_action(); + self setclientfield( "sloth_vomit", 0 ); + self.dance_end = getTime() + 30000; + level.sloth_protect = 0; + while ( 1 ) + { + if ( getTime() >= self.dance_end ) + { + break; + } + else + { + self animscripted( self.origin, self.angles, "zm_dance" ); + maps/mp/animscripts/zm_shared::donotetracks( "dance_anim", ::dance_attack ); + wait 0,1; + } + } + self notify( "stop_dance" ); + self animscripted( self.origin, self.angles, "zm_vomit" ); + maps/mp/animscripts/zm_shared::donotetracks( "vomit_anim", ::vomit_notetrack ); + self.context_done = 1; +} + +dance_attack( note ) +{ + while ( note == "fire" ) + { + zombies = get_round_enemy_array(); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + dist = distancesquared( self.origin, zombie.origin ); + if ( dist < 4096 ) + { + zombie dodamage( zombie.health * 10, zombie.origin ); + zombie playsound( "zmb_ai_sloth_attack_impact" ); + } + i++; + } + } +} + +vomit_notetrack( note ) +{ + if ( note == "vomit" ) + { + self setclientfield( "sloth_vomit", 1 ); + } +} + +sloth_paralyzed( player, upgraded ) +{ + sizzle = "zombie_slowgun_sizzle"; + if ( upgraded ) + { + sizzle = "zombie_slowgun_sizzle_ug"; + } + if ( isDefined( level._effect[ sizzle ] ) ) + { + playfxontag( level._effect[ sizzle ], self, "J_SpineLower" ); + } + self maps/mp/zombies/_zm_weap_slowgun::zombie_slow_for_time( 0,3 ); +} + +is_holding_candybooze( player ) +{ + if ( is_holding( player, "candy" ) || is_holding( player, "booze" ) ) + { + return 1; + } + return 0; +} + +is_holding( player, name ) +{ + if ( should_ignore_candybooze( player ) ) + { + return 0; + } + piece = player player_get_buildable_piece( 1 ); + if ( isDefined( piece ) ) + { + if ( isDefined( piece.buildablename ) && piece.buildablename == name ) + { + return 1; + } + } + return 0; +} + +create_candy_booze_trigger() +{ + if ( !is_buildable_included( "sloth" ) ) + { + return; + } + gift_trigger = maps/mp/zombies/_zm_buildables::ai_buildable_trigger_think( self, "sloth", "sloth", "", 3 ); + gift_trigger bpstub_set_custom_think_callback( ::bptrigger_think_unbuild_no_return ); + gift_trigger.onbeginuse = ::onbeginusecandybooze; + gift_trigger.onenduse = ::onendusecandybooze; + gift_trigger.onuse = ::onuseplantobjectcandybooze; + gift_trigger.oncantuse = ::oncantusecandybooze; + gift_trigger.prompt_and_visibility_func = ::sloth_gift_prompt; + gift_trigger.originfunc = ::sloth_get_unitrigger_origin; + gift_trigger.buildablestruct.building = ""; + gift_trigger.building_prompt = &"ZM_BURIED_GIVING"; + gift_trigger.build_weapon = "no_hands_zm"; + gift_trigger.ignore_open_sesame = 1; + gift_trigger.usetime = int( 750 ); + gift_trigger.radius = 96; + self.gift_trigger = gift_trigger; + gift_trigger thread watch_prompt_reassessment(); + level thread wait_start_candy_booze( gift_trigger.buildablezone.pieces[ 1 ] ); + self waittill( "death" ); + gift_trigger maps/mp/zombies/_zm_buildables::buildablestub_remove(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( gift_trigger ); +} + +wait_start_candy_booze( piece ) +{ + piece piece_unspawn(); + level.jail_barricade_down = 0; + level waittill( "jail_barricade_down" ); + level.jail_barricade_down = 1; + piece piece_spawn_at(); +} + +watch_prompt_reassessment() +{ + self.inactive_reasses_time = 0,2; + self.active_reasses_time = 0,2; + level waittill( "jail_barricade_down" ); + self.inactive_reasses_time = 0,3; + self.active_reasses_time = 0,3; +} + +is_facing( facee, dot_limit ) +{ + if ( !isDefined( dot_limit ) ) + { + dot_limit = 0,7; + } + if ( isplayer( self ) ) + { + orientation = self getplayerangles(); + } + else + { + orientation = self.angles; + } + forwardvec = anglesToForward( orientation ); + forwardvec2d = ( forwardvec[ 0 ], forwardvec[ 1 ], 0 ); + unitforwardvec2d = vectornormalize( forwardvec2d ); + tofaceevec = facee.origin - self.origin; + tofaceevec2d = ( tofaceevec[ 0 ], tofaceevec[ 1 ], 0 ); + unittofaceevec2d = vectornormalize( tofaceevec2d ); + dotproduct = vectordot( unitforwardvec2d, unittofaceevec2d ); + return dotproduct > dot_limit; +} + +sloth_get_unitrigger_origin() +{ + if ( isDefined( self.origin_parent ) ) + { + forward = anglesToForward( self.origin_parent.angles ); + return ( self.origin_parent.origin + vectorScale( ( 0, 1, 0 ), 35 ) ) + ( 32 * forward ); + } + return self.origin; +} + +sloth_gift_prompt( player ) +{ + can_use = 1; + if ( isDefined( self.thread_running ) ) + { + active = self.thread_running; + } + sloth = self.stub.link_parent; + if ( active ) + { + dotlimit = 0,7; + } + else + { + dotlimit = 0,75; + } + if ( !player is_facing( sloth, dotlimit ) || !sloth is_facing( player, dotlimit ) ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + can_use = 0; + } + else + { + if ( active ) + { + can_use = 1; + } + else + { + piece = player player_get_buildable_piece( 1 ); + if ( isDefined( piece ) ) + { + if ( piece.buildablename == "candy" ) + { + level.zombie_buildables[ "sloth" ].hint = &"ZM_BURIED_CANDY_GV"; + } + else + { + level.zombie_buildables[ "sloth" ].hint = &"ZM_BURIED_BOOZE_GV"; + } + } + can_use = self buildabletrigger_update_prompt( player ); + } + } + if ( can_use ) + { + self.reassess_time = self.stub.active_reasses_time; + } + return can_use; +} + +onbeginusecandybooze( player ) +{ + sloth = self.origin_parent; + sloth sloth_set_state( "player_idle", 1 ); +} + +onendusecandybooze( team, player, result ) +{ + sloth = self.origin_parent; + if ( sloth.state != "jail_cower" || result ) + { + sloth unlink(); + } +} + +oncantusecandybooze( player ) +{ +} + +onuseplantobjectcandybooze( player ) +{ + if ( !isDefined( player player_get_buildable_piece( 1 ) ) ) + { + return; + } + self.hint_string = ""; + switch( player player_get_buildable_piece( 1 ).buildablename ) + { + case "booze": + if ( level.sloth.state == "eat" ) + { + return; + } + level.sloth sloth_set_state( "berserk", player ); + break; + case "candy": + if ( level.sloth.state == "berserk" ) + { + return; + } + level.sloth sloth_set_state( "eat", player ); + player notify( "player_gives_sloth_candy" ); + break; + } + self.built = 1; +} + +sloth_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( sweapon == "equip_headchopper_zm" ) + { + self.damageweapon_name = sweapon; + self check_zombie_damage_callbacks( smeansofdeath, shitloc, vpoint, eattacker, idamage ); + self.damageweapon_name = undefined; + } + if ( isDefined( self.sloth_damage_func ) ) + { + damage = self [[ self.sloth_damage_func ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + return damage; + } + if ( smeansofdeath == level.slowgun_damage_mod && sweapon == "slowgun_zm" ) + { + return 0; + } + if ( smeansofdeath == "MOD_MELEE" ) + { + self sloth_leg_pain(); + return 0; + } + if ( self.state == "jail_idle" ) + { + self stop_action(); + self sloth_set_state( "jail_cower" ); + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + return 0; + } + if ( smeansofdeath != "MOD_EXPLOSIVE" && smeansofdeath != "MOD_EXPLOSIVE_SPLASH" && smeansofdeath != "MOD_GRENADE" && smeansofdeath != "MOD_GRENADE_SPLASH" || smeansofdeath == "MOD_PROJECTILE" && smeansofdeath == "MOD_PROJECTILE_SPLASH" ) + { + do_pain = self sloth_pain_react(); + self sloth_set_state( "jail_run", do_pain ); + return 0; + } + if ( !is_true( self.damage_accumulating ) ) + { + self thread sloth_accumulate_damage( idamage ); + } + else + { + self.damage_taken += idamage; + self.num_hits++; + } + return 0; +} + +sloth_pain_react() +{ + if ( self.state != "roam" || self.state == "follow" && self.state == "player_idle" ) + { + if ( !self sloth_is_traversing() ) + { + return 1; + } + } + return 0; +} + +sloth_accumulate_damage( amount ) +{ + self endon( "death" ); + self notify( "stop_accumulation" ); + self endon( "stop_accumulation" ); + self.damage_accumulating = 1; + self.damage_taken = amount; + self.num_hits = 1; + if ( self sloth_pain_react() ) + { + self.is_pain = 1; + prev_anim_state = self getanimstatefromasd(); + if ( self.state == "roam" || self.state == "follow" ) + { + self animmode( "gravity" ); + } + self setanimstatefromasd( "zm_pain" ); + self.reset_asd = "zm_pain"; + maps/mp/animscripts/zm_shared::donotetracks( "pain_anim" ); + if ( self.state == "roam" || self.state == "follow" ) + { + self animmode( "normal" ); + } + self.is_pain = 0; + self.reset_asd = undefined; + self setanimstatefromasd( prev_anim_state ); + } + else + { + wait 1; + } +/# + sloth_print( "num hits: " + self.num_hits ); +#/ + self.damage_accumulating = 0; + if ( self.num_hits >= 3 ) + { + self sloth_set_state( "jail_run", 0 ); + } +} + +sloth_leg_pain() +{ + self.leg_pain_time = getTime() + 4000; +} + +sloth_non_attacker( damage, weapon ) +{ + return 0; +} + +sloth_set_anim_rate( rate ) +{ + if ( isDefined( self.crawler ) ) + { + self.crawler maps/mp/zombies/_zm_weap_slowgun::set_anim_rate( rate ); + } +} + +sloth_reset_anim() +{ + self endon( "death" ); + if ( self.state == "jail_idle" ) + { + self animscripted( self.jail_start.origin, self.jail_start.angles, "zm_jail_idle" ); + maps/mp/animscripts/zm_shared::donotetracks( "jail_idle_anim" ); + } + else if ( isDefined( self.reset_asd ) ) + { + self setanimstatefromasd( self.reset_asd ); + } + else + { + self maps/mp/zombies/_zm_weap_slowgun::reset_anim(); + } +} + +sloth_time_bomb_setup() +{ + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_save( ::time_bomb_global_data_save_sloth ); + maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_restore( ::time_bomb_global_data_restore_sloth ); +} + +time_bomb_global_data_save_sloth() +{ +} + +time_bomb_global_data_restore_sloth() +{ + players = getplayers(); + _a4918 = players; + _k4918 = getFirstArrayKey( _a4918 ); + while ( isDefined( _k4918 ) ) + { + player = _a4918[ _k4918 ]; + if ( player istouching( level.jail_cell_volume ) ) + { + if ( !is_true( level.cell_open ) ) + { + level.sloth.open_jail = 1; + } + } + _k4918 = getNextArrayKey( _a4918, _k4918 ); + } +} + +sndchangebreathingstate( type1, type2 ) +{ + self notify( "sndStateChange" ); + self endon( "sndStateChange" ); + alias = "zmb_ai_sloth_lp_" + type1; + if ( isDefined( type2 ) ) + { + if ( cointoss() ) + { + alias = "zmb_ai_sloth_lp_" + type2; + } + } + self.sndent stoploopsound( 0,75 ); + wait 0,75; + self.sndent playloopsound( alias, 0,75 ); +} + +ignore_stop_func() +{ + if ( is_true( self.is_inert ) ) + { + return 1; + } + return 0; +} + +sloth_debug_axis() +{ +/# + self endon( "death" ); + if ( !isDefined( self.debug_axis ) ) + { + org = self gettagorigin( "tag_weapon_right" ); + ang = self gettagangles( "tag_weapon_right" ); + self.debug_axis = spawn( "script_model", org ); + self.debug_axis.angles = ang; + self.debug_axis setmodel( "fx_axis_createfx" ); + self.debug_axis linkto( self, "tag_weapon_right" ); +#/ + } +} + +sloth_debug_doors() +{ +/# + while ( 1 ) + { + while ( is_true( level.sloth_debug_doors ) ) + { + _a5004 = level.sloth_doors; + _k5004 = getFirstArrayKey( _a5004 ); + while ( isDefined( _k5004 ) ) + { + door = _a5004[ _k5004 ]; + debugstar( door.origin, 100, ( 0, 1, 0 ) ); + circle( door.origin, 120, ( 0, 1, 0 ), 0, 1, 100 ); + _k5004 = getNextArrayKey( _a5004, _k5004 ); + } + } + wait 1; +#/ + } +} + +sloth_debug_buildables() +{ +/# + while ( 1 ) + { + if ( is_true( level.sloth_debug_buildables ) ) + { + if ( !isDefined( self.buildable_model ) ) + { + tag_name = "tag_stowed_back"; + twr_origin = self gettagorigin( tag_name ); + twr_angles = self gettagangles( tag_name ); + self.devgui_buildable = 1; + self.buildable_model = spawn( "script_model", twr_origin ); + self.buildable_model.angles = twr_angles; + self.buildable_model setmodel( level.small_turbine ); + self.buildable_model linkto( self, tag_name ); + } + _a5039 = level.sloth_buildable_zones; + _k5039 = getFirstArrayKey( _a5039 ); + while ( isDefined( _k5039 ) ) + { + zone = _a5039[ _k5039 ]; + debugstar( zone.stub.origin, 100, ( 0, 1, 0 ) ); + _k5039 = getNextArrayKey( _a5039, _k5039 ); + } + } + else if ( is_true( self.devgui_buildable ) ) + { + self.devgui_buildable = 0; + if ( isDefined( self.buildable_model ) ) + { + self.buildable_model unlink(); + self.buildable_model delete(); + } + } + wait 1; +#/ + } +} + +sloth_debug_input() +{ +/# + level.player_candy = 0; + wait 2; + while ( 1 ) + { + while ( !getDvarInt( #"B6252E7C" ) ) + { + wait 0,2; + } + twr_origin = self gettagorigin( "tag_weapon_right" ); + debugstar( twr_origin, 6, ( 0, 1, 0 ) ); + player = get_players()[ 0 ]; + if ( player actionslotonebuttonpressed() ) + { + } + else if ( player actionslottwobuttonpressed() ) + { + } + else if ( player actionslotthreebuttonpressed() ) + { + } + else + { + if ( player actionslotfourbuttonpressed() ) + { + } + } + wait 0,1; +#/ + } +} + +sloth_devgui_teleport() +{ +/# + sloth = level.sloth; + if ( isDefined( sloth ) ) + { + player = gethostplayer(); + 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 ); + if ( sloth.state == "jail_idle" ) + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( sloth.gift_trigger, ::maps/mp/zombies/_zm_buildables::buildable_place_think ); + level.devgui_break = 1; + level.jail_barricade notify( "trigger" ); + } + sloth forceteleport( trace[ "position" ] ); + sloth.got_booze = 1; + level notify( "cell_open" ); + if ( sloth.state != "context" ) + { + sloth stop_action(); + sloth sloth_set_state( "roam" ); +#/ + } + } +} + +sloth_devgui_barricade() +{ +/# + player = gethostplayer(); + 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 ); + pos = trace[ "position" ]; + closest = 0; + triggers = getentarray( "sloth_barricade", "targetname" ); + i = 0; + while ( i < triggers.size ) + { + trigger = triggers[ i ]; + dist = distancesquared( trigger.origin, pos ); + if ( i == 0 ) + { + dist_max = dist; + i++; + continue; + } + else + { + if ( dist < dist_max ) + { + closest = i; + dist_max = dist; + } + } + i++; + } + level.devgui_break = 1; + triggers[ closest ] notify( "trigger" ); +#/ +} + +sloth_devgui_context() +{ +/# + sloth = level.sloth; + if ( isDefined( sloth ) ) + { + sloth.context_debug = 1; + sloth check_contextual_actions(); +#/ + } +} + +sloth_devgui_booze() +{ +/# + sloth = level.sloth; + if ( isDefined( sloth ) ) + { + player = gethostplayer(); + sloth stop_action(); + sloth sloth_set_state( "berserk", player ); +#/ + } +} + +sloth_devgui_candy() +{ +/# + sloth = level.sloth; + if ( isDefined( sloth ) ) + { + player = gethostplayer(); + sloth stop_action(); + sloth sloth_set_state( "eat", player ); +#/ + } +} + +sloth_devgui_warp_to_jail() +{ +/# + player = gethostplayer(); + player setorigin( ( -1142, 557, 28 ) ); + player setplayerangles( vectorScale( ( 0, 1, 0 ), 90 ) ); +#/ +} + +sloth_devgui_move_lamp() +{ +/# + level.oillamp maps/mp/zombies/_zm_buildables::piece_unspawn(); + level.oillamp maps/mp/zombies/_zm_buildables::piece_spawn_at(); +#/ +} + +sloth_devgui_make_crawler() +{ +/# + zombies = get_round_enemy_array(); + _a5231 = zombies; + _k5231 = getFirstArrayKey( _a5231 ); + while ( isDefined( _k5231 ) ) + { + zombie = _a5231[ _k5231 ]; + gib_style = []; + gib_style[ gib_style.size ] = "no_legs"; + gib_style[ gib_style.size ] = "right_leg"; + gib_style[ gib_style.size ] = "left_leg"; + gib_style = array_randomize( gib_style ); + zombie.a.gib_ref = gib_style[ 0 ]; + zombie.has_legs = 0; + zombie allowedstances( "crouch" ); + zombie setphysparams( 15, 0, 24 ); + zombie allowpitchangle( 1 ); + zombie setpitchorient(); + health = zombie.health; + health *= 0,1; + zombie thread maps/mp/animscripts/zm_run::needsdelayedupdate(); + zombie thread maps/mp/animscripts/zm_death::do_gib(); + _k5231 = getNextArrayKey( _a5231, _k5231 ); +#/ + } +} + +sloth_devgui_double_wide() +{ +/# + if ( getDvar( "zombie_double_wide_checks" ) == "1" ) + { + setdvar( "zombie_double_wide_checks", 0 ); + iprintln( "double wide disabled" ); + level.devgui_double_wide = 0; + } + else + { + setdvar( "zombie_double_wide_checks", 1 ); + iprintln( "double wide enabled" ); + level.devgui_double_wide = 1; +#/ + } +} + +sloth_devgui_update_phys_params() +{ +/# + while ( 1 ) + { + devgui_width = getDvarInt( #"2443DFBB" ); + devgui_height = getDvarInt( #"897C9AB4" ); + if ( self.debug_width != devgui_width || self.debug_height != devgui_height ) + { + self.debug_width = devgui_width; + self.debug_height = devgui_height; + self setphysparams( self.debug_width, 0, self.debug_height ); + } + wait 0,2; +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_buildables.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_buildables.gsc new file mode 100644 index 0000000..e8cf64a --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_buildables.gsc @@ -0,0 +1,897 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zm_buried_buildables; +#include maps/mp/zm_buried; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_ai_sloth; +#include maps/mp/zombies/_zm_ai_sloth_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +build_buildable_condition() +{ + while ( level.sloth_buildable_zones.size > 0 ) + { + i = 0; + while ( i < level.sloth_buildable_zones.size ) + { + zone = level.sloth_buildable_zones[ i ]; + if ( is_true( zone.built ) ) + { + remove_zone = zone; + i++; + continue; + } + else piece_remaining = 0; + pieces = zone.pieces; + j = 0; + while ( j < pieces.size ) + { + if ( isDefined( pieces[ j ].unitrigger ) && !is_true( pieces[ j ].built ) ) + { + piece_remaining = 1; + break; + } + else + { + j++; + } + } + if ( !piece_remaining ) + { + i++; + continue; + } + else + { + dist = distancesquared( zone.stub.origin, self.origin ); + if ( dist < 32400 ) + { + self.buildable_zone = zone; + return 1; + } + } + i++; + } + } + if ( isDefined( remove_zone ) ) + { + arrayremovevalue( level.sloth_buildable_zones, remove_zone ); + } + return 0; +} + +common_move_to_table( stub, table, asd_name, check_pickup ) +{ + if ( !isDefined( table ) ) + { +/# + assertmsg( "Table not found for " + self.buildable_zone.buildable_name ); +#/ + self.context_done = 1; + return 0; + } + anim_id = self getanimfromasd( asd_name, 0 ); + start_org = getstartorigin( table.origin, table.angles, anim_id ); + start_ang = getstartangles( table.origin, table.angles, anim_id ); + self setgoalpos( start_org ); + while ( 1 ) + { + if ( is_true( check_pickup ) ) + { + if ( self.candy_player is_player_equipment( stub.weaponname ) ) + { +/# + sloth_print( stub.weaponname + " was picked up" ); +#/ + self.context_done = 1; + return 0; + } + } + if ( isDefined( self.buildable_zone ) && stub != self.buildable_zone.stub ) + { +/# + sloth_print( "location change during pathing" ); +#/ + stub = self.buildable_zone.stub; + table = getent( stub.model.target, "targetname" ); + if ( !isDefined( table ) ) + { +/# + assertmsg( "Table not found for " + self.buildable_zone.buildable_name ); +#/ + self.context_done = 1; + return 0; + } + start_org = getstartorigin( table.origin, table.angles, anim_id ); + start_ang = getstartangles( table.origin, table.angles, anim_id ); + self setgoalpos( start_org ); + } + dist = distancesquared( self.origin, start_org ); + if ( dist < 1024 ) + { + break; + } + else + { + wait 0,1; + } + } + self setgoalpos( self.origin ); + self sloth_face_object( table, "angle", start_ang[ 1 ], 0,9 ); + return 1; +} + +build_buildable_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); + stub = self.buildable_zone.stub; + table = getent( stub.model.target, "targetname" ); + if ( !self common_move_to_table( stub, table, "zm_make_buildable_intro" ) ) + { + return; + } + self maps/mp/zombies/_zm_ai_sloth::action_animscripted( "zm_make_buildable_intro", "make_buildable_intro_anim", table.origin, table.angles ); +/# + sloth_print( "looking for " + self.buildable_zone.buildable_name + " pieces" ); +#/ + store = getstruct( "sloth_general_store", "targetname" ); + self setgoalpos( store.origin ); + self waittill( "goal" ); + self.pieces = []; + while ( isDefined( self.buildable_zone ) ) + { + pieces = self.buildable_zone.pieces; + if ( pieces.size == 0 ) + { +/# + sloth_print( "no pieces available" ); +#/ + self.context_done = 1; + return; + } + i = 0; + while ( i < pieces.size ) + { + if ( isDefined( pieces[ i ].unitrigger ) && !is_true( pieces[ i ].built ) ) + { +/# + if ( getDvarInt( #"B6252E7C" ) == 2 ) + { + line( self.origin, pieces[ i ].start_origin, ( 1, 1, 1 ), 1, 0, 1000 ); +#/ + } + self maps/mp/zombies/_zm_buildables::player_take_piece( pieces[ i ] ); + self.pieces[ self.pieces.size ] = pieces[ i ]; + } + i++; + } + } + self animscripted( self.origin, self.angles, "zm_pickup_part" ); + maps/mp/animscripts/zm_shared::donotetracks( "pickup_part_anim" ); +/# + sloth_print( "took " + self.pieces.size + " pieces" ); +#/ + if ( !self common_move_to_table( stub, table, "zm_make_buildable" ) ) + { + return; + } + self.buildable_zone.stub.bound_to_buildable = self.buildable_zone.stub; + if ( stub != self.buildable_zone.stub ) + { + stub = self.buildable_zone.stub; + table = getent( stub.model.target, "targetname" ); + } + self thread build_buildable_fx( table ); + self animscripted( table.origin, table.angles, "zm_make_buildable" ); + wait 2,5; + self notify( "stop_buildable_fx" ); + self maps/mp/zombies/_zm_buildables::player_build( self.buildable_zone, self.pieces ); + if ( isDefined( self.buildable_zone.stub.onuse ) ) + { + self.buildable_zone.stub [[ self.buildable_zone.stub.onuse ]]( self ); + } + self.pieces = undefined; + self.context_done = 1; +} + +build_buildable_fx( table ) +{ + self endon( "death" ); + self notify( "stop_buildable_fx" ); + self endon( "stop_buildable_fx" ); + while ( 1 ) + { + playfx( level._effect[ "fx_buried_sloth_building" ], table.origin ); + wait 0,25; + } +} + +build_buildable_interrupt() +{ + while ( isDefined( self.pieces ) && self.pieces.size > 0 ) + { + _a238 = self.pieces; + _k238 = getFirstArrayKey( _a238 ); + while ( isDefined( _k238 ) ) + { + piece = _a238[ _k238 ]; + piece maps/mp/zombies/_zm_buildables::piece_spawn_at(); + _k238 = getNextArrayKey( _a238, _k238 ); + } + } +} + +fetch_buildable_condition() +{ + self.turbine = undefined; + turbines = []; + equipment = maps/mp/zombies/_zm_equipment::get_destructible_equipment_list(); + _a254 = equipment; + _k254 = getFirstArrayKey( _a254 ); + while ( isDefined( _k254 ) ) + { + item = _a254[ _k254 ]; + if ( !isDefined( item.equipname ) ) + { + } + else + { + if ( item.equipname == "equip_turbine_zm" ) + { +/# + self sloth_debug_context( item, sqrt( 32400 ) ); +#/ + dist = distancesquared( item.origin, self.origin ); + if ( dist < 32400 ) + { + self.power_stubs = get_power_stubs( self.candy_player ); + if ( self.power_stubs.size > 0 ) + { + self.turbine = item; + return 1; + } + else + { + localpower = item.owner.localpower; + if ( check_localpower_list( localpower.added_list ) || check_localpower_list( localpower.enabled_list ) ) + { + self.turbine = item; + return 1; + } + } + } + turbines[ turbines.size ] = item; + } + } + _k254 = getNextArrayKey( _a254, _k254 ); + } + _a290 = equipment; + _k290 = getFirstArrayKey( _a290 ); + while ( isDefined( _k290 ) ) + { + item = _a290[ _k290 ]; + if ( !isDefined( item.equipname ) ) + { + } + else + { + while ( item.equipname != "equip_turret_zm" || item.equipname == "equip_electrictrap_zm" && item.equipname == "equip_subwoofer_zm" ) + { +/# + self sloth_debug_context( item, sqrt( 32400 ) ); +#/ + dist = distancesquared( item.origin, self.origin ); + while ( dist < 32400 ) + { + while ( is_true( item.power_on ) ) + { + _a307 = turbines; + _k307 = getFirstArrayKey( _a307 ); + while ( isDefined( _k307 ) ) + { + turbine = _a307[ _k307 ]; + if ( is_turbine_powering_item( turbine, item ) ) + { + self.turbine = turbine; + return 1; + } + _k307 = getNextArrayKey( _a307, _k307 ); + } + } + } + } + } + _k290 = getNextArrayKey( _a290, _k290 ); + } + _a320 = equipment; + _k320 = getFirstArrayKey( _a320 ); + while ( isDefined( _k320 ) ) + { + item = _a320[ _k320 ]; + if ( !isDefined( item.equipname ) ) + { + } + else if ( item.equipname != "equip_turret_zm" || item.equipname == "equip_electrictrap_zm" && item.equipname == "equip_subwoofer_zm" ) + { +/# + self sloth_debug_context( item, sqrt( 32400 ) ); +#/ + dist = distancesquared( item.origin, self.origin ); + if ( dist < 32400 ) + { + if ( is_true( level.turbine_zone.built ) ) + { + self.power_item = item; + return 1; + } + else + { +/# + sloth_print( "turbine not built" ); +#/ + } + } + } + _k320 = getNextArrayKey( _a320, _k320 ); + } + return 0; +} + +is_turbine_powering_item( turbine, item ) +{ + localpower = turbine.owner.localpower; + while ( isDefined( localpower.added_list ) ) + { + _a358 = localpower.added_list; + _k358 = getFirstArrayKey( _a358 ); + while ( isDefined( _k358 ) ) + { + added = _a358[ _k358 ]; + if ( added == item ) + { + return 1; + } + _k358 = getNextArrayKey( _a358, _k358 ); + } + } + while ( isDefined( localpower.enabled_list ) ) + { + _a368 = localpower.enabled_list; + _k368 = getFirstArrayKey( _a368 ); + while ( isDefined( _k368 ) ) + { + enabled = _a368[ _k368 ]; + if ( enabled == item ) + { + return 1; + } + _k368 = getNextArrayKey( _a368, _k368 ); + } + } + return 0; +} + +get_power_stubs( player ) +{ + power_stubs = []; + _a382 = level.power_zones; + _k382 = getFirstArrayKey( _a382 ); + while ( isDefined( _k382 ) ) + { + zone = _a382[ _k382 ]; + if ( is_true( zone.built ) ) + { + if ( !player has_player_equipment( zone.stub.weaponname ) ) + { + power_stubs[ power_stubs.size ] = zone.stub; + } + } + _k382 = getNextArrayKey( _a382, _k382 ); + } + return power_stubs; +} + +fetch_buildable_start() +{ +/# + sloth_print( self.context.name ); +#/ + self.context_done = 0; + self.pi_origin = undefined; + if ( isDefined( self.turbine ) ) + { + localpower = self.turbine.owner.localpower; + if ( check_localpower_list( localpower.added_list ) || check_localpower_list( localpower.enabled_list ) ) + { +/# + sloth_print( "has powered item, go get turbine" ); +#/ + self thread fetch_buildable_action( "turbine" ); + return; + } +/# + sloth_print( "find a power item" ); +#/ + self thread fetch_buildable_action( "power_item" ); + } + else + { + if ( isDefined( self.power_item ) ) + { +/# + sloth_print( "power item needs turbine" ); +#/ + self.pi_origin = self.power_item.origin; + self thread fetch_buildable_action( "turbine" ); + } + } +} + +check_localpower_list( list ) +{ + while ( isDefined( list ) ) + { + _a436 = list; + _k436 = getFirstArrayKey( _a436 ); + while ( isDefined( _k436 ) ) + { + item = _a436[ _k436 ]; + item_name = item.target.name; + if ( !isDefined( item_name ) ) + { + } + else + { + if ( item_name != "equip_turret_zm" || item_name == "equip_electrictrap_zm" && item_name == "equip_subwoofer_zm" ) + { + return 1; + } + } + _k436 = getNextArrayKey( _a436, _k436 ); + } + } + return 0; +} + +fetch_buildable_action( item ) +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); + player = self.candy_player; + if ( item == "turbine" ) + { + if ( isDefined( self.turbine ) ) + { + plant_origin = self.turbine.origin; + plant_angles = self.turbine.angles; + } + stub = level.turbine_zone.stub; + } + else + { + if ( item == "power_item" ) + { + self.power_stubs = array_randomize( self.power_stubs ); + stub = self.power_stubs[ 0 ]; + } + } + append_name = "equipment"; + pickup_asd = "zm_pickup_" + append_name; + table = getent( stub.model.target, "targetname" ); + if ( !self common_move_to_table( stub, table, pickup_asd, 1 ) ) + { + return; + } + self.buildable_item = item; + self animscripted( table.origin, table.angles, pickup_asd ); + maps/mp/animscripts/zm_shared::donotetracks( "pickup_equipment_anim", ::pickup_notetracks, stub ); + if ( player is_player_equipment( stub.weaponname ) ) + { +/# + sloth_print( "during anim player picked up " + stub.weaponname ); +#/ + self.context_done = 1; + return; + } + if ( !player has_deployed_equipment( stub.weaponname ) ) + { + player.deployed_equipment[ player.deployed_equipment.size ] = stub.weaponname; + } +/# + sloth_print( "got " + stub.equipname ); +#/ + if ( isDefined( self.turbine ) ) + { + ground_pos = self.turbine.origin; + } + else if ( isDefined( self.power_item ) ) + { + ground_pos = self.power_item.origin; + } + else + { + ground_pos = self.pi_origin; + } + run_asd = "run_holding_" + append_name; + self.ignore_common_run = 1; + self set_zombie_run_cycle( run_asd ); + self.locomotion = run_asd; + self setgoalpos( ground_pos ); + range = 10000; + if ( item == "power_item" || isDefined( self.power_item ) ) + { + range = 25600; + } + while ( 1 ) + { + while ( self sloth_is_traversing() ) + { + wait 0,1; + } + dist = distancesquared( self.origin, ground_pos ); + if ( dist < range ) + { + break; + } + else + { + wait 0,1; + } + } + if ( item == "turbine" ) + { + if ( isDefined( self.turbine ) ) + { + self orientmode( "face point", self.turbine.origin ); + self animscripted( self.origin, flat_angle( vectorToAngle( self.turbine.origin - self.origin ) ), "zm_kick_equipment" ); + maps/mp/animscripts/zm_shared::donotetracks( "kick_equipment_anim", ::destroy_item, self.turbine ); + self orientmode( "face default" ); + self animscripted( self.origin, self.angles, "zm_idle_equipment" ); + wait 3; + } + } + if ( !isDefined( plant_origin ) ) + { + plant_origin = self.origin; + plant_angles = self.angles; + } + drop_asd = "zm_drop_" + append_name; + self maps/mp/zombies/_zm_ai_sloth::action_animscripted( drop_asd, "drop_equipment_anim" ); + if ( player has_player_equipment( stub.weaponname ) ) + { + player equipment_take( stub.weaponname ); + } + player player_set_equipment_damage( stub.weaponname, 0 ); + if ( !player has_deployed_equipment( stub.weaponname ) ) + { + player.deployed_equipment[ player.deployed_equipment.size ] = stub.weaponname; + } + if ( isDefined( self.buildable_model ) ) + { + self.buildable_model unlink(); + self.buildable_model delete(); + } + equipment = stub.weaponname; + plant_origin = self gettagorigin( "tag_weapon_right" ); + plant_angles = self gettagangles( "tag_weapon_right" ); + replacement = player [[ level.zombie_equipment[ equipment ].place_fn ]]( plant_origin, plant_angles ); + if ( isDefined( replacement ) ) + { + replacement.owner = player; + replacement.original_owner = player; + replacement.name = equipment; + player notify( "equipment_placed" ); + if ( isDefined( level.equipment_planted ) ) + { + player [[ level.equipment_planted ]]( replacement, equipment, self ); + } + } + self.context_done = 1; +} + +pickup_notetracks( note, stub ) +{ + if ( note == "pickup" ) + { + tag_name = "tag_stowed_back"; + twr_origin = self gettagorigin( tag_name ); + twr_angles = self gettagangles( tag_name ); + self.buildable_model = spawn( "script_model", twr_origin ); + self.buildable_model.angles = twr_angles; + if ( self.buildable_item == "turbine" ) + { + self.buildable_model setmodel( level.small_turbine ); + } + else + { + self.buildable_model setmodel( stub.model.model ); + } + self.buildable_model linkto( self, tag_name ); + } +} + +destroy_item( note, item ) +{ + if ( note == "kick" ) + { + if ( isDefined( item ) ) + { + if ( isDefined( item.owner ) ) + { + item.owner thread maps/mp/zombies/_zm_equipment::player_damage_equipment( item.equipname, 1001, item.origin ); + return; + } + else + { + item thread maps/mp/zombies/_zm_equipment::dropped_equipment_destroy( 1 ); + } + } + } +} + +fetch_buildable_interrupt() +{ + if ( isDefined( self.buildable_model ) ) + { + self.buildable_model unlink(); + self.buildable_model delete(); + } +} + +wallbuy_condition() +{ + if ( !wallbuy_get_stub_array().size ) + { + return 0; + } + if ( !wallbuy_get_piece_array().size ) + { + return 0; + } + if ( isDefined( level.gunshop_zone ) ) + { + if ( self istouching( level.gunshop_zone ) ) + { +/# + sloth_print( "using new gunshop zone" ); +#/ + return 1; + } + } + else + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_gun_store" ) ) + { + return 1; + } + } + return 0; +} + +wallbuy_get_stub_array() +{ + stubs = []; + i = 0; + while ( i < level.sloth_wallbuy_stubs.size ) + { + stub = level.sloth_wallbuy_stubs[ i ]; + if ( !isDefined( stub.in_zone ) ) + { +/# + iprintln( "WALLBUY NOT IN VALID ZONE" ); +#/ + i++; + continue; + } + else if ( !level.zones[ stub.in_zone ].is_enabled ) + { + i++; + continue; + } + else if ( is_true( stub.built ) ) + { + remove_stub = stub; + i++; + continue; + } + else if ( stub.in_zone == "zone_general_store" ) + { + if ( !is_general_store_open() ) + { + i++; + continue; + } + } + else if ( stub.in_zone == "zone_underground_courthouse2" ) + { + if ( !maps/mp/zm_buried::is_courthouse_open() ) + { + i++; + continue; + } + } + else if ( stub.in_zone == "zone_tunnels_center" ) + { + if ( !maps/mp/zm_buried::is_tunnel_open() ) + { + i++; + continue; + } + } + else + { + stubs[ stubs.size ] = stub; + } + i++; + } + if ( isDefined( remove_stub ) ) + { + arrayremovevalue( level.sloth_wallbuy_stubs, remove_stub ); + } + return stubs; +} + +wallbuy_get_piece_array() +{ + pieces = []; + i = 0; + while ( i < level.chalk_pieces.size ) + { + piece = level.chalk_pieces[ i ]; + if ( isDefined( piece.unitrigger ) && !is_true( piece.built ) ) + { + pieces[ pieces.size ] = piece; + } + i++; + } + return pieces; +} + +wallbuy_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); + wallbuy_struct = getstruct( "sloth_allign_gunshop", "targetname" ); + asd_name = "zm_wallbuy_remove"; + anim_id = self getanimfromasd( asd_name, 0 ); + start_org = getstartorigin( wallbuy_struct.origin, wallbuy_struct.angles, anim_id ); + start_ang = getstartangles( wallbuy_struct.origin, wallbuy_struct.angles, anim_id ); + self setgoalpos( start_org ); + self waittill( "goal" ); + self setgoalpos( self.origin ); + self sloth_face_object( undefined, "angle", start_ang[ 1 ], 0,9 ); + self animscripted( wallbuy_struct.origin, wallbuy_struct.angles, asd_name ); + maps/mp/animscripts/zm_shared::donotetracks( "wallbuy_remove_anim", ::wallbuy_grab_pieces ); + if ( !self.wallbuy_stubs.size || !self.wallbuy_pieces.size ) + { + self.context_done = 1; + return; + } + i = 0; + while ( i < self.pieces_needed ) + { + stub = self.wallbuy_stubs[ i ]; + vec_right = vectornormalize( anglesToRight( stub.angles ) ); + org = stub.origin - ( vec_right * 60 ); + org = groundpos( org ); + self setgoalpos( org ); + skip_piece = 0; + while ( 1 ) + { + if ( is_true( stub.built ) ) + { +/# + sloth_print( "stub was built during pathing" ); +#/ + skip_piece = 1; + break; + } + else dist = distancesquared( self.origin, org ); + if ( dist < 576 ) + { + break; + } + else + { + wait 0,1; + } + } + if ( !skip_piece ) + { + self setgoalpos( self.origin ); + chalk_angle = vectorToAngle( vec_right ); + self sloth_face_object( stub, "angle", chalk_angle[ 1 ], 0,9 ); + if ( is_true( stub.built ) ) + { +/# + sloth_print( "stub was built during facing" ); +#/ + skip_piece = 1; + } + } + self player_set_buildable_piece( self.wallbuy_pieces[ i ], 1 ); + current_piece = self player_get_buildable_piece( 1 ); + if ( skip_piece ) + { + arrayremovevalue( self.wallbuy_pieces_taken, current_piece ); + current_piece maps/mp/zm_buried_buildables::ondrop_chalk( self ); + self orientmode( "face default" ); + i++; + continue; + } + else + { + self thread player_draw_chalk( stub ); + self maps/mp/zombies/_zm_ai_sloth::action_animscripted( "zm_wallbuy_add", "wallbuy_add_anim", org, chalk_angle ); + self notify( "end_chalk_dust" ); + playsoundatposition( "zmb_cha_ching_loud", stub.origin ); + if ( is_true( stub.built ) ) + { + current_piece maps/mp/zm_buried_buildables::ondrop_chalk( self ); +/# + sloth_print( "stub was built during anim" ); +#/ + } + else + { + stub maps/mp/zm_buried_buildables::onuseplantobject_chalk( self ); + stub buildablestub_finish_build( self ); + stub buildablestub_remove(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( stub ); +/# + sloth_print( "built " + self player_get_buildable_piece( 1 ).script_noteworthy ); +#/ + } + arrayremovevalue( self.wallbuy_pieces_taken, self player_get_buildable_piece( 1 ) ); + self orientmode( "face default" ); + } + i++; + } + self.context_done = 1; +} + +wallbuy_grab_pieces( note ) +{ + while ( note == "pulled" ) + { + self.wallbuy_stubs = wallbuy_get_stub_array(); + self.wallbuy_pieces = wallbuy_get_piece_array(); + self.pieces_needed = self.wallbuy_stubs.size; + if ( self.pieces_needed > self.wallbuy_pieces.size ) + { + self.pieces_needed = self.wallbuy_pieces.size; + } + self.wallbuy_pieces = array_randomize( self.wallbuy_pieces ); + self.wallbuy_pieces_taken = []; + i = 0; + while ( i < self.pieces_needed ) + { + self.wallbuy_pieces_taken[ i ] = self.wallbuy_pieces[ i ]; + self.wallbuy_pieces[ i ] maps/mp/zombies/_zm_buildables::piece_unspawn(); + i++; + } + } +} + +wallbuy_interrupt() +{ + while ( isDefined( self.wallbuy_pieces_taken ) && self.wallbuy_pieces_taken.size > 0 ) + { + _a920 = self.wallbuy_pieces_taken; + _k920 = getFirstArrayKey( _a920 ); + while ( isDefined( _k920 ) ) + { + wallbuy = _a920[ _k920 ]; + wallbuy maps/mp/zm_buried_buildables::ondrop_chalk( self ); + _k920 = getNextArrayKey( _a920, _k920 ); + } + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_crawler.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_crawler.gsc new file mode 100644 index 0000000..8deada8 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_crawler.gsc @@ -0,0 +1,434 @@ +#include maps/mp/animscripts/zm_shared; +#include maps/mp/animscripts/zm_run; +#include maps/mp/zombies/_zm_ai_sloth; +#include maps/mp/zombies/_zm_ai_sloth_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +crawler_condition() +{ + zombies = get_round_enemy_array(); + i = 0; + while ( i < zombies.size ) + { + zombie = zombies[ i ]; + if ( !is_true( zombie.has_legs ) ) + { + dist = distancesquared( self.origin, zombie.origin ); + if ( dist < 32400 ) + { + self.crawler = zombie; + if ( isDefined( level.sloth.custom_crawler_pickup_func ) ) + { + self.crawler thread [[ level.sloth.custom_crawler_pickup_func ]](); + } + return 1; + } + } + i++; + } + return 0; +} + +crawler_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); + self thread watch_sloth_on_exit_side(); + self thread watch_sloth_on_same_side(); + self thread crawler_watch_death(); + self.release_crawler = 0; + anim_id = self getanimfromasd( "zm_sloth_pickup_crawler", 0 ); + sloth_goal = getstartorigin( self.crawler.origin, self.crawler.angles, anim_id ); + sloth_offset = distance( sloth_goal, self.crawler.origin ); + while ( 1 ) + { + while ( self sloth_is_traversing() ) + { + wait 0,1; + } + vec_forward = vectornormalize( anglesToForward( self.crawler.angles ) ); + start_pos = self.crawler.origin - ( vec_forward * sloth_offset ); + raised_start_pos = ( start_pos[ 0 ], start_pos[ 1 ], start_pos[ 2 ] + sloth_offset ); + ground_pos = groundpos( raised_start_pos ); + height_check = abs( self.crawler.origin[ 2 ] - ground_pos[ 2 ] ); + if ( height_check > 8 ) + { + self setanimstatefromasd( "zm_player_idle" ); + } + else + { + self maps/mp/animscripts/zm_run::needsupdate(); + self setgoalpos( start_pos ); + } + if ( !isDefined( self.crawler ) || self.crawler.health <= 0 ) + { + self.context_done = 1; + return; + } + dist = distancesquared( self.origin, start_pos ); + z_dist = abs( self.origin[ 2 ] - start_pos[ 2 ] ); + if ( dist < 1024 && z_dist < 12 ) + { + break; + } + else + { + wait 0,1; + } + } + self orientmode( "face angle", self.crawler.angles[ 1 ] ); + wait 0,25; + self.crawler.is_inert = 1; + self.crawler.ignoreall = 1; + self.crawler notify( "stop_find_flesh" ); + self.crawler notify( "zombie_acquire_enemy" ); + self.anchor.origin = self.crawler.origin; + self.anchor.angles = self.crawler.angles; + sloth_pickup = self append_hunched( "zm_sloth_pickup_crawler" ); + crawler_pickup = self append_hunched( "zm_crawler_pickup_by_sloth" ); + self animscripted( self.anchor.origin, self.anchor.angles, sloth_pickup ); + self.crawler animscripted( self.anchor.origin, self.anchor.angles, crawler_pickup ); + maps/mp/animscripts/zm_shared::donotetracks( "sloth_pickup_crawler_anim" ); + self.carrying_crawler = 1; + self.crawler.guts_explosion = 1; + self.pre_traverse = ::crawler_pre_traverse; + self.post_traverse = ::crawler_post_traverse; + self.crawler notsolid(); + self.crawler linkto( self, "tag_weapon_right" ); + self.ignore_common_run = 1; + self set_zombie_run_cycle( "walk_crawlerhold" ); + self.locomotion = "walk_crawlerhold"; + self.setanimstatefromspeed = ::slothanimstatefromspeed; + self.crawler_end = getTime() + 5000; + self.crawler.actor_damage_func = ::crawler_damage_func; + self.sloth_damage_func = ::crawler_damage_func; + roam = array_randomize( level.roam_points ); + roam_index = 0; + while ( 1 ) + { + if ( is_true( self.release_crawler ) ) + { + break; + } + else + { + while ( self sloth_is_traversing() ) + { + wait 0,1; + } + dist = distancesquared( self.origin, self.candy_player.origin ); + if ( dist < 25600 || is_true( self.candy_player.is_in_ghost_zone ) && is_true( self.on_exit_side ) ) + { + self.check_turn = 1; + self setgoalpos( self.origin ); + sloth_idle = self append_hunched( "zm_sloth_crawlerhold_idle" ); + crawler_idle = self append_hunched( "zm_crawler_crawlerhold_idle" ); + self animscripted( self.origin, self.angles, sloth_idle ); + self.crawler animscripted( self.origin, self.angles, crawler_idle ); + } + else + { + self stopanimscripted(); + self.crawler stopanimscripted(); + if ( should_ignore_candybooze( self.candy_player ) ) + { + dist = distancesquared( self.origin, roam[ roam_index ].origin ); + if ( dist < 1024 ) + { + roam_index++; + if ( roam_index >= roam.size ) + { + roam_index = 0; + } + } + self maps/mp/zombies/_zm_ai_sloth::sloth_check_turn( roam[ roam_index ].origin ); + self setgoalpos( roam[ roam_index ].origin ); + } + else + { + if ( !self sloth_move_to_same_side() ) + { + if ( is_true( self.check_turn ) ) + { + self.check_turn = 0; + if ( self sloth_is_same_zone( self.candy_player ) ) + { + self maps/mp/zombies/_zm_ai_sloth::sloth_check_turn( self.candy_player.origin, -0,965 ); + } + } + self setgoalpos( self.candy_player.origin ); + } + } + self crawler_update_locomotion(); + } + wait 0,1; + } + } + self.setanimstatefromspeed = undefined; + self.crawler unlink(); + sloth_putdown = self append_hunched( "zm_sloth_putdown_crawler" ); + crawler_putdown = self append_hunched( "zm_crawler_putdown_by_sloth" ); + self animscripted( self.origin, self.angles, sloth_putdown ); + self.crawler animscripted( self.origin, self.angles, crawler_putdown ); + maps/mp/animscripts/zm_shared::donotetracks( "sloth_putdown_crawler_anim" ); + self.carrying_crawler = 0; + self.crawler.deathfunction = ::crawler_death; + sloth_kill = self append_hunched( "zm_sloth_kill_crawler_stomp" ); + crawler_kill = self append_hunched( "zm_crawler_slothkill_stomp" ); + self notify( "stop_crawler_watch" ); + self animscripted( self.origin, self.angles, sloth_kill ); + self.crawler animscripted( self.origin, self.angles, crawler_kill ); + maps/mp/animscripts/zm_shared::donotetracks( "sloth_kill_crawler_anim" ); + if ( isDefined( self.crawler ) ) + { + self.crawler dodamage( self.crawler.health * 10, self.crawler.origin ); + self.crawler playsound( "zmb_ai_sloth_attack_impact" ); + } + self.sloth_damage_func = undefined; + self maps/mp/zombies/_zm_ai_sloth::sloth_set_traverse_funcs(); + self.crawler = undefined; + self.context_done = 1; +} + +watch_sloth_on_exit_side() +{ + self endon( "death" ); + while ( 1 ) + { + if ( is_true( self.context_done ) ) + { + return; + } + self.on_exit_side = 0; + player = self.candy_player; + if ( isDefined( player ) && is_true( player.is_in_ghost_zone ) ) + { + name = player.current_ghost_room_name; + if ( isDefined( name ) ) + { + room = level.ghost_rooms[ name ]; + if ( is_true( room.to_maze ) ) + { + if ( self maps/mp/zombies/_zm_ai_sloth::sloth_behind_mansion() ) + { + self.on_exit_side = 1; + } + break; + } + else + { + if ( is_true( room.from_maze ) ) + { + if ( !self maps/mp/zombies/_zm_ai_sloth::sloth_behind_mansion() ) + { + self.on_exit_side = 1; + } + } + } + } + } + wait 0,25; + } +} + +watch_sloth_on_same_side() +{ + self endon( "death" ); + while ( 1 ) + { + if ( is_true( self.context_done ) ) + { + return; + } + self.on_same_side = 0; + player = self.candy_player; + if ( isDefined( player ) ) + { + if ( self maps/mp/zombies/_zm_ai_sloth::sloth_behind_mansion() ) + { + if ( player maps/mp/zombies/_zm_ai_sloth::behind_mansion_zone() ) + { + self.on_same_side = 1; + } + break; + } + else + { + if ( !player maps/mp/zombies/_zm_ai_sloth::behind_mansion_zone() ) + { + self.on_same_side = 1; + } + } + } + wait 0,25; + } +} + +sloth_move_to_same_side() +{ + self endon( "death" ); + if ( isDefined( self.teleport_time ) ) + { + if ( ( getTime() - self.teleport_time ) < 1000 ) + { + return 0; + } + } + player = self.candy_player; + if ( is_true( player.is_in_ghost_zone ) ) + { + if ( is_true( self.on_exit_side ) ) + { + return 0; + } + } + else + { + if ( is_true( self.on_same_side ) ) + { + return 0; + } + } + if ( self maps/mp/zombies/_zm_ai_sloth::sloth_behind_mansion() ) + { + self maps/mp/zombies/_zm_ai_sloth::action_navigate_mansion( level.courtyard_depart, level.courtyard_arrive ); + } + else + { + self maps/mp/zombies/_zm_ai_sloth::action_navigate_mansion( level.maze_depart, level.maze_arrive ); + } + return 1; +} + +sloth_is_same_zone( player ) +{ + zone_sloth = self get_current_zone(); + zone_player = player get_current_zone(); + if ( !isDefined( zone_sloth ) || !isDefined( zone_player ) ) + { + return 0; + } + if ( zone_sloth == zone_player ) + { + return 1; + } + return 0; +} + +append_hunched( asd_name ) +{ + if ( self.is_inside ) + { + return asd_name + "_hunched"; + } + return asd_name; +} + +crawler_update_locomotion() +{ + if ( self.zombie_move_speed == "walk_crawlerhold" ) + { + if ( self.is_inside ) + { + self set_zombie_run_cycle( "walk_crawlerhold_hunched" ); + self.locomotion = "walk_crawlerhold_hunched"; + } + } + else + { + if ( self.zombie_move_speed == "walk_crawlerhold_hunched" ) + { + if ( !self.is_inside ) + { + self set_zombie_run_cycle( "walk_crawlerhold" ); + self.locomotion = "walk_crawlerhold"; + } + } + } +} + +crawler_watch_death() +{ + self endon( "stop_crawler_watch" ); + self.crawler waittill( "death" ); + self stop_action(); +/# + sloth_print( "crawler died" ); +#/ + if ( isDefined( self.crawler ) ) + { + self.crawler unlink(); + } + self.setanimstatefromspeed = undefined; + self.sloth_damage_func = undefined; + self maps/mp/zombies/_zm_ai_sloth::sloth_set_traverse_funcs(); + self.crawler = undefined; + self.context_done = 1; +} + +crawler_pre_traverse() +{ + sloth_sling = self append_hunched( "zm_sloth_crawlerhold_sling" ); + crawler_sling = self append_hunched( "zm_crawler_sloth_crawlerhold_sling" ); + self setanimstatefromasd( sloth_sling ); + self.crawler setanimstatefromasd( crawler_sling ); + self maps/mp/animscripts/zm_shared::donotetracks( "sloth_crawlerhold_sling_anim" ); + self.crawler thread crawler_traverse_idle(); +} + +crawler_traverse_idle() +{ + self endon( "death" ); + self endon( "stop_traverse_idle" ); + while ( 1 ) + { + self setanimstatefromasd( "zm_crawler_sloth_crawlerhold_slung_idle" ); + wait 0,1; + } +} + +crawler_post_traverse() +{ + self.crawler notify( "stop_traverse_idle" ); + sloth_unsling = self append_hunched( "zm_sloth_crawlerhold_unsling" ); + crawler_unsling = self append_hunched( "zm_crawler_sloth_crawlerhold_unsling" ); + self setanimstatefromasd( sloth_unsling ); + self.crawler setanimstatefromasd( crawler_unsling ); + self maps/mp/animscripts/zm_shared::donotetracks( "sloth_crawlerhold_unsling_anim" ); +} + +crawler_death() +{ + return 1; +} + +crawler_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + level.sloth.release_crawler = 1; + return 0; +} + +is_crawler_alive() +{ + if ( isDefined( self.crawler ) && self.crawler.health > 0 ) + { + return 1; + } + return 0; +} + +slothanimstatefromspeed( animstate, substate ) +{ + if ( isDefined( self.crawler ) ) + { + crawler_walk = "zm_crawler_crawlerhold_walk"; + if ( self.is_inside ) + { + crawler_walk += "_hunched"; + } + self.crawler setanimstatefromasd( crawler_walk ); + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_ffotd.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_ffotd.gsc new file mode 100644 index 0000000..b005c2a --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_ffotd.gsc @@ -0,0 +1,14 @@ +#include maps/mp/zombies/_zm_ai_sloth_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +sloth_ffotd_init() +{ + level.double_wide_override = undefined; + level.interior_override = undefined; +} + +sloth_ffotd_prespawn() +{ +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_magicbox.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_magicbox.gsc new file mode 100644 index 0000000..05944c9 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_magicbox.gsc @@ -0,0 +1,519 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_hackables_box; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zm_buried; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zombies/_zm_ai_sloth; +#include maps/mp/zombies/_zm_ai_sloth_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +box_lock_condition() +{ + box = level.chests[ level.chest_index ]; + if ( !isDefined( box ) ) + { + return 0; + } +/# + self sloth_debug_context( box, sqrt( 32400 ) ); +#/ + if ( flag( "moving_chest_now" ) ) + { + return 0; + } + if ( is_true( box._box_open ) || is_true( box._box_opened_by_fire_sale ) ) + { + return 0; + } + dist = distancesquared( self.origin, box.origin ); + if ( dist < 32400 ) + { + return 1; + } + return 0; +} + +box_get_ground_offset() +{ + vec_right = vectornormalize( anglesToRight( self.angles ) ); + box_pos = self.origin - ( vec_right * 36 ); + ground_pos = groundpos( box_pos ); + return ground_pos; +} + +common_abort_box( box ) +{ + if ( flag( "moving_chest_now" ) ) + { + self.context_done = 1; + return 1; + } + if ( isDefined( box ) ) + { + if ( is_true( box._box_open ) || is_true( box._box_opened_by_fire_sale ) ) + { +/# + sloth_print( "box was opened...abort" ); +#/ + self.context_done = 1; + return 1; + } + } + return 0; +} + +common_move_to_maze( box ) +{ + self endon( "death" ); + while ( 1 ) + { + if ( self common_abort_box( box ) ) + { + return 0; + } + if ( self maps/mp/zombies/_zm_ai_sloth::sloth_behind_mansion() ) + { + break; + } + else + { + self maps/mp/zombies/_zm_ai_sloth::action_navigate_mansion( level.maze_depart, level.maze_arrive ); + wait 0,2; + } + } + return 1; +} + +common_move_to_courtyard( box ) +{ + self endon( "death" ); + while ( 1 ) + { + if ( self common_abort_box( box ) ) + { + return 0; + } + if ( !self maps/mp/zombies/_zm_ai_sloth::sloth_behind_mansion() ) + { + break; + } + else + { + self maps/mp/zombies/_zm_ai_sloth::action_navigate_mansion( level.courtyard_depart, level.courtyard_arrive ); + wait 0,2; + } + } + return 1; +} + +common_move_to_box( box, range, ignore_open, asd_name ) +{ + if ( isDefined( asd_name ) ) + { + anim_id = self getanimfromasd( asd_name, 0 ); + start_org = getstartorigin( box.origin, box.angles, anim_id ); + start_ang = getstartangles( box.origin, box.angles, anim_id ); + self setgoalpos( start_org ); + ground_pos = start_org; + } + else + { + vec_right = vectornormalize( anglesToRight( box.angles ) ); + box_pos = box.origin - ( vec_right * 36 ); + ground_pos = groundpos( box_pos ); + self setgoalpos( ground_pos ); + } + while ( 1 ) + { + if ( flag( "moving_chest_now" ) ) + { + self.context_done = 1; + return 0; + } + if ( !is_true( ignore_open ) || is_true( box._box_open ) && is_true( box._box_opened_by_fire_sale ) ) + { +/# + sloth_print( "box was opened...abort" ); +#/ + self.context_done = 1; + return 0; + } + dist = distancesquared( self.origin, ground_pos ); + if ( dist < range ) + { + break; + } + else + { + wait 0,1; + } + } + if ( isDefined( asd_name ) ) + { + self setgoalpos( self.origin ); + self sloth_face_object( box, "angle", start_ang[ 1 ], 0,9 ); + } + else + { + angles = vectorToAngle( vec_right ); + self.anchor.origin = self.origin; + self.anchor.angles = angles; + self orientmode( "face angle", angles[ 1 ] ); + wait 0,2; + } + if ( flag( "moving_chest_now" ) ) + { + self.context_done = 1; + return 0; + } + return 1; +} + +box_lock_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); + box = level.chests[ level.chest_index ]; + if ( !self common_move_to_box( box, 1024 ) ) + { + return; + } + self animscripted( box.origin, box.angles, "zm_lock_magicbox" ); + maps/mp/animscripts/zm_shared::donotetracks( "lock_magicbox_anim", ::box_notetracks, box ); + if ( flag( "moving_chest_now" ) ) + { + self.context_done = 1; + return; + } + setdvar( "magic_chest_movable", "0" ); +/# + sloth_print( "box will not move" ); +#/ + maps/mp/zombies/_zm_ai_sloth::unregister_candy_context( "box_lock" ); + maps/mp/zombies/_zm_ai_sloth::unregister_candy_context( "box_move" ); + self.context_done = 1; +} + +box_move_condition() +{ + if ( flag( "moving_chest_now" ) ) + { + return 0; + } + self.box_move = undefined; + self.box_current = undefined; + self.box_current_in_maze = 0; + box_current = level.chests[ level.chest_index ]; + if ( is_true( box_current._box_open ) || is_true( box_current._box_opened_by_fire_sale ) ) + { + return 0; + } + if ( box_current.script_noteworthy == "courtroom_chest1" ) + { + if ( !maps/mp/zm_buried::is_courthouse_open() ) + { + return 0; + } + } + if ( box_current.script_noteworthy == "tunnels_chest1" ) + { + if ( !maps/mp/zm_buried::is_tunnel_open() ) + { + return 0; + } + } + if ( box_current.script_noteworthy == "maze_chest1" || box_current.script_noteworthy == "maze_chest2" ) + { + self.box_current_in_maze = 1; + if ( !is_maze_open() ) + { + return 0; + } + } + i = 0; + while ( i < level.chests.size ) + { + if ( i == level.chest_index ) + { + i++; + continue; + } + else + { + box = level.chests[ i ]; + if ( box.script_noteworthy != "maze_chest1" ) + { + self.box_move_in_maze = box.script_noteworthy == "maze_chest2"; + } + dist = distancesquared( self.origin, box.origin ); + if ( dist < 32400 ) + { + self.box_move_index = i; + self.box_move = box; + self.box_current = box_current; + return 1; + } + } + i++; + } + return 0; +} + +box_move_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); +/# + sloth_print( "moving box from: " + self.box_current.script_noteworthy + " to: " + self.box_move.script_noteworthy ); +#/ + if ( !self common_move_to_box( self.box_move, 1024, 0, "zm_magicbox_point" ) ) + { + return; + } + self maps/mp/zombies/_zm_ai_sloth::action_animscripted( "zm_magicbox_point", "magicbox_point_anim", self.box_move.origin, self.box_move.angles ); + if ( is_true( self.box_current_in_maze ) ) + { + if ( !is_true( self.box_move_in_maze ) ) + { + if ( !self common_move_to_maze( self.box_current ) ) + { + return; + } + } + } + else + { + if ( is_true( self.box_move_in_maze ) ) + { + if ( !self common_move_to_courtyard( self.box_current ) ) + { + return; + } + } + } + if ( !self common_move_to_box( self.box_current, 1024, 0, "zm_pull_magicbox" ) ) + { + return; + } + self animscripted( self.box_current.origin, self.box_current.angles, "zm_pull_magicbox" ); + maps/mp/animscripts/zm_shared::donotetracks( "pull_magicbox_anim", ::box_notetracks, self.box_current ); + if ( self common_abort_box( self.box_current ) ) + { + self box_move_interrupt(); + return; + } + if ( isDefined( level.sloth.custom_box_move_func ) ) + { + self thread [[ level.sloth.custom_box_move_func ]]( 0 ); + } + level.sloth_moving_box = 1; + self.ignore_common_run = 1; + self set_zombie_run_cycle( "run_holding_magicbox" ); + self.locomotion = "run_holding_magicbox"; + if ( is_true( self.box_current_in_maze ) ) + { + if ( !is_true( self.box_move_in_maze ) ) + { + if ( !self common_move_to_courtyard( undefined ) ) + { + self box_move_interrupt(); + return; + } + } + } + else + { + if ( is_true( self.box_move_in_maze ) ) + { + if ( !self common_move_to_maze( undefined ) ) + { + self box_move_interrupt(); + return; + } + } + } + if ( !self common_move_to_box( self.box_move, 1024, 0, "zm_place_magicbox" ) ) + { + self box_move_interrupt(); + return; + } + self animscripted( self.box_move.origin, self.box_move.angles, "zm_place_magicbox" ); + maps/mp/animscripts/zm_shared::donotetracks( "place_magicbox_anim", ::box_notetracks, self.box_move ); + self.box_current = undefined; + self.context_done = 1; + level.sloth_moving_box = undefined; + if ( isDefined( level.sloth.custom_box_move_func ) ) + { + self thread [[ level.sloth.custom_box_move_func ]]( 1 ); + } +} + +box_notetracks( note, box ) +{ + if ( !flag( "moving_chest_now" ) || is_true( box._box_open ) && is_true( box._box_opened_by_fire_sale ) ) + { + return 0; + } + if ( note == "pulled" ) + { + playfx( level._effect[ "fx_buried_sloth_box_slam" ], box.origin ); + tag_name = "tag_stowed_back"; + twr_origin = self gettagorigin( tag_name ); + twr_angles = self gettagangles( tag_name ); + if ( !isDefined( self.box_model ) ) + { + self.box_model = spawn( "script_model", twr_origin ); + self.box_model.angles = twr_angles; + self.box_model setmodel( level.small_magic_box ); + self.box_model linkto( self, tag_name ); + self.box_model_visible = 1; + } + else + { + self.box_model show(); + self.box_model_visible = 1; + } + self.box_current maps/mp/zombies/_zm_magicbox::hide_chest(); + } + else if ( note == "placed" ) + { + playfx( level._effect[ "fx_buried_sloth_box_slam" ], box.origin ); + self box_model_hide(); + if ( isDefined( self.box_move.zbarrier ) ) + { + self.box_move.zbarrier maps/mp/zombies/_zm_magicbox::set_magic_box_zbarrier_state( "initial" ); + self.box_move.hidden = 0; + self.box_move thread [[ level.pandora_show_func ]](); + level.chest_index = self.box_move_index; + } + } + else + { + if ( note == "locked" ) + { + playfx( level._effect[ "fx_buried_sloth_box_slam" ], box.origin ); + } + } +} + +box_model_hide() +{ + if ( isDefined( self.box_model ) ) + { + self.box_model ghost(); + self.box_model_visible = 0; + } +} + +box_move_interrupt() +{ + if ( isDefined( self.box_current ) ) + { + if ( isDefined( self.box_current.zbarrier ) ) + { + self.box_current.zbarrier maps/mp/zombies/_zm_magicbox::set_magic_box_zbarrier_state( "initial" ); + self.box_current.hidden = 0; + self.box_current thread [[ level.pandora_show_func ]](); + } + } + if ( isDefined( level.sloth.custom_box_move_func ) ) + { + self thread [[ level.sloth.custom_box_move_func ]]( 1 ); + } + level.sloth_moving_box = undefined; + self box_model_hide(); +} + +box_spin_condition() +{ + if ( flag( "moving_chest_now" ) ) + { + return 0; + } + box = level.chests[ level.chest_index ]; + if ( is_true( box._box_open ) || is_true( box._box_opened_by_fire_sale ) ) + { + ground_pos = groundpos( box.origin ); + dist = distancesquared( self.origin, ground_pos ); + if ( dist < 32400 ) + { + return 1; + } + } + return 0; +} + +box_spin_action() +{ + self endon( "death" ); + self endon( "stop_action" ); + self maps/mp/zombies/_zm_ai_sloth::common_context_action(); + box = level.chests[ level.chest_index ]; + hackable = spawnstruct(); + hackable.chest = box; + if ( !self common_move_to_box( box, 1024, 1, "zm_cycle_magicbox" ) ) + { + return; + } + if ( !self box_spin_qualifier( hackable ) ) + { + return; + } + self animscripted( box.origin, box.angles, "zm_cycle_magicbox" ); + maps/mp/animscripts/zm_shared::donotetracks( "cycle_magicbox_anim", ::box_kick, hackable ); + self.context_done = 1; +} + +box_kick( note, hackable ) +{ + if ( note == "kick" ) + { + if ( !self box_spin_qualifier( hackable ) ) + { + return; + } + if ( !flag( "moving_chest_now" ) ) + { + hackable thread box_trigger(); + hackable maps/mp/zombies/_zm_hackables_box::respin_box( self.candy_player ); + } + } +} + +box_trigger() +{ + if ( isDefined( self.chest ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.chest.unitrigger_stub ); + self.chest.zbarrier waittill( "randomization_done" ); + if ( !flag( "moving_chest_now" ) ) + { + thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.chest.unitrigger_stub, ::maps/mp/zombies/_zm_magicbox::magicbox_unitrigger_think ); + } + } +} + +box_spin_qualifier( hackable ) +{ + if ( isDefined( hackable.chest ) ) + { + if ( !isDefined( hackable.chest.chest_user ) ) + { + self.context_done = 1; + return 0; + } + } + if ( !hackable maps/mp/zombies/_zm_hackables_box::hack_box_qualifier( self.candy_player ) ) + { +/# + sloth_print( "hack_box_qualifier failed" ); +#/ + self.context_done = 1; + return 0; + } + return 1; +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_utility.gsc b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_utility.gsc new file mode 100644 index 0000000..fc6ee97 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_utility.gsc @@ -0,0 +1,211 @@ +#include maps/mp/zombies/_zm_ai_sloth; +#include maps/mp/zm_buried; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +should_ignore_candybooze( player ) +{ + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_underground_courthouse" ) || player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_underground_courthouse2" ) ) + { + if ( !maps/mp/zm_buried::is_courthouse_open() ) + { + return 1; + } + } + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_tunnels_north2" ) ) + { + if ( !maps/mp/zm_buried::is_courthouse_open() ) + { + return 1; + } + } + if ( !player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_tunnels_center" ) || player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_tunnels_north" ) && player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_tunnels_south" ) ) + { + if ( !maps/mp/zm_buried::is_tunnel_open() ) + { + return 1; + } + } + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_start_lower" ) ) + { + return 1; + } + if ( player maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_underground_bar" ) ) + { + if ( !maps/mp/zombies/_zm_ai_sloth::is_bar_open() ) + { + return 1; + } + } + return 0; +} + +watch_crash_pos() +{ + dist_crash = 4096; + level.crash_pos = []; + level.crash_pos[ level.crash_pos.size ] = ( 3452, 1012, 56 ); + level.crash_pos[ level.crash_pos.size ] = ( 3452, 1092, 56 ); + level.crash_pos[ level.crash_pos.size ] = ( 3452, 1056, 56 ); + while ( 1 ) + { + while ( !isDefined( self.state ) || self.state != "berserk" ) + { + wait 0,1; + } + _a82 = level.crash_pos; + _k82 = getFirstArrayKey( _a82 ); + while ( isDefined( _k82 ) ) + { + pos = _a82[ _k82 ]; + dist = distancesquared( self.origin, pos ); + if ( dist < dist_crash ) + { + self.anchor.origin = self.origin; + self.anchor.angles = self.angles; + self linkto( self.anchor ); + self setclientfield( "sloth_berserk", 0 ); + self sloth_set_state( "crash", 0 ); + wait 0,25; + self unlink(); + } + _k82 = getNextArrayKey( _a82, _k82 ); + } + wait 0,05; + } +} + +sloth_is_pain() +{ + if ( is_true( self.is_pain ) ) + { + anim_state = self getanimstatefromasd(); + if ( anim_state == "zm_pain" || anim_state == "zm_pain_no_restart" ) + { + return 1; + } + else + { + self.reset_asd = undefined; + self animmode( "normal" ); + self.is_pain = 0; + self.damage_accumulating = 0; + self notify( "stop_accumulation" ); +/# + sloth_print( "pain was interrupted" ); +#/ + } + } + return 0; +} + +sloth_is_traversing() +{ + if ( is_true( self.is_traversing ) ) + { + anim_state = self getanimstatefromasd(); + if ( anim_state != "zm_traverse" && anim_state != "zm_traverse_no_restart" && anim_state != "zm_traverse_barrier" && anim_state != "zm_traverse_barrier_no_restart" && anim_state != "zm_sling_equipment" && anim_state != "zm_unsling_equipment" && anim_state != "zm_sling_magicbox" && anim_state != "zm_unsling_magicbox" && anim_state != "zm_sloth_crawlerhold_sling" && anim_state != "zm_sloth_crawlerhold_unsling" || anim_state == "zm_sloth_crawlerhold_sling_hunched" && anim_state == "zm_sloth_crawlerhold_unsling_hunched" ) + { + return 1; + } + else + { + self.is_traversing = 0; +/# + sloth_print( "traverse was interrupted" ); +#/ + } + } + return 0; +} + +sloth_face_object( facee, type, data, dot_limit ) +{ + if ( type == "angle" ) + { + self orientmode( "face angle", data ); + } + else + { + if ( type == "point" ) + { + self orientmode( "face point", data ); + } + } + time_started = getTime(); + while ( 1 ) + { + if ( type == "angle" ) + { + delta = abs( self.angles[ 1 ] - data ); + if ( delta <= 15 ) + { + break; + } + else } + else if ( isDefined( dot_limit ) ) + { + if ( self is_facing( facee, dot_limit ) ) + { + break; + } + else } + else if ( self is_facing( facee ) ) + { + break; + } + else if ( ( getTime() - time_started ) > 1000 ) + { +/# + sloth_print( "face took too long" ); +#/ + break; + } + else + { + wait 0,1; + } + } +/# + time_elapsed = getTime() - time_started; + sloth_print( "time to face: " + time_elapsed ); +#/ +} + +sloth_print( str ) +{ +/# + if ( getDvarInt( #"B6252E7C" ) ) + { + iprintln( "sloth: " + 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; +#/ + } + } +} + +sloth_debug_context( item, dist ) +{ +/# + if ( is_true( self.context_debug ) ) + { + debugstar( item.origin, 100, ( 1, 1, 1 ) ); + circle( item.origin, dist, ( 1, 1, 1 ), 0, 1, 100 ); +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_banking.gsc b/zm_buried_patch/maps/mp/zombies/_zm_banking.gsc new file mode 100644 index 0000000..69431c5 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_buildables_pooled.gsc b/zm_buried_patch/maps/mp/zombies/_zm_buildables_pooled.gsc new file mode 100644 index 0000000..46504ff --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_buildables_pooled.gsc @@ -0,0 +1,443 @@ +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +add_buildable_to_pool( stub, poolname ) +{ + if ( !isDefined( level.buildablepools ) ) + { + level.buildablepools = []; + } + if ( !isDefined( level.buildablepools[ poolname ] ) ) + { + level.buildablepools[ poolname ] = spawnstruct(); + level.buildablepools[ poolname ].stubs = []; + } + level.buildablepools[ poolname ].stubs[ level.buildablepools[ poolname ].stubs.size ] = stub; + if ( !isDefined( level.buildablepools[ poolname ].buildable_slot ) ) + { + level.buildablepools[ poolname ].buildable_slot = stub.buildablestruct.buildable_slot; + } + else + { +/# + assert( level.buildablepools[ poolname ].buildable_slot == stub.buildablestruct.buildable_slot ); +#/ + } + stub.buildable_pool = level.buildablepools[ poolname ]; + stub.original_prompt_and_visibility_func = stub.prompt_and_visibility_func; + stub.original_trigger_func = stub.trigger_func; + stub.prompt_and_visibility_func = ::pooledbuildabletrigger_update_prompt; + reregister_unitrigger( stub, ::pooled_buildable_place_think ); +} + +reregister_unitrigger( unitrigger_stub, new_trigger_func ) +{ + static = 0; + if ( isDefined( unitrigger_stub.in_zone ) ) + { + static = 1; + } + unregister_unitrigger( unitrigger_stub ); + unitrigger_stub.trigger_func = new_trigger_func; + if ( static ) + { + register_static_unitrigger( unitrigger_stub, new_trigger_func, 0 ); + } + else + { + register_unitrigger( unitrigger_stub, new_trigger_func ); + } +} + +randomize_pooled_buildables( poolname ) +{ + level waittill( "buildables_setup" ); + while ( isDefined( level.buildablepools[ poolname ] ) ) + { + count = level.buildablepools[ poolname ].stubs.size; + while ( count > 1 ) + { + targets = []; + i = 0; + while ( i < count ) + { + while ( 1 ) + { + p = randomint( count ); + if ( !isDefined( targets[ p ] ) ) + { + targets[ p ] = i; + i++; + continue; + } + else + { + } + } + i++; + } + i = 0; + while ( i < count ) + { + if ( isDefined( targets[ i ] ) && targets[ i ] != i ) + { + swap_buildable_fields( level.buildablepools[ poolname ].stubs[ i ], level.buildablepools[ poolname ].stubs[ targets[ i ] ] ); + } + i++; + } + } + } +} + +pooledbuildable_has_piece( piece ) +{ + return isDefined( self pooledbuildable_stub_for_piece( piece ) ); +} + +pooledbuildable_stub_for_piece( piece ) +{ + _a104 = self.stubs; + _k104 = getFirstArrayKey( _a104 ); + while ( isDefined( _k104 ) ) + { + stub = _a104[ _k104 ]; + if ( isDefined( stub.bound_to_buildable ) ) + { + } + else + { + if ( stub.buildablezone buildable_has_piece( piece ) ) + { + return stub; + } + } + _k104 = getNextArrayKey( _a104, _k104 ); + } + return undefined; +} + +pooledbuildabletrigger_update_prompt( player ) +{ + can_use = self.stub pooledbuildablestub_update_prompt( player, self ); + self sethintstring( self.stub.hint_string ); + if ( isDefined( self.stub.cursor_hint ) ) + { + if ( self.stub.cursor_hint == "HINT_WEAPON" && isDefined( self.stub.cursor_hint_weapon ) ) + { + self setcursorhint( self.stub.cursor_hint, self.stub.cursor_hint_weapon ); + } + else + { + self setcursorhint( self.stub.cursor_hint ); + } + } + return can_use; +} + +pooledbuildablestub_update_prompt( player, trigger ) +{ + if ( !self anystub_update_prompt( player ) ) + { + return 0; + } + can_use = 1; + if ( isDefined( self.custom_buildablestub_update_prompt ) && !( self [[ self.custom_buildablestub_update_prompt ]]( player ) ) ) + { + return 0; + } + self.cursor_hint = "HINT_NOICON"; + self.cursor_hint_weapon = undefined; + if ( isDefined( self.built ) && !self.built ) + { + slot = self.buildablestruct.buildable_slot; + if ( !isDefined( player player_get_buildable_piece( slot ) ) ) + { + if ( isDefined( level.zombie_buildables[ self.equipname ].hint_more ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint_more; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_MORE"; + } + if ( isDefined( level.custom_buildable_need_part_vo ) ) + { + player thread [[ level.custom_buildable_need_part_vo ]](); + } + return 0; + } + else + { + if ( isDefined( self.bound_to_buildable ) && !self.bound_to_buildable.buildablezone buildable_has_piece( player player_get_buildable_piece( slot ) ) ) + { + if ( isDefined( level.zombie_buildables[ self.bound_to_buildable.equipname ].hint_wrong ) ) + { + self.hint_string = level.zombie_buildables[ self.bound_to_buildable.equipname ].hint_wrong; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_WRONG"; + } + if ( isDefined( level.custom_buildable_wrong_part_vo ) ) + { + player thread [[ level.custom_buildable_wrong_part_vo ]](); + } + return 0; + } + else + { + if ( !isDefined( self.bound_to_buildable ) && !self.buildable_pool pooledbuildable_has_piece( player player_get_buildable_piece( slot ) ) ) + { + if ( isDefined( level.zombie_buildables[ self.equipname ].hint_wrong ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint_wrong; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_WRONG"; + } + return 0; + } + else + { + if ( isDefined( self.bound_to_buildable ) ) + { +/# + assert( isDefined( level.zombie_buildables[ self.equipname ].hint ), "Missing buildable hint" ); +#/ + if ( isDefined( level.zombie_buildables[ self.equipname ].hint ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint; + } + else + { + self.hint_string = "Missing buildable hint"; + } + } + else /# + assert( isDefined( level.zombie_buildables[ self.equipname ].hint ), "Missing buildable hint" ); +#/ + if ( isDefined( level.zombie_buildables[ self.equipname ].hint ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint; + } + else + { + self.hint_string = "Missing buildable hint"; + } + } + } + } + } + else + { + return trigger [[ self.original_prompt_and_visibility_func ]]( player ); + } + return 1; +} + +find_bench( bench_name ) +{ + return getent( bench_name, "targetname" ); +} + +swap_buildable_fields( stub1, stub2 ) +{ + tbz = stub2.buildablezone; + stub2.buildablezone = stub1.buildablezone; + stub2.buildablezone.stub = stub2; + stub1.buildablezone = tbz; + stub1.buildablezone.stub = stub1; + tbs = stub2.buildablestruct; + stub2.buildablestruct = stub1.buildablestruct; + stub1.buildablestruct = tbs; + te = stub2.equipname; + stub2.equipname = stub1.equipname; + stub1.equipname = te; + th = stub2.hint_string; + stub2.hint_string = stub1.hint_string; + stub1.hint_string = th; + ths = stub2.trigger_hintstring; + stub2.trigger_hintstring = stub1.trigger_hintstring; + stub1.trigger_hintstring = ths; + tp = stub2.persistent; + stub2.persistent = stub1.persistent; + stub1.persistent = tp; + tobu = stub2.onbeginuse; + stub2.onbeginuse = stub1.onbeginuse; + stub1.onbeginuse = tobu; + tocu = stub2.oncantuse; + stub2.oncantuse = stub1.oncantuse; + stub1.oncantuse = tocu; + toeu = stub2.onenduse; + stub2.onenduse = stub1.onenduse; + stub1.onenduse = toeu; + tt = stub2.target; + stub2.target = stub1.target; + stub1.target = tt; + ttn = stub2.targetname; + stub2.targetname = stub1.targetname; + stub1.targetname = ttn; + twn = stub2.weaponname; + stub2.weaponname = stub1.weaponname; + stub1.weaponname = twn; + pav = stub2.original_prompt_and_visibility_func; + stub2.original_prompt_and_visibility_func = stub1.original_prompt_and_visibility_func; + stub1.original_prompt_and_visibility_func = pav; + bench1 = undefined; + bench2 = undefined; + transfer_pos_as_is = 1; + if ( isDefined( stub1.model.target ) && isDefined( stub2.model.target ) ) + { + bench1 = find_bench( stub1.model.target ); + bench2 = find_bench( stub2.model.target ); + if ( isDefined( bench1 ) && isDefined( bench2 ) ) + { + transfer_pos_as_is = 0; + w2lo1 = bench1 worldtolocalcoords( stub1.model.origin ); + w2la1 = stub1.model.angles - bench1.angles; + w2lo2 = bench2 worldtolocalcoords( stub2.model.origin ); + w2la2 = stub2.model.angles - bench2.angles; + stub1.model.origin = bench2 localtoworldcoords( w2lo1 ); + stub1.model.angles = bench2.angles + w2la1; + stub2.model.origin = bench1 localtoworldcoords( w2lo2 ); + stub2.model.angles = bench1.angles + w2la2; + } + tmt = stub2.model.target; + stub2.model.target = stub1.model.target; + stub1.model.target = tmt; + } + tm = stub2.model; + stub2.model = stub1.model; + stub1.model = tm; + if ( transfer_pos_as_is ) + { + tmo = stub2.model.origin; + tma = stub2.model.angles; + stub2.model.origin = stub1.model.origin; + stub2.model.angles = stub1.model.angles; + stub1.model.origin = tmo; + stub1.model.angles = tma; + } +} + +pooled_buildable_place_think() +{ + self endon( "kill_trigger" ); + if ( isDefined( self.stub.built ) && self.stub.built ) + { + return buildable_place_think(); + } + player_built = undefined; + while ( isDefined( self.stub.built ) && !self.stub.built ) + { + self waittill( "trigger", player ); + while ( player != self.parent_player ) + { + continue; + } + while ( isDefined( player.screecher_weapon ) ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + } + bind_to = self.stub; + slot = bind_to.buildablestruct.buildable_slot; + if ( !isDefined( self.stub.bound_to_buildable ) ) + { + bind_to = self.stub.buildable_pool pooledbuildable_stub_for_piece( player player_get_buildable_piece( slot ) ); + } + while ( isDefined( bind_to ) && isDefined( self.stub.bound_to_buildable ) || self.stub.bound_to_buildable != bind_to && isDefined( bind_to.bound_to_buildable ) && self.stub != bind_to.bound_to_buildable ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + if ( isDefined( self.stub.oncantuse ) ) + { + self.stub [[ self.stub.oncantuse ]]( player ); + } + } + status = player player_can_build( bind_to.buildablezone ); + if ( !status ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + if ( isDefined( bind_to.oncantuse ) ) + { + bind_to [[ bind_to.oncantuse ]]( player ); + } + continue; + } + else + { + if ( isDefined( bind_to.onbeginuse ) ) + { + self.stub [[ bind_to.onbeginuse ]]( player ); + } + result = self buildable_use_hold_think( player, bind_to ); + team = player.pers[ "team" ]; + if ( result ) + { + if ( isDefined( self.stub.bound_to_buildable ) && self.stub.bound_to_buildable != bind_to ) + { + result = 0; + } + if ( isDefined( bind_to.bound_to_buildable ) && self.stub != bind_to.bound_to_buildable ) + { + result = 0; + } + } + if ( isDefined( bind_to.onenduse ) ) + { + self.stub [[ bind_to.onenduse ]]( team, player, result ); + } + while ( !result ) + { + continue; + } + if ( !isDefined( self.stub.bound_to_buildable ) && isDefined( bind_to ) ) + { + if ( bind_to != self.stub ) + { + swap_buildable_fields( self.stub, bind_to ); + } + self.stub.bound_to_buildable = self.stub; + } + if ( isDefined( self.stub.onuse ) ) + { + self.stub [[ self.stub.onuse ]]( player ); + } + if ( isDefined( player player_get_buildable_piece( slot ) ) ) + { + prompt = player player_build( self.stub.buildablezone ); + player_built = player; + self.stub.hint_string = prompt; + self sethintstring( self.stub.hint_string ); + } + } + } + switch( self.stub.persistent ) + { + case 1: + self bptrigger_think_persistent( player_built ); + break; + case 0: + self bptrigger_think_one_time( player_built ); + break; + case 3: + self bptrigger_think_unbuild( player_built ); + break; + case 2: + self bptrigger_think_one_use_and_fly( player_built ); + break; + case 4: + self [[ self.stub.custom_completion_callback ]]( player_built ); + break; + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_equip_headchopper.gsc b/zm_buried_patch/maps/mp/zombies/_zm_equip_headchopper.gsc new file mode 100644 index 0000000..01920bc --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_equip_headchopper.gsc @@ -0,0 +1,1002 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/animscripts/zm_run; +#include maps/mp/animscripts/zm_death; +#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_spawner; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zombie_headchopper" ); + +init( pickupstring, howtostring ) +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_headchopper_zm" ) ) + { + return; + } + level.headchopper_name = "equip_headchopper_zm"; + init_animtree(); + maps/mp/zombies/_zm_equipment::register_equipment( level.headchopper_name, pickupstring, howtostring, "t6_wpn_zmb_chopper", "headchopper", undefined, ::transferheadchopper, ::dropheadchopper, ::pickupheadchopper, ::placeheadchopper ); + maps/mp/zombies/_zm_equipment::add_placeable_equipment( level.headchopper_name, "t6_wpn_zmb_chopper", undefined, "wallmount" ); + maps/mp/zombies/_zm_spawner::register_zombie_damage_callback( ::headchopper_zombie_damage_response ); + maps/mp/zombies/_zm_spawner::register_zombie_death_animscript_callback( ::headchopper_zombie_death_response ); + level thread onplayerconnect(); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "equip_headchopper", pickupstring ); + level._effect[ "headchoppere_on" ] = loadfx( "maps/zombie_buried/fx_buried_headchopper_os" ); + thread init_anim_slice_times(); + thread wait_init_damage(); +} + +wait_init_damage() +{ + while ( !isDefined( level.zombie_vars ) || !isDefined( level.zombie_vars[ "zombie_health_start" ] ) ) + { + wait 1; + } + level.headchopper_damage = maps/mp/zombies/_zm::ai_zombie_health( 50 ); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread onplayerspawned(); + player thread player_hide_turrets_from_other_players(); + } +} + +onplayerspawned() +{ + self endon( "disconnect" ); + self thread setupwatchers(); + for ( ;; ) + { + self waittill( "spawned_player" ); + self thread watchheadchopperuse(); + } +} + +setupwatchers() +{ + self waittill( "weapon_watchers_created" ); + watcher = maps/mp/gametypes_zm/_weaponobjects::getweaponobjectwatcher( "equip_headchopper" ); + watcher.onspawnretrievetriggers = ::maps/mp/zombies/_zm_equipment::equipment_onspawnretrievableweaponobject; +} + +watchheadchopperuse() +{ + self notify( "watchHeadChopperUse" ); + self endon( "watchHeadChopperUse" ); + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_placed", weapon, weapname ); + if ( weapname == level.headchopper_name ) + { + self cleanupoldheadchopper(); + self.buildableheadchopper = weapon; + self thread startheadchopperdeploy( weapon ); + } + } +} + +cleanupoldheadchopper() +{ + if ( isDefined( self.buildableheadchopper ) ) + { + if ( isDefined( self.buildableheadchopper.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildableheadchopper.stub ); + self.buildableheadchopper.stub = undefined; + } + self.buildableheadchopper delete(); + self.headchopper_kills = undefined; + } + if ( isDefined( level.headchopper_sound_ent ) ) + { + level.headchopper_sound_ent delete(); + level.headchopper_sound_ent = undefined; + } +} + +watchforcleanup() +{ + self notify( "headchopper_cleanup" ); + self endon( "headchopper_cleanup" ); + self waittill_any( "death_or_disconnect", "equip_headchopper_zm_taken", "equip_headchopper_zm_pickup" ); + cleanupoldheadchopper(); +} + +player_hide_turrets_from_other_players() +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "create_equipment_turret", equipment, turret ); + if ( equipment == level.headchopper_name ) + { + turret setinvisibletoall(); + turret setvisibletoplayer( self ); + } + } +} + +placeheadchopper( origin, angles ) +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "t6_wpn_zmb_chopper", level.headchopper_name, origin, angles, 100, 0 ); + if ( isDefined( item ) ) + { + item.headchopper_kills = self.headchopper_kills; + item.requires_pickup = 1; + item.zombie_attack_callback = ::headchopper_add_chop_ent; + } + self.headchopper_kills = undefined; + return item; +} + +dropheadchopper() +{ + item = self maps/mp/zombies/_zm_equipment::dropped_equipment_think( "t6_wpn_zmb_chopper", level.headchopper_name, self.origin, self.angles, 100, 0 ); + if ( isDefined( item ) ) + { + item.headchopper_kills = self.headchopper_kills; + item.requires_pickup = 1; + } + self.headchopper_kills = undefined; + return item; +} + +pickupheadchopper( item ) +{ + self.headchopper_kills = item.headchopper_kills; + item.headchopper_kills = undefined; +} + +transferheadchopper( fromplayer, toplayer ) +{ + buildableheadchopper = toplayer.buildableheadchopper; + toarmed = 0; + if ( isDefined( buildableheadchopper ) ) + { + if ( isDefined( buildableheadchopper.is_armed ) ) + { + toarmed = buildableheadchopper.is_armed; + } + } + headchopper_kills = toplayer.headchopper_kills; + fromarmed = 0; + if ( isDefined( fromplayer.buildableheadchopper ) ) + { + if ( isDefined( fromplayer.buildableheadchopper.is_armed ) ) + { + fromarmed = fromplayer.buildableheadchopper.is_armed; + } + } + toplayer.buildableheadchopper = fromplayer.buildableheadchopper; + toplayer.buildableheadchopper.original_owner = toplayer; + toplayer.buildableheadchopper.owner = toplayer; + toplayer notify( "equip_headchopper_zm_taken" ); + toplayer.headchopper_kills = fromplayer.headchopper_kills; + toplayer thread startheadchopperdeploy( toplayer.buildableheadchopper, fromarmed ); + fromplayer.buildableheadchopper = buildableheadchopper; + fromplayer.headchopper_kills = headchopper_kills; + fromplayer notify( "equip_headchopper_zm_taken" ); + if ( isDefined( fromplayer.buildableheadchopper ) ) + { + fromplayer thread startheadchopperdeploy( fromplayer.buildableheadchopper, toarmed ); + fromplayer.buildableheadchopper.original_owner = fromplayer; + fromplayer.buildableheadchopper.owner = fromplayer; + } + else + { + fromplayer maps/mp/zombies/_zm_equipment::equipment_release( level.headchopper_name ); + } +} + +headchopper_in_range( delta, origin, radius ) +{ + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +headchopper_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(); +} + +headchopper_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: trap off\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 0; +} + +startheadchopperdeploy( weapon, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_headchopper_zm_taken" ); + self thread watchforcleanup(); + electricradius = 45; + if ( isDefined( self.headchopper_kills ) ) + { + weapon.headchopper_kills = self.headchopper_kills; + self.headchopper_kills = undefined; + } + if ( !isDefined( weapon.headchopper_kills ) ) + { + weapon.headchopper_kills = 0; + } + if ( isDefined( weapon ) ) + { +/# + weapon thread debugheadchopper( electricradius ); +#/ + fwdangles = anglesToUp( weapon.angles ); + traceback = groundtrace( weapon.origin + ( fwdangles * 5 ), weapon.origin - ( fwdangles * 999999 ), 0, weapon ); + if ( isDefined( traceback ) && isDefined( traceback[ "entity" ] ) ) + { + weapon.planted_on_ent = traceback[ "entity" ]; + if ( isDefined( traceback[ "entity" ].targetname ) ) + { + parententities = getentarray( traceback[ "entity" ].targetname, "target" ); + if ( isDefined( parententities ) && parententities.size > 0 ) + { + parententity = parententities[ 0 ]; + if ( isDefined( parententity.targetname ) ) + { + if ( parententity.targetname == "zombie_debris" || parententity.targetname == "zombie_door" ) + { + weapon thread destroyheadchopperonplantedblockeropen(); + } + } + } + } + weapon thread destroyheadchopperonplantedentitydeath(); + } + weapon.deployed_time = getTime(); + if ( isDefined( level.equipment_headchopper_needs_power ) && level.equipment_headchopper_needs_power ) + { + weapon.power_on = 0; + maps/mp/zombies/_zm_power::add_temp_powered_item( ::headchopper_power_on, ::headchopper_power_off, ::headchopper_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 headchopperthink( weapon, electricradius, armed ); + if ( isDefined( level.equipment_headchopper_needs_power ) && !level.equipment_headchopper_needs_power ) + { + } + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( weapon ); + weapon waittill( "death" ); + if ( isDefined( level.headchopper_sound_ent ) ) + { + level.headchopper_sound_ent playsound( "wpn_zmb_electrap_stop" ); + level.headchopper_sound_ent delete(); + level.headchopper_sound_ent = undefined; + } + self notify( "headchopper_cleanup" ); + } +} + +headchopper_zombie_damage_response( mod, hit_location, hit_origin, player, amount ) +{ + if ( isDefined( self.damageweapon ) || self.damageweapon == level.headchopper_name && isDefined( self.damageweapon_name ) && self.damageweapon_name == level.headchopper_name ) + { + player.planted_wallmount_on_a_zombie = 1; + } + return 0; +} + +headchopper_zombie_death_response( mod, hit_location, hit_origin, player, amount ) +{ + if ( isDefined( self.damageweapon ) && self.damageweapon == level.headchopper_name && isDefined( self.damagemod ) && self.damagemod == "MOD_IMPACT" ) + { + origin = self.origin; + if ( isDefined( self.damagehit_origin ) ) + { + origin = self.damagehit_origin; + } + players = get_players(); + choppers = []; + _a412 = players; + _k412 = getFirstArrayKey( _a412 ); + while ( isDefined( _k412 ) ) + { + player = _a412[ _k412 ]; + if ( isDefined( player.buildableheadchopper ) ) + { + choppers[ choppers.size ] = player.buildableheadchopper; + } + _k412 = getNextArrayKey( _a412, _k412 ); + } + chopper = getclosest( origin, choppers ); + level thread headchopper_zombie_death_remove_chopper( chopper ); + } + return 0; +} + +headchopper_zombie_death_remove_chopper( chopper ) +{ + player = chopper.owner; + thread maps/mp/zombies/_zm_equipment::equipment_disappear_fx( chopper.origin, undefined, chopper.angles ); + chopper dropped_equipment_destroy( 0 ); + if ( !player hasweapon( level.headchopper_name ) ) + { + player giveweapon( level.headchopper_name ); + player setweaponammoclip( level.headchopper_name, 1 ); + player setactionslot( 1, "weapon", level.headchopper_name ); + } +} + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +init_anim_slice_times() +{ + level.headchopper_slice_times = []; + slice_times = getnotetracktimes( %o_zmb_chopper_slice_slow, "slice" ); + retract_times = getnotetracktimes( %o_zmb_chopper_slice_slow, "retract" ); + animlength = getanimlength( %o_zmb_chopper_slice_slow ); + _a462 = slice_times; + _k462 = getFirstArrayKey( _a462 ); + while ( isDefined( _k462 ) ) + { + frac = _a462[ _k462 ]; + level.headchopper_slice_times[ level.headchopper_slice_times.size ] = animlength * frac; + _k462 = getNextArrayKey( _a462, _k462 ); + } + _a467 = retract_times; + _k467 = getFirstArrayKey( _a467 ); + while ( isDefined( _k467 ) ) + { + frac = _a467[ _k467 ]; + level.headchopper_slice_times[ level.headchopper_slice_times.size ] = animlength * frac; + _k467 = getNextArrayKey( _a467, _k467 ); + } +} + +headchopper_animate( weapon, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_headchopper_zm_taken" ); + weapon endon( "death" ); + weapon useanimtree( -1 ); + f_animlength = getanimlength( %o_zmb_chopper_slice_fast ); + s_animlength = getanimlength( %o_zmb_chopper_slice_slow ); + weapon thread headchopper_audio(); + prearmed = 0; + if ( isDefined( armed ) && armed ) + { + prearmed = 1; + } + zombies_only = 0; + while ( isDefined( weapon ) ) + { + if ( !prearmed ) + { + wait 0,1; + } + else + { + wait 0,05; + } + prearmed = 0; + weapon.is_armed = 1; + weapon waittill( "chop", zombies_only ); + if ( isDefined( weapon ) ) + { + weapon.is_slicing = 1; + if ( isDefined( zombies_only ) && zombies_only ) + { + weapon thread watch_notetracks_slicing(); + weapon playsound( "zmb_headchopper_swing" ); + weapon setanim( %o_zmb_chopper_slice_slow ); + wait s_animlength; + weapon clearanim( %o_zmb_chopper_slice_slow, 0,2 ); + } + else + { + weapon setanim( %o_zmb_chopper_slice_fast ); + wait f_animlength; + weapon clearanim( %o_zmb_chopper_slice_fast, 0,2 ); + } + weapon notify( "end" ); + weapon.is_slicing = 0; + } + } +} + +watch_notetracks_slicing() +{ + self endon( "death" ); + _a546 = level.headchopper_slice_times; + _k546 = getFirstArrayKey( _a546 ); + while ( isDefined( _k546 ) ) + { + time = _a546[ _k546 ]; + self thread watch_notetracks_slicing_times( time ); + _k546 = getNextArrayKey( _a546, _k546 ); + } +} + +watch_notetracks_slicing_times( time ) +{ + self endon( "death" ); + wait time; + self notify( "slicing" ); +} + +playheadchopperresetaudio( time ) +{ + self endon( "headchopperAudioCleanup" ); + ent = spawn( "script_origin", self.origin ); + ent playloopsound( "zmb_highrise_launcher_reset_loop" ); + self thread deleteentwhensounddone( time, ent ); + self waittill( "death" ); + ent delete(); +} + +deleteentwhensounddone( time, ent ) +{ + self endon( "death" ); + wait time; + self notify( "headchopperAudioCleanup" ); + ent delete(); +} + +headchopper_audio() +{ + loop_ent = spawn( "script_origin", self.origin ); + loop_ent playloopsound( "zmb_highrise_launcher_loop" ); + self waittill( "death" ); + loop_ent delete(); +} + +headchopper_fx( weapon ) +{ + weapon endon( "death" ); + self endon( "equip_headchopper_zm_taken" ); + while ( isDefined( weapon ) ) + { + playfxontag( level._effect[ "headchoppere_on" ], weapon, "tag_origin" ); + wait 1; + } +} + +headchopperthink( weapon, electricradius, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_headchopper_zm_taken" ); + weapon endon( "death" ); + radiussquared = electricradius * electricradius; + traceposition = weapon getcentroid() + ( anglesToForward( flat_angle( weapon.angles ) ) * -15 ); + trace = bullettrace( traceposition, traceposition + vectorScale( ( 0, 0, 1 ), 48 ), 1, weapon ); + trigger_origin = weapon gettagorigin( "TAG_SAW" ); + trigger = spawn( "trigger_box", trigger_origin, 1, 8, 128, 64 ); + trigger.origin += anglesToUp( weapon.angles ) * 32; + trigger.angles = weapon.angles; + trigger enablelinkto(); + trigger linkto( weapon ); + weapon.trigger = trigger; +/# + trigger.extent = ( 4, 64, 32 ); +#/ + weapon thread headchopperthinkcleanup( trigger ); + direction_forward = anglesToForward( flat_angle( weapon.angles ) + vectorScale( ( 0, 0, 1 ), 60 ) ); + direction_vector = vectorScale( direction_forward, 1024 ); + direction_origin = weapon.origin + direction_vector; + home_angles = weapon.angles; + weapon.is_armed = 0; + self thread headchopper_fx( weapon ); + self thread headchopper_animate( weapon, armed ); + while ( isDefined( weapon.is_armed ) && !weapon.is_armed ) + { + wait 0,5; + } + weapon.chop_targets = []; + self thread targeting_thread( weapon, trigger ); + while ( isDefined( weapon ) ) + { + wait_for_targets( weapon ); + if ( isDefined( weapon.chop_targets ) && weapon.chop_targets.size > 0 ) + { + is_slicing = 1; + slice_count = 0; + while ( isDefined( is_slicing ) && is_slicing ) + { + weapon notify( "chop" ); + weapon.is_armed = 0; + weapon.zombies_only = 1; + _a680 = weapon.chop_targets; + _k680 = getFirstArrayKey( _a680 ); + while ( isDefined( _k680 ) ) + { + ent = _a680[ _k680 ]; + self thread headchopperattack( weapon, ent ); + _k680 = getNextArrayKey( _a680, _k680 ); + } + if ( weapon.headchopper_kills >= 42 ) + { + self thread headchopper_expired( weapon ); + } + weapon.chop_targets = []; + weapon waittill_any( "slicing", "end" ); + weapon notify( "slice_done" ); + slice_count++; + is_slicing = weapon.is_slicing; + } + while ( isDefined( weapon.is_armed ) && !weapon.is_armed ) + { + wait 0,5; + } + } + else wait 0,1; + } +} + +headchopperattack( weapon, ent ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_headchopper_zm_taken" ); + weapon endon( "death" ); + if ( !isDefined( ent ) || !isalive( ent ) ) + { + return; + } + eye_position = ent geteye(); + head_position = eye_position[ 2 ] + 13; + foot_position = ent.origin[ 2 ]; + length_head_to_toe = abs( head_position - foot_position ); + length_head_to_toe_25_percent = length_head_to_toe * 0,25; + if ( weapon.origin[ 2 ] <= head_position ) + { + is_headchop = weapon.origin[ 2 ] >= ( head_position - length_head_to_toe_25_percent ); + } + if ( weapon.origin[ 2 ] <= ( head_position - length_head_to_toe_25_percent ) ) + { + is_torsochop = weapon.origin[ 2 ] >= ( foot_position + length_head_to_toe_25_percent ); + } + is_footchop = abs( foot_position - weapon.origin[ 2 ] ) <= length_head_to_toe_25_percent; + trace_point = undefined; + if ( isDefined( is_headchop ) && is_headchop ) + { + trace_point = eye_position; + } + else + { + if ( isDefined( is_torsochop ) && is_torsochop ) + { + trace_point = ent.origin + ( 0, 0, length_head_to_toe_25_percent * 2 ); + } + else + { + trace_point = ent.origin + ( 0, 0, length_head_to_toe_25_percent ); + } + } + fwdangles = anglesToUp( weapon.angles ); + tracefwd = bullettrace( weapon.origin + ( fwdangles * 5 ), trace_point, 0, weapon, 1, 1 ); + if ( isDefined( tracefwd ) || !isDefined( tracefwd[ "position" ] ) && tracefwd[ "position" ] != trace_point ) + { + return; + } + if ( isplayer( ent ) ) + { + if ( isDefined( weapon.deployed_time ) && ( getTime() - weapon.deployed_time ) <= 2000 ) + { + return; + } + if ( isDefined( is_headchop ) && is_headchop && !ent hasperk( "specialty_armorvest" ) ) + { + ent dodamage( ent.health, weapon.origin ); + } + else + { + if ( isDefined( is_torsochop ) && is_torsochop ) + { + ent dodamage( 50, weapon.origin ); + } + else + { + if ( isDefined( is_footchop ) && is_footchop ) + { + ent dodamage( 25, weapon.origin ); + } + else + { + ent dodamage( 10, weapon.origin ); + } + } + } + } + else if ( isDefined( is_headchop ) || !is_headchop && isDefined( is_headchop ) && !is_headchop && isDefined( ent.has_legs ) && !ent.has_legs ) + { + headchop_height = 25; + if ( isDefined( ent.has_legs ) && !ent.has_legs ) + { + headchop_height = 35; + } + is_headchop = abs( eye_position[ 2 ] - weapon.origin[ 2 ] ) <= headchop_height; + } + if ( isDefined( is_headchop ) && is_headchop ) + { + if ( isDefined( ent.no_gib ) && !ent.no_gib ) + { + ent maps/mp/zombies/_zm_spawner::zombie_head_gib(); + } + ent dodamage( ent.health + 666, weapon.origin ); + ent.headchopper_last_damage_time = getTime(); + ent playsound( "zmb_exp_jib_headchopper_zombie" ); + weapon.headchopper_kills++; + self thread headchopper_kill_vo( ent ); + } + else + { + if ( isDefined( is_torsochop ) && is_torsochop ) + { + if ( ent.health <= 20 ) + { + ent playsound( "zmb_exp_jib_headchopper_zombie" ); + weapon.headchopper_kills++; + self thread headchopper_kill_vo( ent ); + } + ent dodamage( 20, weapon.origin ); + ent.headchopper_last_damage_time = getTime(); + return; + } + else + { + if ( isDefined( is_footchop ) && is_footchop ) + { + if ( isDefined( ent.no_gib ) && !ent.no_gib ) + { + ent.a.gib_ref = "no_legs"; + ent thread maps/mp/animscripts/zm_death::do_gib(); + ent.has_legs = 0; + ent allowedstances( "crouch" ); + ent setphysparams( 15, 0, 24 ); + ent allowpitchangle( 1 ); + ent setpitchorient(); + ent thread maps/mp/animscripts/zm_run::needsdelayedupdate(); + if ( isDefined( ent.crawl_anim_override ) ) + { + ent [[ ent.crawl_anim_override ]](); + } + } + if ( ent.health <= 10 ) + { + ent playsound( "zmb_exp_jib_headchopper_zombie" ); + weapon.headchopper_kills++; + self thread headchopper_kill_vo( ent ); + } + ent dodamage( 10, weapon.origin ); + ent.headchopper_last_damage_time = getTime(); + } + } + } +} + +headchopper_kill_vo( zombie ) +{ + self endon( "disconnect" ); + if ( !isDefined( zombie ) ) + { + return; + } + if ( distance2dsquared( self.origin, zombie.origin ) < 1000000 ) + { + if ( self is_player_looking_at( zombie.origin, 0,25 ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "headchopper" ); + } + } +} + +wait_for_targets( weapon ) +{ + weapon endon( "hi_priority_target" ); + while ( isDefined( weapon ) ) + { + if ( isDefined( weapon.chop_targets ) && weapon.chop_targets.size > 0 ) + { + wait 0,075; + return; + } + wait 0,05; + } +} + +targeting_thread( weapon, trigger ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_headchopper_zm_taken" ); + weapon endon( "death" ); + weapon.zombies_only = 1; + while ( isDefined( weapon ) ) + { + if ( weapon.is_armed || isDefined( weapon.is_slicing ) && weapon.is_slicing ) + { + if ( isDefined( weapon.is_slicing ) && weapon.is_slicing ) + { + weapon waittill( "slice_done" ); + } + zombies = getaiarray( level.zombie_team ); + _a922 = zombies; + _k922 = getFirstArrayKey( _a922 ); + while ( isDefined( _k922 ) ) + { + zombie = _a922[ _k922 ]; + if ( !isDefined( zombie ) || !isalive( zombie ) ) + { + } + else + { + if ( isDefined( zombie.ignore_headchopper ) && zombie.ignore_headchopper ) + { + break; + } + else + { + if ( zombie istouching( trigger ) ) + { + weapon headchopper_add_chop_ent( zombie ); + } + } + } + _k922 = getNextArrayKey( _a922, _k922 ); + } + players = get_players(); + _a950 = players; + _k950 = getFirstArrayKey( _a950 ); + while ( isDefined( _k950 ) ) + { + player = _a950[ _k950 ]; + if ( is_player_valid( player ) && player istouching( trigger ) ) + { + weapon headchopper_add_chop_ent( player ); + weapon.zombies_only = 0; + } + _k950 = getNextArrayKey( _a950, _k950 ); + } + if ( !weapon.zombies_only ) + { + weapon notify( "hi_priority_target" ); + } + } + wait 0,05; + } +} + +headchopper_add_chop_ent( ent ) +{ + self.chop_targets = add_to_array( self.chop_targets, ent, 0 ); +} + +headchopper_expired( weapon, usedestroyfx ) +{ + if ( !isDefined( usedestroyfx ) ) + { + usedestroyfx = 1; + } + weapon maps/mp/zombies/_zm_equipment::dropped_equipment_destroy( usedestroyfx ); + self maps/mp/zombies/_zm_equipment::equipment_release( level.headchopper_name ); + self.headchopper_kills = 0; +} + +headchopperthinkcleanup( trigger ) +{ + self waittill( "death" ); + if ( isDefined( trigger ) ) + { + trigger delete(); + } +} + +destroyheadchopperonplantedblockeropen( trigger ) +{ + self endon( "death" ); + home_origin = self.planted_on_ent.origin; + home_angles = self.planted_on_ent.angles; + while ( isDefined( self.planted_on_ent ) ) + { + if ( self.planted_on_ent.origin != home_origin || self.planted_on_ent.angles != home_angles ) + { + break; + } + else + { + wait 0,5; + } + } + self.owner thread headchopper_expired( self, 0 ); +} + +destroyheadchopperonplantedentitydeath() +{ + self endon( "death" ); + self.planted_on_ent waittill( "death" ); + self.owner thread headchopper_expired( self, 0 ); +} + +destroyheadchopperstouching( usedestroyfx ) +{ + headchoppers = self getheadchopperstouching(); + _a1031 = headchoppers; + _k1031 = getFirstArrayKey( _a1031 ); + while ( isDefined( _k1031 ) ) + { + headchopper = _a1031[ _k1031 ]; + headchopper.owner thread headchopper_expired( headchopper, usedestroyfx ); + _k1031 = getNextArrayKey( _a1031, _k1031 ); + } +} + +getheadchopperstouching() +{ + headchoppers = []; + players = get_players(); + _a1043 = players; + _k1043 = getFirstArrayKey( _a1043 ); + while ( isDefined( _k1043 ) ) + { + player = _a1043[ _k1043 ]; + if ( isDefined( player.buildableheadchopper ) ) + { + chopper = player.buildableheadchopper; + if ( isDefined( chopper.planted_on_ent ) && chopper.planted_on_ent == self ) + { + headchoppers[ headchoppers.size ] = chopper; + break; + } + else + { + if ( chopper istouching( self ) ) + { + headchoppers[ headchoppers.size ] = chopper; + break; + } + else if ( distance2dsquared( chopper.origin, self.origin ) > 16384 ) + { + break; + } + else + { + fwdangles = anglesToUp( chopper.angles ); + traceback = groundtrace( chopper.origin + ( fwdangles * 5 ), chopper.origin - ( fwdangles * 999999 ), 0, chopper ); + if ( isDefined( traceback ) && isDefined( traceback[ "entity" ] ) && traceback[ "entity" ] == self ) + { + headchoppers[ headchoppers.size ] = chopper; + } + } + } + } + _k1043 = getNextArrayKey( _a1043, _k1043 ); + } + return headchoppers; +} + +getheadchoppersnear( source_origin, max_distance ) +{ + if ( !isDefined( max_distance ) ) + { + max_distance = 128; + } + headchoppers = []; + players = get_players(); + _a1096 = players; + _k1096 = getFirstArrayKey( _a1096 ); + while ( isDefined( _k1096 ) ) + { + player = _a1096[ _k1096 ]; + if ( isDefined( player.buildableheadchopper ) ) + { + chopper = player.buildableheadchopper; + if ( distancesquared( chopper.origin, source_origin ) < ( max_distance * max_distance ) ) + { + headchoppers[ headchoppers.size ] = chopper; + } + } + _k1096 = getNextArrayKey( _a1096, _k1096 ); + } + return headchoppers; +} + +check_headchopper_in_bad_area( origin ) +{ + if ( !isDefined( level.headchopper_bad_areas ) ) + { + level.headchopper_bad_areas = getentarray( "headchopper_bad_area", "targetname" ); + } + scr_org = spawn( "script_origin", origin ); + in_bad_area = 0; + _a1122 = level.headchopper_bad_areas; + _k1122 = getFirstArrayKey( _a1122 ); + while ( isDefined( _k1122 ) ) + { + area = _a1122[ _k1122 ]; + if ( scr_org istouching( area ) ) + { + in_bad_area = 1; + break; + } + else + { + _k1122 = getNextArrayKey( _a1122, _k1122 ); + } + } + scr_org delete(); + return in_bad_area; +} + +debugheadchopper( radius ) +{ +/# + color_armed = ( 0, 0, 1 ); + color_unarmed = vectorScale( ( 0, 0, 1 ), 0,65 ); + while ( isDefined( self ) ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + if ( isDefined( self.trigger ) ) + { + color = color_unarmed; + if ( isDefined( self.is_armed ) && self.is_armed ) + { + color = color_armed; + } + vec = self.trigger.extent; + box( self.trigger.origin, vec * -1, vec, self.trigger.angles[ 1 ], color, 1, 0, 1 ); + } + color = ( 0, 0, 1 ); + text = ""; + if ( isDefined( self.headchopper_kills ) ) + { + text = "" + self.headchopper_kills + ""; + } + else + { + if ( isDefined( self.owner.headchopper_kills ) ) + { + text = "[ " + self.owner.headchopper_kills + " ]"; + } + } + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 30 ), text, color, 1, 0,5, 1 ); + } + wait 0,05; +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_equip_springpad.gsc b/zm_buried_patch/maps/mp/zombies/_zm_equip_springpad.gsc new file mode 100644 index 0000000..7715df8 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_equip_springpad.gsc @@ -0,0 +1,631 @@ +#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; + +#using_animtree( "zombie_springpad" ); + +init( pickupstring, howtostring ) +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_springpad_zm" ) ) + { + return; + } + level.springpad_name = "equip_springpad_zm"; + init_animtree(); + maps/mp/zombies/_zm_equipment::register_equipment( "equip_springpad_zm", pickupstring, howtostring, "zom_hud_trample_steam_complete", "springpad", undefined, ::transferspringpad, ::dropspringpad, ::pickupspringpad, ::placespringpad ); + maps/mp/zombies/_zm_equipment::add_placeable_equipment( "equip_springpad_zm", "p6_anim_zm_buildable_view_tramplesteam" ); + level thread onplayerconnect(); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "equip_springpad", pickupstring ); + level._effect[ "springpade_on" ] = loadfx( "maps/zombie_highrise/fx_highrise_trmpl_steam_os" ); + if ( !isDefined( level.springpad_trigger_radius ) ) + { + level.springpad_trigger_radius = 72; + } + thread wait_init_damage(); +} + +wait_init_damage() +{ + while ( !isDefined( level.zombie_vars ) || !isDefined( level.zombie_vars[ "zombie_health_start" ] ) ) + { + wait 1; + } + level.springpad_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 watchspringpaduse(); + } +} + +setupwatchers() +{ + self waittill( "weapon_watchers_created" ); + watcher = maps/mp/gametypes_zm/_weaponobjects::getweaponobjectwatcher( "equip_springpad" ); + watcher.onspawnretrievetriggers = ::maps/mp/zombies/_zm_equipment::equipment_onspawnretrievableweaponobject; +} + +watchspringpaduse() +{ + self notify( "watchSpringPadUse" ); + self endon( "watchSpringPadUse" ); + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_placed", weapon, weapname ); + if ( weapname == level.springpad_name ) + { + self cleanupoldspringpad(); + self.buildablespringpad = weapon; + self thread startspringpaddeploy( weapon ); + } + } +} + +cleanupoldspringpad() +{ + if ( isDefined( self.buildablespringpad ) ) + { + if ( isDefined( self.buildablespringpad.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildablespringpad.stub ); + self.buildablespringpad.stub = undefined; + } + self.buildablespringpad delete(); + self.springpad_kills = undefined; + } + if ( isDefined( level.springpad_sound_ent ) ) + { + level.springpad_sound_ent delete(); + level.springpad_sound_ent = undefined; + } +} + +watchforcleanup() +{ + self notify( "springpad_cleanup" ); + self endon( "springpad_cleanup" ); + self waittill_any( "death_or_disconnect", "equip_springpad_zm_taken", "equip_springpad_zm_pickup" ); + cleanupoldspringpad(); +} + +placespringpad( origin, angles ) +{ + if ( isDefined( self.turret_placement ) && !self.turret_placement[ "result" ] ) + { + forward = anglesToForward( angles ); + origin -= -24 * forward; + } + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "p6_anim_zm_buildable_tramplesteam", "equip_springpad_zm", origin, angles, level.springpad_trigger_radius, -24 ); + if ( isDefined( item ) ) + { + item.springpad_kills = self.springpad_kills; + item.requires_pickup = 1; + item.zombie_attack_callback = ::springpad_fling_attacker; + } + self.springpad_kills = undefined; + return item; +} + +dropspringpad() +{ + item = self maps/mp/zombies/_zm_equipment::dropped_equipment_think( "p6_anim_zm_buildable_tramplesteam", "equip_springpad_zm", self.origin, self.angles, level.springpad_trigger_radius, -24 ); + if ( isDefined( item ) ) + { + item.springpad_kills = self.springpad_kills; + item.requires_pickup = 1; + } + self.springpad_kills = undefined; + return item; +} + +pickupspringpad( item ) +{ + self.springpad_kills = item.springpad_kills; + item.springpad_kills = undefined; +} + +transferspringpad( fromplayer, toplayer ) +{ + buildablespringpad = toplayer.buildablespringpad; + toarmed = 0; + if ( isDefined( buildablespringpad ) ) + { + if ( isDefined( buildablespringpad.is_armed ) ) + { + toarmed = buildablespringpad.is_armed; + } + } + springpad_kills = toplayer.springpad_kills; + fromarmed = 0; + if ( isDefined( fromplayer.buildablespringpad ) ) + { + if ( isDefined( fromplayer.buildablespringpad.is_armed ) ) + { + fromarmed = fromplayer.buildablespringpad.is_armed; + } + } + toplayer.buildablespringpad = fromplayer.buildablespringpad; + toplayer.buildablespringpad.original_owner = toplayer; + toplayer.buildablespringpad.owner = toplayer; + toplayer notify( "equip_springpad_zm_taken" ); + toplayer.springpad_kills = fromplayer.springpad_kills; + toplayer thread startspringpaddeploy( toplayer.buildablespringpad, fromarmed ); + fromplayer.buildablespringpad = buildablespringpad; + fromplayer.springpad_kills = springpad_kills; + fromplayer notify( "equip_springpad_zm_taken" ); + if ( isDefined( fromplayer.buildablespringpad ) ) + { + fromplayer thread startspringpaddeploy( fromplayer.buildablespringpad, toarmed ); + fromplayer.buildablespringpad.original_owner = fromplayer; + fromplayer.buildablespringpad.owner = fromplayer; + } + else + { + fromplayer maps/mp/zombies/_zm_equipment::equipment_release( "equip_springpad_zm" ); + } +} + +springpad_in_range( delta, origin, radius ) +{ + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +springpad_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(); +} + +springpad_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: trap off\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 0; +} + +startspringpaddeploy( weapon, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_springpad_zm_taken" ); + self thread watchforcleanup(); + electricradius = 45; + if ( isDefined( self.springpad_kills ) ) + { + weapon.springpad_kills = self.springpad_kills; + self.springpad_kills = undefined; + } + if ( !isDefined( weapon.springpad_kills ) ) + { + weapon.springpad_kills = 0; + } + if ( isDefined( weapon ) ) + { +/# + weapon thread debugspringpad( electricradius ); +#/ + if ( isDefined( level.equipment_springpad_needs_power ) && level.equipment_springpad_needs_power ) + { + weapon.power_on = 0; + maps/mp/zombies/_zm_power::add_temp_powered_item( ::springpad_power_on, ::springpad_power_off, ::springpad_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 springpadthink( weapon, electricradius, armed ); + if ( isDefined( level.equipment_springpad_needs_power ) && !level.equipment_springpad_needs_power ) + { + } + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( weapon ); + weapon waittill( "death" ); + if ( isDefined( level.springpad_sound_ent ) ) + { + level.springpad_sound_ent playsound( "wpn_zmb_electrap_stop" ); + level.springpad_sound_ent delete(); + level.springpad_sound_ent = undefined; + } + self notify( "springpad_cleanup" ); + } +} + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +springpad_animate( weapon, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_springpad_zm_taken" ); + weapon endon( "death" ); + weapon useanimtree( -1 ); + f_animlength = getanimlength( %o_zombie_buildable_tramplesteam_reset_zombie ); + r_animlength = getanimlength( %o_zombie_buildable_tramplesteam_reset ); + l_animlength = getanimlength( %o_zombie_buildable_tramplesteam_launch ); + weapon thread springpad_audio(); + prearmed = 0; + if ( isDefined( armed ) && armed ) + { + prearmed = 1; + } + fast_reset = 0; + while ( isDefined( weapon ) ) + { + if ( !prearmed ) + { + if ( fast_reset ) + { + weapon setanim( %o_zombie_buildable_tramplesteam_reset_zombie ); + weapon thread playspringpadresetaudio( f_animlength ); + wait f_animlength; + } + else + { + weapon setanim( %o_zombie_buildable_tramplesteam_reset ); + weapon thread playspringpadresetaudio( r_animlength ); + wait r_animlength; + } + } + else + { + wait 0,05; + } + prearmed = 0; + weapon notify( "armed" ); + fast_reset = 0; + if ( isDefined( weapon ) ) + { + weapon setanim( %o_zombie_buildable_tramplesteam_compressed_idle ); + weapon waittill( "fling", fast ); + fast_reset = fast; + } + if ( isDefined( weapon ) ) + { + weapon setanim( %o_zombie_buildable_tramplesteam_launch ); + wait l_animlength; + } + } +} + +playspringpadresetaudio( time ) +{ + self endon( "springpadAudioCleanup" ); + ent = spawn( "script_origin", self.origin ); + ent playloopsound( "zmb_highrise_launcher_reset_loop" ); + self thread deleteentwhensounddone( time, ent ); + self waittill( "death" ); + ent delete(); +} + +deleteentwhensounddone( time, ent ) +{ + self endon( "death" ); + wait time; + self notify( "springpadAudioCleanup" ); + ent delete(); +} + +springpad_audio() +{ + loop_ent = spawn( "script_origin", self.origin ); + loop_ent playloopsound( "zmb_highrise_launcher_loop" ); + self waittill( "death" ); + loop_ent delete(); +} + +springpad_fx( weapon ) +{ + weapon endon( "death" ); + self endon( "equip_springpad_zm_taken" ); + while ( isDefined( weapon ) ) + { + playfxontag( level._effect[ "springpade_on" ], weapon, "tag_origin" ); + wait 1; + } +} + +springpadthink( weapon, electricradius, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_springpad_zm_taken" ); + weapon endon( "death" ); + radiussquared = electricradius * electricradius; + trigger = spawn( "trigger_box", weapon getcentroid(), 1, 48, 48, 32 ); + trigger.origin += anglesToForward( flat_angle( weapon.angles ) ) * -15; + trigger.angles = weapon.angles; + trigger enablelinkto(); + trigger linkto( weapon ); + weapon.trigger = trigger; +/# + trigger.extent = ( 24, 24, 16 ); +#/ + weapon thread springpadthinkcleanup( trigger ); + direction_forward = anglesToForward( flat_angle( weapon.angles ) + vectorScale( ( 0, 0, 1 ), 60 ) ); + direction_vector = vectorScale( direction_forward, 1024 ); + direction_origin = weapon.origin + direction_vector; + home_angles = weapon.angles; + weapon.is_armed = 0; + self thread springpad_fx( weapon ); + self thread springpad_animate( weapon, armed ); + weapon waittill( "armed" ); + weapon.is_armed = 1; + weapon.fling_targets = []; + self thread targeting_thread( weapon, trigger ); + while ( isDefined( weapon ) ) + { + wait_for_targets( weapon ); + if ( isDefined( weapon.fling_targets ) && weapon.fling_targets.size > 0 ) + { + weapon notify( "fling" ); + weapon.is_armed = 0; + weapon.zombies_only = 1; + _a490 = weapon.fling_targets; + _k490 = getFirstArrayKey( _a490 ); + while ( isDefined( _k490 ) ) + { + ent = _a490[ _k490 ]; + if ( isplayer( ent ) ) + { + ent thread player_fling( weapon.origin + vectorScale( ( 0, 0, 1 ), 30 ), weapon.angles, direction_vector, weapon ); + } + else if ( isDefined( ent ) && isDefined( ent.custom_springpad_fling ) ) + { + if ( !isDefined( self.num_zombies_flung ) ) + { + self.num_zombies_flung = 0; + } + self.num_zombies_flung++; + self notify( "zombie_flung" ); + ent thread [[ ent.custom_springpad_fling ]]( weapon, self ); + } + else + { + if ( isDefined( ent ) ) + { + if ( !isDefined( self.num_zombies_flung ) ) + { + self.num_zombies_flung = 0; + } + self.num_zombies_flung++; + self notify( "zombie_flung" ); + if ( !isDefined( weapon.fling_scaler ) ) + { + weapon.fling_scaler = 1; + } + if ( isDefined( weapon.direction_vec_override ) ) + { + direction_vector = weapon.direction_vec_override; + } + ent dodamage( ent.health + 666, ent.origin ); + ent startragdoll(); + ent launchragdoll( ( direction_vector / 4 ) * weapon.fling_scaler ); + weapon.springpad_kills++; + } + } + _k490 = getNextArrayKey( _a490, _k490 ); + } + if ( weapon.springpad_kills >= 28 ) + { + self thread springpad_expired( weapon ); + } + weapon.fling_targets = []; + weapon waittill( "armed" ); + weapon.is_armed = 1; + continue; + } + else + { + wait 0,1; + } + } +} + +wait_for_targets( weapon ) +{ + weapon endon( "hi_priority_target" ); + while ( isDefined( weapon ) ) + { + if ( isDefined( weapon.fling_targets ) && weapon.fling_targets.size > 0 ) + { + wait 0,15; + return; + } + wait 0,05; + } +} + +targeting_thread( weapon, trigger ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_springpad_zm_taken" ); + weapon endon( "death" ); + weapon.zombies_only = 1; + while ( isDefined( weapon ) ) + { + if ( weapon.is_armed ) + { + zombies = getaiarray( level.zombie_team ); + _a577 = zombies; + _k577 = getFirstArrayKey( _a577 ); + while ( isDefined( _k577 ) ) + { + zombie = _a577[ _k577 ]; + if ( !isDefined( zombie ) || !isalive( zombie ) ) + { + } + else + { + if ( isDefined( zombie.ignore_spring_pad ) && zombie.ignore_spring_pad ) + { + break; + } + else + { + if ( zombie istouching( trigger ) ) + { + weapon springpad_add_fling_ent( zombie ); + } + } + } + _k577 = getNextArrayKey( _a577, _k577 ); + } + players = get_players(); + _a605 = players; + _k605 = getFirstArrayKey( _a605 ); + while ( isDefined( _k605 ) ) + { + player = _a605[ _k605 ]; + if ( is_player_valid( player ) && player istouching( trigger ) ) + { + weapon springpad_add_fling_ent( player ); + weapon.zombies_only = 0; + } + _k605 = getNextArrayKey( _a605, _k605 ); + } + if ( !weapon.zombies_only ) + { + weapon notify( "hi_priority_target" ); + } + } + wait 0,05; + } +} + +springpad_fling_attacker( ent ) +{ + springpad_add_fling_ent( ent ); + if ( isDefined( level.springpad_attack_delay ) ) + { + wait level.springpad_attack_delay; + } +} + +springpad_add_fling_ent( ent ) +{ + self.fling_targets = add_to_array( self.fling_targets, ent, 0 ); +} + +springpad_expired( weapon ) +{ + weapon maps/mp/zombies/_zm_equipment::dropped_equipment_destroy( 1 ); + self maps/mp/zombies/_zm_equipment::equipment_release( "equip_springpad_zm" ); + self.springpad_kills = 0; +} + +player_fling( origin, angles, velocity, weapon ) +{ + torigin = ( self.origin[ 0 ], self.origin[ 1 ], origin[ 2 ] ); + aorigin = ( origin + torigin ) * 0,5; + trace = physicstrace( origin, torigin, vectorScale( ( 0, 0, 1 ), 15 ), ( 15, 15, 30 ), self ); + if ( isDefined( trace ) || !isDefined( trace[ "fraction" ] ) && trace[ "fraction" ] < 1 ) + { + if ( !isDefined( weapon.springpad_kills ) ) + { + weapon.springpad_kills = 0; + } + weapon.springpad_kills += 5; + if ( weapon.springpad_kills >= 28 ) + { + weapon.owner thread springpad_expired( weapon ); + } + return; + } + self setorigin( aorigin ); + wait_network_frame(); + self setvelocity( velocity ); +} + +springpadthinkcleanup( trigger ) +{ + self waittill( "death" ); + if ( isDefined( trigger ) ) + { + trigger delete(); + } +} + +debugspringpad( radius ) +{ +/# + color_armed = ( 0, 0, 1 ); + color_unarmed = vectorScale( ( 0, 0, 1 ), 0,65 ); + while ( isDefined( self ) ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + if ( isDefined( self.trigger ) ) + { + color = color_unarmed; + if ( isDefined( self.is_armed ) && self.is_armed ) + { + color = color_armed; + } + vec = self.trigger.extent; + box( self.trigger.origin, vec * -1, vec, self.trigger.angles[ 1 ], color, 1, 0, 1 ); + } + color = ( 0, 0, 1 ); + text = ""; + if ( isDefined( self.springpad_kills ) ) + { + text = "" + self.springpad_kills + ""; + } + else + { + if ( isDefined( self.owner.springpad_kills ) ) + { + text = "[" + self.owner.springpad_kills + "]"; + } + } + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 30 ), text, color, 1, 0,5, 1 ); + } + wait 0,05; +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_equip_subwoofer.gsc b/zm_buried_patch/maps/mp/zombies/_zm_equip_subwoofer.gsc new file mode 100644 index 0000000..53fc0b3 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_equip_subwoofer.gsc @@ -0,0 +1,992 @@ +#include maps/mp/animscripts/zm_shared; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_audio; +#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( pickupstring, howtostring ) +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_subwoofer_zm" ) ) + { + return; + } + level.subwoofer_name = "equip_subwoofer_zm"; + precacherumble( "subwoofer_light" ); + precacherumble( "subwoofer_medium" ); + precacherumble( "subwoofer_heavy" ); + init_animtree(); + maps/mp/zombies/_zm_equipment::register_equipment( level.subwoofer_name, pickupstring, howtostring, "zom_hud_subwoofer_complete", "subwoofer", undefined, ::transfersubwoofer, ::dropsubwoofer, ::pickupsubwoofer, ::placesubwoofer ); + maps/mp/zombies/_zm_equipment::add_placeable_equipment( level.subwoofer_name, "t6_wpn_turret_zmb_subwoofer_view" ); + level thread onplayerconnect(); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "equip_subwoofer", pickupstring ); + level._effect[ "subwoofer_on" ] = loadfx( "maps/zombie_highrise/fx_highrise_trmpl_steam_os" ); + level._effect[ "subwoofer_audio_wave" ] = loadfx( "maps/zombie_buried/fx_buried_subwoofer_blast" ); + level._effect[ "subwoofer_knockdown_ground" ] = loadfx( "weapon/thunder_gun/fx_thundergun_knockback_ground" ); + level._effect[ "subwoofer_disappear" ] = loadfx( "maps/zombie/fx_zmb_tranzit_turbine_explo" ); + level.subwoofer_gib_refs = []; + level.subwoofer_gib_refs[ level.subwoofer_gib_refs.size ] = "guts"; + level.subwoofer_gib_refs[ level.subwoofer_gib_refs.size ] = "right_arm"; + level.subwoofer_gib_refs[ level.subwoofer_gib_refs.size ] = "left_arm"; + registerclientfield( "actor", "subwoofer_flings_zombie", 12000, 1, "int" ); + thread wait_init_damage(); +} + +wait_init_damage() +{ + while ( !isDefined( level.zombie_vars ) || !isDefined( level.zombie_vars[ "zombie_health_start" ] ) ) + { + wait 1; + } + level.subwoofer_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 watchsubwooferuse(); + } +} + +setupwatchers() +{ + self waittill( "weapon_watchers_created" ); + watcher = maps/mp/gametypes_zm/_weaponobjects::getweaponobjectwatcher( "equip_subwoofer" ); + watcher.onspawnretrievetriggers = ::maps/mp/zombies/_zm_equipment::equipment_onspawnretrievableweaponobject; +} + +watchsubwooferuse() +{ + self notify( "watchSubwooferUse" ); + self endon( "watchSubwooferUse" ); + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_placed", weapon, weapname ); + if ( weapname == level.subwoofer_name ) + { + self cleanupoldsubwoofer(); + self.buildablesubwoofer = weapon; + self thread startsubwooferdeploy( weapon ); + } + } +} + +cleanupoldsubwoofer( preserve_state ) +{ + if ( isDefined( self.buildablesubwoofer ) ) + { + if ( isDefined( self.buildablesubwoofer.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildablesubwoofer.stub ); + self.buildablesubwoofer.stub = undefined; + } + self.buildablesubwoofer delete(); + self.subwoofer_kills = undefined; + if ( isDefined( preserve_state ) && !preserve_state ) + { + self.subwoofer_health = undefined; + self.subwoofer_emped = undefined; + self.subwoofer_emp_time = undefined; + } + } + if ( isDefined( level.subwoofer_sound_ent ) ) + { + level.subwoofer_sound_ent delete(); + level.subwoofer_sound_ent = undefined; + } +} + +watchforcleanup() +{ + self notify( "subwoofer_cleanup" ); + self endon( "subwoofer_cleanup" ); + evt = self waittill_any_return( "death_or_disconnect", "equip_subwoofer_zm_taken", "equip_subwoofer_zm_pickup" ); + if ( isDefined( self ) ) + { + self cleanupoldsubwoofer( evt == "equip_subwoofer_zm_pickup" ); + } +} + +placesubwoofer( origin, angles ) +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "t6_wpn_zmb_subwoofer", level.subwoofer_name, origin, angles, 32, 0 ); + if ( isDefined( item ) ) + { + item.subwoofer_kills = self.subwoofer_kills; + item.requires_pickup = 1; + } + self.subwoofer_kills = undefined; + return item; +} + +dropsubwoofer() +{ + item = self maps/mp/zombies/_zm_equipment::dropped_equipment_think( "t6_wpn_zmb_subwoofer", level.subwoofer_name, self.origin, self.angles, 32, 0 ); + if ( isDefined( item ) ) + { + item.subwoofer_kills = self.subwoofer_kills; + item.requires_pickup = 1; + item.subwoofer_power_on = self.subwoofer_power_on; + item.subwoofer_power_level = self.subwoofer_power_level; + item.subwoofer_round_start = self.subwoofer_round_start; + item.subwoofer_health = self.subwoofer_health; + item.subwoofer_emped = self.subwoofer_emped; + item.subwoofer_emp_time = self.subwoofer_emp_time; + } + self.subwoofer_kills = undefined; + self.subwoofer_is_powering_on = undefined; + self.subwoofer_power_on = undefined; + self.subwoofer_power_level = undefined; + self.subwoofer_round_start = undefined; + self.subwoofer_health = undefined; + self.subwoofer_emped = undefined; + self.subwoofer_emp_time = undefined; + return item; +} + +pickupsubwoofer( item ) +{ + self.subwoofer_kills = item.subwoofer_kills; + item.subwoofer_kills = undefined; +} + +transfersubwoofer( fromplayer, toplayer ) +{ + buildablesubwoofer = toplayer.buildablesubwoofer; + toarmed = 0; + if ( isDefined( buildablesubwoofer ) ) + { + if ( isDefined( buildablesubwoofer.is_armed ) ) + { + toarmed = buildablesubwoofer.is_armed; + } + } + subwoofer_kills = toplayer.subwoofer_kills; + fromarmed = 0; + if ( isDefined( fromplayer.buildablesubwoofer ) ) + { + if ( isDefined( fromplayer.buildablesubwoofer.is_armed ) ) + { + fromarmed = fromplayer.buildablesubwoofer.is_armed; + } + } + toplayer.buildablesubwoofer = fromplayer.buildablesubwoofer; + subwoofer_power_on = toplayer.subwoofer_power_on; + subwoofer_power_level = toplayer.subwoofer_power_level; + subwoofer_round_start = toplayer.subwoofer_round_start; + subwoofer_health = toplayer.subwoofer_health; + subwoofer_emped = toplayer.subwoofer_emped; + subwoofer_emp_time = toplayer.subwoofer_emp_time; + toplayer.buildablesubwoofer = fromplayer.buildablesubwoofer; + fromplayer.buildablesubwoofer = buildablesubwoofer; + toplayer.subwoofer_emped = fromplayer.subwoofer_emped; + fromplayer.subwoofer_emped = subwoofer_emped; + toplayer.subwoofer_emp_time = fromplayer.subwoofer_emp_time; + fromplayer.subwoofer_emp_time = subwoofer_emp_time; + toplayer.subwoofer_is_powering_on = undefined; + fromplayer.subwoofer_is_powering_on = undefined; + toplayer.subwoofer_power_on = fromplayer.subwoofer_power_on; + fromplayer.subwoofer_power_on = subwoofer_power_on; + toplayer.subwoofer_power_level = fromplayer.subwoofer_power_level; + toplayer.subwoofer_round_start = fromplayer.subwoofer_round_start; + fromplayer.subwoofer_power_level = subwoofer_power_level; + fromplayer.subwoofer_round_start = subwoofer_round_start; + toplayer.subwoofer_health = fromplayer.subwoofer_health; + fromplayer.subwoofer_health = subwoofer_health; + toplayer.buildablesubwoofer.original_owner = toplayer; + toplayer.buildablesubwoofer.owner = toplayer; + toplayer notify( "equip_subwoofer_zm_taken" ); + toplayer.subwoofer_kills = fromplayer.subwoofer_kills; + toplayer thread startsubwooferdeploy( toplayer.buildablesubwoofer, fromarmed ); + fromplayer.subwoofer_kills = subwoofer_kills; + fromplayer notify( "equip_subwoofer_zm_taken" ); + if ( isDefined( fromplayer.buildablesubwoofer ) ) + { + fromplayer thread startsubwooferdeploy( fromplayer.buildablesubwoofer, toarmed ); + fromplayer.buildablesubwoofer.original_owner = fromplayer; + fromplayer.buildablesubwoofer.owner = fromplayer; + } + else + { + fromplayer maps/mp/zombies/_zm_equipment::equipment_release( level.subwoofer_name ); + } +} + +subwoofer_in_range( delta, origin, radius ) +{ + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +subwoofer_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.owner thread subwooferthink( self.target ); +} + +subwoofer_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: trap off\n" ); +#/ + if ( !isDefined( self.target ) ) + { + return; + } + self.target.power_on = 0; +} + +subwoofer_cost() +{ + return maps/mp/zombies/_zm_power::cost_high() / 2; +} + +startsubwooferdeploy( weapon, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_subwoofer_zm_taken" ); + self thread watchforcleanup(); + if ( isDefined( self.subwoofer_kills ) ) + { + weapon.subwoofer_kills = self.subwoofer_kills; + self.subwoofer_kills = undefined; + } + if ( !isDefined( weapon.subwoofer_kills ) ) + { + weapon.subwoofer_kills = 0; + } + if ( !isDefined( self.subwoofer_health ) ) + { + self.subwoofer_health = 60; + self.subwoofer_power_level = 4; + } + if ( isDefined( weapon ) ) + { +/# + self thread debugsubwoofer(); +#/ + if ( isDefined( level.equipment_subwoofer_needs_power ) && level.equipment_subwoofer_needs_power ) + { + weapon.power_on = 0; + maps/mp/zombies/_zm_power::add_temp_powered_item( ::subwoofer_power_on, ::subwoofer_power_off, ::subwoofer_in_range, ::subwoofer_cost, 1, weapon.power_on, weapon ); + } + else + { + weapon.power_on = 1; + } + if ( weapon.power_on ) + { + self thread subwooferthink( weapon, armed ); + } + else + { + self iprintlnbold( &"ZOMBIE_NEED_LOCAL_POWER" ); + } + if ( isDefined( level.equipment_subwoofer_needs_power ) && !level.equipment_subwoofer_needs_power ) + { + self thread startsubwooferdecay( weapon ); + } + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( weapon ); + weapon waittill( "death" ); + if ( isDefined( level.subwoofer_sound_ent ) ) + { + level.subwoofer_sound_ent playsound( "wpn_zmb_electrap_stop" ); + level.subwoofer_sound_ent delete(); + level.subwoofer_sound_ent = undefined; + } + self notify( "subwoofer_cleanup" ); + } +} + +startsubwooferdecay( weapon ) +{ + self notify( "subwooferDecay" ); + self endon( "subwooferDecay" ); + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_subwoofer_zm_taken" ); + weapon endon( "death" ); + roundlives = 4; + if ( !isDefined( self.subwoofer_power_level ) ) + { + self.subwoofer_power_level = roundlives; + } + while ( weapon.subwoofer_kills < 45 ) + { + old_power_level = self.subwoofer_power_level; + if ( isDefined( self.subwoofer_emped ) && self.subwoofer_emped && isDefined( self.subwoofer_is_powering_on ) && !self.subwoofer_is_powering_on ) + { + emp_time = level.zombie_vars[ "emp_perk_off_time" ]; + now = getTime(); + emp_time_left = emp_time - ( ( now - self.subwoofer_emp_time ) / 1000 ); + if ( emp_time_left <= 0 ) + { + self.subwoofer_emped = undefined; + self.subwoofer_emp_time = undefined; + old_power_level = -1; + } + } + if ( isDefined( self.subwoofer_emped ) && self.subwoofer_emped ) + { + self.subwoofer_power_level = 0; + } + cost = 1; + if ( weapon.subwoofer_kills > 30 ) + { + self.subwoofer_power_level = 1; + if ( isDefined( weapon.low_health_sparks ) && !weapon.low_health_sparks ) + { + weapon.low_health_sparks = 1; + playfxontag( level._effect[ "switch_sparks" ], weapon, "tag_origin" ); + } + } + else if ( weapon.subwoofer_kills > 15 ) + { + self.subwoofer_power_level = 2; + } + else + { + self.subwoofer_power_level = 4; + } + if ( old_power_level != self.subwoofer_power_level ) + { + self notify( "subwoofer_power_change" ); + } + wait 1; + } + if ( isDefined( weapon ) ) + { + self destroy_placed_subwoofer(); + subwoofer_disappear_fx( weapon ); + } + self thread wait_and_take_equipment(); + self.subwoofer_health = undefined; + self.subwoofer_power_level = undefined; + self.subwoofer_round_start = undefined; + self.subwoofer_power_on = undefined; + self.subwoofer_emped = undefined; + self.subwoofer_emp_time = undefined; + self cleanupoldsubwoofer(); +} + +destroy_placed_subwoofer() +{ + if ( isDefined( self.buildablesubwoofer ) ) + { + if ( isDefined( self.buildablesubwoofer.dying ) && self.buildablesubwoofer.dying ) + { + while ( isDefined( self.buildablesubwoofer ) ) + { + wait 0,05; + } + return; + } + if ( isDefined( self.buildablesubwoofer.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildablesubwoofer.stub ); + } + thread subwoofer_disappear_fx( self.buildablesubwoofer, 0,75 ); + self.buildablesubwoofer.dying = 1; + } +} + +wait_and_take_equipment() +{ + wait 0,05; + self thread maps/mp/zombies/_zm_equipment::equipment_release( level.subwoofer_name ); +} + +init_animtree() +{ +} + +subwoofer_fx( weapon ) +{ + weapon endon( "death" ); + self endon( "equip_subwoofer_zm_taken" ); + while ( isDefined( weapon ) ) + { + wait 1; + } +} + +subwoofer_disappear_fx( weapon, waittime ) +{ + if ( isDefined( waittime ) && waittime > 0 ) + { + wait waittime; + } + if ( isDefined( weapon ) ) + { + playfx( level._effect[ "subwoofer_disappear" ], weapon.origin ); + } +} + +subwoofer_choke() +{ + while ( 1 ) + { + level._subwoofer_choke = 0; + wait_network_frame(); + } +} + +subwooferthink( weapon, armed ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_subwoofer_zm_taken" ); + weapon notify( "subwooferthink" ); + weapon endon( "subwooferthink" ); + weapon endon( "death" ); + direction_forward = anglesToForward( flat_angle( weapon.angles ) + vectorScale( ( 0, 0, 1 ), 30 ) ); + direction_vector = vectorScale( direction_forward, 512 ); + direction_origin = weapon.origin + direction_vector; + original_angles = weapon.angles; + original_origin = weapon.origin; + tag_spin_origin = weapon gettagorigin( "tag_spin" ); + wait 0,05; + while ( 1 ) + { + while ( isDefined( weapon.power_on ) && !weapon.power_on ) + { + wait 1; + } + wait 2; + if ( isDefined( weapon.power_on ) && !weapon.power_on ) + { + continue; + } + if ( !isDefined( level._subwoofer_choke ) ) + { + level thread subwoofer_choke(); + } + while ( level._subwoofer_choke ) + { + wait 0,05; + } + level._subwoofer_choke++; + weapon.subwoofer_network_choke_count = 0; + weapon thread maps/mp/zombies/_zm_equipment::signal_equipment_activated( 1 ); + vibrateamplitude = 4; + if ( self.subwoofer_power_level == 3 ) + { + vibrateamplitude = 8; + } + else + { + if ( self.subwoofer_power_level == 2 ) + { + vibrateamplitude = 13; + } + } + if ( self.subwoofer_power_level == 1 ) + { + vibrateamplitude = 17; + } + weapon vibrate( vectorScale( ( 0, 0, 1 ), 100 ), vibrateamplitude, 0,2, 0,3 ); + zombies = get_array_of_closest( weapon.origin, get_round_enemy_array(), undefined, undefined, 1200 ); + players = get_array_of_closest( weapon.origin, get_players(), undefined, undefined, 1200 ); + props = get_array_of_closest( weapon.origin, getentarray( "subwoofer_target", "script_noteworthy" ), undefined, undefined, 1200 ); + entities = arraycombine( zombies, players, 0, 0 ); + entities = arraycombine( entities, props, 0, 0 ); + _a681 = entities; + _k681 = getFirstArrayKey( _a681 ); + while ( isDefined( _k681 ) ) + { + ent = _a681[ _k681 ]; + if ( !isDefined( ent ) || !isplayer( ent ) && isai( ent ) && !isalive( ent ) ) + { + } + else + { + if ( isDefined( ent.ignore_subwoofer ) && ent.ignore_subwoofer ) + { + break; + } + else + { + distanceentityandsubwoofer = distance2dsquared( original_origin, ent.origin ); + onlydamage = 0; + action = undefined; + if ( distanceentityandsubwoofer <= 32400 ) + { + action = "burst"; + } + else if ( distanceentityandsubwoofer <= 230400 ) + { + action = "fling"; + } + else if ( distanceentityandsubwoofer <= 1440000 ) + { + action = "stumble"; + } + else + { + } + if ( !within_fov( original_origin, original_angles, ent.origin, cos( 45 ) ) ) + { + if ( isplayer( ent ) ) + { + ent hit_player( action, 0 ); + } + break; + } + else weapon subwoofer_network_choke(); + ent_trace_origin = ent.origin; + if ( isai( ent ) || isplayer( ent ) ) + { + ent_trace_origin = ent geteye(); + } + if ( isDefined( ent.script_noteworthy ) && ent.script_noteworthy == "subwoofer_target" ) + { + ent_trace_origin += vectorScale( ( 0, 0, 1 ), 48 ); + } + if ( !sighttracepassed( tag_spin_origin, ent_trace_origin, 1, weapon ) ) + { + break; + } + else if ( isDefined( ent.script_noteworthy ) && ent.script_noteworthy == "subwoofer_target" ) + { + ent notify( "damaged_by_subwoofer" ); + break; + } + else + { + if ( isDefined( ent.in_the_ground ) && !ent.in_the_ground && isDefined( ent.in_the_ceiling ) && !ent.in_the_ceiling && isDefined( ent.ai_state ) || ent.ai_state == "zombie_goto_entrance" && isDefined( ent.completed_emerging_into_playable_area ) && !ent.completed_emerging_into_playable_area ) + { + onlydamage = 1; + } + if ( isplayer( ent ) ) + { + ent notify( "player_" + action ); + ent hit_player( action, 1 ); + break; + } + else if ( isDefined( ent ) ) + { + ent notify( "zombie_" + action ); +/# + ent thread subwoofer_debug_print( action, ( 0, 0, 1 ) ); +#/ + shouldgib = distanceentityandsubwoofer <= 810000; + if ( action == "fling" ) + { + ent thread fling_zombie( weapon, direction_vector / 4, self, onlydamage ); + weapon.subwoofer_kills++; + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "subwoofer" ); + break; + } + else if ( action == "burst" ) + { + ent thread burst_zombie( weapon, self ); + weapon.subwoofer_kills++; + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "subwoofer" ); + break; + } + else + { + if ( action == "stumble" ) + { + ent thread knockdown_zombie( weapon, shouldgib, onlydamage ); + } + } + } + } + } + } + _k681 = getNextArrayKey( _a681, _k681 ); + } + if ( weapon.subwoofer_kills >= 45 ) + { + self thread subwoofer_expired( weapon ); + } + } +} + +subwoofer_expired( weapon ) +{ + weapon maps/mp/zombies/_zm_equipment::dropped_equipment_destroy( 1 ); + self maps/mp/zombies/_zm_equipment::equipment_release( level.subwoofer_name ); + self.subwoofer_kills = 0; +} + +hit_player( action, doshellshock ) +{ + if ( action == "burst" ) + { + self playrumbleonentity( "subwoofer_heavy" ); + if ( isDefined( doshellshock ) && doshellshock ) + { + self shellshock( "frag_grenade_mp", 1,5 ); + } + } + else if ( action == "fling" ) + { + self playrumbleonentity( "subwoofer_medium" ); + if ( isDefined( doshellshock ) && doshellshock ) + { + self shellshock( "frag_grenade_mp", 0,5 ); + } + } + else + { + if ( action == "stumble" ) + { + if ( isDefined( doshellshock ) && doshellshock ) + { + self playrumbleonentity( "subwoofer_light" ); + self shellshock( "frag_grenade_mp", 0,13 ); + } + } + } +} + +burst_zombie( weapon, player ) +{ + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( self.subwoofer_burst_func ) ) + { + self thread [[ self.subwoofer_burst_func ]]( weapon ); + return; + } + self dodamage( self.health + 666, weapon.origin ); + player notify( "zombie_subwoofer_kill" ); + if ( isDefined( self.guts_explosion ) && !self.guts_explosion ) + { + self.guts_explosion = 1; + self setclientfield( "zombie_gut_explosion", 1 ); + if ( isDefined( self.isdog ) && !self.isdog ) + { + wait 0,1; + } + self ghost(); + } +} + +fling_zombie( weapon, fling_vec, player, onlydamage ) +{ + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( self.subwoofer_fling_func ) ) + { + self thread [[ self.subwoofer_fling_func ]]( weapon, fling_vec ); + player notify( "zombie_subwoofer_kill" ); + return; + } + self dodamage( self.health + 666, weapon.origin ); + player notify( "zombie_subwoofer_kill" ); + if ( self.health <= 0 ) + { + if ( isDefined( onlydamage ) && !onlydamage ) + { + self startragdoll(); + self setclientfield( "subwoofer_flings_zombie", 1 ); + } + self.subwoofer_death = 1; + } +} + +knockdown_zombie( weapon, gib, onlydamage ) +{ + self endon( "death" ); + if ( isDefined( self.is_knocked_down ) && self.is_knocked_down ) + { + return; + } + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( self.subwoofer_knockdown_func ) ) + { + self thread [[ self.subwoofer_knockdown_func ]]( weapon, gib ); + return; + } + if ( isDefined( onlydamage ) && onlydamage ) + { + self thread knockdown_zombie_damage( weapon ); + return; + } + if ( gib && isDefined( self.gibbed ) && !self.gibbed ) + { + self thread knockdown_zombie_damage( weapon ); + self.a.gib_ref = random( level.subwoofer_gib_refs ); + self thread maps/mp/animscripts/zm_death::do_gib(); + } + self.subwoofer_handle_pain_notetracks = ::handle_subwoofer_pain_notetracks; + self thread knockdown_zombie_damage( weapon ); + self animcustom( ::knockdown_zombie_animate ); +} + +knockdown_zombie_damage( weapon ) +{ + if ( self.health <= 15 ) + { + weapon.subwoofer_kills++; + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "subwoofer" ); + } + self dodamage( 15, weapon.origin ); +} + +handle_subwoofer_pain_notetracks( note ) +{ + if ( note == "zombie_knockdown_ground_impact" ) + { + playfx( level._effect[ "subwoofer_knockdown_ground" ], self.origin, anglesToForward( self.angles ), anglesToUp( self.angles ) ); + } +} + +knockdown_zombie_animate() +{ + self notify( "end_play_subwoofer_pain_anim" ); + self endon( "killanimscript" ); + self endon( "death" ); + self endon( "end_play_subwoofer_pain_anim" ); + if ( isDefined( self.marked_for_death ) && self.marked_for_death ) + { + return; + } + if ( isDefined( self.has_legs ) && !self.has_legs ) + { + return; + } + if ( isDefined( self.barricade_enter ) && self.barricade_enter ) + { + return; + } + if ( !issubstr( self.animstatedef, "buried" ) ) + { + return; + } + animation_direction = undefined; + animation_side = undefined; + animation_duration = "_default"; + if ( self.damageyaw <= -135 || self.damageyaw >= 135 ) + { + animation_direction = "back"; + animation_side = "back"; + } + else + { + if ( self.damageyaw > -135 && self.damageyaw < -45 ) + { + animation_direction = "left"; + animation_side = "back"; + } + else + { + if ( self.damageyaw > 45 && self.damageyaw < 135 ) + { + animation_direction = "right"; + animation_side = "belly"; + } + else + { + animation_direction = "front"; + animation_side = "belly"; + } + } + } + wait randomfloatrange( 0,05, 0,35 ); + self thread knockdown_zombie_animate_state(); +/# + self thread subwoofer_debug_animation_print( animation_direction, animation_side ); +#/ + self setanimstatefromasd( "zm_subwoofer_fall_" + animation_direction ); + self maps/mp/animscripts/zm_shared::donotetracks( "subwoofer_fall_anim", self.subwoofer_handle_pain_notetracks ); + if ( isDefined( self ) && isalive( self ) && isDefined( self.has_legs ) || !self.has_legs && isDefined( self.marked_for_death ) && self.marked_for_death ) + { + return; + } + if ( isDefined( self.a.gib_ref ) ) + { + if ( self.a.gib_ref != "no_legs" && self.a.gib_ref != "no_arms" && self.a.gib_ref != "left_leg" && self.a.gib_ref == "right_leg" || randomint( 100 ) > 25 && self.a.gib_ref != "left_arm" && self.a.gib_ref == "right_arm" && randomint( 100 ) > 75 ) + { + animation_duration = "_late"; + } + else + { + if ( randomint( 100 ) > 75 ) + { + animation_duration = "_early"; + } + } + } + else + { + if ( randomint( 100 ) > 25 ) + { + animation_duration = "_early"; + } + } + self setanimstatefromasd( "zm_subwoofer_getup_" + animation_side + animation_duration ); + self maps/mp/animscripts/zm_shared::donotetracks( "subwoofer_getup_anim" ); + self notify( "back_up" ); +} + +knockdown_zombie_animate_state() +{ + self endon( "death" ); + self.is_knocked_down = 1; + self waittill_any( "damage", "back_up" ); + self.is_knocked_down = 0; +} + +subwoofer_network_choke() +{ + self.subwoofer_network_choke_count++; + if ( self.subwoofer_network_choke_count % 10 ) + { + wait_network_frame(); + } +} + +enemy_killed_by_subwoofer() +{ + if ( isDefined( self.subwoofer_death ) ) + { + return self.subwoofer_death; + } +} + +debugsubwoofer() +{ +/# + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_subwoofer_zm_taken" ); + self.buildablesubwoofer endon( "death" ); + red = ( 0, 0, 1 ); + green = ( 0, 0, 1 ); + blue = ( 0, 0, 1 ); + yellow = vectorScale( ( 0, 0, 1 ), 0,65 ); + while ( isDefined( self.buildablesubwoofer ) ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + row = 1; + health_color = green; + if ( self.subwoofer_power_level <= 1 ) + { + health_color = red; + } + else + { + if ( self.subwoofer_power_level <= 3 ) + { + health_color = yellow; + } + } + if ( isDefined( self.buildablesubwoofer.subwoofer_kills ) ) + { + row = self debugsubwooferprint3d( row, "Kills: " + self.buildablesubwoofer.subwoofer_kills, health_color ); + } + if ( isDefined( self.subwoofer_health ) ) + { + row = self debugsubwooferprint3d( row, "Use Time: " + self.subwoofer_health, health_color ); + } + if ( isDefined( self.buildablesubwoofer.original_owner ) ) + { + row = self debugsubwooferprint3d( row, "Original Owner: " + self.buildablesubwoofer.original_owner.name, green ); + } + if ( isDefined( self.buildablesubwoofer.owner ) ) + { + row = self debugsubwooferprint3d( row, "Current Owner: " + self.buildablesubwoofer.owner.name, green ); + } + } + wait 0,05; +#/ + } +} + +debugsubwooferprint3d( row, text, color ) +{ +/# + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_subwoofer_zm_taken" ); + self.buildablesubwoofer endon( "death" ); + print3dspace = vectorScale( ( 0, 0, 1 ), 10 ); + print3d( self.buildablesubwoofer.origin + vectorScale( ( 0, 0, 1 ), 30 ) + ( print3dspace * row ), text, color, 1, 0,5, 1 ); + row++; + return row; +#/ +} + +subwoofer_debug_print( msg, color, offset ) +{ +/# + if ( !getDvarInt( #"EB512CB7" ) ) + { + return; + } + if ( !isDefined( color ) ) + { + color = ( 0, 0, 1 ); + } + if ( !isDefined( offset ) ) + { + offset = ( 0, 0, 1 ); + } + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 60 ) + offset, msg, color, 1, 1, 40 ); +#/ +} + +subwoofer_debug_animation_print( msg1, msg2 ) +{ +/# + if ( getDvarInt( #"EB512CB7" ) != 1 ) + { + return; + } + self endon( "death" ); + self endon( "damage" ); + self endon( "back_up" ); + color = ( 0, 0, 1 ); + while ( 1 ) + { + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 50 ), "FallDown: " + msg1, color, 1, 0,75 ); + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 40 ), "GetUp: " + msg2, color, 1, 0,75 ); + wait 0,05; +#/ + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_game_module_cleansed.gsc b/zm_buried_patch/maps/mp/zombies/_zm_game_module_cleansed.gsc new file mode 100644 index 0000000..9c08b8c --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_game_module_cleansed.gsc @@ -0,0 +1,17 @@ +#include maps/mp/zombies/_zm_turned; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; + +register_game_module() +{ +} + +onstartgametype( name ) +{ +} + +onstartcleansedgametype() +{ +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_game_module_grief.gsc b/zm_buried_patch/maps/mp/zombies/_zm_game_module_grief.gsc new file mode 100644 index 0000000..14a2eba --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_game_module_meat.gsc b/zm_buried_patch/maps/mp/zombies/_zm_game_module_meat.gsc new file mode 100644 index 0000000..e083fb3 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc b/zm_buried_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc new file mode 100644 index 0000000..101f026 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_game_module_turned.gsc b/zm_buried_patch/maps/mp/zombies/_zm_game_module_turned.gsc new file mode 100644 index 0000000..98be664 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_game_module_turned.gsc @@ -0,0 +1,64 @@ +#include maps/mp/zombies/_zm_game_module_cleansed; +#include maps/mp/zombies/_zm_turned; +#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_turned_index = 6; + maps/mp/zombies/_zm_game_module::register_game_module( level.game_module_turned_index, "zturned", ::maps/mp/zombies/_zm_game_module_cleansed::onpreinitgametype, ::onpostinitgametype, undefined, ::maps/mp/zombies/_zm_game_module_cleansed::onspawnzombie, ::maps/mp/zombies/_zm_game_module_cleansed::onstartgametype ); +} + +register_turned_match( start_func, end_func, name ) +{ + if ( !isDefined( level._registered_turned_matches ) ) + { + level._registered_turned_matches = []; + } + match = spawnstruct(); + match.match_name = name; + match.match_start_func = start_func; + match.match_end_func = end_func; + level._registered_turned_matches[ level._registered_turned_matches.size ] = match; +} + +get_registered_turned_match( name ) +{ + _a41 = level._registered_turned_matches; + _k41 = getFirstArrayKey( _a41 ); + while ( isDefined( _k41 ) ) + { + struct = _a41[ _k41 ]; + if ( struct.match_name == name ) + { + return struct; + } + _k41 = getNextArrayKey( _a41, _k41 ); + } +} + +set_current_turned_match( name ) +{ + level._current_turned_match = name; +} + +get_current_turned_match() +{ + return level._current_turned_match; +} + +init_zombie_weapon() +{ + maps/mp/zombies/_zm_turned::init(); +} + +onpostinitgametype() +{ + if ( level.scr_zm_game_module != level.game_module_turned_index ) + { + return; + } + level thread init_zombie_weapon(); +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_game_module_utility.gsc b/zm_buried_patch/maps/mp/zombies/_zm_game_module_utility.gsc new file mode 100644 index 0000000..7c90b48 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_melee_weapon.gsc b/zm_buried_patch/maps/mp/zombies/_zm_melee_weapon.gsc new file mode 100644 index 0000000..da4574a --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_melee_weapon.gsc @@ -0,0 +1,621 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; +#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 ) + { + 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 ); + 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_buried_patch/maps/mp/zombies/_zm_perk_divetonuke.gsc b/zm_buried_patch/maps/mp/zombies/_zm_perk_divetonuke.gsc new file mode 100644 index 0000000..eae26c8 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_perk_divetonuke.gsc @@ -0,0 +1,139 @@ +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +enable_divetonuke_perk_for_level() +{ + maps/mp/zombies/_zm_perks::register_perk_basic_info( "specialty_flakjacket", "divetonuke", 2000, &"ZOMBIE_PERK_DIVETONUKE", "zombie_perk_bottle_nuke" ); + maps/mp/zombies/_zm_perks::register_perk_precache_func( "specialty_flakjacket", ::divetonuke_precache ); + maps/mp/zombies/_zm_perks::register_perk_clientfields( "specialty_flakjacket", ::divetonuke_register_clientfield, ::divetonuke_set_clientfield ); + maps/mp/zombies/_zm_perks::register_perk_machine( "specialty_flakjacket", ::divetonuke_perk_machine_setup, ::divetonuke_perk_machine_think ); + maps/mp/zombies/_zm_perks::register_perk_host_migration_func( "specialty_flakjacket", ::divetonuke_host_migration_func ); +} + +init_divetonuke() +{ + level.zombiemode_divetonuke_perk_func = ::divetonuke_explode; + maps/mp/_visionset_mgr::vsmgr_register_info( "visionset", "zm_perk_divetonuke", 9000, 400, 5, 1 ); + level._effect[ "divetonuke_groundhit" ] = loadfx( "maps/zombie/fx_zmb_phdflopper_exp" ); + set_zombie_var( "zombie_perk_divetonuke_radius", 300 ); + set_zombie_var( "zombie_perk_divetonuke_min_damage", 1000 ); + set_zombie_var( "zombie_perk_divetonuke_max_damage", 5000 ); +} + +divetonuke_precache() +{ + if ( isDefined( level.divetonuke_precache_override_func ) ) + { + [[ level.divetonuke_precache_override_func ]](); + return; + } + precacheitem( "zombie_perk_bottle_nuke" ); + precacheshader( "specialty_divetonuke_zombies" ); + precachemodel( "zombie_vending_nuke" ); + precachemodel( "zombie_vending_nuke_on" ); + precachestring( &"ZOMBIE_PERK_DIVETONUKE" ); + level._effect[ "divetonuke_light" ] = loadfx( "misc/fx_zombie_cola_dtap_on" ); + level.machine_assets[ "divetonuke" ] = spawnstruct(); + level.machine_assets[ "divetonuke" ].weapon = "zombie_perk_bottle_nuke"; + level.machine_assets[ "divetonuke" ].off_model = "zombie_vending_nuke"; + level.machine_assets[ "divetonuke" ].on_model = "zombie_vending_nuke_on"; +} + +divetonuke_register_clientfield() +{ + registerclientfield( "toplayer", "perk_dive_to_nuke", 9000, 1, "int" ); +} + +divetonuke_set_clientfield( state ) +{ + self setclientfieldtoplayer( "perk_dive_to_nuke", state ); +} + +divetonuke_perk_machine_setup( use_trigger, perk_machine, bump_trigger, collision ) +{ + use_trigger.script_sound = "mus_perks_phd_jingle"; + use_trigger.script_string = "divetonuke_perk"; + use_trigger.script_label = "mus_perks_phd_sting"; + use_trigger.target = "vending_divetonuke"; + perk_machine.script_string = "divetonuke_perk"; + perk_machine.targetname = "vending_divetonuke"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "divetonuke_perk"; + } +} + +divetonuke_perk_machine_think() +{ + init_divetonuke(); + while ( 1 ) + { + machine = getentarray( "vending_divetonuke", "targetname" ); + machine_triggers = getentarray( "vending_divetonuke", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "divetonuke" ].off_model ); + i++; + } + array_thread( machine_triggers, ::set_power_on, 0 ); + level thread do_initial_power_off_callback( machine, "divetonuke" ); + level waittill( "divetonuke_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "divetonuke" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0,3, 0,4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "divetonuke_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_flakjacket_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "divetonuke" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "divetonuke" ].power_on_callback ); + } + level waittill( "divetonuke_off" ); + if ( isDefined( level.machine_assets[ "divetonuke" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "divetonuke" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + } +} + +divetonuke_host_migration_func() +{ + flop = getentarray( "vending_divetonuke", "targetname" ); + _a138 = flop; + _k138 = getFirstArrayKey( _a138 ); + while ( isDefined( _k138 ) ) + { + perk = _a138[ _k138 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "divetonuke" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "divetonuke_light" ); + } + _k138 = getNextArrayKey( _a138, _k138 ); + } +} + +divetonuke_explode( attacker, origin ) +{ + radius = level.zombie_vars[ "zombie_perk_divetonuke_radius" ]; + min_damage = level.zombie_vars[ "zombie_perk_divetonuke_min_damage" ]; + max_damage = level.zombie_vars[ "zombie_perk_divetonuke_max_damage" ]; + radiusdamage( origin, radius, max_damage, min_damage, attacker, "MOD_GRENADE_SPLASH" ); + playfx( level._effect[ "divetonuke_groundhit" ], origin ); + attacker playsound( "zmb_phdflop_explo" ); + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_perk_divetonuke", attacker ); + wait 1; + maps/mp/_visionset_mgr::vsmgr_deactivate( "visionset", "zm_perk_divetonuke", attacker ); +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_perk_vulture.gsc b/zm_buried_patch/maps/mp/zombies/_zm_perk_vulture.gsc new file mode 100644 index 0000000..21405c1 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_perk_vulture.gsc @@ -0,0 +1,1622 @@ +#include maps/mp/zombies/_zm_perk_vulture; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +enable_vulture_perk_for_level() +{ + maps/mp/zombies/_zm_perks::register_perk_basic_info( "specialty_nomotionsensor", "vulture", 3000, &"ZOMBIE_PERK_VULTURE", "zombie_perk_bottle_vulture" ); + maps/mp/zombies/_zm_perks::register_perk_precache_func( "specialty_nomotionsensor", ::vulture_precache ); + maps/mp/zombies/_zm_perks::register_perk_clientfields( "specialty_nomotionsensor", ::vulture_register_clientfield, ::vulture_set_clientfield ); + maps/mp/zombies/_zm_perks::register_perk_threads( "specialty_nomotionsensor", ::give_vulture_perk, ::take_vulture_perk ); + maps/mp/zombies/_zm_perks::register_perk_machine( "specialty_nomotionsensor", ::vulture_perk_machine_setup, ::vulture_perk_machine_think ); + maps/mp/zombies/_zm_perks::register_perk_host_migration_func( "specialty_nomotionsensor", ::vulture_host_migration_func ); +} + +vulture_precache() +{ + precacheitem( "zombie_perk_bottle_vulture" ); + precacheshader( "specialty_vulture_zombies" ); + precachestring( &"ZOMBIE_PERK_VULTURE" ); + precachemodel( "p6_zm_vending_vultureaid" ); + precachemodel( "p6_zm_vending_vultureaid_on" ); + precachemodel( "p6_zm_perk_vulture_ammo" ); + precachemodel( "p6_zm_perk_vulture_points" ); + level._effect[ "vulture_light" ] = loadfx( "misc/fx_zombie_cola_jugg_on" ); + level._effect[ "vulture_perk_zombie_stink" ] = loadfx( "maps/zombie/fx_zm_vulture_perk_stink" ); + level._effect[ "vulture_perk_zombie_stink_trail" ] = loadfx( "maps/zombie/fx_zm_vulture_perk_stink_trail" ); + level._effect[ "vulture_perk_bonus_drop" ] = loadfx( "misc/fx_zombie_powerup_vulture" ); + level._effect[ "vulture_drop_picked_up" ] = loadfx( "misc/fx_zombie_powerup_grab" ); + level._effect[ "vulture_perk_wallbuy_static" ] = loadfx( "maps/zombie/fx_zm_vulture_wallbuy_rifle" ); + level._effect[ "vulture_perk_wallbuy_dynamic" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_question" ); + level._effect[ "vulture_perk_machine_glow_doubletap" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_dbltap" ); + level._effect[ "vulture_perk_machine_glow_juggernog" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_jugg" ); + level._effect[ "vulture_perk_machine_glow_revive" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_revive" ); + level._effect[ "vulture_perk_machine_glow_speed" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_speed" ); + level._effect[ "vulture_perk_machine_glow_marathon" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_marathon" ); + level._effect[ "vulture_perk_machine_glow_mule_kick" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_mule" ); + level._effect[ "vulture_perk_machine_glow_pack_a_punch" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_pap" ); + level._effect[ "vulture_perk_machine_glow_vulture" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_vulture" ); + level._effect[ "vulture_perk_mystery_box_glow" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_mystery_box" ); + level._effect[ "vulture_perk_powerup_drop" ] = loadfx( "maps/zombie/fx_zm_vulture_glow_powerup" ); + level._effect[ "vulture_perk_zombie_eye_glow" ] = loadfx( "misc/fx_zombie_eye_vulture" ); + onplayerconnect_callback( ::vulture_player_connect_callback ); +} + +vulture_player_connect_callback() +{ + self thread end_game_turn_off_vulture_overlay(); +} + +end_game_turn_off_vulture_overlay() +{ + self endon( "disconnect" ); + level waittill( "end_game" ); + self thread take_vulture_perk(); +} + +init_vulture() +{ + setdvarint( "zombies_perk_vulture_pickup_time", 12 ); + setdvarint( "zombies_perk_vulture_pickup_time_stink", 16 ); + setdvarint( "zombies_perk_vulture_drop_chance", 65 ); + setdvarint( "zombies_perk_vulture_ammo_chance", 33 ); + setdvarint( "zombies_perk_vulture_points_chance", 33 ); + setdvarint( "zombies_perk_vulture_stink_chance", 33 ); + setdvarint( "zombies_perk_vulture_drops_max", 20 ); + setdvarint( "zombies_perk_vulture_network_drops_max", 5 ); + setdvarint( "zombies_perk_vulture_network_time_frame", 250 ); + setdvarint( "zombies_perk_vulture_spawn_stink_zombie_cooldown", 12 ); + setdvarint( "zombies_perk_vulture_max_stink_zombies", 4 ); + level.perk_vulture = spawnstruct(); + level.perk_vulture.zombie_stink_array = []; + level.perk_vulture.drop_time_last = 0; + level.perk_vulture.drop_slots_for_network = 0; + level.perk_vulture.last_stink_zombie_spawned = 0; + level.perk_vulture.use_exit_behavior = 0; + level.perk_vulture.clientfields = spawnstruct(); + level.perk_vulture.clientfields.scriptmovers = []; + level.perk_vulture.clientfields.scriptmovers[ "vulture_stink_fx" ] = 0; + level.perk_vulture.clientfields.scriptmovers[ "vulture_drop_fx" ] = 1; + level.perk_vulture.clientfields.scriptmovers[ "vulture_drop_pickup" ] = 2; + level.perk_vulture.clientfields.scriptmovers[ "vulture_powerup_drop" ] = 3; + level.perk_vulture.clientfields.actors = []; + level.perk_vulture.clientfields.actors[ "vulture_stink_trail_fx" ] = 0; + level.perk_vulture.clientfields.actors[ "vulture_eye_glow" ] = 1; + level.perk_vulture.clientfields.toplayer = []; + level.perk_vulture.clientfields.toplayer[ "vulture_perk_active" ] = 0; + registerclientfield( "toplayer", "vulture_perk_toplayer", 12000, 1, "int" ); + registerclientfield( "actor", "vulture_perk_actor", 12000, 2, "int" ); + registerclientfield( "scriptmover", "vulture_perk_scriptmover", 12000, 4, "int" ); + registerclientfield( "zbarrier", "vulture_perk_zbarrier", 12000, 1, "int" ); + registerclientfield( "toplayer", "sndVultureStink", 12000, 1, "int" ); + registerclientfield( "world", "vulture_perk_disable_solo_quick_revive_glow", 12000, 1, "int" ); + registerclientfield( "toplayer", "vulture_perk_disease_meter", 12000, 5, "float" ); + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "vulture_stink_overlay", 12000, 120, 31, 1 ); + maps/mp/zombies/_zm_spawner::add_cusom_zombie_spawn_logic( ::vulture_zombie_spawn_func ); + register_zombie_death_event_callback( ::zombies_drop_stink_on_death ); + level thread vulture_perk_watch_mystery_box(); + level thread vulture_perk_watch_fire_sale(); + level thread vulture_perk_watch_powerup_drops(); + level thread vulture_handle_solo_quick_revive(); +/# + assert( !isDefined( level.exit_level_func ), "vulture perk is attempting to use level.exit_level_func, but one already exists for this level!" ); +#/ + level.exit_level_func = ::vulture_zombies_find_exit_point; + level.perk_vulture.invalid_bonus_ammo_weapons = array( "time_bomb_zm", "time_bomb_detonator_zm" ); + if ( !isDefined( level.perk_vulture.func_zombies_find_valid_exit_locations ) ) + { + level.perk_vulture.func_zombies_find_valid_exit_locations = ::get_valid_exit_points_for_zombie; + } + setup_splitscreen_optimizations(); + initialize_bonus_entity_pool(); + initialize_stink_entity_pool(); +/# + level.vulture_devgui_spawn_stink = ::vulture_devgui_spawn_stink; +#/ +} + +add_additional_stink_locations_for_zone( str_zone, a_zones ) +{ + if ( !isDefined( level.perk_vulture.zones_for_extra_stink_locations ) ) + { + level.perk_vulture.zones_for_extra_stink_locations = []; + } + level.perk_vulture.zones_for_extra_stink_locations[ str_zone ] = a_zones; +} + +vulture_register_clientfield() +{ + registerclientfield( "toplayer", "perk_vulture", 12000, 2, "int" ); +} + +vulture_set_clientfield( state ) +{ + self setclientfieldtoplayer( "perk_vulture", state ); +} + +give_vulture_perk() +{ + vulture_debug_text( "player " + self getentitynumber() + " has vulture perk!" ); + if ( !isDefined( self.perk_vulture ) ) + { + self.perk_vulture = spawnstruct(); + } + self.perk_vulture.active = 1; + self vulture_vision_toggle( 1 ); + self vulture_clientfield_toplayer_set( "vulture_perk_active" ); + self thread _vulture_perk_think(); +} + +take_vulture_perk() +{ + if ( isDefined( self.perk_vulture ) && isDefined( self.perk_vulture.active ) && self.perk_vulture.active ) + { + vulture_debug_text( "player " + self getentitynumber() + " has lost vulture perk!" ); + self.perk_vulture.active = 0; + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + self.ignoreme = 0; + } + self vulture_vision_toggle( 0 ); + self vulture_clientfield_toplayer_clear( "vulture_perk_active" ); + self set_vulture_overlay( 0 ); + self.vulture_stink_value = 0; + self setclientfieldtoplayer( "vulture_perk_disease_meter", 0 ); + self notify( "vulture_perk_lost" ); + } +} + +vulture_host_migration_func() +{ + a_vulture_perk_machines = getentarray( "vending_vulture", "targetname" ); + _a235 = a_vulture_perk_machines; + _k235 = getFirstArrayKey( _a235 ); + while ( isDefined( _k235 ) ) + { + perk_machine = _a235[ _k235 ]; + if ( isDefined( perk_machine.model ) && perk_machine.model == "p6_zm_vending_vultureaid_on" ) + { + perk_machine maps/mp/zombies/_zm_perks::perk_fx( undefined, 1 ); + perk_machine thread maps/mp/zombies/_zm_perks::perk_fx( "vulture_light" ); + } + _k235 = getNextArrayKey( _a235, _k235 ); + } +} + +vulture_perk_add_invalid_bonus_ammo_weapon( str_weapon ) +{ +/# + assert( isDefined( level.perk_vulture ), "vulture_perk_add_invalid_bonus_ammo_weapon() was called before vulture perk was initialized. Make sure this is called after the vulture perk initialization func!" ); +#/ + level.perk_vulture.invalid_bonus_ammo_weapons[ level.perk_vulture.invalid_bonus_ammo_weapons.size ] = str_weapon; +} + +vulture_perk_machine_setup( use_trigger, perk_machine, bump_trigger, collision ) +{ + use_trigger.script_sound = "mus_perks_vulture_jingle"; + use_trigger.script_string = "vulture_perk"; + use_trigger.script_label = "mus_perks_vulture_sting"; + use_trigger.target = "vending_vulture"; + perk_machine.script_string = "vulture_perk"; + perk_machine.targetname = "vending_vulture"; + bump_trigger.script_string = "vulture_perk"; +} + +vulture_perk_machine_think() +{ + init_vulture(); + while ( 1 ) + { + machine = getentarray( "vending_vulture", "targetname" ); + machine_triggers = getentarray( "vending_vulture", "target" ); + array_thread( machine_triggers, ::maps/mp/zombies/_zm_perks::set_power_on, 0 ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( "p6_zm_vending_vultureaid" ); + i++; + } + level waittill( "specialty_nomotionsensor" + "_on" ); + level notify( "specialty_nomotionsensor" + "_power_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( "p6_zm_vending_vultureaid_on" ); + machine[ i ] vibrate( vectorScale( ( 0, 0, 1 ), 100 ), 0,3, 0,4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread maps/mp/zombies/_zm_perks::perk_fx( "vulture_light" ); + machine[ i ] thread maps/mp/zombies/_zm_perks::play_loop_on_machine(); + i++; + } + array_thread( machine_triggers, ::maps/mp/zombies/_zm_perks::set_power_on, 1 ); + level waittill( "specialty_nomotionsensor" + "_off" ); + array_thread( machine, ::maps/mp/zombies/_zm_perks::turn_perk_off ); + } +} + +do_vulture_death( player ) +{ + if ( isDefined( self ) ) + { + self thread _do_vulture_death( player ); + } +} + +_do_vulture_death( player ) +{ + if ( should_do_vulture_drop( self.origin ) ) + { + str_bonus = get_vulture_drop_type(); + str_identifier = "_" + self getentitynumber() + "_" + getTime(); + v_drop_origin = groundtrace( self.origin + vectorScale( ( 0, 0, 1 ), 50 ), self.origin - vectorScale( ( 0, 0, 1 ), 100 ), 0, self )[ "position" ]; + player thread show_debug_info( self.origin, str_identifier, str_bonus ); + self thread vulture_drop_funcs( self.origin, player, str_identifier, str_bonus ); + } +} + +vulture_drop_funcs( v_origin, player, str_identifier, str_bonus ) +{ + vulture_drop_count_increment(); + switch( str_bonus ) + { + case "ammo": + e_temp = player _vulture_drop_model( str_identifier, "p6_zm_perk_vulture_ammo", v_origin, vectorScale( ( 0, 0, 1 ), 15 ) ); + self thread check_vulture_drop_pickup( e_temp, player, str_identifier, str_bonus ); + break; + case "points": + e_temp = player _vulture_drop_model( str_identifier, "p6_zm_perk_vulture_points", v_origin, vectorScale( ( 0, 0, 1 ), 15 ) ); + self thread check_vulture_drop_pickup( e_temp, player, str_identifier, str_bonus ); + break; + case "stink": + self _drop_zombie_stink( player, str_identifier, str_bonus ); + break; + } +} + +_drop_zombie_stink( player, str_identifier, str_bonus ) +{ + self clear_zombie_stink_fx(); + e_temp = player zombie_drops_stink( self, str_identifier ); + e_temp = player _vulture_spawn_fx( str_identifier, self.origin, str_bonus, e_temp ); + clean_up_stink( e_temp ); +} + +zombie_drops_stink( ai_zombie, str_identifier ) +{ + e_temp = ai_zombie.stink_ent; + if ( isDefined( e_temp ) ) + { + e_temp thread delay_showing_vulture_ent( self, ai_zombie.origin ); + level.perk_vulture.zombie_stink_array[ level.perk_vulture.zombie_stink_array.size ] = e_temp; + self delay_notify( str_identifier, getDvarInt( #"DDE8D546" ) ); + } + return e_temp; +} + +delay_showing_vulture_ent( player, v_moveto_pos, str_model, func ) +{ + self.drop_time = getTime(); + wait_network_frame(); + wait_network_frame(); + self.origin = v_moveto_pos; + wait_network_frame(); + if ( isDefined( str_model ) ) + { + self setmodel( str_model ); + } + self show(); + if ( isplayer( player ) ) + { + self setinvisibletoall(); + self setvisibletoplayer( player ); + } + if ( isDefined( func ) ) + { + self [[ func ]](); + } +} + +clean_up_stink( e_temp ) +{ + e_temp vulture_clientfield_scriptmover_clear( "vulture_stink_fx" ); + arrayremovevalue( level.perk_vulture.zombie_stink_array, e_temp, 0 ); + wait 4; + e_temp clear_stink_ent(); +} + +_delete_vulture_ent( n_delay ) +{ + if ( !isDefined( n_delay ) ) + { + n_delay = 0; + } + if ( n_delay > 0 ) + { + self ghost(); + wait n_delay; + } + self clear_bonus_ent(); +} + +_vulture_drop_model( str_identifier, str_model, v_model_origin, v_offset ) +{ + if ( !isDefined( v_offset ) ) + { + v_offset = ( 0, 0, 1 ); + } + if ( !isDefined( self.perk_vulture_models ) ) + { + self.perk_vulture_models = []; + } + e_temp = get_unused_bonus_ent(); + if ( !isDefined( e_temp ) ) + { + self notify( str_identifier ); + return; + } + e_temp thread delay_showing_vulture_ent( self, v_model_origin + v_offset, str_model, ::set_vulture_drop_fx ); + self.perk_vulture_models[ self.perk_vulture_models.size ] = e_temp; + e_temp setinvisibletoall(); + e_temp setvisibletoplayer( self ); + e_temp thread _vulture_drop_model_thread( str_identifier, self ); + return e_temp; +} + +set_vulture_drop_fx() +{ + self vulture_clientfield_scriptmover_set( "vulture_drop_fx" ); +} + +_vulture_drop_model_thread( str_identifier, player ) +{ + self thread _vulture_model_blink_timeout( player ); + player waittill_any( str_identifier, "death_or_disconnect", "vulture_perk_lost" ); + self vulture_clientfield_scriptmover_clear( "vulture_drop_fx" ); + n_delete_delay = 0,1; + if ( isDefined( self.picked_up ) && self.picked_up ) + { + self _play_vulture_drop_pickup_fx(); + n_delete_delay = 1; + } + if ( isDefined( player.perk_vulture_models ) ) + { + arrayremovevalue( player.perk_vulture_models, self, 0 ); + self.perk_vulture_models = remove_undefined_from_array( player.perk_vulture_models ); + } + self _delete_vulture_ent( n_delete_delay ); +} + +_vulture_model_blink_timeout( player ) +{ + self endon( "death" ); + player endon( "death" ); + player endon( "disconnect" ); + self endon( "stop_vulture_behavior" ); + n_time_total = getDvarInt( #"34FA67DE" ); + n_frames = n_time_total * 20; + n_section = int( n_frames / 6 ); + n_flash_slow = n_section * 3; + n_flash_medium = n_section * 4; + n_flash_fast = n_section * 5; + b_show = 1; + i = 0; + while ( i < n_frames ) + { + if ( i < n_flash_slow ) + { + n_multiplier = n_flash_slow; + } + else if ( i < n_flash_medium ) + { + n_multiplier = 10; + } + else if ( i < n_flash_fast ) + { + n_multiplier = 5; + } + else + { + n_multiplier = 2; + } + if ( b_show ) + { + self show(); + self setinvisibletoall(); + self setvisibletoplayer( player ); + } + else + { + self ghost(); + } + b_show = !b_show; + i += n_multiplier; + wait ( 0,05 * n_multiplier ); + } +} + +_vulture_spawn_fx( str_identifier, v_fx_origin, str_bonus, e_temp ) +{ + b_delete = 0; + if ( !isDefined( e_temp ) ) + { + e_temp = get_unused_bonus_ent(); + if ( !isDefined( e_temp ) ) + { + self notify( str_identifier ); + return; + } + b_delete = 1; + } + e_temp thread delay_showing_vulture_ent( self, v_fx_origin, "tag_origin", ::clientfield_set_vulture_stink_enabled ); + if ( isplayer( self ) ) + { + self waittill_any( str_identifier, "disconnect", "vulture_perk_lost" ); + } + else + { + self waittill( str_identifier ); + } + if ( b_delete ) + { + e_temp _delete_vulture_ent(); + } + return e_temp; +} + +clientfield_set_vulture_stink_enabled() +{ + self vulture_clientfield_scriptmover_set( "vulture_stink_fx" ); +} + +should_do_vulture_drop( v_death_origin ) +{ + b_is_inside_playable_area = check_point_in_enabled_zone( v_death_origin, 1 ); + b_ents_are_available = get_unused_bonus_ent_count() > 0; + b_network_slots_available = level.perk_vulture.drop_slots_for_network < getDvarInt( #"1786213A" ); + n_roll = randomint( 100 ); + b_passed_roll = n_roll > ( 100 - getDvarInt( #"70E3B3FA" ) ); + if ( isDefined( self.is_stink_zombie ) ) + { + b_is_stink_zombie = self.is_stink_zombie; + } + if ( !b_is_stink_zombie ) + { + if ( b_is_inside_playable_area && b_ents_are_available && b_network_slots_available ) + { + b_should_drop = b_passed_roll; + } + } + return b_should_drop; +} + +get_vulture_drop_type() +{ + n_chance_ammo = getDvarInt( #"F75E07AF" ); + n_chance_points = getDvarInt( #"D7BCDBE2" ); + n_chance_stink = getDvarInt( #"4918C38E" ); + n_total_weight = n_chance_ammo + n_chance_points; + n_cutoff_ammo = n_chance_ammo; + n_cutoff_points = n_chance_ammo + n_chance_points; + n_roll = randomint( n_total_weight ); + if ( n_roll < n_cutoff_ammo ) + { + str_bonus = "ammo"; + } + else + { + str_bonus = "points"; + } + if ( isDefined( self.is_stink_zombie ) && self.is_stink_zombie ) + { + str_bonus = "stink"; + } + return str_bonus; +} + +show_debug_info( v_drop_point, str_identifier, str_bonus ) +{ +/# + n_radius = 32; + if ( str_bonus == "stink" ) + { + n_radius = 70; + } + while ( getDvarInt( #"38E68F2B" ) ) + { + self endon( str_identifier ); + vulture_debug_text( "zombie dropped " + str_bonus ); + i = 0; + while ( i < ( get_vulture_drop_duration( str_bonus ) * 20 ) ) + { + circle( v_drop_point, n_radius, get_debug_circle_color( str_bonus ), 0, 1, 1 ); + wait 0,05; + i++; +#/ + } + } +} + +get_vulture_drop_duration( str_bonus ) +{ + str_dvar = "zombies_perk_vulture_pickup_time"; + if ( str_bonus == "stink" ) + { + str_dvar = "zombies_perk_vulture_pickup_time_stink"; + } + n_duration = getDvarInt( str_dvar ); + return n_duration; +} + +get_debug_circle_color( str_bonus ) +{ + switch( str_bonus ) + { + case "ammo": + v_color = ( 0, 0, 1 ); + break; + case "points": + v_color = ( 0, 0, 1 ); + break; + case "stink": + v_color = ( 0, 0, 1 ); + break; + default: + v_color = ( 0, 0, 1 ); + break; + } + return v_color; +} + +check_vulture_drop_pickup( e_temp, player, str_identifier, str_bonus ) +{ + if ( !isDefined( e_temp ) ) + { + return; + } + player endon( "death" ); + player endon( "disconnect" ); + e_temp endon( "death" ); + e_temp endon( "stop_vulture_behavior" ); + wait_network_frame(); + n_times_to_check = int( get_vulture_drop_duration( str_bonus ) / 0,15 ); + i = 0; + while ( i < n_times_to_check ) + { + b_player_inside_radius = distancesquared( e_temp.origin, player.origin ) < 1024; + if ( b_player_inside_radius ) + { + e_temp.picked_up = 1; + break; + } + else + { + wait 0,15; + i++; + } + } + player notify( str_identifier ); + if ( b_player_inside_radius ) + { + player give_vulture_bonus( str_bonus ); + } +} + +_handle_zombie_stink( b_player_inside_radius ) +{ + if ( !isDefined( self.perk_vulture.is_in_zombie_stink ) ) + { + self.perk_vulture.is_in_zombie_stink = 0; + } + b_in_stink_last_check = self.perk_vulture.is_in_zombie_stink; + self.perk_vulture.is_in_zombie_stink = b_player_inside_radius; + if ( self.perk_vulture.is_in_zombie_stink ) + { + n_current_time = getTime(); + if ( !b_in_stink_last_check ) + { + self.perk_vulture.stink_time_entered = n_current_time; + self toggle_stink_overlay( 1 ); + self thread stink_react_vo(); + } + if ( isDefined( self.perk_vulture.stink_time_entered ) ) + { + b_should_ignore_player = ( ( n_current_time - self.perk_vulture.stink_time_entered ) * 0,001 ) >= 0; + } + if ( b_should_ignore_player ) + { + self.ignoreme = 1; + } + if ( get_targetable_player_count() == 0 || !self are_any_players_in_adjacent_zone() ) + { + if ( b_should_ignore_player && !level.perk_vulture.use_exit_behavior ) + { + level.perk_vulture.use_exit_behavior = 1; + level.default_find_exit_position_override = ::vulture_perk_should_zombies_resume_find_flesh; + self thread vulture_zombies_find_exit_point(); + } + } + } + else + { + if ( b_in_stink_last_check ) + { + self.perk_vulture.stink_time_exit = getTime(); + self thread _zombies_reacquire_player_after_leaving_stink(); + } + } +} + +stink_react_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + wait 1; + chance = get_response_chance( "vulture_stink" ); + if ( chance > randomintrange( 1, 100 ) ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "vulture_stink" ); + } +} + +get_targetable_player_count() +{ + n_targetable_player_count = 0; + _a819 = get_players(); + _k819 = getFirstArrayKey( _a819 ); + while ( isDefined( _k819 ) ) + { + player = _a819[ _k819 ]; + if ( !isDefined( player.ignoreme ) || !player.ignoreme ) + { + n_targetable_player_count++; + } + _k819 = getNextArrayKey( _a819, _k819 ); + } + return n_targetable_player_count; +} + +are_any_players_in_adjacent_zone() +{ + b_players_in_adjacent_zone = 0; + str_zone = self maps/mp/zombies/_zm_zonemgr::get_player_zone(); + _a836 = get_players(); + _k836 = getFirstArrayKey( _a836 ); + while ( isDefined( _k836 ) ) + { + player = _a836[ _k836 ]; + if ( player == self ) + { + } + else + { + str_zone_compare = player maps/mp/zombies/_zm_zonemgr::get_player_zone(); + if ( isinarray( level.zones[ str_zone ].adjacent_zones, str_zone_compare ) && isDefined( level.zones[ str_zone ].adjacent_zones[ str_zone_compare ].is_connected ) && level.zones[ str_zone ].adjacent_zones[ str_zone_compare ].is_connected ) + { + b_players_in_adjacent_zone = 1; + break; + } + } + else + { + _k836 = getNextArrayKey( _a836, _k836 ); + } + } + return b_players_in_adjacent_zone; +} + +toggle_stink_overlay( b_show_overlay ) +{ + if ( !isDefined( self.vulture_stink_value ) ) + { + self.vulture_stink_value = 0; + } + if ( b_show_overlay ) + { + self thread _ramp_up_stink_overlay(); + } + else + { + self thread _ramp_down_stink_overlay(); + } +} + +_ramp_up_stink_overlay( b_instant_change ) +{ + if ( !isDefined( b_instant_change ) ) + { + b_instant_change = 0; + } + self notify( "vulture_perk_stink_ramp_up_done" ); + self endon( "vulture_perk_stink_ramp_up_done" ); + self endon( "death_or_disconnect" ); + self endon( "vulture_perk_lost" ); + self setclientfieldtoplayer( "sndVultureStink", 1 ); + if ( !isDefined( level.perk_vulture.stink_change_increment ) ) + { + level.perk_vulture.stink_change_increment = ( pow( 2, 5 ) * 0,25 ) / 8; + } + while ( self.perk_vulture.is_in_zombie_stink ) + { + self.vulture_stink_value += level.perk_vulture.stink_change_increment; + if ( self.vulture_stink_value > ( pow( 2, 5 ) - 1 ) ) + { + self.vulture_stink_value = pow( 2, 5 ) - 1; + } + fraction = self _get_disease_meter_fraction(); + self setclientfieldtoplayer( "vulture_perk_disease_meter", fraction ); + self set_vulture_overlay( fraction ); + vulture_debug_text( "disease counter = " + self.vulture_stink_value ); + wait 0,25; + } +} + +set_vulture_overlay( fraction ) +{ + state = level.vsmgr[ "overlay" ].info[ "vulture_stink_overlay" ].state; + if ( fraction > 0 ) + { + state maps/mp/_visionset_mgr::vsmgr_set_state_active( self, 1 - fraction ); + } + else + { + state maps/mp/_visionset_mgr::vsmgr_set_state_inactive( self ); + } +} + +_get_disease_meter_fraction() +{ + return self.vulture_stink_value / ( pow( 2, 5 ) - 1 ); +} + +_ramp_down_stink_overlay( b_instant_change ) +{ + if ( !isDefined( b_instant_change ) ) + { + b_instant_change = 0; + } + self notify( "vulture_perk_stink_ramp_down_done" ); + self endon( "vulture_perk_stink_ramp_down_done" ); + self endon( "death_or_disconnect" ); + self endon( "vulture_perk_lost" ); + self setclientfieldtoplayer( "sndVultureStink", 0 ); + if ( !isDefined( level.perk_vulture.stink_change_decrement ) ) + { + level.perk_vulture.stink_change_decrement = ( pow( 2, 5 ) * 0,25 ) / 4; + } + while ( !self.perk_vulture.is_in_zombie_stink && self.vulture_stink_value > 0 ) + { + self.vulture_stink_value -= level.perk_vulture.stink_change_decrement; + if ( self.vulture_stink_value < 0 ) + { + self.vulture_stink_value = 0; + } + fraction = self _get_disease_meter_fraction(); + self set_vulture_overlay( fraction ); + self setclientfieldtoplayer( "vulture_perk_disease_meter", fraction ); + vulture_debug_text( "disease counter = " + self.vulture_stink_value ); + wait 0,25; + } +} + +_zombies_reacquire_player_after_leaving_stink() +{ + self endon( "death_or_disconnect" ); + self notify( "vulture_perk_stop_zombie_reacquire_player" ); + self endon( "vulture_perk_stop_zombie_reacquire_player" ); + self toggle_stink_overlay( 0 ); + while ( self.vulture_stink_value > 0 ) + { + vulture_debug_text( "zombies ignoring player..." ); + wait 0,25; + } + self.ignoreme = 0; + level.perk_vulture.use_exit_behavior = 0; +} + +vulture_perk_should_zombies_resume_find_flesh() +{ + b_should_find_flesh = !is_player_in_zombie_stink(); + return b_should_find_flesh; +} + +is_player_in_zombie_stink() +{ + a_players = get_players(); + b_player_in_zombie_stink = 0; + i = 0; + while ( !b_player_in_zombie_stink && i < a_players.size ) + { + if ( isDefined( a_players[ i ].is_in_zombie_stink ) && a_players[ i ].is_in_zombie_stink ) + { + b_player_in_zombie_stink = 1; + } + i++; + } + return b_player_in_zombie_stink; +} + +give_vulture_bonus( str_bonus ) +{ + switch( str_bonus ) + { + case "ammo": + self give_bonus_ammo(); + break; + case "points": + self give_bonus_points(); + break; + case "stink": + self give_bonus_stink(); + break; + default: +/# + assert( "invalid bonus string '" + str_bonus + "' used in give_vulture_bonus()!" ); +#/ + break; + } +} + +give_bonus_ammo() +{ + str_weapon_current = self getcurrentweapon(); + if ( str_weapon_current != "none" ) + { + n_heat_value = self isweaponoverheating( 1, str_weapon_current ); + n_fuel_total = weaponfuellife( str_weapon_current ); + b_is_fuel_weapon = n_fuel_total > 0; + b_is_overheating_weapon = n_heat_value > 0; + if ( b_is_overheating_weapon ) + { + n_ammo_refunded = randomintrange( 1, 3 ); + b_weapon_is_overheating = self isweaponoverheating(); + self setweaponoverheating( b_weapon_is_overheating, n_heat_value - n_ammo_refunded ); + } + else if ( b_is_fuel_weapon ) + { + n_fuel_used = self getweaponammofuel( str_weapon_current ); + n_fuel_refunded = randomintrange( int( n_fuel_total * 0,01 ), int( n_fuel_total * 0,03 ) ); + self setweaponammofuel( str_weapon_current, n_fuel_used - n_fuel_refunded ); + n_ammo_refunded = ( n_fuel_refunded / n_fuel_total ) * 100; + } + else + { + if ( is_valid_ammo_bonus_weapon( str_weapon_current ) ) + { + n_ammo_count_current = self getweaponammostock( str_weapon_current ); + n_ammo_count_max = weaponmaxammo( str_weapon_current ); + n_ammo_refunded = clamp( int( n_ammo_count_max * randomfloatrange( 0, 0,025 ) ), 1, n_ammo_count_max ); + b_is_custom_weapon = self handle_custom_weapon_refunds( str_weapon_current ); + if ( !b_is_custom_weapon ) + { + self setweaponammostock( str_weapon_current, n_ammo_count_current + n_ammo_refunded ); + } + } + } + self playsoundtoplayer( "zmb_vulture_drop_pickup_ammo", self ); + chance = get_response_chance( "vulture_ammo_drop" ); + if ( chance > randomintrange( 1, 100 ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "vulture_ammo_drop" ); + } +/# + if ( getDvarInt( #"38E68F2B" ) ) + { + if ( !isDefined( n_ammo_refunded ) ) + { + n_ammo_refunded = 0; + } + vulture_debug_text( ( str_weapon_current + " bullets given: " ) + n_ammo_refunded ); +#/ + } + } +} + +is_valid_ammo_bonus_weapon( str_weapon ) +{ + if ( !is_placeable_mine( str_weapon ) && !maps/mp/zombies/_zm_equipment::is_placeable_equipment( str_weapon )return !isinarray( level.perk_vulture.invalid_bonus_ammo_weapons, str_weapon ); +} + +_play_vulture_drop_pickup_fx() +{ + self vulture_clientfield_scriptmover_set( "vulture_drop_pickup" ); +} + +give_bonus_points( v_fx_origin ) +{ + n_multiplier = randomintrange( 1, 5 ); + self maps/mp/zombies/_zm_score::player_add_points( "vulture", 5 * n_multiplier ); + self playsoundtoplayer( "zmb_vulture_drop_pickup_money", self ); + chance = get_response_chance( "vulture_money_drop" ); + if ( chance > randomintrange( 1, 100 ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "vulture_money_drop" ); + } +} + +give_bonus_stink( v_drop_origin ) +{ + self _handle_zombie_stink( 0 ); +} + +_vulture_perk_think() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "vulture_perk_lost" ); + while ( 1 ) + { + b_player_in_zombie_stink = 0; + if ( !isDefined( level.perk_vulture.zombie_stink_array ) ) + { + level.perk_vulture.zombie_stink_array = []; + } + if ( level.perk_vulture.zombie_stink_array.size > 0 ) + { + a_close_points = arraysort( level.perk_vulture.zombie_stink_array, self.origin, 1, 300 ); + if ( a_close_points.size > 0 ) + { + b_player_in_zombie_stink = self _is_player_in_zombie_stink( a_close_points ); + } + } + self _handle_zombie_stink( b_player_in_zombie_stink ); + wait randomfloatrange( 0,25, 0,5 ); + } +} + +_is_player_in_zombie_stink( a_points ) +{ + b_is_in_stink = 0; + i = 0; + while ( i < a_points.size ) + { + if ( distancesquared( a_points[ i ].origin, self.origin ) < 4900 ) + { + b_is_in_stink = 1; + } + i++; + } + return b_is_in_stink; +} + +vulture_drop_count_increment() +{ + level.perk_vulture.drop_slots_for_network++; + level thread _decrement_network_slots_after_time(); +} + +_decrement_network_slots_after_time() +{ + wait ( getDvarInt( #"DB295746" ) * 0,001 ); + level.perk_vulture.drop_slots_for_network--; + +} + +vulture_zombie_spawn_func() +{ + self endon( "death" ); + self thread add_zombie_eye_glow(); + self waittill( "completed_emerging_into_playable_area" ); + while ( self should_zombie_have_stink() ) + { + self stink_zombie_array_add(); +/# + while ( isDefined( self.stink_ent ) ) + { + while ( 1 ) + { + if ( getDvarInt( #"38E68F2B" ) ) + { + debugstar( self.origin, 2, ( 0, 0, 1 ) ); + } + wait 0,1; +#/ + } + } + } +} + +add_zombie_eye_glow() +{ + self endon( "death" ); + self waittill( "risen" ); + self vulture_clientfield_actor_set( "vulture_eye_glow" ); +} + +zombies_drop_stink_on_death() +{ + self vulture_clientfield_actor_clear( "vulture_eye_glow" ); + if ( isDefined( self.attacker ) && isplayer( self.attacker ) && self.attacker hasperk( "specialty_nomotionsensor" ) ) + { + self thread do_vulture_death( self.attacker ); + } + else + { + if ( isDefined( self.is_stink_zombie ) && self.is_stink_zombie && isDefined( self.stink_ent ) ) + { + str_identifier = "_" + self getentitynumber() + "_" + getTime(); + self thread _drop_zombie_stink( level, str_identifier, "stink" ); + } + } +} + +clear_zombie_stink_fx() +{ + self vulture_clientfield_actor_clear( "vulture_stink_trail_fx" ); +} + +stink_zombie_array_add() +{ + if ( get_unused_stink_ent_count() > 0 ) + { + self.stink_ent = get_unused_stink_ent(); + if ( isDefined( self.stink_ent ) ) + { + self.stink_ent.owner = self; + wait_network_frame(); + wait_network_frame(); + self.stink_ent thread _show_debug_location(); + self vulture_clientfield_actor_set( "vulture_stink_trail_fx" ); + level.perk_vulture.last_stink_zombie_spawned = getTime(); + self.is_stink_zombie = 1; + } + } + else + { + self.is_stink_zombie = 0; + } +} + +should_zombie_have_stink() +{ + if ( isDefined( self.animname ) ) + { + b_is_zombie = self.animname == "zombie"; + } + b_cooldown_up = ( getTime() - level.perk_vulture.last_stink_zombie_spawned ) > ( getDvarInt( #"47A03A7E" ) * 1000 ); + b_roll_passed = ( 100 - randomint( 100 ) ) > 50; + b_stink_ent_available = get_unused_stink_ent_count() > 0; + if ( b_is_zombie && b_roll_passed && b_cooldown_up ) + { + b_should_have_stink = b_stink_ent_available; + } + return b_should_have_stink; +} + +vulture_debug_text( str_text ) +{ +/# + if ( getDvarInt( #"38E68F2B" ) ) + { + iprintln( str_text ); +#/ + } +} + +vulture_clientfield_scriptmover_set( str_field_name ) +{ +/# + assert( isDefined( level.perk_vulture.clientfields.scriptmovers[ str_field_name ] ), str_field_name + " is not a valid client field for vulture perk!" ); +#/ + n_value = self getclientfield( "vulture_perk_scriptmover" ); + n_value |= 1 << level.perk_vulture.clientfields.scriptmovers[ str_field_name ]; + self setclientfield( "vulture_perk_scriptmover", n_value ); +} + +vulture_clientfield_scriptmover_clear( str_field_name ) +{ +/# + assert( isDefined( level.perk_vulture.clientfields.scriptmovers[ str_field_name ] ), str_field_name + " is not a valid client field for vulture perk!" ); +#/ + n_value = self getclientfield( "vulture_perk_scriptmover" ); + n_value &= 1 << level.perk_vulture.clientfields.scriptmovers[ str_field_name ]; + self setclientfield( "vulture_perk_scriptmover", n_value ); +} + +vulture_clientfield_actor_set( str_field_name ) +{ +/# + assert( isDefined( level.perk_vulture.clientfields.actors[ str_field_name ] ), str_field_name + " is not a valid field for vulture_clientfield_actor_set!" ); +#/ + n_value = getclientfield( "vulture_perk_actor" ); + n_value |= 1 << level.perk_vulture.clientfields.actors[ str_field_name ]; + self setclientfield( "vulture_perk_actor", n_value ); +} + +vulture_clientfield_actor_clear( str_field_name ) +{ +/# + assert( isDefined( level.perk_vulture.clientfields.actors[ str_field_name ] ), str_field_name + " is not a valid field for vulture_clientfield_actor_clear!" ); +#/ + n_value = getclientfield( "vulture_perk_actor" ); + n_value &= 1 << level.perk_vulture.clientfields.actors[ str_field_name ]; + self setclientfield( "vulture_perk_actor", n_value ); +} + +vulture_clientfield_toplayer_set( str_field_name ) +{ +/# + assert( isDefined( level.perk_vulture.clientfields.toplayer[ str_field_name ] ), str_field_name + " is not a valid client field for vulture perk!" ); +#/ + n_value = self getclientfieldtoplayer( "vulture_perk_toplayer" ); + n_value |= 1 << level.perk_vulture.clientfields.toplayer[ str_field_name ]; + self setclientfieldtoplayer( "vulture_perk_toplayer", n_value ); +} + +vulture_clientfield_toplayer_clear( str_field_name ) +{ +/# + assert( isDefined( level.perk_vulture.clientfields.toplayer[ str_field_name ] ), str_field_name + " is not a valid client field for vulture perk!" ); +#/ + n_value = self getclientfieldtoplayer( "vulture_perk_toplayer" ); + n_value &= 1 << level.perk_vulture.clientfields.toplayer[ str_field_name ]; + self setclientfieldtoplayer( "vulture_perk_toplayer", n_value ); +} + +vulture_perk_watch_mystery_box() +{ + wait_network_frame(); + while ( isDefined( level.chests ) && level.chests.size > 0 && isDefined( level.chest_index ) ) + { + level.chests[ level.chest_index ].zbarrier vulture_perk_shows_mystery_box( 1 ); + flag_wait( "moving_chest_now" ); + level.chests[ level.chest_index ].zbarrier vulture_perk_shows_mystery_box( 0 ); + flag_waitopen( "moving_chest_now" ); + } +} + +vulture_perk_shows_mystery_box( b_show ) +{ + self setclientfield( "vulture_perk_zbarrier", b_show ); +} + +vulture_perk_watch_fire_sale() +{ + wait_network_frame(); + while ( isDefined( level.chests ) && level.chests.size > 0 ) + { + level waittill( "powerup fire sale" ); + i = 0; + while ( i < level.chests.size ) + { + if ( i != level.chest_index ) + { + level.chests[ i ] thread vulture_fire_sale_box_fx_enable(); + } + i++; + } + level waittill( "fire_sale_off" ); + i = 0; + while ( i < level.chests.size ) + { + if ( i != level.chest_index ) + { + level.chests[ i ] thread vulture_fire_sale_box_fx_disable(); + } + i++; + } + } +} + +vulture_fire_sale_box_fx_enable() +{ + if ( self.zbarrier.state == "arriving" ) + { + self.zbarrier waittill( "arrived" ); + } + self.zbarrier setclientfield( "vulture_perk_zbarrier", 1 ); +} + +vulture_fire_sale_box_fx_disable() +{ + self.zbarrier setclientfield( "vulture_perk_zbarrier", 0 ); +} + +vulture_perk_watch_powerup_drops() +{ + while ( 1 ) + { + level waittill( "powerup_dropped", m_powerup ); + m_powerup thread _powerup_drop_think(); + } +} + +_powerup_drop_think() +{ + e_temp = spawn( "script_model", self.origin ); + e_temp setmodel( "tag_origin" ); + e_temp vulture_clientfield_scriptmover_set( "vulture_powerup_drop" ); + self waittill_any( "powerup_timedout", "powerup_grabbed", "death" ); + e_temp vulture_clientfield_scriptmover_clear( "vulture_powerup_drop" ); + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + e_temp delete(); +} + +vulture_zombies_find_exit_point() +{ +/# + while ( getDvarInt( #"38E68F2B" ) > 0 ) + { + _a1459 = level.enemy_dog_locations; + _k1459 = getFirstArrayKey( _a1459 ); + while ( isDefined( _k1459 ) ) + { + struct = _a1459[ _k1459 ]; + debugstar( struct.origin, 200, ( 0, 0, 1 ) ); + _k1459 = getNextArrayKey( _a1459, _k1459 ); +#/ + } + } + a_zombies = get_round_enemy_array(); + i = 0; + while ( i < a_zombies.size ) + { + a_zombies[ i ] thread zombie_goes_to_exit_location(); + i++; + } +} + +zombie_goes_to_exit_location() +{ + self endon( "death" ); + if ( isDefined( self.completed_emerging_into_playable_area ) && !self.completed_emerging_into_playable_area ) + { + self waittill( "completed_emerging_into_playable_area" ); + wait 1; + } + s_goal = _get_zombie_exit_point(); + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + if ( isDefined( s_goal ) ) + { + self setgoalpos( s_goal.origin ); + } + while ( 1 ) + { + b_passed_override = 1; + if ( isDefined( level.default_find_exit_position_override ) ) + { + b_passed_override = [[ level.default_find_exit_position_override ]](); + } + if ( !flag( "wait_and_revive" ) && b_passed_override ) + { + break; + } + else + { + wait 0,1; + } + } + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +_get_zombie_exit_point() +{ + player = get_players()[ 0 ]; + n_dot_best = 9999999; + a_exit_points = self [[ level.perk_vulture.func_zombies_find_valid_exit_locations ]](); +/# + assert( a_exit_points.size > 0, "_get_zombie_exit_point() couldn't find any zombie exit points for player at " + player.origin + "! Add more dog_locations!" ); +#/ + i = 0; + while ( i < a_exit_points.size ) + { + v_to_player = vectornormalize( player.origin - self.origin ); + v_to_goal = a_exit_points[ i ].origin - self.origin; + n_dot = vectordot( v_to_player, v_to_goal ); + if ( n_dot < n_dot_best && distancesquared( player.origin, a_exit_points[ i ].origin ) > 360000 ) + { + nd_best = a_exit_points[ i ]; + n_dot_best = n_dot; + } +/# + if ( getDvarInt( #"38E68F2B" ) ) + { + debugstar( a_exit_points[ i ].origin, 200, ( 0, 0, 1 ) ); +#/ + } + i++; + } + return nd_best; +} + +get_valid_exit_points_for_zombie() +{ + a_exit_points = level.enemy_dog_locations; + while ( isDefined( level.perk_vulture.zones_for_extra_stink_locations ) && level.perk_vulture.zones_for_extra_stink_locations.size > 0 ) + { + a_zones_with_extra_stink_locations = getarraykeys( level.perk_vulture.zones_for_extra_stink_locations ); + _a1560 = level.active_zone_names; + _k1560 = getFirstArrayKey( _a1560 ); + while ( isDefined( _k1560 ) ) + { + zone = _a1560[ _k1560 ]; + while ( isinarray( a_zones_with_extra_stink_locations, zone ) ) + { + a_zones_temp = level.perk_vulture.zones_for_extra_stink_locations[ zone ]; + i = 0; + while ( i < a_zones_temp.size ) + { + a_exit_points = arraycombine( a_exit_points, get_zone_dog_locations( a_zones_temp[ i ] ), 0, 0 ); + i++; + } + } + _k1560 = getNextArrayKey( _a1560, _k1560 ); + } + } + return a_exit_points; +} + +get_zone_dog_locations( str_zone ) +{ + a_dog_locations = []; + if ( isDefined( level.zones[ str_zone ] ) && isDefined( level.zones[ str_zone ].dog_locations ) ) + { + a_dog_locations = level.zones[ str_zone ].dog_locations; + } + return a_dog_locations; +} + +vulture_vision_toggle( b_enable ) +{ +} + +vulture_handle_solo_quick_revive() +{ + flag_wait( "initial_blackscreen_passed" ); + if ( flag( "solo_game" ) ) + { + flag_wait( "solo_revive" ); + setclientfield( "vulture_perk_disable_solo_quick_revive_glow", 1 ); + } +} + +vulture_devgui_spawn_stink() +{ +/# + player = gethostplayer(); + forward_dir = vectornormalize( anglesToForward( player.angles ) ); + target_pos = player.origin + ( forward_dir * 100 ) + vectorScale( ( 0, 0, 1 ), 50 ); + target_pos_down = target_pos + vectorScale( ( 0, 0, 1 ), 150 ); + str_bonus = "stink"; + str_identifier = "_" + "test_" + getTime(); + drop_pos = groundtrace( target_pos, target_pos_down, 0, player )[ "position" ]; + setdvarint( "zombies_debug_vulture_perk", 1 ); + player thread show_debug_info( drop_pos, str_identifier, str_bonus ); + e_temp = player maps/mp/zombies/_zm_perk_vulture::zombie_drops_stink( drop_pos, str_identifier ); + e_temp = player maps/mp/zombies/_zm_perk_vulture::_vulture_spawn_fx( str_identifier, drop_pos, str_bonus, e_temp ); + maps/mp/zombies/_zm_perk_vulture::clean_up_stink( e_temp ); +#/ +} + +setup_splitscreen_optimizations() +{ + if ( level.splitscreen && getDvarInt( "splitscreen_playerCount" ) > 2 ) + { + setdvarint( "zombies_perk_vulture_drops_max", int( getDvarInt( #"612F9831" ) * 0,5 ) ); + setdvarint( "zombies_perk_vulture_spawn_stink_zombie_cooldown", int( getDvarInt( #"47A03A7E" ) * 2 ) ); + setdvarint( "zombies_perk_vulture_max_stink_zombies", int( getDvarInt( #"16BCAE6A" ) * 0,5 ) ); + } +} + +initialize_bonus_entity_pool() +{ + n_ent_pool_size = getDvarInt( #"612F9831" ); + level.perk_vulture.bonus_drop_ent_pool = []; + i = 0; + while ( i < n_ent_pool_size ) + { + e_temp = spawn( "script_model", ( 0, 0, 1 ) ); + e_temp setmodel( "tag_origin" ); + e_temp.targetname = "vulture_perk_bonus_pool_ent"; + e_temp.in_use = 0; + level.perk_vulture.bonus_drop_ent_pool[ level.perk_vulture.bonus_drop_ent_pool.size ] = e_temp; + i++; + } +} + +get_unused_bonus_ent() +{ + e_found = undefined; + i = 0; + while ( i < level.perk_vulture.bonus_drop_ent_pool.size && !isDefined( e_found ) ) + { + if ( !level.perk_vulture.bonus_drop_ent_pool[ i ].in_use ) + { + e_found = level.perk_vulture.bonus_drop_ent_pool[ i ]; + e_found.in_use = 1; + } + i++; + } + return e_found; +} + +get_unused_bonus_ent_count() +{ + n_found = 0; + i = 0; + while ( i < level.perk_vulture.bonus_drop_ent_pool.size ) + { + if ( !level.perk_vulture.bonus_drop_ent_pool[ i ].in_use ) + { + n_found++; + } + i++; + } + return n_found; +} + +clear_bonus_ent() +{ + self notify( "stop_vulture_behavior" ); + self vulture_clientfield_scriptmover_clear( "vulture_drop_fx" ); + self.in_use = 0; + self setmodel( "tag_origin" ); + self ghost(); +} + +initialize_stink_entity_pool() +{ + n_ent_pool_size = getDvarInt( #"16BCAE6A" ); + level.perk_vulture.stink_ent_pool = []; + i = 0; + while ( i < n_ent_pool_size ) + { + e_temp = spawn( "script_model", ( 0, 0, 1 ) ); + e_temp setmodel( "tag_origin" ); + e_temp.targetname = "vulture_perk_bonus_pool_ent"; + e_temp.in_use = 0; + level.perk_vulture.stink_ent_pool[ level.perk_vulture.stink_ent_pool.size ] = e_temp; + i++; + } +} + +get_unused_stink_ent_count() +{ + n_found = 0; + i = 0; + while ( i < level.perk_vulture.stink_ent_pool.size ) + { + if ( !level.perk_vulture.stink_ent_pool[ i ].in_use ) + { + n_found++; + i++; + continue; + } + else + { + if ( !isDefined( level.perk_vulture.stink_ent_pool[ i ].owner ) && !isDefined( level.perk_vulture.stink_ent_pool[ i ].drop_time ) ) + { + level.perk_vulture.stink_ent_pool[ i ] clear_stink_ent(); + n_found++; + } + } + i++; + } + return n_found; +} + +get_unused_stink_ent() +{ + e_found = undefined; + i = 0; + while ( i < level.perk_vulture.stink_ent_pool.size && !isDefined( e_found ) ) + { + if ( !level.perk_vulture.stink_ent_pool[ i ].in_use ) + { + e_found = level.perk_vulture.stink_ent_pool[ i ]; + e_found.in_use = 1; + vulture_debug_text( "vulture stink >> ent " + e_found getentitynumber() + " in use" ); + } + i++; + } + return e_found; +} + +clear_stink_ent() +{ + vulture_debug_text( "vulture stink >> ent " + self getentitynumber() + " CLEAR" ); + self vulture_clientfield_scriptmover_clear( "vulture_stink_fx" ); + self notify( "stop_vulture_behavior" ); + self.in_use = 0; + self.drop_time = undefined; + self.owner = undefined; + self setmodel( "tag_origin" ); + self ghost(); +} + +_show_debug_location() +{ +/# + while ( self.in_use ) + { + if ( getDvarInt( #"38E68F2B" ) > 0 ) + { + debugstar( self.origin, 1, ( 0, 0, 1 ) ); + print3d( self.origin, self getentitynumber(), ( 0, 0, 1 ), 1, 1, 1 ); + } + wait 0,05; +#/ + } +} + +handle_custom_weapon_refunds( str_weapon ) +{ + b_is_custom_weapon = 0; + if ( issubstr( str_weapon, "knife_ballistic" ) ) + { + self _refund_oldest_ballistic_knife( str_weapon ); + b_is_custom_weapon = 1; + } + return b_is_custom_weapon; +} + +_refund_oldest_ballistic_knife( str_weapon ) +{ + self endon( "death_or_disconnect" ); + self endon( "vulture_perk_lost" ); + if ( isDefined( self.weaponobjectwatcherarray ) && self.weaponobjectwatcherarray.size > 0 ) + { + b_found_weapon_object = 0; + i = 0; + while ( i < self.weaponobjectwatcherarray.size ) + { + if ( isDefined( self.weaponobjectwatcherarray[ i ].weapon ) && self.weaponobjectwatcherarray[ i ].weapon == str_weapon ) + { + s_found = self.weaponobjectwatcherarray[ i ]; + break; + } + else + { + i++; + } + } + if ( isDefined( s_found ) ) + { + if ( isDefined( s_found.objectarray ) && s_found.objectarray.size > 0 ) + { + e_oldest = undefined; + i = 0; + while ( i < s_found.objectarray.size ) + { + if ( isDefined( s_found.objectarray[ i ] ) ) + { + if ( isDefined( s_found.objectarray[ i ].retrievabletrigger ) && isDefined( s_found.objectarray[ i ].retrievabletrigger.owner ) || s_found.objectarray[ i ].retrievabletrigger.owner != self && !isDefined( s_found.objectarray[ i ].birthtime ) ) + { + i++; + continue; + } + else + { + if ( !isDefined( e_oldest ) ) + { + e_oldest = s_found.objectarray[ i ]; + } + if ( s_found.objectarray[ i ].birthtime < e_oldest.birthtime ) + { + e_oldest = s_found.objectarray[ i ]; + } + } + } + i++; + } + if ( isDefined( e_oldest ) ) + { + e_oldest.retrievabletrigger.force_pickup = 1; + e_oldest.retrievabletrigger notify( "trigger" ); + } + } + } + } +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc b/zm_buried_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc new file mode 100644 index 0000000..04f7af6 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_weap_bowie.gsc b/zm_buried_patch/maps/mp/zombies/_zm_weap_bowie.gsc new file mode 100644 index 0000000..4ad88c6 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_weap_claymore.gsc b/zm_buried_patch/maps/mp/zombies/_zm_weap_claymore.gsc new file mode 100644 index 0000000..2ccc1ab --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_weap_claymore.gsc @@ -0,0 +1,476 @@ +#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" ); + } + } + } +} + +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_buried_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc b/zm_buried_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc new file mode 100644 index 0000000..48ea6b2 --- /dev/null +++ b/zm_buried_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_buried_patch/maps/mp/zombies/_zm_weap_time_bomb.gsc b/zm_buried_patch/maps/mp/zombies/_zm_weap_time_bomb.gsc new file mode 100644 index 0000000..807dbe7 --- /dev/null +++ b/zm_buried_patch/maps/mp/zombies/_zm_weap_time_bomb.gsc @@ -0,0 +1,2329 @@ +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_weapon_locker; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +register_time_bomb_enemy( str_type, func_conditions_for_round, func_save_enemy_data, func_respawn_enemies ) +{ +/# + assert( isDefined( str_type ), "str_type is a required parameter for register_time_bomb_enemy! This identifies the round type" ); +#/ +/# + assert( isDefined( func_conditions_for_round ), "func_conditions_for_round is a required parameter for register_time_bomb_enemy! This returns a bool that tells the script what type of round it is." ); +#/ +/# + assert( isDefined( func_save_enemy_data ), "func_save_enemy_data is a required parameter for register_time_bomb_enemy! This should store all relevant data about an individual enemy, and requires one input argument." ); +#/ +/# + assert( isDefined( func_respawn_enemies ), "func_respawn is a required parameter for register_time_bomb_enemy! This will run a function to respawn the new creature type." ); +#/ + if ( !isDefined( level._time_bomb.enemy_type[ str_type ] ) ) + { + level._time_bomb.enemy_type[ str_type ] = spawnstruct(); + } + level._time_bomb.enemy_type[ str_type ].conditions_for_round = func_conditions_for_round; + level._time_bomb.enemy_type[ str_type ].enemy_data_save_func = func_save_enemy_data; + level._time_bomb.enemy_type[ str_type ].respawn_func = func_respawn_enemies; +} + +register_time_bomb_enemy_save_filter( str_type, func_filter_save ) +{ +/# + assert( isDefined( str_type ), "str_type is a required parameter for register_time_bomb_enemy_save_filter! This identifies the round type where the filter function should run." ); +#/ +/# + assert( isDefined( level._time_bomb.enemy_type ), str_type + " enemy type is not yet registered with the time bomb system scripts. Register that type before calling register_time_bomb_enemy_save_filter()" ); +#/ + level._time_bomb.enemy_type[ str_type ].enemy_data_save_filter_func = func_filter_save; +} + +register_time_bomb_enemy_default( str_type ) +{ +/# + assert( isDefined( level._time_bomb.enemy_type[ str_type ] ), str_type + " enemy type is not set up in time bomb enemy array! Initialize this enemy before trying to make it the default." ); +#/ + level._time_bomb.enemy_type_default = str_type; +} + +time_bomb_add_custom_func_global_save( func_save ) +{ + if ( !isDefined( level._time_bomb.custom_funcs_save ) ) + { + level._time_bomb.custom_funcs_save = []; + } + level._time_bomb.custom_funcs_save[ level._time_bomb.custom_funcs_save.size ] = func_save; +} + +time_bomb_add_custom_func_global_restore( func_restore ) +{ + if ( !isDefined( level._time_bomb.custom_funcs_restore ) ) + { + level._time_bomb.custom_funcs_restore = []; + } + level._time_bomb.custom_funcs_restore[ level._time_bomb.custom_funcs_restore.size ] = func_restore; +} + +get_time_bomb_saved_round_type() +{ + if ( !isDefined( level.time_bomb_save_data ) || !isDefined( level.time_bomb_save_data.round_type ) ) + { + str_type = "none"; + } + else + { + str_type = level.time_bomb_save_data.round_type; + } + return str_type; +} + +init_time_bomb() +{ + time_bomb_precache(); + level thread time_bomb_post_init(); + flag_init( "time_bomb_round_killed" ); + flag_init( "time_bomb_enemies_restored" ); + flag_init( "time_bomb_zombie_respawning_done" ); + flag_init( "time_bomb_restore_active" ); + flag_init( "time_bomb_restore_done" ); + flag_init( "time_bomb_global_restore_done" ); + flag_init( "time_bomb_detonation_enabled" ); + flag_init( "time_bomb_stores_door_state" ); + registerclientfield( "world", "time_bomb_saved_round_number", 12000, 8, "int" ); + registerclientfield( "world", "time_bomb_lua_override", 12000, 1, "int" ); + registerclientfield( "world", "time_bomb_hud_toggle", 12000, 1, "int" ); + registerclientfield( "toplayer", "sndTimebombLoop", 12000, 2, "int" ); + maps/mp/zombies/_zm_weapons::register_zombie_weapon_callback( "time_bomb_zm", ::player_give_time_bomb ); + level.zombiemode_time_bomb_give_func = ::player_give_time_bomb; + include_weapon( "time_bomb_zm", 1 ); + maps/mp/zombies/_zm_weapons::add_limited_weapon( "time_bomb_zm", 1 ); + register_tactical_grenade_for_level( "time_bomb_zm" ); + add_time_bomb_to_mystery_box(); + register_equipment_for_level( "time_bomb_zm" ); + register_equipment_for_level( "time_bomb_detonator_zm" ); + if ( !isDefined( level.round_wait_func ) ) + { + level.round_wait_func = ::time_bomb_round_wait; + } + level.zombie_round_change_custom = ::time_bomb_custom_round_change; + level._effect[ "time_bomb_set" ] = loadfx( "weapon/time_bomb/fx_time_bomb_detonate" ); + level._effect[ "time_bomb_ammo_fx" ] = loadfx( "misc/fx_zombie_powerup_on" ); + level._effect[ "time_bomb_respawns_enemy" ] = loadfx( "maps/zombie_buried/fx_buried_time_bomb_spawn" ); + level._effect[ "time_bomb_kills_enemy" ] = loadfx( "maps/zombie_buried/fx_buried_time_bomb_death" ); + level._time_bomb = spawnstruct(); + level._time_bomb.enemy_type = []; + register_time_bomb_enemy( "zombie", ::is_zombie_round, ::time_bomb_saves_zombie_data, ::time_bomb_respawns_zombies ); + register_time_bomb_enemy_default( "zombie" ); + level._time_bomb.last_round_restored = -1; + flag_set( "time_bomb_detonation_enabled" ); +/# + level thread test_mode(); +#/ +} + +has_time_bomb_restored_this_round() +{ + return level._time_bomb.last_round_restored == level.round_number; +} + +time_bomb_precache() +{ + precacheshader( "zombie_hud_time_bomb" ); + precacheitem( "time_bomb_detonator_zm" ); +} + +time_bomb_post_init() +{ + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zombie_time_bomb_overlay", 12000, 200, 20, 0, ::time_bomb_overlay_lerp_thread ); +} + +add_time_bomb_to_mystery_box() +{ + maps/mp/zombies/_zm_weapons::add_zombie_weapon( "time_bomb_zm", undefined, &"ZOMBIE_WEAPON_TIME_BOMB", 50, "pickup_bomb", "", undefined, 1 ); +} + +player_give_time_bomb() +{ +/# + assert( isplayer( self ), "player_give_time_bomb can only be used on players!" ); +#/ + self giveweapon( "time_bomb_zm" ); + self swap_weapon_to_time_bomb(); + self thread show_time_bomb_hints(); + self thread time_bomb_think(); + self thread watch_for_tactical_grenade_change(); + self thread detonator_think(); + self thread time_bomb_inventory_slot_think(); + self thread destroy_time_bomb_save_if_user_bleeds_out_or_disconnects(); + self thread sndwatchforweapswitch(); +} + +sndwatchforweapswitch() +{ + self endon( "disconnect" ); + self.sndlastweapon = ""; + while ( 1 ) + { + self waittill( "weapon_change", weapon ); + if ( weapon == "time_bomb_zm" ) + { + self setclientfieldtoplayer( "sndTimebombLoop", 1 ); + self.sndlastweapon = "time_bomb_zm"; + continue; + } + else if ( weapon == "time_bomb_detonator_zm" ) + { + self setclientfieldtoplayer( "sndTimebombLoop", 2 ); + self.sndlastweapon = "time_bomb_detonator_zm"; + continue; + } + else + { + if ( self.sndlastweapon == "time_bomb_zm" || self.sndlastweapon == "time_bomb_detonator_zm" ) + { + self setclientfieldtoplayer( "sndTimebombLoop", 0 ); + } + } + } +} + +time_bomb_think() +{ + self notify( "_time_bomb_kill_thread" ); + self endon( "_time_bomb_kill_thread" ); + self endon( "death" ); + self endon( "disconnect" ); + self endon( "player_lost_time_bomb" ); + while ( 1 ) + { + self waittill( "grenade_fire", e_grenade, str_grenade_name ); + if ( str_grenade_name == "time_bomb_zm" ) + { + if ( isDefined( str_grenade_name ) && str_grenade_name == "time_bomb_zm" ) + { + e_grenade thread setup_time_bomb_detonation_model(); + time_bomb_saves_data(); + e_grenade time_bomb_model_init(); + self thread swap_weapon_to_detonator( e_grenade ); + self thread time_bomb_thrown_vo(); + } + } + } +} + +time_bomb_thrown_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + wait 1,5; + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "throw_bomb" ); +} + +time_bomb_model_init() +{ + delete_existing_time_bomb_model(); + level.time_bomb_save_data.time_bomb_model = self; + level.time_bomb_save_data.time_bomb_model playloopsound( "zmb_timebomb_3d_timer", 1 ); + level notify( "new_time_bomb_set" ); + playsoundatposition( "zmb_timebomb_plant_2d", ( 0, 0, 0 ) ); +} + +delete_existing_time_bomb_model() +{ + if ( isDefined( level.time_bomb_save_data ) && isDefined( level.time_bomb_save_data.time_bomb_model ) && isDefined( level.time_bomb_save_data.time_bomb_model.origin ) ) + { + level.time_bomb_save_data.time_bomb_model delete_time_bomb_model(); + } +} + +setup_time_bomb_detonation_model() +{ + playfxontag( level._effect[ "time_bomb_ammo_fx" ], self, "tag_origin" ); +} + +detonate_time_bomb() +{ + if ( isDefined( level.time_bomb_save_data.time_bomb_model ) && isDefined( level.time_bomb_save_data.time_bomb_model.origin ) ) + { + playsoundatposition( "zmb_timebomb_3d_timer_end", level.time_bomb_save_data.time_bomb_model.origin ); + } + delete_time_bomb_model(); + if ( time_bomb_save_exists() ) + { + level thread time_bomb_restores_saved_data(); + } +} + +delete_time_bomb_model() +{ + if ( isDefined( self ) && isDefined( self.origin ) ) + { + playfx( level._effect[ "time_bomb_set" ], self.origin ); + self delete(); + } +} + +watch_for_tactical_grenade_change() +{ + self notify( "_time_bomb_kill_tactical_grenade_watch" ); + self endon( "_time_bomb_kill_tactical_grenade_watch" ); + self endon( "death" ); + self endon( "disconnect" ); + while ( self hasweapon( "time_bomb_zm" ) ) + { + self waittill( "new_tactical_grenade" ); + } + if ( self hasweapon( "time_bomb_detonator_zm" ) ) + { + self takeweapon( "time_bomb_detonator_zm" ); + } + self notify( "player_lost_time_bomb" ); + destroy_time_bomb_save(); +} + +destroy_time_bomb_save() +{ + delete_existing_time_bomb_model(); + time_bomb_destroy_hud_elem(); + time_bomb_clears_global_data(); + self clean_up_time_bomb_notifications(); +} + +show_time_bomb_notification( str_text ) +{ + self thread show_equipment_hint_text( str_text ); +} + +clean_up_time_bomb_notifications() +{ + self notify( "hide_equipment_hint_text" ); +} + +time_bomb_saves_data( b_show_icon, save_struct ) +{ + level thread _time_bomb_saves_data( b_show_icon, save_struct ); +} + +_time_bomb_saves_data( b_show_icon, save_struct ) +{ + if ( !isDefined( b_show_icon ) ) + { + b_show_icon = 1; + } + debug_time_bomb_print( "TIME BOMB SET! Saving..." ); + if ( !isDefined( save_struct ) && !time_bomb_save_exists() ) + { + level.time_bomb_save_data = spawnstruct(); + } + time_bomb_saves_global_data( save_struct ); + time_bomb_saves_player_data( save_struct ); + if ( isDefined( save_struct ) ) + { + save_struct.save_ready = 1; + } + else + { + level.time_bomb_save_data.save_ready = 1; + } + if ( b_show_icon ) + { + time_bomb_hud_icon_show(); + } +} + +time_bomb_saves_global_data( save_struct ) +{ + if ( !isDefined( save_struct ) ) + { + s_temp = level.time_bomb_save_data; + } + else + { + s_temp = save_struct; + } + s_temp.n_time_id = getTime(); + s_temp.round_number = level.round_number; + s_temp.round_initialized = level._time_bomb.round_initialized; + s_temp.round_type = _get_time_bomb_round_type(); + s_temp = _time_bomb_saves_enemy_info( s_temp ); + if ( flag( "time_bomb_stores_door_state" ) ) + { + _time_bomb_saves_door_states( s_temp ); + } + s_temp.custom_data = spawnstruct(); + while ( isDefined( level._time_bomb.custom_funcs_save ) ) + { + i = 0; + while ( i < level._time_bomb.custom_funcs_save.size ) + { + s_temp.custom_data [[ level._time_bomb.custom_funcs_save[ i ] ]](); + i++; + } + } + if ( !isDefined( save_struct ) ) + { + level.time_bomb_save_data = s_temp; + } +} + +_time_bomb_saves_door_states( s_temp ) +{ + a_doors = getentarray( "zombie_door", "targetname" ); + s_temp.door_states = []; + _a426 = a_doors; + _k426 = getFirstArrayKey( _a426 ); + while ( isDefined( _k426 ) ) + { + door = _a426[ _k426 ]; + door thread store_door_state( s_temp ); + _k426 = getNextArrayKey( _a426, _k426 ); + } +} + +store_door_state( s_temp ) +{ + s_door_struct = spawnstruct(); + s_door_struct.doors = []; + if ( isDefined( self._door_open ) || self._door_open && isDefined( self.has_been_opened ) && self.has_been_opened ) + { + if ( isDefined( self.is_moving ) && self.is_moving ) + { + self waittill_either( "movedone", "rotatedone" ); + } + _a445 = self.doors; + _k445 = getFirstArrayKey( _a445 ); + while ( isDefined( _k445 ) ) + { + door = _a445[ _k445 ]; + s = spawnstruct(); + s.saved_angles = door.angles; + s.saved_origin = door.origin; + s_door_struct.doors[ s_door_struct.doors.size ] = s; + _k445 = getNextArrayKey( _a445, _k445 ); + } + s_door_struct.state = 1; + } + else + { + _a459 = self.doors; + _k459 = getFirstArrayKey( _a459 ); + while ( isDefined( _k459 ) ) + { + door = _a459[ _k459 ]; + s = spawnstruct(); + s.saved_angles = door.og_angles; + s.saved_origin = door.origin; + s_door_struct.doors[ s_door_struct.doors.size ] = s; + _k459 = getNextArrayKey( _a459, _k459 ); + } + s_door_struct.state = 0; + } + s_temp.door_states[ self getentitynumber() ] = s_door_struct; +} + +_time_bomb_restores_door_states( s_temp ) +{ + if ( !isDefined( s_temp.door_states ) ) + { +/# + assertmsg( "Trying to restore door states, where none have been saved." ); +#/ + return; + } + a_doors = getentarray( "zombie_door", "targetname" ); + _a486 = a_doors; + _k486 = getFirstArrayKey( _a486 ); + while ( isDefined( _k486 ) ) + { + door = _a486[ _k486 ]; + door thread restore_door_state( s_temp ); + _k486 = getNextArrayKey( _a486, _k486 ); + } +} + +restore_door_state( s_temp ) +{ + s_door_struct = s_temp.door_states[ self getentitynumber() ]; + if ( !isDefined( s_door_struct ) ) + { +/# + assertmsg( "Trying to restore doorstate for door @ " + self.origin + " but none saved." ); +#/ + return; + } + if ( isDefined( self._door_open ) || self._door_open && isDefined( self.has_been_opened ) && self.has_been_opened ) + { + if ( s_door_struct.state == 1 ) + { + return; + } + i = 0; + while ( i < s_door_struct.doors.size ) + { + if ( isDefined( self.doors[ i ].script_string ) && self.doors[ i ].script_string == "rotate" ) + { + self.doors[ i ] rotateto( self.doors[ i ].og_angles, 0,05, 0, 0 ); + wait 0,05; + } + self.doors[ i ] solid(); + self.doors[ i ] disconnectpaths(); + i++; + } + self._door_open = 0; + self.has_been_opened = 0; + self setvisibletoall(); + self notify( "kill_door_think" ); + self thread maps/mp/zombies/_zm_blockers::door_init(); + } + else + { + if ( s_door_struct.state == 0 ) + { + return; + } + i = 0; + while ( i < s_door_struct.doors.size ) + { + if ( isDefined( self.doors[ i ].script_string ) && self.doors[ i ].script_string == "rotate" ) + { + self.doors[ i ] rotateto( s_door_struct.doors[ i ].script_angles, 0,05, 0, 0 ); + } + self.doors[ i ] notsolid(); + self.doors[ i ] disconnectpaths(); + i++; + } + self._door_open = 1; + self.has_been_opened = 1; + self setinvisibletoall(); + self notify( "kill_door_think" ); + } +} + +_time_bomb_saves_enemy_info( s_temp ) +{ + s_temp.enemies = []; + s_temp.zombie_total = level.zombie_total; + a_enemies = time_bomb_get_enemy_array(); +/# + assert( isDefined( level._time_bomb.enemy_type[ s_temp.round_type ].enemy_data_save_func ), "enemy save data func is missing for AI type " + s_temp.round_type ); +#/ + i = 0; + while ( i < a_enemies.size ) + { + s_data = spawnstruct(); + if ( !isDefined( level._time_bomb.enemy_type[ s_temp.round_type ].enemy_data_save_filter_func ) || a_enemies[ i ] [[ level._time_bomb.enemy_type[ s_temp.round_type ].enemy_data_save_filter_func ]]() ) + { + a_enemies[ i ] [[ level._time_bomb.enemy_type[ s_temp.round_type ].enemy_data_save_func ]]( s_data ); + s_temp.enemies[ s_temp.enemies.size ] = s_data; + } + i++; + } + return s_temp; +} + +time_bomb_saves_player_data( save_struct ) +{ + a_players = get_players(); + if ( isDefined( save_struct ) ) + { + save_struct.player_saves = []; + } + _a593 = a_players; + _k593 = getFirstArrayKey( _a593 ); + while ( isDefined( _k593 ) ) + { + player = _a593[ _k593 ]; + player_save_struct = undefined; + if ( isDefined( save_struct ) ) + { + save_struct.player_saves[ player getentitynumber() ] = spawnstruct(); + player_save_struct = save_struct; + } + player _time_bomb_save_internal( player_save_struct ); + _k593 = getNextArrayKey( _a593, _k593 ); + } +} + +_time_bomb_save_internal( save_struct ) +{ + if ( !isDefined( save_struct ) && !isDefined( self.time_bomb_save_data ) ) + { + self.time_bomb_save_data = spawnstruct(); + } + if ( !self ent_flag_exist( "time_bomb_restore_thread_done" ) ) + { + self ent_flag_init( "time_bomb_restore_thread_done" ); + } + self ent_flag_clear( "time_bomb_restore_thread_done" ); + s_temp = spawnstruct(); + s_temp.weapons = spawnstruct(); + if ( isDefined( save_struct ) ) + { + s_temp.n_time_id = save_struct.n_time_id; + } + else + { + s_temp.n_time_id = level.time_bomb_save_data.n_time_id; + } + s_temp.player_origin = self.origin; + s_temp.player_angles = self getplayerangles(); + s_temp.player_stance = self getstance(); + s_temp.is_last_stand = self maps/mp/zombies/_zm_laststand::player_is_in_laststand(); + s_temp.stored_weapon_info = self.stored_weapon_info; + s_temp.is_spectator = self is_spectator(); + s_temp.weapons.array = self getweaponslist(); + s_temp.weapons.ammo_reserve = []; + s_temp.weapons.ammo_clip = []; + s_temp.weapons.type = []; + s_temp.weapons.primary = self getcurrentweapon(); + if ( s_temp.weapons.primary == "none" || s_temp.weapons.primary == "time_bomb_zm" ) + { + self thread _save_time_bomb_weapon_after_switch( save_struct ); + } + i = 0; + while ( i < s_temp.weapons.array.size ) + { + str_weapon_temp = s_temp.weapons.array[ i ]; + s_temp.weapons.ammo_reserve[ i ] = self getweaponammostock( str_weapon_temp ); + if ( weaponfuellife( str_weapon_temp ) > 0 ) + { + n_ammo_amount = self getweaponammofuel( str_weapon_temp ); + n_type = 1; + } + else if ( self isweaponoverheating( 1, str_weapon_temp ) > 0 ) + { + n_ammo_amount = self isweaponoverheating( 1, str_weapon_temp ); + n_type = 2; + } + else + { + n_ammo_amount = self getweaponammoclip( str_weapon_temp ); + n_type = 0; + } + s_temp.weapons.type[ i ] = n_type; + s_temp.weapons.ammo_clip[ i ] = n_ammo_amount; + i++; + } + s_temp.current_equipment = self.current_equipment; + s_temp.perks_all = self get_player_perk_list(); + s_temp.perks_disabled = self.disabled_perks; + s_temp.perk_count = self.num_perks; + s_temp.lives_remaining = self.lives; + if ( isDefined( self.perks_active ) ) + { + s_temp.perks_active = arraycopy( self.perks_active ); + } + s_temp.points_current = self.score; + if ( is_weapon_locker_available_in_game() ) + { + s_temp.weapon_locker_data = self maps/mp/zombies/_zm_weapon_locker::wl_get_stored_weapondata(); + } + s_temp.account_value = self.account_value; + s_temp.save_ready = 1; + if ( isDefined( save_struct ) ) + { + save_struct.player_saves[ self getentitynumber() ] = s_temp; + } + else + { + self.time_bomb_save_data = s_temp; + } +} + +is_weapon_locker_available_in_game() +{ + if ( isDefined( level.weapon_locker_online ) && level.weapon_locker_online ) + { + return isDefined( level.weapon_locker_map ); + } +} + +_save_time_bomb_weapon_after_switch( save_struct ) +{ + self endon( "death" ); + self endon( "disconnect" ); + level endon( "time_bomb_restore_active" ); + if ( !self is_spectator() ) + { + self waittill( "weapon_change" ); + str_weapon = self getcurrentweapon(); + if ( str_weapon == "none" ) + { + b_valid_weapon = 0; + } + else + { + str_type = weapontype( str_weapon ); + if ( str_type != "grenade" && str_type != "melee" ) + { + b_valid_weapon = str_weapon != "time_bomb_zm"; + } + } + if ( isDefined( save_struct ) ) + { + save_struct.player_saves[ self getentitynumber() ].weapons.primary = str_weapon; + return; + } + else + { + self.time_bomb_save_data.weapons.primary = str_weapon; + } + } +} + +time_bomb_save_exists() +{ + if ( isDefined( level.time_bomb_save_data ) ) + { + if ( isDefined( level.time_bomb_save_data.save_ready ) ) + { + return level.time_bomb_save_data.save_ready; + } + } +} + +detonator_think() +{ + self notify( "_detonator_think_done" ); + self endon( "_detonator_think_done" ); + self endon( "death" ); + self endon( "disconnect" ); + self endon( "player_lost_time_bomb" ); + debug_time_bomb_print( "player picked up detonator" ); + while ( 1 ) + { + self waittill( "detonate" ); + debug_time_bomb_print( "detonate detected! " ); + if ( time_bomb_save_exists() && flag( "time_bomb_detonation_enabled" ) ) + { + level.time_bomb_save_data.player_used = self; + level.time_bomb_save_data.time_bomb_model thread detonate_time_bomb(); + self notify( "player_activates_timebomb" ); + self thread time_bomb_detonation_vo(); + } + } +} + +time_bomb_detonation_vo() +{ + self endon( "death" ); + self endon( "disconnect" ); + level.time_bomb_detonation_vo = 1; + level waittill( "time_bomb_detonation_complete" ); + wait 2; + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "activate_bomb" ); + level.time_bomb_detonation_vo = 0; +} + +_watch_for_detonation() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "_kill_detonator_watcher" ); + while ( 1 ) + { + self waittill( "detonate" ); + if ( time_bomb_save_exists() ) + { + level thread time_bomb_restores_saved_data(); + } + } +} + +time_bomb_inventory_slot_think() +{ + self notify( "_time_bomb_inventory_think_done" ); + self endon( "_time_bomb_inventory_think_done" ); + self endon( "death_or_disconnect" ); + self endon( "player_lost_time_bomb" ); + self.time_bomb_detonator_only = 0; + while ( 1 ) + { + self waittill( "zmb_max_ammo" ); + if ( self.time_bomb_detonator_only ) + { + self.time_bomb_detonator_only = 0; + } + self swap_weapon_to_time_bomb(); + } +} + +time_bomb_restores_saved_data( b_show_fx, save_struct ) +{ + if ( !isDefined( b_show_fx ) ) + { + b_show_fx = 1; + } + level setclientfield( "time_bomb_lua_override", 1 ); + debug_time_bomb_print( "GO BACK IN TIME!" ); + n_time_start = getTime(); + flag_set( "time_bomb_restore_active" ); + if ( isDefined( level._time_bomb.functionality_override ) && level._time_bomb.functionality_override ) + { + return; + } + if ( b_show_fx ) + { + playsoundatposition( "zmb_timebomb_timechange_2d", ( 0, 0, 0 ) ); + _time_bomb_show_overlay(); + } + flag_clear( "time_bomb_enemies_restored" ); + flag_clear( "time_bomb_round_killed" ); + slow_all_actors(); + level thread time_bomb_restores_global_data( save_struct, n_time_start ); + flag_wait( "time_bomb_round_killed" ); + timebomb_wait_for_hostmigration(); + time_bomb_restores_player_data( n_time_start, save_struct ); + timebomb_wait_for_hostmigration(); + if ( !isDefined( save_struct ) ) + { + time_bomb_clears_global_data(); + time_bomb_clears_player_data(); + } + timebomb_wait_for_hostmigration(); + flag_wait( "time_bomb_global_restore_done" ); + if ( b_show_fx ) + { + _time_bomb_hide_overlay( n_time_start ); + } + time_bomb_destroy_hud_elem(); + flag_clear( "time_bomb_restore_active" ); + level setclientfield( "time_bomb_lua_override", 0 ); + level thread all_actors_resume_speed(); + level notify( "time_bomb_detonation_complete" ); +} + +timebomb_wait_for_hostmigration() +{ + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0,05; + } +} + +time_bomb_restores_global_data( save_struct, n_time_start ) +{ + timebomb_wait_for_hostmigration(); + debug_time_bomb_print( "TIME BOMB RESTORE GLOBAL DATA" ); + if ( isDefined( save_struct ) ) + { + s_temp = save_struct; + } + else + { + s_temp = level.time_bomb_save_data; + } + flag_clear( "time_bomb_global_restore_done" ); + s_temp.current_round = level.round_number; + level._time_bomb.changing_round = s_temp.round_number != level.round_number; + level._time_bomb.last_round_restored = s_temp.round_number; + timebomb_wait_for_hostmigration(); + if ( level._time_bomb.changing_round ) + { + level timebomb_change_to_round( s_temp.round_number ); + } + timebomb_wait_for_hostmigration(); + level _time_bomb_kill_all_active_enemies(); + timebomb_wait_for_hostmigration(); + level _time_bomb_restores_enemies( s_temp, n_time_start ); + if ( flag( "time_bomb_stores_door_state" ) ) + { + _time_bomb_restores_door_states( s_temp ); + } + timebomb_wait_for_hostmigration(); + _pack_a_punch_sequence_ends(); + timebomb_wait_for_hostmigration(); + close_magic_boxes(); + timebomb_wait_for_hostmigration(); + while ( isDefined( level._time_bomb.custom_funcs_restore ) ) + { + i = 0; + while ( i < level._time_bomb.custom_funcs_restore.size ) + { + s_temp.custom_data [[ level._time_bomb.custom_funcs_restore[ i ] ]](); + i++; + } + } + timebomb_wait_for_hostmigration(); + flag_set( "time_bomb_global_restore_done" ); +} + +_pack_a_punch_sequence_ends() +{ + while ( flag( "pack_machine_in_use" ) ) + { + _a983 = get_players(); + _k983 = getFirstArrayKey( _a983 ); + while ( isDefined( _k983 ) ) + { + player = _a983[ _k983 ]; + player notify( "pap_player_disconnected" ); + _k983 = getNextArrayKey( _a983, _k983 ); + } + _a989 = level.pap_triggers; + _k989 = getFirstArrayKey( _a989 ); + while ( isDefined( _k989 ) ) + { + trigger = _a989[ _k989 ]; + trigger notify( "pap_player_disconnected" ); + if ( isDefined( trigger.current_weapon ) && !isDefined( trigger.upgrade_name ) ) + { + trigger.upgrade_name = maps/mp/zombies/_zm_weapons::get_upgrade_weapon( trigger.current_weapon, trigger will_upgrade_weapon_as_attachment( self.current_weapon ) ); + } + _k989 = getNextArrayKey( _a989, _k989 ); + } + waittillframeend; + _a1003 = level.pap_triggers; + _k1003 = getFirstArrayKey( _a1003 ); + while ( isDefined( _k1003 ) ) + { + trigger = _a1003[ _k1003 ]; + trigger notify( "pap_timeout" ); + _k1003 = getNextArrayKey( _a1003, _k1003 ); + } + } +} + +close_magic_boxes() +{ + if ( isDefined( level.chest_index ) && isDefined( level.chests ) && level.chests.size > 0 ) + { + level.chests[ level.chest_index ] _close_magic_box(); + } + while ( isDefined( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) && level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) + { + i = 0; + while ( i < level.chests.size ) + { + if ( isDefined( level.chest_index ) && i != level.chest_index && isDefined( level.chests[ i ]._box_opened_by_fire_sale ) && level.chests[ i ]._box_opened_by_fire_sale ) + { + level.chests[ i ] _close_magic_box(); + } + i++; + } + } +} + +_close_magic_box() +{ + if ( !flag( "moving_chest_now" ) && self.zbarrier.state == "open" ) + { + if ( isDefined( self.weapon_out ) && self.weapon_out && !isDefined( self.zbarrier.weapon_model ) ) + { + self.zbarrier waittill( "randomization_done" ); + wait_network_frame(); + } + self notify( "trigger" ); + self.zbarrier notify( "weapon_grabbed" ); + self.zbarrier notify( "box_hacked_respin" ); + self.zbarrier maps/mp/zombies/_zm_magicbox::magic_box_closes(); + } +} + +_time_bomb_restores_enemies( save_struct, n_time_start ) +{ + _time_bomb_resets_all_barrier_attack_spots_taken(); + str_type = save_struct.round_type; +/# + assert( isDefined( level._time_bomb.enemy_type[ str_type ] ), str_type + " respawn type isn't set up for time bomb!" ); +#/ + _get_wait_time( n_time_start ); + timebomb_wait_for_hostmigration(); + [[ level._time_bomb.enemy_type[ str_type ].respawn_func ]]( save_struct ); +} + +_get_wait_time( n_time_start ) +{ + n_time_end = getTime(); + n_time_elapsed = ( n_time_end - n_time_start ) * 0,001; + n_delay = 2 - n_time_elapsed; + if ( n_delay > 0 ) + { + wait n_delay; + } +} + +_get_time_bomb_zombie_spawn_location() +{ + a_spawn_locations = level.zombie_spawn_locations; + a_valid_spawners = []; + i = 0; + while ( i < a_spawn_locations.size ) + { + if ( isDefined( a_spawn_locations[ i ].script_noteworthy ) ) + { + b_is_standard_spawn = a_spawn_locations[ i ].script_noteworthy == "spawn_location"; + } + if ( b_is_standard_spawn ) + { + a_valid_spawners[ a_valid_spawners.size ] = a_spawn_locations[ i ]; + } + i++; + } +/# + assert( a_valid_spawners.size > 0, "_get_time_bomb_zombie_spawn_location found no valid spawn locations!" ); +#/ + s_spawn_point = random( a_valid_spawners ); + return s_spawn_point; +} + +time_bomb_restores_player_data( n_time_start, save_struct ) +{ + _get_wait_time( n_time_start ); + white_screen_flash(); + a_players = get_players(); + _a1107 = a_players; + _k1107 = getFirstArrayKey( _a1107 ); + while ( isDefined( _k1107 ) ) + { + player = _a1107[ _k1107 ]; + player _time_bomb_restores_player_data_internal( save_struct ); + _k1107 = getNextArrayKey( _a1107, _k1107 ); + } + remove_white_screen_flash(); +} + +has_packapunch_weapon() +{ + b_player_has_packapunch_weapon = 0; + if ( isDefined( level.machine_assets ) && isDefined( level.machine_assets[ "packapunch" ] ) && isDefined( level.machine_assets[ "packapunch" ].weapon ) ) + { + b_player_has_packapunch_weapon = self hasweapon( level.machine_assets[ "packapunch" ].weapon ); + } + return b_player_has_packapunch_weapon; +} + +_time_bomb_restores_player_data_internal( save_struct ) +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + debug_time_bomb_print( "TIMEBOMB >> " + self.name + " in last stand, reviving..." ); + self maps/mp/zombies/_zm_laststand::auto_revive( self ); + } + else + { + if ( isDefined( self.sessionstate ) && self.sessionstate == "spectator" ) + { + self [[ level.spawnplayer ]](); + self thread refresh_player_navcard_hud(); + } + } + if ( isDefined( self.is_drinking ) && self.is_drinking ) + { + if ( self has_packapunch_weapon() ) + { + self.is_drinking++; + } + self thread maps/mp/zombies/_zm_perks::perk_abort_drinking( 0,1 ); + } + if ( self can_time_bomb_restore_data_on_player( save_struct ) ) + { + debug_time_bomb_print( "TIMEBOMB >> restoring player " + self.name ); + if ( !isDefined( self.time_bomb_save_data ) && !isDefined( save_struct ) ) + { + self.time_bomb_save_data = spawnstruct(); + } + if ( !isDefined( save_struct ) ) + { + s_temp = self.time_bomb_save_data; + } + else + { + s_temp = save_struct.player_saves[ self getentitynumber() ]; + } + self setorigin( s_temp.player_origin ); + self setplayerangles( s_temp.player_angles ); + self setstance( s_temp.player_stance ); + self thread _restore_player_perks_and_weapons( s_temp ); + n_difference_in_score = s_temp.points_current - self.score; + if ( n_difference_in_score > 0 ) + { + self maps/mp/zombies/_zm_score::add_to_player_score( n_difference_in_score ); + } + else + { + self maps/mp/zombies/_zm_score::minus_to_player_score( abs( n_difference_in_score ) ); + } + if ( is_weapon_locker_available_in_game() ) + { + if ( isDefined( s_temp.weapon_locker_data ) ) + { + self maps/mp/zombies/_zm_weapon_locker::wl_set_stored_weapondata( s_temp.weapon_locker_data ); + } + else + { + self maps/mp/zombies/_zm_weapon_locker::wl_clear_stored_weapondata(); + } + } + if ( isDefined( s_temp.account_value ) && isDefined( level.banking_map ) ) + { + self.account_value = s_temp.account_value; + self maps/mp/zombies/_zm_stats::set_map_stat( "depositBox", self.account_value, level.banking_map ); + } + s_temp.save_ready = 1; + if ( !isDefined( save_struct ) ) + { + self.time_bomb_save_data = s_temp; + } + self ent_flag_wait( "time_bomb_restore_thread_done" ); + } + else + { + debug_time_bomb_print( "TIMEBOMB >> restoring player " + self.name + " FAILED. No matching save detected" ); + self restore_player_to_initial_loadout(); + } + self _give_revive_points( s_temp ); +} + +_restore_player_perks_and_weapons( s_temp ) +{ + if ( isDefined( s_temp.is_spectator ) && s_temp.is_spectator ) + { + self restore_player_to_initial_loadout( s_temp ); + } + else + { + if ( isDefined( s_temp.is_last_stand ) && s_temp.is_last_stand ) + { + self.stored_weapon_info = s_temp.stored_weapon_info; +/# + assert( isDefined( level.zombie_last_stand_ammo_return ), "time bomb attempting to give player back weapons taken by last stand, but level.zombie_last_stand_ammo_return is undefined!" ); +#/ + self [[ level.zombie_last_stand_ammo_return ]](); + } + else + { + a_current_perks = self get_player_perk_list(); + _a1251 = a_current_perks; + _k1251 = getFirstArrayKey( _a1251 ); + while ( isDefined( _k1251 ) ) + { + perk = _a1251[ _k1251 ]; + self notify( perk + "_stop" ); + _k1251 = getNextArrayKey( _a1251, _k1251 ); + } + wait_network_frame(); + if ( get_players().size == 1 ) + { + if ( isinarray( s_temp.perks_all, "specialty_quickrevive" ) && isDefined( level.solo_lives_given ) && level.solo_lives_given > 0 && level.solo_lives_given < 3 && isDefined( self.lives ) && self.lives == 1 ) + { + level.solo_lives_given--; + + } + } + while ( isDefined( s_temp.perks_active ) ) + { + i = 0; + while ( i < s_temp.perks_active.size ) + { + if ( get_players().size == 1 && s_temp.perks_active[ i ] == "specialty_quickrevive" ) + { + if ( isDefined( level.solo_lives_given ) && level.solo_lives_given == 3 && isDefined( self.lives ) && self.lives == 0 ) + { + i++; + continue; + } + } + else + { + self maps/mp/zombies/_zm_perks::give_perk( s_temp.perks_active[ i ] ); + wait_network_frame(); + if ( isDefined( s_temp.perks_disabled ) && isDefined( s_temp.perks_disabled[ s_temp.perks_active[ i ] ] ) && s_temp.perks_disabled[ s_temp.perks_active[ i ] ] ) + { + self maps/mp/zombies/_zm_perks::perk_pause( s_temp.perks_active[ i ] ); + wait_network_frame(); + } + } + i++; + } + } + self.disabled_perks = s_temp.perks_disabled; + self.num_perks = s_temp.perk_count; + self.lives = s_temp.lives_remaining; + self takeallweapons(); + self set_player_melee_weapon( level.zombie_melee_weapon_player_init ); + i = 0; + while ( i < s_temp.weapons.array.size ) + { + str_weapon_temp = s_temp.weapons.array[ i ]; + n_ammo_reserve = s_temp.weapons.ammo_reserve[ i ]; + n_ammo_clip = s_temp.weapons.ammo_clip[ i ]; + n_type = s_temp.weapons.type[ i ]; + if ( !is_temporary_zombie_weapon( str_weapon_temp ) && str_weapon_temp != "time_bomb_zm" ) + { + if ( isDefined( level.zombie_weapons[ str_weapon_temp ] ) && isDefined( level.zombie_weapons[ str_weapon_temp ].vox ) ) + { + self maps/mp/zombies/_zm_weapons::weapon_give( str_weapon_temp, issubstr( str_weapon_temp, "upgrade" ) ); + } + else + { + self giveweapon( str_weapon_temp, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( str_weapon_temp ) ); + } + if ( n_type == 1 ) + { + self setweaponammofuel( str_weapon_temp, n_ammo_clip ); + } + else if ( n_type == 2 ) + { + self setweaponoverheating( 0, n_ammo_clip, str_weapon_temp ); + } + else + { + if ( isDefined( n_ammo_clip ) ) + { + self setweaponammoclip( str_weapon_temp, n_ammo_clip ); + } + } + self setweaponammostock( str_weapon_temp, n_ammo_reserve ); + } + i++; + } + if ( s_temp.weapons.primary == "none" || s_temp.weapons.primary == "time_bomb_zm" ) + { + i = 0; + while ( i < s_temp.weapons.array.size ) + { + str_weapon_type = weapontype( s_temp.weapons.array[ i ] ); + if ( !is_player_equipment( str_weapon_type ) || str_weapon_type == "bullet" && str_weapon_type == "projectile" ) + { + str_weapon_temp = s_temp.weapons.array[ i ]; + break; + } + else + { + i++; + } + } + self switchtoweapon( str_weapon_temp ); + } + else + { + self switchtoweapon( s_temp.weapons.primary ); + } + self maps/mp/zombies/_zm_equipment::equipment_take( self.current_equipment ); + if ( isDefined( self.deployed_equipment ) && isinarray( self.deployed_equipment, s_temp.current_equipment ) ) + { + self maps/mp/zombies/_zm_equipment::equipment_take( s_temp.current_equipment ); + } + if ( isDefined( s_temp.current_equipment ) ) + { + self.do_not_display_equipment_pickup_hint = 1; + self maps/mp/zombies/_zm_equipment::equipment_give( s_temp.current_equipment ); + self.do_not_display_equipment_pickup_hint = undefined; + } + if ( isinarray( s_temp.weapons.array, "time_bomb_zm" ) ) + { + wait_network_frame(); + self.time_bomb_detonator_only = 1; + self swap_weapon_to_detonator(); + } + } + } + self ent_flag_set( "time_bomb_restore_thread_done" ); +} + +get_player_perk_list() +{ + a_perks = []; + while ( isDefined( self.disabled_perks ) && isarray( self.disabled_perks ) ) + { + a_keys = getarraykeys( self.disabled_perks ); + i = 0; + while ( i < a_keys.size ) + { + if ( self.disabled_perks[ a_keys[ i ] ] ) + { + a_perks[ a_perks.size ] = a_keys[ i ]; + } + i++; + } + } + if ( isDefined( self.perks_active ) && isarray( self.perks_active ) ) + { + a_perks = arraycombine( self.perks_active, a_perks, 0, 0 ); + } + return a_perks; +} + +restore_player_to_initial_loadout( s_temp ) +{ + self takeallweapons(); +/# + assert( isDefined( level.start_weapon ), "time bomb attempting to restore a spectator, but level.start_weapon isn't defined!" ); +#/ + self maps/mp/zombies/_zm_weapons::weapon_give( level.start_weapon ); +/# + assert( isDefined( level.zombie_lethal_grenade_player_init ), "time bomb attempting to restore a spectator, but level.zombie_lethal_grenade_player_init isn't defined!" ); +#/ + self set_player_lethal_grenade( level.zombie_lethal_grenade_player_init ); + self giveweapon( level.zombie_lethal_grenade_player_init ); + self setweaponammoclip( level.zombie_lethal_grenade_player_init, 2 ); +/# + assert( isDefined( level.zombie_melee_weapon_player_init ), "time bomb attempting to restore a spectator, but level.zombie_melee_weapon_player_init isn't defined!" ); +#/ + self giveweapon( level.zombie_melee_weapon_player_init ); + a_current_perks = self get_player_perk_list(); + _a1434 = a_current_perks; + _k1434 = getFirstArrayKey( _a1434 ); + while ( isDefined( _k1434 ) ) + { + perk = _a1434[ _k1434 ]; + self notify( perk + "_stop" ); + _k1434 = getNextArrayKey( _a1434, _k1434 ); + } + if ( isDefined( s_temp ) && s_temp.points_current < 1500 && self.score < 1500 || level.round_number > 6 && self.score < 1500 && level.round_number > 6 ) + { + self.score = 1500; + } +} + +_give_revive_points( save_struct ) +{ + while ( isDefined( save_struct ) && isDefined( save_struct.player_used ) && save_struct.player_used == self ) + { + _a1451 = get_players(); + _k1451 = getFirstArrayKey( _a1451 ); + while ( isDefined( _k1451 ) ) + { + player = _a1451[ _k1451 ]; + if ( isDefined( player.score_lost_when_downed ) ) + { + self maps/mp/zombies/_zm_score::player_add_points( "reviver", player.score_lost_when_downed ); + } + _k1451 = getNextArrayKey( _a1451, _k1451 ); + } + } +} + +can_time_bomb_restore_data_on_player( save_struct ) +{ + b_can_restore_data_on_player = 0; + if ( isDefined( save_struct ) ) + { + if ( isDefined( save_struct.player_saves ) ) + { + b_can_restore_data_on_player = isDefined( save_struct.player_saves[ self getentitynumber() ] ); + } + } + else + { + b_global_save_exists = isDefined( level.time_bomb_save_data.n_time_id ); + if ( isDefined( self.time_bomb_save_data ) ) + { + b_player_save_exists = isDefined( self.time_bomb_save_data.n_time_id ); + } + if ( b_global_save_exists && b_player_save_exists ) + { + if ( level.time_bomb_save_data.n_time_id == self.time_bomb_save_data.n_time_id ) + { + b_can_restore_data_on_player = 1; + } + } + } + return b_can_restore_data_on_player; +} + +time_bomb_clears_global_data() +{ + level setclientfield( "time_bomb_saved_round_number", 0 ); + if ( isDefined( level.time_bomb_save_data ) ) + { + level.time_bomb_save_data.save_ready = 0; + level.time_bomb_save_data.ammo_respawned_in_round = undefined; + } +} + +time_bomb_clears_player_data() +{ + a_players = get_players(); + _a1502 = a_players; + _k1502 = getFirstArrayKey( _a1502 ); + while ( isDefined( _k1502 ) ) + { + player = _a1502[ _k1502 ]; + if ( isDefined( player.time_bomb_save_data ) ) + { + player.time_bomb_save_data = undefined; + } + _k1502 = getNextArrayKey( _a1502, _k1502 ); + } +} + +timebomb_change_to_round( n_target_round ) +{ + debug_time_bomb_print( "TIMEBOMB >> changing from round " + level.round_number + " to round " + n_target_round ); + if ( n_target_round < 1 ) + { + n_target_round = 1; + } + level.time_bomb_round_change = 1; + level.zombie_round_start_delay = 0; + level.zombie_round_end_delay = 0; + n_between_round_time = level.zombie_vars[ "zombie_between_round_time" ]; + level.zombie_vars[ "zombie_between_round_time" ] = 0; + level notify( "end_of_round" ); + flag_set( "end_round_wait" ); + maps/mp/zombies/_zm::ai_calculate_health( n_target_round ); + if ( level._time_bomb.round_initialized ) + { + level._time_bomb.restoring_initialized_round = 1; + n_target_round--; + + } + level.round_number = n_target_round; + setroundsplayed( n_target_round ); + level waittill( "between_round_over" ); + timebomb_wait_for_hostmigration(); + level.zombie_round_start_delay = undefined; + level.time_bomb_round_change = undefined; + level.zombie_vars[ "zombie_between_round_time" ] = n_between_round_time; + flag_clear( "end_round_wait" ); +} + +_time_bomb_kill_all_active_enemies() +{ + flag_clear( "spawn_zombies" ); + zombies = time_bomb_get_enemy_array(); + while ( zombies.size > 0 ) + { + i = 0; + while ( i < zombies.size ) + { + timebomb_wait_for_hostmigration(); + if ( isDefined( zombies[ i ] ) ) + { + zombies[ i ] thread _kill_time_bomb_enemy(); + } + if ( ( i % 3 ) == 0 ) + { + wait_network_frame(); + } + i++; + } + zombies = time_bomb_get_enemy_array(); + } + flag_set( "time_bomb_round_killed" ); +} + +_kill_time_bomb_enemy() +{ + self dodamage( self.health + 100, self.origin, self, self, self.origin ); + self ghost(); + playfx( level._effect[ "time_bomb_kills_enemy" ], self.origin ); + if ( isDefined( self ) && isDefined( self.anchor ) ) + { + self.anchor delete(); + } + wait_network_frame(); + if ( isDefined( self ) ) + { + if ( isDefined( self.script_mover ) ) + { + self.script_mover delete(); + } + self delete(); + } +} + +time_bomb_get_enemy_array() +{ + if ( isDefined( level._time_bomb.custom_funcs_get_enemies ) ) + { + a_enemies = [[ level._time_bomb.custom_funcs_get_enemies ]](); + } + else + { + a_enemies = get_round_enemy_array(); + } + return a_enemies; +} + +_time_bomb_show_overlay() +{ + flag_clear( "time_bomb_restore_done" ); + level setclientfield( "time_bomb_hud_toggle", 1 ); + a_players = get_players(); + _a1628 = a_players; + _k1628 = getFirstArrayKey( _a1628 ); + while ( isDefined( _k1628 ) ) + { + player = _a1628[ _k1628 ]; + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zombie_time_bomb_overlay", player ); + player freezecontrols( 1 ); + player enableinvulnerability(); + _k1628 = getNextArrayKey( _a1628, _k1628 ); + } + level thread kill_overlay_at_match_end(); +} + +_time_bomb_hide_overlay( n_time_start ) +{ + n_time_end = getTime(); + if ( isDefined( n_time_start ) ) + { + n_time_elapsed = ( n_time_end - n_time_start ) * 0,001; + n_delay = 4 - n_time_elapsed; + n_delay = clamp( n_delay, 0, 4 ); + if ( n_delay > 0 ) + { + wait n_delay; + timebomb_wait_for_hostmigration(); + } + } + timebomb_wait_for_hostmigration(); + a_players = get_players(); + level setclientfield( "time_bomb_hud_toggle", 0 ); + flag_set( "time_bomb_restore_done" ); + _a1664 = a_players; + _k1664 = getFirstArrayKey( _a1664 ); + while ( isDefined( _k1664 ) ) + { + player = _a1664[ _k1664 ]; + player freezecontrols( 0 ); + player thread _disable_invulnerability(); + _k1664 = getNextArrayKey( _a1664, _k1664 ); + } +} + +kill_overlay_at_match_end() +{ + level endon( "time_bomb_overlay_deactivated" ); + level waittill( "end_game" ); + if ( flag( "time_bomb_restore_active" ) ) + { + wait 5; + } + level thread _deactivate_lerp_thread(); +} + +_disable_invulnerability() +{ + self endon( "death" ); + self endon( "disconnect" ); + wait 2; + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { +/# + if ( getDvarInt( "zombie_cheat" ) >= 1 ) + { + return; +#/ + } + debug_time_bomb_print( "disabling invulnerability on " + self.name ); + self disableinvulnerability(); + } +} + +debug_time_bomb_print( str_text ) +{ +/# + if ( getDvarInt( #"6F8A0CF1" ) ) + { + iprintln( str_text ); +#/ + } +} + +time_bomb_spawn_func() +{ + self endon( "death" ); + s_temp = level.time_bomb_save_data; + if ( isDefined( level.timebomb_override_struct ) ) + { + s_temp = level.timebomb_override_struct; + } + if ( !isDefined( s_temp.respawn_count ) ) + { + s_temp.respawn_count = 0; + } + b_can_respawn_zombie = s_temp.enemies.size > s_temp.respawn_count; + if ( b_can_respawn_zombie ) + { + self _restore_zombie_data( s_temp.enemies[ s_temp.respawn_count ] ); + self.spawn_point_override = s_temp.enemies[ s_temp.respawn_count ]; + s_temp.respawn_count++; + self thread _time_bomb_spawns_zombie(); + } + if ( s_temp.enemies.size == s_temp.respawn_count ) + { + flag_set( "time_bomb_zombie_respawning_done" ); + } + return 1; +} + +time_bomb_enemy_respawn_failsafe() +{ + while ( !flag( "time_bomb_zombie_respawning_done" ) ) + { + if ( get_current_zombie_count() >= level.zombie_ai_limit || level.zombie_total == 0 ) + { + flag_set( "time_bomb_zombie_respawning_done" ); + } + wait 0,5; + } +} + +_time_bomb_spawns_zombie() +{ + if ( isDefined( self.anchor ) ) + { + self.anchor delete(); + } + self maps/mp/zombies/_zm_spawner::do_zombie_spawn(); + self thread _zombies_go_back_into_ai_when_time_bomb_is_done(); +} + +_restore_zombie_data( s_info ) +{ + if ( isDefined( s_info.zombie_move_speed ) ) + { + self.zombie_move_speed = s_info.zombie_move_speed; + } + self.targetname = s_info.targetname; + self.script_noteworthy = s_info.script_noteworthy; + self.script_string = s_info.script_string; + self.target = s_info.target; + if ( isDefined( s_info.is_traversing ) || s_info.is_traversing && isDefined( self.is_traversing ) && self.is_traversing ) + { + self notify( "killanimscript" ); + } + self.is_traversing = 0; + self.attacking_node = s_info.attacking_node; + self.attacking_spot = s_info.attacking_spot; + self.first_node = s_info.first_node; + self.attacking_spot_index = s_info.attacking_spot_index; + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + self.entrance_nodes = s_info.entrance_nodes; + self.attacking_spot_string = s_info.attacking_spot_string; + if ( !isDefined( s_info.completed_emerging_into_playable_area ) ) + { + s_info.completed_emerging_into_playable_area = 0; + } + self.completed_emerging_into_playable_area = s_info.completed_emerging_into_playable_area; + if ( isDefined( self.completed_emerging_into_playable_area ) && self.completed_emerging_into_playable_area ) + { + } + if ( isDefined( s_info.has_legs ) ) + { + self.has_legs = s_info.has_legs; + if ( isDefined( self.has_legs ) && !self.has_legs ) + { + self setphysparams( 15, 0, 24 ); + } + } + self.a.gib_ref = s_info.gib_ref; + if ( isDefined( self.has_legs ) && !self.has_legs && isDefined( self.a.gib_ref ) ) + { + self thread maps/mp/animscripts/zm_death::do_gib(); + } + if ( isDefined( s_info.in_the_ground ) && s_info.in_the_ground ) + { + self maps/mp/zombies/_zm_spawner::zombie_eye_glow(); + self._rise_spot = s_info; + } + if ( isDefined( s_info.zombie_faller_location ) && isDefined( s_info.spawn_point ) && isDefined( s_info.spawn_point.script_noteworthy ) ) + { + s_info.script_noteworthy = s_info.spawn_point.script_noteworthy; + } + self.doing_equipment_attack = s_info.doing_equipment_attack; + if ( isDefined( self.doing_equipment_attack ) && self.doing_equipment_attack ) + { + self stopanimscripted(); + } + self.is_traversing = s_info.is_traversing; + self.spawn_point = s_info.spawn_point; + if ( isDefined( s_info.spawn_point ) && !self.completed_emerging_into_playable_area ) + { + self.script_noteworthy = s_info.spawn_point.script_noteworthy; + self.script_string = s_info.spawn_point.script_string; + self.target = s_info.spawn_point.target; + } + self.time_bomb_restored_data = s_info; + self zombie_history( "time bomb -> all data restored " ); +} + +time_bomb_round_wait() +{ + maps/mp/zombies/_zm::round_wait(); + if ( isDefined( level._time_bomb.restoring_initialized_round ) && level._time_bomb.restoring_initialized_round && isDefined( level.time_bomb_save_data ) && isDefined( level.time_bomb_save_data.round_initialized ) && !level.time_bomb_save_data.round_initialized ) + { + level.round_number--; + + } + else + { + if ( isDefined( level._time_bomb.changing_round ) && !level._time_bomb.changing_round && !level.time_bomb_save_data.round_initialized && level._time_bomb.round_initialized ) + { + level.round_number--; + + } + else + { + if ( isDefined( level._time_bomb.changing_round ) && level._time_bomb.changing_round && !level._time_bomb.round_initialized ) + { + level.round_number--; + + } + } + } + level._time_bomb.changing_round = undefined; + level._time_bomb.restoring_initialized_round = undefined; + level._time_bomb.round_initialized = 0; + if ( flag( "time_bomb_restore_active" ) ) + { + if ( !is_time_bomb_round_change() ) + { + flag_wait( "time_bomb_round_killed" ); + flag_wait( "time_bomb_enemies_restored" ); + time_bomb_round_wait(); + } + } + if ( isDefined( level.time_bomb_restored_into_current_round ) && level.time_bomb_restored_into_current_round ) + { + level.old_music_state = undefined; + level.time_bomb_restored_into_current_round = undefined; + } + level notify( "time_bomb_round_wait_done" ); +} + +_zombies_go_back_into_ai_when_time_bomb_is_done() +{ + self endon( "death" ); + if ( isDefined( self ) ) + { + playfxontag( level._effect[ "time_bomb_respawns_enemy" ], self, "J_SpineLower" ); + self setgoalpos( self.origin ); + self.angles = self.time_bomb_restored_data.angles; + flag_waitopen( "time_bomb_restore_active" ); + str_restore_state = self.time_bomb_restored_data.ai_state; + s_temp = self.time_bomb_restored_data; + str_notify_message = undefined; + if ( isDefined( str_restore_state ) ) + { + if ( str_restore_state == "find_flesh" ) + { + str_notify_message = self _handle_find_flesh( s_temp ); + } + else if ( str_restore_state == "zombie_goto_entrance" ) + { + str_notify_message = self _send_zombie_to_barricade(); + } + else if ( str_restore_state == "zombie_think" || str_restore_state == "idle" ) + { + if ( isDefined( self.in_the_ground ) && self.in_the_ground ) + { + self waittill( "risen" ); + str_notify_message = self _handle_find_flesh( s_temp ); + } + else + { + if ( isDefined( self.completed_emerging_into_playable_area ) ) + { + if ( self.completed_emerging_into_playable_area ) + { + str_notify_message = self _handle_find_flesh( s_temp ); + } + else + { + str_notify_message = self _send_zombie_to_barricade(); + } + } + } + } + } + self notify( "zombie_custom_think_done" ); + if ( !isDefined( str_notify_message ) ) + { + str_notify_message = ""; + } + self zombie_history( "time bomb -> zombie restored with string = " + str_notify_message ); + } +} + +_handle_find_flesh( s_temp ) +{ + if ( s_temp.completed_emerging_into_playable_area ) + { + self notify( "stop_zombie_goto_entrance" ); + self.target = undefined; + } + else + { + self.target = s_temp.spawn_point.target; + } + return "find_flesh"; +} + +_send_zombie_to_barricade() +{ + if ( isDefined( self.time_bomb_restored_data.entrance_nodes ) && self.time_bomb_restored_data.entrance_nodes.size > 0 ) + { + a_entrance_nodes = self.time_bomb_restored_data.entrance_nodes; + } + else + { + a_entrance_nodes = level.exterior_goals; + } + nd_closest = getclosest( self.origin, a_entrance_nodes ); + str_notify_message = nd_closest.script_string; + if ( isDefined( self.time_bomb_restored_data.traversing_over_barrier_into_playspace ) && self.time_bomb_restored_data.traversing_over_barrier_into_playspace ) + { + self thread _barrier_jump_failsafe(); + } + return str_notify_message; +} + +_barrier_jump_failsafe() +{ + self endon( "death" ); + wait randomfloatrange( 2,5, 3 ); + if ( !isDefined( self.completed_emerging_into_playable_area ) || !self.completed_emerging_into_playable_area && self in_playable_area() ) + { + self notify( "goal" ); + self zombie_complete_emerging_into_playable_area(); + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); + } +} + +time_bomb_custom_round_change() +{ + level thread _monitor_zombie_total_init(); + if ( is_time_bomb_round_change() ) + { + level.time_bomb_restored_into_current_round = 1; + } + else + { + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "round_start" ); + round_one_up(); + } +} + +_monitor_zombie_total_init() +{ + level notify( "_kill_end_of_round_monitor" ); + level endon( "_kill_end_of_round_monitor" ); + level endon( "end_of_round" ); + level._time_bomb.round_initialized = 0; + level waittill( "zombie_total_set" ); + level._time_bomb.round_initialized = 1; +} + +is_time_bomb_round_change() +{ + if ( isDefined( level.time_bomb_round_change ) ) + { + return level.time_bomb_round_change; + } +} + +time_bomb_overlay_lerp_thread() +{ + level endon( "time_bomb_overlay_deactivated" ); + n_frames = 40; + n_change_per_frame = 1 / n_frames; + i = 0; + while ( i < n_frames ) + { + a_players = get_players(); + j = 0; + while ( j < a_players.size ) + { + self maps/mp/_visionset_mgr::vsmgr_set_state_active( a_players[ j ], clamp( i * n_change_per_frame, 0, 1 ) ); + j++; + } + wait 0,05; + i++; + } + flag_wait( "time_bomb_restore_done" ); + i = 0; + while ( i < n_frames ) + { + a_players = get_players(); + j = 0; + while ( j < a_players.size ) + { + self maps/mp/_visionset_mgr::vsmgr_set_state_active( a_players[ j ], clamp( 1 - ( i * n_change_per_frame ), 0, 1 ) ); + j++; + } + wait 0,05; + i++; + } + level thread _deactivate_lerp_thread(); +} + +_deactivate_lerp_thread() +{ + a_players = get_players(); + i = 0; + while ( i < a_players.size ) + { + maps/mp/_visionset_mgr::deactivate_per_player( "overlay", "zombie_time_bomb_overlay", a_players[ i ] ); + i++; + } + level notify( "time_bomb_overlay_deactivated" ); +} + +time_bomb_hud_icon_show() +{ + time_bomb_destroy_hud_elem(); + level setclientfield( "time_bomb_saved_round_number", level.round_number ); +} + +time_bomb_destroy_hud_elem() +{ + level setclientfield( "time_bomb_saved_round_number", 0 ); +} + +is_zombie_round() +{ + return 0; +} + +time_bomb_respawns_zombies( save_struct ) +{ + s_temp = save_struct; + if ( save_struct.round_number != level.round_number ) + { + flag_wait( "time_bomb_round_killed" ); + } + flag_clear( "time_bomb_zombie_respawning_done" ); + n_time_start = getTime(); + n_old_spawn_delay = level.zombie_vars[ "zombie_spawn_delay" ]; + level.zombie_vars[ "zombie_spawn_delay" ] = 0; + level.zombie_total = save_struct.enemies.size + save_struct.zombie_total; + level.zombie_custom_think_logic = ::time_bomb_spawn_func; + level thread time_bomb_enemy_respawn_failsafe(); + if ( level.zombie_total == 0 ) + { + flag_set( "time_bomb_zombie_respawning_done" ); + } + flag_set( "spawn_zombies" ); + flag_wait( "time_bomb_zombie_respawning_done" ); + level.zombie_vars[ "zombie_spawn_delay" ] = n_old_spawn_delay; + flag_set( "time_bomb_enemies_restored" ); + n_time_end = getTime(); + n_restore_time = ( n_time_end - n_time_start ) * 0,001; + debug_time_bomb_print( "TIMEBOMB >> ENEMIES RESTORED IN " + n_restore_time + " SECONDS!" ); + level.zombie_custom_think_logic = undefined; +} + +time_bomb_saves_zombie_data( s_data ) +{ + s_data.origin = self.origin; + s_data.angles = self.angles; + s_data.targetname = self.targetname; + s_data.script_noteworthy = self.script_noteworthy; + if ( !isDefined( s_data.script_noteworthy ) ) + { + s_data.script_noteworthy = "spawn_location"; + } + s_data.spawn_point = self.spawn_point; + s_data.is_traversing = self.is_traversing; + s_data.traversestartnode = self.traversestartnode; + if ( isDefined( s_data.is_traversing ) && s_data.is_traversing ) + { + if ( isDefined( self.traversestartnode ) && isDefined( self.traversestartnode.origin ) ) + { + s_data.origin = self.traversestartnode.origin; + } + } + if ( self _is_traversing_over_barrier_from_outside_playable_space() ) + { + s_data.traversing_over_barrier_into_playspace = 1; + s_data.origin = self.entrance_nodes[ 0 ].neg_start.origin; + } + s_data.target = self.target; + s_data.is_traversing = self.is_traversing; + s_data.ai_state = self.ai_state; + s_data.attacking_node = self.attacking_node; + s_data.attacking_spot = self.attacking_spot; + s_data.attacking_spot_index = self.attacking_spot_index; + if ( isDefined( s_data.attacking_node ) ) + { + s_data.attacking_spot_string = self.attacking_node.script_string; + } + s_data.entrance_nodes = self.entrance_nodes; + s_data.completed_emerging_into_playable_area = self.completed_emerging_into_playable_area; + s_data.in_the_ground = self.in_the_ground; + s_data._rise_spot = self._rise_spot; + s_data.doing_equipment_attack = self.doing_equipment_attack; + s_data.is_traversing = self.is_traversing; + s_data.first_node = self.first_node; + s_data.has_legs = self.has_legs; + s_data.gib_ref = self.a.gib_ref; + s_data.zombie_faller_location = self.zombie_faller_location; + s_data.zombie_move_speed = self.zombie_move_speed; + return s_data; +} + +_is_traversing_over_barrier_from_outside_playable_space() +{ + if ( isDefined( self.completed_emerging_into_playable_area ) && !self.completed_emerging_into_playable_area && isDefined( self.entrance_nodes ) && self.entrance_nodes.size == 1 && self.ai_state == "zombie_goto_entrance" && self isinscriptedstate() && isDefined( self.target ) ) + { + b_is_traversing_into_playspace = self.target == self.entrance_nodes[ 0 ].neg_start.targetname; + } + return b_is_traversing_into_playspace; +} + +_get_time_bomb_round_type() +{ + a_round_type = []; + a_keys = getarraykeys( level._time_bomb.enemy_type ); + i = 0; + while ( i < a_keys.size ) + { + if ( [[ level._time_bomb.enemy_type[ a_keys[ i ] ].conditions_for_round ]]() ) + { + a_round_type[ a_round_type.size ] = a_keys[ i ]; + } + i++; + } + if ( a_round_type.size == 0 ) + { + a_round_type[ 0 ] = level._time_bomb.enemy_type_default; + } + if ( a_round_type.size > 1 ) + { + str_types = ""; + i = 0; + while ( i < a_round_type.size ) + { + str_types = ( str_types + " " ) + a_round_type; + i++; + } +/# + assertmsg( "_get_time_bomb_round_type conditions passed multiple times for the following types: " + str_types ); +#/ + } + debug_time_bomb_print( "round type = " + a_round_type[ 0 ] ); + return a_round_type[ 0 ]; +} + +is_spectator() +{ + if ( isplayer( self ) && isDefined( self.sessionstate ) ) + { + return self.sessionstate == "spectator"; + } +} + +_time_bomb_resets_all_barrier_attack_spots_taken() +{ + _a2282 = level.exterior_goals; + _k2282 = getFirstArrayKey( _a2282 ); + while ( isDefined( _k2282 ) ) + { + barrier = _a2282[ _k2282 ]; + i = 0; + while ( i < barrier.attack_spots_taken.size ) + { + barrier.attack_spots_taken[ i ] = 0; + i++; + } + _k2282 = getNextArrayKey( _a2282, _k2282 ); + } +} + +destroy_time_bomb_save_if_user_bleeds_out_or_disconnects() +{ + self endon( "player_lost_time_bomb" ); + self waittill_any( "bled_out", "disconnect" ); + destroy_time_bomb_save(); +} + +show_time_bomb_hints() +{ + self endon( "death_or_disconnect" ); + self endon( "player_lost_time_bomb" ); + if ( !isDefined( self.time_bomb_hints_shown ) ) + { + self.time_bomb_hints_shown = 0; + } + if ( !self.time_bomb_hints_shown ) + { + self.time_bomb_hints_shown = 1; + wait 0,5; + self show_time_bomb_notification( &"ZOMBIE_TIMEBOMB_PICKUP" ); + self thread _watch_for_player_switch_to_time_bomb(); + self waittill_notify_or_timeout( "player_holding_time_bomb", 3,5 ); + self clean_up_time_bomb_notifications(); + if ( !isDefined( self.time_bomb_held ) ) + { + self waittill( "player_holding_time_bomb" ); + } + wait 0,5; + self show_time_bomb_notification( &"ZOMBIE_TIMEBOMB_HOWTO" ); + self waittill_notify_or_timeout( "player_activates_timebomb", 3,5 ); + self clean_up_time_bomb_notifications(); + } +} + +_watch_for_player_switch_to_time_bomb() +{ + self endon( "death_or_disconnect" ); + self waittill( "weapon_change", new_weapon ); + self notify( "player_holding_time_bomb" ); + self.time_bomb_held = 1; +} + +slow_all_actors() +{ + level endon( "time_bomb_stop_slow_all_actors" ); + set_all_actor_anim_rate( 0,8 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,6 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,4 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,2 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,05 ); + wait 2; +} + +all_actors_resume_speed() +{ + flag_wait( "time_bomb_enemies_restored" ); + timebomb_wait_for_hostmigration(); + wait_network_frame(); + wait_network_frame(); + level notify( "time_bomb_stop_slow_all_actors" ); + set_actor_traverse_callbacks(); + set_all_actor_anim_rate( 0,2 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,4 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,6 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 0,8 ); + wait 0,5; + timebomb_wait_for_hostmigration(); + set_all_actor_anim_rate( 1, 1 ); + level thread restore_actor_traverse_callbacks(); + wait_network_frame(); + cleanup_actor_anim_flags(); +} + +set_actor_traverse_callbacks() +{ + actors = getaispeciesarray( "all", "all" ); + i = 0; + while ( i < actors.size ) + { + actors[ i ].pre_traverse_old = actors[ i ].pre_traverse; + actors[ i ].pre_traverse = ::time_bomb_pre_traverse; + actors[ i ].post_traverse_old = actors[ i ].post_traverse; + actors[ i ].post_traverse = ::time_bomb_post_traverse; + if ( isDefined( actors[ i ].in_the_ground ) && !actors[ i ].in_the_ground || actors[ i ] isinscriptedstate() || !isDefined( actors[ i ].zombie_init_done ) && !actors[ i ].zombie_init_done ) + { + actors[ i ].do_not_set_anim_rate = 1; + actors[ i ] setclientfield( "anim_rate", 1 ); + qrate = actors[ i ] getclientfield( "anim_rate" ); + actors[ i ] setentityanimrate( qrate ); + } + if ( isDefined( level.time_bomb_custom_actor_speedup_func ) ) + { + actors[ i ] [[ level.time_bomb_custom_actor_speedup_func ]](); + } + i++; + } +} + +restore_actor_traverse_callbacks() +{ + actors = getaispeciesarray( "all", "all" ); + i = 0; + while ( i < actors.size ) + { + actors[ i ].pre_traverse = undefined; + actors[ i ].post_traverse = undefined; + if ( isDefined( actors[ i ].pre_traverse_old ) ) + { + actors[ i ].pre_traverse = actors[ i ].pre_traverse_old; + } + if ( isDefined( actors[ i ].post_traverse_old ) ) + { + actors[ i ].post_traverse = actors[ i ].post_traverse_old; + } + i++; + } +} + +time_bomb_pre_traverse() +{ + self.is_about_to_traverse = 1; +} + +time_bomb_post_traverse() +{ + self.is_about_to_traverse = undefined; +} + +set_actor_anim_rate( rate, b_force_update ) +{ + if ( !isDefined( b_force_update ) ) + { + b_force_update = 0; + } + self endon( "death" ); + level endon( "time_bomb_stop_slow_all_actors" ); + if ( !b_force_update ) + { + if ( isDefined( self.in_the_ground ) && !self.in_the_ground || self isinscriptedstate() && isDefined( self.do_not_set_anim_rate ) && self.do_not_set_anim_rate ) + { + return; + } + if ( isDefined( self.is_about_to_traverse ) || isDefined( self.ignore_timebomb_slowdown ) && self.ignore_timebomb_slowdown ) + { + rate = 1; + } + } + self setclientfield( "anim_rate", rate ); + qrate = self getclientfield( "anim_rate" ); + self setentityanimrate( qrate ); + wait ( 0,5 * 0,5 ); + self.preserve_asd_substates = 1; + self.needs_run_update = 1; + self notify( "needs_run_update" ); +} + +set_all_actor_anim_rate( rate, b_force ) +{ + actors = getaispeciesarray( "all", "all" ); + i = 0; + while ( i < actors.size ) + { + actors[ i ] thread set_actor_anim_rate( rate, b_force ); + i++; + } +} + +cleanup_actor_anim_flags() +{ + actors = getaispeciesarray( "all", "all" ); + i = 0; + while ( i < actors.size ) + { + actors[ i ].preserve_asd_substates = 0; + i++; + } +} + +white_screen_flash() +{ + level.time_bomb_whiteout_hudelem = _create_white_screen_hud_elem(); + level.time_bomb_whiteout_hudelem fadeovertime( 0,2 ); + level.time_bomb_whiteout_hudelem.alpha = 1; +} + +_create_white_screen_hud_elem() +{ + hud_elem = newhudelem(); + hud_elem.x = 0; + hud_elem.y = 0; + hud_elem.horzalign = "fullscreen"; + hud_elem.vertalign = "fullscreen"; + hud_elem.foreground = 1; + hud_elem.alpha = 0; + hud_elem.hidewheninmenu = 0; + hud_elem.shader = "white"; + hud_elem setshader( "white", 640, 480 ); + return hud_elem; +} + +remove_white_screen_flash() +{ + level.time_bomb_whiteout_hudelem fadeovertime( 0,2 ); + level.time_bomb_whiteout_hudelem.alpha = 0; + wait 0,2; + level.time_bomb_whiteout_hudelem destroy(); +} + +swap_weapon_to_detonator( e_grenade ) +{ + self endon( "death_or_disconnect" ); + self endon( "player_lost_time_bomb" ); + b_switch_to_weapon = 0; + if ( isDefined( e_grenade ) ) + { + b_switch_to_weapon = 1; + e_grenade waittill_notify_or_timeout( "stationary", 0,6 ); + } + self takeweapon( "time_bomb_zm" ); + self giveweapon( "time_bomb_detonator_zm" ); + self setweaponammoclip( "time_bomb_detonator_zm", 0 ); + self setweaponammostock( "time_bomb_detonator_zm", 0 ); + self setactionslot( 2, "weapon", "time_bomb_detonator_zm" ); + if ( b_switch_to_weapon ) + { + self switchtoweapon( "time_bomb_detonator_zm" ); + } + self giveweapon( "time_bomb_zm" ); +} + +swap_weapon_to_time_bomb() +{ + self takeweapon( "time_bomb_detonator_zm" ); + self giveweapon( "time_bomb_zm" ); + self setactionslot( 2, "weapon", "time_bomb_zm" ); +} + +test_mode() +{ + self endon( "death_or_disconnect" ); + while ( 1 ) + { + level waittill( "time_bomb_test_mode_start" ); + _test_mode_loop(); + } +} + +_test_mode_loop() +{ + level endon( "time_bomb_test_mode_end" ); + player = get_players()[ 0 ]; + if ( !player hasweapon( "time_bomb_zm" ) ) + { + player player_give_time_bomb(); + } + while ( 1 ) + { + time_bomb_saves_data(); + print_ent_count(); + wait 8; + detonate_time_bomb(); + print_ent_count(); + wait 12; + } +} + +print_ent_count() +{ + a_ents_origins = getentarray( "script_origin", "classname" ); + a_ents_models = getentarray( "script_model", "classname" ); + iprintln( "ENT COUNT - script_origins: " + a_ents_origins.size + ". script_models: " + a_ents_models.size ); +} diff --git a/zm_buried_patch/maps/mp/zombies/_zm_weapon_locker.gsc b/zm_buried_patch/maps/mp/zombies/_zm_weapon_locker.gsc new file mode 100644 index 0000000..712805a --- /dev/null +++ b/zm_buried_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_buried_patch/readme.md b/zm_buried_patch/readme.md index 5cc97fa..9dc1f3b 100644 --- a/zm_buried_patch/readme.md +++ b/zm_buried_patch/readme.md @@ -17,7 +17,75 @@ zm_buried_patch/maps/mp/zombies/_zm_weap_slowgun.gsc ### The following scripts are not tested yet, uploaded to setup a baseline: ``` ``` +### The following scripts have been checked, but they have not been tested yet +``` +``` +### The following scripts are not checked yet, uploaded to setup a baseline: +``` +zm_buried_patch/maps/mp/zm_buried.gsc +zm_buried_patch/maps/mp/zm_buried_achievement.gsc +zm_buried_patch/maps/mp/zm_buried_amb.gsc +zm_buried_patch/maps/mp/zm_buried_buildables.gsc +zm_buried_patch/maps/mp/zm_buried_classic.gsc +zm_buried_patch/maps/mp/zm_buried_distance_tracking.gsc +zm_buried_patch/maps/mp/zm_buried_ee.gsc +zm_buried_patch/maps/mp/zm_buried_ffotd.gsc +zm_buried_patch/maps/mp/zm_buried_fountain.gsc +zm_buried_patch/maps/mp/zm_buried_fx.gsc +zm_buried_patch/maps/mp/zm_buried_gamemodes.gsc +zm_buried_patch/maps/mp/zm_buried_grief_street.gsc +zm_buried_patch/maps/mp/zm_buried_jail.gsc +zm_buried_patch/maps/mp/zm_buried_maze.gsc +zm_buried_patch/maps/mp/zm_buried_power.gsc +zm_buried_patch/maps/mp/zm_buried_sq.gsc +zm_buried_patch/maps/mp/zm_buried_sq_bt.gsc +zm_buried_patch/maps/mp/zm_buried_sq_ctw.gsc +zm_buried_patch/maps/mp/zm_buried_sq_ftl.gsc +zm_buried_patch/maps/mp/zm_buried_sq_gl.gsc +zm_buried_patch/maps/mp/zm_buried_sq_ip.gsc +zm_buried_patch/maps/mp/zm_buried_sq_ll.gsc +zm_buried_patch/maps/mp/zm_buried_sq_mta.gsc +zm_buried_patch/maps/mp/zm_buried_sq_ows.gsc +zm_buried_patch/maps/mp/zm_buried_sq_tpo.gsc +zm_buried_patch/maps/mp/zm_buried_sq_ts.gsc +zm_buried_patch/maps/mp/zm_buried_standard.gsc +zm_buried_patch/maps/mp/zm_buried_turned_street.gsc + +zm_buried_patch/maps/mp/gametypes_zm/zcleansed.gsc +zm_buried_patch/maps/mp/gametypes_zm/zgrief.gsc +zm_buried_patch/maps/mp/gametypes_zm/zmeat.gsc +zm_buried_patch/maps/mp/gametypes_zm/zstandard.gsc + +zm_buried_patch/maps/mp/teams/_teamset_cdc.gsc + +zm_buried_patch/maps/mp/zombies/_zm_ai_ghost.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_ghost_ffotd.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_sloth.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_buildables.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_crawler.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_ffotd.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_magicbox.gsc +zm_buried_patch/maps/mp/zombies/_zm_ai_sloth_utility.gsc +zm_buried_patch/maps/mp/zombies/_zm_banking.gsc +zm_buried_patch/maps/mp/zombies/_zm_buildables_pooled.gsc +zm_buried_patch/maps/mp/zombies/_zm_equip_headchopper.gsc +zm_buried_patch/maps/mp/zombies/_zm_equip_springpad.gsc +zm_buried_patch/maps/mp/zombies/_zm_equip_subwoofer.gsc +zm_buried_patch/maps/mp/zombies/_zm_game_module_cleansed.gsc +zm_buried_patch/maps/mp/zombies/_zm_game_module_grief.gsc +zm_buried_patch/maps/mp/zombies/_zm_game_module_meat.gsc +zm_buried_patch/maps/mp/zombies/_zm_game_module_meat_utility.gsc +zm_buried_patch/maps/mp/zombies/_zm_game_module_turned.gsc +zm_buried_patch/maps/mp/zombies/_zm_game_module_utility.gsc +zm_buried_patch/maps/mp/zombies/_zm_melee_weapon.gsc +zm_buried_patch/maps/mp/zombies/_zm_perk_divetonuke.gsc +zm_buried_patch/maps/mp/zombies/_zm_perk_vulture.gsc +zm_buried_patch/maps/mp/zombies/_zm_weap_ballistic_knife.gsc +zm_buried_patch/maps/mp/zombies/_zm_weap_tazer_knuckles.gsc +zm_buried_patch/maps/mp/zombies/_zm_weap_tomb_bomb.gsc +zm_buried_patch/maps/mp/zombies/_zm_weapon_locker.gsc +``` ### notes: ``` ```