4
|
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 #include <stdio.h>
|
|
21 #include <math.h>
|
|
22 #include <signal.h>
|
|
23 #include "defs.h"
|
|
24 #include "struct.h"
|
|
25 #include "data.h"
|
|
26 #include "weapons.h"
|
|
27 #include "shmem.h"
|
|
28
|
|
29 /*-----------------------------VISIBLE FUNCTIONS---------------------------*/
|
|
30
|
|
31 /*----------------------------------PHASER---------------------------------*/
|
|
32 /*
|
|
33 * This function shoots a phaser for a player. Various conditions are
|
|
34 * checked to see if the phaser should be allowed to fire. If the player can
|
|
35 * fire then, a player is found in the direction the phaser was fired.
|
|
36 */
|
|
37
|
|
38
|
|
39 extern int angdist();
|
|
40
|
|
41 void
|
|
42 phaser(course)
|
|
43 unsigned char course;
|
|
44 {
|
|
45 int i; /* looping var */
|
|
46 struct player *j, *target = 0;/* to hold player found */
|
|
47 struct plasmatorp *k, *target2 = 0; /* to hold plasma torp found */
|
|
48 struct missile *d, *target3 = 0;
|
|
49 struct phaser *mine; /* to pnt to player's phaser */
|
|
50 int whichtarget; /* to hold type of target */
|
|
51 int target_x = 0, target_y = 0; /* target's x and y coords */
|
|
52 unsigned char dir; /* to get direction of phasr */
|
|
53 int range, trange; /* range of target */
|
|
54 int maxangle; /* potential target range */
|
|
55 int myphrange; /* angle to hit potentl targ */
|
|
56 char buf[80]; /* to sprintf warnings into */
|
|
57
|
|
58 mine = &phasers[me->p_no]; /* get phaser struct */
|
|
59 if (!(myship->s_nflags & SFNHASPHASERS))
|
|
60 { /* do we have phasers? */
|
|
61 warning("Weapons Officer: This ship is not armed with phasers, captain!");
|
|
62 return;
|
|
63 }
|
|
64 if (mine->ph_status != PHFREE)
|
|
65 { /* is phaser currently being */
|
|
66 warning("Phasers have not recharged"); /* fired */
|
|
67 return;
|
|
68 }
|
|
69 if (me->p_fuel < myship->s_phaser.cost)
|
|
70 { /* do we have enough fuel */
|
|
71 warning("Not enough fuel for phaser");
|
|
72 return;
|
|
73 }
|
|
74 if (me->p_flags & PFREPAIR)
|
|
75 { /* cannot fire while in */
|
|
76 warning("Can't fire while repairing"); /* repair mode */
|
|
77 return;
|
|
78 }
|
|
79 if (me->p_flags & PFWEP)
|
|
80 { /* cannot fire while weapon */
|
|
81 warning("Weapons overheated"); /* temped */
|
|
82 return;
|
|
83 }
|
|
84 if ((me->p_cloakphase) && (me->p_ship.s_type != ATT))
|
|
85 {
|
|
86 warning("Cannot fire while cloaked"); /* cannot fire while cloaked */
|
|
87 return;
|
|
88 }
|
|
89 if (!check_fire_warp()
|
|
90 || !check_fire_warpprep()
|
|
91 || !check_fire_docked())
|
|
92 return;
|
|
93
|
|
94 me->p_fuel -= myship->s_phaser.cost; /* subtract off fuel cost */
|
|
95 me->p_wtemp += myship->s_phaser.wtemp; /* add to w temp */
|
|
96 mine->ph_dir = course; /* get direction of phaser */
|
|
97 whichtarget = 0; /* no target fount yet */
|
|
98 range = 1000000; /* Sufficiently big. */
|
|
99 /* check the players */
|
|
100 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
|
|
101 { /* loop all players */
|
|
102 if (((j->p_status != PALIVE)
|
|
103 #ifdef PFBIRD
|
|
104 && !(j->p_flags & PFBIRD)
|
|
105 #endif
|
|
106 ) || (j == me)) /* only check alive players */
|
|
107 continue;
|
|
108 if ((!((j->p_swar | j->p_hostile) & me->p_team)) &&
|
|
109 (!((me->p_swar | me->p_hostile) & j->p_team)) &&
|
|
110 #ifdef PFBIRD
|
|
111 !(j->p_flags & PFBIRD)
|
|
112 #endif
|
|
113 )
|
|
114 continue; /* only check at war with */
|
|
115 dir = (unsigned char) (int) (atan2((double) (j->p_x - me->p_x),
|
|
116 (double) (me->p_y - j->p_y)) / 3.14159 * 128.);
|
|
117 /* get range of target */
|
|
118 trange = ihypot(j->p_x - me->p_x, j->p_y - me->p_y);
|
|
119 if (trange == 0) /* don't want zero in atan */
|
|
120 trange = 1;
|
|
121 maxangle = atan((float) EXPDIST / trange) / 3.14159 * 128.0;
|
|
122 if (angdist(dir, course) <= maxangle)
|
|
123 { /* if angle within tolerance */
|
|
124 if (range > trange)
|
|
125 { /* then check to see if */
|
|
126 whichtarget = 1; /* this is the closest target */
|
|
127 target = j; /* found yet */
|
|
128 range = trange; /* record if it is */
|
|
129 }
|
|
130 }
|
|
131 } /* check the plasmas */
|
|
132 for (i = 0, k = &plasmatorps[i]; i < MAXPLASMA * MAXPLAYER; i++, k++)
|
|
133 {
|
|
134 if ((k->pt_status != PTMOVE) || (k->pt_owner == me->p_no))
|
|
135 continue; /* only check live plasmas */
|
|
136 if ((!(k->pt_war & me->p_team)) && /* and unfriendly ones */
|
|
137 (!((me->p_swar | me->p_hostile) & k->pt_team)))
|
|
138 continue;
|
|
139 dir = (unsigned char) (int) (atan2((double) (k->pt_x - me->p_x),
|
|
140 (double) (me->p_y - k->pt_y)) / 3.14159 * 128.); /* find direction */
|
|
141 trange = ihypot(k->pt_x - me->p_x, k->pt_y - me->p_y);
|
|
142 if (trange == 0) /* no zeroes in math funcs */
|
|
143 trange = 1;
|
|
144 maxangle = atan((float) EXPDIST / 4 / trange) / 3.14159 * 128.0;
|
|
145 if (angdist(dir, course) <= (maxangle + 1))
|
|
146 { /* if we can hit it */
|
|
147 if (range > trange)
|
|
148 { /* then check to see if this */
|
|
149 target_x = k->pt_x; /* is the closest plasma */
|
|
150 target_y = k->pt_y; /* found yet */
|
|
151 whichtarget = 2; /* and record it if it is */
|
|
152 target2 = k;
|
|
153 range = trange;
|
|
154 }
|
|
155 }
|
|
156 }
|
|
157 /* check the fighters */
|
|
158 for (i = 0, d = &missiles[i]; i < NPTHINGIES * MAXPLAYER; i++, d++)
|
|
159 {
|
|
160 if ((d->ms_owner == me->p_no) || (d->ms_type != FIGHTERTHINGY))
|
|
161 continue; /* only check live fighters */
|
|
162 if ((!(d->ms_war & me->p_team)) && /* and unfriendly ones */
|
|
163 (!((me->p_swar | me->p_hostile) & d->ms_team)))
|
|
164 continue;
|
|
165 dir = (unsigned char) (atan2((double) (d->ms_x - me->p_x),
|
|
166 (double) (me->p_y - d->ms_y))
|
|
167 / 3.14159 * 128.); /* find direction */
|
|
168 trange = ihypot(d->ms_x - me->p_x, d->ms_y - me->p_y);
|
|
169 if (trange == 0) /* no zeroes in math funcs */
|
|
170 trange = 1;
|
|
171 maxangle = atan((float) EXPDIST / 8 / trange) / 3.14159 * 128.0;
|
|
172 if (angdist(dir, course) <= (maxangle + 1))
|
|
173 { /* if we can hit it */
|
|
174 if (range > trange)
|
|
175 { /* then check to see if this */
|
|
176 target_x = d->ms_x; /* is the closest fighter */
|
|
177 target_y = d->ms_y; /* found yet */
|
|
178 whichtarget = 3; /* and record it if it is */
|
|
179 target3 = d;
|
|
180 range = trange;
|
|
181 }
|
|
182 }
|
|
183 }
|
|
184
|
|
185 mine->ph_fuse = me->p_ship.s_phaser.fuse; /* set phaser fuse */
|
|
186 myphrange = me->p_ship.s_phaser.speed; /* phaser range */
|
|
187 if ((whichtarget == 0) || /* if no target found or all */
|
|
188 (range > myphrange))
|
|
189 { /* targets too long */
|
|
190 mine->ph_status = PHMISS; /* then we missed */
|
|
191 warning("Phaser missed!!!");
|
|
192 }
|
|
193 else if (whichtarget == 2)
|
|
194 { /* if we hit a plasma then */
|
|
195 warning("You destroyed the plasma torpedo!");
|
|
196 mine->ph_x = target_x; /* the set point to shoot at */
|
|
197 mine->ph_y = target_y;
|
|
198 mine->ph_status = PHHIT2; /* we hit a plasma */
|
|
199 target2->pt_status = PTEXPLODE; /* Plasmas hurt everyone */
|
|
200 target2->pt_whodet = me->p_no;
|
|
201 }
|
|
202 else if (whichtarget == 3)
|
|
203 { /* if we hit a fighter then */
|
|
204 warning("You shot a fighter!");
|
|
205 mine->ph_x = target_x; /* the set point to shoot at */
|
|
206 mine->ph_y = target_y;
|
|
207 mine->ph_status = PHHIT2; /* we hit the fighter */
|
|
208 target3->ms_status = TDET; /* det the fighter */
|
|
209 target3->ms_whodet = me->p_no;
|
|
210 }
|
|
211 else
|
|
212 { /* else if we hit player */
|
|
213 mine->ph_target = target->p_no; /* set the player number */
|
|
214 mine->ph_damage = me->p_ship.s_phaser.damage * /* get damage */
|
|
215 (1.0 - (range / (float) myphrange));
|
|
216 if (mine->ph_damage < 0) /* if damage inflicted */
|
|
217 mine->ph_damage = -mine->ph_damage; /* set the phaser damage */
|
|
218 mine->ph_status = PHHIT; /* status is a hit */
|
|
219
|
|
220 #ifdef PFBIRD
|
|
221 if (target->p_flags & PFBIRD)
|
|
222 {
|
|
223 /* change to PHHIT2 so phaser won't follow bird */
|
|
224 mine->ph_status = PHHIT2;
|
|
225 mine->ph_x = target->p_x;
|
|
226 mine->ph_y = target->p_y;
|
|
227 /* xx: slight misuse of fields here */
|
|
228 target->p_damage = mine->ph_damage;
|
|
229 target->p_whodead = me->p_no;
|
|
230
|
|
231 (void) sprintf(buf, "\"AAWWK!\"");
|
|
232 }
|
|
233 #endif
|
|
234
|
|
235 (void) sprintf(buf, "Phaser burst hit %s for %d points",
|
|
236 target->p_name, mine->ph_damage);
|
|
237 warning(buf);
|
|
238 }
|
|
239 }
|
|
240
|
|
241 /*------------------------------------------------------------------------*/
|
|
242
|
|
243
|
|
244
|
|
245
|
|
246
|
|
247 /*-------END OF FILE-------*/
|