1 #using scripts\codescripts\struct;
2 #using scripts\shared\array_shared;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\flagsys_shared;
6 #using scripts\shared\hud_util_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\abilities\_ability_util;
11 #insert scripts\shared\weapons\grapple.gsh;
12 #insert scripts\shared\shared.gsh;
13 #insert scripts\shared\version.gsh;
19 #define GRAPPLE_TARGET "grapple_target"
20 #define GRAPPLE_RETARGET_DELAY 0.1
22 #define WEAPON_CHANGE_NOTIFY "grapple_weapon_change"
33 foreach( target
in grapple_targets )
36 target SetGrapplableType( target.grapple_type );
42 self endon(
"disconnect" );
43 self endon(
"death" );
44 self endon(
"spawned_player" );
46 while (IsDefined(
self))
48 self waittill( from_notify, param1, param2, param3 );
49 self notify( to_notify, from_notify, param1, param2, param3 );
56 self endon(
"disconnect" );
57 self endon(
"death" );
58 self endon(
"spawned_player" );
59 self endon(
"killReplayGunMonitor");
68 if (
IS_TRUE(weapon.grappleWeapon) )
74 self notify(
"grapple_unwield" );
81 self endon(
"disconnect" );
82 self endon(
"death" );
83 self endon(
"spawned_player" );
84 self endon(
"grapple_unwield" );
85 self notify(
"watch_lockon" );
86 self endon(
"watch_lockon" );
92 self.use_expensive_targeting =
true;
97 if ( !(
self IsGrappling()) )
100 if ( !(
self IsGrappling()) && !
IS_EQUAL(target,
self.lockonentity) )
102 self WeaponLockNoClearance( !
IS_EQUAL( target,
self.dummy_target ) );
103 self.lockonentity = target;
112 self endon(
"disconnect" );
113 self endon(
"death" );
114 self endon(
"spawned_player" );
115 self endon(
"grapple_unwield" );
116 self notify(
"clear_lockon_after_grapple" );
117 self endon(
"clear_lockon_after_grapple" );
122 if ( IsDefined(
self.lockonentity ) )
124 self.lockonentity = undefined;
125 self.use_expensive_targeting =
true;
132 self endon(
"disconnect" );
133 self endon(
"death" );
134 self endon(
"spawned_player" );
135 self endon(
"grapple_unwield" );
136 self notify(
"watch_lockon_angles" );
137 self endon(
"watch_lockon_angles" );
142 if ( !(
self IsGrappling()) )
144 if ( IsDefined(
self.lockonentity ) )
146 if (
IS_EQUAL(
self.lockonentity,
self.dummy_target ) )
148 self weaponlocktargettooclose(
false );
155 self weaponlocktargettooclose(
true );
159 self weaponlocktargettooclose(
false );
170 if ( !IsDefined(
self.dummy_target) )
172 self.dummy_target =
Spawn(
"script_origin", origin );
178 distance = weapon.lockOnMaxRange * 0.9;
179 if ( IsDefined( level.grapple_notarget_distance ) )
180 distance = level.grapple_notarget_distance;
182 end = origin + forward * distance;
184 if ( !(
self IsGrappling()) )
186 self.dummy_target.origin =
self trace( start,
end,
self.dummy_target );
189 minrange_sq = weapon.lockOnMinRange * weapon.lockOnMinRange;
190 if ( DistanceSquared(
self.dummy_target.origin, origin ) < minrange_sq )
193 return self.dummy_target;
198 origin =
self geteye();
199 forward =
self GetWeaponForwardDir();
201 targets = GetGrappleTargetArray();
203 if ( !IsDefined( targets ) )
206 if ( !IsDefined(weapon.lockOnScreenRadius) || weapon.lockOnScreenRadius< 1 )
211 should_wait_limit = 2;
213 if (
IS_TRUE(
self.use_expensive_targeting ) )
215 should_wait_limit = 4;
216 self.use_expensive_targeting =
false;
219 for ( i = 0; i < targets.size; i++ )
221 if ( should_wait >= should_wait_limit )
224 origin =
self GetWeaponMuzzlePoint();
225 forward =
self GetWeaponForwardDir();
229 testTarget = targets[i];
238 test_range = Distance( origin, testOrigin );
241 if ( test_range > weapon.lockOnMaxRange ||
242 test_range < weapon.lockOnMinRange )
247 normal = VectorNormalize( testOrigin - origin );
248 dot = VectorDot( forward, normal );
261 canSee =
self can_see( testTarget, testOrigin, origin, forward, 30 );
266 validTargets[ validTargets.size ] = testTarget;
270 best =
pick_a_target_from( validTargets, origin, forward, weapon.lockOnMinRange, weapon.lockOnMaxRange );
272 if (
IS_TRUE( level.grapple_notarget_enabled ) )
274 if (!IsDefined(best) ||
IS_EQUAL(best,
self.dummy_target) )
285 if ( !IsDefined( target ) )
288 if (
IS_EQUAL(target,
self.dummy_target) )
297 if ( !IsDefined(target.grapple_type) )
310 #define GRAPPLE_TARGET_WEIGHT_DOT_OVER_DIST 0.85
314 if ( !IsDefined( target ) )
317 if (
IS_EQUAL(target,
self.dummy_target) )
323 normal = VectorNormalize( testOrigin - origin );
324 dot = VectorDot( forward, normal );
325 targetDistance = Distance(
self.origin, testOrigin );
326 distance_score = 1-((targetDistance - min_range) / (max_range - min_range));
340 if ( !IsDefined( targets ) )
343 bestTarget = undefined;
344 bestScore = undefined;
346 for ( i = 0; i < targets.size; i++ )
354 if ( !IsDefined( bestTarget ) || !IsDefined( bestScore ) )
359 else if ( score > bestScore )
371 trace = bullettrace(from,to,
false,
self,
true,
false, target );
372 return trace[
"position" ];
377 function can_see( target, target_origin, player_origin, player_forward, distance )
379 start = player_origin + player_forward * distance;
380 end = target_origin - player_forward * distance;
382 collided =
self trace( start,
end, target );
384 if ( Distance2DSquared(
end,collided) > 3 * 3 )
387 if ( GetDvarInt(
"scr_grapple_target_debug" ) )
389 Line(start,collided,(0,0,1),1,0,50);
390 Line(collided,
end,(1,0,0),1,0,50);
397 if ( GetDvarInt(
"scr_grapple_target_debug" ) )
399 Line(start,
end,(0,1,0),1,0,30);
407 if ( IsDefined( ent ) && IsDefined( level.grapple_valid_target_check ) )
409 if ( ![[level.grapple_valid_target_check]](ent) )
412 return IsDefined( ent ) && ( IsAlive( ent ) || !IsSentient(ent) );
417 hang = weapon.lockonlossanglehorizontal;
419 hang = weapon.lockonanglehorizontal;
420 vang = weapon.lockonlossanglevertical;
422 vang = weapon.lockonanglevertical;
424 angles =
self GetTargetScreenAngles( testOrigin );
426 return abs(angles[0]) < hang && abs(angles[1]) < vang;
431 radius = weapon.lockOnScreenRadius;
438 radius =
self getLockOnRadius();
447 return Target_OriginIsInCircle( targetOrigin,
self, useFov, radius );
452 return self GetLockOnOrigin( target );