1 /* projectile.c */
2
3 /* Copyright Hugh Robinson 2006-2008.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <math.h>
19 #include "asylum.h"
20
21 #define _projno 32
22 #define _projlim 0x1000
23
24 #define _projsmallno 54
25 #define _rocketspriteno 32
26 #define _rocketspritelim 41
27
28 #define bulletloss (2<<8)
29
30 const char _spcrumblelowlim = 140, _spcrumblehighlim = 143;
31 extern const char _translowlim, _transhighlim;
32
33 extern int xposmax, yposmax;
34 extern fastspr_sprite blokeadr[];
35 extern char masterplotal;
36
37 projent projofs[_projlim];
38
39 projent* projadr;
40 int projctr;
41
causeexplo(projent * r11)42 void causeexplo(projent* r11)
43 {
44 explogomaybe(r11->x-r11->dx, r11->y-r11->dy-(8<<8), 0, 0, 1, -1, 0);
45 }
causeexplonopyro(projent * r11)46 void causeexplonopyro(projent* r11)
47 {
48 explogonopyro(r11->x-r11->dx, r11->y-r11->dy-(8<<8), 0, 0, 1, -1, 0);
49 }
50
project()51 void project() // the projectile handler
52 {
53 int i = _projno; // get table length
54 projent* r11 = projadr;
55
56 for (; i > 0; i--, r11++)
57 {
58 loop41:
59 if (r11->type == 0) continue;
60 foundproj:
61 r11->x += r11->dx; r11->y += r11->dy;
62 if ((r11->x <= xlowlim) || (xposmax <= r11->x) || (r11->y <= ylowlim) || (yposmax <= r11->y))
63 {
64 // goto projoffscr
65 r11->type = 0;
66 continue;
67 }
68 if (r11->flags&PROJ_ROCKET)
69 {
70 r11->dx += r11->dx>>4; r11->dy += r11->dy>>4;
71 }
72
73 projnoacc:
74 if (r11->dx > _speedlim) r11->dx = _speedlim;
75 if (r11->dx < -_speedlim) r11->dx = -_speedlim;
76 if (r11->dy > _speedlim) r11->dy = _speedlim;
77 if (r11->dy < -_speedlim) r11->dy = -_speedlim;
78
79 r11->flags -= PROJ_TTL; // decrement the life counter
80 if (r11->flags < 0) // out of time
81 {
82 projdestroy:
83 if (r11->flags&PROJ_SPLIT)
84 {
85 projsplit(r11); continue;
86 }
87 projoffscr:
88 r11->type = 0;
89 continue;
90 }
91 alent* rs = bulcolcheck(r11->x, r11->y);
92 if (rs != NULL)
93 {
94 int r6;
95 if (r11->flags&PROJ_ROCKET)
96 r6 = projhital(rs,bulletloss<<2);
97 else r6 = projhital(rs, bulletloss);
98 r11->type = 0;
99 if (r6 == 0) continue;
100 makeobj(_Flyingbonus, r11->x, r11->y, r11->dx>>2, -(1<<10), (0x200<<16), r6);
101 if (r11->flags&PROJ_ROCKET) causeexplo(r11);
102 else causeexplonopyro(r11);
103 continue;
104 }
105
106 char* r0 = fntranslate(r11->x, r11->y);
107 char r1 = *r0;
108 if ((r1 < 16) ||
109 // projhit: // hit a block
110 ((r1 >= _translowlim) && (r1 <= _transhighlim) && !(r11->flags&PROJ_ATOM)))
111 {
112 projhitins:
113 if (masterplotal == 0) continue;
114 relplot(blokeadr, r11->type, r11->x, r11->y);
115 continue;
116 }
117 projhitcont:
118 if ((r1 >= _spcrumblelowlim) && (r1 <= _spcrumblehighlim)
119 && ((r11->type == _projsmallno+2) || (r11->flags&PROJ_WEIRDSPLIT)))
120 // hack, better than original && (plweapontype == 5)
121 {
122 *r0 = 0;
123 explogo(r11->x, r11->y, 0, 0, 0, 0, 0);
124 }
125 nospcrumble:
126 r11->type = 0;
127 destroy(r0);
128 if (r11->flags&PROJ_ATOM)
129 {
130 atomrocket(r11, r0); continue;
131 }
132 if (r11->flags&PROJ_EXPLO)
133 {
134 causeexplonopyro(r11); continue;
135 }
136 if (r11->flags&PROJ_ROCKET)
137 {
138 causeexplo(r11); continue;
139 }
140 }
141 }
142
143 int projsplittab[10];
144
init_projsplittab()145 void init_projsplittab()
146 {
147 for (int i = 0; i < 5; i++)
148 {
149 projsplittab[i*2] = (int)(0x40*(0.5-sin(i/4.0*M_PI)));
150 projsplittab[i*2+1] = 0x100*(i-2);
151 }
152 }
153
projsplit(projent * r11)154 void projsplit(projent* r11)
155 {
156 int x = r11->x, y = r11->y, dx = (r11->dx)>>1, dy = (r11->dy)>>1;
157 int flags = r11->flags;
158 int* r10;
159 int r9;
160
161 if (flags&PROJ_ROCKET)
162 {
163 rocketsplit(r11); return;
164 }
165
166 int r7 = r11->type, r4, r6;
167
168 if (flags&PROJ_FIVEWAY)
169 {
170 r10 = projsplittab; r9 = 5; r4 = _projsmallno+1;
171 }
172 else
173 {
174 r10 = projsplittab+2; r9 = 3; r4 = _projsmallno;
175 }
176 if ((flags&PROJ_SLOWSPLIT) == 0) dx >>= 1;
177 if (flags&PROJ_WEIRDSPLIT)
178 {
179 r4 = _projsmallno+2; dx <<= 2;
180 }
181 if (flags&PROJ_EXPLO)
182 {
183 r4 = _projsmallno+3; r6 = PROJ_ROCKET;
184 }
185 else r6 = 64*PROJ_TTL;
186
187 for (; r9 > 0; r9--)
188 {
189 loop76:
190 makeproj(x, y, dx+r10[0], dy+r10[1], r4, r6);
191 r10 += 2;
192 }
193 r11->type = 0;
194 }
195
196 int rocketbursttab[10];
197
init_rocketbursttab()198 void init_rocketbursttab()
199 {
200 for (int i = 0; i < 5; i++)
201 {
202 rocketbursttab[i*2] = (int)(0x200*sin((0.5+i)/2.5*M_PI));
203 rocketbursttab[i*2+1] = (int)(0x200*cos((0.5+i)/2.5*M_PI));
204 }
205 }
206
rocketsplit(projent * r11)207 void rocketsplit(projent* r11)
208 {
209 int x = r11->x, y = r11->y, dx = (r11->dx)>>3, dy = (r11->dy)>>3;
210 int flags = r11->flags;
211
212 if (flags&ROCK_DIVIDE)
213 {
214 rocketpair(r11); return;
215 }
216 rocketburst:;
217
218 int r5 = (64*PROJ_TTL)|PROJ_ROCKET|PROJ_EXPLO;
219 int* r10 = rocketbursttab;
220 for (int r9 = 5; r9 > 0; r9--)
221 {
222 loop77:
223 makeproj(x, y, dx+r10[0], dy+r10[1], _projsmallno+3, r5);
224 r10 += 2;
225 }
226 r11->type = 0;
227 causeexplonopyro(r11);
228 }
229
rocketpair(projent * r11)230 void rocketpair(projent* r11)
231 {
232 int x = r11->x, y = r11->y, dx = r11->dx, dy = r11->dy;
233 int flags = r11->flags;
234 int type = r11->type;
235 int newflags = 64*PROJ_TTL;
236
237 if (flags&ROCK_BURST) newflags = (16*PROJ_TTL)|ROCK_BURST|PROJ_SPLIT;
238 if (flags&ROCK_REDIVIDE) // continue splitting
239 {
240 newflags &= ~(64*PROJ_TTL); newflags |= (16*PROJ_TTL)|ROCK_DIVIDE|PROJ_SPLIT;
241 }
242 newflags |= PROJ_ROCKET;
243
244 int newtype = type-2;
245 if (newtype < _rocketspriteno) newtype += 2;
246
247 if (type&1) makeproj(x, y, dx-(dy>>2), dy+(dx>>2)-(dy>>4), newtype, newflags);
248 else makeproj(x, y, dx+(dy>>2), dy-(dx>>2)+(dy>>4), newtype, newflags);
249
250 newtype = type+2;
251 if (newtype > _rocketspritelim) newtype -= 2;
252
253 if (type&1) makeproj(x, y, dx+(dy>>2), dy-(dx>>2)+(dy>>4), newtype, newflags);
254 else makeproj(x, y, dx-(dy>>2), dy+(dx>>2)-(dy>>4), newtype, newflags);
255
256 r11->type = 0;
257 }
258
makeproj(int x,int y,int dx,int dy,int type,int flags)259 int makeproj(int x, int y, int dx, int dy, int type, int flags)
260 {
261 projent* r10 = projadr+projctr;
262 int r9 = _projno-projctr;
263 int r8 = projctr;
264
265 for (; r9 > 0; r9--)
266 {
267 loop42:
268 if (r10->type == 0) return foundmakeproj(r10, r8, x, y, dx, dy, type, flags);
269 r10++;
270 r8++;
271 }
272 r10 = projadr;
273 for (r9 = projctr; r9 > 0; r9--)
274 {
275 loop43:
276 if (r10->type == 0) return foundmakeproj(r10, r8, x, y, dx, dy, type, flags);
277 r10++;
278 r8++;
279 }
280 return 1;
281 }
282
foundmakeproj(projent * r10,int r8,int x,int y,int dx,int dy,int type,int flags)283 int foundmakeproj(projent* r10, int r8, int x, int y, int dx, int dy, int type, int flags)
284 {
285 if (flags < (1*PROJ_TTL)) flags |= (64*PROJ_TTL);
286 r10->type = type; r10->x = x; r10->y = y;
287 r10->dx = dx; r10->dy = dy; r10->flags = flags;
288
289 for (r8++; r8 >= _projno; r8 -= _projno)
290 loop45:;
291 projctr = r8;
292 return 0;
293 }
294
initprojtab()295 void initprojtab()
296 {
297 projadr = projofs;
298 projent* r10 = projadr;
299 projctr = 0;
300 for (int r9 = _projno; r9 > 0; r9--)
301 {
302 loop44:
303 *(int*)r10 = 0;
304 r10++;
305 }
306 }
307