1 #using scripts\codescripts\struct;
3 #using scripts\shared\aat_shared;
4 #using scripts\shared\array_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\flag_shared;
7 #using scripts\shared\spawner_shared;
8 #using scripts\shared\system_shared;
9 #using scripts\shared\trigger_shared;
10 #using scripts\shared\util_shared;
12 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
13 #insert scripts\shared\shared.gsh;
14 #insert scripts\shared\version.gsh;
16 #insert scripts\shared\aat_zm.gsh;
17 #using scripts\zm\_util;
18 #using scripts\zm\_zm;
19 #using scripts\zm\_zm_audio;
20 #using scripts\zm\_zm_net;
21 #using scripts\zm\_zm_powerups;
22 #using scripts\zm\_zm_score;
23 #using scripts\zm\_zm_spawner;
24 #using scripts\zm\_zm_stats;
25 #using scripts\zm\_zm_utility;
27 #using scripts\shared\ai\zombie_utility;
29 #insert scripts\zm\_zm_utility.gsh;
31 #precache( "fx", "zombie/fx_dog_lightning_buildup_zmb" );
32 #precache( "fx", "zombie/fx_dog_eyes_zmb" );
33 #precache( "fx", "zombie/fx_dog_explosion_zmb" );
34 #precache( "fx", "zombie/fx_dog_fire_trail_zmb" );
36 #define ZM_DOGS_HERO_WEAPON_KILL_POWER 2
38 #namespace zm_ai_dogs;
52 level.dogs_enabled =
true;
53 level.dog_rounds_enabled =
false;
54 level.dog_round_count = 1;
56 level.dog_spawners = [];
61 if ( GetDvarString(
"zombie_dog_animset" ) ==
"" )
63 SetDvar(
"zombie_dog_animset",
"zombie" );
66 if ( GetDvarString(
"scr_dog_health_walk_multiplier" ) ==
"" )
68 SetDvar(
"scr_dog_health_walk_multiplier",
"4.0" );
71 if ( GetDvarString(
"scr_dog_run_distance" ) ==
"" )
73 SetDvar(
"scr_dog_run_distance",
"500" );
76 level.melee_range_sav = GetDvarString(
"ai_meleeRange" );
77 level.melee_width_sav = GetDvarString(
"ai_meleeWidth" );
78 level.melee_height_sav = GetDvarString(
"ai_meleeHeight" );
98 level._effect[
"lightning_dog_spawn" ] =
"zombie/fx_dog_lightning_buildup_zmb";
99 level._effect[
"dog_eye_glow" ] =
"zombie/fx_dog_eyes_zmb";
100 level._effect[
"dog_gib" ] =
"zombie/fx_dog_explosion_zmb";
101 level._effect[
"dog_trail_fire" ] =
"zombie/fx_dog_fire_trail_zmb";
109 level.dog_rounds_enabled =
true;
111 if( !isdefined( level.dog_round_track_override ) )
116 level thread [[level.dog_round_track_override]]();
122 level.dog_spawners = getEntArray(
"zombie_dog_spawner",
"script_noteworthy" );
123 later_dogs = getentarray(
"later_round_dog_spawners",
"script_noteworthy" );
124 level.dog_spawners = ArrayCombine( level.dog_spawners, later_dogs,
true,
false );
126 if( level.dog_spawners.size == 0 )
131 for( i = 0; i < level.dog_spawners.size; i++ )
135 level.dog_spawners[i].is_enabled =
false;
139 level.dog_spawners[i].is_enabled =
true;
140 level.dog_spawners[i].script_forcespawn =
true;
144 assert( level.dog_spawners.size > 0 );
145 level.dog_health = 100;
153 level endon(
"intermission" );
154 level endon(
"end_of_round" );
155 level endon(
"restart_round" );
157 level.dog_targets = getplayers();
158 for( i = 0 ; i < level.dog_targets.size; i++ )
160 level.dog_targets[i].hunted_by = 0;
163 level endon(
"kill_round" );
165 if( level.intermission )
170 level.dog_intermission =
true;
172 players = GetPlayers();
178 if( level.dog_round_count < 3 )
180 max = players.size * 6;
184 max = players.size * 8;
187 level.zombie_total = max;
212 players = GetPlayers();
215 if ( isdefined( level.dog_spawn_func ) )
217 spawn_loc = [[level.dog_spawn_func]]( level.dog_spawners, favorite_enemy );
220 if( isdefined( ai ) )
222 ai.favoriteenemy = favorite_enemy;
224 level.zombie_total--;
235 if( isdefined( ai ) )
237 ai.favoriteenemy = favorite_enemy;
239 level.zombie_total--;
254 if( level.dog_round_count == 1)
258 else if( level.dog_round_count == 2)
262 else if( level.dog_round_count == 3)
271 default_wait = default_wait - ( count / max );
273 default_wait = max( default_wait, 0.05 );
275 wait( default_wait );
280 level waittill(
"last_ai_down", e_last );
284 power_up_origin = level.last_dog_origin;
285 if ( isdefined(e_last) )
287 power_up_origin = e_last.origin;
290 if( isdefined( power_up_origin ) )
298 level.dog_intermission =
false;
316 ai SetFreeCameraLockOnAllowed(
false );
319 Playfx( level._effect[
"lightning_dog_spawn"], ent.origin );
320 playsoundatposition(
"zmb_hellhound_prespawn", ent.origin );
322 playsoundatposition(
"zmb_hellhound_bolt", ent.origin );
324 Earthquake( 0.5, 0.75, ent.origin, 1000);
326 playsoundatposition(
"zmb_hellhound_spawn", ent.origin );
329 if ( IsDefined( ai.favoriteenemy ) )
331 angle = VectorToAngles( ai.favoriteenemy.origin - ent.origin );
332 angles = ( ai.angles[0], angle[1], ai.angles[2] );
338 ai ForceTeleport( ent.origin, angles );
341 assert( isdefined( ai ),
"Ent isn't defined." );
342 assert( IsAlive( ai ),
"Ent is dead." );
343 assert( ai.isdog,
"Ent isn't a dog;" );
351 ai SetFreeCameraLockOnAllowed(
true );
353 ai notify(
"visible" );
364 dog_locs = array::randomize( level.zm_loc_types[
"dog_location" ] );
367 for( i = 0; i < dog_locs.size; i++ )
369 if( isdefined( level.old_dog_spawn ) && level.old_dog_spawn == dog_locs[i] )
374 if( !isdefined( favorite_enemy ) )
379 dist_squared = DistanceSquared( dog_locs[i].origin, favorite_enemy.origin );
380 if( dist_squared > ( 400 * 400 ) && dist_squared < ( 1000 * 1000 ) )
382 level.old_dog_spawn = dog_locs[i];
393 dog_targets = getplayers();
394 least_hunted = dog_targets[0];
395 for( i = 0; i < dog_targets.size; i++ )
397 if ( !isdefined( dog_targets[i].hunted_by ) )
399 dog_targets[i].hunted_by = 0;
409 least_hunted = dog_targets[i];
412 if( dog_targets[i].hunted_by < least_hunted.hunted_by )
414 least_hunted = dog_targets[i];
425 least_hunted.hunted_by += 1;
435 players = getplayers();
437 if( level.dog_round_count == 1 )
439 level.dog_health = 400;
441 else if( level.dog_round_count == 2 )
443 level.dog_health = 900;
445 else if( level.dog_round_count == 3 )
447 level.dog_health = 1300;
449 else if( level.dog_round_count == 4 )
451 level.dog_health = 1600;
454 if( level.dog_health > 1600 )
456 level.dog_health = 1600;
465 while( level.dog_intermission )
472 level.sndMusicSpecialRound =
false;
477 level.dog_round_count = 1;
482 level.next_dog_round = level.round_number + randomintrange( 4, 7 );
485 old_spawn_func = level.round_spawn_func;
486 old_wait_func = level.round_wait_func;
490 level waittill (
"between_round_over" );
492 if ( level.round_number == level.next_dog_round )
494 level.sndMusicSpecialRound =
true;
495 old_spawn_func = level.round_spawn_func;
496 old_wait_func = level.round_wait_func;
501 level.next_dog_round = level.round_number + randomintrange( 4, 6 );
506 level.round_spawn_func = old_spawn_func;
507 level.round_wait_func = old_wait_func;
508 level.dog_round_count += 1;
520 level notify(
"dog_round_starting" );
524 if(isdefined(level.dog_melee_range))
526 SetDvar(
"ai_meleeRange", level.dog_melee_range );
530 SetDvar(
"ai_meleeRange", 100 );
541 level notify(
"dog_round_ending" );
544 SetDvar(
"ai_meleeRange", level.melee_range_sav );
545 SetDvar(
"ai_meleeWidth", level.melee_width_sav );
546 SetDvar(
"ai_meleeHeight", level.melee_height_sav );
552 self playlocalsound(
"zmb_dog_round_start" );
557 players = getplayers();
558 num = randomintrange(0,players.size);
565 self.targetname =
"zombie_dog";
566 self.script_noteworthy = undefined;
567 self.animname =
"zombie_dog";
568 self.ignoreall =
true;
569 self.ignoreme =
true;
570 self.allowdeath =
true;
571 self.allowpain =
false;
572 self.force_gib =
true;
573 self.is_zombie =
true;
576 self.head_gibbed =
false;
577 self.default_goalheight = 40;
578 self.ignore_inert =
true;
580 self.holdfire =
true;
584 self.grenadeawareness = 0;
585 self.badplaceawareness = 0;
587 self.ignoreSuppression =
true;
588 self.suppressionThreshold = 1;
589 self.noDodgeMove =
true;
590 self.dontShootWhileMoving =
true;
591 self.pathenemylookahead = 0;
593 self.badplaceawareness = 0;
594 self.chatInitialized =
false;
596 self.team = level.zombie_team;
599 self AllowPitchAngle( 1 );
600 self setPitchOrient();
601 self setAvoidanceMask(
"avoid none" );
603 self PushActors(
true );
605 health_multiplier = 1.0;
606 if ( GetDvarString(
"scr_dog_health_walk_multiplier" ) !=
"" )
608 health_multiplier = GetDvarFloat(
"scr_dog_health_walk_multiplier" );
611 self.maxhealth = int( level.dog_health * health_multiplier );
612 self.health = int( level.dog_health * health_multiplier );
614 self.freezegun_damage = 0;
616 self.zombie_move_speed =
"sprint";
617 self.a.nodeath =
true;
632 self.a.disablePain =
true;
634 self ClearGoalVolume();
636 self.flame_damage_time = 0;
637 self.meleeDamage = 40;
643 if ( isdefined(level.achievement_monitor_func) )
645 self [[level.achievement_monitor_func]]();
651 self waittill(
"death" );
656 level.last_dog_origin =
self.origin;
657 level notify(
"last_ai_down",
self );
662 if( IsPlayer(
self.attacker ) )
665 if (
self.damageweapon.isBallisticKnife )
667 event =
"ballistic_knife_death";
670 if ( !
IS_TRUE(
self.deathpoints_already_given ) )
675 if( isdefined(level.hero_power_update))
677 [[level.hero_power_update]](
self.attacker, self );
680 if( RandomIntRange(0,100) >= 80 )
691 if( isdefined(
self.attacker ) && isai(
self.attacker ) )
693 self.attacker notify(
"killed",
self );
697 self stoploopsound();
702 trace = GroundTrace(
self.origin + ( 0, 0, 10 ),
self.origin - ( 0, 0, 30 ),
false,
self );
703 if (
trace[
"fraction"] < 1 )
705 pitch = Acos( VectorDot(
trace[
"normal"], ( 0, 0, 1 ) ) );
708 self.a.nodeath =
true;
713 if ( isdefined(
self.
a.nodeath ) )
720 self notify(
"bhtn_action_notify",
"death" );
727 PlayFX( level._effect[
"dog_gib"], origin );
728 PlaySoundAtPosition(
"zmb_hellhound_explode", origin );
740 self.ignoreall =
false;
743 self.meleeAttackDist = 64;
746 self.disableArrivals =
true;
747 self.disableExits =
true;
749 if ( isdefined( level.dog_setup_func ) )
751 self [[level.dog_setup_func]]();
759 self waittill(
"death");
770 self notify(
"bhtn_action_notify",
"close" );
775 players = GetPlayers();
776 for(i=0;i<players.size;i++)
778 dogAngle = AngleClamp180( vectorToAngles(
self.origin - players[i].origin )[1] - players[i].angles[1] );
780 if(isAlive(players[i]) && !isdefined(players[i].revivetrigger))
782 if ((abs(dogAngle) > 90) && distance2d(
self.origin,players[i].origin) > 100)
784 self notify(
"bhtn_action_notify",
"close" );
800 level.dog_clips = GetEntArray(
"dog_clips",
"targetname" );
803 for ( i=0; i<level.dog_clips.size; i++ )
806 level.dog_clips[i] ConnectPaths();
811 if(isdefined(level.no_dog_clip) && level.no_dog_clip ==
true)
816 for ( i=0; i<level.dog_clips.size; i++ )
819 level.dog_clips[i] DisconnectPaths();
824 while ( dog_is_alive || level
flag::get(
"dog_round" ) )
826 dog_is_alive =
false;
827 dogs = GetEntArray(
"zombie_dog",
"targetname" );
828 for ( i=0; i<dogs.size; i++ )
830 if ( IsAlive(dogs[i]) )
847 dogs = GetAISpeciesArray(
"all",
"zombie_dog" );
849 if ( isdefined( dogs ) && dogs.size >= 9 )
854 if ( !isdefined(num_to_spawn) )
859 spawn_point = undefined;
861 while ( count < num_to_spawn )
864 players = GetPlayers();
867 if ( isdefined( spawners ) )
869 if ( !isdefined( spawn_point ) )
871 spawn_point = spawners[ RandomInt(spawners.size) ];
875 if( isdefined( ai ) )
877 ai.favoriteenemy = favorite_enemy;
885 if ( isdefined( level.dog_spawn_func ) )
887 spawn_loc = [[level.dog_spawn_func]]( level.dog_spawners, favorite_enemy );
890 if( isdefined( ai ) )
892 ai.favoriteenemy = favorite_enemy;
904 if( isdefined( ai ) )
906 ai.favoriteenemy = favorite_enemy;
922 self endon(
"death" );
927 self waittill(
"visible" );
930 if (
self.health > level.dog_health )
932 self.maxhealth = level.dog_health;
933 self.health = level.dog_health;
938 self playloopsound(
"zmb_hellhound_loop_fire" );
948 if( isdefined( level.custom_dog_target_validity_check ) )
950 self [[ level.custom_dog_target_validity_check ]]();
959 self endon(
"death" );
960 self endon(
"dog_running" );
961 self endon(
"dog_combat" );
965 self notify(
"bhtn_action_notify",
"ambient" );
966 wait randomfloatrange(2,4);
972 self endon(
"death" );
974 damage = int(
self.maxhealth * 0.5 );
975 self DoDamage(
damage, player.origin, player );