1 #using scripts\codescripts\struct;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\scoreevents_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\weapons\_weaponobjects;
9 #using scripts\shared\util_shared;
11 #insert scripts\shared\shared.gsh;
12 #insert scripts\shared\version.gsh;
14 #precache( "fx", "weapon/fx_prox_grenade_scan_blue" );
15 #precache( "fx", "weapon/fx_prox_grenade_wrn_grn" );
16 #precache( "fx", "weapon/fx_prox_grenade_scan_orng" );
17 #precache( "fx", "weapon/fx_prox_grenade_wrn_red" );
18 #precache( "fx", "weapon/fx_prox_grenade_impact_player_spwner" );
19 #precache( "fx", "weapon/fx_prox_grenade_elec_jump" );
21 #namespace proximity_grenade;
25 level._effect[
"prox_grenade_friendly_default"] =
"weapon/fx_prox_grenade_scan_blue";
26 level._effect[
"prox_grenade_friendly_warning"] =
"weapon/fx_prox_grenade_wrn_grn";
27 level._effect[
"prox_grenade_enemy_default"] =
"weapon/fx_prox_grenade_scan_orng";
28 level._effect[
"prox_grenade_enemy_warning"] =
"weapon/fx_prox_grenade_wrn_red";
29 level._effect[
"prox_grenade_player_shock"] =
"weapon/fx_prox_grenade_impact_player_spwner";
30 level._effect[
"prox_grenade_chain_bolt"] =
"weapon/fx_prox_grenade_elec_jump";
32 level.proximityGrenadeDetectionRadius = GetDvarInt(
"scr_proximityGrenadeDetectionRadius", 180 );
33 level.proximityGrenadeDuration = GetDvarFloat(
"scr_proximityGrenadeDuration", 1.2 );
34 level.proximityGrenadeGracePeriod = GetDvarFloat(
"scr_proximityGrenadeGracePeriod", 0.05 );
35 level.proximityGrenadeDOTDamageAmount = GetDvarInt(
"scr_proximityGrenadeDOTDamageAmount", 1 );
36 level.proximityGrenadeDOTDamageAmountHardcore = GetDvarInt(
"scr_proximityGrenadeDOTDamageAmountHardcore", 1 );
37 level.proximityGrenadeDOTDamageTime = GetDvarFloat(
"scr_proximityGrenadeDOTDamageTime", 0.2 );
38 level.proximityGrenadeDOTDamageInstances = GetDvarInt(
"scr_proximityGrenadeDOTDamageInstances", 4 );
39 level.proximityGrenadeActivationTime = GetDvarFloat(
"scr_proximityGrenadeActivationTime", .1 );
40 level.proximityChainDebug = GetDvarInt(
"scr_proximityChainDebug", 0 );
41 level.proximityChainGracePeriod = GetDvarInt(
"scr_proximityChainGracePeriod", 2500 );
42 level.proximityChainBoltSpeed = GetDvarFloat(
"scr_proximityChainBoltSpeed", 400.0 );
43 level.proximityGrenadeProtectedTime = GetDvarFloat(
"scr_proximityGrenadeProtectedTime", 0.45 );
45 level.poisonFXDuration = 6;
47 level thread
register();
71 level.proximityGrenadeDetectionRadius = GetDvarInt(
"scr_proximityGrenadeDetectionRadius", level.proximityGrenadeDetectionRadius );
72 level.proximityGrenadeDuration = GetDvarFloat(
"scr_proximityGrenadeDuration", 1.5 );
73 level.proximityGrenadeGracePeriod = GetDvarFloat(
"scr_proximityGrenadeGracePeriod", level.proximityGrenadeGracePeriod );
74 level.proximityGrenadeDOTDamageAmount = GetDvarInt(
"scr_proximityGrenadeDOTDamageAmount", level.proximityGrenadeDOTDamageAmount );
75 level.proximityGrenadeDOTDamageAmountHardcore = GetDvarInt(
"scr_proximityGrenadeDOTDamageAmountHardcore", level.proximityGrenadeDOTDamageAmountHardcore );
76 level.proximityGrenadeDOTDamageTime = GetDvarFloat(
"scr_proximityGrenadeDOTDamageTime", level.proximityGrenadeDOTDamageTime );
77 level.proximityGrenadeDOTDamageInstances = GetDvarInt(
"scr_proximityGrenadeDOTDamageInstances", level.proximityGrenadeDOTDamageInstances );
78 level.proximityGrenadeActivationTime = GetDvarFloat(
"scr_proximityGrenadeActivationTime", level.proximityGrenadeActivationTime );
79 level.proximityChainDebug = GetDvarInt(
"scr_proximityChainDebug", level.proximityChainDebug );
80 level.proximityChainGracePeriod = GetDvarInt(
"scr_proximityChainGracePeriod", level.proximityChainGracePeriod );
81 level.proximityChainBoltSpeed = GetDvarFloat(
"scr_proximityChainBoltSpeed", level.proximityChainBoltSpeed );
82 level.proximityGrenadeProtectedTime = GetDvarFloat(
"scr_proximityGrenadeProtectedTime", level.proximityGrenadeProtectedTime );
91 watcher.watchForFire =
true;
92 watcher.hackable =
true;
93 watcher.hackerToolRadius = level.equipmentHackerToolRadius;
94 watcher.hackerToolTimeMs = level.equipmentHackerToolTimeMs;
95 watcher.headIcon =
false;
96 watcher.activateFx =
true;
97 watcher.ownerGetsAssist =
true;
98 watcher.ignoreDirection =
true;
99 watcher.immediateDetonation =
true;
100 watcher.detectionGracePeriod = level.proximityGrenadeGracePeriod;
101 watcher.detonateRadius = level.proximityGrenadeDetectionRadius;
103 watcher.stunTime = 1;
105 watcher.activationDelay = level.proximityGrenadeActivationTime;
106 watcher.activateSound =
"wpn_claymore_alert";
107 watcher.immunespecialty =
"specialty_immunetriggershock";
115 watcher.watchForFire =
true;
116 watcher.hackable =
true;
117 watcher.hackerToolRadius = level.equipmentHackerToolRadius;
118 watcher.hackerToolTimeMs = level.equipmentHackerToolTimeMs;
119 watcher.headIcon =
false;
120 watcher.activateFx =
true;
121 watcher.ownerGetsAssist =
true;
122 watcher.ignoreDirection =
true;
123 watcher.immediateDetonation =
true;
124 watcher.detectionGracePeriod = level.proximityGrenadeGracePeriod;
125 watcher.detonateRadius = level.proximityGrenadeDetectionRadius;
127 watcher.stunTime = 1;
129 watcher.activationDelay = level.proximityGrenadeActivationTime;
130 watcher.activateSound =
"wpn_claymore_alert";
138 owner AddWeaponStat(
self.weapon,
"used", 1 );
140 if ( IsDefined(
self.weapon ) &&
self.weapon.proximityDetonation > 0 )
142 watcher.detonateRadius =
self.weapon.proximityDetonation;
152 if ( level.trackProximityGrenadesOnOwner ===
true )
154 if ( !isdefined( owner ) )
157 if ( !isdefined( owner.activeProximityGrenades ) )
159 owner.activeProximityGrenades = [];
163 ArrayRemoveValue( owner.activeProximityGrenades, undefined );
166 owner.activeProximityGrenades[ owner.activeProximityGrenades.size ] =
self;
172 self endon(
"death" );
176 self.killCamEnt =
spawn(
"script_model",
self.origin + (0,0,8 ) );
182 self waittill(
"death" );
184 self.killCamEnt
util::deleteAfterTime( 4 + level.proximityGrenadeDOTDamageTime * level.proximityGrenadeDOTDamageInstances );
189 if ( isdefined( weapon ) && weapon.isValid )
191 if ( isdefined( attacker ) )
211 if ( weapon.chainEventRadius > 0 && !
self hasPerk (
"specialty_proximityprotection") )
219 if ( !isdefined( level.proximityChains ) )
221 level.proximityChains = [];
225 foreach( chain
in level.proximityChains )
233 chain = spawnstruct();
234 level.proximityChains[level.proximityChains.size] = chain;
242 if ( isdefined( chain.activeEndTime ) && chain.activeEndTime > GetTime() )
260 if ( !isdefined(
self ) )
267 foreach( proximityChain
in self.chains )
269 if ( proximityChain.activeEndTime > GetTime() )
277 if ( isdefined(
self ) )
285 player_num = player GetEntityNumber();
287 return isdefined(
self.chain_players[player_num] );
292 player_num = player GetEntityNumber();
294 self.chain_players[player_num] = player;
299 self endon(
"disconnect" );
300 self endon(
"death" );
302 eAttacker endon(
"disconnect" );
304 if ( !isdefined( proximityChain ) )
308 proximityChain.chainEventNum = 0;
310 if ( !isdefined( eInflictor.proximityChainEnt ) )
313 eInflictor.proximityChainEnt =
spawn(
"script_origin",
self.origin );
314 eInflictor.proximityChainEnt.chains = [];
315 eInflictor.proximityChainEnt.chain_players = [];
318 proximityChain.proximityChainEnt = eInflictor.proximityChainEnt;
319 proximityChain.proximityChainEnt.chains[proximityChain.proximityChainEnt.chains.size] = proximityChain;
322 proximityChain.chainEventNum += 1;
324 if ( proximityChain.chainEventNum >= weapon.chainEventMax )
330 chainEventRadiusSq = weapon.chainEventRadius * weapon.chainEventRadius;
332 endTime = GetTime() + weapon.chainEventTime;
335 proximityChain.activeEndTime = endTime + (
delay * 1000) + level.proximityChainGracePeriod;
343 if( !isdefined( proximityChain.proximityChainEnt.cleanUp ) )
351 currentTime = GetTime();
353 if ( endTime < currentTime )
358 closestPlayers = ArraySort( level.players,
self.origin,
true );
360 foreach( player
in closestPlayers )
364 if ( proximityChain.chainEventNum >= weapon.chainEventMax )
370 if ( !isdefined( player ) || !IsAlive( player ) || player ==
self )
375 if ( player.sessionstate !=
"playing" )
380 distanceSq = DistanceSquared( player.origin,
self.origin );
382 if ( distanceSq > chainEventRadiusSq )
387 if ( proximityChain.proximityChainEnt
isInChain( player ) )
394 if ( level.proximityChainDebug || !player hasPerk (
"specialty_proximityprotection") )
398 self thread
chainPlayer( eAttacker, killCamEnt, weapon, meansOfDeath,
damage, proximityChain, player, distanceSq );
407 function chainPlayer( eAttacker, killCamEnt, weapon, meansOfDeath,
damage, proximityChain, player, distanceSq )
411 speedSq = level.proximityChainBoltSpeed * level.proximityChainBoltSpeed;
412 if ( speedSq > 100 && distanceSq > 1 )
414 waitTime = distanceSq / speedSq;
421 if ( level.proximityChainDebug )
428 util::debug_line(
self.origin + (0,0,50), player.origin + (0,0,50), color, alpha, depth, time );
439 if ( !IsDefined(
self ) || !IsDefined( target ) )
444 tag =
"J_SpineUpper";
445 target_tag =
"J_SpineUpper";
447 origin =
self GetTagOrigin( tag );
448 target_origin = target GetTagOrigin( target_tag );
450 distance_squared = 128 * 128;
452 if ( DistanceSquared( origin, target_origin ) < distance_squared )
458 fxOrg =
spawn(
"script_model", origin );
459 fxOrg SetModel(
"tag_origin" );
461 fx = PlayFxOnTag( level._effect[
"prox_grenade_chain_bolt"], fxOrg,
"tag_origin" );
462 playsoundatposition(
"wpn_tesla_bounce", fxOrg.origin );
464 fxOrg MoveTo( target_origin, waitTime );
465 fxOrg waittill(
"movedone" );
478 self endon(
"death" );
480 self SetOwner( owner );
481 self SetTeam( owner.team );
485 self waittill(
"grenade_bounce", pos, normal, ent, surface);
487 if ( isdefined(ent) && isplayer( ent ) && surface !=
"riotshield" )
489 if ( ( level.teambased && ent.team ==
self.owner.team ))
502 forwardVec = VectorNormalize( AnglesToForward(
self.angles ) );
503 rightVec = VectorNormalize( AnglesToRight(
self.angles ) );
504 explosionVec = VectorNormalize( position -
self.origin );
506 fDot = VectorDot( explosionVec, forwardVec );
507 rDot = VectorDot( explosionVec, rightVec );
509 fAngle = ACos( fDot );
510 rAngle = ACos( rDot );
515 self notify(
"proximityGrenadeDamageStart" );
516 self endon(
"proximityGrenadeDamageStart" );
517 self endon(
"disconnect" );
518 self endon(
"death" );
519 eAttacker endon(
"disconnect" );
521 PlayFxOnTag( level._effect[
"prox_grenade_player_shock"],
self,
"J_SpineUpper" );
526 if ( !
self hasPerk (
"specialty_proximityprotection") )
528 self.lastShockedBy = eAttacker;
529 self.shockEndTime = getTime() + ( level.proximityGrenadeDuration * 1000 );
530 self shellshock(
"proximity_grenade", level.proximityGrenadeDuration,
false );
536 self playrumbleonentity(
"proximity_grenade");
537 self PlaySound(
"wpn_taser_mine_zap" );
539 if ( !
self hasPerk (
"specialty_proximityprotection") )
543 if ( !isdefined( killCamEnt ) )
545 killCamEnt =
spawn(
"script_model", position + (0,0,8) );
548 killCamEnt.soundMod =
"taser_spike";
549 killCamEnt
util::deleteAfterTime( 3 + level.proximityGrenadeDOTDamageTime * level.proximityGrenadeDOTDamageInstances);
552 damage = level.proximityGrenadeDOTDamageAmount;
554 if( level.hardcoreMode )
556 damage = level.proximityGrenadeDOTDamageAmountHardcore;
559 for ( i = 0; i < level.proximityGrenadeDOTDamageInstances; i++ )
561 assert( isdefined( eAttacker ) );
563 if ( !isdefined( killCamEnt ) )
565 killCamEnt =
spawn(
"script_model", position + (0,0,8) );
566 killCamEnt.soundMod =
"taser_spike";
567 killCamEnt
util::deleteAfterTime( 3 + level.proximityGrenadeDOTDamageTime * ( level.proximityGrenadeDOTDamageInstances - i ) );
570 self DoDamage(
damage, position, eAttacker, killCamEnt,
"none",
"MOD_GAS", 0, GetWeapon(
"proximity_grenade_aoe" ) );
572 wait( level.proximityGrenadeDOTDamageTime );
575 if (GetTime() - g_time < (level.proximityGrenadeDuration*1000) )
577 wait ( ( GetTime() - g_time) / 1000);
585 wait( level.proximityGrenadeProtectedTime );
593 self waittill(
"death" );
595 self notify(
"deleteSound" );
602 self endon(
"delete" );
603 owner waittill(
"death" );
604 self notify(
"deleteSound" );
609 self endon(
"delete" );
611 self notify(
"deleteSound" );
616 self endon(
"delete" );
617 self waittill(
"deleteSound" );
623 self endon(
"disconnect" );
624 self notify(
"proximity_cleanup" );
625 self endon(
"proximity_cleanup" );
628 self waittill(
"death");
629 self StopRumble(
"proximity_grenade" );
645 self endon(
"death" );
646 self endon(
"disconnect" );
648 self notify(
"proximityTrackingStart" );
649 self endon(
"proximityTrackingStart" );
653 self waittill (
"grenade_fire", grenade, weapon, cookTime );
660 if ( weapon.rootWeapon.name ==
"proximity_grenade" )