mirror of
https://github.com/JezuzLizard/Recompilable-gscs-for-BO2-zombies-and-multiplayer.git
synced 2025-06-07 17:37:50 -05:00
3291 lines
86 KiB
Plaintext
3291 lines
86 KiB
Plaintext
#include maps/mp/zombies/_zm_ai_faller;
|
|
#include maps/mp/zombies/_zm_weapons;
|
|
#include maps/mp/zombies/_zm_spawner;
|
|
#include maps/mp/zombies/_zm;
|
|
#include maps/mp/zombies/_zm_pers_upgrades_functions;
|
|
#include maps/mp/zombies/_zm_stats;
|
|
#include maps/mp/zombies/_zm_pers_upgrades;
|
|
#include maps/mp/zombies/_zm_score;
|
|
#include maps/mp/zombies/_zm_powerups;
|
|
#include maps/mp/animscripts/zm_run;
|
|
#include maps/mp/animscripts/zm_death;
|
|
#include maps/mp/zombies/_zm_blockers;
|
|
#include maps/mp/zombies/_zm_audio;
|
|
#include maps/mp/animscripts/zm_shared;
|
|
#include maps/mp/animscripts/zm_utility;
|
|
#include maps/mp/zombies/_zm_ai_basic;
|
|
#include maps/mp/zombies/_zm_laststand;
|
|
#include maps/mp/zombies/_zm_net;
|
|
#include maps/mp/zombies/_zm_utility;
|
|
#include maps/mp/_utility;
|
|
#include common_scripts/utility;
|
|
|
|
init() //checked changed to match cerberus output
|
|
{
|
|
level._contextual_grab_lerp_time = 0.3;
|
|
level.zombie_spawners = getentarray( "zombie_spawner", "script_noteworthy" );
|
|
if ( is_true( level.use_multiple_spawns ) )
|
|
{
|
|
level.zombie_spawn = [];
|
|
for ( i = 0; i < level.zombie_spawners.size; i++ )
|
|
{
|
|
if ( isDefined( level.zombie_spawners[ i ].script_int ) )
|
|
{
|
|
int = level.zombie_spawners[ i ].script_int;
|
|
if ( !isDefined( level.zombie_spawn[ int ] ) )
|
|
{
|
|
level.zombie_spawn[ int ] = [];
|
|
}
|
|
level.zombie_spawn[ int ][ level.zombie_spawn[ int ].size ] = level.zombie_spawners[ i ];
|
|
}
|
|
}
|
|
}
|
|
precachemodel( "p6_anim_zm_barricade_board_01_upgrade" );
|
|
precachemodel( "p6_anim_zm_barricade_board_02_upgrade" );
|
|
precachemodel( "p6_anim_zm_barricade_board_03_upgrade" );
|
|
precachemodel( "p6_anim_zm_barricade_board_04_upgrade" );
|
|
precachemodel( "p6_anim_zm_barricade_board_05_upgrade" );
|
|
precachemodel( "p6_anim_zm_barricade_board_06_upgrade" );
|
|
if ( isDefined( level.ignore_spawner_func ) )
|
|
{
|
|
for ( i = 0; i < level.zombie_spawners.size; i++ )
|
|
{
|
|
ignore = [[ level.ignore_spawner_func ]]( level.zombie_spawners[ i ] );
|
|
if ( ignore )
|
|
{
|
|
arrayremovevalue( level.zombie_spawners, level.zombie_spawners[ i ] );
|
|
}
|
|
}
|
|
}
|
|
gametype = getDvar( "ui_gametype" );
|
|
if ( !isDefined( level.attack_player_thru_boards_range ) )
|
|
{
|
|
level.attack_player_thru_boards_range = 109.8;
|
|
}
|
|
if ( isDefined( level._game_module_custom_spawn_init_func ) )
|
|
{
|
|
[[ level._game_module_custom_spawn_init_func ]]();
|
|
}
|
|
registerclientfield( "actor", "zombie_has_eyes", 1, 1, "int" );
|
|
registerclientfield( "actor", "zombie_ragdoll_explode", 1, 1, "int" );
|
|
registerclientfield( "actor", "zombie_gut_explosion", 9000, 1, "int" );
|
|
}
|
|
|
|
add_cusom_zombie_spawn_logic( func ) //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( level._zombie_custom_spawn_logic ) )
|
|
{
|
|
level._zombie_custom_spawn_logic = [];
|
|
}
|
|
level._zombie_custom_spawn_logic[ level._zombie_custom_spawn_logic.size ] = func;
|
|
}
|
|
|
|
player_attacks_enemy( player, amount, type, point ) //checked matches cerberus output
|
|
{
|
|
team = undefined;
|
|
if ( isDefined( self._race_team ) )
|
|
{
|
|
team = self._race_team;
|
|
}
|
|
if ( !isads( player ) )
|
|
{
|
|
[[ level.global_damage_func ]]( type, self.damagelocation, point, player, amount, team );
|
|
return 0;
|
|
}
|
|
if ( !bullet_attack( type ) )
|
|
{
|
|
[[ level.global_damage_func ]]( type, self.damagelocation, point, player, amount, team );
|
|
return 0;
|
|
}
|
|
[[ level.global_damage_func_ads ]]( type, self.damagelocation, point, player, amount, team );
|
|
return 1;
|
|
}
|
|
|
|
player_attacker( attacker ) //checked matches cerberus output
|
|
{
|
|
if ( isplayer( attacker ) )
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
enemy_death_detection() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
for ( ;; )
|
|
{
|
|
self waittill( "damage", amount, attacker, direction_vec, point, type );
|
|
if ( !isDefined( amount ) )
|
|
{
|
|
continue;
|
|
}
|
|
if ( !isalive( self ) || self.delayeddeath )
|
|
{
|
|
return;
|
|
}
|
|
if ( !player_attacker( attacker ) )
|
|
{
|
|
continue;
|
|
}
|
|
self.has_been_damaged_by_player = 1;
|
|
self player_attacks_enemy( attacker, amount, type, point );
|
|
}
|
|
}
|
|
|
|
is_spawner_targeted_by_blocker( ent ) //checked changed to match cerberus output
|
|
{
|
|
if ( isDefined( ent.targetname ) )
|
|
{
|
|
targeters = getentarray( ent.targetname, "target" );
|
|
for ( i = 0; i < targeters.size; i++ )
|
|
{
|
|
if ( targeters[ i ].targetname == "zombie_door" || targeters[ i ].targetname == "zombie_debris" )
|
|
{
|
|
return 1;
|
|
}
|
|
result = is_spawner_targeted_by_blocker( targeters[ i ] );
|
|
if ( result )
|
|
{
|
|
return 1;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
add_custom_zombie_spawn_logic( func ) //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( level._zombie_custom_spawn_logic ) )
|
|
{
|
|
level._zombie_custom_spawn_logic = [];
|
|
}
|
|
level._zombie_custom_spawn_logic[ level._zombie_custom_spawn_logic.size ] = func;
|
|
}
|
|
|
|
zombie_spawn_init( animname_set ) //checked partially changed to match cerberus output
|
|
{
|
|
if ( !isDefined( animname_set ) )
|
|
{
|
|
animname_set = 0;
|
|
}
|
|
self.targetname = "zombie";
|
|
self.script_noteworthy = undefined;
|
|
recalc_zombie_array();
|
|
if ( !animname_set )
|
|
{
|
|
self.animname = "zombie";
|
|
}
|
|
if ( isDefined( get_gamemode_var( "pre_init_zombie_spawn_func" ) ) )
|
|
{
|
|
self [[ get_gamemode_var( "pre_init_zombie_spawn_func" ) ]]();
|
|
}
|
|
self thread play_ambient_zombie_vocals();
|
|
self.zmb_vocals_attack = "zmb_vocals_zombie_attack";
|
|
self.ignoreall = 1;
|
|
self.ignoreme = 1;
|
|
self.allowdeath = 1;
|
|
self.force_gib = 1;
|
|
self.is_zombie = 1;
|
|
self.has_legs = 1;
|
|
self allowedstances( "stand" );
|
|
self.zombie_damaged_by_bar_knockdown = 0;
|
|
self.gibbed = 0;
|
|
self.head_gibbed = 0;
|
|
self setphysparams( 15, 0, 72 );
|
|
self.disablearrivals = 1;
|
|
self.disableexits = 1;
|
|
self.grenadeawareness = 0;
|
|
self.badplaceawareness = 0;
|
|
self.ignoresuppression = 1;
|
|
self.suppressionthreshold = 1;
|
|
self.nododgemove = 1;
|
|
self.dontshootwhilemoving = 1;
|
|
self.pathenemylookahead = 0;
|
|
self.badplaceawareness = 0;
|
|
self.chatinitialized = 0;
|
|
self.a.disablepain = 1;
|
|
|
|
self disable_react();
|
|
if ( isDefined( level.zombie_health ) )
|
|
{
|
|
self.maxhealth = level.zombie_health;
|
|
if ( isDefined( level.zombie_respawned_health ) && level.zombie_respawned_health.size > 0 )
|
|
{
|
|
self.health = level.zombie_respawned_health[ 0 ];
|
|
arrayremovevalue( level.zombie_respawned_health, level.zombie_respawned_health[ 0 ] );
|
|
}
|
|
else
|
|
{
|
|
self.health = level.zombie_health;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.maxhealth = level.zombie_vars[ "zombie_health_start" ];
|
|
self.health = self.maxhealth;
|
|
}
|
|
self.freezegun_damage = 0;
|
|
self.dropweapon = 0;
|
|
level thread zombie_death_event( self );
|
|
self init_zombie_run_cycle();
|
|
self thread zombie_think();
|
|
self thread zombie_gib_on_damage();
|
|
self thread zombie_damage_failsafe();
|
|
self thread enemy_death_detection();
|
|
if ( isDefined( level._zombie_custom_spawn_logic ) )
|
|
{
|
|
if ( isarray( level._zombie_custom_spawn_logic ) )
|
|
{
|
|
for ( i = 0; i < level._zombie_custom_spawn_logic.size; i++ )
|
|
{
|
|
self thread [[ level._zombie_custom_spawn_logic[ i ] ]]();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self thread [[ level._zombie_custom_spawn_logic ]]();
|
|
}
|
|
}
|
|
if ( !is_true( self.no_eye_glow ) )
|
|
{
|
|
if ( !is_true( self.is_inert ) ) //imported from beta dump
|
|
{
|
|
self thread delayed_zombie_eye_glow();
|
|
}
|
|
}
|
|
self.deathfunction = ::zombie_death_animscript;
|
|
self.flame_damage_time = 0;
|
|
self.meleedamage = 60;
|
|
self.no_powerups = 1;
|
|
self zombie_history( "zombie_spawn_init -> Spawned = " + self.origin );
|
|
self.thundergun_knockdown_func = level.basic_zombie_thundergun_knockdown;
|
|
self.tesla_head_gib_func = ::zombie_tesla_head_gib;
|
|
self.team = level.zombie_team;
|
|
if ( isDefined( level.achievement_monitor_func ) )
|
|
{
|
|
self [[ level.achievement_monitor_func ]]();
|
|
}
|
|
if ( isDefined( get_gamemode_var( "post_init_zombie_spawn_func" ) ) )
|
|
{
|
|
self [[ get_gamemode_var( "post_init_zombie_spawn_func" ) ]]();
|
|
}
|
|
if ( isDefined( level.zombie_init_done ) )
|
|
{
|
|
self [[ level.zombie_init_done ]]();
|
|
}
|
|
self.zombie_init_done = 1;
|
|
self notify( "zombie_init_done" );
|
|
}
|
|
|
|
delayed_zombie_eye_glow() //checked changed to match cerberus output
|
|
{
|
|
self endon( "zombie_delete" );
|
|
if ( is_true( self.in_the_ground ) || is_true( self.in_the_ceiling ) )
|
|
{
|
|
while ( !isDefined( self.create_eyes ) )
|
|
{
|
|
wait 0.1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wait 0.5;
|
|
}
|
|
self zombie_eye_glow();
|
|
}
|
|
|
|
zombie_damage_failsafe() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
continue_failsafe_damage = 0;
|
|
while ( 1 )
|
|
{
|
|
wait 0.5;
|
|
if ( !isDefined( self.enemy ) || !isplayer( self.enemy ) )
|
|
{
|
|
continue;
|
|
}
|
|
if ( self istouching( self.enemy ) )
|
|
{
|
|
old_org = self.origin;
|
|
if ( !continue_failsafe_damage )
|
|
{
|
|
wait 5;
|
|
}
|
|
if ( !isDefined( self.enemy ) || !isplayer( self.enemy ) || self.enemy hasperk( "specialty_armorvest" ) )
|
|
{
|
|
continue;
|
|
}
|
|
if ( self istouching( self.enemy ) && !self.enemy maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isalive( self.enemy ) )
|
|
{
|
|
if ( distancesquared( old_org, self.origin ) < 3600 )
|
|
{
|
|
self.enemy dodamage( self.enemy.health + 1000, self.enemy.origin, self, self, "none", "MOD_RIFLE_BULLET" );
|
|
continue_failsafe_damage = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue_failsafe_damage = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
should_skip_teardown( find_flesh_struct_string ) //checked matches cerberus output
|
|
{
|
|
if ( isDefined( find_flesh_struct_string ) && find_flesh_struct_string == "find_flesh" )
|
|
{
|
|
return 1;
|
|
}
|
|
if ( isDefined( self.script_string ) && self.script_string == "zombie_chaser" )
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
zombie_think() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
/*
|
|
/#
|
|
assert( !self.isdog );
|
|
#/
|
|
*/
|
|
self.ai_state = "zombie_think";
|
|
find_flesh_struct_string = undefined;
|
|
if ( isDefined( level.zombie_custom_think_logic ) )
|
|
{
|
|
shouldwait = self [[ level.zombie_custom_think_logic ]]();
|
|
if ( shouldwait )
|
|
{
|
|
self waittill( "zombie_custom_think_done", find_flesh_struct_string );
|
|
}
|
|
}
|
|
else if ( is_true( self.start_inert ) )
|
|
{
|
|
find_flesh_struct_string = "find_flesh";
|
|
}
|
|
else
|
|
{
|
|
if ( isDefined( self.custom_location ) )
|
|
{
|
|
self thread [[ self.custom_location ]]();
|
|
}
|
|
else
|
|
{
|
|
self thread do_zombie_spawn();
|
|
}
|
|
self waittill( "risen", find_flesh_struct_string );
|
|
}
|
|
node = undefined;
|
|
desired_nodes = [];
|
|
self.entrance_nodes = [];
|
|
if ( isDefined( level.max_barrier_search_dist_override ) )
|
|
{
|
|
max_dist = level.max_barrier_search_dist_override;
|
|
}
|
|
else
|
|
{
|
|
max_dist = 500;
|
|
}
|
|
if ( !isDefined( find_flesh_struct_string ) && isDefined( self.target ) && self.target != "" )
|
|
{
|
|
desired_origin = get_desired_origin();
|
|
/*
|
|
/#
|
|
assert( isDefined( desired_origin ), "Spawner @ " + self.origin + " has a .target but did not find a target" );
|
|
#/
|
|
*/
|
|
origin = desired_origin;
|
|
node = getclosest( origin, level.exterior_goals );
|
|
self.entrance_nodes[ self.entrance_nodes.size ] = node;
|
|
self zombie_history( "zombie_think -> #1 entrance (script_forcegoal) origin = " + self.entrance_nodes[ 0 ].origin );
|
|
}
|
|
else if ( self should_skip_teardown( find_flesh_struct_string ) )
|
|
{
|
|
self zombie_setup_attack_properties();
|
|
if ( isDefined( self.target ) )
|
|
{
|
|
end_at_node = getnode( self.target, "targetname" );
|
|
if ( isDefined( end_at_node ) )
|
|
{
|
|
self setgoalnode( end_at_node );
|
|
self waittill( "goal" );
|
|
}
|
|
}
|
|
if ( is_true( self.start_inert ) )
|
|
{
|
|
self thread maps/mp/zombies/_zm_ai_basic::start_inert( 1 );
|
|
self zombie_complete_emerging_into_playable_area();
|
|
}
|
|
else
|
|
{
|
|
self thread maps/mp/zombies/_zm_ai_basic::find_flesh();
|
|
self thread zombie_entered_playable();
|
|
}
|
|
return;
|
|
}
|
|
else if ( isDefined( find_flesh_struct_string ) )
|
|
{
|
|
/*
|
|
/#
|
|
assert( isDefined( find_flesh_struct_string ) );
|
|
#/
|
|
*/
|
|
for ( i = 0; i < level.exterior_goals.size; i++ )
|
|
{
|
|
if ( isDefined( level.exterior_goals[ i ].script_string ) && level.exterior_goals[ i ].script_string == find_flesh_struct_string )
|
|
{
|
|
node = level.exterior_goals[ i ];
|
|
break;
|
|
}
|
|
}
|
|
self.entrance_nodes[ self.entrance_nodes.size ] = node;
|
|
self zombie_history( "zombie_think -> #1 entrance origin = " + node.origin );
|
|
self thread zombie_assure_node();
|
|
}
|
|
else
|
|
{
|
|
origin = self.origin;
|
|
desired_origin = get_desired_origin();
|
|
if ( isDefined( desired_origin ) )
|
|
{
|
|
origin = desired_origin;
|
|
}
|
|
nodes = get_array_of_closest( origin, level.exterior_goals, undefined, 3 );
|
|
desired_nodes[ 0 ] = nodes[ 0 ];
|
|
prev_dist = distance( self.origin, nodes[ 0 ].origin );
|
|
for ( i = 1; i < nodes.size; i++ )
|
|
{
|
|
dist = distance( self.origin, nodes[ i ].origin );
|
|
if ( ( dist - prev_dist ) > max_dist )
|
|
{
|
|
break;
|
|
}
|
|
prev_dist = dist;
|
|
desired_nodes[ i ] = nodes[ i ];
|
|
}
|
|
node = desired_nodes[ 0 ];
|
|
if ( desired_nodes.size > 1 )
|
|
{
|
|
node = desired_nodes[ randomint( desired_nodes.size ) ];
|
|
}
|
|
self.entrance_nodes = desired_nodes;
|
|
self zombie_history( "zombie_think -> #1 entrance origin = " + node.origin );
|
|
self thread zombie_assure_node();
|
|
}
|
|
/*
|
|
/#
|
|
assert( isDefined( node ), "Did not find a node!!! [Should not see this!]" );
|
|
#/
|
|
*/
|
|
level thread draw_line_ent_to_pos( self, node.origin, "goal" );
|
|
self.first_node = node;
|
|
self thread zombie_goto_entrance( node );
|
|
}
|
|
|
|
zombie_entered_playable() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
if ( !isDefined( level.playable_areas ) )
|
|
{
|
|
level.playable_areas = getentarray( "player_volume", "script_noteworthy" );
|
|
}
|
|
while ( 1 )
|
|
{
|
|
foreach ( area in level.playable_areas )
|
|
{
|
|
if ( self istouching( area ) )
|
|
{
|
|
wait 1.5;
|
|
self zombie_complete_emerging_into_playable_area();
|
|
return;
|
|
}
|
|
}
|
|
wait 1;
|
|
}
|
|
}
|
|
|
|
get_desired_origin() //checked matches cerberus output
|
|
{
|
|
if ( isDefined( self.target ) )
|
|
{
|
|
ent = getent( self.target, "targetname" );
|
|
if ( !isDefined( ent ) )
|
|
{
|
|
ent = getstruct( self.target, "targetname" );
|
|
}
|
|
if ( !isDefined( ent ) )
|
|
{
|
|
ent = getnode( self.target, "targetname" );
|
|
}
|
|
/*
|
|
/#
|
|
assert( isDefined( ent ), "Cannot find the targeted ent/node/struct, "" + self.target + "" at " + self.origin );
|
|
#/
|
|
*/
|
|
return ent.origin;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
zombie_goto_entrance( node, endon_bad_path ) //checked matches cerberus output
|
|
{
|
|
/*
|
|
/#
|
|
assert( !self.isdog );
|
|
#/
|
|
*/
|
|
self endon( "death" );
|
|
self endon( "stop_zombie_goto_entrance" );
|
|
level endon( "intermission" );
|
|
self.ai_state = "zombie_goto_entrance";
|
|
if ( is_true( endon_bad_path ) )
|
|
{
|
|
self endon( "bad_path" );
|
|
}
|
|
self zombie_history( "zombie_goto_entrance -> start goto entrance " + node.origin );
|
|
self.got_to_entrance = 0;
|
|
self.goalradius = 128;
|
|
self setgoalpos( node.origin );
|
|
self waittill( "goal" );
|
|
self.got_to_entrance = 1;
|
|
self zombie_history( "zombie_goto_entrance -> reached goto entrance " + node.origin );
|
|
self tear_into_building();
|
|
if ( isDefined( level.pre_aggro_pathfinding_func ) )
|
|
{
|
|
self [[ level.pre_aggro_pathfinding_func ]]();
|
|
}
|
|
barrier_pos = [];
|
|
barrier_pos[ 0 ] = "m";
|
|
barrier_pos[ 1 ] = "r";
|
|
barrier_pos[ 2 ] = "l";
|
|
self.barricade_enter = 1;
|
|
animstate = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "zm_barricade_enter" );
|
|
substate = "barrier_" + self.zombie_move_speed + "_" + barrier_pos[ self.attacking_spot_index ];
|
|
self animscripted( self.first_node.zbarrier.origin, self.first_node.zbarrier.angles, animstate, substate );
|
|
maps/mp/animscripts/zm_shared::donotetracks( "barricade_enter_anim" );
|
|
self zombie_setup_attack_properties();
|
|
self thread maps/mp/zombies/_zm_ai_basic::find_flesh();
|
|
self.pathenemyfightdist = 4;
|
|
self zombie_complete_emerging_into_playable_area();
|
|
self.pathenemyfightdist = 64;
|
|
self.barricade_enter = 0;
|
|
}
|
|
|
|
zombie_assure_node() //checked changed to match cerberus output //changed for loops to while loops to prevent infinite loops with continues
|
|
{
|
|
self endon( "death" );
|
|
self endon( "goal" );
|
|
level endon( "intermission" );
|
|
start_pos = self.origin;
|
|
if ( isDefined( self.entrance_nodes ) )
|
|
{
|
|
for ( i = 0; i < self.entrance_nodes.size; i++ )
|
|
{
|
|
if ( self zombie_bad_path() )
|
|
{
|
|
self zombie_history( "zombie_assure_node -> assigned assured node = " + self.entrance_nodes[ i ].origin );
|
|
/*
|
|
/#
|
|
println( "^1Zombie @ " + self.origin + " did not move for 1 second. Going to next closest node @ " + self.entrance_nodes[ i ].origin );
|
|
#/
|
|
*/
|
|
level thread draw_line_ent_to_pos( self, self.entrance_nodes[ i ].origin, "goal" );
|
|
self.first_node = self.entrance_nodes[ i ];
|
|
self setgoalpos( self.entrance_nodes[ i ].origin );
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
wait 2;
|
|
nodes = get_array_of_closest( self.origin, level.exterior_goals, undefined, 20 );
|
|
if ( isDefined( nodes ) )
|
|
{
|
|
self.entrance_nodes = nodes;
|
|
for ( i = 0; i < self.entrance_nodes.size; i++ )
|
|
{
|
|
if ( self zombie_bad_path() )
|
|
{
|
|
self zombie_history( "zombie_assure_node -> assigned assured node = " + self.entrance_nodes[ i ].origin );
|
|
/*
|
|
/#
|
|
println( "^1Zombie @ " + self.origin + " did not move for 1 second. Going to next closest node @ " + self.entrance_nodes[ i ].origin );
|
|
#/
|
|
*/
|
|
level thread draw_line_ent_to_pos( self, self.entrance_nodes[ i ].origin, "goal" );
|
|
self.first_node = self.entrance_nodes[ i ];
|
|
self setgoalpos( self.entrance_nodes[ i ].origin );
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
self zombie_history( "zombie_assure_node -> failed to find a good entrance point" );
|
|
wait 20;
|
|
self dodamage( self.health + 10, self.origin );
|
|
level.zombies_timeout_spawn++;
|
|
}
|
|
|
|
zombie_bad_path() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "goal" );
|
|
self thread zombie_bad_path_notify();
|
|
self thread zombie_bad_path_timeout();
|
|
self.zombie_bad_path = undefined;
|
|
while ( !isDefined( self.zombie_bad_path ) )
|
|
{
|
|
wait 0.05;
|
|
}
|
|
self notify( "stop_zombie_bad_path" );
|
|
return self.zombie_bad_path;
|
|
}
|
|
|
|
zombie_bad_path_notify() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "stop_zombie_bad_path" );
|
|
self waittill( "bad_path" );
|
|
self.zombie_bad_path = 1;
|
|
}
|
|
|
|
zombie_bad_path_timeout() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "stop_zombie_bad_path" );
|
|
wait 2;
|
|
self.zombie_bad_path = 0;
|
|
}
|
|
|
|
tear_into_building() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "teleporting" );
|
|
self zombie_history( "tear_into_building -> start" );
|
|
while ( 1 )
|
|
{
|
|
if ( isDefined( self.first_node.script_noteworthy ) )
|
|
{
|
|
if ( self.first_node.script_noteworthy == "no_blocker" )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if ( !isDefined( self.first_node.target ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( all_chunks_destroyed( self.first_node, self.first_node.barrier_chunks ) )
|
|
{
|
|
self zombie_history( "tear_into_building -> all chunks destroyed" );
|
|
}
|
|
if ( !get_attack_spot( self.first_node ) )
|
|
{
|
|
self zombie_history( "tear_into_building -> Could not find an attack spot" );
|
|
self thread do_a_taunt();
|
|
wait 0.5;
|
|
continue;
|
|
}
|
|
self.goalradius = 2;
|
|
if ( isDefined( level.tear_into_position ) )
|
|
{
|
|
self [[ level.tear_into_position ]]();
|
|
}
|
|
else
|
|
{
|
|
angles = self.first_node.zbarrier.angles;
|
|
self setgoalpos( self.attacking_spot, angles );
|
|
}
|
|
self waittill( "goal" );
|
|
if ( isDefined( level.tear_into_wait ) )
|
|
{
|
|
self [[ level.tear_into_wait ]]();
|
|
}
|
|
else
|
|
{
|
|
self waittill_notify_or_timeout( "orientdone", 1 );
|
|
}
|
|
self zombie_history( "tear_into_building -> Reach position and orientated" );
|
|
if ( all_chunks_destroyed( self.first_node, self.first_node.barrier_chunks ) )
|
|
{
|
|
self zombie_history( "tear_into_building -> all chunks destroyed" );
|
|
for ( i = 0; i < self.first_node.attack_spots_taken.size; i++ )
|
|
{
|
|
self.first_node.attack_spots_taken[ i ] = 0;
|
|
}
|
|
return;
|
|
}
|
|
while ( 1 )
|
|
{
|
|
if ( isDefined( self.zombie_board_tear_down_callback ) )
|
|
{
|
|
self [[ self.zombie_board_tear_down_callback ]]();
|
|
}
|
|
chunk = get_closest_non_destroyed_chunk( self.origin, self.first_node, self.first_node.barrier_chunks );
|
|
if ( !isDefined( chunk ) )
|
|
{
|
|
if ( !all_chunks_destroyed( self.first_node, self.first_node.barrier_chunks ) )
|
|
{
|
|
attack = self should_attack_player_thru_boards();
|
|
if ( !is_true( attack ) && self.has_legs )
|
|
{
|
|
self do_a_taunt();
|
|
}
|
|
else
|
|
{
|
|
wait 0.1;
|
|
}
|
|
continue;
|
|
}
|
|
for ( i = 0; i < self.first_node.attack_spots_taken.size; i++ )
|
|
{
|
|
self.first_node.attack_spots_taken[ i ] = 0;
|
|
}
|
|
return;
|
|
}
|
|
self zombie_history( "tear_into_building -> animating" );
|
|
self.first_node.zbarrier setzbarrierpiecestate( chunk, "targetted_by_zombie" );
|
|
self.first_node thread check_zbarrier_piece_for_zombie_inert( chunk, self.first_node.zbarrier, self );
|
|
self.first_node thread check_zbarrier_piece_for_zombie_death( chunk, self.first_node.zbarrier, self );
|
|
self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "teardown", self.animname );
|
|
if ( isDefined( level.zbarrier_override_tear_in ) )
|
|
{
|
|
animstatebase = self [[ level.zbarrier_override_tear_in ]]( chunk );
|
|
}
|
|
else
|
|
{
|
|
animstatebase = self.first_node.zbarrier getzbarrierpieceanimstate( chunk );
|
|
}
|
|
animsubstate = "spot_" + self.attacking_spot_index + "_piece_" + self.first_node.zbarrier getzbarrierpieceanimsubstate( chunk );
|
|
anim_sub_index = self getanimsubstatefromasd( animstatebase + "_in", animsubstate );
|
|
self animscripted( self.first_node.zbarrier.origin, self.first_node.zbarrier.angles, maps/mp/animscripts/zm_utility::append_missing_legs_suffix( animstatebase + "_in" ), anim_sub_index );
|
|
self zombie_tear_notetracks( "tear_anim", chunk, self.first_node );
|
|
while ( self.first_node.zbarrier.chunk_health[ chunk ] > 0 )
|
|
{
|
|
self animscripted( self.first_node.zbarrier.origin, self.first_node.zbarrier.angles, maps/mp/animscripts/zm_utility::append_missing_legs_suffix( animstatebase + "_loop" ), anim_sub_index );
|
|
self zombie_tear_notetracks( "tear_anim", chunk, self.first_node );
|
|
self.first_node.zbarrier.chunk_health[ chunk ]--;
|
|
|
|
}
|
|
self animscripted( self.first_node.zbarrier.origin, self.first_node.zbarrier.angles, maps/mp/animscripts/zm_utility::append_missing_legs_suffix( animstatebase + "_out" ), anim_sub_index );
|
|
self zombie_tear_notetracks( "tear_anim", chunk, self.first_node );
|
|
self.lastchunk_destroy_time = getTime();
|
|
attack = self should_attack_player_thru_boards();
|
|
if ( !is_true( attack ) && self.has_legs )
|
|
{
|
|
self do_a_taunt();
|
|
}
|
|
if ( all_chunks_destroyed( self.first_node, self.first_node.barrier_chunks ) )
|
|
{
|
|
for ( i = 0; i < self.first_node.attack_spots_taken.size; i++ )
|
|
{
|
|
self.first_node.attack_spots_taken[ i ] = 0;
|
|
}
|
|
level notify( "last_board_torn", self.first_node.zbarrier.origin );
|
|
return;
|
|
}
|
|
}
|
|
self reset_attack_spot();
|
|
}
|
|
}
|
|
|
|
do_a_taunt() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
if ( !self.has_legs )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( !self.first_node.zbarrier zbarriersupportszombietaunts() )
|
|
{
|
|
return;
|
|
}
|
|
self.old_origin = self.origin;
|
|
if ( getDvar( "zombie_taunt_freq" ) == "" )
|
|
{
|
|
setdvar( "zombie_taunt_freq", "5" );
|
|
}
|
|
freq = getDvarInt( "zombie_taunt_freq" );
|
|
if ( freq >= randomint( 100 ) )
|
|
{
|
|
self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "taunt", self.animname );
|
|
tauntstate = "zm_taunt";
|
|
if ( isDefined( self.first_node.zbarrier ) && self.first_node.zbarrier getzbarriertauntanimstate() != "" )
|
|
{
|
|
tauntstate = self.first_node.zbarrier getzbarriertauntanimstate();
|
|
}
|
|
self animscripted( self.origin, self.angles, tauntstate );
|
|
self taunt_notetracks( "taunt_anim" );
|
|
}
|
|
}
|
|
|
|
taunt_notetracks( msg ) //see info.md No 8.
|
|
{
|
|
self endon( "death" );
|
|
while ( 1 )
|
|
{
|
|
self waittill( "taunt_anim", notetrack );
|
|
if ( notetrack == "end" )
|
|
{
|
|
self forceteleport( self.old_origin );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
should_attack_player_thru_boards() //checked changed to match cerberus output
|
|
{
|
|
if ( !self.has_legs )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( isDefined( self.first_node.zbarrier ) )
|
|
{
|
|
if ( !self.first_node.zbarrier zbarriersupportszombiereachthroughattacks() )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
if ( getDvar( "zombie_reachin_freq" ) == "" )
|
|
{
|
|
setdvar( "zombie_reachin_freq", "50" );
|
|
}
|
|
freq = getDvarInt( "zombie_reachin_freq" );
|
|
players = get_players();
|
|
attack = 0;
|
|
self.player_targets = [];
|
|
for ( i = 0; i < players.size; i++ )
|
|
{
|
|
if ( isalive( players[ i ] ) && !isDefined( players[ i ].revivetrigger ) && distance2d( self.origin, players[ i ].origin ) <= level.attack_player_thru_boards_range && !is_true( players[ i ].zombie_vars[ "zombie_powerup_zombie_blood_on" ] ) )
|
|
{
|
|
self.player_targets[ self.player_targets.size ] = players[ i ];
|
|
attack = 1;
|
|
}
|
|
}
|
|
if ( !attack || freq < randomint( 100 ) )
|
|
{
|
|
return 0;
|
|
}
|
|
self.old_origin = self.origin;
|
|
attackanimstate = "zm_window_melee";
|
|
if ( isDefined( self.first_node.zbarrier ) && self.first_node.zbarrier getzbarrierreachthroughattackanimstate() != "" )
|
|
{
|
|
attackanimstate = self.first_node.zbarrier getzbarrierreachthroughattackanimstate();
|
|
}
|
|
self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", self.animname );
|
|
self animscripted( self.origin, self.angles, attackanimstate, self.attacking_spot_index - 1 );
|
|
self window_notetracks( "window_melee_anim" );
|
|
return 1;
|
|
}
|
|
|
|
window_notetracks( msg ) //see info.md No 8.
|
|
{
|
|
self endon( "death" );
|
|
while ( 1 )
|
|
{
|
|
self waittill( "window_melee_anim", notetrack );
|
|
if ( notetrack == "end" )
|
|
{
|
|
self teleport( self.old_origin );
|
|
return;
|
|
}
|
|
if ( notetrack == "fire" )
|
|
{
|
|
if ( self.ignoreall )
|
|
{
|
|
self.ignoreall = 0;
|
|
}
|
|
if ( isDefined( self.first_node ) )
|
|
{
|
|
_melee_dist_sq = 8100;
|
|
if ( isDefined( level.attack_player_thru_boards_range ) )
|
|
{
|
|
_melee_dist_sq = level.attack_player_thru_boards_range * level.attack_player_thru_boards_range;
|
|
}
|
|
_trigger_dist_sq = 2601;
|
|
for ( i = 0; i < self.player_targets.size; i++ )
|
|
{
|
|
playerdistsq = distance2dsquared( self.player_targets[ i ].origin, self.origin );
|
|
heightdiff = abs( self.player_targets[ i ].origin[ 2 ] - self.origin[ 2 ] );
|
|
if ( playerdistsq < _melee_dist_sq && ( heightdiff * heightdiff ) < _melee_dist_sq )
|
|
{
|
|
triggerdistsq = distance2dsquared( self.player_targets[ i ].origin, self.first_node.trigger_location.origin );
|
|
heightdiff = abs( self.player_targets[ i ].origin[ 2 ] - self.first_node.trigger_location.origin[ 2 ] );
|
|
if ( triggerdistsq < _trigger_dist_sq && ( heightdiff * heightdiff ) < _trigger_dist_sq )
|
|
{
|
|
self.player_targets[ i ] dodamage( self.meleedamage, self.origin, self, self, "none", "MOD_MELEE" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self melee();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
reset_attack_spot() //checked matches cerberus output
|
|
{
|
|
if ( isDefined( self.attacking_node ) )
|
|
{
|
|
node = self.attacking_node;
|
|
index = self.attacking_spot_index;
|
|
node.attack_spots_taken[ index ] = 0;
|
|
self.attacking_node = undefined;
|
|
self.attacking_spot_index = undefined;
|
|
}
|
|
}
|
|
|
|
get_attack_spot( node ) //checked matches cerberus output
|
|
{
|
|
index = get_attack_spot_index( node );
|
|
if ( !isDefined( index ) )
|
|
{
|
|
return 0;
|
|
}
|
|
self.attacking_node = node;
|
|
self.attacking_spot_index = index;
|
|
node.attack_spots_taken[ index ] = 1;
|
|
self.attacking_spot = node.attack_spots[ index ];
|
|
return 1;
|
|
}
|
|
|
|
get_attack_spot_index( node ) //checked changed to match cerberus output
|
|
{
|
|
indexes = [];
|
|
for ( i = 0; i < node.attack_spots.size; i++ )
|
|
{
|
|
if ( !node.attack_spots_taken[ i ] )
|
|
{
|
|
indexes[ indexes.size ] = i;
|
|
}
|
|
}
|
|
if ( indexes.size == 0 )
|
|
{
|
|
return undefined;
|
|
}
|
|
return indexes[ randomint( indexes.size ) ];
|
|
}
|
|
|
|
zombie_tear_notetracks( msg, chunk, node ) //checked again see info.md No 8.
|
|
{
|
|
self endon( "death" );
|
|
while ( 1 )
|
|
{
|
|
self waittill( "tear_anim", notetrack ); //fix for the compiler
|
|
if ( notetrack == "end" )
|
|
{
|
|
return;
|
|
}
|
|
if ( notetrack == "board" || notetrack == "destroy_piece" || notetrack == "bar" )
|
|
{
|
|
if ( isDefined( level.zbarrier_zombie_tear_notetrack_override ) )
|
|
{
|
|
self thread [[ level.zbarrier_zombie_tear_notetrack_override ]]( node, chunk );
|
|
}
|
|
node.zbarrier setzbarrierpiecestate( chunk, "opening" );
|
|
}
|
|
}
|
|
}
|
|
|
|
zombie_boardtear_offset_fx_horizontle( chunk, node ) //checked changed to match cerberus output
|
|
{
|
|
if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "repair_board" || isDefined( chunk.script_parameters ) && chunk.script_parameters == "board" )
|
|
{
|
|
if ( isDefined( chunk.unbroken ) && chunk.unbroken == 1 )
|
|
{
|
|
if ( isDefined( chunk.material ) && chunk.material == "glass" )
|
|
{
|
|
playfx( level._effect[ "glass_break" ], chunk.origin, node.angles );
|
|
chunk.unbroken = 0;
|
|
}
|
|
else if ( isDefined( chunk.material ) && chunk.material == "metal" )
|
|
{
|
|
playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin );
|
|
chunk.unbroken = 0;
|
|
}
|
|
else if ( isDefined( chunk.material ) && chunk.material == "rock" )
|
|
{
|
|
if ( is_true( level.use_clientside_rock_tearin_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_rock_fx );
|
|
}
|
|
else
|
|
{
|
|
playfx( level._effect[ "wall_break" ], chunk.origin );
|
|
}
|
|
chunk.unbroken = 0;
|
|
}
|
|
}
|
|
}
|
|
if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "barricade_vents" )
|
|
{
|
|
if ( is_true( level.use_clientside_board_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_board_horizontal_fx );
|
|
}
|
|
else
|
|
{
|
|
playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin );
|
|
}
|
|
}
|
|
else if ( isDefined( chunk.material ) && chunk.material == "rock" )
|
|
{
|
|
if ( is_true( level.use_clientside_rock_tearin_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_rock_fx );
|
|
}
|
|
}
|
|
else if ( isDefined( level.use_clientside_board_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_board_horizontal_fx );
|
|
}
|
|
else
|
|
{
|
|
playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( 0, 0, 1 ), 30 ) );
|
|
wait randomfloatrange( 0.2, 0.4 );
|
|
playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( 0, 0, -1 ), 30 ) );
|
|
}
|
|
}
|
|
|
|
zombie_boardtear_offset_fx_verticle( chunk, node ) //checked changed to match cerberus output
|
|
{
|
|
if ( ( chunk.script_parameters == "repair_board" || chunk.script_parameters == "board" ) && isDefined( chunk.script_parameters ) )
|
|
{
|
|
if ( isDefined( chunk.unbroken ) && chunk.unbroken == 1 )
|
|
{
|
|
if ( isDefined( chunk.material ) && chunk.material == "glass" )
|
|
{
|
|
playfx( level._effect[ "glass_break" ], chunk.origin, node.angles );
|
|
chunk.unbroken = 0;
|
|
}
|
|
else if ( isDefined( chunk.material ) && chunk.material == "metal" )
|
|
{
|
|
playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin );
|
|
chunk.unbroken = 0;
|
|
}
|
|
else if ( isDefined( chunk.material ) && chunk.material == "rock" )
|
|
{
|
|
if ( is_true( level.use_clientside_rock_tearin_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_rock_fx );
|
|
}
|
|
else
|
|
{
|
|
playfx( level._effect[ "wall_break" ], chunk.origin );
|
|
}
|
|
chunk.unbroken = 0;
|
|
}
|
|
}
|
|
}
|
|
if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "barricade_vents" )
|
|
{
|
|
if ( isDefined( level.use_clientside_board_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_board_vertical_fx );
|
|
}
|
|
else
|
|
{
|
|
playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin );
|
|
}
|
|
}
|
|
else if ( isDefined( chunk.material ) && chunk.material == "rock" )
|
|
{
|
|
if ( is_true( level.use_clientside_rock_tearin_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_rock_fx );
|
|
}
|
|
return;
|
|
}
|
|
else if ( isDefined( level.use_clientside_board_fx ) )
|
|
{
|
|
chunk setclientflag( level._zombie_scriptmover_flag_board_vertical_fx );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( 1, 0, 0 ), 30 ) );
|
|
wait randomfloatrange( 0.2, 0.4 );
|
|
playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) );
|
|
}
|
|
}
|
|
|
|
zombie_bartear_offset_fx_verticle( chunk ) //checked changed to match cerberus output
|
|
{
|
|
if ( ( chunk.script_parameters == "bar" || chunk.script_noteworthy == "board" ) && isDefined( chunk.script_parameters ) )
|
|
{
|
|
possible_tag_array_1 = [];
|
|
possible_tag_array_1[ 0 ] = "Tag_fx_top";
|
|
possible_tag_array_1[ 1 ] = "";
|
|
possible_tag_array_1[ 2 ] = "Tag_fx_top";
|
|
possible_tag_array_1[ 3 ] = "";
|
|
possible_tag_array_2 = [];
|
|
possible_tag_array_2[ 0 ] = "";
|
|
possible_tag_array_2[ 1 ] = "Tag_fx_bottom";
|
|
possible_tag_array_2[ 2 ] = "";
|
|
possible_tag_array_2[ 3 ] = "Tag_fx_bottom";
|
|
possible_tag_array_2 = array_randomize( possible_tag_array_2 );
|
|
random_fx = [];
|
|
random_fx[ 0 ] = level._effect[ "fx_zombie_bar_break" ];
|
|
random_fx[ 1 ] = level._effect[ "fx_zombie_bar_break_lite" ];
|
|
random_fx[ 2 ] = level._effect[ "fx_zombie_bar_break" ];
|
|
random_fx[ 3 ] = level._effect[ "fx_zombie_bar_break_lite" ];
|
|
random_fx = array_randomize( random_fx );
|
|
switch( randomint( 9 ) )
|
|
{
|
|
case 0:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
case 1:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_top" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
case 2:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
case 3:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_top" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
case 4:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
case 5:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" );
|
|
break;
|
|
case 6:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
case 7:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_top" );
|
|
break;
|
|
case 8:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_bottom" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
zombie_bartear_offset_fx_horizontle( chunk ) //checked changed to match cerberus output
|
|
{
|
|
if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "bar" || chunk.script_noteworthy == "board" )
|
|
{
|
|
switch( randomint( 10 ) )
|
|
{
|
|
case 0:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 1:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_left" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 2:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 3:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_left" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 4:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" );
|
|
wait randomfloatrange( 0, 0.3 );
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 5:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" );
|
|
break;
|
|
case 6:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 7:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
case 8:
|
|
playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
check_zbarrier_piece_for_zombie_inert( chunk_index, zbarrier, zombie ) //checked matches cerberus output
|
|
{
|
|
zombie endon( "completed_emerging_into_playable_area" );
|
|
zombie waittill( "stop_zombie_goto_entrance" );
|
|
if ( zbarrier getzbarrierpiecestate( chunk_index ) == "targetted_by_zombie" )
|
|
{
|
|
zbarrier setzbarrierpiecestate( chunk_index, "closed" );
|
|
}
|
|
}
|
|
|
|
check_zbarrier_piece_for_zombie_death( chunk_index, zbarrier, zombie ) //checked matches cerberus output
|
|
{
|
|
while ( 1 )
|
|
{
|
|
if ( zbarrier getzbarrierpiecestate( chunk_index ) != "targetted_by_zombie" )
|
|
{
|
|
return;
|
|
}
|
|
if ( !isDefined( zombie ) || !isalive( zombie ) )
|
|
{
|
|
zbarrier setzbarrierpiecestate( chunk_index, "closed" );
|
|
return;
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
check_for_zombie_death( zombie ) //checked matches cerberus output
|
|
{
|
|
self endon( "destroyed" );
|
|
wait 2.5;
|
|
self maps/mp/zombies/_zm_blockers::update_states( "repaired" );
|
|
}
|
|
|
|
zombie_hat_gib( attacker, means_of_death ) //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
if ( !is_mature() )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( is_true( self.hat_gibbed ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !isDefined( self.gibspawn5 ) || !isDefined( self.gibspawntag5 ) )
|
|
{
|
|
return;
|
|
}
|
|
self.hat_gibbed = 1;
|
|
if ( isDefined( self.hatmodel ) )
|
|
{
|
|
self detach( self.hatmodel, "" );
|
|
}
|
|
temp_array = [];
|
|
temp_array[ 0 ] = level._zombie_gib_piece_index_hat;
|
|
self gib( "normal", temp_array );
|
|
if ( isDefined( level.track_gibs ) )
|
|
{
|
|
level [[ level.track_gibs ]]( self, temp_array );
|
|
}
|
|
}
|
|
|
|
zombie_head_gib( attacker, means_of_death ) //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
if ( !is_mature() )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( is_true( self.head_gibbed ) )
|
|
{
|
|
return;
|
|
}
|
|
self.head_gibbed = 1;
|
|
self zombie_eye_glow_stop();
|
|
size = self getattachsize();
|
|
for ( i = 0; i < size; i++ )
|
|
{
|
|
model = self getattachmodelname( i );
|
|
if ( issubstr( model, "head" ) )
|
|
{
|
|
if ( isDefined( self.hatmodel ) )
|
|
{
|
|
self detach( self.hatmodel, "" );
|
|
}
|
|
self detach( model, "" );
|
|
if ( isDefined( self.torsodmg5 ) )
|
|
{
|
|
self attach( self.torsodmg5, "", 1 );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
temp_array = [];
|
|
temp_array[ 0 ] = level._zombie_gib_piece_index_head;
|
|
if ( !is_true( self.hat_gibbed ) && isDefined( self.gibspawn5 ) && isDefined( self.gibspawntag5 ) )
|
|
{
|
|
temp_array[ 1 ] = level._zombie_gib_piece_index_hat;
|
|
}
|
|
self.hat_gibbed = 1;
|
|
self gib( "normal", temp_array );
|
|
if ( isDefined( level.track_gibs ) )
|
|
{
|
|
level [[ level.track_gibs ]]( self, temp_array );
|
|
}
|
|
self thread damage_over_time( ceil( self.health * 0.2 ), 1, attacker, means_of_death );
|
|
}
|
|
|
|
damage_over_time( dmg, delay, attacker, means_of_death ) //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "exploding" );
|
|
if ( !isalive( self ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !isplayer( attacker ) )
|
|
{
|
|
attacker = self;
|
|
}
|
|
if ( !isDefined( means_of_death ) )
|
|
{
|
|
means_of_death = "MOD_UNKNOWN";
|
|
}
|
|
while ( 1 )
|
|
{
|
|
if ( isDefined( delay ) )
|
|
{
|
|
wait delay;
|
|
}
|
|
if ( isDefined( self ) )
|
|
{
|
|
self dodamage( dmg, self gettagorigin( "j_neck" ), attacker, self, self.damagelocation, means_of_death, 0, self.damageweapon );
|
|
}
|
|
}
|
|
}
|
|
|
|
head_should_gib( attacker, type, point ) //checked changed to match cerberus output
|
|
{
|
|
if ( !is_mature() )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( self.head_gibbed )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( !isDefined( attacker ) || !isplayer( attacker ) )
|
|
{
|
|
return 0;
|
|
}
|
|
weapon = attacker getcurrentweapon();
|
|
if ( type != "MOD_RIFLE_BULLET" && type != "MOD_PISTOL_BULLET" )
|
|
{
|
|
if ( type == "MOD_GRENADE" || type == "MOD_GRENADE_SPLASH" )
|
|
{
|
|
if ( distance( point, self gettagorigin( "j_head" ) ) > 55 )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
else if ( type == "MOD_PROJECTILE" )
|
|
{
|
|
if ( distance( point, self gettagorigin( "j_head" ) ) > 10 )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
else if ( weaponclass( weapon ) != "spread" )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
if ( !self maps/mp/animscripts/zm_utility::damagelocationisany( "head", "helmet", "neck" ) )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( weapon == "none" || weapon == level.start_weapon || weaponisgasweapon( self.weapon ) )
|
|
{
|
|
return 0;
|
|
}
|
|
low_health_percent = ( self.health / self.maxhealth ) * 100;
|
|
if ( low_health_percent > 10 )
|
|
{
|
|
self zombie_hat_gib( attacker, type );
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
headshot_blood_fx() //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( self ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !is_mature() )
|
|
{
|
|
return;
|
|
}
|
|
fxtag = "j_neck";
|
|
fxorigin = self gettagorigin( fxtag );
|
|
upvec = anglesToUp( self gettagangles( fxtag ) );
|
|
forwardvec = anglesToForward( self gettagangles( fxtag ) );
|
|
playfx( level._effect[ "headshot" ], fxorigin, forwardvec, upvec );
|
|
playfx( level._effect[ "headshot_nochunks" ], fxorigin, forwardvec, upvec );
|
|
wait 0.3;
|
|
if ( isDefined( self ) )
|
|
{
|
|
playfxontag( level._effect[ "bloodspurt" ], self, fxtag );
|
|
}
|
|
}
|
|
|
|
zombie_gib_on_damage() //checked changed to match cerberus output
|
|
{
|
|
|
|
while ( 1 )
|
|
{
|
|
self waittill( "damage", amount, attacker, direction_vec, point, type, tagname, modelname, partname, weaponname );
|
|
if ( !isDefined( self ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !self zombie_should_gib( amount, attacker, type ) )
|
|
{
|
|
continue;
|
|
}
|
|
if ( self head_should_gib( attacker, type, point ) && type != "MOD_BURNED" )
|
|
{
|
|
self zombie_head_gib( attacker, type );
|
|
continue; //added from cerberus output
|
|
}
|
|
if ( !self.gibbed )
|
|
{
|
|
if ( self maps/mp/animscripts/zm_utility::damagelocationisany( "head", "helmet", "neck" ) )
|
|
{
|
|
continue;
|
|
}
|
|
refs = [];
|
|
switch( self.damagelocation )
|
|
{
|
|
case "torso_lower":
|
|
case "torso_upper":
|
|
refs[ refs.size ] = "guts";
|
|
refs[ refs.size ] = "right_arm";
|
|
break;
|
|
case "right_arm_lower":
|
|
case "right_arm_upper":
|
|
case "right_hand":
|
|
refs[ refs.size ] = "right_arm";
|
|
break;
|
|
case "left_arm_lower":
|
|
case "left_arm_upper":
|
|
case "left_hand":
|
|
refs[ refs.size ] = "left_arm";
|
|
break;
|
|
case "right_foot":
|
|
case "right_leg_lower":
|
|
case "right_leg_upper":
|
|
if ( self.health <= 0 )
|
|
{
|
|
refs[ refs.size ] = "right_leg";
|
|
refs[ refs.size ] = "right_leg";
|
|
refs[ refs.size ] = "right_leg";
|
|
refs[ refs.size ] = "no_legs";
|
|
}
|
|
break;
|
|
case "left_foot":
|
|
case "left_leg_lower":
|
|
case "left_leg_upper":
|
|
if ( self.health <= 0 )
|
|
{
|
|
refs[ refs.size ] = "left_leg";
|
|
refs[ refs.size ] = "left_leg";
|
|
refs[ refs.size ] = "left_leg";
|
|
refs[ refs.size ] = "no_legs";
|
|
}
|
|
break;
|
|
default:
|
|
if ( self.damagelocation == "none" )
|
|
{
|
|
if ( type != "MOD_GRENADE" && type != "MOD_GRENADE_SPLASH" || type == "MOD_PROJECTILE" && type == "MOD_PROJECTILE_SPLASH" )
|
|
{
|
|
refs = self derive_damage_refs( point );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( isDefined( level.custom_derive_damage_refs ) )
|
|
{
|
|
refs = self [[ level.custom_derive_damage_refs ]]( refs, point, weaponname );
|
|
}
|
|
if ( refs.size )
|
|
{
|
|
self.a.gib_ref = maps/mp/animscripts/zm_death::get_random( refs );
|
|
if ( self.a.gib_ref == "no_legs" && self.health > 0 || self.a.gib_ref == "right_leg" && self.health > 0 || self.a.gib_ref == "left_leg" && self.health > 0 )
|
|
{
|
|
self.has_legs = 0;
|
|
self allowedstances( "crouch" );
|
|
self setphysparams( 15, 0, 24 );
|
|
self allowpitchangle( 1 );
|
|
self setpitchorient();
|
|
health = self.health;
|
|
health *= 0.1;
|
|
self thread maps/mp/animscripts/zm_run::needsdelayedupdate();
|
|
if ( isDefined( self.crawl_anim_override ) )
|
|
{
|
|
self [[ self.crawl_anim_override ]]();
|
|
}
|
|
}
|
|
}
|
|
if ( self.health > 0 )
|
|
{
|
|
self thread maps/mp/animscripts/zm_death::do_gib();
|
|
if ( isDefined( level.gib_on_damage ) )
|
|
{
|
|
self thread [[ level.gib_on_damage ]]();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
zombie_should_gib( amount, attacker, type ) //checked changed to match cerberus output
|
|
{
|
|
if ( !is_mature() )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( !isDefined( type ) )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( is_true( self.is_on_fire ) )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( isDefined( self.no_gib ) && self.no_gib == 1 )
|
|
{
|
|
return 0;
|
|
}
|
|
switch( type )
|
|
{
|
|
case "MOD_BURNED":
|
|
case "MOD_CRUSH":
|
|
case "MOD_FALLING":
|
|
case "MOD_SUICIDE":
|
|
case "MOD_TELEFRAG":
|
|
case "MOD_TRIGGER_HURT":
|
|
case "MOD_UNKNOWN":
|
|
return 0;
|
|
case "MOD_MELEE":
|
|
return 0;
|
|
}
|
|
if ( type == "MOD_PISTOL_BULLET" || type == "MOD_RIFLE_BULLET" )
|
|
{
|
|
if ( !isDefined( attacker ) || !isplayer( attacker ) )
|
|
{
|
|
return 0;
|
|
}
|
|
weapon = attacker getcurrentweapon();
|
|
if ( weapon == "none" || weapon == level.start_weapon )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( weaponisgasweapon( self.weapon ) )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else if ( type == "MOD_PROJECTILE" )
|
|
{
|
|
if ( isDefined( attacker ) && isplayer( attacker ) )
|
|
{
|
|
weapon = attacker getcurrentweapon();
|
|
if ( weapon == "slipgun_zm" || weapon == "slipgun_upgraded_zm" )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
prev_health = amount + self.health;
|
|
if ( prev_health <= 0 )
|
|
{
|
|
prev_health = 1;
|
|
}
|
|
damage_percent = ( amount / prev_health ) * 100;
|
|
if ( damage_percent < 10 )
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
derive_damage_refs( point ) //checked changed to match cerberus output
|
|
{
|
|
if ( !isDefined( level.gib_tags ) )
|
|
{
|
|
init_gib_tags();
|
|
}
|
|
closesttag = undefined;
|
|
i = 0;
|
|
while ( i < level.gib_tags.size )
|
|
{
|
|
if ( !isDefined( closesttag ) )
|
|
{
|
|
closesttag = level.gib_tags[ i ];
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( distancesquared( point, self gettagorigin( level.gib_tags[ i ] ) ) < distancesquared( point, self gettagorigin( closesttag ) ) )
|
|
{
|
|
closesttag = level.gib_tags[ i ];
|
|
}
|
|
i++;
|
|
}
|
|
refs = [];
|
|
if ( closesttag != "J_SpineLower" || closesttag == "J_SpineUpper" || closesttag == "J_Spine4" )
|
|
{
|
|
refs[ refs.size ] = "guts";
|
|
refs[ refs.size ] = "right_arm";
|
|
}
|
|
else if ( closesttag != "J_Shoulder_LE" || closesttag == "J_Elbow_LE" && closesttag == "J_Wrist_LE" )
|
|
{
|
|
refs[ refs.size ] = "left_arm";
|
|
}
|
|
else if ( closesttag != "J_Shoulder_RI" || closesttag == "J_Elbow_RI" && closesttag == "J_Wrist_RI" )
|
|
{
|
|
refs[ refs.size ] = "right_arm";
|
|
}
|
|
else if ( closesttag != "J_Hip_LE" || closesttag == "J_Knee_LE" && closesttag == "J_Ankle_LE" )
|
|
{
|
|
refs[ refs.size ] = "left_leg";
|
|
refs[ refs.size ] = "no_legs";
|
|
}
|
|
else if ( closesttag != "J_Hip_RI" || closesttag == "J_Knee_RI" && closesttag == "J_Ankle_RI" )
|
|
{
|
|
refs[ refs.size ] = "right_leg";
|
|
refs[ refs.size ] = "no_legs";
|
|
}
|
|
/*
|
|
/#
|
|
assert( array_validate( refs ), "get_closest_damage_refs(): couldn't derive refs from closestTag " + closesttag );
|
|
#/
|
|
*/
|
|
return refs;
|
|
}
|
|
|
|
init_gib_tags() //checked matches cerberus output
|
|
{
|
|
tags = [];
|
|
tags[ tags.size ] = "J_SpineLower";
|
|
tags[ tags.size ] = "J_SpineUpper";
|
|
tags[ tags.size ] = "J_Spine4";
|
|
tags[ tags.size ] = "J_Shoulder_LE";
|
|
tags[ tags.size ] = "J_Elbow_LE";
|
|
tags[ tags.size ] = "J_Wrist_LE";
|
|
tags[ tags.size ] = "J_Shoulder_RI";
|
|
tags[ tags.size ] = "J_Elbow_RI";
|
|
tags[ tags.size ] = "J_Wrist_RI";
|
|
tags[ tags.size ] = "J_Hip_LE";
|
|
tags[ tags.size ] = "J_Knee_LE";
|
|
tags[ tags.size ] = "J_Ankle_LE";
|
|
tags[ tags.size ] = "J_Hip_RI";
|
|
tags[ tags.size ] = "J_Knee_RI";
|
|
tags[ tags.size ] = "J_Ankle_RI";
|
|
level.gib_tags = tags;
|
|
}
|
|
|
|
zombie_can_drop_powerups( zombie ) //checked matches cerberus output
|
|
{
|
|
if ( is_tactical_grenade( zombie.damageweapon ) || !flag( "zombie_drop_powerups" ) )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( is_true( zombie.no_powerups ) )
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
zombie_delay_powerup_drop( origin ) //checked matches cerberus output
|
|
{
|
|
wait_network_frame();
|
|
level thread maps/mp/zombies/_zm_powerups::powerup_drop( origin );
|
|
}
|
|
|
|
zombie_death_points( origin, mod, hit_location, attacker, zombie, team ) //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( attacker ) || !isplayer( attacker ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( zombie_can_drop_powerups( zombie ) )
|
|
{
|
|
if ( isDefined( zombie.in_the_ground ) && zombie.in_the_ground == 1 )
|
|
{
|
|
trace = bullettrace( zombie.origin + vectorScale( ( 0, 0, 1 ), 100 ), zombie.origin + vectorScale( ( 0, 0, 0 ), -100 ), 0, undefined );
|
|
origin = trace[ "position" ];
|
|
level thread zombie_delay_powerup_drop( origin );
|
|
}
|
|
else
|
|
{
|
|
trace = groundtrace( zombie.origin + vectorScale( ( 0, 0, 1 ), 5 ), zombie.origin + vectorScale( ( 0, 0, 0 ), -300 ), 0, undefined );
|
|
origin = trace[ "position" ];
|
|
level thread zombie_delay_powerup_drop( origin );
|
|
}
|
|
}
|
|
level thread maps/mp/zombies/_zm_audio::player_zombie_kill_vox( hit_location, attacker, mod, zombie );
|
|
event = "death";
|
|
if ( isDefined( zombie.damageweapon ) && issubstr( zombie.damageweapon, "knife_ballistic_" ) || mod == "MOD_MELEE" && mod == "MOD_IMPACT" )
|
|
{
|
|
event = "ballistic_knife_death";
|
|
}
|
|
if ( is_true( zombie.deathpoints_already_given ) )
|
|
{
|
|
return;
|
|
}
|
|
zombie.deathpoints_already_given = 1;
|
|
if ( isDefined( zombie.damageweapon ) && is_equipment( zombie.damageweapon ) )
|
|
{
|
|
return;
|
|
}
|
|
attacker maps/mp/zombies/_zm_score::player_add_points( event, mod, hit_location, undefined, team, attacker.currentweapon );
|
|
}
|
|
|
|
get_number_variants( aliasprefix ) //checked matches cerberus output
|
|
{
|
|
for ( i = 0; i < 100; i++ )
|
|
{
|
|
if ( !soundexists( aliasprefix + "_" + i ) )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
dragons_breath_flame_death_fx() //checked matches cerberus output
|
|
{
|
|
if ( self.isdog )
|
|
{
|
|
return;
|
|
}
|
|
if ( !isDefined( level._effect ) || !isDefined( level._effect[ "character_fire_death_sm" ] ) )
|
|
{
|
|
/*
|
|
/#
|
|
println( "^3ANIMSCRIPT WARNING: You are missing level._effect["character_fire_death_sm"], please set it in your levelname_fx.gsc. Use "env/fire/fx_fire_zombie_md"" );
|
|
#/
|
|
*/
|
|
return;
|
|
}
|
|
playfxontag( level._effect[ "character_fire_death_sm" ], self, "J_SpineLower" );
|
|
tagarray = [];
|
|
if ( !isDefined( self.a.gib_ref ) || self.a.gib_ref != "left_arm" )
|
|
{
|
|
tagarray[ tagarray.size ] = "J_Elbow_LE";
|
|
tagarray[ tagarray.size ] = "J_Wrist_LE";
|
|
}
|
|
if ( !isDefined( self.a.gib_ref ) || self.a.gib_ref != "right_arm" )
|
|
{
|
|
tagarray[ tagarray.size ] = "J_Elbow_RI";
|
|
tagarray[ tagarray.size ] = "J_Wrist_RI";
|
|
}
|
|
if ( !isDefined( self.a.gib_ref ) || self.a.gib_ref != "no_legs" && self.a.gib_ref != "left_leg" )
|
|
{
|
|
tagarray[ tagarray.size ] = "J_Knee_LE";
|
|
tagarray[ tagarray.size ] = "J_Ankle_LE";
|
|
}
|
|
if ( !isDefined( self.a.gib_ref ) || self.a.gib_ref != "no_legs" && self.a.gib_ref != "right_leg" )
|
|
{
|
|
tagarray[ tagarray.size ] = "J_Knee_RI";
|
|
tagarray[ tagarray.size ] = "J_Ankle_RI";
|
|
}
|
|
tagarray = array_randomize( tagarray );
|
|
playfxontag( level._effect[ "character_fire_death_sm" ], self, tagarray[ 0 ] );
|
|
}
|
|
|
|
zombie_ragdoll_then_explode( launchvector, attacker ) //checked changed to match cerberus output
|
|
{
|
|
if ( !isDefined( self ) )
|
|
{
|
|
return;
|
|
}
|
|
self zombie_eye_glow_stop();
|
|
self setclientfield( "zombie_ragdoll_explode", 1 );
|
|
self notify( "exploding" );
|
|
self notify( "end_melee" );
|
|
self notify( "death", attacker );
|
|
self.dont_die_on_me = 1;
|
|
self.exploding = 1;
|
|
self.a.nodeath = 1;
|
|
self.dont_throw_gib = 1;
|
|
self startragdoll();
|
|
self setplayercollision( 0 );
|
|
self reset_attack_spot();
|
|
if ( isDefined( launchvector ) )
|
|
{
|
|
self launchragdoll( launchvector );
|
|
}
|
|
wait 2.1;
|
|
if ( isDefined( self ) )
|
|
{
|
|
self ghost();
|
|
self delay_thread( 0.25, ::self_delete );
|
|
}
|
|
}
|
|
|
|
zombie_death_animscript() //checked changed to match cerberus output
|
|
{
|
|
team = undefined;
|
|
recalc_zombie_array();
|
|
if ( isDefined( self._race_team ) )
|
|
{
|
|
team = self._race_team;
|
|
}
|
|
self reset_attack_spot();
|
|
if ( self check_zombie_death_animscript_callbacks() )
|
|
{
|
|
return 0;
|
|
}
|
|
if ( isDefined( level.zombie_death_animscript_override ) )
|
|
{
|
|
self [[ level.zombie_death_animscript_override ]]();
|
|
}
|
|
if ( self.has_legs && isDefined( self.a.gib_ref ) && self.a.gib_ref == "no_legs" )
|
|
{
|
|
self.deathanim = "zm_death";
|
|
}
|
|
self.grenadeammo = 0;
|
|
if ( isDefined( self.nuked ) )
|
|
{
|
|
if ( zombie_can_drop_powerups( self ) )
|
|
{
|
|
if ( isDefined( self.in_the_ground ) && self.in_the_ground == 1 )
|
|
{
|
|
trace = bullettrace( self.origin + vectorScale( ( 0, 0, 1 ), 100 ), self.origin + vectorScale( ( 0, 0, 0 ), -100 ), 0, undefined );
|
|
origin = trace[ "position" ];
|
|
level thread zombie_delay_powerup_drop( origin );
|
|
}
|
|
else
|
|
{
|
|
trace = groundtrace( self.origin + vectorScale( ( 0, 0, 1 ), 5 ), self.origin + vectorScale( ( 0, 0, 0 ), -300 ), 0, undefined );
|
|
origin = trace[ "position" ];
|
|
level thread zombie_delay_powerup_drop( self.origin );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
level zombie_death_points( self.origin, self.damagemod, self.damagelocation, self.attacker, self, team );
|
|
}
|
|
if ( isDefined( self.attacker ) && isai( self.attacker ) )
|
|
{
|
|
self.attacker notify( "killed", self );
|
|
}
|
|
if ( self.damageweapon == "rottweil72_upgraded_zm" && self.damagemod == "MOD_RIFLE_BULLET" )
|
|
{
|
|
self thread dragons_breath_flame_death_fx();
|
|
}
|
|
if ( self.damageweapon == "tazer_knuckles_zm" && self.damagemod == "MOD_MELEE" )
|
|
{
|
|
self.is_on_fire = 0;
|
|
self notify( "stop_flame_damage" );
|
|
}
|
|
if ( self.damagemod == "MOD_BURNED" )
|
|
{
|
|
self thread maps/mp/animscripts/zm_death::flame_death_fx();
|
|
}
|
|
if ( self.damagemod == "MOD_GRENADE" || self.damagemod == "MOD_GRENADE_SPLASH" )
|
|
{
|
|
level notify( "zombie_grenade_death", self.origin );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
check_zombie_death_animscript_callbacks() //checked changed to match cerberus output
|
|
{
|
|
if ( !isDefined( level.zombie_death_animscript_callbacks ) )
|
|
{
|
|
return 0;
|
|
}
|
|
for ( i = 0; i < level.zombie_death_animscript_callbacks.size; i++ )
|
|
{
|
|
if ( self [[ level.zombie_death_animscript_callbacks[ i ] ]]() )
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
register_zombie_death_animscript_callback( func ) //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( level.zombie_death_animscript_callbacks ) )
|
|
{
|
|
level.zombie_death_animscript_callbacks = [];
|
|
}
|
|
level.zombie_death_animscript_callbacks[ level.zombie_death_animscript_callbacks.size ] = func;
|
|
}
|
|
|
|
damage_on_fire( player ) //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "stop_flame_damage" );
|
|
wait 2;
|
|
while ( is_true( self.is_on_fire ) )
|
|
{
|
|
if ( level.round_number < 6 )
|
|
{
|
|
dmg = level.zombie_health * randomfloatrange( 0.2, 0.3 );
|
|
}
|
|
else if ( level.round_number < 9 )
|
|
{
|
|
dmg = level.zombie_health * randomfloatrange( 0.15, 0.25 );
|
|
}
|
|
else if ( level.round_number < 11 )
|
|
{
|
|
dmg = level.zombie_health * randomfloatrange( 0.1, 0.2 );
|
|
}
|
|
else
|
|
{
|
|
dmg = level.zombie_health * randomfloatrange( 0.1, 0.15 );
|
|
}
|
|
if ( isDefined( player ) && isalive( player ) )
|
|
{
|
|
self dodamage( dmg, self.origin, player );
|
|
}
|
|
else
|
|
{
|
|
self dodamage( dmg, self.origin, level );
|
|
}
|
|
wait randomfloatrange( 1, 3 );
|
|
}
|
|
}
|
|
|
|
player_using_hi_score_weapon( player ) //checked matches cerberus output
|
|
{
|
|
weapon = player getcurrentweapon();
|
|
if ( weapon == "none" || weaponissemiauto( weapon ) )
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
zombie_damage( mod, hit_location, hit_origin, player, amount, team ) //checked changed to match cerberus output
|
|
{
|
|
if ( is_magic_bullet_shield_enabled( self ) )
|
|
{
|
|
return;
|
|
}
|
|
player.use_weapon_type = mod;
|
|
if ( isDefined( self.marked_for_death ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !isDefined( player ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( isDefined( hit_origin ) )
|
|
{
|
|
self.damagehit_origin = hit_origin;
|
|
}
|
|
else
|
|
{
|
|
self.damagehit_origin = player getweaponmuzzlepoint();
|
|
}
|
|
if ( self check_zombie_damage_callbacks( mod, hit_location, hit_origin, player, amount ) )
|
|
{
|
|
return;
|
|
}
|
|
else if ( self zombie_flame_damage( mod, player ) )
|
|
{
|
|
if ( self zombie_give_flame_damage_points() )
|
|
{
|
|
player maps/mp/zombies/_zm_score::player_add_points( "damage", mod, hit_location, self.isdog, team );
|
|
}
|
|
}
|
|
else if ( player_using_hi_score_weapon( player ) )
|
|
{
|
|
damage_type = "damage";
|
|
}
|
|
else
|
|
{
|
|
damage_type = "damage_light";
|
|
}
|
|
if ( !is_true( self.no_damage_points ) )
|
|
{
|
|
player maps/mp/zombies/_zm_score::player_add_points( damage_type, mod, hit_location, self.isdog, team, self.damageweapon );
|
|
}
|
|
if ( isDefined( self.zombie_damage_fx_func ) )
|
|
{
|
|
self [[ self.zombie_damage_fx_func ]]( mod, hit_location, hit_origin, player );
|
|
}
|
|
modname = remove_mod_from_methodofdeath( mod );
|
|
if ( is_placeable_mine( self.damageweapon ) )
|
|
{
|
|
if ( isDefined( self.zombie_damage_claymore_func ) )
|
|
{
|
|
self [[ self.zombie_damage_claymore_func ]]( mod, hit_location, hit_origin, player );
|
|
}
|
|
else if ( isDefined( player ) && isalive( player ) )
|
|
{
|
|
self dodamage( level.round_number * randomintrange( 100, 200 ), self.origin, player, self, hit_location, mod );
|
|
}
|
|
else
|
|
{
|
|
self dodamage( level.round_number * randomintrange( 100, 200 ), self.origin, undefined, self, hit_location, mod );
|
|
}
|
|
}
|
|
else if ( mod == "MOD_GRENADE" || mod == "MOD_GRENADE_SPLASH" )
|
|
{
|
|
if ( isDefined( player ) && isalive( player ) )
|
|
{
|
|
player.grenade_multiattack_count++;
|
|
player.grenade_multiattack_ent = self;
|
|
self dodamage( level.round_number + randomintrange( 100, 200 ), self.origin, player, self, hit_location, modname );
|
|
}
|
|
else
|
|
{
|
|
self dodamage( level.round_number + randomintrange( 100, 200 ), self.origin, undefined, self, hit_location, modname );
|
|
}
|
|
}
|
|
else if ( mod != "MOD_PROJECTILE" || mod == "MOD_EXPLOSIVE" && mod == "MOD_PROJECTILE_SPLASH" )
|
|
{
|
|
if ( isDefined( player ) && isalive( player ) )
|
|
{
|
|
self dodamage( level.round_number * randomintrange( 0, 100 ), self.origin, player, self, hit_location, modname );
|
|
}
|
|
else
|
|
{
|
|
self dodamage( level.round_number * randomintrange( 0, 100 ), self.origin, undefined, self, hit_location, modname );
|
|
}
|
|
}
|
|
if ( isDefined( self.a.gib_ref ) && self.a.gib_ref == "no_legs" && isalive( self ) )
|
|
{
|
|
if ( isDefined( player ) )
|
|
{
|
|
rand = randomintrange( 0, 100 );
|
|
if ( rand < 10 )
|
|
{
|
|
player create_and_play_dialog( "general", "crawl_spawn" );
|
|
}
|
|
}
|
|
}
|
|
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( player ) )
|
|
{
|
|
rand = randomintrange( 0, 100 );
|
|
if ( rand < 7 )
|
|
{
|
|
player create_and_play_dialog( "general", "shoot_arm" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
self thread maps/mp/zombies/_zm_powerups::check_for_instakill( player, mod, hit_location );
|
|
}
|
|
|
|
zombie_damage_ads( mod, hit_location, hit_origin, player, amount, team ) //checked changed to match cerberus output
|
|
{
|
|
if ( is_magic_bullet_shield_enabled( self ) )
|
|
{
|
|
return;
|
|
}
|
|
player.use_weapon_type = mod;
|
|
if ( !isDefined( player ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( isDefined( hit_origin ) )
|
|
{
|
|
self.damagehit_origin = hit_origin;
|
|
}
|
|
else
|
|
{
|
|
self.damagehit_origin = player getweaponmuzzlepoint();
|
|
}
|
|
if ( self check_zombie_damage_callbacks( mod, hit_location, hit_origin, player, amount ) )
|
|
{
|
|
return;
|
|
}
|
|
else if ( self zombie_flame_damage( mod, player ) )
|
|
{
|
|
if ( self zombie_give_flame_damage_points() )
|
|
{
|
|
player maps/mp/zombies/_zm_score::player_add_points( "damage_ads", mod, hit_location, undefined, team );
|
|
}
|
|
}
|
|
else if ( player_using_hi_score_weapon( player ) )
|
|
{
|
|
damage_type = "damage";
|
|
}
|
|
else
|
|
{
|
|
damage_type = "damage_light";
|
|
}
|
|
if ( !is_true( self.no_damage_points ) )
|
|
{
|
|
player maps/mp/zombies/_zm_score::player_add_points( damage_type, mod, hit_location, undefined, team, self.damageweapon );
|
|
}
|
|
self thread maps/mp/zombies/_zm_powerups::check_for_instakill( player, mod, hit_location );
|
|
}
|
|
|
|
check_zombie_damage_callbacks( mod, hit_location, hit_origin, player, amount ) //checked changed to match cerberus output
|
|
{
|
|
if ( !isDefined( level.zombie_damage_callbacks ) )
|
|
{
|
|
return 0;
|
|
}
|
|
for ( i = 0; i < level.zombie_damage_callbacks.size; i++ )
|
|
{
|
|
if ( self [[ level.zombie_damage_callbacks[ i ] ]]( mod, hit_location, hit_origin, player, amount ) )
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
register_zombie_damage_callback( func ) //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( level.zombie_damage_callbacks ) )
|
|
{
|
|
level.zombie_damage_callbacks = [];
|
|
}
|
|
level.zombie_damage_callbacks[ level.zombie_damage_callbacks.size ] = func;
|
|
}
|
|
|
|
zombie_give_flame_damage_points() //checked matches cerberus output
|
|
{
|
|
if ( getTime() > self.flame_damage_time )
|
|
{
|
|
self.flame_damage_time = getTime() + level.zombie_vars[ "zombie_flame_dmg_point_delay" ];
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
zombie_flame_damage( mod, player ) //checked changed to match cerberus output
|
|
{
|
|
if ( mod == "MOD_BURNED" )
|
|
{
|
|
if ( !is_true( self.is_on_fire ) )
|
|
{
|
|
self thread damage_on_fire( player );
|
|
}
|
|
do_flame_death = 1;
|
|
dist = 10000;
|
|
ai = getaiarray( level.zombie_team );
|
|
for ( i = 0; i < ai.size; i++ )
|
|
{
|
|
if ( is_true( ai[ i ].is_on_fire ) )
|
|
{
|
|
if ( distancesquared( ai[ i ].origin, self.origin ) < dist )
|
|
{
|
|
do_flame_death = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( do_flame_death )
|
|
{
|
|
self thread maps/mp/animscripts/zm_death::flame_death_fx();
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
is_weapon_shotgun( sweapon ) //checked matches cerberus output
|
|
{
|
|
if ( isDefined( sweapon ) && weaponclass( sweapon ) == "spread" )
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
zombie_death_event( zombie ) //checked changed to match cerberus output
|
|
{
|
|
zombie.marked_for_recycle = 0;
|
|
force_explode = 0;
|
|
force_head_gib = 0;
|
|
zombie waittill( "death", attacker );
|
|
time_of_death = getTime();
|
|
if ( isDefined( zombie ) )
|
|
{
|
|
zombie stopsounds();
|
|
}
|
|
if ( isDefined( zombie ) && isDefined( zombie.marked_for_insta_upgraded_death ) )
|
|
{
|
|
force_head_gib = 1;
|
|
}
|
|
if ( !isDefined( zombie.damagehit_origin ) && isDefined( attacker ) )
|
|
{
|
|
zombie.damagehit_origin = attacker getweaponmuzzlepoint();
|
|
}
|
|
if ( isDefined( attacker ) && isplayer( attacker ) )
|
|
{
|
|
if ( is_true( level.pers_upgrade_carpenter ) )
|
|
{
|
|
maps/mp/zombies/_zm_pers_upgrades::pers_zombie_death_location_check( attacker, zombie.origin );
|
|
}
|
|
if ( is_true( level.pers_upgrade_sniper ) )
|
|
{
|
|
attacker pers_upgrade_sniper_kill_check( zombie, attacker );
|
|
}
|
|
if ( isDefined( zombie ) && isDefined( zombie.damagelocation ) )
|
|
{
|
|
if ( is_headshot( zombie.damageweapon, zombie.damagelocation, zombie.damagemod ) )
|
|
{
|
|
attacker.headshots++;
|
|
attacker maps/mp/zombies/_zm_stats::increment_client_stat( "headshots" );
|
|
attacker addweaponstat( zombie.damageweapon, "headshots", 1 );
|
|
attacker maps/mp/zombies/_zm_stats::increment_player_stat( "headshots" );
|
|
if ( is_classic() )
|
|
{
|
|
attacker maps/mp/zombies/_zm_pers_upgrades_functions::pers_check_for_pers_headshot( time_of_death, zombie );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
attacker notify( "zombie_death_no_headshot" );
|
|
}
|
|
}
|
|
if ( isDefined( zombie ) && isDefined( zombie.damagemod ) && zombie.damagemod == "MOD_MELEE" )
|
|
{
|
|
attacker maps/mp/zombies/_zm_stats::increment_client_stat( "melee_kills" );
|
|
attacker maps/mp/zombies/_zm_stats::increment_player_stat( "melee_kills" );
|
|
attacker notify( "melee_kill" );
|
|
if ( attacker maps/mp/zombies/_zm_pers_upgrades::is_insta_kill_upgraded_and_active() )
|
|
{
|
|
force_explode = 1;
|
|
}
|
|
}
|
|
attacker maps/mp/zombies/_zm::add_rampage_bookmark_kill_time();
|
|
attacker.kills++;
|
|
attacker maps/mp/zombies/_zm_stats::increment_client_stat( "kills" );
|
|
attacker maps/mp/zombies/_zm_stats::increment_player_stat( "kills" );
|
|
if ( is_true( level.pers_upgrade_pistol_points ) )
|
|
{
|
|
attacker maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_pistol_points_kill();
|
|
}
|
|
dmgweapon = zombie.damageweapon;
|
|
if ( is_alt_weapon( dmgweapon ) )
|
|
{
|
|
dmgweapon = weaponaltweaponname( dmgweapon );
|
|
}
|
|
attacker addweaponstat( dmgweapon, "kills", 1 );
|
|
if ( attacker maps/mp/zombies/_zm_pers_upgrades_functions::pers_mulit_kill_headshot_active() || force_head_gib )
|
|
{
|
|
zombie maps/mp/zombies/_zm_spawner::zombie_head_gib();
|
|
}
|
|
if ( is_true( level.pers_upgrade_nube ) )
|
|
{
|
|
attacker notify( "pers_player_zombie_kill" );
|
|
}
|
|
}
|
|
zombie_death_achievement_sliquifier_check( attacker, zombie );
|
|
recalc_zombie_array();
|
|
if ( !isDefined( zombie ) )
|
|
{
|
|
return;
|
|
}
|
|
level.global_zombies_killed++;
|
|
if ( isDefined( zombie.marked_for_death ) && !isDefined( zombie.nuked ) )
|
|
{
|
|
level.zombie_trap_killed_count++;
|
|
}
|
|
zombie check_zombie_death_event_callbacks();
|
|
name = zombie.animname;
|
|
if ( isDefined( zombie.sndname ) )
|
|
{
|
|
name = zombie.sndname;
|
|
}
|
|
zombie thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "death", name );
|
|
zombie thread zombie_eye_glow_stop();
|
|
if ( isDefined( zombie.damageweapon ) && is_weapon_shotgun( zombie.damageweapon ) && !maps/mp/zombies/_zm_weapons::is_weapon_upgraded( zombie.damageweapon ) || isDefined( zombie.damageweapon ) && is_placeable_mine( zombie.damageweapon ) || zombie.damagemod == "MOD_GRENADE" || zombie.damagemod == "MOD_GRENADE_SPLASH" || zombie.damagemod == "MOD_EXPLOSIVE" || force_explode == 1 )
|
|
{
|
|
splode_dist = 180;
|
|
if ( isDefined( zombie.damagehit_origin ) && distancesquared( zombie.origin, zombie.damagehit_origin ) < ( splode_dist * splode_dist ) )
|
|
{
|
|
tag = "J_SpineLower";
|
|
if ( is_true( zombie.isdog ) )
|
|
{
|
|
tag = "tag_origin";
|
|
}
|
|
if ( !is_true( zombie.is_on_fire ) && !is_true( zombie.guts_explosion ) )
|
|
{
|
|
zombie thread zombie_gut_explosion();
|
|
}
|
|
}
|
|
}
|
|
if ( zombie.damagemod == "MOD_GRENADE" || zombie.damagemod == "MOD_GRENADE_SPLASH" )
|
|
{
|
|
if ( isDefined( attacker ) && isalive( attacker ) )
|
|
{
|
|
attacker.grenade_multiattack_count++;
|
|
attacker.grenade_multiattack_ent = zombie;
|
|
}
|
|
}
|
|
if ( !is_true( zombie.has_been_damaged_by_player ) && is_true( zombie.marked_for_recycle ) )
|
|
{
|
|
level.zombie_total++;
|
|
level.zombie_total_subtract++;
|
|
}
|
|
else if ( isDefined( zombie.attacker ) && isplayer( zombie.attacker ) )
|
|
{
|
|
level.zombie_player_killed_count++;
|
|
if ( isDefined( zombie.sound_damage_player ) && zombie.sound_damage_player == zombie.attacker )
|
|
{
|
|
chance = get_response_chance( "damage" );
|
|
if ( chance != 0 )
|
|
{
|
|
if ( chance > randomintrange( 1, 100 ) )
|
|
{
|
|
zombie.attacker maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "damage" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zombie.attacker maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "damage" );
|
|
}
|
|
}
|
|
zombie.attacker notify( "zom_kill", zombie );
|
|
damageloc = zombie.damagelocation;
|
|
damagemod = zombie.damagemod;
|
|
attacker = zombie.attacker;
|
|
weapon = zombie.damageweapon;
|
|
bbprint( "zombie_kills", "round %d zombietype %s damagetype %s damagelocation %s playername %s playerweapon %s playerx %f playery %f playerz %f zombiex %f zombiey %f zombiez %f", level.round_number, zombie.animname, damagemod, damageloc, attacker.name, weapon, attacker.origin, zombie.origin );
|
|
}
|
|
else if ( zombie.ignoreall && !is_true( zombie.marked_for_death ) )
|
|
{
|
|
level.zombies_timeout_spawn++;
|
|
}
|
|
level notify( "zom_kill" );
|
|
level.total_zombies_killed++;
|
|
}
|
|
|
|
zombie_gut_explosion() //checked matches cerberus output
|
|
{
|
|
self.guts_explosion = 1;
|
|
if ( is_mature() )
|
|
{
|
|
self setclientfield( "zombie_gut_explosion", 1 );
|
|
}
|
|
if ( !is_true( self.isdog ) )
|
|
{
|
|
wait 0.1;
|
|
}
|
|
if ( isDefined( self ) )
|
|
{
|
|
self ghost();
|
|
}
|
|
}
|
|
|
|
zombie_death_achievement_sliquifier_check( e_player, e_zombie ) //checked matches cerberus output
|
|
{
|
|
if ( !isplayer( e_player ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( isDefined( e_zombie ) )
|
|
{
|
|
if ( isDefined( e_zombie.damageweapon ) && e_zombie.damageweapon == "slipgun_zm" )
|
|
{
|
|
if ( !isDefined( e_player.num_sliquifier_kills ) )
|
|
{
|
|
e_player.num_sliquifier_kills = 0;
|
|
}
|
|
e_player.num_sliquifier_kills++;
|
|
e_player notify( "sliquifier_kill" );
|
|
}
|
|
}
|
|
}
|
|
|
|
check_zombie_death_event_callbacks() //checked changed to match cerberus output
|
|
{
|
|
if ( !isDefined( level.zombie_death_event_callbacks ) )
|
|
{
|
|
return;
|
|
}
|
|
for ( i = 0; i < level.zombie_death_event_callbacks.size; i++ )
|
|
{
|
|
self [[ level.zombie_death_event_callbacks[ i ] ]]();
|
|
}
|
|
}
|
|
|
|
register_zombie_death_event_callback( func ) //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( level.zombie_death_event_callbacks ) )
|
|
{
|
|
level.zombie_death_event_callbacks = [];
|
|
}
|
|
level.zombie_death_event_callbacks[ level.zombie_death_event_callbacks.size ] = func;
|
|
}
|
|
|
|
deregister_zombie_death_event_callback( func ) //checked matches cerberus output
|
|
{
|
|
if ( isDefined( level.zombie_death_event_callbacks ) )
|
|
{
|
|
arrayremovevalue( level.zombie_death_event_callbacks, func );
|
|
}
|
|
}
|
|
|
|
zombie_setup_attack_properties() //checked matches cerberus output
|
|
{
|
|
self zombie_history( "zombie_setup_attack_properties()" );
|
|
self.ignoreall = 0;
|
|
self.pathenemyfightdist = 64;
|
|
self.meleeattackdist = 64;
|
|
self.maxsightdistsqrd = 16384;
|
|
self.disablearrivals = 1;
|
|
self.disableexits = 1;
|
|
}
|
|
|
|
attractors_generated_listener() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
level endon( "intermission" );
|
|
self endon( "stop_find_flesh" );
|
|
self endon( "path_timer_done" );
|
|
level waittill( "attractor_positions_generated" );
|
|
self.zombie_path_timer = 0;
|
|
}
|
|
|
|
zombie_pathing() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "zombie_acquire_enemy" );
|
|
level endon( "intermission" );
|
|
/*
|
|
/#
|
|
if ( !isDefined( self.favoriteenemy ) )
|
|
{
|
|
assert( isDefined( self.enemyoverride ) );
|
|
}
|
|
#/
|
|
*/
|
|
self._skip_pathing_first_delay = 1;
|
|
self thread zombie_follow_enemy();
|
|
self waittill( "bad_path" );
|
|
level.zombie_pathing_failed++;
|
|
if ( isDefined( self.enemyoverride ) )
|
|
{
|
|
//debug_print( "Zombie couldn't path to point of interest at origin: " + self.enemyoverride[ 0 ] + " Falling back to breadcrumb system" );
|
|
if ( isDefined( self.enemyoverride[ 1 ] ) )
|
|
{
|
|
self.enemyoverride = self.enemyoverride[ 1 ] invalidate_attractor_pos( self.enemyoverride, self );
|
|
self.zombie_path_timer = 0;
|
|
return;
|
|
}
|
|
}
|
|
else if ( isDefined( self.favoriteenemy ) )
|
|
{
|
|
//debug_print( "Zombie couldn't path to player at origin: " + self.favoriteenemy.origin + " Falling back to breadcrumb system" );
|
|
}
|
|
else
|
|
{
|
|
//debug_print( "Zombie couldn't path to a player ( the other 'prefered' player might be ignored for encounters mode ). Falling back to breadcrumb system" );
|
|
}
|
|
if ( !isDefined( self.favoriteenemy ) )
|
|
{
|
|
self.zombie_path_timer = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
self.favoriteenemy endon( "disconnect" );
|
|
}
|
|
players = get_players();
|
|
valid_player_num = 0;
|
|
for ( i = 0; i < players.size; i++ )
|
|
{
|
|
if ( is_player_valid( players[ i ], 1 ) )
|
|
{
|
|
valid_player_num += 1;
|
|
}
|
|
}
|
|
if ( players.size > 1 )
|
|
{
|
|
if ( isDefined( level._should_skip_ignore_player_logic ) && [[ level._should_skip_ignore_player_logic ]]() )
|
|
{
|
|
self.zombie_path_timer = 0;
|
|
return;
|
|
}
|
|
if ( array_check_for_dupes( self.ignore_player, self.favoriteenemy ) )
|
|
{
|
|
self.ignore_player[ self.ignore_player.size ] = self.favoriteenemy;
|
|
}
|
|
if ( self.ignore_player.size < valid_player_num )
|
|
{
|
|
self.zombie_path_timer = 0;
|
|
return;
|
|
}
|
|
}
|
|
crumb_list = self.favoriteenemy.zombie_breadcrumbs;
|
|
bad_crumbs = [];
|
|
while ( 1 )
|
|
{
|
|
if ( !is_player_valid( self.favoriteenemy, 1 ) )
|
|
{
|
|
self.zombie_path_timer = 0;
|
|
return;
|
|
}
|
|
goal = zombie_pathing_get_breadcrumb( self.favoriteenemy.origin, crumb_list, bad_crumbs, randomint( 100 ) < 20 );
|
|
if ( !isDefined( goal ) )
|
|
{
|
|
//debug_print( "Zombie exhausted breadcrumb search" );
|
|
level.zombie_breadcrumb_failed++;
|
|
goal = self.favoriteenemy.spectator_respawn.origin;
|
|
}
|
|
//debug_print( "Setting current breadcrumb to " + goal );
|
|
self.zombie_path_timer += 100;
|
|
self setgoalpos( goal );
|
|
self waittill( "bad_path" );
|
|
//debug_print( "Zombie couldn't path to breadcrumb at " + goal + " Finding next breadcrumb" );
|
|
for ( i = 0; i < crumb_list.size; i++ )
|
|
{
|
|
if ( goal == crumb_list[ i ] )
|
|
{
|
|
bad_crumbs[ bad_crumbs.size ] = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
zombie_pathing_get_breadcrumb( origin, breadcrumbs, bad_crumbs, pick_random ) //checked changed to match cerberus output
|
|
{
|
|
/*
|
|
/#
|
|
assert( isDefined( origin ) );
|
|
#/
|
|
/#
|
|
assert( isDefined( breadcrumbs ) );
|
|
#/
|
|
/#
|
|
assert( isarray( breadcrumbs ) );
|
|
#/
|
|
/#
|
|
if ( pick_random )
|
|
{
|
|
debug_print( "Finding random breadcrumb" );
|
|
#/
|
|
}
|
|
*/
|
|
i = 0;
|
|
while ( i < breadcrumbs.size )
|
|
{
|
|
if ( pick_random )
|
|
{
|
|
crumb_index = randomint( breadcrumbs.size );
|
|
}
|
|
else
|
|
{
|
|
crumb_index = i;
|
|
}
|
|
if ( crumb_is_bad( crumb_index, bad_crumbs ) )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
i++;
|
|
return breadcrumbs[ crumb_index ];
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
crumb_is_bad( crumb, bad_crumbs ) //checked changed to match cerberus output
|
|
{
|
|
for ( i = 0; i < bad_crumbs.size; i++ )
|
|
{
|
|
if ( bad_crumbs[ i ] == crumb )
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
jitter_enemies_bad_breadcrumbs( start_crumb ) //checked changed to match cerberus output
|
|
{
|
|
trace_distance = 35;
|
|
jitter_distance = 2;
|
|
index = start_crumb;
|
|
while ( isDefined( self.favoriteenemy.zombie_breadcrumbs[ index + 1 ] ) )
|
|
{
|
|
current_crumb = self.favoriteenemy.zombie_breadcrumbs[ index ];
|
|
next_crumb = self.favoriteenemy.zombie_breadcrumbs[ index + 1 ];
|
|
angles = vectorToAngles( current_crumb - next_crumb );
|
|
right = anglesToRight( angles );
|
|
left = anglesToRight( angles + vectorScale( ( 0, 1, 0 ), 180 ) );
|
|
dist_pos = current_crumb + vectorScale( right, trace_distance );
|
|
trace = bullettrace( current_crumb, dist_pos, 1, undefined );
|
|
vector = trace[ "position" ];
|
|
if ( distance( vector, current_crumb ) < 17 )
|
|
{
|
|
self.favoriteenemy.zombie_breadcrumbs[ index ] = current_crumb + vectorScale( left, jitter_distance );
|
|
continue;
|
|
}
|
|
dist_pos = current_crumb + vectorScale( left, trace_distance );
|
|
trace = bullettrace( current_crumb, dist_pos, 1, undefined );
|
|
vector = trace[ "position" ];
|
|
if ( distance( vector, current_crumb ) < 17 )
|
|
{
|
|
self.favoriteenemy.zombie_breadcrumbs[ index ] = current_crumb + vectorScale( right, jitter_distance );
|
|
continue;
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
|
|
zombie_repath_notifier() //checked changed to match cerberus output
|
|
{
|
|
note = 0;
|
|
notes = [];
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
notes[ notes.size ] = "zombie_repath_notify_" + i;
|
|
}
|
|
while ( 1 )
|
|
{
|
|
level notify( notes[ note ] );
|
|
note = ( note + 1 ) % 4;
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
zombie_follow_enemy() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
self endon( "zombie_acquire_enemy" );
|
|
self endon( "bad_path" );
|
|
level endon( "intermission" );
|
|
if ( !isDefined( level.repathnotifierstarted ) )
|
|
{
|
|
level.repathnotifierstarted = 1;
|
|
level thread zombie_repath_notifier();
|
|
}
|
|
if ( !isDefined( self.zombie_repath_notify ) )
|
|
{
|
|
self.zombie_repath_notify = "zombie_repath_notify_" + self getentitynumber() % 4;
|
|
}
|
|
while ( 1 )
|
|
{
|
|
if ( !isDefined( self._skip_pathing_first_delay ) )
|
|
{
|
|
level waittill( self.zombie_repath_notify );
|
|
}
|
|
else
|
|
{
|
|
self._skip_pathing_first_delay = undefined;
|
|
}
|
|
if ( !is_true( self.ignore_enemyoverride ) && isDefined( self.enemyoverride ) && isDefined( self.enemyoverride[ 1 ] ) )
|
|
{
|
|
if ( distancesquared( self.origin, self.enemyoverride[ 0 ] ) > 1 )
|
|
{
|
|
self orientmode( "face motion" );
|
|
}
|
|
else
|
|
{
|
|
self orientmode( "face point", self.enemyoverride[ 1 ].origin );
|
|
}
|
|
self.ignoreall = 1;
|
|
goalpos = self.enemyoverride[ 0 ];
|
|
if ( isDefined( level.adjust_enemyoverride_func ) )
|
|
{
|
|
goalpos = self [[ level.adjust_enemyoverride_func ]]();
|
|
}
|
|
self setgoalpos( goalpos );
|
|
}
|
|
else if ( isDefined( self.favoriteenemy ) )
|
|
{
|
|
self.ignoreall = 0;
|
|
self orientmode( "face default" );
|
|
goalpos = self.favoriteenemy.origin;
|
|
if ( isDefined( level.enemy_location_override_func ) )
|
|
{
|
|
goalpos = [[ level.enemy_location_override_func ]]( self, self.favoriteenemy );
|
|
}
|
|
self setgoalpos( goalpos );
|
|
if ( !isDefined( level.ignore_path_delays ) )
|
|
{
|
|
distsq = distancesquared( self.origin, self.favoriteenemy.origin );
|
|
if ( distsq > 10240000 )
|
|
{
|
|
wait ( 2 + randomfloat( 1 ) );
|
|
}
|
|
else if ( distsq > 4840000 )
|
|
{
|
|
wait ( 1 + randomfloat( 0.5 ) );
|
|
}
|
|
else if ( distsq > 1440000 )
|
|
{
|
|
wait ( 0.5 + randomfloat( 0.5 ) );
|
|
}
|
|
}
|
|
}
|
|
if ( isDefined( level.inaccesible_player_func ) )
|
|
{
|
|
self [[ level.inaccessible_player_func ]]();
|
|
}
|
|
}
|
|
}
|
|
|
|
zombie_eye_glow() //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( self ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !is_true( self.no_eye_glow ) )
|
|
{
|
|
self setclientfield( "zombie_has_eyes", 1 );
|
|
}
|
|
}
|
|
|
|
zombie_eye_glow_stop() //checked matches cerberus output
|
|
{
|
|
if ( !isDefined( self ) )
|
|
{
|
|
return;
|
|
}
|
|
if ( !is_true( self.no_eye_glow ) )
|
|
{
|
|
self setclientfield( "zombie_has_eyes", 0 );
|
|
}
|
|
}
|
|
|
|
zombie_history( msg ) //dev call did not check
|
|
{
|
|
/*
|
|
/#
|
|
if ( !isDefined( self.zombie_history ) || self.zombie_history.size > 32 )
|
|
{
|
|
self.zombie_history = [];
|
|
}
|
|
self.zombie_history[ self.zombie_history.size ] = msg;
|
|
#/
|
|
*/
|
|
}
|
|
|
|
do_zombie_spawn() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
spots = [];
|
|
if ( isDefined( self._rise_spot ) )
|
|
{
|
|
spot = self._rise_spot;
|
|
self thread do_zombie_rise( spot );
|
|
return;
|
|
}
|
|
if ( isDefined( level.zombie_spawn_locations ) )
|
|
{
|
|
i = 0;
|
|
while ( i < level.zombie_spawn_locations.size )
|
|
{
|
|
if ( is_true( level.use_multiple_spawns ) && isDefined( self.script_int ) )
|
|
{
|
|
if ( isDefined( level.spawner_int ) && self.script_int == level.spawner_int && ( !isDefined( level.zombie_spawn_locations[ i ].script_int ) || !isDefined( level.zones[ level.zombie_spawn_locations[ i ].zone_name ].script_int ) ) )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( isDefined( level.zombie_spawn_locations[ i ].script_int ) && level.zombie_spawn_locations[ i ].script_int != self.script_int )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( isDefined( level.zones[ level.zombie_spawn_locations[ i ].zone_name ].script_int ) && level.zones[ level.zombie_spawn_locations[ i ].zone_name ].script_int != self.script_int )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
spots[ spots.size ] = level.zombie_spawn_locations[ i ];
|
|
i++;
|
|
}
|
|
}
|
|
/*
|
|
/#
|
|
if ( getDvarInt( #"A8C231AA" ) )
|
|
{
|
|
if ( isDefined( level.zombie_spawn_locations ) )
|
|
{
|
|
player = get_players()[ 0 ];
|
|
spots = [];
|
|
i = 0;
|
|
while ( i < level.zombie_spawn_locations.size )
|
|
{
|
|
player_vec = vectornormalize( anglesToForward( player.angles ) );
|
|
player_spawn = vectornormalize( level.zombie_spawn_locations[ i ].origin - player.origin );
|
|
dot = vectordot( player_vec, player_spawn );
|
|
if ( dot > 0,707 )
|
|
{
|
|
spots[ spots.size ] = level.zombie_spawn_locations[ i ];
|
|
debugstar( level.zombie_spawn_locations[ i ].origin, 1000, ( 0, 0, 0 ) );
|
|
}
|
|
i++;
|
|
}
|
|
if ( spots.size <= 0 )
|
|
{
|
|
spots[ spots.size ] = level.zombie_spawn_locations[ 0 ];
|
|
iprintln( "no spawner in view" );
|
|
#/
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
/*
|
|
/#
|
|
assert( spots.size > 0, "No spawn locations found" );
|
|
#/
|
|
*/
|
|
spot = random( spots );
|
|
self.spawn_point = spot;
|
|
/*
|
|
/#
|
|
if ( is_true( level.toggle_show_spawn_locations ) )
|
|
{
|
|
debugstar( spot.origin, getDvarInt( #"BB9101B2" ), ( 0, 0, 0 ) );
|
|
host_player = gethostplayer();
|
|
distance = distance( spot.origin, host_player.origin );
|
|
iprintln( "Distance to player: " + ( distance / 12 ) + "feet" );
|
|
#/
|
|
}
|
|
*/
|
|
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;
|
|
}
|
|
tokens = strtok( spot.script_noteworthy, " " );
|
|
i = 0;
|
|
while ( i < tokens.size )
|
|
{
|
|
if ( isdefined( self.spawn_point_override ) )
|
|
{
|
|
spot = self.spawn_point_override;
|
|
tokens[ i ] = spot.script_noteworthy;
|
|
}
|
|
if ( tokens[ i ] == "custom_spawner_entry" )
|
|
{
|
|
if ( isdefined( tokens[ i ] ) )
|
|
{
|
|
str_spawn_entry = tokens[ i ];
|
|
if ( isdefined( level.custom_spawner_entry ) && isdefined( level.custom_spawner_entry[ str_spawn_entry ] ) )
|
|
{
|
|
self thread [[ level.custom_spawner_entry[ str_spawn_entry ] ]](spot);
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
if ( tokens[ i ] == "riser_location" )
|
|
{
|
|
self thread do_zombie_rise( spot );
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( tokens[ i ] == "faller_location" )
|
|
{
|
|
self thread maps/mp/zombies/_zm_ai_faller::do_zombie_fall( spot );
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( tokens[ i ] == "dog_location" )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( tokens[ i ] == "screecher_location" )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( tokens[ i ] == "leaper_location" )
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if ( isdefined(self.anchor ) )
|
|
{
|
|
i++;
|
|
return;
|
|
}
|
|
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 );
|
|
}
|
|
self ghost();
|
|
self.anchor moveto( spot.origin, 0.05 );
|
|
self.anchor waittill( "movedone" );
|
|
target_org = get_desired_origin();
|
|
if ( isDefined( target_org ) )
|
|
{
|
|
anim_ang = vectorToAngles( target_org - self.origin );
|
|
self.anchor rotateto( ( 0, anim_ang[ 1 ], 0 ), 0.05 );
|
|
self.anchor waittill( "rotatedone" );
|
|
}
|
|
if ( isDefined( level.zombie_spawn_fx ) )
|
|
{
|
|
playfx( level.zombie_spawn_fx, spot.origin );
|
|
}
|
|
self unlink();
|
|
if ( isDefined( self.anchor ) )
|
|
{
|
|
self.anchor delete();
|
|
}
|
|
self show();
|
|
self notify( "risen", spot.script_string );
|
|
i++;
|
|
}
|
|
}
|
|
|
|
do_zombie_rise( spot ) //checked changed to match cerberus output
|
|
{
|
|
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 = vectorToAngles( 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 hide_pop();
|
|
level thread zombie_rise_death( self, spot );
|
|
spot thread zombie_rise_fx( self );
|
|
substate = 0;
|
|
if ( self.zombie_move_speed == "walk" )
|
|
{
|
|
substate = randomint( 2 );
|
|
}
|
|
else if ( self.zombie_move_speed == "run" )
|
|
{
|
|
substate = 2;
|
|
}
|
|
else if ( self.zombie_move_speed == "sprint" )
|
|
{
|
|
substate = 3;
|
|
}
|
|
self orientmode( "face default" );
|
|
self animscripted( self.origin, spot.angles, "zm_rise", substate );
|
|
self maps/mp/animscripts/zm_shared::donotetracks( "rise_anim", ::handle_rise_notetracks, spot );
|
|
self notify( "rise_anim_finished" );
|
|
spot notify( "stop_zombie_rise_fx" );
|
|
self.in_the_ground = 0;
|
|
self notify( "risen", spot.script_string );
|
|
}
|
|
|
|
hide_pop() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
wait 0.5;
|
|
if ( isDefined( self ) )
|
|
{
|
|
self show();
|
|
wait_network_frame();
|
|
if ( isDefined( self ) )
|
|
{
|
|
self.create_eyes = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
handle_rise_notetracks( note, spot ) //checked matches cerberus output
|
|
{
|
|
if ( note == "deathout" || note == "deathhigh" )
|
|
{
|
|
self.zombie_rise_death_out = 1;
|
|
self notify( "zombie_rise_death_out" );
|
|
wait 2;
|
|
spot notify( "stop_zombie_rise_fx" );
|
|
}
|
|
}
|
|
|
|
zombie_rise_death( zombie, spot ) //checked matches cerberus output
|
|
{
|
|
zombie.zombie_rise_death_out = 0;
|
|
zombie endon( "rise_anim_finished" );
|
|
while ( isDefined( zombie ) && isDefined( zombie.health ) && zombie.health > 1 )
|
|
{
|
|
zombie waittill( "damage", amount );
|
|
}
|
|
spot notify( "stop_zombie_rise_fx" );
|
|
if ( isDefined( zombie ) )
|
|
{
|
|
zombie.deathanim = zombie get_rise_death_anim();
|
|
zombie stopanimscripted();
|
|
}
|
|
}
|
|
|
|
zombie_rise_fx( zombie ) //checked matches cerberus output
|
|
{
|
|
if ( !is_true( level.riser_fx_on_client ) )
|
|
{
|
|
self thread zombie_rise_dust_fx( zombie );
|
|
self thread zombie_rise_burst_fx( zombie );
|
|
}
|
|
else
|
|
{
|
|
self thread zombie_rise_burst_fx( zombie );
|
|
}
|
|
zombie endon( "death" );
|
|
self endon( "stop_zombie_rise_fx" );
|
|
wait 1;
|
|
if ( zombie.zombie_move_speed != "sprint" )
|
|
{
|
|
wait 1;
|
|
}
|
|
}
|
|
|
|
zombie_rise_burst_fx( zombie ) //checked changed to match cerberus output
|
|
{
|
|
self endon( "stop_zombie_rise_fx" );
|
|
self endon( "rise_anim_finished" );
|
|
if ( isDefined( self.script_parameters ) && self.script_parameters == "in_water" && !is_true( level._no_water_risers ) )
|
|
{
|
|
zombie setclientfield( "zombie_riser_fx_water", 1 );
|
|
}
|
|
else if ( isDefined( self.script_parameters ) && self.script_parameters == "in_foliage" && is_true( level._foliage_risers ) )
|
|
{
|
|
zombie setclientfield( "zombie_riser_fx_foliage", 1 );
|
|
return;
|
|
}
|
|
else if ( isDefined( self.script_parameters ) && self.script_parameters == "in_snow" )
|
|
{
|
|
zombie setclientfield( "zombie_riser_fx", 1 );
|
|
return;
|
|
}
|
|
else if ( isDefined( zombie.zone_name ) && isDefined( level.zones[ zombie.zone_name ] ) )
|
|
{
|
|
low_g_zones = getentarray( zombie.zone_name, "targetname" );
|
|
if ( isDefined( low_g_zones[ 0 ].script_string ) && low_g_zones[ 0 ].script_string == "lowgravity" )
|
|
{
|
|
zombie setclientfield( "zombie_riser_fx_lowg", 1 );
|
|
}
|
|
else
|
|
{
|
|
zombie setclientfield( "zombie_riser_fx", 1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zombie setclientfield( "zombie_riser_fx", 1 );
|
|
}
|
|
}
|
|
|
|
zombie_rise_dust_fx( zombie ) //checked does not match cerberus output did not change
|
|
{
|
|
dust_tag = "J_SpineUpper";
|
|
self endon( "stop_zombie_rise_dust_fx" );
|
|
self thread stop_zombie_rise_dust_fx( zombie );
|
|
wait 2;
|
|
dust_time = 5.5;
|
|
dust_interval = 0.3;
|
|
if ( isDefined( self.script_string ) && self.script_string == "in_water" )
|
|
{
|
|
t = 0;
|
|
while ( t < dust_time )
|
|
{
|
|
playfxontag( level._effect[ "rise_dust_water" ], zombie, dust_tag );
|
|
wait dust_interval;
|
|
t += dust_interval;
|
|
}
|
|
}
|
|
if ( isDefined( self.script_string ) && self.script_string == "in_snow" )
|
|
{
|
|
t = 0;
|
|
while ( t < dust_time )
|
|
{
|
|
playfxontag( level._effect[ "rise_dust_snow" ], zombie, dust_tag );
|
|
wait dust_interval;
|
|
t += dust_interval;
|
|
}
|
|
}
|
|
if ( isDefined( self.script_string ) && self.script_string == "in_foliage" )
|
|
{
|
|
t = 0;
|
|
while ( t < dust_time )
|
|
{
|
|
playfxontag( level._effect[ "rise_dust_foliage" ], zombie, dust_tag );
|
|
wait dust_interval;
|
|
t += dust_interval;
|
|
}
|
|
}
|
|
while ( t < dust_time )
|
|
{
|
|
playfxontag( level._effect[ "rise_dust" ], zombie, dust_tag );
|
|
wait dust_interval;
|
|
t += dust_interval;
|
|
}
|
|
}
|
|
|
|
stop_zombie_rise_dust_fx( zombie ) //checked matches cerberus output
|
|
{
|
|
zombie waittill( "death" );
|
|
self notify( "stop_zombie_rise_dust_fx" );
|
|
}
|
|
|
|
get_rise_death_anim() //checked matches cerberus output
|
|
{
|
|
if ( self.zombie_rise_death_out )
|
|
{
|
|
return "zm_rise_death_out";
|
|
}
|
|
self.noragdoll = 1;
|
|
self.nodeathragdoll = 1;
|
|
return "zm_rise_death_in";
|
|
}
|
|
|
|
zombie_tesla_head_gib() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
if ( self.animname == "quad_zombie" )
|
|
{
|
|
return;
|
|
}
|
|
if ( randomint( 100 ) < level.zombie_vars[ "tesla_head_gib_chance" ] )
|
|
{
|
|
wait randomfloatrange( 0.53, 1 );
|
|
self zombie_head_gib();
|
|
}
|
|
else
|
|
{
|
|
network_safe_play_fx_on_tag( "tesla_death_fx", 2, level._effect[ "tesla_shock_eyes" ], self, "J_Eyeball_LE" );
|
|
}
|
|
}
|
|
|
|
play_ambient_zombie_vocals() //checked changed to match cerberus output
|
|
{
|
|
self endon( "death" );
|
|
if ( self.animname == "monkey_zombie" || isDefined( self.is_avogadro ) && self.is_avogadro )
|
|
{
|
|
return;
|
|
}
|
|
while ( 1 )
|
|
{
|
|
type = "ambient";
|
|
float = 2;
|
|
while ( !isDefined( self.zombie_move_speed ) )
|
|
{
|
|
wait 0.5;
|
|
}
|
|
switch( self.zombie_move_speed )
|
|
{
|
|
case "walk":
|
|
type = "ambient";
|
|
float = 4;
|
|
break;
|
|
case "run":
|
|
type = "sprint";
|
|
float = 4;
|
|
break;
|
|
case "sprint":
|
|
type = "sprint";
|
|
float = 4;
|
|
break;
|
|
}
|
|
if ( self.animname == "zombie" && !self.has_legs )
|
|
{
|
|
type = "crawler";
|
|
}
|
|
else if ( self.animname == "thief_zombie" || self.animname == "leaper_zombie" )
|
|
{
|
|
float = 1.2;
|
|
}
|
|
name = self.animname;
|
|
if ( isDefined( self.sndname ) )
|
|
{
|
|
name = self.sndname;
|
|
}
|
|
self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( type, name );
|
|
wait randomfloatrange( 1, float );
|
|
}
|
|
}
|
|
|
|
zombie_complete_emerging_into_playable_area() //checked matches cerberus output
|
|
{
|
|
self.completed_emerging_into_playable_area = 1;
|
|
self notify( "completed_emerging_into_playable_area" );
|
|
self.no_powerups = 0;
|
|
self thread zombie_free_cam_allowed();
|
|
}
|
|
|
|
zombie_free_cam_allowed() //checked matches cerberus output
|
|
{
|
|
self endon( "death" );
|
|
wait 1.5;
|
|
self setfreecameralockonallowed( 1 );
|
|
}
|
|
|
|
|
|
|