1 #using scripts\codescripts\struct;
3 #using scripts\shared\array_shared;
4 #using scripts\shared\callbacks_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\laststand_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\weapons\_weaponobjects;
11 #insert scripts\shared\shared.gsh;
12 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
14 #using scripts\shared\ai\zombie_death;
15 #using scripts\shared\ai\zombie_utility;
17 #using scripts\zm\_util;
18 #using scripts\zm\_zm;
19 #using scripts\zm\_zm_audio;
20 #using scripts\zm\_zm_equipment;
21 #using scripts\zm\_zm_laststand;
22 #using scripts\zm\_zm_spawner;
23 #using scripts\zm\_zm_stats;
24 #using scripts\zm\_zm_unitrigger;
25 #using scripts\zm\_zm_utility;
26 #using scripts\zm\_zm_weapons;
28 #insert scripts\zm\_zm_buildables.gsh;
29 #insert scripts\zm\_zm_utility.gsh;
30 #insert scripts\shared\version.gsh;
32 #define HINT_ICON "riotshield_zm_icon"
33 #define GROUND_LEVEL 0
35 #define RIOTSHIELD_HEALTH_CLIENTFIELD "zmInventory.shield_health"
38 #precache( "material", HINT_ICON );
39 #precache( "string", "ZOMBIE_EQUIP_RIOTSHIELD_PICKUP_HINT_STRING" );
41 #namespace riotshield;
47 DEFAULT(level.weaponRiotshield,GetWeapon(
"riotshield" ));
69 level.riotshield_network_choke_count=0;
70 level.riotshield_gib_refs = [];
71 level.riotshield_gib_refs[level.riotshield_gib_refs.size] =
"guts";
72 level.riotshield_gib_refs[level.riotshield_gib_refs.size] =
"right_arm";
73 level.riotshield_gib_refs[level.riotshield_gib_refs.size] =
"left_arm";
119 orientation =
self getPlayerAngles();
120 forwardVec = anglesToForward( orientation );
121 forwardVec2D = ( forwardVec[0], forwardVec[1], 0 );
122 unitForwardVec2D = VectorNormalize( forwardVec2D );
125 toFaceeVec2D = ( toFaceeVec[0], toFaceeVec[1], 0 );
126 unitToFaceeVec2D = VectorNormalize( toFaceeVec2D );
128 dotProduct = VectorDot( unitForwardVec2D, unitToFaceeVec2D );
129 return ( dotProduct >
limit );
135 if (
IS_TRUE(
self.hasRiotShield) && IsDefined(vDir) )
137 if ( isDefined( eAttacker ) && (
IS_TRUE(eAttacker.is_zombie) || IsPlayer(eAttacker)) )
139 if (
IS_TRUE(
self.hasRiotShieldEquipped) )
147 else if ( !IsDefined(
self.riotshieldEntity ))
152 return level.zombie_vars[
"riotshield_stowed_block_fraction"];
157 Assert(!IsDefined(
self.riotshieldEntity ),
"Planted riotshield no longer supported.");
168 friendly_fire = ( IsDefined( eAttacker ) && eAttacker.team ===
self.team );
169 if (
IS_TRUE(
self.hasRiotShield) && !friendly_fire )
171 fBlockFraction =
self [[level.should_shield_absorb_damage]] ( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
172 if ( fBlockFraction > 0.0 && isdefined(
self.player_shield_apply_damage) )
174 iBlocked = int( fBlockFraction * iDamage );
175 iUnblocked = iDamage-iBlocked;
176 if ( isdefined(
self.player_shield_apply_damage) )
178 self [[
self.player_shield_apply_damage]]( iBlocked,
false, sHitLoc==
"riotshield", sMeansOfDeath );
179 if( isdefined(
self.riotshield_damage_absorb_callback ) )
181 self [[
self.riotshield_damage_absorb_callback]]( eAttacker, iBlocked, sHitLoc, sMeansOfDeath );
193 damageMax = level.weaponRiotshield.weaponstarthitpoints;
194 if ( IsDefined(
self.weaponRiotshield) )
195 damageMax =
self.weaponRiotshield.weaponstarthitpoints;
196 shieldHealth = damageMax;
197 shieldDamage = iDamage;
201 shieldHealth =
self DamageRiotShield(shieldDamage);
203 if( shieldHealth <= 0 )
207 self PlayRumbleOnEntity(
"damage_heavy" );
208 Earthquake( 1.0, 0.75,
self.origin, 100 );
216 self PlayRumbleOnEntity(
"damage_light" );
217 Earthquake( 0.5, 0.5,
self.origin, 100 );
219 self PlaySound(
"fly_riotshield_zm_impact_zombies" );
236 self waittill(
"weapon_change", weapon );
251 self waittill(
"weapon_melee", weapon );
252 if ( weapon.isriotshield )
253 self [[level.riotshield_melee]]( weapon );
261 self waittill(
"weapon_melee_power", weapon );
262 if ( weapon.isriotshield )
263 self [[level.riotshield_melee_power]]( weapon );
269 if( !IsDefined(
self ) || !IsAlive(
self ) )
275 if (
IS_TRUE(
self.ignore_riotshield))
278 if ( IsDefined(
self.riotshield_fling_func ) )
280 self [[
self.riotshield_fling_func ]]( player );
287 self DoDamage(
damage, player.origin, player, player,
"",
"MOD_IMPACT" );
288 if (
self.health < 1 )
290 self.riotshield_death =
true;
291 self StartRagdoll(
true );
292 self LaunchRagdoll( fling_vec );
300 damage = level.zombie_vars[
"riotshield_knockdown_damage"];
301 if(isDefined(level.override_riotshield_damage_func))
303 self[[level.override_riotshield_damage_func]](player,
gib);
309 self.a.gib_ref = array::random( level.riotshield_gib_refs );
313 self DoDamage(
damage, player.origin, player );
322 self endon(
"death" );
323 playsoundatposition (
"vox_riotshield_forcehit",
self.origin);
324 playsoundatposition (
"wpn_riotshield_proj_impact",
self.origin);
327 if( !IsDefined(
self ) || !IsAlive(
self ) )
333 if ( IsDefined(
self.riotshield_knockdown_func ) )
335 self [[
self.riotshield_knockdown_func ]]( player,
gib );
345 self DoDamage( level.zombie_vars[
"riotshield_knockdown_damage"], player.origin, player );
346 self playsound(
"fly_riotshield_forcehit" );
352 view_pos =
self geteye();
353 zombies = array::get_all_closest( view_pos, GetAITeamArray( level.zombie_team ), undefined, undefined, 2 * level.zombie_vars[
"riotshield_knockdown_range"] );
354 if ( !isDefined( zombies ) )
359 knockdown_range_squared = level.zombie_vars[
"riotshield_knockdown_range"] * level.zombie_vars[
"riotshield_knockdown_range"];
360 gib_range_squared = level.zombie_vars[
"riotshield_gib_range"] * level.zombie_vars[
"riotshield_gib_range"];
361 fling_range_squared = level.zombie_vars[
"riotshield_fling_range"] * level.zombie_vars[
"riotshield_fling_range"];
362 cylinder_radius_squared = level.zombie_vars[
"riotshield_cylinder_radius"] * level.zombie_vars[
"riotshield_cylinder_radius"];
364 fling_force = level.zombie_vars[
"riotshield_fling_force_melee"];
367 forward_view_angles =
self GetWeaponForwardDir();
368 end_pos = view_pos + VectorScale( forward_view_angles, level.zombie_vars[
"riotshield_knockdown_range"] );
370 for ( i = 0; i < zombies.size; i++ )
372 if ( !IsDefined( zombies[i] ) || !IsAlive( zombies[i] ) )
383 test_origin = zombies[i] getcentroid();
385 test_range_squared = DistanceSquared( view_pos, test_origin );
386 if ( test_range_squared > knockdown_range_squared )
392 normal = VectorNormalize( test_origin - view_pos );
393 dot = VectorDot( forward_view_angles, normal );
401 radial_origin = PointOnSegmentNearestToPoint( view_pos, end_pos, test_origin );
402 if ( DistanceSquared( test_origin, radial_origin ) > cylinder_radius_squared )
409 if ( 0 == zombies[i] DamageConeTrace( view_pos,
self ) )
416 if ( test_range_squared < fling_range_squared )
418 level.riotshield_fling_enemies[level.riotshield_fling_enemies.size] = zombies[i];
421 dist_mult = (fling_range_squared - test_range_squared) / fling_range_squared;
422 fling_vec = VectorNormalize( test_origin - view_pos );
425 if ( 5000 < test_range_squared )
427 fling_vec = fling_vec + VectorNormalize( test_origin - radial_origin );
429 fling_vec = (fling_vec[0], fling_vec[1], fling_force_v * abs( fling_vec[2] ));
430 fling_vec = VectorScale( fling_vec, fling_force + fling_force * dist_mult );
431 level.riotshield_fling_vecs[level.riotshield_fling_vecs.size] = fling_vec;
447 level.riotshield_knockdown_enemies[level.riotshield_knockdown_enemies.size] = zombies[i];
448 level.riotshield_knockdown_gib[level.riotshield_knockdown_gib.size] =
false;
459 level.riotshield_network_choke_count++;
461 if ( !(level.riotshield_network_choke_count % 10) )
475 if ( !IsDefined( level.riotshield_knockdown_enemies ) )
477 level.riotshield_knockdown_enemies = [];
478 level.riotshield_knockdown_gib = [];
479 level.riotshield_fling_enemies = [];
480 level.riotshield_fling_vecs = [];
489 level.riotshield_network_choke_count = 0;
490 for ( i = 0; i < level.riotshield_fling_enemies.size; i++ )
493 if (isdefined(level.riotshield_fling_enemies[i]))
496 shield_damage += level.zombie_vars[
"riotshield_fling_damage_shield"];
500 for ( i = 0; i < level.riotshield_knockdown_enemies.size; i++ )
504 shield_damage += level.zombie_vars[
"riotshield_knockdown_damage_shield"];
507 level.riotshield_knockdown_enemies = [];
508 level.riotshield_knockdown_gib = [];
509 level.riotshield_fling_enemies = [];
510 level.riotshield_fling_vecs = [];
536 self.hasRiotShield =
false;
537 self.weaponRiotshield = level.weaponNone;
538 foreach ( weapon
in self GetWeaponsList(
true ) )
540 if ( weapon.isriotshield )
542 self.hasRiotShield =
true;
543 self.weaponRiotshield = weapon;
546 current =
self getCurrentWeapon();
547 self.hasRiotShieldEquipped = (current.isriotshield);
548 if (
self.hasRiotShield )
551 if (
self.hasRiotShieldEquipped )
563 self SetStowedWeapon( level.weaponNone );
565 self RefreshShieldAttachment();
572 self notify(
"destroy_riotshield" );
575 current =
self getCurrentWeapon();
576 if ( current.isriotshield )
580 new_primary = level.weaponNone;
581 primaryWeapons =
self GetWeaponsListPrimaries();
582 for ( i = 0; i < primaryWeapons.size; i++ )
584 if ( !primaryWeapons[i].isriotshield )
586 new_primary = primaryWeapons[i];
591 if (new_primary == level.weaponNone )
594 self SwitchToWeaponImmediate();
595 self PlaySound(
"wpn_riotshield_zm_destroy" );
600 self SwitchToWeaponImmediate();
601 self PlaySound(
"wpn_riotshield_zm_destroy" );
602 self waittill (
"weapon_change" );
607 self playsound(
"zmb_rocketshield_break" );
609 if ( IsDefined(
self.weaponRiotshield) )
614 self.hasRiotShield =
false;
615 self.hasRiotShieldEquipped =
false;