naev 0.11.5
pilot_ew.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <math.h>
11
12#include "naev.h"
15#include "array.h"
16#include "hook.h"
17#include "log.h"
18#include "pilot.h"
19#include "player.h"
20#include "player_autonav.h"
21#include "space.h"
22
23static double ew_interference = 1.;
25/*
26 * Prototypes.
27 */
28static void pilot_ewUpdate( Pilot *p );
29static double pilot_ewMass( double mass );
30static double pilot_ewAsteroid( const Pilot *p );
31static double pilot_ewJumpPoint( const Pilot *p );
32static int pilot_ewStealthGetNearby( const Pilot *p, double *mod, int *close, int *isplayer );
33
40double pilot_ewScanTime( const Pilot *p )
41{
42 /* Here larger is "better", so we divide by ew_hide and ew_signature instead of multiplying. */
43 return pow( p->solid.mass, 1./3. ) * 1.25 / (p->stats.ew_hide * p->stats.ew_signature) * p->stats.ew_scanned_time;
44}
45
52{
53 const Pilot *target = pilot_getTarget( p );
54 if (target==NULL)
55 return;
56
57 /* Player did bad stuff and is getting scanned. */
58 if (pilot_isPlayer(target) && pilot_hasIllegal(target,p->faction))
60
61 /* Scan time. */
62 p->scantimer = pilot_ewScanTime(p);
63}
64
71int pilot_ewScanCheck( const Pilot *p )
72{
73 if (p->target == p->id)
74 return 0;
75 return (p->scantimer < 0.);
76}
77
81static void pilot_ewUpdate( Pilot *p )
82{
83 p->ew_detection = p->ew_mass * p->ew_asteroid * p->stats.ew_hide;
84 p->ew_signature = p->ew_detection * 0.75 * ew_interference * p->stats.ew_signature;
85 /* For stealth we apply the ew_asteroid and ew_interference bonus outside of the max, so that it can go below 1000 with in-system features. */
86 p->ew_stealth = MAX( 1000., p->ew_mass * p->stats.ew_hide * 0.25 * p->stats.ew_stealth ) * p->ew_asteroid * ew_interference * p->ew_jumppoint;
87}
88
95{
96 p->ew_mass = pilot_ewMass( p->solid.mass );
97 pilot_ewUpdate( p );
98}
99
106void pilot_ewUpdateDynamic( Pilot *p, double dt )
107{
108 Pilot *t;
109
110 /* Electronic warfare values. */
111 p->ew_asteroid = pilot_ewAsteroid( p );
112 p->ew_jumppoint = pilot_ewJumpPoint( p );
113 pilot_ewUpdate( p );
114
115 /* Already scanned so skipping. */
116 if (p->scantimer < 0.)
117 return;
118
119 /* Get the target pilot. */
120 t = pilot_getTarget( p );
121 if (t == NULL)
122 return;
123
124 /* Must be in evasion range. */
125 if (vec2_dist2( &p->solid.pos, &t->solid.pos ) < pow2( MAX( 0., p->stats.ew_detect * p->stats.ew_track * t->ew_signature ) )) {
126 p->scantimer -= dt;
127
128 if (p->scantimer < 0.) {
129 HookParam hparam = { .type = HOOK_PARAM_PILOT };
130 /* Run scan hook. */
131 hparam.u.lp = t->id;
132 pilot_runHookParam( p, PILOT_HOOK_SCAN, &hparam, 1 );
133 /* Run scanned hook. */
134 hparam.u.lp = p->id;
135 pilot_runHookParam( t, PILOT_HOOK_SCANNED, &hparam, 1 );
136
137 /* Run outfit stuff. */
140
141 /* TODO handle case the player finished scanning by setting a flag or something. */
142 }
143 }
144}
145
152static double pilot_ewMass( double mass )
153{
154 return pow(mass, 1./1.8) * 350.;
155}
156
163static double pilot_ewAsteroid( const Pilot *p )
164{
165 int infield = asteroids_inField(&p->solid.pos);
166 if (infield < 0)
167 return 1.;
168 return 1. / (1. + 0.4*cur_system->asteroids[infield].density);
169}
170
177static double pilot_ewJumpPoint( const Pilot *p )
178{
179 /* Don't have to really check when not in stealth. */
180 if (!pilot_isFlag(p,PILOT_STEALTH))
181 return 1.;
182
183 /* Gets lower when near jump. */
184 for (int i=0; i<array_size(cur_system->jumps); i++) {
185 JumpPoint *jp = &cur_system->jumps[i];
186 if (jp_isFlag(jp,JP_EXITONLY) || jp_isFlag(jp,JP_HIDDEN))
187 continue;
188 double d2 = vec2_dist2( &jp->pos, &p->solid.pos );
189 if (d2 <= pow2(EW_JUMP_BONUS_RANGE))
190 return MAX( 0.5, sqrt(d2) / EW_JUMP_BONUS_RANGE);
191 }
192 return 1.;
193}
194
199{
200 ew_interference = 1. / (1. + cur_system->interference/100.);
201}
202
208double pilot_sensorRange( void )
209{
210 return 7500.;
211}
212
221int pilot_inRange( const Pilot *p, double x, double y )
222{
223 double d = pow2(x-p->solid.pos.x) + pow2(y-p->solid.pos.y);
224 double sr = pilot_sensorRange();
225 double sense = MAX( 0., sr * p->stats.ew_detect );
226 if (d < pow2(sense))
227 return 1;
228 /* points can't evade.
229 sense = MAX( 0., sr * p->stats.ew_signature );
230 if (d > pow2(sense))
231 return -1;
232 */
233 return 0;
234}
235
244int pilot_inRangePilot( const Pilot *p, const Pilot *target, double *dist2 )
245{
246 double d;
247
248 /* Get distance if needed. */
249 if (dist2 != NULL)
250 *dist2 = vec2_dist2( &p->solid.pos, &target->solid.pos );
251
252 /* Special case player or omni-visible. */
253 if ((pilot_isPlayer(p) && pilot_isFlag(target, PILOT_VISPLAYER)) ||
254 pilot_isFlag(target, PILOT_VISIBLE) ||
255 target->parent == p->id)
256 return 1;
257
258 /* Stealth detection. */
259 if (pilot_isFlag( target, PILOT_STEALTH ) && !pilot_areAllies( p, target ))
260 return 0;
261
262 /* No stealth so normal detection. */
263 d = (dist2!=NULL ? *dist2 : vec2_dist2( &p->solid.pos, &target->solid.pos ) );
264 if (d < pow2( MAX( 0., p->stats.ew_detect * p->stats.ew_track * target->ew_signature )))
265 return 1;
266 else if (d < pow2( MAX( 0., p->stats.ew_detect * target->ew_detection )))
267 return -1;
268
269 return 0;
270}
271
279int pilot_inRangeSpob( const Pilot *p, int target )
280{
281 double d;
282 Spob *pnt;
283 double sense;
284
285 /* pilot must exist */
286 if (p == NULL)
287 return 0;
288
289 /* Get the spob. */
290 pnt = cur_system->spobs[target];
291 sense = EW_SPOBDETECT_DIST;
292
293 /* Get distance. */
294 d = vec2_dist2( &p->solid.pos, &pnt->pos );
295 if (d < pow2( MAX( 0., sense * p->stats.ew_detect * pnt->hide) ) )
296 return 1;
297
298 return 0;
299}
300
309int pilot_inRangeAsteroid( const Pilot *p, int ast, int fie )
310{
311 double d;
312 Asteroid *as;
314 double sense;
315
316 /* pilot must exist */
317 if (p == NULL)
318 return 0;
319
320 /* Get the asteroid. */
321 f = &cur_system->asteroids[fie];
322 as = &f->asteroids[ast];
323
324 /* TODO something better than this. */
325 sense = EW_ASTEROID_DIST;
326
327 /* Get distance. */
328 d = vec2_dist2( &p->solid.pos, &as->sol.pos );
329
330 /* By default, asteroid's hide score is 1. It could be made changeable via xml.*/
331 if (d < pow2( MAX( 0., sense * p->stats.ew_detect ) ) )
332 return 1;
333
334 return 0;
335}
336
344int pilot_inRangeJump( const Pilot *p, int i )
345{
346 double d;
347 JumpPoint *jp;
348 double sense;
349 double hide;
350
351 /* pilot must exist */
352 if (p == NULL)
353 return 0;
354
355 /* Get the jump point. */
356 jp = &cur_system->jumps[i];
357
358 /* We don't want exit-only jumps. */
359 if (jp_isFlag(jp, JP_EXITONLY))
360 return 0;
361
362 /* Jumps with 0. hide are considered to be highway points and always visible. */
363 hide = jp->hide;
364 if (hide==0.)
365 return 1;
366
367 sense = EW_JUMPDETECT_DIST * p->stats.ew_jump_detect * p->stats.ew_detect;
368 /* Handle hidden jumps separately, as they use a special range parameter. */
369 if (jp_isFlag(jp, JP_HIDDEN))
370 sense *= p->stats.misc_hidden_jump_detect;
371
372 /* Get distance. */
373 d = vec2_dist2( &p->solid.pos, &jp->pos );
374 if (d < pow2( MAX( 0., sense * hide )))
375 return 1;
376
377 return 0;
378}
379
389double pilot_ewWeaponTrack( const Pilot *p, const Pilot *t, double trackmin, double trackmax )
390{
391 double mod = p->stats.ew_track * p->stats.ew_detect;
392 return CLAMP( 0., 1., (t->ew_signature * mod - trackmin) / (trackmax - trackmin + 1e-5) ); /* Avoid divide by zero if trackmax==trackmin. */
393}
394
404static int pilot_ewStealthGetNearby( const Pilot *p, double *mod, int *close, int *isplayer )
405{
406 Pilot *const* ps;
407 int n;
408
409 /* Check nearby non-allies. */
410 if (mod != NULL)
411 *mod = 0.;
412 if (close != NULL)
413 *close = 0;
414 if (isplayer != NULL)
415 *isplayer = 0;
416 n = 0;
417 ps = pilot_getAll();
418 for (int i=0; i<array_size(ps); i++) {
419 double dist;
420 Pilot *t = ps[i];
421
422 /* Quick checks first. */
423 if (pilot_isDisabled(t))
424 continue;
425 if (!pilot_canTarget(t))
426 continue;
427
428 /* Must not be landing nor taking off. */
429 if (pilot_isFlag(t, PILOT_LANDING) ||
430 pilot_isFlag(t, PILOT_TAKEOFF))
431 continue;
432
433 /* Allies are ignored. */
434 if (pilot_areAllies( p, t ))
435 continue;
436
437 /* Stealthed pilots don't reduce stealth. */
438 //if (pilot_isFlag(t, PILOT_STEALTH))
439 // continue;
440
441 /* Compute distance. */
442 dist = vec2_dist2( &p->solid.pos, &t->solid.pos );
443 /* TODO maybe not hardcode the close value. */
444 if ((close != NULL) && !pilot_isFlag(t,PILOT_STEALTH) &&
445 (dist < pow2( MAX( 0., p->ew_stealth * t->stats.ew_detect * 1.5 ))))
446 (*close)++;
447 if (dist > pow2( MAX( 0., p->ew_stealth * t->stats.ew_detect )))
448 continue;
449
450 if (mod != NULL)
451 *mod += 1.0 - sqrt(dist) / (p->ew_stealth * t->stats.ew_detect);
452
453 /* We found a pilot that is in range. */
454 n++;
455 if ((isplayer != NULL) && pilot_isPlayer(t))
456 *isplayer = 1;
457 }
458
459 return n;
460}
461
468void pilot_ewUpdateStealth( Pilot *p, double dt )
469{
470 int n, close, isplayer;
471 double mod;
472
473 if (!pilot_isFlag( p, PILOT_STEALTH ))
474 return;
475
476 /* Get nearby pilots. */
477 if (pilot_isPlayer(p)) {
478 if (pilot_isFlag(p, PILOT_NONTARGETABLE))
479 return;
480
481 n = pilot_ewStealthGetNearby( p, &mod, &close, &isplayer );
482
483 /* Stop autonav if pilots are nearby. */
484 if (close>0)
486 }
487 else
488 n = pilot_ewStealthGetNearby( p, &mod, NULL, &isplayer );
489
490 /* Increases if nobody nearby. */
491 if (n == 0) {
492 p->ew_stealth_timer += dt * 5e3 / p->ew_stealth;
493 if (p->ew_stealth_timer > 1.)
494 p->ew_stealth_timer = 1.;
495 }
496 /* Otherwise decreases. */
497 else {
498 p->ew_stealth_timer -= dt * (p->ew_stealth / 10e3 + mod) * p->stats.ew_stealth_timer;
499 if (p->ew_stealth_timer < 0.) {
500 pilot_destealth( p );
501 if (pilot_isPlayer(p))
502 player_message( "#r%s", _("You have been uncovered!"));
503 else if (isplayer)
504 player_message(_("You have uncovered '#%c%s#0'!"), pilot_getFactionColourChar(p), p->name);
505 ai_discovered( p );
506 }
507 }
508}
509
514{
515 int n, ret;
516
517 if (pilot_isFlag( p, PILOT_STEALTH ))
518 return 1;
519
520 /* Can't stealth if locked on. */
521 if (p->lockons > 0)
522 return 0;
523
524 /* Can't stealth if pilots nearby. */
525 pilot_setFlag( p, PILOT_STEALTH );
526 n = pilot_ewStealthGetNearby( p, NULL, NULL, NULL );
527 if (n > 0) {
528 pilot_rmFlag( p, PILOT_STEALTH );
529 return 0;
530 }
531
532 /* Turn off all weapon sets. */
534
535 /* Turn off outfits. */
536 ret = pilot_outfitOffAll( p );
537
538 /* Got into stealth. */
539 if (!pilot_outfitLOnstealth( p ) || ret)
541 p->ew_stealth_timer = 0.;
542
543 /* Run hook. */
544 const HookParam hparam = { .type = HOOK_PARAM_BOOL, .u.b = 1 };
545 pilot_runHookParam( p, PILOT_HOOK_STEALTH, &hparam, 1 );
546 return 1;
547}
548
553{
554 if (!pilot_isFlag( p, PILOT_STEALTH ))
555 return;
556 pilot_rmFlag( p, PILOT_STEALTH );
557 p->ew_stealth_timer = 0.;
558 if (!pilot_outfitLOnstealth( p ))
560
561 /* Run hook. */
562 const HookParam hparam = { .type = HOOK_PARAM_BOOL, .u.b = 0 };
563 pilot_runHookParam( p, PILOT_HOOK_STEALTH, &hparam, 1 );
564}
void ai_discovered(Pilot *discovered)
Triggers the discovered() function in the pilot's AI.
Definition ai.c:948
Provides macros to work with dynamic arrays.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
int asteroids_inField(const vec2 *p)
See if the position is in an asteroid field.
Definition asteroid.c:997
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:335
Header file with generic functions and naev-specifics.
#define CLAMP(a, b, x)
Definition naev.h:41
#define pow2(x)
Definition naev.h:46
#define MAX(x, y)
Definition naev.h:39
char pilot_getFactionColourChar(const Pilot *p)
Gets the faction colour char, works like faction_getColourChar but for a pilot.
Definition pilot.c:1080
Pilot * pilot_getTarget(Pilot *p)
Gets the target of a pilot using a fancy caching system.
Definition pilot.c:634
int pilot_hasIllegal(const Pilot *p, int faction)
Checks to see if the pilot has illegal stuf to a faction.
Definition pilot.c:4153
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
Definition pilot.c:94
int pilot_canTarget(const Pilot *p)
Same as pilot_validTarget but without the range check.
Definition pilot.c:254
int pilot_areAllies(const Pilot *p, const Pilot *target)
Like areAllies but for pilots.
Definition pilot.c:721
void pilot_ewUpdateStealth(Pilot *p, double dt)
Updates the stealth mode and checks to see if it is getting broken.
Definition pilot_ew.c:468
int pilot_inRangePilot(const Pilot *p, const Pilot *target, double *dist2)
Check to see if a pilot is in sensor range of another.
Definition pilot_ew.c:244
void pilot_ewUpdateDynamic(Pilot *p, double dt)
Updates the pilot's dynamic electronic warfare properties.
Definition pilot_ew.c:106
int pilot_ewScanCheck(const Pilot *p)
Checks to see if a scan is done.
Definition pilot_ew.c:71
static double pilot_ewJumpPoint(const Pilot *p)
Gets the electronic warfare jump point modifier.
Definition pilot_ew.c:177
int pilot_inRangeSpob(const Pilot *p, int target)
Check to see if a spob is in sensor range of the pilot.
Definition pilot_ew.c:279
static double ew_interference
Definition pilot_ew.c:23
void pilot_updateSensorRange(void)
Updates the system's base sensor range.
Definition pilot_ew.c:198
void pilot_destealth(Pilot *p)
Destealths a pilot.
Definition pilot_ew.c:552
int pilot_inRangeJump(const Pilot *p, int i)
Check to see if a jump point is in sensor range of the pilot.
Definition pilot_ew.c:344
void pilot_ewScanStart(Pilot *p)
Initializes the scan timer for a pilot.
Definition pilot_ew.c:51
double pilot_ewWeaponTrack(const Pilot *p, const Pilot *t, double trackmin, double trackmax)
Calculates the weapon lead (1. is 100%, 0. is 0%)..
Definition pilot_ew.c:389
void pilot_ewUpdateStatic(Pilot *p)
Updates the pilot's static electronic warfare properties.
Definition pilot_ew.c:94
int pilot_inRangeAsteroid(const Pilot *p, int ast, int fie)
Check to see if an asteroid is in sensor range of the pilot.
Definition pilot_ew.c:309
static int pilot_ewStealthGetNearby(const Pilot *p, double *mod, int *close, int *isplayer)
Checks to see if there are pilots nearby to a stealthed pilot that could break stealth.
Definition pilot_ew.c:404
static void pilot_ewUpdate(Pilot *p)
Updates all the internal values.
Definition pilot_ew.c:81
double pilot_sensorRange(void)
Returns the default sensor range for the current system.
Definition pilot_ew.c:208
static double pilot_ewAsteroid(const Pilot *p)
Gets the electronic warfare asteroid modifier.
Definition pilot_ew.c:163
double pilot_ewScanTime(const Pilot *p)
Gets the time it takes to scan a pilot.
Definition pilot_ew.c:40
int pilot_inRange(const Pilot *p, double x, double y)
Check to see if a position is in range of the pilot.
Definition pilot_ew.c:221
static double pilot_ewMass(double mass)
Gets the electronic warfare mass modifier for a given mass.
Definition pilot_ew.c:152
int pilot_stealth(Pilot *p)
Stealths a pilot.
Definition pilot_ew.c:513
void pilot_calcStats(Pilot *pilot)
Recalculates the pilot's stats based on his outfits.
int pilot_outfitLOnstealth(Pilot *pilot)
Runs the pilot's Lua outfits onhit script.
void pilot_outfitLOnscan(Pilot *pilot)
Runs Lua outfits when pilot scanned their target.
void pilot_outfitLOnscanned(Pilot *pilot, const Pilot *scanner)
Runs Lua outfits when pilot was scanned by scanner.
void pilot_weapSetAIClear(Pilot *p)
Useful function for AI, clears activeness of all weapon sets.
int pilot_outfitOffAll(Pilot *p)
Disables all active outfits for a pilot.
void player_autonavResetSpeed(void)
Resets the game speed.
static const double d[]
Definition rng.c:273
StarSystem * cur_system
Definition space.c:106
Represents an asteroid field anchor.
Definition asteroid.h:100
Asteroid * asteroids
Definition asteroid.h:105
Represents a single asteroid.
Definition asteroid.h:77
Solid sol
Definition asteroid.h:87
The actual hook parameter.
Definition hook.h:38
LuaPilot lp
Definition hook.h:44
union HookParam::@25 u
The representation of an in-game pilot.
Definition pilot.h:217
ShipStats stats
Definition pilot.h:294
unsigned int id
Definition pilot.h:218
unsigned int parent
Definition pilot.h:333
double ew_detection
Definition pilot.h:271
Solid solid
Definition pilot.h:227
double ew_signature
Definition pilot.h:272
double ew_detect
Definition shipstats.h:244
vec2 pos
Definition physics.h:49
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:89
vec2 pos
Definition space.h:94
double hide
Definition space.h:105