1 /*
2 * See Licensing and Copyright notice in naev.h
3 */
4
5
6 /**
7 * @file pilot_ew.c
8 *
9 * @brief Pilot electronic warfare information.
10 */
11
12
13 #include "pilot.h"
14
15 #include "naev.h"
16
17 #include <math.h>
18
19 #include "log.h"
20 #include "space.h"
21 #include "player.h"
22
23 static double sensor_curRange = 0.; /**< Current base sensor range, used to calculate
24 what is in range and what isn't. */
25
26 #define EVASION_SCALE 1.3225 /**< 1.15 squared. Ensures that ships have higher evasion than hide. */
27 #define SENSOR_DEFAULT_RANGE 7500 /**< The default sensor range for all ships. */
28
29 /**
30 * @brief Updates the pilot's static electronic warfare properties.
31 *
32 * @param p Pilot to update.
33 */
pilot_ewUpdateStatic(Pilot * p)34 void pilot_ewUpdateStatic( Pilot *p )
35 {
36 /*
37 * Unlike the other values, heat isn't squared. The ew_hide formula is thus
38 * equivalent to: ew_base_hide * ew_mass * sqrt(ew_heat)
39 */
40 p->ew_mass = pow2( pilot_ewMass( p->solid->mass ) );
41 p->ew_heat = pilot_ewHeat( p->heat_T );
42 p->ew_asteroid = pilot_ewAsteroid( p );
43 p->ew_hide = p->ew_base_hide * p->ew_mass * p->ew_heat * p->ew_asteroid;
44 p->ew_evasion = p->ew_hide * EVASION_SCALE;
45 }
46
47
48 /**
49 * @brief Updates the pilot's dynamic electronic warfare properties.
50 *
51 * @param p Pilot to update.
52 */
pilot_ewUpdateDynamic(Pilot * p)53 void pilot_ewUpdateDynamic( Pilot *p )
54 {
55 /* Update hide. */
56 p->ew_heat = pilot_ewHeat( p->heat_T );
57 p->ew_asteroid = pilot_ewAsteroid( p );
58 p->ew_hide = p->ew_base_hide * p->ew_mass * p->ew_heat * p->ew_asteroid;
59
60 /* Update evasion. */
61 p->ew_movement = pilot_ewMovement( VMOD(p->solid->vel) );
62 p->ew_evasion = p->ew_hide * EVASION_SCALE;
63 }
64
65
66 /**
67 * @brief Gets the electronic warfare movement modifier for a given velocity.
68 *
69 * @param vmod Velocity to get electronic warfare movement modifier of.
70 * @return The electronic warfare movement modifier.
71 */
pilot_ewMovement(double vmod)72 double pilot_ewMovement( double vmod )
73 {
74 return 1. + vmod / 100.;
75 }
76
77
78 /**
79 * @brief Gets the electronic warfare heat modifier for a given temperature.
80 *
81 * @param T Temperature of the ship.
82 * @return The electronic warfare heat modifier.
83 */
pilot_ewHeat(double T)84 double pilot_ewHeat( double T )
85 {
86 return 1. - 0.001 * (T - CONST_SPACE_STAR_TEMP);
87 }
88
89
90 /**
91 * @brief Gets the electronic warfare mass modifier for a given mass.
92 *
93 * @param mass Mass to get the electronic warfare mass modifier of.
94 * @return The electronic warfare mass modifier.
95 */
pilot_ewMass(double mass)96 double pilot_ewMass( double mass )
97 {
98 return 1. / (.3 + sqrt(mass) / 30. );
99 }
100
101
102 /**
103 * @brief Gets the electronic warfare asteroid modifier.
104 *
105 * @param pilot.
106 * @return The electronic warfare asteroid modifier.
107 */
pilot_ewAsteroid(Pilot * p)108 double pilot_ewAsteroid( Pilot *p )
109 {
110 int i;
111
112 i = space_isInField(&p->solid->pos);
113 if ( i>=0 )
114 return 1. + cur_system->asteroids[i].density;
115 else
116 return 1.;
117 }
118
119
120 /**
121 * @brief Updates the system's base sensor range.
122 */
pilot_updateSensorRange(void)123 void pilot_updateSensorRange (void)
124 {
125 /* Adjust sensor range based on system interference. */
126 /* See: http://www.wolframalpha.com/input/?i=y+%3D+7500+%2F+%28%28x+%2B+200%29+%2F+200%29+from+x%3D0+to+1000 */
127 sensor_curRange = SENSOR_DEFAULT_RANGE / ((cur_system->interference + 200) / 200.);
128
129 /* Speeds up calculations as we compare it against vectors later on
130 * and we want to avoid actually calculating the sqrt(). */
131 sensor_curRange = pow2(sensor_curRange);
132 }
133
134
135 /**
136 * @brief Returns the default sensor range for the current system.
137 *
138 * @return Sensor range.
139 */
pilot_sensorRange(void)140 double pilot_sensorRange( void )
141 {
142 return sensor_curRange;
143 }
144
145
146 /**
147 * @brief Check to see if a position is in range of the pilot.
148 *
149 * @param p Pilot to check to see if position is in their sensor range.
150 * @param x X position to check.
151 * @param y Y position to check.
152 * @return 1 if the position is in range, 0 if it isn't.
153 */
pilot_inRange(const Pilot * p,double x,double y)154 int pilot_inRange( const Pilot *p, double x, double y )
155 {
156 double d, sense;
157
158 /* Get distance. */
159 d = pow2(x-p->solid->pos.x) + pow2(y-p->solid->pos.y);
160
161 sense = sensor_curRange * p->ew_detect;
162 if (d < sense)
163 return 1;
164
165 return 0;
166 }
167
168
169 /**
170 * @brief Check to see if a pilot is in sensor range of another.
171 *
172 * @param p Pilot who is trying to check to see if other is in sensor range.
173 * @param target Target of p to check to see if is in sensor range.
174 * @return 1 if they are in range, 0 if they aren't and -1 if they are detected fuzzily.
175 */
pilot_inRangePilot(const Pilot * p,const Pilot * target)176 int pilot_inRangePilot( const Pilot *p, const Pilot *target )
177 {
178 double d, sense;
179
180 /* Special case player or omni-visible. */
181 if ((pilot_isPlayer(p) && pilot_isFlag(target, PILOT_VISPLAYER)) ||
182 pilot_isFlag(target, PILOT_VISIBLE) ||
183 target->parent == p->id)
184 return 1;
185
186 /* Get distance. */
187 d = vect_dist2( &p->solid->pos, &target->solid->pos );
188
189 sense = sensor_curRange * p->ew_detect;
190 if (d * target->ew_evasion < sense)
191 return 1;
192 else if (d * target->ew_hide < sense)
193 return -1;
194
195 return 0;
196 }
197
198
199 /**
200 * @brief Check to see if a planet is in sensor range of the pilot.
201 *
202 * @param p Pilot who is trying to check to see if the planet is in sensor range.
203 * @param target Planet to see if is in sensor range.
204 * @return 1 if they are in range, 0 if they aren't.
205 */
pilot_inRangePlanet(const Pilot * p,int target)206 int pilot_inRangePlanet( const Pilot *p, int target )
207 {
208 double d;
209 Planet *pnt;
210 double sense;
211
212 /* pilot must exist */
213 if ( p == NULL )
214 return 0;
215
216 /* Get the planet. */
217 pnt = cur_system->planets[target];
218
219 /* target must not be virtual */
220 if ( !pnt->real )
221 return 0;
222
223 sense = sensor_curRange * p->ew_detect;
224
225 /* Get distance. */
226 d = vect_dist2( &p->solid->pos, &pnt->pos );
227
228 if (d * pnt->hide < sense )
229 return 1;
230
231 return 0;
232 }
233
234 /**
235 * @brief Check to see if a jump point is in sensor range of the pilot.
236 *
237 * @param p Pilot who is trying to check to see if the jump point is in sensor range.
238 * @param target Jump point to see if is in sensor range.
239 * @return 1 if they are in range, 0 if they aren't.
240 */
pilot_inRangeJump(const Pilot * p,int i)241 int pilot_inRangeJump( const Pilot *p, int i )
242 {
243 double d;
244 JumpPoint *jp;
245 double sense;
246 double hide;
247
248 /* pilot must exist */
249 if ( p == NULL )
250 return 0;
251
252 /* Get the jump point. */
253 jp = &cur_system->jumps[i];
254
255 /* We don't want exit-only jumps. */
256 if (jp_isFlag(jp, JP_EXITONLY))
257 return 0;
258
259 /* Handle hidden jumps separately, as they use a special range parameter. */
260 if (jp_isFlag(jp, JP_HIDDEN))
261 sense = pow(p->stats.misc_hidden_jump_detect, 2);
262 else
263 sense = sensor_curRange * p->ew_jump_detect;
264
265 hide = jp->hide;
266
267 /* Get distance. */
268 d = vect_dist2( &p->solid->pos, &jp->pos );
269
270 if (d * hide < sense)
271 return 1;
272
273 return 0;
274 }
275
276 /**
277 * @brief Calculates the weapon lead (1. is 100%, 0. is 0%)..
278 *
279 * @param p Pilot tracking.
280 * @param t Pilot being tracked.
281 * @param track Track limit of the weapon.
282 * @return The lead angle of the weapon.
283 */
pilot_ewWeaponTrack(const Pilot * p,const Pilot * t,double track)284 double pilot_ewWeaponTrack( const Pilot *p, const Pilot *t, double track )
285 {
286 double limit, lead;
287
288 limit = track * p->ew_detect;
289 if (t->ew_evasion * t->ew_movement < limit)
290 lead = 1.;
291 else
292 lead = MAX( 0., 1. - 0.5*((t->ew_evasion * t->ew_movement)/limit - 1.));
293 return lead;
294 }
295
296
297
298