mirror of
https://github.com/InfinityLoader/IL-GSC.git
synced 2025-06-07 17:17:50 -05:00
2179 lines
62 KiB
Plaintext
2179 lines
62 KiB
Plaintext
#include maps\_utility;
|
||
#include common_scripts\utility;
|
||
#include maps\_zombiemode_utility;
|
||
#include animscripts\zombie_Utility;
|
||
init()
|
||
{
|
||
PrecacheRumble( "explosion_generic" );
|
||
init_monkey_zombie_anims();
|
||
level._effect["monkey_groundhit"] = loadfx("maps/zombie/fx_zmb_monkey_ground_hit");
|
||
level._effect["monkey_death"] = loadfx("maps/zombie/fx_zmb_monkey_death");
|
||
level._effect["monkey_spawn"] = loadfx("maps/zombie/fx_zombie_ape_spawn_dust");
|
||
level._effect["monkey_eye_glow"] = LoadFx( "maps/zombie/fx_zmb_monkey_eyes" );
|
||
if( !isDefined( level.monkey_zombie_spawn_heuristic ) )
|
||
{
|
||
level.monkey_zombie_spawn_heuristic = maps\_zombiemode_ai_monkey::monkey_zombie_default_spawn_heuristic;
|
||
}
|
||
if ( !isDefined( level.monkey_zombie_enter_level ) )
|
||
{
|
||
level.monkey_zombie_enter_level = ::monkey_zombie_default_enter_level;
|
||
}
|
||
precacheshellshock( "electrocution" );
|
||
level.num_monkey_zombies = 0;
|
||
level.monkey_zombie_spawners = GetEntArray( "monkey_zombie_spawner", "targetname" );
|
||
array_thread( level.monkey_zombie_spawners, ::add_spawn_function, maps\_zombiemode_ai_monkey::monkey_prespawn );
|
||
if ( !isDefined( level.max_monkey_zombies ) )
|
||
{
|
||
level.max_monkey_zombies = 1;
|
||
}
|
||
if ( !isDefined( level.monkey_zombie_min_health ) )
|
||
{
|
||
level.monkey_zombie_min_health = 150;
|
||
}
|
||
if ( !isDefined( level.monkey_zombie_groundhit_damage ) )
|
||
{
|
||
level.monkey_zombie_groundhit_damage = 100;
|
||
}
|
||
if ( !isDefined( level.monkey_zombie_groundhit_trigger_radius ) )
|
||
{
|
||
level.monkey_zombie_groundhit_trigger_radius = 96;
|
||
}
|
||
if ( !isDefined( level.monkey_zombie_groundhit_damage_radius ) )
|
||
{
|
||
level.monkey_zombie_groundhit_damage_radius = 280;
|
||
}
|
||
if ( !isDefined( level.monkey_ground_attack_delay ) )
|
||
{
|
||
level.monkey_ground_attack_delay = 5000;
|
||
}
|
||
if ( !isdefined( level.monkeys_per_pack ) )
|
||
{
|
||
level.monkeys_per_pack = 3;
|
||
}
|
||
if ( !isDefined( level.monkey_pack_max ) )
|
||
{
|
||
level.monkey_pack_max = 1;
|
||
}
|
||
if ( !isdefined( level.monkey_pack ) )
|
||
{
|
||
level.monkey_pack = [];
|
||
}
|
||
if ( !isdefined( level.machine_health_max ) )
|
||
{
|
||
level.machine_health_max = 100;
|
||
}
|
||
if ( !isdefined( level.machine_damage_min ) )
|
||
{
|
||
level.machine_damage_min = 1;
|
||
}
|
||
if ( !isdefined( level.machine_damage_max ) )
|
||
{
|
||
level.machine_damage_max = 8;
|
||
}
|
||
if ( !isdefined( level.ground_hit_delay ) )
|
||
{
|
||
level.ground_hit_delay = RandomFloatRange( 4.5, 6.5 ) * 1000;
|
||
}
|
||
level.monkey_death = 0;
|
||
level.monkey_death_total = 0;
|
||
level.monkey_packs_killed = 0;
|
||
level.monkey_encounters = 1;
|
||
level.monkey_intermission = false;
|
||
flag_init( "monkey_round" );
|
||
flag_init( "last_monkey_down" );
|
||
flag_init( "monkey_pack_down" );
|
||
flag_init( "perk_bought" );
|
||
flag_init( "monkey_free_perk" );
|
||
level thread monkey_round_tracker();
|
||
level.perk_lost_func = ::monkey_perk_lost;
|
||
level.perk_bought_func = ::monkey_perk_bought;
|
||
level.revive_solo_fx_func = ::monkey_revive_solo_fx;
|
||
}
|
||
#using_animtree( "generic_human" );
|
||
monkey_prespawn()
|
||
{
|
||
self.animname = "monkey_zombie";
|
||
self.custom_idle_setup = maps\_zombiemode_ai_monkey::monkey_zombie_idle_setup;
|
||
self.a.idleAnimOverrideArray = [];
|
||
self.a.idleAnimOverrideArray["stand"] = [];
|
||
self.a.idleAnimOverrideWeights["stand"] = [];
|
||
self.a.idleAnimOverrideArray["stand"][0][0] = %ai_zombie_monkey_idle_01;
|
||
self.a.idleAnimOverrideWeights["stand"][0][0] = 10;
|
||
self.a.idleAnimOverrideArray["stand"][0][1] = %ai_zombie_monkey_idle_01;
|
||
self.a.idleAnimOverrideWeights["stand"][0][1] = 10;
|
||
rand = randomIntRange( 1, 4 );
|
||
self.deathanim = level.scr_anim["monkey_zombie"]["death"+rand];
|
||
self.ignorelocationaldamage = true;
|
||
self.ignoreall = true;
|
||
self.allowdeath = true;
|
||
self.is_zombie = true;
|
||
self.has_legs = true;
|
||
self allowedStances( "stand" );
|
||
self.gibbed = false;
|
||
self.head_gibbed = false;
|
||
self PushPlayer( true );
|
||
self.disableArrivals = true;
|
||
self.disableExits = true;
|
||
self.grenadeawareness = 0;
|
||
self.badplaceawareness = 0;
|
||
self.ignoreSuppression = true;
|
||
self.suppressionThreshold = 1;
|
||
self.noDodgeMove = true;
|
||
self.dontShootWhileMoving = true;
|
||
self.pathenemylookahead = 0;
|
||
self.badplaceawareness = 0;
|
||
self.chatInitialized = false;
|
||
self.a.disablePain = true;
|
||
self disable_react();
|
||
self.freezegun_damage = 0;
|
||
self.dropweapon = false;
|
||
self thread maps\_zombiemode_spawner::zombie_damage_failsafe();
|
||
self thread maps\_zombiemode_spawner::delayed_zombie_eye_glow();
|
||
self.flame_damage_time = 0;
|
||
self.meleeDamage = 40;
|
||
self.no_powerups = true;
|
||
self.no_gib = 1;
|
||
self.custom_damage_func = ::monkey_custom_damage;
|
||
self.chest_beat = false;
|
||
self.machine_damage = level.machine_damage_min;
|
||
self setPhysParams( 24, 0, 24 );
|
||
self.dropped = true;
|
||
self setTeamForEntity( "axis" );
|
||
self AllowPitchAngle( 1 );
|
||
self.thundergun_fling_func = ::monkey_fling;
|
||
self monkey_zombie_set_state( "default" );
|
||
self.noChangeDuringMelee = true;
|
||
if ( isDefined( level.monkey_prespawn ) )
|
||
{
|
||
self [[ level.monkey_prespawn ]]();
|
||
}
|
||
self notify( "zombie_init_done" );
|
||
}
|
||
monkey_zombie_idle_setup()
|
||
{
|
||
self.a.array["turn_left_45"] = %exposed_tracking_turn45L;
|
||
self.a.array["turn_left_90"] = %exposed_tracking_turn90L;
|
||
self.a.array["turn_left_135"] = %exposed_tracking_turn135L;
|
||
self.a.array["turn_left_180"] = %exposed_tracking_turn180L;
|
||
self.a.array["turn_right_45"] = %exposed_tracking_turn45R;
|
||
self.a.array["turn_right_90"] = %exposed_tracking_turn90R;
|
||
self.a.array["turn_right_135"] = %exposed_tracking_turn135R;
|
||
self.a.array["turn_right_180"] = %exposed_tracking_turn180L;
|
||
self.a.array["exposed_idle"] = array( %ai_zombie_monkey_idle_01, %ai_zombie_monkey_idle_01 );
|
||
self.a.array["straight_level"] = %ai_zombie_monkey_idle_01;
|
||
self.a.array["stand_2_crouch"] = %ai_zombie_shot_leg_right_2_crawl;
|
||
}
|
||
init_monkey_specific_zombie_anims()
|
||
{
|
||
level.scr_anim["monkey_zombie"]["death1"] = %ai_zombie_monkey_death_01;
|
||
level.scr_anim["monkey_zombie"]["death2"] = %ai_zombie_monkey_death_02;
|
||
level.scr_anim["monkey_zombie"]["death3"] = %ai_zombie_monkey_death_03;
|
||
level.scr_anim["monkey_zombie"]["walk1"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk2"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk3"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk4"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk5"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk6"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk7"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["walk8"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["run1"] = %ai_zombie_monkey_run_01;
|
||
level.scr_anim["monkey_zombie"]["run2"] = %ai_zombie_monkey_run_02;
|
||
level.scr_anim["monkey_zombie"]["sprint1"] = %ai_zombie_monkey_sprint_01;
|
||
level.scr_anim["monkey_zombie"]["sprint2"] = %ai_zombie_monkey_sprint_02;
|
||
level.scr_anim["monkey_zombie"]["sprint3"] = %ai_zombie_monkey_sprint_03;
|
||
level.scr_anim["monkey_zombie"]["sprint4"] = %ai_zombie_monkey_sprint_04;
|
||
level._zombie_melee["monkey_zombie"][0] = %ai_zombie_monkey_attack_01;
|
||
level._zombie_melee["monkey_zombie"][1] = %ai_zombie_monkey_attack_02;
|
||
level._zombie_melee["monkey_zombie"][2] = %ai_zombie_monkey_attack_03;
|
||
level._zombie_melee["monkey_zombie"][3] = %ai_zombie_monkey_attack_04;
|
||
level._zombie_melee["monkey_zombie"][4] = %ai_zombie_monkey_attack_05;
|
||
level._zombie_melee["monkey_zombie"][5] = %ai_zombie_monkey_attack_06;
|
||
level._zombie_melee["monkey_zombie"][6] = %ai_zombie_monkey_attack_07;
|
||
level._zombie_run_melee["monkey_zombie"][0] = %ai_zombie_monkey_attack_01;
|
||
level._zombie_run_melee["monkey_zombie"][1] = %ai_zombie_monkey_attack_02;
|
||
level._zombie_run_melee["monkey_zombie"][2] = %ai_zombie_monkey_attack_03;
|
||
level._zombie_deaths["monkey_zombie"] = [];
|
||
level._zombie_deaths["monkey_zombie"][0] = %ai_zombie_monkey_death_01;
|
||
level._zombie_deaths["monkey_zombie"][1] = %ai_zombie_monkey_death_02;
|
||
level._zombie_deaths["monkey_zombie"][2] = %ai_zombie_monkey_death_03;
|
||
level._zombie_board_taunt["monkey_zombie"][0] = %ai_zombie_monkey_taunt_01;
|
||
level._zombie_board_taunt["monkey_zombie"][1] = %ai_zombie_monkey_taunt_02;
|
||
level._zombie_board_taunt["monkey_zombie"][2] = %ai_zombie_monkey_taunt_03;
|
||
level._zombie_board_taunt["monkey_zombie"][3] = %ai_zombie_monkey_taunt_04;
|
||
level._zombie_board_taunt["monkey_zombie"][4] = %ai_zombie_monkey_taunt_05;
|
||
level.monkey_groundpound_anims[0] = %ai_zombie_monkey_groundpound_01;
|
||
level.monkey_groundpound_anims[1] = %ai_zombie_monkey_groundpound_02;
|
||
level.monkey_groundpound_anims[2] = %ai_zombie_monkey_groundpound_03;
|
||
level.monkey_groundpound_anims[3] = %ai_zombie_monkey_groundpound_04;
|
||
level.monkey_perk_attack_anims[0] = %ai_zombie_monkey_attack_perks_front;
|
||
level.monkey_perk_attack_anims[1] = %ai_zombie_monkey_attack_perks_left;
|
||
level.monkey_perk_attack_anims[2] = %ai_zombie_monkey_attack_perks_left_top;
|
||
level.monkey_perk_attack_anims[3] = %ai_zombie_monkey_attack_perks_right;
|
||
level.monkey_perk_attack_anims[4] = %ai_zombie_monkey_attack_perks_right_top;
|
||
level.monkey_perk_attack_anims["specialty_armorvest"]["left_top"] = %ai_zombie_monkey_attack_perks_left_top_jugg;
|
||
level.monkey_perk_attack_anims["specialty_armorvest"]["right_top"] = %ai_zombie_monkey_attack_perks_right_top_jugg;
|
||
level.monkey_perk_attack_anims["specialty_longersprint"]["left_top"] = %ai_zombie_monkey_attack_perks_left_top_marathon;
|
||
level.monkey_perk_attack_anims["specialty_longersprint"]["right_top"] = %ai_zombie_monkey_attack_perks_right_top_marathon;
|
||
level.monkey_perk_attack_anims["specialty_quickrevive"]["left_top"] = %ai_zombie_monkey_attack_perks_left_top_revive;
|
||
level.monkey_perk_attack_anims["specialty_quickrevive"]["right_top"] = %ai_zombie_monkey_attack_perks_right_top_revive;
|
||
level.monkey_perk_attack_anims["specialty_fastreload"]["left_top"] = %ai_zombie_monkey_attack_perks_left_top_speed;
|
||
level.monkey_perk_attack_anims["specialty_fastreload"]["right_top"] = %ai_zombie_monkey_attack_perks_right_top_speed;
|
||
level.monkey_thundergun_roll_anims[0] = %ai_zombie_monkey_thundergun_roll_01;
|
||
level.monkey_thundergun_roll_anims[1] = %ai_zombie_monkey_thundergun_roll_02;
|
||
level.monkey_thundergun_roll_anims[2] = %ai_zombie_monkey_thundergun_roll_03;
|
||
level.monkey_thundergun_roll_anims[3] = %ai_zombie_monkey_thundergun_roll_04;
|
||
}
|
||
#using_animtree( "generic_human" );
|
||
init_monkey_zombie_anims()
|
||
{
|
||
level.scr_anim["monkey_zombie"]["crawl1"] = %ai_zombie_crawl;
|
||
level.scr_anim["monkey_zombie"]["crawl2"] = %ai_zombie_crawl_v1;
|
||
level.scr_anim["monkey_zombie"]["crawl3"] = %ai_zombie_crawl_v2;
|
||
level.scr_anim["monkey_zombie"]["crawl4"] = %ai_zombie_crawl_v3;
|
||
level.scr_anim["monkey_zombie"]["crawl5"] = %ai_zombie_crawl_v4;
|
||
level.scr_anim["monkey_zombie"]["crawl6"] = %ai_zombie_crawl_v5;
|
||
level.scr_anim["monkey_zombie"]["crawl_hand_1"] = %ai_zombie_walk_on_hands_a;
|
||
level.scr_anim["monkey_zombie"]["crawl_hand_2"] = %ai_zombie_walk_on_hands_b;
|
||
level.scr_anim["monkey_zombie"]["crawl_sprint1"] = %ai_zombie_crawl_sprint;
|
||
level.scr_anim["monkey_zombie"]["crawl_sprint2"] = %ai_zombie_crawl_sprint_1;
|
||
level.scr_anim["monkey_zombie"]["crawl_sprint3"] = %ai_zombie_crawl_sprint_2;
|
||
if( !isDefined( level._zombie_melee ) )
|
||
{
|
||
level._zombie_melee = [];
|
||
}
|
||
if( !isDefined( level._zombie_walk_melee ) )
|
||
{
|
||
level._zombie_walk_melee = [];
|
||
}
|
||
if( !isDefined( level._zombie_run_melee ) )
|
||
{
|
||
level._zombie_run_melee = [];
|
||
}
|
||
level._zombie_melee["monkey_zombie"] = [];
|
||
level._zombie_walk_melee["monkey_zombie"] = [];
|
||
level._zombie_run_melee["monkey_zombie"] = [];
|
||
if( isDefined( level.monkey_zombie_anim_override ) )
|
||
{
|
||
[[ level.monkey_zombie_anim_override ]]();
|
||
}
|
||
if( !isDefined( level._zombie_melee_crawl ) )
|
||
{
|
||
level._zombie_melee_crawl = [];
|
||
}
|
||
level._zombie_melee_crawl["monkey_zombie"] = [];
|
||
level._zombie_melee_crawl["monkey_zombie"][0] = %ai_zombie_attack_crawl;
|
||
level._zombie_melee_crawl["monkey_zombie"][1] = %ai_zombie_attack_crawl_lunge;
|
||
if( !isDefined( level._zombie_stumpy_melee ) )
|
||
{
|
||
level._zombie_stumpy_melee = [];
|
||
}
|
||
level._zombie_stumpy_melee["monkey_zombie"] = [];
|
||
level._monkey_zombie_stumpy_melee["monkey_zombie"][0] = %ai_zombie_walk_on_hands_shot_a;
|
||
level._monkey_zombie_stumpy_melee["monkey_zombie"][1] = %ai_zombie_walk_on_hands_shot_b;
|
||
if( !isDefined( level._zombie_tesla_deaths ) )
|
||
{
|
||
level._zombie_tesla_deaths = [];
|
||
}
|
||
level._zombie_tesla_death["monkey_zombie"] = [];
|
||
level._zombie_tesla_death["monkey_zombie"][0] = %ai_zombie_boss_tesla_death_a;
|
||
level._zombie_tesla_death["monkey_zombie"][1] = %ai_zombie_boss_tesla_death_a;
|
||
level._zombie_tesla_death["monkey_zombie"][2] = %ai_zombie_boss_tesla_death_a;
|
||
level._zombie_tesla_death["monkey_zombie"][3] = %ai_zombie_boss_tesla_death_a;
|
||
level._zombie_tesla_death["monkey_zombie"][4] = %ai_zombie_boss_tesla_death_a;
|
||
if( !isDefined( level._zombie_tesla_crawl_death ) )
|
||
{
|
||
level._zombie_tesla_crawl_death = [];
|
||
}
|
||
level._zombie_tesla_crawl_death["monkey_zombie"] = [];
|
||
level._zombie_tesla_crawl_death["monkey_zombie"][0] = %ai_zombie_tesla_crawl_death_a;
|
||
level._zombie_tesla_crawl_death["monkey_zombie"][1] = %ai_zombie_tesla_crawl_death_b;
|
||
if( !isDefined( level._zombie_deaths ) )
|
||
{
|
||
level._zombie_deaths = [];
|
||
}
|
||
if( !isDefined( level._zombie_rise_anims ) )
|
||
{
|
||
level._zombie_rise_anims = [];
|
||
}
|
||
level._zombie_rise_anims["monkey_zombie"] = [];
|
||
level._zombie_rise_anims["monkey_zombie"][1]["walk"][0] = %ai_zombie_traverse_ground_v1_walk;
|
||
level._zombie_rise_anims["monkey_zombie"][1]["run"][0] = %ai_zombie_traverse_ground_v1_run;
|
||
level._zombie_rise_anims["monkey_zombie"][1]["sprint"][0] = %ai_zombie_traverse_ground_climbout_fast;
|
||
level._zombie_rise_anims["monkey_zombie"][2]["walk"][0] = %ai_zombie_traverse_ground_v2_walk_altA;
|
||
if( !isDefined( level._zombie_rise_death_anims ) )
|
||
{
|
||
level._zombie_rise_death_anims = [];
|
||
}
|
||
level._zombie_rise_death_anims["monkey_zombie"] = [];
|
||
level._zombie_rise_death_anims["monkey_zombie"][1]["in"][0] = %ai_zombie_traverse_ground_v1_deathinside;
|
||
level._zombie_rise_death_anims["monkey_zombie"][1]["in"][1] = %ai_zombie_traverse_ground_v1_deathinside_alt;
|
||
level._zombie_rise_death_anims["monkey_zombie"][1]["out"][0] = %ai_zombie_traverse_ground_v1_deathoutside;
|
||
level._zombie_rise_death_anims["monkey_zombie"][1]["out"][1] = %ai_zombie_traverse_ground_v1_deathoutside_alt;
|
||
level._zombie_rise_death_anims["monkey_zombie"][2]["in"][0] = %ai_zombie_traverse_ground_v2_death_low;
|
||
level._zombie_rise_death_anims["monkey_zombie"][2]["in"][1] = %ai_zombie_traverse_ground_v2_death_low_alt;
|
||
level._zombie_rise_death_anims["monkey_zombie"][2]["out"][0] = %ai_zombie_traverse_ground_v2_death_high;
|
||
level._zombie_rise_death_anims["monkey_zombie"][2]["out"][1] = %ai_zombie_traverse_ground_v2_death_high_alt;
|
||
if( !isDefined( level._zombie_run_taunt ) )
|
||
{
|
||
level._zombie_run_taunt = [];
|
||
}
|
||
if( !isDefined( level._zombie_board_taunt ) )
|
||
{
|
||
level._zombie_board_taunt = [];
|
||
}
|
||
level._zombie_run_taunt["monkey_zombie"] = [];
|
||
level._zombie_board_taunt["monkey_zombie"] = [];
|
||
init_monkey_specific_zombie_anims();
|
||
}
|
||
monkey_zombie_spawn( pack )
|
||
{
|
||
self.script_moveoverride = true;
|
||
if( !isDefined( level.num_monkey_zombies ) )
|
||
{
|
||
level.num_monkey_zombies = 0;
|
||
}
|
||
level.num_monkey_zombies++;
|
||
monkey_zombie = self maps\_zombiemode_net::network_safe_stalingrad_spawn( "monkey_zombie_spawn", 1 );
|
||
self.count = 666;
|
||
self.last_spawn_time = GetTime();
|
||
if( !spawn_failed( monkey_zombie ) )
|
||
{
|
||
monkey_zombie.script_noteworthy = self.script_noteworthy;
|
||
monkey_zombie.targetname = self.targetname;
|
||
monkey_zombie.target = self.target;
|
||
monkey_zombie.deathFunction = maps\_zombiemode_ai_monkey::monkey_zombie_die;
|
||
monkey_zombie.animname = "monkey_zombie";
|
||
monkey_zombie.pack = pack;
|
||
monkey_zombie.perk = pack.perk;
|
||
monkey_zombie.ground_hit_time = pack.ground_hit_time;
|
||
monkey_zombie.spawn_origin = self.origin;
|
||
monkey_zombie.spawn_angles = self.angles;
|
||
monkey_zombie thread monkey_zombie_think();
|
||
}
|
||
else
|
||
{
|
||
level.num_monkey_zombies--;
|
||
}
|
||
return monkey_zombie;
|
||
}
|
||
monkey_round_spawning()
|
||
{
|
||
level endon( "intermission" );
|
||
level endon( "end_of_round" );
|
||
level endon( "restart_round" );
|
||
if ( level.intermission )
|
||
{
|
||
return;
|
||
}
|
||
level.monkey_intermission = true;
|
||
level thread monkey_round_aftermath();
|
||
pack_idx = 0;
|
||
while ( 1 )
|
||
{
|
||
level monkey_pack_spawn();
|
||
pack_idx++;
|
||
if ( pack_idx >= level.monkey_pack_max )
|
||
{
|
||
break;
|
||
}
|
||
time = RandomFloatRange( 3.2, 4.4 );
|
||
wait( time );
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_setup_packs()
|
||
{
|
||
level.monkey_packs_killed = 0;
|
||
players = getplayers();
|
||
if ( players.size > level.monkey_encounters )
|
||
{
|
||
level.monkey_pack_max = players.size + level.monkey_encounters;
|
||
}
|
||
else
|
||
{
|
||
level.monkey_pack_max = players.size * 2;
|
||
}
|
||
level.monkey_encounters++;
|
||
}
|
||
monkey_setup_health()
|
||
{
|
||
switch( level.monkey_encounters )
|
||
{
|
||
case 1:
|
||
level.monkey_zombie_health = level.zombie_health * 0.25;
|
||
break;
|
||
case 2:
|
||
level.monkey_zombie_health = level.zombie_health * 0.5;
|
||
break;
|
||
case 3:
|
||
level.monkey_zombie_health = level.zombie_health * 0.75;
|
||
break;
|
||
default:
|
||
level.monkey_zombie_health = level.zombie_health;
|
||
break;
|
||
}
|
||
if ( level.zombie_health > 1600 )
|
||
{
|
||
level.zombie_health = 1600;
|
||
}
|
||
monkey_print( "monkey health = " + level.monkey_zombie_health );
|
||
}
|
||
monkey_setup_spawners()
|
||
{
|
||
level.current_monkey_spawners = [];
|
||
for ( i = 0; i < level.monkey_zombie_spawners.size; i++ )
|
||
{
|
||
if ( level.zones[ level.monkey_zombie_spawners[i].script_noteworthy ].is_enabled )
|
||
{
|
||
level.current_monkey_spawners[ level.current_monkey_spawners.size ] = level.monkey_zombie_spawners[i];
|
||
}
|
||
}
|
||
level.current_monkey_spawners = array_randomize( level.current_monkey_spawners );
|
||
level.monkey_spawner_idx = 0;
|
||
}
|
||
monkey_get_next_spawner()
|
||
{
|
||
spawner = level.current_monkey_spawners[ level.monkey_spawner_idx ];
|
||
assertex( isdefined( spawner ), "no monkey spawner found" );
|
||
if ( isdefined( spawner ) )
|
||
{
|
||
level.monkey_spawner_idx++;
|
||
if ( level.monkey_spawner_idx == level.current_monkey_spawners.size )
|
||
{
|
||
level monkey_setup_spawners();
|
||
}
|
||
}
|
||
return spawner;
|
||
}
|
||
monkey_get_available_spawners()
|
||
{
|
||
spawners = [];
|
||
for ( i = 0; i < level.monkey_zombie_spawners.size; i++ )
|
||
{
|
||
if ( level.zones[ level.monkey_zombie_spawners[i].script_noteworthy ].is_enabled )
|
||
{
|
||
spawners[ spawners.size ] = level.monkey_zombie_spawners[i];
|
||
}
|
||
}
|
||
spawners = array_randomize( spawners );
|
||
return spawners;
|
||
}
|
||
monkey_pack_man_setup_perks()
|
||
{
|
||
level.monkey_perks = [];
|
||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||
for ( i = 0; i < vending_triggers.size; i++ )
|
||
{
|
||
if ( vending_triggers[i].targeted )
|
||
{
|
||
continue;
|
||
}
|
||
players = getplayers();
|
||
for ( j = 0; j < players.size; j++ )
|
||
{
|
||
perk = vending_triggers[i].script_noteworthy;
|
||
org = vending_triggers[i].origin;
|
||
if ( isdefined( vending_triggers[i].realorigin ) )
|
||
{
|
||
org = vending_triggers[i].realorigin;
|
||
}
|
||
zone_enabled = check_point_in_active_zone( org );
|
||
if ( players[j] HasPerk( perk ) && zone_enabled )
|
||
{
|
||
level.monkey_perks[ level.monkey_perks.size ] = vending_triggers[i];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if ( level.monkey_perks.size > 1 )
|
||
{
|
||
level.monkey_perks = array_randomize( level.monkey_perks );
|
||
}
|
||
level.monkey_perk_idx = 0;
|
||
}
|
||
monkey_pack_man_get_next_perk()
|
||
{
|
||
if ( level.monkey_perks.size == 0 )
|
||
{
|
||
self.perk = undefined;
|
||
return;
|
||
}
|
||
perk = level.monkey_perks[ level.monkey_perk_idx ];
|
||
perk.targeted = 1;
|
||
level.monkey_perk_idx++;
|
||
if ( level.monkey_perk_idx == level.monkey_perks.size )
|
||
{
|
||
level monkey_pack_man_setup_perks();
|
||
}
|
||
self.perk = perk;
|
||
}
|
||
monkey_pack_spawn()
|
||
{
|
||
monkey_print( "spawning pack" );
|
||
pack = SpawnStruct();
|
||
pack.monkeys = [];
|
||
pack.attack = [];
|
||
pack.target = undefined;
|
||
level.monkey_pack[ level.monkey_pack.size ] = pack;
|
||
pack thread monkey_pack_think();
|
||
}
|
||
monkey_pack_think()
|
||
{
|
||
self.ground_hit_time = GetTime();
|
||
self monkey_pack_man_get_next_perk();
|
||
self monkey_pack_set_machine();
|
||
self monkey_pack_choose_enemy();
|
||
self.spawning_done = false;
|
||
for ( i = 0; i < level.monkeys_per_pack; i++ )
|
||
{
|
||
spawner = monkey_get_next_spawner();
|
||
if ( isdefined( spawner ) )
|
||
{
|
||
monkey = spawner monkey_zombie_spawn( self );
|
||
self.monkeys[ self.monkeys.size ] = monkey;
|
||
}
|
||
if ( i < (level.monkeys_per_pack-1) )
|
||
{
|
||
time = RandomFloatRange( 2.2, 4.4 );
|
||
wait( time );
|
||
}
|
||
}
|
||
self.spawning_done = true;
|
||
self thread monkey_pack_update_enemy();
|
||
self thread monkey_pack_update_perk();
|
||
}
|
||
monkey_pack_update_perk()
|
||
{
|
||
while ( 1 )
|
||
{
|
||
if ( !isdefined( self.perk ) )
|
||
{
|
||
break;
|
||
}
|
||
if ( self.machine.monkey_health == 0 )
|
||
{
|
||
monkey_print( "pack destroyed " + self.machine.targetname );
|
||
self monkey_pack_take_perk();
|
||
wait_network_frame();
|
||
self monkey_pack_clear_perk_pos();
|
||
self monkey_pack_man_get_next_perk();
|
||
self monkey_pack_set_machine();
|
||
for ( i = 0; i < self.monkeys.size; i++ )
|
||
{
|
||
if ( !self.monkeys[i].charge_player )
|
||
{
|
||
self.monkeys[i].perk = self.perk;
|
||
self.monkeys[i] notify( "stop_perk_attack" );
|
||
}
|
||
}
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_pack_next_perk()
|
||
{
|
||
perk = undefined;
|
||
perk_idx = -1;
|
||
num_perks = 0;
|
||
keys = getarraykeys( level.monkey_perks );
|
||
for ( i = 0; i < keys.size; i++ )
|
||
{
|
||
if ( level.monkey_perks[ keys[i] ] > num_perks )
|
||
{
|
||
num_perks = level.monkey_perks[ keys[i] ];
|
||
perk_idx = i;
|
||
}
|
||
}
|
||
if ( perk_idx >= 0 )
|
||
{
|
||
perk = keys[ perk_idx ];
|
||
}
|
||
if ( isdefined( perk ) )
|
||
{
|
||
monkey_print( "perk is " + perk );
|
||
}
|
||
else
|
||
{
|
||
monkey_print( "no more perks" );
|
||
}
|
||
self.perk = perk;
|
||
}
|
||
monkey_pack_set_machine()
|
||
{
|
||
self.machine = undefined;
|
||
if ( !isdefined( self.perk ) )
|
||
{
|
||
return;
|
||
}
|
||
targets = getentarray( self.perk.target, "targetname" );
|
||
for ( j = 0; j < targets.size; j++ )
|
||
{
|
||
if ( targets[j].classname == "script_model" )
|
||
{
|
||
self.machine = targets[j];
|
||
}
|
||
}
|
||
}
|
||
monkey_pack_choose_enemy()
|
||
{
|
||
monkey_enemy = [];
|
||
players = getplayers();
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
if ( !is_player_valid( players[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
monkey_enemy[ monkey_enemy.size ] = players[i];
|
||
}
|
||
monkey_enemy = array_randomize( monkey_enemy );
|
||
if ( monkey_enemy.size > 0 )
|
||
{
|
||
self.enemy = monkey_enemy[0];
|
||
}
|
||
else
|
||
{
|
||
self.enemy = players[0];
|
||
}
|
||
}
|
||
monkey_pack_update_enemy()
|
||
{
|
||
while ( self.monkeys.size > 0 )
|
||
{
|
||
players = getplayers();
|
||
total_dist = 1000000;
|
||
player_idx = 0;
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
if ( !is_player_valid( players[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
dist = 0;
|
||
for ( j = 0; j < self.monkeys.size; j++ )
|
||
{
|
||
if ( !isdefined( self.monkeys[j] ) )
|
||
{
|
||
continue;
|
||
}
|
||
dist += Distance( players[i].origin, self.monkeys[j].origin );
|
||
}
|
||
if ( dist < total_dist )
|
||
{
|
||
total_dist = dist;
|
||
player_idx = i;
|
||
}
|
||
}
|
||
if ( isdefined( players ) )
|
||
{
|
||
if ( isdefined( self.enemy ) )
|
||
{
|
||
if ( self.enemy != players[ player_idx ] )
|
||
{
|
||
monkey_print( "pack enemy is " + self.enemy.playername );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
monkey_print( "pack enemy is " + players[ player_idx ].playername );
|
||
}
|
||
self.enemy = players[ player_idx ];
|
||
}
|
||
wait( 0.2 );
|
||
}
|
||
}
|
||
monkey_zombie_check_ground_hit()
|
||
{
|
||
if ( GetTime() >= self.ground_hit_time )
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
monkey_pack_update_ground_hit( hitter )
|
||
{
|
||
self.ground_hit_time = GetTime() + level.ground_hit_delay;
|
||
level.ground_hit_delay = RandomFloatRange( 4.5, 6.5 ) * 1000;
|
||
for ( i = 0; i < self.monkeys.size; i++ )
|
||
{
|
||
if ( isDefined( self.monkeys[i] ) )
|
||
{
|
||
self.monkeys[i].ground_hit_time = self.ground_hit_time;
|
||
}
|
||
}
|
||
groundpound_reset = level.monkey_zombie_groundhit_trigger_radius * 2;
|
||
groundpound_reset_sq = groundpound_reset * groundpound_reset;
|
||
for ( i = 0; i < level.monkey_pack.size; i++ )
|
||
{
|
||
pack = level.monkey_pack[i];
|
||
if ( self == pack )
|
||
{
|
||
continue;
|
||
}
|
||
for ( j = 0; j < pack.monkeys.size; j++ )
|
||
{
|
||
monkey = pack.monkeys[j];
|
||
if ( !isDefined( monkey ) )
|
||
{
|
||
continue;
|
||
}
|
||
if ( hitter == monkey )
|
||
{
|
||
continue;
|
||
}
|
||
dist_sq = DistanceSquared( hitter.origin, monkey.origin );
|
||
if ( dist_sq <= groundpound_reset_sq )
|
||
{
|
||
monkey.ground_hit_time = self.ground_hit_time;
|
||
}
|
||
}
|
||
}
|
||
monkey_print( "next ground hit in " + level.ground_hit_delay );
|
||
}
|
||
monkey_round_wait()
|
||
{
|
||
wait( 1 );
|
||
if ( flag( "monkey_round" ) )
|
||
{
|
||
wait( 7 );
|
||
while ( level.monkey_intermission )
|
||
{
|
||
wait( 0.5 );
|
||
}
|
||
}
|
||
}
|
||
monkey_round_aftermath()
|
||
{
|
||
flag_wait( "last_monkey_down" );
|
||
level thread maps\_zombiemode_audio::change_zombie_music( "dog_end" );
|
||
level.round_spawn_func = level.monkey_save_spawn_func;
|
||
level.round_wait_func = level.monkey_save_wait_func;
|
||
wait( 6 );
|
||
level.monkey_intermission = false;
|
||
}
|
||
monkey_round_tracker()
|
||
{
|
||
flag_wait( "power_on" );
|
||
flag_wait( "perk_bought" );
|
||
level.monkey_save_spawn_func = level.round_spawn_func;
|
||
level.monkey_save_wait_func = level.round_wait_func;
|
||
level.next_monkey_round = level.round_number + randomintrange( 1, 4 );
|
||
level.prev_monkey_round = level.next_monkey_round;
|
||
while ( 1 )
|
||
{
|
||
level waittill( "between_round_over" );
|
||
if ( level.round_number == level.next_monkey_round )
|
||
{
|
||
if ( !monkey_player_has_perk() )
|
||
{
|
||
level.next_monkey_round++;
|
||
monkey_print( "next monkey round at " + level.next_monkey_round );
|
||
continue;
|
||
}
|
||
level.music_round_override = true;
|
||
level.monkey_save_spawn_func = level.round_spawn_func;
|
||
level.monkey_save_wait_func = level.round_wait_func;
|
||
monkey_round_start();
|
||
level.round_spawn_func = ::monkey_round_spawning;
|
||
level.round_wait_func = ::monkey_round_wait;
|
||
level.prev_monkey_round = level.next_monkey_round;
|
||
level.next_monkey_round = level.round_number + randomintrange( 4, 6 );
|
||
monkey_print( "next monkey round at " + level.next_monkey_round );
|
||
}
|
||
else if ( flag( "monkey_round" ) )
|
||
{
|
||
monkey_round_stop();
|
||
level.music_round_override = false;
|
||
}
|
||
}
|
||
}
|
||
monkey_round_start()
|
||
{
|
||
flag_set( "monkey_round" );
|
||
flag_set( "monkey_free_perk" );
|
||
if ( isDefined( level.monkey_round_start ) )
|
||
{
|
||
level thread [[ level.monkey_round_start ]]();
|
||
}
|
||
level thread monkey_zombie_setup_perks();
|
||
level monkey_setup_health();
|
||
level monkey_setup_spawners();
|
||
level monkey_setup_packs();
|
||
level monkey_pack_man_setup_perks();
|
||
level thread monkey_grenade_watcher();
|
||
clientnotify( "monkey_start" );
|
||
level thread play_delayed_player_vox();
|
||
}
|
||
play_delayed_player_vox()
|
||
{
|
||
wait(8);
|
||
players = getplayers();
|
||
players[RandomIntRange(0,players.size)] maps\_zombiemode_audio::create_and_play_dialog( "general", "monkey_spawn" );
|
||
}
|
||
monkey_round_stop()
|
||
{
|
||
flag_clear( "monkey_round" );
|
||
flag_clear( "last_monkey_down" );
|
||
if ( isDefined( level.monkey_round_stop ) )
|
||
{
|
||
level thread [[ level.monkey_round_stop ]]();
|
||
}
|
||
clientnotify( "monkey_stop" );
|
||
level notify( "grenade_watcher_stop" );
|
||
}
|
||
monkey_player_has_perk()
|
||
{
|
||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||
for ( i = 0; i < vending_triggers.size; i++ )
|
||
{
|
||
players = getplayers();
|
||
for ( j = 0; j < players.size; j++ )
|
||
{
|
||
perk = vending_triggers[i].script_noteworthy;
|
||
org = vending_triggers[i].origin;
|
||
if ( isdefined( vending_triggers[i].realorigin ) )
|
||
{
|
||
org = vending_triggers[i].realorigin;
|
||
}
|
||
zone_enabled = check_point_in_active_zone( org );
|
||
if ( players[j] HasPerk( perk ) && zone_enabled )
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
monkey_zombie_manager()
|
||
{
|
||
while( true )
|
||
{
|
||
AssertEx( isDefined( level.num_monkey_zombies ) && isDefined( level.max_monkey_zombies ), "Either max_monkey_zombies or num_monkey_zombies not defined, this should never be the case!" );
|
||
while( level.num_monkey_zombies < level.max_monkey_zombies )
|
||
{
|
||
spawner = monkey_zombie_pick_best_spawner();
|
||
if( isDefined( spawner ) )
|
||
{
|
||
spawner monkey_zombie_spawn();
|
||
}
|
||
wait( 10 );
|
||
}
|
||
wait( 10 );
|
||
}
|
||
}
|
||
monkey_zombie_pick_best_spawner()
|
||
{
|
||
best_spawner = undefined;
|
||
best_score = -1;
|
||
for( i = 0; i < level.monkey_zombie_spawners.size; i++ )
|
||
{
|
||
score = [[ level.monkey_zombie_spawn_heuristic ]]( level.monkey_zombie_spawners[i] );
|
||
if( score > best_score )
|
||
{
|
||
best_spawner = level.monkey_zombie_spawners[i];
|
||
best_score = score;
|
||
}
|
||
}
|
||
return best_spawner;
|
||
}
|
||
monkey_zombie_choose_run()
|
||
{
|
||
self endon( "death" );
|
||
rand = randomIntRange( 1, 3 );
|
||
self set_run_anim( "run"+rand );
|
||
self.run_combatanim = level.scr_anim["monkey_zombie"]["run"+rand];
|
||
self.crouchRunAnim = level.scr_anim["monkey_zombie"]["run"+rand];
|
||
self.crouchrun_combatanim = level.scr_anim["monkey_zombie"]["run"+rand];
|
||
self.zombie_move_speed = "run";
|
||
self waittill( "speed_up" );
|
||
rand = randomIntRange( 1, 5 );
|
||
self set_run_anim( "sprint"+rand );
|
||
self.run_combatanim = level.scr_anim["monkey_zombie"]["sprint"+rand];
|
||
self.crouchRunAnim = level.scr_anim["monkey_zombie"]["sprint"+rand];
|
||
self.crouchrun_combatanim = level.scr_anim["monkey_zombie"]["sprint"+rand];
|
||
self.zombie_move_speed = "sprint";
|
||
}
|
||
monkey_zombie_think()
|
||
{
|
||
self endon( "death" );
|
||
self thread play_random_monkey_vox();
|
||
self.goalradius = 32;
|
||
self.pathEnemyFightDist = 64;
|
||
self.meleeAttackDist = 64;
|
||
self.charge_player = false;
|
||
level.monkey_zombie_min_health = int( level.monkey_zombie_health );
|
||
if( self.maxhealth < level.monkey_zombie_min_health )
|
||
{
|
||
self.maxhealth = level.monkey_zombie_min_health;
|
||
self.health = level.monkey_zombie_min_health;
|
||
}
|
||
if ( isdefined( level.user_ryan_monkey_health ) )
|
||
{
|
||
self.maxhealth = 1;
|
||
self.health = 1;
|
||
}
|
||
self thread monkey_zombie_choose_run();
|
||
self.maxsightdistsqrd = 96 * 96;
|
||
self [[ level.monkey_zombie_enter_level ]]();
|
||
if ( isDefined( level.monkey_zombie_custom_think ) )
|
||
{
|
||
self thread [[ level.monkey_zombie_custom_think ]]();
|
||
}
|
||
self thread monkey_zombie_ground_hit_think();
|
||
self thread monkey_zombie_grenade_watcher();
|
||
self thread monkey_zombie_bhb_watcher();
|
||
self thread monkey_zombie_speed_watcher();
|
||
self thread monkey_zombie_fling_watcher();
|
||
self thread monkey_zombie_update();
|
||
if ( isDefined( level.monkey_zombie_failsafe ) )
|
||
{
|
||
self thread [[ level.monkey_zombie_failsafe ]]();
|
||
}
|
||
}
|
||
monkey_zombie_debug()
|
||
{
|
||
self endon( "death" );
|
||
while( true )
|
||
{
|
||
forward = VectorNormalize( AnglesToForward( self.angles ) );
|
||
end_pos = self.origin - vector_scale( forward, 120 );
|
||
recordLine( self.origin, end_pos, (.5,1,0), "Script", self );
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_zombie_update()
|
||
{
|
||
self endon( "death" );
|
||
self endon( "monkey_update_stop" );
|
||
self animmode( "none" );
|
||
while( true )
|
||
{
|
||
if ( isDefined( self.custom_think ) && self.custom_think )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
else if ( self.state == "bhb_response" || self.state == "grenade_response" )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
else if ( isDefined( self.perk ) )
|
||
{
|
||
self thread monkey_zombie_destroy_perk();
|
||
self waittill( "stop_perk_attack" );
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
else if ( isDefined( self.ground_hit ) && self.ground_hit )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
else if( !isDefined( self.following_player ) || !self.following_player )
|
||
{
|
||
self thread maps\_zombiemode_ai_monkey::monkey_find_flesh();
|
||
self.following_player = true;
|
||
self monkey_zombie_set_state( "charge_player" );
|
||
}
|
||
wait( 1 );
|
||
}
|
||
}
|
||
monkey_zombie_get_perk_pos()
|
||
{
|
||
points = getstructarray( self.pack.machine.target, "targetname" );
|
||
for ( i = 0; i < points.size; i++ )
|
||
{
|
||
if ( isdefined( self.pack.attack[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
self.pack.attack[i] = self;
|
||
self.attack = points[i];
|
||
break;
|
||
}
|
||
}
|
||
monkey_pack_clear_perk_pos()
|
||
{
|
||
self.attack = [];
|
||
}
|
||
monkey_zombie_health_watcher()
|
||
{
|
||
self endon( "death" );
|
||
health_limit = self.health * 0.75;
|
||
while ( 1 )
|
||
{
|
||
if ( self.health <= health_limit )
|
||
{
|
||
self StopAnimScripted();
|
||
wait_network_frame();
|
||
self notify( "stop_perk_attack" );
|
||
self monkey_zombie_set_state( "charge_player" );
|
||
self.charge_player = true;
|
||
self.perk = undefined;
|
||
break;
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_zombie_fling_watcher()
|
||
{
|
||
self endon( "death" );
|
||
half_health = level.monkey_zombie_health * 0.5;
|
||
while ( 1 )
|
||
{
|
||
if ( self.health <= half_health )
|
||
{
|
||
self.thundergun_fling_func = undefined;
|
||
break;
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_zombie_speed_watcher()
|
||
{
|
||
self endon( "death" );
|
||
while ( 1 )
|
||
{
|
||
if ( self.health < self.maxhealth )
|
||
{
|
||
break;
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
self notify( "speed_up" );
|
||
}
|
||
monkey_grenade_watcher()
|
||
{
|
||
self endon( "death" );
|
||
level.monkey_grenades = [];
|
||
level.monkey_bhbs = [];
|
||
players = getplayers();
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
players[i] thread monkey_grenade_watch();
|
||
}
|
||
}
|
||
monkey_grenade_watch()
|
||
{
|
||
self endon( "death" );
|
||
level endon( "grenade_watcher_stop" );
|
||
while ( true )
|
||
{
|
||
self waittill( "grenade_fire", grenade, weapName );
|
||
if ( is_lethal_grenade( weapName ) )
|
||
{
|
||
grenade thread monkey_grenade_wait();
|
||
grenade.thrower = self;
|
||
level.monkey_grenades[ level.monkey_grenades.size ] = grenade;
|
||
}
|
||
if ( weapName == "zombie_black_hole_bomb" )
|
||
{
|
||
grenade thread monkey_bhb_wait();
|
||
level.monkey_bhbs[ level.monkey_bhbs.size ] = grenade;
|
||
}
|
||
monkey_print( "thrown from " + weapName );
|
||
}
|
||
}
|
||
monkey_grenade_wait()
|
||
{
|
||
self waittill( "death" );
|
||
level.monkey_grenades = array_remove( level.monkey_grenades, self );
|
||
monkey_print( "remove grenade from level" );
|
||
}
|
||
monkey_bhb_wait()
|
||
{
|
||
self waittill( "death" );
|
||
level.monkey_bhbs = array_remove( level.monkey_bhbs, self );
|
||
monkey_print( "remove bhb from level" );
|
||
}
|
||
monkey_zombie_grenade_throw_watcher( target, animname )
|
||
{
|
||
self endon( "death" );
|
||
self waittillmatch( animname, "grenade_throw" );
|
||
throw_angle = RandomIntRange( 20, 30 );
|
||
dir = VectorToAngles( target.origin - self.origin );
|
||
dir = ( dir[0] - throw_angle, dir[1], dir[2] );
|
||
dir = AnglesToForward( dir );
|
||
velocity = dir * 550;
|
||
fuse = RandomFloatRange( 1, 2 );
|
||
hand_pos = self GetTagOrigin( "TAG_WEAPON_RIGHT" );
|
||
grenade_type = target get_player_lethal_grenade();
|
||
self MagicGrenadeType( grenade_type, hand_pos, velocity, fuse );
|
||
}
|
||
monkey_zombie_grenade_throw( target )
|
||
{
|
||
self endon( "death" );
|
||
throw_anim = [];
|
||
forward = VectorNormalize( AnglesToForward( self.angles ) );
|
||
end_pos = self.origin + vector_scale( forward, 96 );
|
||
if ( BulletTracePassed( self.origin, end_pos, false, undefined ) )
|
||
{
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_run_01;
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_run_02;
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_run_03;
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_run_04;
|
||
}
|
||
else
|
||
{
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_still_01;
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_still_02;
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_still_03;
|
||
throw_anim[ throw_anim.size ] = %ai_zombie_monkey_grenade_throw_back_still_04;
|
||
}
|
||
throw_back_anim = throw_anim[ RandomInt( throw_anim.size ) ];
|
||
self animscripted( "throw_back_anim", self.origin, self.angles, throw_back_anim );
|
||
self thread monkey_zombie_grenade_throw_watcher( target, "throw_back_anim" );
|
||
animscripts\traverse\zombie_shared::wait_anim_length( throw_back_anim, .02 );
|
||
choose = RandomInt( level._zombie_board_taunt["monkey_zombie"].size );
|
||
taunt_anim = level._zombie_board_taunt["monkey_zombie"][ choose ];
|
||
self animscripted( "taunt_anim", self.origin, self.angles, taunt_anim );
|
||
animscripts\traverse\zombie_shared::wait_anim_length( taunt_anim, .02 );
|
||
self notify( "throw_done" );
|
||
}
|
||
monkey_zombie_watch_machine_damage()
|
||
{
|
||
self endon( "death" );
|
||
self endon( "stop_perk_attack" );
|
||
self endon( "stop_machine_watch" );
|
||
arrival_health = self.health;
|
||
while ( 1 )
|
||
{
|
||
monkey_zone = self monkey_get_zone();
|
||
if ( isdefined( monkey_zone ) )
|
||
{
|
||
if ( monkey_zone.is_occupied || self.health < arrival_health )
|
||
{
|
||
monkey_print( "player is here, go crazy" );
|
||
self.machine_damage = level.machine_damage_max;
|
||
break;
|
||
}
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_zombie_set_state( state )
|
||
{
|
||
self.state = state;
|
||
monkey_print( "set state to " + state );
|
||
}
|
||
monkey_zombie_get_state()
|
||
{
|
||
if ( isdefined( self.state ) )
|
||
{
|
||
return self.state;
|
||
}
|
||
return undefined;
|
||
}
|
||
monkey_zombie_attack_perk()
|
||
{
|
||
self endon( "death" );
|
||
self endon( "stop_perk_attack" );
|
||
self endon( "next_perk" );
|
||
if ( !isdefined( self.perk ) )
|
||
{
|
||
return;
|
||
}
|
||
flag_clear( "monkey_free_perk" );
|
||
self.following_player = false;
|
||
self thread monkey_zombie_health_watcher();
|
||
self monkey_zombie_set_state( "attack_perk" );
|
||
level thread play_player_perk_theft_vox( self.perk.script_noteworthy, self );
|
||
spot = self.attack.script_int;
|
||
self Teleport( self.attack.origin, self.attack.angles );
|
||
monkey_print( "attack " + self.perk.script_noteworthy + " from " + spot );
|
||
choose = 0;
|
||
if ( spot == 1 )
|
||
{
|
||
choose = RandomIntRange( 1, 3 );
|
||
}
|
||
else if ( spot == 3 )
|
||
{
|
||
choose = RandomIntRange( 3, 5 );
|
||
}
|
||
perk_attack_anim = undefined;
|
||
if ( choose == 2 )
|
||
{
|
||
if ( isdefined( level.monkey_perk_attack_anims[ self.perk.script_noteworthy ] ) )
|
||
{
|
||
perk_attack_anim = level.monkey_perk_attack_anims[ self.perk.script_noteworthy ][ "left_top" ];
|
||
}
|
||
}
|
||
else if ( choose == 4 )
|
||
{
|
||
if ( isdefined( level.monkey_perk_attack_anims[ self.perk.script_noteworthy ] ) )
|
||
{
|
||
perk_attack_anim = level.monkey_perk_attack_anims[ self.perk.script_noteworthy ][ "right_top" ];
|
||
}
|
||
}
|
||
if ( !isdefined( perk_attack_anim ) )
|
||
{
|
||
perk_attack_anim = level.monkey_perk_attack_anims[ choose ];
|
||
}
|
||
time = getAnimLength( perk_attack_anim );
|
||
self thread monkey_wait_to_drop();
|
||
while ( 1 )
|
||
{
|
||
monkey_pack_flash_perk( self.perk.script_noteworthy );
|
||
self animscripted( "perk_attack_anim", self.attack.origin, self.attack.angles, perk_attack_anim, "normal", %body, 1, 0.2 );
|
||
self thread play_attack_impacts( time );
|
||
if ( self monkey_zombie_perk_damage( self.machine_damage ) )
|
||
{
|
||
break;
|
||
}
|
||
wait( time );
|
||
}
|
||
self notify( "stop_machine_watch" );
|
||
self monkey_zombie_set_state( "attack_perk_done" );
|
||
}
|
||
monkey_wait_to_drop()
|
||
{
|
||
self endon( "death" );
|
||
wait( 0.2 );
|
||
self.dropped = false;
|
||
self.perk_attack_origin = self.attack.origin;
|
||
while ( true )
|
||
{
|
||
diff = abs( self.perk_attack_origin[2] - self.origin[2] );
|
||
if ( diff < 8 )
|
||
{
|
||
break;
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
self.dropped = true;
|
||
monkey_print( "close to ground" );
|
||
}
|
||
play_player_perk_theft_vox( perk, monkey )
|
||
{
|
||
force_quit = 0;
|
||
if( !IsDefined( level.perk_theft_vox ) )
|
||
level.perk_theft_vox = [];
|
||
if( !IsDefined( level.perk_theft_vox[perk] ) )
|
||
level.perk_theft_vox[perk] = false;
|
||
if( level.perk_theft_vox[perk] )
|
||
return;
|
||
level.perk_theft_vox[perk] = true;
|
||
while(1)
|
||
{
|
||
player = getplayers();
|
||
rand = RandomIntRange(0, player.size );
|
||
if ( monkey monkey_zombie_perk_damage( monkey.machine_damage ) )
|
||
{
|
||
level.perk_theft_vox[perk] = false;
|
||
return;
|
||
}
|
||
if( ( IsAlive( player[rand] ) ) && ( !player[rand] maps\_laststand::player_is_in_laststand() ) && ( player[rand] HasPerk( perk ) ) )
|
||
{
|
||
player[rand] maps\_zombiemode_audio::create_and_play_dialog( "perk", "steal_" + perk );
|
||
break;
|
||
}
|
||
else if( force_quit >= 6 )
|
||
{
|
||
break;
|
||
}
|
||
force_quit ++;
|
||
wait(.05);
|
||
}
|
||
while( !monkey monkey_zombie_perk_damage( monkey.machine_damage ) )
|
||
{
|
||
wait(1);
|
||
}
|
||
level.perk_theft_vox[perk] = false;
|
||
}
|
||
play_attack_impacts( time )
|
||
{
|
||
self endon( "death" );
|
||
for(i=0;i<time;i++)
|
||
{
|
||
if( RandomIntRange(0,100) >= 41 )
|
||
self PlaySound( "zmb_monkey_attack_machine" );
|
||
wait(RandomFloatRange(.7,1.1));
|
||
}
|
||
}
|
||
monkey_zombie_destroy_perk()
|
||
{
|
||
self endon( "death" );
|
||
self endon( "stop_perk_attack" );
|
||
if ( isdefined( self.perk ) )
|
||
{
|
||
self monkey_zombie_set_state( "destroy_perk" );
|
||
monkey_print( "goto " + self.perk.script_noteworthy );
|
||
self monkey_zombie_get_perk_pos();
|
||
if ( isdefined( self.attack ) )
|
||
{
|
||
self SetGoalPos( self.attack.origin );
|
||
self waittill( "goal" );
|
||
self SetGoalPos( self.origin );
|
||
self thread monkey_zombie_watch_machine_damage();
|
||
self thread monkey_zombie_attack_perk();
|
||
}
|
||
}
|
||
}
|
||
monkey_zombie_default_spawn_heuristic( spawner )
|
||
{
|
||
if( !isDefined( spawner.script_noteworthy ) )
|
||
{
|
||
return -1;
|
||
}
|
||
if( !isDefined( level.zones ) || !isDefined( level.zones[ spawner.script_noteworthy ] ) || !level.zones[ spawner.script_noteworthy ].is_enabled )
|
||
{
|
||
return -1;
|
||
}
|
||
score = 0;
|
||
players = get_players();
|
||
for( i = 0; i < players.size; i++ )
|
||
{
|
||
score = int( distanceSquared( spawner.origin, players[i].origin ) );
|
||
}
|
||
return score;
|
||
}
|
||
monkey_zombie_ground_hit()
|
||
{
|
||
self endon( "death" );
|
||
if ( self.ground_hit )
|
||
{
|
||
return;
|
||
}
|
||
self monkey_zombie_set_state( "ground_pound" );
|
||
self.ground_hit = true;
|
||
self thread groundhit_watcher( "groundhit_anim" );
|
||
choose = RandomInt( level.monkey_groundpound_anims.size );
|
||
groundpound_anim = level.monkey_groundpound_anims[ choose ];
|
||
self animscripted( "groundhit_anim", self.origin, self.angles, groundpound_anim );
|
||
animscripts\traverse\zombie_shared::wait_anim_length(groundpound_anim, .02);
|
||
self.ground_hit = false;
|
||
self monkey_zombie_set_state( "ground_pound_done" );
|
||
self.nextGroundHit = GetTime() + level.monkey_ground_attack_delay;
|
||
if ( self.chest_beat )
|
||
{
|
||
choose = RandomInt( level._zombie_board_taunt["monkey_zombie"].size );
|
||
taunt_anim = level._zombie_board_taunt["monkey_zombie"][ choose ];
|
||
self animscripted( "taunt_anim", self.origin, self.angles, taunt_anim );
|
||
time = getAnimLength( taunt_anim );
|
||
wait( time );
|
||
self.chest_beat = false;
|
||
}
|
||
self thread animscripts\zombie_combat::main();
|
||
}
|
||
monkey_pack_ready_to_detonate( claymore )
|
||
{
|
||
for ( i = 0; i < self.monkeys.size; i++ )
|
||
{
|
||
if ( self.monkeys[i] == self )
|
||
{
|
||
continue;
|
||
}
|
||
ready = self.monkeys[i].force_detonate;
|
||
if ( isdefined( ready ) )
|
||
{
|
||
for ( j = 0; j < ready.size; j++ )
|
||
{
|
||
if ( claymore == ready[j] )
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
monkey_zombie_force_groundhit()
|
||
{
|
||
if ( !isdefined( level.claymores ) )
|
||
{
|
||
return false;
|
||
}
|
||
claymore_dist = 216*216;
|
||
height_max = 12;
|
||
self.force_detonate = [];
|
||
for ( i = 0; i < level.claymores.size; i++ )
|
||
{
|
||
if ( self.pack monkey_pack_ready_to_detonate( level.claymores[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
height_diff = abs( self.origin[2] - level.claymores[i].origin[2] );
|
||
if ( height_diff < height_max )
|
||
{
|
||
if ( DistanceSquared( self.origin, level.claymores[i].origin ) < claymore_dist )
|
||
{
|
||
self.force_detonate[ self.force_detonate.size ] = level.claymores[i];
|
||
}
|
||
}
|
||
}
|
||
return self.force_detonate.size > 0;
|
||
}
|
||
monkey_zombie_ground_hit_think()
|
||
{
|
||
self endon( "death" );
|
||
self.ground_hit = false;
|
||
self.nextGroundHit = GetTime() + level.monkey_ground_attack_delay;
|
||
while( 1 )
|
||
{
|
||
if ( self.state == "attack_perk" )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
if ( !self.dropped )
|
||
{
|
||
wait( 1 );
|
||
continue;
|
||
}
|
||
if ( !self.ground_hit && self monkey_zombie_force_groundhit() )
|
||
{
|
||
self.pack monkey_pack_update_ground_hit( self );
|
||
self animcustom( ::monkey_zombie_ground_hit );
|
||
}
|
||
else if ( !self.ground_hit && self monkey_zombie_check_ground_hit() )
|
||
{
|
||
players = GetPlayers();
|
||
closeEnough = false;
|
||
origin = self GetEye();
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
if ( players[i] maps\_laststand::player_is_in_laststand() )
|
||
{
|
||
continue;
|
||
}
|
||
test_origin = players[i] GetEye();
|
||
d = DistanceSquared( origin, test_origin );
|
||
if ( d > level.monkey_zombie_groundhit_trigger_radius * level.monkey_zombie_groundhit_trigger_radius )
|
||
{
|
||
continue;
|
||
}
|
||
if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
|
||
{
|
||
continue;
|
||
}
|
||
closeEnough = true;
|
||
break;
|
||
}
|
||
if ( closeEnough )
|
||
{
|
||
self.pack monkey_pack_update_ground_hit( self );
|
||
self animcustom( ::monkey_zombie_ground_hit );
|
||
}
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
groundhit_watcher( animname )
|
||
{
|
||
self endon( "death" );
|
||
self waittillmatch( animname, "fire" );
|
||
playfxontag( level._effect["monkey_groundhit"], self, "tag_origin" );
|
||
origin = self.origin + ( 0, 0, 40 );
|
||
zombies_axis = get_array_of_closest( origin, GetAiSpeciesArray( "axis", "all" ), undefined, undefined, level.monkey_zombie_groundhit_damage_radius );
|
||
dogs = get_array_of_closest( origin, GetAiSpeciesArray( "allies", "zombie_dog" ), undefined, undefined, level.monkey_zombie_groundhit_damage_radius );
|
||
zombies = array_combine( zombies_axis, dogs );
|
||
if ( IsDefined( zombies ) )
|
||
{
|
||
for ( i = 0; i < zombies.size; i++ )
|
||
{
|
||
if ( !IsDefined( zombies[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
if ( is_magic_bullet_shield_enabled( zombies[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
test_origin = zombies[i] GetEye();
|
||
if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
|
||
{
|
||
continue;
|
||
}
|
||
if ( zombies[i] == self )
|
||
{
|
||
continue;
|
||
}
|
||
if ( zombies[i].animname == "monkey_zombie" )
|
||
{
|
||
continue;
|
||
}
|
||
refs = [];
|
||
refs[refs.size] = "guts";
|
||
refs[refs.size] = "right_arm";
|
||
refs[refs.size] = "left_arm";
|
||
refs[refs.size] = "right_leg";
|
||
refs[refs.size] = "left_leg";
|
||
refs[refs.size] = "no_legs";
|
||
refs[refs.size] = "head";
|
||
if( refs.size )
|
||
{
|
||
zombies[i].a.gib_ref = random( refs );
|
||
}
|
||
zombies[i] DoDamage( zombies[i].health * 10, self.origin, self );
|
||
}
|
||
}
|
||
players = get_players();
|
||
affected_players = [];
|
||
for( i = 0; i < players.size; i++ )
|
||
{
|
||
if ( !is_player_valid( players[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
test_origin = players[i] GetEye();
|
||
if( distanceSquared( origin, test_origin ) > level.monkey_zombie_groundhit_damage_radius * level.monkey_zombie_groundhit_damage_radius )
|
||
{
|
||
continue;
|
||
}
|
||
if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
|
||
{
|
||
continue;
|
||
}
|
||
affected_players = array_add( affected_players, players[i] );
|
||
}
|
||
self.chest_beat = false;
|
||
for( i = 0; i < affected_players.size; i++ )
|
||
{
|
||
self.chest_beat = true;
|
||
player = affected_players[i];
|
||
if ( player IsOnGround() )
|
||
{
|
||
damage = player.maxhealth * 0.5;
|
||
player ShellShock( "electrocution", 1.5, true );
|
||
player DoDamage( damage, self.origin, self );
|
||
}
|
||
}
|
||
if ( isdefined( self.force_detonate ) )
|
||
{
|
||
for ( i = 0; i < self.force_detonate.size; i++ )
|
||
{
|
||
if ( isdefined( self.force_detonate[i] ) )
|
||
{
|
||
self.force_detonate[i] detonate( undefined );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
monkey_zombie_grenade_pickup()
|
||
{
|
||
self endon( "death" );
|
||
pickup_dist_sq = 32*32;
|
||
picked_up = false;
|
||
while ( isdefined( self.monkey_grenade ) )
|
||
{
|
||
self SetGoalPos( self.monkey_grenade.origin );
|
||
grenade_dist_sq = DistanceSquared( self.origin, self.monkey_grenade.origin );
|
||
if ( grenade_dist_sq <= pickup_dist_sq )
|
||
{
|
||
self.monkey_thrower = self.monkey_grenade.thrower;
|
||
self.monkey_grenade delete();
|
||
self.monkey_grenade = undefined;
|
||
picked_up = true;
|
||
monkey_print( "deleting grenade" );
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
if ( picked_up )
|
||
{
|
||
while ( 1 )
|
||
{
|
||
self SetGoalPos( self.monkey_thrower.origin );
|
||
target_dir = self.monkey_thrower.origin - self.origin;
|
||
monkey_dir = AnglesToForward( self.angles );
|
||
dot = VectorDot( VectorNormalize( target_dir ), VectorNormalize( monkey_dir ) );
|
||
if ( dot >= 0.5 )
|
||
{
|
||
break;
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
self thread monkey_zombie_grenade_throw( self.monkey_thrower );
|
||
self waittill( "throw_done" );
|
||
}
|
||
}
|
||
monkey_zombie_grenade_response()
|
||
{
|
||
self endon( "death" );
|
||
monkey_print( "go for grenade" );
|
||
self notify( "stop_find_flesh" );
|
||
self notify( "zombie_acquire_enemy" );
|
||
self notify( "monkey_update_stop" );
|
||
self notify( "stop_perk_attack" );
|
||
self.following_player = false;
|
||
self monkey_zombie_set_state( "grenade_response" );
|
||
self monkey_zombie_clear_attack_pos();
|
||
self monkey_zombie_grenade_pickup();
|
||
self thread monkey_zombie_update();
|
||
self monkey_zombie_set_state( "grenade_response_done" );
|
||
}
|
||
monkey_zombie_grenade_watcher()
|
||
{
|
||
self endon( "death" );
|
||
grenade_respond_dist_sq = 120 * 120;
|
||
while ( 1 )
|
||
{
|
||
if ( self.state == "default" )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
if ( is_true( self.ground_hit ) )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
if ( is_true( self.monkey_grenade ) )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
if ( level.monkey_grenades.size > 0 )
|
||
{
|
||
for ( i = 0; i < level.monkey_grenades.size; i++ )
|
||
{
|
||
grenade = level.monkey_grenades[i];
|
||
if ( !isdefined( grenade ) || isdefined( grenade.monkey ) )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
grenade_dist_sq = DistanceSquared( self.origin, grenade.origin );
|
||
if ( grenade_dist_sq <= grenade_respond_dist_sq )
|
||
{
|
||
grenade.monkey = self;
|
||
self.monkey_grenade = grenade;
|
||
self monkey_zombie_grenade_response();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_zombie_bhb_teleport()
|
||
{
|
||
self endon( "death" );
|
||
monkey_print( "bhb teleport" );
|
||
black_hole_teleport = getstructarray( "struct_black_hole_teleport", "targetname" );
|
||
assertex( black_hole_teleport.size > 0, "struct_black_hole_teleport not found" );
|
||
zone_name = self get_current_zone();
|
||
locations = [];
|
||
for ( i = 0; i < black_hole_teleport.size; i++ )
|
||
{
|
||
bhb_zone_name = black_hole_teleport[i].script_string;
|
||
if ( !isDefined( bhb_zone_name ) || !isDefined( zone_name ) )
|
||
{
|
||
continue;
|
||
}
|
||
if ( bhb_zone_name == zone_name )
|
||
{
|
||
continue;
|
||
}
|
||
if ( !level.zones[ bhb_zone_name ].is_enabled )
|
||
{
|
||
continue;
|
||
}
|
||
locations[ locations.size ] = black_hole_teleport[i];
|
||
}
|
||
self StopAnimScripted();
|
||
wait_network_frame();
|
||
so = spawn( "script_origin", self.origin );
|
||
so.angles = self.angles;
|
||
self linkto( so );
|
||
if ( locations.size > 0 )
|
||
{
|
||
locations = array_randomize( locations );
|
||
so.origin = locations[0].origin;
|
||
so.angles = locations[0].angles;
|
||
}
|
||
else
|
||
{
|
||
so.origin = self.spawn_origin;
|
||
so.angles = self.spawn_angles;
|
||
}
|
||
wait_network_frame();
|
||
self unlink();
|
||
so delete();
|
||
maps\_zombiemode_weap_black_hole_bomb::black_hole_bomb_create_exit_portal( self.origin );
|
||
}
|
||
monkey_zombie_bhb_failsafe()
|
||
{
|
||
self endon( "death" );
|
||
self endon( "bhb_old_failsafe" );
|
||
prev_origin = self.origin;
|
||
min_movement = 16*16;
|
||
while ( true )
|
||
{
|
||
wait( 1 );
|
||
dist = DistanceSquared( prev_origin, self.origin );
|
||
if ( dist < min_movement )
|
||
{
|
||
break;
|
||
}
|
||
prev_origin = self.origin;
|
||
}
|
||
if ( self.state == "ground_pound" )
|
||
{
|
||
return;
|
||
}
|
||
self.safeToChangeScript = true;
|
||
self animmode( "none" );
|
||
}
|
||
monkey_zombie_bhb_run()
|
||
{
|
||
self endon( "death" );
|
||
jump_dist_sq = 64*64;
|
||
jump = false;
|
||
wait_network_frame();
|
||
if ( !isdefined( self.monkey_bhb ) || !isdefined( self.monkey_bhb.origin ) )
|
||
{
|
||
return;
|
||
}
|
||
self.safeToChangeScript = false;
|
||
self SetGoalPos( self.monkey_bhb.origin );
|
||
while ( isdefined( self.monkey_bhb ) )
|
||
{
|
||
bhb_dist_sq = DistanceSquared( self.origin, self.monkey_bhb.origin );
|
||
if ( bhb_dist_sq <= jump_dist_sq )
|
||
{
|
||
jump = true;
|
||
break;
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
if ( jump )
|
||
{
|
||
jump_anim = %ai_zombie_monkey_portal_jump_01;
|
||
self animscripted( "jump_anim", self.origin, self.angles, jump_anim );
|
||
jump_length = getanimlength( jump_anim );
|
||
pre_jump = jump_length * 0.625;
|
||
post_jump = jump_length * 0.375;
|
||
wait( pre_jump );
|
||
self stopanimscripted();
|
||
wait_network_frame();
|
||
self monkey_zombie_bhb_teleport();
|
||
}
|
||
wait_network_frame();
|
||
self.safeToChangeScript = true;
|
||
self SetGoalPos( self.origin );
|
||
self waittill_any_or_timeout( 0.5, "goal" );
|
||
self notify( "bhb_old_failsafe" );
|
||
wait_network_frame();
|
||
self thread monkey_zombie_bhb_failsafe();
|
||
}
|
||
monkey_zombie_clear_attack_pos()
|
||
{
|
||
if ( isDefined( self.attack ) )
|
||
{
|
||
if ( isDefined( self.pack.attack ) )
|
||
{
|
||
for ( i = 0; i < self.pack.attack.size; i++ )
|
||
{
|
||
if ( self == self.pack.attack[i] )
|
||
{
|
||
self.pack.attack = array_remove( self.pack.attack, self );
|
||
self.attack = undefined;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
monkey_zombie_bhb_response()
|
||
{
|
||
self endon( "death" );
|
||
monkey_print( "bhb response" );
|
||
self notify( "stop_find_flesh" );
|
||
self notify( "zombie_acquire_enemy" );
|
||
self notify( "monkey_update_stop" );
|
||
self notify( "stop_perk_attack" );
|
||
self.following_player = false;
|
||
self monkey_zombie_set_state( "bhb_response" );
|
||
self monkey_zombie_clear_attack_pos();
|
||
self monkey_zombie_bhb_run();
|
||
self thread monkey_zombie_update();
|
||
self monkey_zombie_set_state( "bhb_response_done" );
|
||
}
|
||
monkey_zombie_bhb_watcher()
|
||
{
|
||
self endon( "death" );
|
||
bhb_respond_dist_sq = 512 * 512;
|
||
while ( 1 )
|
||
{
|
||
if ( self.state == "default" ||
|
||
self.state == "ground_pound" || self.state == "ground_pound_taunt" ||
|
||
self.state == "grenade_reponse" || self.state == "bhb_response" ||
|
||
self.state == "attack_perk" || !self.dropped )
|
||
{
|
||
wait_network_frame();
|
||
continue;
|
||
}
|
||
if ( level.monkey_bhbs.size > 0 )
|
||
{
|
||
for ( i = 0; i < level.monkey_bhbs.size; i++ )
|
||
{
|
||
bhb = level.monkey_bhbs[i];
|
||
if ( is_true( bhb.is_valid ) )
|
||
{
|
||
if ( !isDefined( bhb ) || !isDefined( bhb.origin ) || !isDefined( self.origin ) )
|
||
{
|
||
continue;
|
||
}
|
||
bhb_dist_sq = DistanceSquared( self.origin, bhb.origin );
|
||
if ( bhb_dist_sq <= bhb_respond_dist_sq )
|
||
{
|
||
self.monkey_bhb = bhb;
|
||
self monkey_zombie_bhb_response();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_remove_from_pack()
|
||
{
|
||
for ( i = 0; i < level.monkey_pack.size; i++ )
|
||
{
|
||
pack = level.monkey_pack[i];
|
||
for ( j = 0; j < pack.monkeys.size; j++ )
|
||
{
|
||
if ( self == pack.monkeys[j] )
|
||
{
|
||
pack.monkeys = array_remove( pack.monkeys, self );
|
||
if ( pack.monkeys.size == 0 && pack.spawning_done )
|
||
{
|
||
if ( isdefined( pack.perk ) )
|
||
{
|
||
pack.perk.targeted = 0;
|
||
}
|
||
level.monkey_packs_killed++;
|
||
flag_set( "monkey_pack_down" );
|
||
level.monkey_pack = array_remove( level.monkey_pack, pack );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ( level.monkey_packs_killed >= level.monkey_pack_max )
|
||
{
|
||
flag_set( "last_monkey_down" );
|
||
if ( self monkey_zombie_can_drop_free_perk() )
|
||
{
|
||
forward = VectorNormalize( AnglesToForward( self.angles ) );
|
||
end_pos = self.origin - vector_scale( forward, 32 );
|
||
level thread maps\_zombiemode_powerups::specific_powerup_drop( "free_perk", end_pos );
|
||
}
|
||
drop_pos = self.origin;
|
||
if ( self.state == "attack_perk" || !self.dropped )
|
||
{
|
||
drop_pos = self.attack.origin;
|
||
}
|
||
level thread maps\_zombiemode_powerups::specific_powerup_drop( "full_ammo", drop_pos );
|
||
}
|
||
}
|
||
monkey_zombie_can_drop_free_perk()
|
||
{
|
||
if ( !flag( "monkey_free_perk" ) )
|
||
{
|
||
return false;
|
||
}
|
||
max_perks = level.max_perks;
|
||
if ( flag( "solo_game" ) )
|
||
{
|
||
if ( level.solo_lives_given >= level.max_solo_lives )
|
||
{
|
||
players = getplayers();
|
||
if ( !players[0] HasPerk( "specialty_quickrevive" ) )
|
||
{
|
||
max_perks--;
|
||
}
|
||
}
|
||
}
|
||
players = getplayers();
|
||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
num_perks = 0;
|
||
for ( j = 0; j < vending_triggers.size; j++ )
|
||
{
|
||
perk = vending_triggers[j].script_noteworthy;
|
||
if ( players[i] HasPerk( perk ) )
|
||
{
|
||
num_perks++;
|
||
}
|
||
}
|
||
if ( num_perks < max_perks )
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
monkey_zombie_die()
|
||
{
|
||
self maps\_zombiemode_spawner::reset_attack_spot();
|
||
self.grenadeAmmo = 0;
|
||
self thread maps\_zombiemode_audio::do_zombies_playvocals( "death", self.animname );
|
||
self thread maps\_zombiemode_spawner::zombie_eye_glow_stop();
|
||
PlayFX( level._effect["monkey_death"], self.origin );
|
||
level maps\_zombiemode_spawner::zombie_death_points( self.origin, self.damagemod, self.damagelocation, self.attacker,self );
|
||
if( RandomIntRange(0,100) >= 75 )
|
||
{
|
||
if( IsDefined( self.attacker ) && IsPlayer( self.attacker ) )
|
||
self.attacker maps\_zombiemode_audio::create_and_play_dialog( "kill", "space_monkey" );
|
||
}
|
||
if( self.damagemod == "MOD_BURNED" )
|
||
{
|
||
self thread animscripts\zombie_death::flame_death_fx();
|
||
}
|
||
level.monkey_death++;
|
||
level.monkey_death_total++;
|
||
self monkey_remove_from_pack();
|
||
return false;
|
||
}
|
||
monkey_custom_damage( player )
|
||
{
|
||
self endon( "death" );
|
||
damage = self.meleeDamage;
|
||
if ( isDefined( self.ground_hit ) && self.ground_hit )
|
||
{
|
||
damage = int( player.maxhealth * 0.25 );
|
||
}
|
||
return damage;
|
||
}
|
||
monkey_zombie_default_enter_level()
|
||
{
|
||
Playfx( level._effect["monkey_spawn"], self.origin );
|
||
playsoundatposition( "zmb_bolt", self.origin );
|
||
PlayRumbleOnPosition("explosion_generic", self.origin);
|
||
}
|
||
monkey_pathing()
|
||
{
|
||
self endon( "death" );
|
||
while ( 1 )
|
||
{
|
||
if( IsDefined( self.favoriteenemy ) )
|
||
{
|
||
self.ignoreall = false;
|
||
self OrientMode( "face default" );
|
||
self SetGoalPos( self.favoriteenemy.origin );
|
||
}
|
||
wait_network_frame();
|
||
}
|
||
}
|
||
monkey_find_flesh()
|
||
{
|
||
self endon( "death" );
|
||
level endon( "intermission" );
|
||
self endon( "stop_find_flesh" );
|
||
if( level.intermission )
|
||
{
|
||
return;
|
||
}
|
||
self maps\_zombiemode_spawner::zombie_history( "monkey find flesh -> start" );
|
||
self.goalradius = 48;
|
||
players = getplayers();
|
||
self.ignore_player = [];
|
||
player = get_closest_valid_player( self.origin, self.ignore_player );
|
||
if( !isDefined( player ) )
|
||
{
|
||
self maps\_zombiemode_spawner::zombie_history( "monkey find flesh -> can't find player, continue" );
|
||
}
|
||
self.favoriteenemy = player;
|
||
while( 1 )
|
||
{
|
||
if ( isdefined( self.pack ) && isdefined( self.pack.enemy ) )
|
||
{
|
||
if ( !isdefined( self.favoriteenemy ) || self.favoriteenemy != self.pack.enemy )
|
||
{
|
||
self.favoriteenemy = self.pack.enemy;
|
||
}
|
||
}
|
||
if ( isdefined( level.user_ryan_monkey_pathing ) )
|
||
{
|
||
self thread maps\_zombiemode_ai_monkey::monkey_pathing();
|
||
}
|
||
else
|
||
{
|
||
self thread maps\_zombiemode_spawner::zombie_pathing();
|
||
}
|
||
self.zombie_path_timer = GetTime() + ( RandomFloatRange( 1, 3 ) * 1000 );
|
||
while( GetTime() < self.zombie_path_timer )
|
||
{
|
||
wait( 0.1 );
|
||
}
|
||
self maps\_zombiemode_spawner::zombie_history( "monkey find flesh -> bottom of loop" );
|
||
debug_print( "Zombie is re-acquiring enemy, ending breadcrumb search" );
|
||
self notify( "zombie_acquire_enemy" );
|
||
}
|
||
}
|
||
monkey_zombie_setup_perks()
|
||
{
|
||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||
for ( i = 0; i < vending_triggers.size; i++ )
|
||
{
|
||
vending_triggers[i] monkey_zombie_perk_init();
|
||
}
|
||
}
|
||
monkey_zombie_perk_init()
|
||
{
|
||
self.targeted = 0;
|
||
machine = undefined;
|
||
targets = getentarray( self.target, "targetname" );
|
||
for ( i = 0; i < targets.size; i++ )
|
||
{
|
||
if ( targets[i].classname == "script_model" )
|
||
{
|
||
machine = targets[i];
|
||
break;
|
||
}
|
||
}
|
||
assertex( isdefined( machine ), "no machine found for " + self.target );
|
||
if ( isdefined( machine ) )
|
||
{
|
||
machine.monkey_health = 100;
|
||
}
|
||
}
|
||
monkey_zombie_perk_damage( amount )
|
||
{
|
||
if ( !isdefined( self.perk ) )
|
||
{
|
||
return true;
|
||
}
|
||
machine = self.pack.machine;
|
||
machine.monkey_health -= amount;
|
||
if ( machine.monkey_health < 0 )
|
||
{
|
||
machine.monkey_health = 0;
|
||
}
|
||
return machine.monkey_health == 0;
|
||
}
|
||
monkey_pack_take_perk()
|
||
{
|
||
players = getplayers();
|
||
self.perk.targeted = 0;
|
||
perk = self.perk.script_noteworthy;
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
if ( players[i] HasPerk( perk ) )
|
||
{
|
||
perk_str = perk + "_stop";
|
||
players[i] notify( perk_str );
|
||
if ( flag( "solo_game" ) && perk == "specialty_quickrevive" )
|
||
{
|
||
players[i].lives--;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
monkey_perk_lost( perk )
|
||
{
|
||
if ( perk == "specialty_armorvest" )
|
||
{
|
||
if ( self.health > self.maxhealth )
|
||
{
|
||
self.health = self.maxhealth;
|
||
}
|
||
}
|
||
if ( isdefined( self.perk_hud ) )
|
||
{
|
||
keys = getarraykeys( self.perk_hud );
|
||
for ( i = 0; i < self.perk_hud.size; i++ )
|
||
{
|
||
self.perk_hud[ keys[i] ].x = i * 30;
|
||
}
|
||
}
|
||
}
|
||
monkey_perk_bought( perk )
|
||
{
|
||
flag_set( "perk_bought" );
|
||
level.perk_bought_func = undefined;
|
||
}
|
||
monkey_pack_flash_perk( perk )
|
||
{
|
||
if ( !isdefined( perk ) )
|
||
{
|
||
return;
|
||
}
|
||
players = getplayers();
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
players[i] maps\_zombiemode_perks::perk_hud_start_flash( perk );
|
||
}
|
||
}
|
||
monkey_pack_stop_flash( perk, taken )
|
||
{
|
||
players = getplayers();
|
||
for ( i = 0; i < players.size; i++ )
|
||
{
|
||
players[i] maps\_zombiemode_perks::perk_hud_stop_flash( perk, taken );
|
||
}
|
||
}
|
||
monkey_get_zone()
|
||
{
|
||
zone = undefined;
|
||
keys = getarraykeys( level.zones );
|
||
for ( i = 0; i < keys.size; i++ )
|
||
{
|
||
zone = level.zones[ keys[i] ];
|
||
for ( j = 0; j < zone.volumes.size; j++ )
|
||
{
|
||
if ( self isTouching( zone.volumes[j] ) )
|
||
{
|
||
return zone;
|
||
}
|
||
}
|
||
}
|
||
assertex( isdefined( zone ), "monkey is NOT in a zone" );
|
||
return zone;
|
||
}
|
||
monkey_fling( player )
|
||
{
|
||
monkey_print( "fling monkey damage" );
|
||
damage = int( level.monkey_zombie_health * 0.5 );
|
||
self DoDamage( damage, self.origin, self );
|
||
forward = VectorNormalize( AnglesToForward( self.angles ) );
|
||
attack_dir = VectorNormalize( self.origin - player.origin );
|
||
dot = VectorDot( attack_dir, forward );
|
||
if ( dot < 0 )
|
||
{
|
||
end_pos = self.origin - vector_scale( forward, 120 );
|
||
if ( sightTracePassed( self.origin, end_pos, false, self ) )
|
||
{
|
||
recordLine( self.origin, end_pos, (0,1,0), "Script", self );
|
||
roll_anim = [];
|
||
roll_anim[ roll_anim.size ] = %ai_zombie_monkey_thundergun_roll_01;
|
||
roll_anim[ roll_anim.size ] = %ai_zombie_monkey_thundergun_roll_02;
|
||
roll_anim[ roll_anim.size ] = %ai_zombie_monkey_thundergun_roll_03;
|
||
roll_anim[ roll_anim.size ] = %ai_zombie_monkey_thundergun_roll_04;
|
||
rollback_anim = roll_anim[ RandomInt( roll_anim.size ) ];
|
||
self animscripted( "rollback_anim", self.origin, self.angles, rollback_anim );
|
||
animscripts\traverse\zombie_shared::wait_anim_length( rollback_anim, .02 );
|
||
}
|
||
else
|
||
{
|
||
recordLine( self.origin, end_pos, (1,0,0), "Script", self );
|
||
}
|
||
}
|
||
self.thundergun_fling_func = undefined;
|
||
}
|
||
monkey_revive_solo_fx()
|
||
{
|
||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||
for ( i = 0; i < vending_triggers.size; i++ )
|
||
{
|
||
if ( vending_triggers[i].script_noteworthy == "specialty_quickrevive" )
|
||
{
|
||
vending_triggers[i] delete();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
monkey_print( str )
|
||
{
|
||
}
|
||
play_random_monkey_vox()
|
||
{
|
||
self endon( "death" );
|
||
while(1)
|
||
{
|
||
self thread maps\_zombiemode_audio::do_zombies_playvocals( "ambient", "monkey_zombie" );
|
||
wait(RandomFloatRange(1.25,3));
|
||
}
|
||
} |