9
|
1 /*--------------------------------------------------------------------------
|
|
2 NETREK II -- Paradise
|
|
3
|
|
4 Permission to use, copy, modify, and distribute this software and its
|
|
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
|
|
6 purpose and without fee is hereby granted, provided that this copyright
|
|
7 notice appear in all copies. No representations are made about the
|
|
8 suitability of this software for any purpose. This software is provided
|
|
9 "as is" without express or implied warranty.
|
|
10
|
|
11 Xtrek Copyright 1986 Chris Guthrie
|
|
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
|
|
13 Scott Silvey
|
|
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
|
|
15 Kurt Olsen
|
|
16 Brandon Gillespie
|
|
17 --------------------------------------------------------------------------*/
|
|
18
|
|
19 #include "config.h"
|
|
20
|
|
21 #include <stdio.h>
|
|
22 #include <stdlib.h>
|
|
23 #include <string.h>
|
|
24 #include <math.h>
|
|
25 #include <setjmp.h>
|
|
26
|
|
27 #include "defs.h"
|
|
28 #include "struct.h"
|
|
29 #include "data.h"
|
|
30 #include "daemonII.h"
|
|
31 #include "weapons.h"
|
|
32 #include "shmem.h"
|
|
33
|
|
34
|
|
35
|
|
36 /*------------------------------VISIBLE FUNCTIONS-------------------------*/
|
|
37
|
|
38 /*---------------------------------HOSTILE_TO-----------------------------*/
|
|
39 /*
|
|
40 * This returns whether an object is hostile to another object. It returns 1
|
|
41 * if we are hostile or at war with the object
|
|
42 */
|
|
43
|
|
44
|
|
45 extern int inflict_damage();
|
|
46 int torp_track_opportunity();
|
|
47 extern void move_torp();
|
|
48 extern void move_missile();
|
|
49
|
|
50 int
|
|
51 hostile_to(warmask, team, pl)
|
|
52 int warmask, team;
|
|
53 struct player *pl;
|
|
54 {
|
|
55 return (warmask & pl->p_team) || (team & (pl->p_swar | pl->p_hostile));
|
|
56 }
|
|
57
|
|
58
|
|
59
|
|
60
|
|
61 /*----------------------------------EXPLODE-------------------------------*/
|
|
62 /*
|
|
63 * This function decides which players to inflict damage on when a torp
|
|
64 * explodes.
|
|
65 */
|
|
66
|
|
67 void
|
|
68 explode_damage(torp, radius, why)
|
|
69 struct basetorp *torp;
|
|
70 int radius;
|
|
71 int why;
|
|
72 {
|
|
73 register int i; /* looping var */
|
|
74 int dx, dy, dist; /* to calc distance from torp to players */
|
|
75 int damage; /* to hold damage inflicted */
|
|
76 register struct player *j; /* to point to players */
|
|
77
|
|
78 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
|
|
79 {
|
|
80 if (j->p_status != PALIVE) /* no need to check players not alive */
|
|
81 continue;
|
|
82
|
|
83 if (j->p_no == torp->bt_owner) /* General Vote, September, 1995. */
|
|
84 continue; /* Torps no longer damage owner. */
|
|
85
|
|
86 if ((torp->bt_status == TDET) /* if torp was detted then */
|
|
87 && ((j->p_no == torp->bt_owner) || /* cannot damage firing
|
|
88 * player */
|
|
89 ((j->p_no != torp->bt_whodet) /* cannot damage players on
|
|
90 * same team */
|
|
91 && (j->p_team == players[torp->bt_whodet].p_team)))
|
|
92 ) /* except the detter */
|
|
93 continue;
|
|
94
|
|
95 dx = torp->bt_x - j->p_x; /* calc delta x and y */
|
|
96 dy = torp->bt_y - j->p_y;
|
|
97 if (ABS(dx) > radius || ABS(dy) > radius)
|
|
98 continue; /* continue if obviously too far */
|
|
99
|
|
100 dist = dx * dx + dy * dy; /* calc distnace squared */
|
|
101 if (dist > radius * radius) /* if not within damage distance */
|
|
102 continue; /* then continue */
|
|
103 if (dist > EXPDIST * EXPDIST) /* if not direct hit */
|
|
104 damage = torp->bt_damage * (radius - sqrt((double) dist)) /
|
|
105 (radius - EXPDIST);
|
|
106 else /* else if direct hit */
|
|
107 damage = torp->bt_damage; /* do torp damage */
|
|
108
|
|
109 if (damage > 0)
|
|
110 { /* if damage was done then */
|
|
111 if (players[torp->bt_owner].p_hostile & j->p_team) /* start war if */
|
|
112 players[torp->bt_owner].p_swar |= j->p_team; /* necessary */
|
|
113 inflict_damage(&players[torp->bt_owner], &players[torp->bt_whodet],
|
|
114 j, damage, why);
|
|
115 }
|
|
116 }
|
|
117 }
|
|
118
|
|
119 void
|
|
120 explode(torp)
|
|
121 struct basetorp *torp; /* pointer to exploding torp's struct */
|
|
122 {
|
|
123 explode_damage(torp, DAMDIST, KTORP);
|
|
124 torp->bt_status = TEXPLODE; /* set the torp to explode */
|
|
125 torp->bt_fuse = 10 / TORPFUSE;
|
|
126 }
|
|
127
|
|
128
|
|
129
|
|
130
|
|
131 /*---------------------------------PEXPLODE-------------------------------*/
|
|
132 /*
|
|
133 * This function does the explosion of a plasma torp. It goes through all
|
|
134 * players and damages them if they are close enough to get damaged
|
|
135 */
|
|
136
|
|
137 void
|
|
138 pexplode(plasmatorp)
|
|
139 struct plasmatorp *plasmatorp;/* ptr to plasma to explode */
|
|
140 {
|
|
141 explode_damage(&plasmatorp->pt_base, PLASDAMDIST, KPLASMA);
|
|
142 plasmatorp->pt_status = PTEXPLODE; /* set the plasma to explode */
|
|
143 plasmatorp->pt_fuse = 10 / PLASMAFUSE;
|
|
144 }
|
|
145
|
|
146
|
|
147
|
|
148
|
|
149 /*-------------------------------UDPHASER----------------------------------*/
|
|
150 /*
|
|
151 * This function goes through all players and calcs the damage from a phaser
|
|
152 * hit if the phaser hit a target.
|
|
153 */
|
|
154
|
|
155 void
|
|
156 udphaser()
|
|
157 {
|
|
158 register int i; /* looping var */
|
|
159 register struct phaser *j; /* to point to phaser being fired */
|
|
160 register struct player *victim; /* to point to the poor victim */
|
|
161
|
|
162 for (i = 0, j = &phasers[i]; i < MAXPLAYER; i++, j++)
|
|
163 { /* all players */
|
|
164 switch (j->ph_status)
|
|
165 { /* check player's phaser status */
|
|
166 case PHFREE: /* if not beging fired */
|
|
167 continue; /* then continue */
|
|
168 case PHMISS: /* if it missed */
|
|
169 case PHHIT2: /* or ????? */
|
|
170 if (j->ph_fuse-- == 1) /* dec count of phaser */
|
|
171 j->ph_status = PHFREE; /* free it up if count done */
|
|
172 break;
|
|
173 case PHHIT: /* if it hit someone then */
|
|
174 if (j->ph_fuse-- == players[i].p_ship.s_phaser.fuse)
|
|
175 {
|
|
176 victim = &players[j->ph_target]; /* get the victim */
|
|
177 if (players[i].p_hostile & victim->p_team) /* start war if */
|
|
178 players[i].p_swar |= victim->p_team; /* necessary */
|
|
179 if (victim->p_status == PALIVE) /* only damage if alive */
|
|
180 inflict_damage(&players[i], 0, victim, j->ph_damage, KPHASER);
|
|
181 } /* end of if phaser hit someone */
|
|
182 if (j->ph_fuse == 0)
|
|
183 j->ph_status = PHFREE;
|
|
184 break;
|
|
185 } /* end of switch */
|
|
186 } /* end of for loop through players */
|
|
187 }
|
|
188
|
|
189
|
|
190
|
|
191 /*----------------------------WEAP_NEAR_OBJECT-----------------------------*/
|
|
192 /* This function checks for objects within *dist* of a weapon. */
|
|
193 /* this function will use the space grid */
|
|
194
|
|
195 int
|
|
196 weap_near_object(torp, type, dist)
|
|
197 struct basetorp *torp;
|
|
198 int type;
|
|
199 int dist;
|
|
200 {
|
|
201 register struct planet *pl; /* to point to the planets */
|
|
202 int dx, dy, i;
|
|
203
|
|
204 for (i = 0, pl = &planets[i]; i < NUMPLANETS; i++, pl = &planets[i])
|
|
205 {
|
|
206 if (PL_TYPE(*pl) != type)
|
|
207 /* if not of the type specified, don't bother */
|
|
208 continue;
|
|
209 dx = torp->bt_x - pl->pl_x;
|
|
210 dy = torp->bt_y - pl->pl_y;
|
|
211 if (ABS(dx) > dist || ABS(dy) > dist)
|
|
212 continue; /* the obvious thing */
|
|
213 if (dx * dx + dy * dy < dist * dist)
|
|
214 return 1; /* yep, it hit. return a 1. */
|
|
215 }
|
|
216 return 0; /* return that it should continue */
|
|
217 }
|
|
218
|
|
219
|
|
220 #if 0 /* I think this is now unused */
|
|
221 /*----------------------------------NEAR----------------------------------*/
|
|
222 /*
|
|
223 * This function checks to see if a player is close enough to a torp for the
|
|
224 * torp to explode on. This function returns a 1 if the torp should explode
|
|
225 * and a zero if not.
|
|
226 */
|
|
227
|
|
228 int
|
|
229 near(torp)
|
|
230 struct torp *torp; /* the torp to check for */
|
|
231 {
|
|
232 #if 1
|
|
233 return near_player(&torp->t_base, EXPDIST);
|
|
234 #else
|
|
235 register int i; /* looping var */
|
|
236 int dx, dy; /* to calc torp-player distance */
|
|
237 register struct player *j; /* to point to players */
|
|
238
|
|
239 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
|
|
240 {
|
|
241 if (j->p_status != PALIVE)
|
|
242 continue; /* don't check players not alive */
|
|
243 if (j->p_no == torp->t_owner)
|
|
244 continue; /* no exploding on self */
|
|
245 if (!hostile_to(torp->t_war, torp->t_team, j))
|
|
246 continue; /* disregard if both teams not at war */
|
|
247 dx = torp->t_x - j->p_x; /* calc delta coords */
|
|
248 dy = torp->t_y - j->p_y;
|
|
249 if (ABS(dx) > EXPDIST || ABS(dy) > EXPDIST)
|
|
250 continue; /* disregard if obviously too far */
|
|
251 if (dx * dx + dy * dy < EXPDIST * EXPDIST)
|
|
252 return 1; /* if close enough to explode then return 1 */
|
|
253 }
|
|
254 return 0; /* return that torp should continue */
|
|
255 #endif
|
|
256 }
|
|
257 #endif
|
|
258
|
|
259 int
|
|
260 near_player(torp, dist)
|
|
261 struct basetorp *torp; /* the torp to check for */
|
|
262 int dist;
|
|
263 {
|
|
264 register int i; /* looping var */
|
|
265 int dx, dy; /* to calc torp-player distance */
|
|
266 register struct player *j; /* to point to players */
|
|
267
|
|
268 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
|
|
269 {
|
|
270 if (j->p_status != PALIVE)
|
|
271 continue; /* don't check players not alive */
|
|
272 if (j->p_no == torp->bt_owner)
|
|
273 continue; /* no exploding on self */
|
|
274 if (!hostile_to(torp->bt_war, torp->bt_team, j))
|
|
275 continue; /* disregard if both teams not at war */
|
|
276 dx = torp->bt_x - j->p_x; /* calc delta coords */
|
|
277 dy = torp->bt_y - j->p_y;
|
|
278 if (ABS(dx) > dist || ABS(dy) > dist)
|
|
279 continue; /* disregard if obviously too far */
|
|
280 if (dx * dx + dy * dy < dist * dist)
|
|
281 {
|
|
282 torp->bt_whodet = i; /* this guy is the detonator */
|
|
283 return 1; /* if close enough to explode then return 1 */
|
|
284 }
|
|
285 }
|
|
286 return 0; /* return that torp should continue */
|
|
287 }
|
|
288
|
|
289
|
|
290 int
|
|
291 f_land(mis) /* the fighter landing function */
|
|
292 struct missile *mis; /* the fighter to check for */
|
|
293 {
|
|
294 int dx, dy; /* to calc fighter-player distance */
|
|
295 register struct player *j; /* to point to players */
|
|
296
|
|
297 j = &players[mis->ms_owner];
|
|
298
|
|
299 if (!(j->p_armies < j->p_ship.s_maxarmies))
|
|
300 return 0; /* no room! */
|
|
301 dx = mis->ms_x - j->p_x; /* calc delta coords */
|
|
302 dy = mis->ms_y - j->p_y;
|
|
303 if (ABS(dx) > EXPDIST || ABS(dy) > EXPDIST)
|
|
304 return 0; /* obviously too far */
|
|
305 if (dx * dx + dy * dy < EXPDIST * EXPDIST)
|
|
306 return 1; /* if close enough to land then return 1 */
|
|
307
|
|
308 return 0; /* return that fighter should continue */
|
|
309 }
|
|
310
|
|
311
|
|
312 /*----------------------------------PNEAR----------------------------------*/
|
|
313 /*
|
|
314 * This function goes through the players and sees if there is a player close
|
|
315 * enough for a plasma torp to explode on. This function returns a 1 if the
|
|
316 * plasma should explode and a 0 if it should continue to travel through
|
|
317 * spac.
|
|
318 */
|
|
319
|
|
320 int
|
|
321 pnear(plasmatorp)
|
|
322 struct plasmatorp *plasmatorp;/* the plasma torp to check for */
|
|
323 {
|
|
324 #if 1
|
|
325 return near_player(&plasmatorp->pt_base, EXPDIST);
|
|
326 #else
|
|
327 register int i; /* looping var */
|
|
328 int dx, dy; /* to calc distances with */
|
|
329 register struct player *j; /* to point to players */
|
|
330 /* fprintf(stderr, "ENTERING PNEAR\n"); */
|
|
331 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
|
|
332 {
|
|
333 if (!(j->p_status == PALIVE))
|
|
334 continue; /* don't check players not alive */
|
|
335 if (plasmatorp->pt_owner == j->p_no)
|
|
336 continue; /* no exploding on self */
|
|
337 if (!hostile_to(plasmatorp->pt_war, plasmatorp->pt_team, j))
|
|
338 continue; /* disregard if both teams not at war */
|
|
339 dx = plasmatorp->pt_x - j->p_x; /* calc delta coords */
|
|
340 dy = plasmatorp->pt_y - j->p_y;
|
|
341 /* fprintf(stderr, "ENTERING UDORPS #1\n"); */
|
|
342 if (ABS(dx) > EXPDIST || ABS(dy) > EXPDIST)
|
|
343 continue; /* disregard if obviously too far */
|
|
344 /* fprintf(stderr, "ENTERING UDORPS #2\n"); */
|
|
345 if (dx * dx + dy * dy < EXPDIST * EXPDIST)
|
|
346 return 1; /* if close enough to explode then return 1 */
|
|
347 /* fprintf(stderr, "ENTERING UDORPS #3\n"); */
|
|
348 }
|
|
349 return 0; /* return that plasma torp should continue */
|
|
350 #endif
|
|
351 }
|
|
352
|
|
353
|
|
354 int
|
|
355 outofbounds(x, y)
|
|
356 int x, y;
|
|
357 {
|
|
358 return x < 0 || x > GWIDTH || y < 0 || y > GWIDTH;
|
|
359 }
|
|
360
|
|
361 /*--------------------------------UDTORPS----------------------------------*/
|
|
362 /*
|
|
363 * This function updates the torps. It goes through all torps and checks to
|
|
364 * see if they need to be updated. It they are mving they track toward the
|
|
365 * nearest target. this function also handles the explosion and makes sure
|
|
366 * that torps do not go off the edge of the galaxy.
|
|
367 */
|
|
368
|
|
369 void
|
|
370 udtorps()
|
|
371 {
|
|
372 register int i; /* looping var--to loop through torps */
|
|
373 int turn; /* to get whether to go right or left */
|
|
374 int heading; /* to hold torps heading */
|
|
375 register struct torp *j; /* to point to torps */
|
|
376
|
|
377 for (i = 0, j = &torps[i]; i < MAXPLAYER * MAXTORP; i++, j++)
|
|
378 {
|
|
379 switch (j->t_status)
|
|
380 { /* check status of torp */
|
|
381 case TFREE: /* if torp not active then */
|
|
382 continue; /* go on to next torp */
|
|
383 case TMOVE:
|
|
384 case TSTRAIGHT: /* if torp moving then */
|
|
385 if (j->t_turns > 0)
|
|
386 { /* if torp can turn then */
|
|
387 turn = torp_track_opportunity
|
|
388 (&j->t_base, j->t_turns,
|
|
389 configvals->improved_tracking[SS_PHOTON]);
|
|
390 /* should we go right or left */
|
|
391 if (turn < 0)
|
|
392 { /* we will go left */
|
|
393 heading = ((int) j->t_dir) - j->t_turns; /* turn left */
|
|
394 if (heading < 0)
|
|
395 j->t_dir = heading + 256;
|
|
396 /*
|
|
397 * j->t_dir = ((heading < 0) ? ((unsigned char) (256 + heading)) :
|
|
398 * ((unsigned char) heading)); * no underflow
|
|
399 */
|
|
400 }
|
|
401 else if (turn > 0)
|
|
402 { /* we will go right */
|
|
403 heading = ((int) j->t_dir) + j->t_turns; /* turn right */
|
|
404 if (heading > 255)
|
|
405 j->t_dir = heading - 256;
|
|
406 /*
|
|
407 * j->t_dir = ((heading > 255) ? ((unsigned char) (heading - 256))
|
|
408 * : ((unsigned char) heading)); * no overflow
|
|
409 */
|
|
410 }
|
|
411 }
|
|
412 j->t_x += (double) j->t_speed * Cos[j->t_dir] * WARP1;
|
|
413 j->t_y += (double) j->t_speed * Sin[j->t_dir] * WARP1;
|
|
414
|
|
415 #if 0
|
|
416 if (outofbounds(j->t_x, j->t_y))
|
|
417 { /* hit top wall? */
|
|
418 j->t_status = TEXPLODE; /* so you cannot wall kill */
|
|
419 j->t_whodet = j->t_owner;
|
|
420 /* explode(&j->t_base); eliminate self wallkills */
|
|
421 break; /* done with this torp */
|
|
422 }
|
|
423 #endif
|
|
424
|
|
425 move_torp(i, j->t_x, j->t_y, 1);
|
|
426
|
|
427 if (j->t_status == TMOVE) /* if a TMOVE torp then */
|
|
428 j->t_dir += (lrand48() % 3) - 1; /* make the torp wobble */
|
|
429 if (j->t_fuse-- <= 0)
|
|
430 { /* dec torp's life and see if dead */
|
|
431 j->t_status = TFREE; /* dead, free the torp */
|
|
432 move_torp(i, -1, -1, 1);
|
|
433 players[j->t_owner].p_ntorp--; /* let player fire another */
|
|
434 break; /* no more torp processing */
|
|
435 }
|
|
436 if ((sun_effect[SS_PHOTON] && weap_near_object(&j->t_base, PLSTAR, ORBDIST))
|
|
437 ||
|
|
438 (wh_effect[SS_PHOTON] && weap_near_object(&j->t_base, PLWHOLE, ORBDIST)))
|
|
439 {
|
|
440 /* did it hit a star or wormhole? */
|
|
441 j->t_whodet = j->t_owner;
|
|
442 explode(&j->t_base);
|
|
443 break;
|
|
444 }
|
|
445
|
|
446 if ((terrain_grid[(int) (j->t_x) / TGRID_GRANULARITY * TGRID_SIZE +
|
|
447 (int) (j->t_y) / TGRID_GRANULARITY].types
|
|
448 & T_ASTEROIDS) &&
|
|
449 ast_effect[SS_PHOTON])
|
|
450 if (TORP_HIT_AST > (lrand48() % 100))
|
|
451 {
|
|
452 explode(&j->t_base);
|
|
453 break;
|
|
454 }
|
|
455
|
|
456 if (near_player(&j->t_base, EXPDIST))
|
|
457 {
|
|
458 /* if torp near enough to hit */
|
|
459 explode(&j->t_base); /* let torp explode on player */
|
|
460 }
|
|
461
|
|
462 break;
|
|
463 case TDET: /* if torp was detted */
|
|
464 explode(&j->t_base); /* make it explode */
|
|
465 break; /* on to next torp */
|
|
466 case TEXPLODE: /* if torp exploding */
|
|
467 if (j->t_fuse-- <= 0)
|
|
468 { /* dec explosion timer */
|
|
469 j->t_status = TFREE; /* if torp done, free it up */
|
|
470 move_torp(i, -1, -1, 1);
|
|
471 players[j->t_owner].p_ntorp--; /* let player fire another */
|
|
472 }
|
|
473 break; /* on to next torp */
|
|
474 case TOFF:
|
|
475 j->t_status = TFREE;
|
|
476 move_torp(i, -1, -1, 1);
|
|
477 players[j->t_owner].p_ntorp--;
|
|
478 break;
|
|
479 default: /* Shouldn't happen */
|
|
480 j->t_status = TFREE;
|
|
481 break;
|
|
482 } /* end of switch */
|
|
483 } /* end of for */
|
|
484 }
|
|
485
|
|
486 void
|
|
487 udmissiles()
|
|
488 {
|
|
489 int i;
|
|
490 int x, y, turn;
|
|
491 struct missile *mis;
|
|
492 struct player *j;
|
|
493
|
|
494 for (i = 0; i < MAXPLAYER * NPTHINGIES; i++)
|
|
495 {
|
|
496 mis = &missiles[i];
|
|
497 switch (mis->ms_status)
|
|
498 {
|
|
499 case TFREE:
|
|
500 break;
|
|
501 case TLAND:
|
|
502 j = &players[mis->ms_owner];
|
|
503 j->p_ship.s_missilestored++;
|
|
504 j->p_armies = (int) (j->p_ship.s_missilestored / FAE_RATE);
|
|
505 mis->ms_status = TFREE;
|
|
506 j->p_nthingys--;
|
|
507 break;
|
|
508 #if 0
|
|
509 case TRETURN:
|
|
510 j = &players[mis->ms_owner];
|
|
511 if (!(j->p_ship.s_nflags & SFNHASFIGHTERS))
|
|
512 {
|
|
513 mis->ms_type = MISSILETHINGY; /* If the player no longer has em, */
|
|
514 mis->ms_status = TMOVE; /* make his fighters kamikazes */
|
|
515 mis->fi_hasfired = 0;
|
|
516 break;
|
|
517 }
|
|
518
|
|
519
|
|
520 if (mis->ms_fuse-- <= 0)
|
|
521 {
|
|
522 mis->ms_status = TFREE;
|
|
523 move_missile(i, -1, -1, 1);
|
|
524 break;
|
|
525 }
|
|
526
|
|
527 if (((sun_effect[SS_MISSILE] && mis->ms_type == MISSILETHINGY
|
|
528 || sun_effect[SS_FIGHTER] && mis->ms_type == FIGHTERTHINGY)
|
|
529 && weap_near_object(&mis->ms_base, PLSTAR, ORBDIST)) ||
|
|
530 ((wh_effect[SS_MISSILE] && mis->ms_type == MISSILETHINGY
|
|
531 || wh_effect[SS_FIGHTER] && mis->ms_type == FIGHTERTHINGY)
|
|
532 && weap_near_object(&mis->ms_base, PLWHOLE, ORBDIST)))
|
|
533 {
|
|
534 /* did it hit a star or wormhole? */
|
|
535 explode(&mis->ms_base);
|
|
536 break;
|
|
537 }
|
|
538 if (mis->ms_turns > 0)
|
|
539 {
|
|
540 turn = fighter_track_target(&mis->ms_base, mis->ms_turns);
|
|
541 mis->ms_dir = (unsigned char) (mis->ms_dir + turn * mis->ms_turns);
|
|
542 }
|
|
543 x = mis->ms_x + mis->ms_speed * Cos[mis->ms_dir] * WARP1;
|
|
544 y = mis->ms_y + mis->ms_speed * Sin[mis->ms_dir] * WARP1;
|
|
545 move_missile(i, x, y, 1);
|
|
546
|
|
547 if (mis->ms_fuse-- <= 0)
|
|
548 {
|
|
549 mis->ms_status = TFREE;
|
|
550 move_missile(i, -1, -1, 1);
|
|
551 }
|
|
552 else if (f_land(mis))
|
|
553 {
|
|
554 mis->ms_status = TLAND;
|
|
555 move_missile(i, -1, -1, 1);
|
|
556 }
|
|
557 break;
|
|
558 #endif
|
|
559 case TRETURN:
|
|
560 case TMOVE:
|
|
561 case TSTRAIGHT:
|
|
562
|
|
563 if (mis->ms_fuse-- <= 0)
|
|
564 {
|
|
565 mis->ms_status = TFREE;
|
|
566 move_missile(i, -1, -1, 1);
|
|
567 break;
|
|
568 }
|
|
569
|
|
570 if (terrain_grid[(int) (mis->ms_x) / TGRID_GRANULARITY * TGRID_SIZE +
|
|
571 (int) (mis->ms_y) / TGRID_GRANULARITY].types
|
|
572 & T_ASTEROIDS)
|
|
573 if ((mis->ms_type == FIGHTERTHINGY) &&
|
|
574 ast_effect[SS_FIGHTER] &&
|
|
575 (FIGHTER_HIT_AST > (lrand48() % 100)))
|
|
576 {
|
|
577 mis->ms_whodet = mis->ms_owner;
|
|
578 explode(&mis->ms_base);
|
|
579 break;
|
|
580 }
|
|
581 else if ((MISSILE_HIT_AST > (lrand48() % 100)) &&
|
|
582 ast_effect[SS_MISSILE])
|
|
583 {
|
|
584 mis->ms_whodet = mis->ms_owner;
|
|
585 explode(&mis->ms_base);
|
|
586 break;
|
|
587 }
|
|
588
|
|
589 if ((((sun_effect[SS_MISSILE] && mis->ms_type == MISSILETHINGY)
|
|
590 || (sun_effect[SS_FIGHTER] && mis->ms_type == FIGHTERTHINGY))
|
|
591 && weap_near_object(&mis->ms_base, PLSTAR, ORBDIST))
|
|
592 ||
|
|
593 (((wh_effect[SS_MISSILE] && mis->ms_type == MISSILETHINGY)
|
|
594 || (wh_effect[SS_FIGHTER] && mis->ms_type == FIGHTERTHINGY))
|
|
595 && weap_near_object(&mis->ms_base, PLWHOLE, ORBDIST)))
|
|
596 {
|
|
597 /* did it hit a star? */
|
|
598 explode(&mis->ms_base);
|
|
599 break;
|
|
600 }
|
|
601
|
|
602 j = &players[mis->ms_owner];
|
|
603
|
|
604 if (mis->ms_type == FIGHTERTHINGY &&
|
|
605 !(j->p_ship.s_nflags & SFNHASFIGHTERS))
|
|
606 {
|
|
607 mis->ms_type = MISSILETHINGY; /* If the player no longer has em, */
|
|
608 mis->ms_status = TMOVE; /* make his fighters kamikazes */
|
|
609 mis->fi_hasfired = 0;
|
|
610 break;
|
|
611 }
|
|
612
|
|
613 if ((mis->ms_type == FIGHTERTHINGY)
|
|
614 && ((mis->ms_fuse < .6 * j->p_ship.s_missile.fuse)
|
|
615 || (mis->fi_hasfired))
|
|
616 && mis->ms_status != TRETURN)
|
|
617 mis->ms_status = TRETURN;
|
|
618
|
|
619 if (mis->ms_turns > 0)
|
|
620 {
|
|
621 if (mis->ms_type == FIGHTERTHINGY)
|
|
622 {
|
|
623 turn = fighter_track_target(&mis->ms_base, mis->ms_turns);
|
|
624 }
|
|
625 else
|
|
626 {
|
|
627 turn = torp_track_opportunity
|
|
628 (&mis->ms_base, mis->ms_turns,
|
|
629 configvals->improved_tracking[SS_MISSILE]);
|
|
630 }
|
|
631 mis->ms_dir = (unsigned char) (mis->ms_dir + turn * mis->ms_turns);
|
|
632 }
|
|
633 x = mis->ms_x + mis->ms_speed * Cos[mis->ms_dir] * WARP1;
|
|
634 y = mis->ms_y + mis->ms_speed * Sin[mis->ms_dir] * WARP1;
|
|
635
|
|
636 #if 0
|
|
637 if (outofbounds(x, y))
|
|
638 {
|
|
639 explode(&mis->ms_base);
|
|
640 break;
|
|
641 }
|
|
642 #endif
|
|
643
|
|
644 move_missile(i, x, y, 1);
|
|
645
|
|
646 if (mis->ms_status != TSTRAIGHT)
|
|
647 mis->ms_dir += (lrand48() % 3) - 1;
|
|
648
|
|
649 if (mis->ms_type == MISSILETHINGY
|
|
650 && near_player(&mis->ms_base, EXPDIST))
|
|
651 {
|
|
652 explode(&mis->ms_base);
|
|
653 }
|
|
654 else if (mis->ms_type == FIGHTERTHINGY
|
|
655 && near_player(&mis->ms_base, FSTRIKEDIST)
|
|
656 && !mis->fi_hasfired)
|
|
657 {
|
|
658 if (f_torp(mis))
|
|
659 mis->fi_hasfired = 1; /* if within strike range, fire a torp */
|
|
660 }
|
|
661
|
|
662 if (mis->ms_status == TRETURN &&
|
|
663 f_land(mis))
|
|
664 {
|
|
665 mis->ms_status = TLAND;
|
|
666 move_missile(i, -1, -1, 1);
|
|
667 }
|
|
668
|
|
669 break;
|
|
670
|
|
671 case TDET:
|
|
672 explode(&mis->ms_base);
|
|
673 break;
|
|
674
|
|
675 case TEXPLODE:
|
|
676 if (mis->ms_fuse-- <= 0)
|
|
677 {
|
|
678 mis->ms_status = TFREE;
|
|
679 players[mis->ms_owner].p_nthingys--;
|
|
680 move_missile(i, -1, -1, 1);
|
|
681 }
|
|
682 break;
|
|
683 default:
|
|
684 mis->ms_status = TFREE;
|
|
685 break;
|
|
686 }
|
|
687 }
|
|
688 }
|
|
689
|
|
690 int
|
|
691 anticipate_impact(w, dx, dy, s, dir)
|
|
692 int w; /* speed of torp */
|
|
693 int dx, dy; /* distance to target */
|
|
694 int s, dir; /* speed of target */
|
|
695 {
|
|
696 float sdx, sdy;
|
|
697 float a, b, c, d;
|
|
698 float t;
|
|
699 float tdx, tdy;
|
|
700 float theta;
|
|
701
|
|
702 #if 1 /* mathematically, these affect t, but not
|
|
703 * the return value */
|
|
704 s *= WARP1 * TICKSPERSEC;
|
|
705 w *= WARP1 * TICKSPERSEC;
|
|
706 #endif
|
|
707
|
|
708 sdx = s * Cos[dir];
|
|
709 sdy = s * Sin[dir];
|
|
710
|
|
711 a = s * (float) s - w * (float) w;
|
|
712 b = 2 * (sdx * (float) dx + sdy * (float) dy);
|
|
713 c = dx * (float) dx + dy * (float) dy;
|
|
714
|
|
715 if (a == 0)
|
|
716 {
|
|
717 t = -c / b;
|
|
718 }
|
|
719 else
|
|
720 {
|
|
721
|
|
722 d = b * b - 4 * a * c;
|
|
723 if (d < 0)
|
|
724 return -1;
|
|
725 d = sqrt(d);
|
|
726
|
|
727 if (a < 0)
|
|
728 {
|
|
729 a = -a;
|
|
730 b = -b;
|
|
731 }
|
|
732
|
|
733 t = (-b - d) / (2 * a);
|
|
734
|
|
735 if (t < 0)
|
|
736 t = (-b + d) / (2 * a);
|
|
737 }
|
|
738
|
|
739 if (t < 0)
|
|
740 return -1;
|
|
741
|
|
742 if (t > 10)
|
|
743 return -1;
|
|
744
|
|
745 tdx = dx / t + sdx;
|
|
746 tdy = dy / t + sdy;
|
|
747
|
|
748 theta = atan2(tdx, -tdy);
|
|
749 return (unsigned char) (int) (theta * 128 / 3.14159);
|
|
750 }
|
|
751
|
|
752 /*----------------------------TORP_TRACK_OPPORTUNITY----------------------*/
|
|
753 /*
|
|
754 * This function finds the closest ship to a torp and returns -1 if the ship
|
|
755 * is to the left of the torp on its current heading and a 1 if the ship is
|
|
756 * to the right. If no target is found then a 0 is return indicating the
|
|
757 * torp should go straight.
|
|
758 */
|
|
759
|
|
760 int
|
|
761 torp_track_opportunity(torp, turnspeed, smart)
|
|
762 struct basetorp *torp; /* the torp to check for */
|
|
763 int turnspeed;
|
|
764 int smart; /* which tracking algorithm? */
|
|
765 {
|
|
766 int i; /* looping var */
|
|
767 int closest; /* to hold closest player */
|
|
768 int clbearing; /* bearing to closest player */
|
|
769 int min_distsq; /* to hold closest distance */
|
|
770 int war_mask; /* who torp own is at war with */
|
|
771 int x, y; /* to hold torps x, y coords */
|
|
772 int bearing; /* to get bearing to hit player */
|
|
773 int dir; /* to hold torps direction */
|
|
774 int range;
|
|
775
|
|
776 closest = -1; /* initialize closest player--no plyr */
|
|
777 x = torp->bt_x; /* get the coords of torp */
|
|
778 y = torp->bt_y;
|
|
779 dir = torp->bt_dir; /* get torp's directions */
|
|
780 war_mask = torp->bt_war; /* and who he as war with */
|
|
781
|
|
782 range = torp->bt_fuse * torp->bt_speed * WARP1;
|
|
783
|
|
784 min_distsq = range * range * 4; /* intialize closest player distance */
|
|
785
|
|
786 for (i = 0; i < MAXPLAYER; i++)
|
|
787 { /* check all other players */
|
|
788 int dx, dy;
|
|
789 if (!(isAlive(&players[i]) &&
|
|
790 hostile_to(war_mask, torp->bt_team, &players[i])))
|
|
791 continue; /* only do if player alive and at war */
|
|
792
|
|
793 dx = players[i].p_x - x;
|
|
794 dy = players[i].p_y - y;
|
|
795
|
|
796 if (ABS(dx) > range || ABS(dy) > range)
|
|
797 continue; /* clearly out of range */
|
|
798
|
|
799 if (smart)
|
|
800 {
|
|
801 bearing = anticipate_impact(torp->bt_speed, dx, dy,
|
|
802 players[i].p_speed, players[i].p_dir);
|
|
803 if (bearing < 0)
|
|
804 bearing = get_bearing(dx, dy, dir);
|
|
805 else
|
|
806 bearing = (unsigned char) (bearing - dir);
|
|
807 }
|
|
808 else
|
|
809 {
|
|
810 bearing = get_bearing(dx, dy, dir);
|
|
811 }
|
|
812 /* torps will only track to targets they have a reasonable chance */
|
|
813 /* of hitting */
|
|
814 if ((turnspeed * torp->bt_fuse > 127) ||
|
|
815 (bearing < ((unsigned char) turnspeed * torp->bt_fuse)) ||
|
|
816 (bearing > ((unsigned char) (256 - turnspeed * torp->bt_fuse))))
|
|
817 {
|
|
818 int distsq;
|
|
819 distsq = dx * dx + dy * dy;
|
|
820 if (distsq < min_distsq)
|
|
821 { /* record it if it is */
|
|
822 min_distsq = distsq; /* less than current closest */
|
|
823 closest = i; /* player */
|
|
824 clbearing = bearing;
|
|
825 }
|
|
826 }
|
|
827 }
|
|
828 if (closest >= 0)
|
|
829 { /* if a target found then */
|
|
830 if (clbearing > 128)
|
|
831 return (-1); /* Target is on the left */
|
|
832 else
|
|
833 return (1); /* Target is on the right */
|
|
834 }
|
|
835 return (0); /* No target ... go straight. */
|
|
836 }
|
|
837
|
|
838
|
|
839
|
|
840
|
|
841 /*------------------------------UDPLASMATORPS-----------------------------*/
|
|
842 /*
|
|
843 * This function updates the plasma torps. It goes through all the plasma
|
|
844 * torps and if they are alive it adjusts their heading to track players. It
|
|
845 * then moves the plasma torp and checks to see if the plasma should explode.
|
|
846 * It will ensure that a plasma torp explodes when it hits the edge of the
|
|
847 * galaxy.
|
|
848 */
|
|
849
|
|
850 void
|
|
851 udplasmatorps()
|
|
852 {
|
|
853 register int i; /* looping var--loop through plasmas */
|
|
854 int turn; /* to get whether to go left or right */
|
|
855 int heading; /* to hold plasma heading */
|
|
856 struct plasmatorp *j; /* to point to a plasma */
|
|
857
|
|
858 for (i = 0, j = &plasmatorps[i]; i < MAXPLAYER * MAXPLASMA; i++, j++)
|
|
859 {
|
|
860 switch (j->pt_status)
|
|
861 { /* check torp's status */
|
|
862 case PTFREE: /* if plasma not being fired */
|
|
863 continue; /* go to next plasma */
|
|
864 case PTMOVE: /* if plasma moving */
|
|
865 turn = torp_track_opportunity
|
|
866 (&j->pt_base, j->pt_turns,
|
|
867 configvals->improved_tracking[SS_PLASMA]);
|
|
868 /* should we go right or left */
|
|
869 if (turn < 0)
|
|
870 { /* if left then */
|
|
871 heading = ((int) j->pt_dir) - j->pt_turns;
|
|
872 j->pt_dir = ((heading < 0) ? ((unsigned char) (256 + heading)) :
|
|
873 ((unsigned char) heading)); /* no rollunder */
|
|
874 }
|
|
875 else if (turn > 0)
|
|
876 { /* else if right */
|
|
877 heading = ((int) j->pt_dir) + j->pt_turns;
|
|
878 j->pt_dir = ((heading > 255) ? ((unsigned char) (heading - 256)) :
|
|
879 ((unsigned char) heading)); /* no rollover */
|
|
880 }
|
|
881 j->pt_x += (double) j->pt_speed * Cos[j->pt_dir] * WARP1;
|
|
882
|
|
883 #if 0
|
|
884 if (j->pt_x < 0)
|
|
885 { /* if torp at left edge */
|
|
886 j->pt_x = 0; /* set x to left edge */
|
|
887 pexplode(j); /* make torp explode */
|
|
888 break; /* go to next torp */
|
|
889 }
|
|
890 else if (j->pt_x > GWIDTH)
|
|
891 { /* if torp is at right edge */
|
|
892 j->pt_x = GWIDTH; /* set x to right edge */
|
|
893 pexplode(j); /* make torp explode */
|
|
894 break; /* on to next torp */
|
|
895 }
|
|
896 #endif
|
|
897 j->pt_y += (double) j->pt_speed * Sin[j->pt_dir] * WARP1;
|
|
898 #if 0
|
|
899 if (j->pt_y < 0)
|
|
900 { /* if torp at top */
|
|
901 j->pt_y = 0; /* set torp to top edge */
|
|
902 pexplode(j); /* make torp explode */
|
|
903 break; /* on to next torp */
|
|
904 }
|
|
905 else if (j->pt_y > GWIDTH)
|
|
906 { /* if torp is at bottom */
|
|
907 j->pt_y = GWIDTH; /* set y to bottom */
|
|
908 pexplode(j); /* make torp explode */
|
|
909 break; /* on to next torp */
|
|
910 }
|
|
911 #endif
|
|
912
|
|
913 if (j->pt_fuse-- <= 0)
|
|
914 { /* dec the torp fuse. if torp done */
|
|
915 j->pt_status = PTFREE; /* free it up */
|
|
916 players[j->pt_owner].p_nplasmatorp--; /* dec p-torps fired */
|
|
917 break;
|
|
918 }
|
|
919
|
|
920 if ((terrain_grid[(int) (j->pt_x) / TGRID_GRANULARITY * TGRID_SIZE +
|
|
921 (int) (j->pt_y) / TGRID_GRANULARITY].types
|
|
922 & T_ASTEROIDS) &&
|
|
923 ast_effect[SS_PLASMA])
|
|
924 if (PLASMA_HIT_AST > (lrand48() % 100))
|
|
925 {
|
|
926 pexplode(j);
|
|
927 break;
|
|
928 }
|
|
929
|
|
930 if ((sun_effect[SS_PLASMA] && weap_near_object(&j->pt_base, PLSTAR, ORBDIST))
|
|
931 ||
|
|
932 (sun_effect[SS_PLASMA] && weap_near_object(&j->pt_base, PLWHOLE, ORBDIST))
|
|
933 /* did it hit a star? */
|
|
934 || pnear(j) /* or a player */ )
|
|
935 {
|
|
936 pexplode(j);
|
|
937 }
|
|
938 break; /* on to next torp */
|
|
939 case PTDET: /* if torp was detted */
|
|
940 pexplode(j); /* make it explode */
|
|
941 break; /* on to next torp */
|
|
942 case PTEXPLODE: /* if torp is exploding */
|
|
943 if (j->pt_fuse-- <= 0)
|
|
944 { /* dec the timer until torp dead */
|
|
945 j->pt_status = PTFREE; /* set the torp free is timer zero */
|
|
946 players[j->pt_owner].p_nplasmatorp--; /* dec ptorps fired by player */
|
|
947 }
|
|
948 break;
|
|
949 default: /* Shouldn't happen */
|
|
950 j->pt_status = PTFREE; /* free torp if it got screwed */
|
|
951 break; /* on to next torp */
|
|
952 }
|
|
953 }
|
|
954 }
|
|
955
|
|
956
|
|
957
|
|
958 /*--------------------------------GET_BEARING------------------------------*/
|
|
959 /*
|
|
960 * This function takes two set of coordinates and a direction. One set of
|
|
961 * coordinates is the current coords of a trop. The other set is some other
|
|
962 * coords you want to get a change in direction for. The direction is the
|
|
963 * current direction of the torp. The function returns the angle that the
|
|
964 * dir need to be changed by to travel to the new points.
|
|
965 */
|
|
966
|
|
967 unsigned char
|
|
968 get_bearing(dx, dy, dir)
|
|
969 int dx, dy; /* delta x, y coords */
|
|
970 int dir; /* current direction travelling */
|
|
971 {
|
|
972 int phi; /* to hold angle */
|
|
973
|
|
974 phi = (int) (atan2((double) dx, (double) -dy) / 3.14159 * 128.0);
|
|
975 if (phi < 0) /* make phi positive */
|
|
976 phi = 256 + phi;
|
|
977 if (phi >= dir)
|
|
978 return ((unsigned char) (phi - dir));
|
|
979 else
|
|
980 return ((unsigned char) (256 + phi - dir));
|
|
981 }
|
|
982
|
|
983 /*------------------------------------------------------------------------*/
|
|
984
|
|
985
|
|
986
|
|
987
|
|
988 /*------------------------------------------------------------------------*/
|
|
989 /*--------------------------FIGHTER_TRACK_TARGET--------------------------*/
|
|
990 /*
|
|
991 * This function finds the closest ship to a fighter and returns -1 if the
|
|
992 * ship is to the left of the fighter on its current heading and a 1 if the
|
|
993 * ship is to the right. If no target is found then a 0 is return indicating
|
|
994 * the fighter should go straight. Also returns fighters to the CV. If the
|
|
995 * player is locked onto an enemy ship, that's the only ship that gets
|
|
996 * checked.
|
|
997 */
|
|
998
|
|
999 int
|
|
1000 fighter_track_target(mis, turnspeed)
|
|
1001 struct missile *mis; /* the torp to check for */
|
|
1002 int turnspeed;
|
|
1003 {
|
|
1004 int i; /* looping var */
|
|
1005 int closest; /* to hold closest player */
|
|
1006 int min_dist; /* to hold closest distance */
|
|
1007 int dist; /* temp var to hold distance */
|
|
1008 int war_mask; /* who fighter own is at war with */
|
|
1009 int x, y; /* to hold fighters x, y coords */
|
|
1010 int owner; /* to hold fighters owner */
|
|
1011 int bearing; /* to get bearing to hit player */
|
|
1012 int dir; /* to hold fighters direction */
|
|
1013 int range;
|
|
1014 int dx, dy;
|
|
1015
|
|
1016 min_dist = GWIDTH * 2; /* intialize closest player distance */
|
|
1017 closest = -1; /* initialize closest player--no plyr */
|
|
1018 x = mis->ms_x; /* get the coords of torp */
|
|
1019 y = mis->ms_y;
|
|
1020 dir = mis->ms_dir; /* get fighter's directions */
|
|
1021 owner = mis->ms_owner; /* get the fighter's owner */
|
|
1022 war_mask = mis->ms_war; /* and who he as war with */
|
|
1023
|
|
1024 range = mis->ms_fuse * mis->ms_speed * WARP1;
|
|
1025
|
|
1026 for (i = 0; i < MAXPLAYER; i++)
|
|
1027 { /* check all other players */
|
|
1028 if (mis->ms_status == TRETURN)
|
|
1029 {
|
|
1030 if (!(isAlive(&players[i])) || (owner != i))
|
|
1031 continue;
|
|
1032 } /* if returning, only check owning player */
|
|
1033 else if ((players[owner].p_flags & PFPLOCK) &&
|
|
1034 (players[owner].p_playerl != i))
|
|
1035 continue; /* if player is locked onto a player, only
|
|
1036 * check that player */
|
|
1037 else if (!(isAlive(&players[i]) &&
|
|
1038 hostile_to(war_mask, mis->ms_team, &players[i])))
|
|
1039 continue; /* only do if player alive and at war */
|
|
1040
|
|
1041 dx = players[i].p_x - x;
|
|
1042 dy = players[i].p_y - y;
|
|
1043
|
|
1044 if (ABS(dx) > range || ABS(dy) > range)
|
|
1045 continue; /* clearly out of range */
|
|
1046
|
|
1047 bearing = get_bearing(dx, dy, dir);
|
|
1048 if ((turnspeed * mis->ms_fuse > 127) ||
|
|
1049 (bearing < ((unsigned char) turnspeed * mis->ms_fuse)) ||
|
|
1050 (bearing > ((unsigned char) (256 - turnspeed * mis->ms_fuse))))
|
|
1051 {
|
|
1052 dist = ihypot(dx, dy);
|
|
1053 if (dist < min_dist)
|
|
1054 { /* record it if it is */
|
|
1055 min_dist = dist; /* less than current closest */
|
|
1056 closest = i; /* player */
|
|
1057 }
|
|
1058 }
|
|
1059 }
|
|
1060 if (closest >= 0)
|
|
1061 { /* if a target found then */
|
|
1062 if (get_bearing(players[closest].p_x - x,
|
|
1063 players[closest].p_y - y, dir) > 128)
|
|
1064 {
|
|
1065 return (-1); /* Target is on the left */
|
|
1066 }
|
|
1067 else
|
|
1068 return (1); /* Target is on the right */
|
|
1069 }
|
|
1070 return (0); /* No target ... go straight. */
|
|
1071 }
|
|
1072
|
|
1073
|
|
1074 /*--------------------------------------------------------------------------*/
|
|
1075 /*------------------------------------F_TORP--------------------------------*/
|
|
1076 /* Checks to see if a valid target is within a certain forward firing angle */
|
|
1077 /* then fires a torpedo at that target. A return value of 1 indicates firing */
|
|
1078
|
|
1079 int
|
|
1080 f_torp(mis)
|
|
1081 struct missile *mis;
|
|
1082 {
|
|
1083 register int i;
|
|
1084 int torp2fire = -1, targetdist = FSTRIKEDIST + 1, tdist, target;
|
|
1085 unsigned char bearing;
|
|
1086 register struct torp *k;
|
|
1087 int dx, dy;
|
|
1088 register struct player *j; /* to point to players */
|
|
1089
|
|
1090 for (i = mis->ms_owner * MAXTORP, k = &torps[i]; /* Find a free torp */
|
|
1091 i < mis->ms_owner * MAXTORP + MAXTORP; i++, k++)
|
|
1092 if (k->t_status == TFREE)
|
|
1093 {
|
|
1094 torp2fire = i;
|
|
1095 break;
|
|
1096 }
|
|
1097 if (torp2fire == -1)
|
|
1098 return 0;
|
|
1099
|
|
1100
|
|
1101 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
|
|
1102 {
|
|
1103 if (j->p_status != PALIVE)
|
|
1104 continue; /* don't check players not alive */
|
|
1105 if (j->p_no == mis->ms_owner)
|
|
1106 continue; /* no firing on self */
|
|
1107 if (!hostile_to(mis->ms_war, mis->ms_team, j))
|
|
1108 continue; /* disregard if both teams not at war */
|
|
1109 if ((players[mis->ms_owner].p_flags & PFPLOCK) &&
|
|
1110 (players[mis->ms_owner].p_playerl != i))
|
|
1111 continue; /* ignore if this isn't the target */
|
|
1112
|
|
1113 dx = mis->ms_x - j->p_x; /* calc delta coords */
|
|
1114 dy = mis->ms_y - j->p_y;
|
|
1115 if (ABS(dx) > FSTRIKEDIST || ABS(dy) > FSTRIKEDIST)
|
|
1116 continue; /* disregard if obviously too far */
|
|
1117
|
|
1118 tdist = ihypot(dx, dy);
|
|
1119 if (tdist < FSTRIKEDIST)
|
|
1120 {
|
|
1121 bearing = (int) get_bearing(dx, dy, mis->ms_dir);
|
|
1122 targetdist = tdist; /* record the target ship */
|
|
1123 target = i;
|
|
1124 }
|
|
1125 }
|
|
1126
|
|
1127 if (targetdist < FSTRIKEDIST)
|
|
1128 {
|
|
1129 j = &players[mis->ms_owner];
|
|
1130 k = &torps[torp2fire];
|
|
1131 k->t_no = torp2fire;
|
|
1132 k->t_status = TMOVE;
|
|
1133 k->t_owner = mis->ms_owner;
|
|
1134 k->t_team = mis->ms_team;
|
|
1135
|
|
1136 move_torp(torp2fire, mis->ms_x, mis->ms_y, 0);
|
|
1137
|
|
1138 k->t_damage = FTORP_DAMAGE;
|
|
1139 k->t_speed = FTORP_SPEED;
|
|
1140 k->t_war = j->p_hostile |
|
|
1141 j->p_swar;
|
|
1142 k->t_fuse = FTORP_FUSE + (lrand48() % 20);
|
|
1143 k->t_turns = FTORP_TRACK;
|
|
1144
|
|
1145 /*
|
|
1146 * here's the biggie -- what angle do I fire this torp at, so I have a
|
|
1147 * reasonable chance of hitting? Especially since I only get one shot.
|
|
1148 * But, then, I have a bunch of buddies, too...
|
|
1149 */
|
|
1150
|
|
1151 if ((mis->ms_no % MAXPLAYER % 3) == 0)
|
|
1152 k->t_dir = mis->ms_dir;
|
|
1153 else if ((mis->ms_no % MAXPLAYER % 3) == 1)
|
|
1154 k->t_dir = mis->ms_dir - 8;
|
|
1155 else if ((mis->ms_no % MAXPLAYER % 3) == 2)
|
|
1156 k->t_dir = mis->ms_dir + 8;
|
|
1157 return 1;
|
|
1158 }
|
|
1159 return 0;
|
|
1160 }
|
|
1161
|
|
1162
|
|
1163 /*----------END OF FILE--------*/
|