1 #using scripts\codescripts\struct;
3 #using scripts\shared\ai_shared;
4 #using scripts\shared\array_shared;
5 #using scripts\shared\callbacks_shared;
6 #using scripts\shared\clientfield_shared;
7 #using scripts\shared\fx_shared;
8 #using scripts\shared\math_shared;
9 #using scripts\shared\scene_shared;
10 #using scripts\shared\spawner_shared;
11 #using scripts\shared\util_shared;
12 #using scripts\shared\visionset_mgr_shared;
13 #using scripts\shared\_burnplayer;
15 #using scripts\shared\ai\systems\animation_state_machine_utility;
16 #using scripts\shared\ai\systems\animation_state_machine_notetracks;
17 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
18 #using scripts\shared\ai\archetype_utility;
19 #using scripts\shared\ai\systems\behavior_tree_utility;
20 #using scripts\shared\ai\systems\blackboard;
21 #using scripts\shared\ai\systems\debug;
22 #using scripts\shared\ai\systems\gib;
23 #using scripts\shared\ai\zombie_utility;
24 #using scripts\shared\ai\archetype_mocomps_utility;
26 #using scripts\shared\weapons\_weaponobjects;
28 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
29 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
30 #insert scripts\shared\ai\systems\behavior.gsh;
31 #insert scripts\shared\ai\systems\behavior_tree.gsh;
32 #insert scripts\shared\ai\systems\blackboard.gsh;
33 #insert scripts\shared\ai\systems\gib.gsh;
34 #insert scripts\shared\ai\mechz.gsh;
35 #insert scripts\shared\ai\utility.gsh;
36 #insert scripts\shared\shared.gsh;
37 #insert scripts\shared\version.gsh;
39 #precache( "xmodel", MECHZ_MODEL_ARMOR_KNEE_LEFT );
40 #precache( "xmodel", MECHZ_MODEL_ARMOR_KNEE_RIGHT );
41 #precache( "xmodel", MECHZ_MODEL_ARMOR_SHOULDER_LEFT );
42 #precache( "xmodel", MECHZ_MODEL_ARMOR_SHOULDER_RIGHT );
43 #precache( "xmodel", MECHZ_MODEL_FACEPLATE );
44 #precache( "xmodel", MECHZ_MODEL_POWERSUPPLY );
45 #precache( "xmodel", MECHZ_MODEL_CLAW );
47 #define PERK_JUGGERNOG "specialty_armorvest"
49 #namespace MechzBehavior;
142 entity.__blackboard = undefined;
150 if( IsDefined(
self.should_turn ) &&
self.should_turn )
162 if( isDefined( entity.mechz_melee_knockdown_function ))
164 entity thread [[ entity.mechz_melee_knockdown_function ]]();
171 if ( !IsDefined( entity.enemy ) )
179 base_target_pos = entity.enemy.origin;
180 v_velocity = entity.enemy GetVelocity();
186 target_pos = base_target_pos + ( target_pos_offset_x, target_pos_offset_y, 0 );
188 dir = VectorToAngles( target_pos - entity.origin );
190 dir = AnglesToForward( dir );
192 launch_offset = (dir * 5);
196 dist = Distance( launch_pos, target_pos );
198 velocity = dir * dist;
199 velocity = velocity + (0,0,120);
212 PlaySoundAtPosition (
"wpn_grenade_fire_mechz", entity.origin);
225 if ( IsDefined( entity.destroy_octobomb ) )
232 entity.favoriteenemy = player;
234 if( !IsDefined( player ) || player IsNoTarget() )
236 if( IsDefined( entity.ignore_player ) )
238 if(isDefined(level._should_skip_ignore_player_logic) && [[level._should_skip_ignore_player_logic]]() )
242 entity.ignore_player = [];
245 /#
if (
IS_TRUE( level.b_mechz_true_ignore ) )
247 entity SetGoal( entity.origin );
251 if( isdefined( level.no_target_override ) )
253 [[ level.no_target_override ]]( entity );
257 entity SetGoal( entity.origin );
265 if( isDefined( level.enemy_location_override_func ))
267 enemy_ground_pos = [[level.enemy_location_override_func]]( entity, player);
268 if( isDefined( enemy_ground_pos ))
270 entity SetGoal( enemy_ground_pos);
276 if ( IsDefined( targetPos ) )
278 entity SetGoal( targetPos );
283 entity SetGoal( entity.origin );
291 if( !isDefined( entity.burstGrenadesFired ))
293 entity.burstGrenadesFired = 0;
298 if ( GetTime() > entity.nextGrenadeTime )
300 entity.burstGrenadesFired = 0;
304 if( isDefined( level.a_electroball_grenades ))
309 entity.activeGrenades = a_active_grenades.size;
313 entity.activeGrenades = 0;
320 if( grenade.owner === mechz )
331 velocity = entity GetVelocity();
333 predicted_pos = entity.origin + ( velocity * predict_time );
334 move_dist_sq = DistanceSquared( predicted_pos, entity.origin );
335 speed = move_dist_sq / predict_time;
343 if( a_filtered_zombies.size > 0 )
345 foreach( zombie
in a_filtered_zombies )
347 zombie.knockdown =
true;
349 zombie_to_mechz = entity.origin - zombie.origin;
350 zombie_to_mechz_2d = VectorNormalize( ( zombie_to_mechz[0], zombie_to_mechz[1], 0 ) );
352 zombie_forward = AnglesToForward( zombie.angles );
353 zombie_forward_2d = VectorNormalize( ( zombie_forward[0], zombie_forward[1], 0 ) );
355 zombie_right = AnglesToRight( zombie.angles );
356 zombie_right_2d = VectorNormalize( ( zombie_right[0], zombie_right[1], 0 ) );
358 dot = VectorDot( zombie_to_mechz_2d, zombie_forward_2d );
362 zombie.knockdown_direction =
"front";
365 else if ( dot < 0.5 && dot > -0.5 )
367 dot = VectorDot( zombie_to_mechz_2d, zombie_right_2d );
370 zombie.knockdown_direction =
"right";
383 zombie.knockdown_direction =
"left";
389 zombie.knockdown_direction =
"back";
399 if( zombie.knockdown ===
true )
404 knockdown_dist_sq = 48*48;
406 dist_sq = DistanceSquared( predicted_pos, zombie.origin );
408 if( dist_sq > knockdown_dist_sq )
413 if( zombie.is_immune_to_knockdown ===
true )
418 origin = mechz.origin;
420 facing_vec = AnglesToForward( mechz.angles );
421 enemy_vec = zombie.origin - origin;
423 enemy_yaw_vec = (enemy_vec[0], enemy_vec[1], 0);
424 facing_yaw_vec = (facing_vec[0], facing_vec[1], 0);
426 enemy_yaw_vec = VectorNormalize( enemy_yaw_vec );
427 facing_yaw_vec = VectorNormalize( facing_yaw_vec );
429 enemy_dot = VectorDot( facing_yaw_vec, enemy_yaw_vec );
445 if( !IsDefined( entity.enemy ) )
456 if(
IS_TRUE( entity.enemy.usingvehicle ) )
461 yaw = abs( zombie_utility::getYawToEnemy() );
472 if( entity.partDestroyed ===
true )
483 if( entity.berserk ===
true )
488 if( entity.gun_attached !==
true )
493 if ( !IsDefined( entity.favoriteenemy ) )
513 if( !entity CanSee( entity.favoriteenemy ) )
518 dist_sq = DistanceSquared( entity.origin, entity.favoriteenemy.origin );
530 if (
IS_TRUE( entity.shoot_flame ) )
536 if( entity.berserk ===
true )
541 if (
IS_TRUE( entity.isShootingFlame ) && GetTime() < entity.stopShootingFlameTime )
546 if ( !IsDefined( entity.favoriteenemy ) )
551 if( entity.isShootingFlame ===
true && entity.stopShootingFlameTime <= GetTime() )
556 if ( entity.nextFlameTime > GetTime() )
566 dist_sq = DistanceSquared( entity.origin, entity.favoriteenemy.origin );
572 can_see = BulletTracePassed( entity.origin + ( 0, 0, 36 ), entity.favoriteenemy.origin + ( 0, 0, 36 ),
false, undefined );
583 if( entity.berserk ===
true )
599 players = GetPlayers();
601 foreach( player
in players )
609 if ( near_players < 2 )
619 if( entity.berserk ===
true && entity.hasTurnedBerserk !==
true )
654 entity.grenadeStartTime = GetTime() + 3000;
661 if ( !
IS_TRUE( entity.shoot_grenade ) )
680 if ( GetTime() > entity.stunTime )
707 if ( GetTime() > entity.stumbleTime )
717 entity.stumble =
false;
747 if (
IS_TRUE( entity.isShootingFlame ) )
749 if ( IsDefined( entity.stopShootingFlameTime ) && GetTime() > entity.stopShootingFlameTime )
774 entity.burstGrenadesFired ++;
788 self endon(
"death" );
790 self notify(
"mechzDelayFlame" );
791 self endon(
"mechzDelayFlame" );
796 self.isShootingFlame =
true;
802 if( IsDefined( level.mechz_flamethrower_player_callback ) )
804 [[level.mechz_flamethrower_player_callback]]( entity );
808 players = GetPlayers();
810 foreach( player
in players )
812 if ( !
IS_TRUE( player.is_burning ) )
814 if ( player IsTouching( entity.flameTrigger ) )
816 if ( IsDefined( entity.mechzFlameDamage ) )
818 player thread [[ entity.mechzFlameDamage ]]();
829 if( IsDefined( level.mechz_flamethrower_ai_callback ) )
831 [[level.mechz_flamethrower_ai_callback]](entity);
837 self endon(
"death" );
838 self endon(
"disconnect" );
861 self notify(
"mechzDelayFlame" );
864 entity.isShootingFlame =
false;
866 entity.stopShootingFlameTime = undefined;
878 if( entity.berserk !==
true )
880 entity.berserk =
true;
881 entity thread mechzEndBerserk();
888 entity.hasTurnedBerserk =
true;
893 self endon(
"death" );
894 self endon(
"disconnect" );
896 While(
self.berserk ===
true )
898 if( GetTime() >=
self.berserkEndTime )
900 self.berserk =
false;
901 self.hasTurnedBerserk =
false;
903 self ASMSetAnimationRate( 1.0 );
934 entity.partDestroyed =
false;
935 entity.show_pain_from_explosive_dmg = undefined;
944 #namespace MechzServerUtils;
948 self DisableAimAssist();
950 self.disableAmmoDrop =
true;
952 self.ignore_nuke =
true;
953 self.ignore_enemy_count =
true;
954 self.ignore_round_robbin_death =
true;
956 self.zombie_move_speed =
"run";
959 self.ignoreRunAndGunDist =
true;
965 self.nextFlameTime = GetTime();
966 self.stumble_stun_cooldown_time = GetTime();
969 self.debug_traversal_ast =
"traverse@mechz";
972 self.flameTrigger =
Spawn(
"trigger_box",
self.origin, 0, 200, 50, 25 );
973 self.flameTrigger EnableLinkTo();
975 self.flameTrigger.origin =
self GetTagOrigin(
MECHZ_FT_TAG );
976 self.flameTrigger.angles =
self GetTagAngles(
MECHZ_FT_TAG );
984 self.pers[
"team"] =
self.team;
991 self endon(
"death" );
995 if ( IsDefined(
self.favoriteenemy ) )
997 if (
self.flameTrigger IsTouching(
self.favoriteenemy ) )
999 /# PrintTopRightLn(
"flame on" ); #/
1010 self.has_left_knee_armor =
true;
1013 self.has_right_knee_armor =
true;
1016 self.has_left_shoulder_armor =
true;
1019 self.has_right_shoulder_armor =
true;
1025 self.gun_attached =
true;
1027 self.has_faceplate =
true;
1030 self.has_powercap =
true;
1031 self.powercap_covered =
true;
1036 function mechzDamageCallback( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex )
1038 if( isDefined(
self.b_flyin_done ) && !
IS_TRUE(
self.b_flyin_done ) )
1043 if ( isDefined( level.mechz_should_stun_override ) && !(
IS_TRUE(
self.stun ) ||
IS_TRUE(
self.stumble ) ) )
1045 if (
self.stumble_stun_cooldown_time < GetTime() && !
IS_TRUE(
self.berserk) )
1047 self [[level.mechz_should_stun_override]]( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
1059 if( isdefined( level.mechz_damage_override ) )
1065 if( !isDefined(
self.next_pain_time ) || GetTime() >=
self.next_pain_time )
1068 self.next_pain_time = GetTime() + 250 + RandomInt( 500 );
1071 if( isDefined(
self.damage_scoring_function ))
1073 self [[
self.damage_scoring_function ]]( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
1076 if( IsDefined( level.mechz_staff_damage_override ) )
1078 staffDamage = [[ level.mechz_staff_damage_override ]]( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
1080 if( staffDamage > 0 )
1082 n_mechz_damage_percent = 0.5;
1085 if( !
IS_TRUE(
self.has_faceplate ) && n_mechz_damage_percent < 1.0 )
1087 n_mechz_damage_percent = 1.0;
1090 staffDamage = staffDamage * n_mechz_damage_percent;
1092 if(
IS_TRUE(
self.has_faceplate ) )
1097 /#iPrintLnBold(
"Staff DMG: " + staffDamage +
". HP: " + (
self.health - staffDamage ) );#/
1099 DEFAULT(
self.explosive_dmg_taken, 0 );
1100 self.explosive_dmg_taken += staffDamage;
1102 if( IsDefined( level.mechz_explosive_damage_reaction_callback ) )
1104 self [[ level.mechz_explosive_damage_reaction_callback ]]();
1111 if( IsDefined( level.mechz_explosive_damage_reaction_callback ) )
1113 if( isDefined( mod ) && mod ==
"MOD_GRENADE" || mod ==
"MOD_GRENADE_SPLASH" || mod ==
"MOD_PROJECTILE" || mod ==
"MOD_PROJECTILE_SPLASH" || mod ==
"MOD_EXPLOSIVE" )
1115 n_mechz_damage_percentage = 0.5;
1116 if( isDefined( attacker ) && IsPlayer( attacker ) && IsAlive( attacker ) && ( level.zombie_vars[attacker.team][
"zombie_insta_kill"] ||
IS_TRUE( attacker.personal_instakill )) )
1118 n_mechz_damage_percentage = 1.0;
1121 explosive_damage =
damage * n_mechz_damage_percentage;
1123 DEFAULT(
self.explosive_dmg_taken, 0 );
1124 self.explosive_dmg_taken += explosive_damage;
1126 if(
IS_TRUE(
self.has_faceplate ) )
1131 self [[ level.mechz_explosive_damage_reaction_callback ]]();
1133 /#iPrintLnBold(
"Explosive DMG: " + explosive_damage +
". HP: " + (
self.health - explosive_damage ) );#/
1135 return explosive_damage;
1139 if ( hitLoc ==
"head" )
1142 /#iPrintLnBold(
"Head DMG: " +
damage +
". HP: " + (
self.health -
damage ) );#/
1146 if( hitloc !==
"none" )
1151 if(
self.has_faceplate ==
true )
1154 dist_sq = DistanceSquared( faceplate_pos, point );
1156 if( dist_sq <= 144 )
1162 headlamp_dist_sq = DistanceSquared( point,
self GetTagOrigin(
"tag_headlamp_FX" ));
1163 if( headlamp_dist_sq <= 9 )
1181 /#iPrintLnBold(
"PowerCore/Supply DMG: " +
damage +
". HP: " + (
self.health -
damage ) );#/
1209 case "left_leg_lower":
1220 case "right_leg_lower":
1232 case "left_arm_lower":
1233 case "left_arm_upper":
1234 if ( IsDefined( level.mechz_left_arm_damage_callback ) )
1236 self [[ level.mechz_left_arm_damage_callback ]]();
1251 if ( mod ==
"MOD_PROJECTILE" )
1255 if(
self.has_faceplate !==
true )
1257 head_pos =
self GetTagOrigin(
"tag_eye" );
1258 dist_sq = DistanceSquared( head_pos, point );
1260 if( dist_sq <= 144 )
1262 /#iPrintLnBold(
"Projectile head DMG: " +
damage +
". HP: " + (
self.health -
damage ) );#/
1269 if(
self.has_faceplate ===
true )
1272 dist_sq = DistanceSquared( faceplate_pos, point );
1274 if( dist_sq <= 144 )
1280 headlamp_dist_sq = DistanceSquared( point,
self GetTagOrigin(
"tag_headlamp_FX" ));
1281 if( headlamp_dist_sq <= 9 )
1289 power_dist_sq = DistanceSquared( power_pos, point );
1291 if( power_dist_sq <= 25 )
1293 if(
self.powercap_covered !==
true &&
self.has_powercap !==
true )
1295 /#iPrintLnBold(
"Projectile powercap DMG: " +
damage +
". HP: " + (
self.health -
damage ) );#/
1300 if(
self.powercap_covered !==
true &&
self.has_powercap ===
true )
1304 /#iPrintLnBold(
"Projectile powercap DMG: " +
damage +
". HP: " + (
self.health -
damage ) );#/
1308 if(
self.powercap_covered ===
true )
1315 if(
self.has_right_shoulder_armor ===
true )
1318 dist_sq = DistanceSquared( armor_pos, point );
1326 if(
self.has_left_shoulder_armor ===
true )
1329 dist_sq = DistanceSquared( armor_pos, point );
1337 if(
self.has_right_knee_armor ===
true )
1340 dist_sq = DistanceSquared( armor_pos, point );
1348 if(
self.has_left_knee_armor ===
true )
1351 dist_sq = DistanceSquared( armor_pos, point );
1359 /#iPrintLnBold(
"Projectile DMG: " + hit_damage +
". HP: " + (
self.health - hit_damage ) );#/
1362 else if ( mod ==
"MOD_PROJECTILE_SPLASH" )
1367 i_num_armor_pieces = 0;
1369 if( isDefined( level.mechz_faceplate_damage_override ))
1371 self [[level.mechz_faceplate_damage_override]]( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
1374 if(
self.has_right_shoulder_armor ===
true )
1376 i_num_armor_pieces += 1;
1377 right_shoulder_index = i_num_armor_pieces;
1380 if(
self.has_left_shoulder_armor ===
true )
1382 i_num_armor_pieces += 1;
1383 left_shoulder_index = i_num_armor_pieces;
1386 if(
self.has_right_knee_armor ===
true )
1388 i_num_armor_pieces += 1;
1389 right_knee_index = i_num_armor_pieces;
1392 if(
self.has_left_knee_armor ===
true )
1394 i_num_armor_pieces += 1;
1395 left_knee_index = i_num_armor_pieces;
1398 if( i_num_armor_pieces > 0 )
1400 if( i_num_armor_pieces <= 1 )
1406 i_random = RandomInt( i_num_armor_pieces - 1 );
1411 if(
self.has_right_shoulder_armor ===
true && right_shoulder_index === i_random )
1416 if(
self.has_left_shoulder_armor ===
true && left_shoulder_index === i_random )
1421 if(
self.has_right_knee_armor ===
true && right_knee_index === i_random )
1426 if(
self.has_left_knee_armor ===
true && left_knee_index === i_random )
1433 if(
self.powercap_covered ===
true )
1438 if(
self.has_faceplate ==
true )
1444 /#iPrintLnBold(
"Projectile Splash DMG: " + hit_damage +
". HP: " + (
self.health - hit_damage ) );#/
1454 if( isDefined( weapon) && isDefined( weapon.name ) )
1456 if( isSubStr( weapon.name,
"shotgun_fullauto") )
1461 if( isSubStr( weapon.name,
"lmg_cqb") )
1466 if( isSubStr( weapon.name,
"lmg_heavy") )
1471 if( isSubStr( weapon.name,
"shotgun_precision") )
1476 if( isSubstr( weapon.name,
"shotgun_semiauto") )
1488 self playsound(
"zmb_ai_mechz_destruction" );
1493 if ( IsDefined(
self ) && IsDefined(
self.hud_damagefeedback ) )
1495 self.hud_damagefeedback SetShader(
"damage_feedback", 24, 48 );
1496 self.hud_damagefeedback.alpha = 1;
1497 self.hud_damagefeedback FadeOverTime(1);
1498 self.hud_damagefeedback.alpha = 0;
1504 if (
self HasPart(strTag) )
1506 self HidePart(strTag);
1513 self.faceplate_health =
self.faceplate_health -
damage;
1514 if(
self.faceplate_health <= 0 )
1518 self.has_faceplate =
false;
1520 self.partDestroyed =
true;
1525 level notify(
"mechz_faceplate_detached" );
1531 self.powercap_cover_health =
self.powercap_cover_health -
damage;
1532 if(
self.powercap_cover_health <= 0 )
1536 self.powercap_covered =
false;
1537 self.partDestroyed =
true;
1547 self.powercap_health =
self.powercap_health -
damage;
1548 if(
self.powercap_health <=0 )
1550 if( IsDefined( level.mechz_powercap_destroyed_callback ) )
1552 self [[level.mechz_powercap_destroyed_callback]]();
1563 self.has_powercap =
false;
1564 self.gun_attached =
false;
1565 self.partDestroyed =
true;
1570 level notify(
"mechz_gun_detached" );
1576 self.right_knee_armor_health =
self.right_knee_armor_health -
damage;
1577 if(
self.right_knee_armor_health <= 0 )
1581 self.has_right_knee_armor =
false;
1588 self.left_knee_armor_health =
self.left_knee_armor_health -
damage;
1589 if(
self.left_knee_armor_health <= 0 )
1593 self.has_left_knee_armor =
false;
1600 self.right_shoulder_armor_health =
self.right_shoulder_armor_health -
damage;
1601 if(
self.right_shoulder_armor_health <= 0 )
1605 self.has_right_shoulder_armor =
false;
1612 self.left_shoulder_armor_health =
self.left_shoulder_armor_health -
damage;
1613 if(
self.left_shoulder_armor_health <= 0 )
1617 self.has_left_shoulder_armor =
false;
1624 origin =
self.origin;
1625 angles =
self.angles;
1627 if ( IsDefined( aim_tag ) )
1629 origin =
self GetTagOrigin( aim_tag );
1630 angles =
self GetTagAngles( aim_tag );
1633 if ( IsDefined( right_offset ) )
1635 right_angle = anglestoright( angles );
1636 origin = origin + (right_angle * right_offset);
1639 facing_vec = AnglesToForward( angles );
1640 enemy_vec =
self.favoriteenemy.origin - origin;
1642 enemy_yaw_vec = (enemy_vec[0], enemy_vec[1], 0);
1643 facing_yaw_vec = (facing_vec[0], facing_vec[1], 0);
1645 enemy_yaw_vec = VectorNormalize( enemy_yaw_vec );
1646 facing_yaw_vec = VectorNormalize( facing_yaw_vec );
1648 enemy_dot = VectorDot( facing_yaw_vec, enemy_yaw_vec );
1655 enemy_angles = VectorToAngles( enemy_vec );
1667 origin =
self.origin;
1668 if ( IsDefined( right_offset ) )
1670 right_angle = anglestoright(
self.angles );
1671 origin = origin + (right_angle * right_offset);
1674 facing_vec = AnglesToForward(
self.angles );
1675 enemy_vec =
self.favoriteenemy.origin - origin;
1677 enemy_yaw_vec = (enemy_vec[0], enemy_vec[1], 0);
1678 facing_yaw_vec = (facing_vec[0], facing_vec[1], 0);
1680 enemy_yaw_vec = VectorNormalize( enemy_yaw_vec );
1681 facing_yaw_vec = VectorNormalize( facing_yaw_vec );
1683 enemy_dot = VectorDot( facing_yaw_vec, enemy_yaw_vec );
1690 enemy_angles = VectorToAngles( enemy_vec );
1703 if( headlamp_broken !==
true )