1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4
5 This file is part of Shadow Warrior version 1.2
6
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 #include "build.h"
27
28 #include "keys.h"
29 #include "names2.h"
30 #include "panel.h"
31 #include "game.h"
32 #include "tags.h"
33 #include "ai.h"
34 #include "pal.h"
35 #include "actor.h"
36 #include "sprite.h"
37 #include "track.h"
38
39 ANIMATOR InitRipperHang;
40 ANIMATOR DoActorMoveJump;
41 ANIMATOR DoRipperMoveJump;
42 ANIMATOR DoRipperHangJF;
43 ANIMATOR DoRipperQuickJump;
44
45 DECISION RipperBattle[] =
46 {
47 {748, InitActorMoveCloser},
48 {750, InitActorAlertNoise},
49 // {900, InitRipperHang},
50 {755, InitActorAttackNoise},
51 {1024, InitActorAttack}
52 };
53
54 DECISION RipperOffense[] =
55 {
56 {700, InitActorMoveCloser},
57 {710, InitActorAlertNoise},
58 {1024, InitActorAttack}
59 };
60
61 DECISION RipperBroadcast[] =
62 {
63 {3, InitActorAlertNoise},
64 {6, InitActorAmbientNoise},
65 {1024, InitActorDecide}
66 };
67
68 DECISION RipperSurprised[] =
69 {
70 {30, InitRipperHang},
71 {701, InitActorMoveCloser},
72 {1024, InitActorDecide}
73 };
74
75 DECISION RipperEvasive[] =
76 {
77 {6, InitRipperHang},
78 {1024, NULL}
79 };
80
81 DECISION RipperLostTarget[] =
82 {
83 {980, InitActorFindPlayer},
84 {1024, InitActorWanderAround}
85 };
86
87 DECISION RipperCloseRange[] =
88 {
89 {900, InitActorAttack },
90 {1024, InitActorReposition }
91 };
92
93 PERSONALITY RipperPersonality =
94 {
95 RipperBattle,
96 RipperOffense,
97 RipperBroadcast,
98 RipperSurprised,
99 RipperEvasive,
100 RipperLostTarget,
101 RipperCloseRange,
102 RipperCloseRange
103 };
104
105 ATTRIBUTE RipperAttrib =
106 {
107 {200, 220, 240, 280}, // Speeds
108 {5, 0, -2, -4}, // Tic Adjusts
109 3, // MaxWeapons;
110 {
111 DIGI_RIPPERAMBIENT, DIGI_RIPPERALERT, DIGI_RIPPERATTACK,
112 DIGI_RIPPERPAIN, DIGI_RIPPERSCREAM, DIGI_RIPPERHEARTOUT,
113 0,0,0,0
114 }
115 };
116
117 //////////////////////
118 //
119 // RIPPER RUN
120 //
121 //////////////////////
122
123 #define RIPPER_RUN_RATE 16
124
125 ANIMATOR DoRipperMove, NullRipper, DoActorDebris;
126
127 STATE s_RipperRun[5][4] =
128 {
129 {
130 {RIPPER_RUN_R0 + 0, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[0][1]},
131 {RIPPER_RUN_R0 + 1, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[0][2]},
132 {RIPPER_RUN_R0 + 2, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[0][3]},
133 {RIPPER_RUN_R0 + 3, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[0][0]},
134 },
135 {
136 {RIPPER_RUN_R1 + 0, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[1][1]},
137 {RIPPER_RUN_R1 + 1, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[1][2]},
138 {RIPPER_RUN_R1 + 2, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[1][3]},
139 {RIPPER_RUN_R1 + 3, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[1][0]},
140 },
141 {
142 {RIPPER_RUN_R2 + 0, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[2][1]},
143 {RIPPER_RUN_R2 + 1, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[2][2]},
144 {RIPPER_RUN_R2 + 2, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[2][3]},
145 {RIPPER_RUN_R2 + 3, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[2][0]},
146 },
147 {
148 {RIPPER_RUN_R3 + 0, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[3][1]},
149 {RIPPER_RUN_R3 + 1, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[3][2]},
150 {RIPPER_RUN_R3 + 2, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[3][3]},
151 {RIPPER_RUN_R3 + 3, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[3][0]},
152 },
153 {
154 {RIPPER_RUN_R4 + 0, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[4][1]},
155 {RIPPER_RUN_R4 + 1, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[4][2]},
156 {RIPPER_RUN_R4 + 2, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[4][3]},
157 {RIPPER_RUN_R4 + 3, RIPPER_RUN_RATE | SF_TIC_ADJUST, DoRipperMove, &s_RipperRun[4][0]},
158 }
159 };
160
161
162 STATEp sg_RipperRun[] =
163 {
164 &s_RipperRun[0][0],
165 &s_RipperRun[1][0],
166 &s_RipperRun[2][0],
167 &s_RipperRun[3][0],
168 &s_RipperRun[4][0]
169 };
170
171 //////////////////////
172 //
173 // RIPPER STAND
174 //
175 //////////////////////
176
177 #define RIPPER_STAND_RATE 12
178
179 STATE s_RipperStand[5][1] =
180 {
181 {
182 {RIPPER_STAND_R0 + 0, RIPPER_STAND_RATE, DoRipperMove, &s_RipperStand[0][0]},
183 },
184 {
185 {RIPPER_STAND_R1 + 0, RIPPER_STAND_RATE, DoRipperMove, &s_RipperStand[1][0]},
186 },
187 {
188 {RIPPER_STAND_R2 + 0, RIPPER_STAND_RATE, DoRipperMove, &s_RipperStand[2][0]},
189 },
190 {
191 {RIPPER_STAND_R3 + 0, RIPPER_STAND_RATE, DoRipperMove, &s_RipperStand[3][0]},
192 },
193 {
194 {RIPPER_STAND_R4 + 0, RIPPER_STAND_RATE, DoRipperMove, &s_RipperStand[4][0]},
195 },
196 };
197
198
199 STATEp sg_RipperStand[] =
200 {
201 s_RipperStand[0],
202 s_RipperStand[1],
203 s_RipperStand[2],
204 s_RipperStand[3],
205 s_RipperStand[4]
206 };
207
208 //////////////////////
209 //
210 // RIPPER SWIPE
211 //
212 //////////////////////
213
214 #define RIPPER_SWIPE_RATE 8
215 ANIMATOR InitActorDecide;
216 ANIMATOR InitRipperSlash;
217
218 STATE s_RipperSwipe[5][8] =
219 {
220 {
221 {RIPPER_SWIPE_R0 + 0, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[0][1]},
222 {RIPPER_SWIPE_R0 + 1, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[0][2]},
223 {RIPPER_SWIPE_R0 + 1, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[0][3]},
224 {RIPPER_SWIPE_R0 + 2, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[0][4]},
225 {RIPPER_SWIPE_R0 + 3, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[0][5]},
226 {RIPPER_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[0][6]},
227 {RIPPER_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSwipe[0][7]},
228 {RIPPER_SWIPE_R0 + 3, RIPPER_SWIPE_RATE, DoRipperMove, &s_RipperSwipe[0][7]},
229 },
230 {
231 {RIPPER_SWIPE_R1 + 0, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[1][1]},
232 {RIPPER_SWIPE_R1 + 1, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[1][2]},
233 {RIPPER_SWIPE_R1 + 1, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[1][3]},
234 {RIPPER_SWIPE_R1 + 2, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[1][4]},
235 {RIPPER_SWIPE_R1 + 3, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[1][5]},
236 {RIPPER_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[1][6]},
237 {RIPPER_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSwipe[1][7]},
238 {RIPPER_SWIPE_R1 + 3, RIPPER_SWIPE_RATE, DoRipperMove, &s_RipperSwipe[1][7]},
239 },
240 {
241 {RIPPER_SWIPE_R2 + 0, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[2][1]},
242 {RIPPER_SWIPE_R2 + 1, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[2][2]},
243 {RIPPER_SWIPE_R2 + 1, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[2][3]},
244 {RIPPER_SWIPE_R2 + 2, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[2][4]},
245 {RIPPER_SWIPE_R2 + 3, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[2][5]},
246 {RIPPER_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[2][6]},
247 {RIPPER_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSwipe[2][7]},
248 {RIPPER_SWIPE_R2 + 3, RIPPER_SWIPE_RATE, DoRipperMove, &s_RipperSwipe[2][7]},
249 },
250 {
251 {RIPPER_SWIPE_R3 + 0, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[3][1]},
252 {RIPPER_SWIPE_R3 + 1, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[3][2]},
253 {RIPPER_SWIPE_R3 + 1, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[3][3]},
254 {RIPPER_SWIPE_R3 + 2, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[3][4]},
255 {RIPPER_SWIPE_R3 + 3, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[3][5]},
256 {RIPPER_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[3][6]},
257 {RIPPER_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSwipe[3][7]},
258 {RIPPER_SWIPE_R3 + 3, RIPPER_SWIPE_RATE, DoRipperMove, &s_RipperSwipe[3][7]},
259 },
260 {
261 {RIPPER_SWIPE_R4 + 0, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[4][1]},
262 {RIPPER_SWIPE_R4 + 1, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[4][2]},
263 {RIPPER_SWIPE_R4 + 1, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[4][3]},
264 {RIPPER_SWIPE_R4 + 2, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[4][4]},
265 {RIPPER_SWIPE_R4 + 3, RIPPER_SWIPE_RATE, NullRipper, &s_RipperSwipe[4][5]},
266 {RIPPER_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitRipperSlash, &s_RipperSwipe[4][6]},
267 {RIPPER_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSwipe[4][7]},
268 {RIPPER_SWIPE_R4 + 3, RIPPER_SWIPE_RATE, DoRipperMove, &s_RipperSwipe[4][7]},
269 }
270 };
271
272
273 STATEp sg_RipperSwipe[] =
274 {
275 &s_RipperSwipe[0][0],
276 &s_RipperSwipe[1][0],
277 &s_RipperSwipe[2][0],
278 &s_RipperSwipe[3][0],
279 &s_RipperSwipe[4][0]
280 };
281
282
283 //////////////////////
284 //
285 // RIPPER SPEW
286 //
287 //////////////////////
288
289 #define RIPPER_SPEW_RATE 8
290 ANIMATOR InitActorDecide;
291 ANIMATOR InitCoolgFire;
292
293 STATE s_RipperSpew[5][7] =
294 {
295 {
296 {RIPPER_SWIPE_R0 + 0, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[0][1]},
297 {RIPPER_SWIPE_R0 + 1, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[0][2]},
298 {RIPPER_SWIPE_R0 + 1, 0 | SF_QUICK_CALL, InitCoolgFire, &s_RipperSpew[0][3]},
299 {RIPPER_SWIPE_R0 + 2, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[0][4]},
300 {RIPPER_SWIPE_R0 + 3, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[0][5]},
301 {RIPPER_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSpew[0][6]},
302 {RIPPER_SWIPE_R0 + 3, RIPPER_SPEW_RATE, DoRipperMove, &s_RipperSpew[0][6]},
303 },
304 {
305 {RIPPER_SWIPE_R1 + 0, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[1][1]},
306 {RIPPER_SWIPE_R1 + 1, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[1][2]},
307 {RIPPER_SWIPE_R1 + 1, 0 | SF_QUICK_CALL, InitCoolgFire, &s_RipperSpew[1][3]},
308 {RIPPER_SWIPE_R1 + 2, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[1][4]},
309 {RIPPER_SWIPE_R1 + 3, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[1][5]},
310 {RIPPER_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSpew[1][6]},
311 {RIPPER_SWIPE_R1 + 3, RIPPER_SPEW_RATE, DoRipperMove, &s_RipperSpew[1][6]},
312 },
313 {
314 {RIPPER_SWIPE_R2 + 0, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[2][1]},
315 {RIPPER_SWIPE_R2 + 1, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[2][2]},
316 {RIPPER_SWIPE_R2 + 1, 0 | SF_QUICK_CALL, InitCoolgFire, &s_RipperSpew[2][3]},
317 {RIPPER_SWIPE_R2 + 2, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[2][4]},
318 {RIPPER_SWIPE_R2 + 3, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[2][5]},
319 {RIPPER_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSpew[2][6]},
320 {RIPPER_SWIPE_R2 + 3, RIPPER_SPEW_RATE, DoRipperMove, &s_RipperSpew[2][6]},
321 },
322 {
323 {RIPPER_SWIPE_R3 + 0, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[3][1]},
324 {RIPPER_SWIPE_R3 + 1, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[3][2]},
325 {RIPPER_SWIPE_R3 + 1, 0 | SF_QUICK_CALL, InitCoolgFire, &s_RipperSpew[3][3]},
326 {RIPPER_SWIPE_R3 + 2, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[3][4]},
327 {RIPPER_SWIPE_R3 + 3, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[3][5]},
328 {RIPPER_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSpew[3][6]},
329 {RIPPER_SWIPE_R3 + 3, RIPPER_SPEW_RATE, DoRipperMove, &s_RipperSpew[3][6]},
330 },
331 {
332 {RIPPER_SWIPE_R4 + 0, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[4][1]},
333 {RIPPER_SWIPE_R4 + 1, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[4][2]},
334 {RIPPER_SWIPE_R4 + 1, 0 | SF_QUICK_CALL, InitCoolgFire, &s_RipperSpew[4][3]},
335 {RIPPER_SWIPE_R4 + 2, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[4][4]},
336 {RIPPER_SWIPE_R4 + 3, RIPPER_SPEW_RATE, NullRipper, &s_RipperSpew[4][5]},
337 {RIPPER_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_RipperSpew[4][6]},
338 {RIPPER_SWIPE_R4 + 3, RIPPER_SPEW_RATE, DoRipperMove, &s_RipperSpew[4][6]},
339 }
340 };
341
342
343 STATEp sg_RipperSpew[] =
344 {
345 &s_RipperSpew[0][0],
346 &s_RipperSpew[1][0],
347 &s_RipperSpew[2][0],
348 &s_RipperSpew[3][0],
349 &s_RipperSpew[4][0]
350 };
351
352
353 //////////////////////
354 //
355 // RIPPER HEART - show players heart
356 //
357 //////////////////////
358
359 #define RIPPER_HEART_RATE 14
360 ANIMATOR DoRipperStandHeart;
361
362 STATE s_RipperHeart[5][4] =
363 {
364 {
365 {RIPPER_HEART_R0 + 0, RIPPER_HEART_RATE, DoRipperStandHeart, &s_RipperHeart[0][0]},
366 },
367 {
368 {RIPPER_HEART_R1 + 0, RIPPER_HEART_RATE, DoRipperStandHeart, &s_RipperHeart[1][0]},
369 },
370 {
371 {RIPPER_HEART_R2 + 0, RIPPER_HEART_RATE, DoRipperStandHeart, &s_RipperHeart[2][0]},
372 },
373 {
374 {RIPPER_HEART_R3 + 0, RIPPER_HEART_RATE, DoRipperStandHeart, &s_RipperHeart[3][0]},
375 },
376 {
377 {RIPPER_HEART_R4 + 0, RIPPER_HEART_RATE, DoRipperStandHeart, &s_RipperHeart[4][0]},
378 }
379 };
380
381 STATEp sg_RipperHeart[] =
382 {
383 &s_RipperHeart[0][0],
384 &s_RipperHeart[1][0],
385 &s_RipperHeart[2][0],
386 &s_RipperHeart[3][0],
387 &s_RipperHeart[4][0]
388 };
389
390 //////////////////////
391 //
392 // RIPPER HANG
393 //
394 //////////////////////
395
396 #define RIPPER_HANG_RATE 14
397 ANIMATOR DoRipperHang;
398
399 STATE s_RipperHang[5][4] =
400 {
401 {
402 {RIPPER_HANG_R0 + 0, RIPPER_HANG_RATE, DoRipperHang, &s_RipperHang[0][0]},
403 },
404 {
405 {RIPPER_HANG_R1 + 0, RIPPER_HANG_RATE, DoRipperHang, &s_RipperHang[1][0]},
406 },
407 {
408 {RIPPER_HANG_R2 + 0, RIPPER_HANG_RATE, DoRipperHang, &s_RipperHang[2][0]},
409 },
410 {
411 {RIPPER_HANG_R3 + 0, RIPPER_HANG_RATE, DoRipperHang, &s_RipperHang[3][0]},
412 },
413 {
414 {RIPPER_HANG_R4 + 0, RIPPER_HANG_RATE, DoRipperHang, &s_RipperHang[4][0]},
415 }
416 };
417
418
419 STATEp sg_RipperHang[] =
420 {
421 &s_RipperHang[0][0],
422 &s_RipperHang[1][0],
423 &s_RipperHang[2][0],
424 &s_RipperHang[3][0],
425 &s_RipperHang[4][0]
426 };
427
428
429 //////////////////////
430 //
431 // RIPPER PAIN
432 //
433 //////////////////////
434
435 #define RIPPER_PAIN_RATE 38
436 ANIMATOR DoRipperPain;
437
438 STATE s_RipperPain[5][1] =
439 {
440 {
441 {RIPPER_JUMP_R0 + 0, RIPPER_PAIN_RATE, DoRipperPain, &s_RipperPain[0][0]},
442 },
443 {
444 {RIPPER_JUMP_R0 + 0, RIPPER_PAIN_RATE, DoRipperPain, &s_RipperPain[1][0]},
445 },
446 {
447 {RIPPER_JUMP_R0 + 0, RIPPER_PAIN_RATE, DoRipperPain, &s_RipperPain[2][0]},
448 },
449 {
450 {RIPPER_JUMP_R0 + 0, RIPPER_PAIN_RATE, DoRipperPain, &s_RipperPain[3][0]},
451 },
452 {
453 {RIPPER_JUMP_R0 + 0, RIPPER_PAIN_RATE, DoRipperPain, &s_RipperPain[4][0]},
454 }
455 };
456
457 STATEp sg_RipperPain[] =
458 {
459 &s_RipperPain[0][0],
460 &s_RipperPain[1][0],
461 &s_RipperPain[2][0],
462 &s_RipperPain[3][0],
463 &s_RipperPain[4][0]
464 };
465
466 //////////////////////
467 //
468 // RIPPER JUMP
469 //
470 //////////////////////
471
472 #define RIPPER_JUMP_RATE 25
473
474 STATE s_RipperJump[5][6] =
475 {
476 {
477 {RIPPER_JUMP_R0 + 0, RIPPER_JUMP_RATE, NullRipper, &s_RipperJump[0][1]},
478 {RIPPER_JUMP_R0 + 1, RIPPER_JUMP_RATE, DoRipperMoveJump, &s_RipperJump[0][1]},
479 },
480 {
481 {RIPPER_JUMP_R1 + 0, RIPPER_JUMP_RATE, NullRipper, &s_RipperJump[1][1]},
482 {RIPPER_JUMP_R1 + 1, RIPPER_JUMP_RATE, DoRipperMoveJump, &s_RipperJump[1][1]},
483 },
484 {
485 {RIPPER_JUMP_R2 + 0, RIPPER_JUMP_RATE, NullRipper, &s_RipperJump[2][1]},
486 {RIPPER_JUMP_R2 + 1, RIPPER_JUMP_RATE, DoRipperMoveJump, &s_RipperJump[2][1]},
487 },
488 {
489 {RIPPER_JUMP_R3 + 0, RIPPER_JUMP_RATE, NullRipper, &s_RipperJump[3][1]},
490 {RIPPER_JUMP_R3 + 1, RIPPER_JUMP_RATE, DoRipperMoveJump, &s_RipperJump[3][1]},
491 },
492 {
493 {RIPPER_JUMP_R4 + 0, RIPPER_JUMP_RATE, NullRipper, &s_RipperJump[4][1]},
494 {RIPPER_JUMP_R4 + 1, RIPPER_JUMP_RATE, DoRipperMoveJump, &s_RipperJump[4][1]},
495 }
496 };
497
498
499 STATEp sg_RipperJump[] =
500 {
501 &s_RipperJump[0][0],
502 &s_RipperJump[1][0],
503 &s_RipperJump[2][0],
504 &s_RipperJump[3][0],
505 &s_RipperJump[4][0]
506 };
507
508
509 //////////////////////
510 //
511 // RIPPER FALL
512 //
513 //////////////////////
514
515 #define RIPPER_FALL_RATE 25
516
517 STATE s_RipperFall[5][6] =
518 {
519 {
520 {RIPPER_FALL_R0 + 0, RIPPER_FALL_RATE, DoRipperMoveJump, &s_RipperFall[0][0]},
521 },
522 {
523 {RIPPER_FALL_R1 + 0, RIPPER_FALL_RATE, DoRipperMoveJump, &s_RipperFall[1][0]},
524 },
525 {
526 {RIPPER_FALL_R2 + 0, RIPPER_FALL_RATE, DoRipperMoveJump, &s_RipperFall[2][0]},
527 },
528 {
529 {RIPPER_FALL_R3 + 0, RIPPER_FALL_RATE, DoRipperMoveJump, &s_RipperFall[3][0]},
530 },
531 {
532 {RIPPER_FALL_R4 + 0, RIPPER_FALL_RATE, DoRipperMoveJump, &s_RipperFall[4][0]},
533 }
534 };
535
536
537 STATEp sg_RipperFall[] =
538 {
539 &s_RipperFall[0][0],
540 &s_RipperFall[1][0],
541 &s_RipperFall[2][0],
542 &s_RipperFall[3][0],
543 &s_RipperFall[4][0]
544 };
545
546
547 //////////////////////
548 //
549 // RIPPER JUMP ATTACK
550 //
551 //////////////////////
552
553 #define RIPPER_JUMP_ATTACK_RATE 35
554 int DoRipperBeginJumpAttack(short SpriteNum);
555
556 STATE s_RipperJumpAttack[5][6] =
557 {
558 {
559 {RIPPER_JUMP_R0 + 0, RIPPER_JUMP_ATTACK_RATE, NullRipper, &s_RipperJumpAttack[0][1]},
560 {RIPPER_JUMP_R0 + 0, 0 | SF_QUICK_CALL, DoRipperBeginJumpAttack, &s_RipperJumpAttack[0][2]},
561 {RIPPER_JUMP_R0 + 1, RIPPER_JUMP_ATTACK_RATE, DoRipperMoveJump, &s_RipperJumpAttack[0][2]},
562 },
563 {
564 {RIPPER_JUMP_R1 + 0, RIPPER_JUMP_ATTACK_RATE, NullRipper, &s_RipperJumpAttack[1][1]},
565 {RIPPER_JUMP_R1 + 0, 0 | SF_QUICK_CALL, DoRipperBeginJumpAttack, &s_RipperJumpAttack[1][2]},
566 {RIPPER_JUMP_R1 + 1, RIPPER_JUMP_ATTACK_RATE, DoRipperMoveJump, &s_RipperJumpAttack[1][2]},
567 },
568 {
569 {RIPPER_JUMP_R2 + 0, RIPPER_JUMP_ATTACK_RATE, NullRipper, &s_RipperJumpAttack[2][1]},
570 {RIPPER_JUMP_R2 + 0, 0 | SF_QUICK_CALL, DoRipperBeginJumpAttack, &s_RipperJumpAttack[2][2]},
571 {RIPPER_JUMP_R2 + 1, RIPPER_JUMP_ATTACK_RATE, DoRipperMoveJump, &s_RipperJumpAttack[2][2]},
572 },
573 {
574 {RIPPER_JUMP_R3 + 0, RIPPER_JUMP_ATTACK_RATE, NullRipper, &s_RipperJumpAttack[3][1]},
575 {RIPPER_JUMP_R3 + 0, 0 | SF_QUICK_CALL, DoRipperBeginJumpAttack, &s_RipperJumpAttack[3][2]},
576 {RIPPER_JUMP_R3 + 1, RIPPER_JUMP_ATTACK_RATE, DoRipperMoveJump, &s_RipperJumpAttack[3][2]},
577 },
578 {
579 {RIPPER_JUMP_R4 + 0, RIPPER_JUMP_ATTACK_RATE, NullRipper, &s_RipperJumpAttack[4][1]},
580 {RIPPER_JUMP_R4 + 0, 0 | SF_QUICK_CALL, DoRipperBeginJumpAttack, &s_RipperJumpAttack[4][2]},
581 {RIPPER_JUMP_R4 + 1, RIPPER_JUMP_ATTACK_RATE, DoRipperMoveJump, &s_RipperJumpAttack[4][2]},
582 }
583 };
584
585
586 STATEp sg_RipperJumpAttack[] =
587 {
588 &s_RipperJumpAttack[0][0],
589 &s_RipperJumpAttack[1][0],
590 &s_RipperJumpAttack[2][0],
591 &s_RipperJumpAttack[3][0],
592 &s_RipperJumpAttack[4][0]
593 };
594
595
596 //////////////////////
597 //
598 // RIPPER HANG_JUMP
599 //
600 //////////////////////
601
602 #define RIPPER_HANG_JUMP_RATE 20
603
604 STATE s_RipperHangJump[5][6] =
605 {
606 {
607 {RIPPER_JUMP_R0 + 0, RIPPER_HANG_JUMP_RATE, NullRipper, &s_RipperHangJump[0][1]},
608 {RIPPER_JUMP_R0 + 1, RIPPER_HANG_JUMP_RATE, DoRipperHangJF, &s_RipperHangJump[0][1]},
609 },
610 {
611 {RIPPER_JUMP_R1 + 0, RIPPER_HANG_JUMP_RATE, NullRipper, &s_RipperHangJump[1][1]},
612 {RIPPER_JUMP_R1 + 1, RIPPER_HANG_JUMP_RATE, DoRipperHangJF, &s_RipperHangJump[1][1]},
613 },
614 {
615 {RIPPER_JUMP_R2 + 0, RIPPER_HANG_JUMP_RATE, NullRipper, &s_RipperHangJump[2][1]},
616 {RIPPER_JUMP_R2 + 1, RIPPER_HANG_JUMP_RATE, DoRipperHangJF, &s_RipperHangJump[2][1]},
617 },
618 {
619 {RIPPER_JUMP_R3 + 0, RIPPER_HANG_JUMP_RATE, NullRipper, &s_RipperHangJump[3][1]},
620 {RIPPER_JUMP_R3 + 1, RIPPER_HANG_JUMP_RATE, DoRipperHangJF, &s_RipperHangJump[3][1]},
621 },
622 {
623 {RIPPER_JUMP_R4 + 0, RIPPER_HANG_JUMP_RATE, NullRipper, &s_RipperHangJump[4][1]},
624 {RIPPER_JUMP_R4 + 1, RIPPER_HANG_JUMP_RATE, DoRipperHangJF, &s_RipperHangJump[4][1]},
625 }
626 };
627
628
629 STATEp sg_RipperHangJump[] =
630 {
631 &s_RipperHangJump[0][0],
632 &s_RipperHangJump[1][0],
633 &s_RipperHangJump[2][0],
634 &s_RipperHangJump[3][0],
635 &s_RipperHangJump[4][0]
636 };
637
638 //////////////////////
639 //
640 // RIPPER HANG_FALL
641 //
642 //////////////////////
643
644 #define RIPPER_FALL_RATE 25
645
646 STATE s_RipperHangFall[5][6] =
647 {
648 {
649 {RIPPER_FALL_R0 + 0, RIPPER_FALL_RATE, DoRipperHangJF, &s_RipperHangFall[0][0]},
650 },
651 {
652 {RIPPER_FALL_R1 + 0, RIPPER_FALL_RATE, DoRipperHangJF, &s_RipperHangFall[1][0]},
653 },
654 {
655 {RIPPER_FALL_R2 + 0, RIPPER_FALL_RATE, DoRipperHangJF, &s_RipperHangFall[2][0]},
656 },
657 {
658 {RIPPER_FALL_R3 + 0, RIPPER_FALL_RATE, DoRipperHangJF, &s_RipperHangFall[3][0]},
659 },
660 {
661 {RIPPER_FALL_R4 + 0, RIPPER_FALL_RATE, DoRipperHangJF, &s_RipperHangFall[4][0]},
662 }
663 };
664
665
666 STATEp sg_RipperHangFall[] =
667 {
668 &s_RipperHangFall[0][0],
669 &s_RipperHangFall[1][0],
670 &s_RipperHangFall[2][0],
671 &s_RipperHangFall[3][0],
672 &s_RipperHangFall[4][0]
673 };
674
675
676
677 //////////////////////
678 //
679 // RIPPER DIE
680 //
681 //////////////////////
682
683 #define RIPPER_DIE_RATE 16
684
685 STATE s_RipperDie[] =
686 {
687 {RIPPER_DIE + 0, RIPPER_DIE_RATE, NullRipper, &s_RipperDie[1]},
688 {RIPPER_DIE + 1, RIPPER_DIE_RATE, NullRipper, &s_RipperDie[2]},
689 {RIPPER_DIE + 2, RIPPER_DIE_RATE, NullRipper, &s_RipperDie[3]},
690 {RIPPER_DIE + 3, RIPPER_DIE_RATE, NullRipper, &s_RipperDie[4]},
691 {RIPPER_DEAD, RIPPER_DIE_RATE, DoActorDebris, &s_RipperDie[4]},
692 };
693
694 #define RIPPER_DEAD_RATE 8
695
696 STATE s_RipperDead[] =
697 {
698 {RIPPER_DIE + 2, RIPPER_DEAD_RATE, NullAnimator, &s_RipperDead[1]},
699 {RIPPER_DIE + 3, RIPPER_DEAD_RATE, NullAnimator, &s_RipperDead[2]},
700 {RIPPER_DEAD, SF_QUICK_CALL, QueueFloorBlood, &s_RipperDead[3]},
701 {RIPPER_DEAD, RIPPER_DEAD_RATE, DoActorDebris, &s_RipperDead[3]},
702 };
703
704 STATEp sg_RipperDie[] =
705 {
706 s_RipperDie
707 };
708
709 STATEp sg_RipperDead[] =
710 {
711 s_RipperDead
712 };
713
714 STATE s_RipperDeathJump[] =
715 {
716 {RIPPER_DIE + 0, RIPPER_DIE_RATE, DoActorDeathMove, &s_RipperDeathJump[0]}
717 };
718
719 STATE s_RipperDeathFall[] =
720 {
721 {RIPPER_DIE + 1, RIPPER_DIE_RATE, DoActorDeathMove, &s_RipperDeathFall[0]}
722 };
723
724
725 STATEp sg_RipperDeathJump[] =
726 {
727 s_RipperDeathJump
728 };
729
730 STATEp sg_RipperDeathFall[] =
731 {
732 s_RipperDeathFall
733 };
734
735
736 /*
737 STATEp *Stand[MAX_WEAPONS];
738 STATEp *Run;
739 STATEp *Jump;
740 STATEp *Fall;
741 STATEp *Crawl;
742 STATEp *Swim;
743 STATEp *Fly;
744 STATEp *Rise;
745 STATEp *Sit;
746 STATEp *Look;
747 STATEp *Climb;
748 STATEp *Pain;
749 STATEp *Death1;
750 STATEp *Death2;
751 STATEp *Dead;
752 STATEp *DeathJump;
753 STATEp *DeathFall;
754 STATEp *CloseAttack[2];
755 STATEp *Attack[6];
756 STATEp *Special[2];
757 */
758
759
760 ACTOR_ACTION_SET RipperActionSet =
761 {
762 sg_RipperStand,
763 sg_RipperRun,
764 sg_RipperJump,
765 sg_RipperFall,
766 NULL, // sg_RipperCrawl,
767 NULL, // sg_RipperSwim,
768 NULL, // sg_RipperFly,
769 NULL, // sg_RipperRise,
770 NULL, // sg_RipperSit,
771 NULL, // sg_RipperLook,
772 NULL, // climb
773 sg_RipperPain,
774 sg_RipperDie,
775 NULL, // sg_RipperHariKari,
776 sg_RipperDead,
777 sg_RipperDeathJump,
778 sg_RipperDeathFall,
779 {sg_RipperSwipe,sg_RipperSpew},
780 {800,1024},
781 {sg_RipperJumpAttack, sg_RipperSpew},
782 {400, 1024},
783 {sg_RipperHeart, sg_RipperHang},
784 NULL,
785 NULL
786 };
787
788 ACTOR_ACTION_SET RipperBrownActionSet =
789 {
790 sg_RipperStand,
791 sg_RipperRun,
792 sg_RipperJump,
793 sg_RipperFall,
794 NULL, // sg_RipperCrawl,
795 NULL, // sg_RipperSwim,
796 NULL, // sg_RipperFly,
797 NULL, // sg_RipperRise,
798 NULL, // sg_RipperSit,
799 NULL, // sg_RipperLook,
800 NULL, // climb
801 sg_RipperPain, // pain
802 sg_RipperDie,
803 NULL, // sg_RipperHariKari,
804 sg_RipperDead,
805 sg_RipperDeathJump,
806 sg_RipperDeathFall,
807 {sg_RipperSwipe},
808 {1024},
809 {sg_RipperJumpAttack, sg_RipperSwipe},
810 {800, 1024},
811 {sg_RipperHeart, sg_RipperHang},
812 NULL,
813 NULL
814 };
815
816 int
SetupRipper(short SpriteNum)817 SetupRipper(short SpriteNum)
818 {
819 SPRITEp sp = &sprite[SpriteNum];
820 USERp u;
821 ANIMATOR DoActorDecide;
822
823 if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
824 {
825 u = User[SpriteNum];
826 ASSERT(u);
827 }
828 else
829 {
830 User[SpriteNum] = u = SpawnUser(SpriteNum, RIPPER_RUN_R0, s_RipperRun[0]);
831 u->Health = HEALTH_RIPPER/2; // Baby rippers are weaker
832 }
833
834 ChangeState(SpriteNum, s_RipperRun[0]);
835 u->Attrib = &RipperAttrib;
836 DoActorSetSpeed(SpriteNum, FAST_SPEED);
837 u->StateEnd = s_RipperDie;
838 u->Rot = sg_RipperRun;
839 sp->xrepeat = 64;
840 sp->yrepeat = 64;
841
842 if (sp->pal == PALETTE_BROWN_RIPPER)
843 {
844 EnemyDefaults(SpriteNum, &RipperBrownActionSet, &RipperPersonality);
845 sp->xrepeat = 106;
846 sp->yrepeat = 90;
847
848 if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
849 u->Health = HEALTH_MOMMA_RIPPER;
850
851 sp->clipdist += 128 >> 2;
852 }
853 else
854 {
855 EnemyDefaults(SpriteNum, &RipperActionSet, &RipperPersonality);
856 }
857
858 SET(u->Flags, SPR_XFLIP_TOGGLE);
859
860 return 0;
861 }
862
863 int
GetJumpHeight(short jump_speed,short jump_grav)864 GetJumpHeight(short jump_speed, short jump_grav)
865 {
866 int jump_iterations;
867 int height;
868
869 jump_speed = labs(jump_speed);
870
871 jump_iterations = jump_speed / (jump_grav * ACTORMOVETICS);
872
873 height = jump_speed * jump_iterations * ACTORMOVETICS;
874
875 height = DIV256(height);
876
877 return DIV2(height);
878 }
879
880 int
PickJumpSpeed(short SpriteNum,int pix_height)881 PickJumpSpeed(short SpriteNum, int pix_height)
882 {
883 USERp u = User[SpriteNum];
884
885 //ASSERT(pix_height < 128);
886
887 u->jump_speed = -600;
888 u->jump_grav = 8;
889
890 while (TRUE)
891 {
892 if (GetJumpHeight(u->jump_speed, u->jump_grav) > pix_height + 20)
893 break;
894
895 u->jump_speed -= 100;
896
897 ASSERT(u->jump_speed > -3000);
898 }
899
900 return u->jump_speed;
901 }
902
903
904 int
PickJumpMaxSpeed(short SpriteNum,short max_speed)905 PickJumpMaxSpeed(short SpriteNum, short max_speed)
906 {
907 SPRITEp sp = &sprite[SpriteNum];
908 USERp u = User[SpriteNum];
909 int zh;
910
911 ASSERT(max_speed < 0);
912
913 u->jump_speed = max_speed;
914 u->jump_grav = 8;
915
916 zh = SPRITEp_TOS(sp);
917
918 while (TRUE)
919 {
920 if (zh - Z(GetJumpHeight(u->jump_speed, u->jump_grav)) - Z(16) > u->hiz)
921 break;
922
923 u->jump_speed += 100;
924
925 if (u->jump_speed > -200)
926 break;
927 }
928
929 return u->jump_speed;
930 }
931
932
933 //
934 // HANGING - Jumping/Falling/Stationary
935 //
936
937 int
InitRipperHang(short SpriteNum)938 InitRipperHang(short SpriteNum)
939 {
940 SPRITEp sp = &sprite[SpriteNum];
941 USERp u = User[SpriteNum];
942 int dist;
943
944 hitdata_t hitinfo = { { 0, 0, 0 }, -2, 0, -2 };
945
946 SWBOOL Found = FALSE;
947 short dang, tang;
948
949 for (dang = 0; dang < 2048; dang += 128)
950 {
951 tang = NORM_ANGLE(sp->ang + dang);
952
953 FAFhitscan(sp->x, sp->y, sp->z - SPRITEp_SIZE_Z(sp), sp->sectnum, // Start position
954 sintable[NORM_ANGLE(tang + 512)], // X vector of 3D ang
955 sintable[tang], // Y vector of 3D ang
956 0, // Z vector of 3D ang
957 &hitinfo, CLIPMASK_MISSILE);
958
959 //ASSERT(hitinfo.sect >= 0);
960 if (hitinfo.sect < 0)
961 continue;
962
963 dist = Distance(sp->x, sp->y, hitinfo.pos.x, hitinfo.pos.y);
964
965 if (hitinfo.wall < 0 || dist < 2000 || dist > 7000)
966 {
967 continue;
968 }
969
970 Found = TRUE;
971 sp->ang = tang;
972 break;
973 }
974
975 if (!Found)
976 {
977 InitActorDecide(SpriteNum);
978 return 0;
979 }
980
981 NewStateGroup(SpriteNum, sg_RipperHangJump);
982 u->StateFallOverride = sg_RipperHangFall;
983 DoActorSetSpeed(SpriteNum, FAST_SPEED);
984
985 //u->jump_speed = -800;
986 PickJumpMaxSpeed(SpriteNum, -800);
987
988 SET(u->Flags, SPR_JUMPING);
989 RESET(u->Flags, SPR_FALLING);
990
991 // set up individual actor jump gravity
992 u->jump_grav = 8;
993
994 DoJump(SpriteNum);
995
996 return 0;
997 }
998
999 int
DoRipperHang(short SpriteNum)1000 DoRipperHang(short SpriteNum)
1001 {
1002 USERp u = User[SpriteNum];
1003
1004 if ((u->WaitTics -= ACTORMOVETICS) > 0)
1005 return 0;
1006
1007 NewStateGroup(SpriteNum, sg_RipperJumpAttack);
1008 // move to the 2nd frame - past the pause frame
1009 u->Tics += u->State->Tics;
1010 return 0;
1011 }
1012
1013 int
DoRipperMoveHang(short SpriteNum)1014 DoRipperMoveHang(short SpriteNum)
1015 {
1016 SPRITEp sp = &sprite[SpriteNum];
1017 USERp u = User[SpriteNum];
1018 int nx, ny;
1019
1020 // Move while jumping
1021 nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
1022 ny = sp->xvel * (int) sintable[sp->ang] >> 14;
1023
1024 // if cannot move the sprite
1025 if (!move_actor(SpriteNum, nx, ny, 0L))
1026 {
1027 switch (TEST(u->ret, HIT_MASK))
1028 {
1029 case HIT_WALL:
1030 {
1031 short hit_wall;
1032 short w, nw;
1033
1034 hit_wall = NORM_WALL(u->ret);
1035
1036 NewStateGroup(SpriteNum, u->ActorActionSet->Special[1]);
1037 u->WaitTics = 2 + ((RANDOM_P2(4 << 8) >> 8) * 120);
1038
1039 // hang flush with the wall
1040 w = hit_wall;
1041 nw = wall[w].point2;
1042 sp->ang = NORM_ANGLE(getangle(wall[nw].x - wall[w].x, wall[nw].y - wall[w].y) - 512);
1043
1044 return 0;
1045 }
1046 }
1047 }
1048
1049 return 0;
1050 }
1051
1052
1053 int
DoRipperHangJF(short SpriteNum)1054 DoRipperHangJF(short SpriteNum)
1055 {
1056 USERp u = User[SpriteNum];
1057
1058 if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1059 {
1060 if (TEST(u->Flags, SPR_JUMPING))
1061 DoJump(SpriteNum);
1062 else
1063 DoFall(SpriteNum);
1064 }
1065
1066 if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1067 {
1068 if (DoRipperQuickJump(SpriteNum))
1069 return 0;
1070
1071 InitActorDecide(SpriteNum);
1072 }
1073
1074 DoRipperMoveHang(SpriteNum);
1075
1076 return 0;
1077
1078 }
1079
1080 //
1081 // JUMP ATTACK
1082 //
1083
1084 int
DoRipperBeginJumpAttack(short SpriteNum)1085 DoRipperBeginJumpAttack(short SpriteNum)
1086 {
1087 SPRITEp sp = &sprite[SpriteNum];
1088 USERp u = User[SpriteNum];
1089 SPRITEp psp = User[SpriteNum]->tgt_sp;
1090 int CanSeePlayer(short SpriteNum);
1091 short tang;
1092
1093 tang = getangle(psp->x - sp->x, psp->y - sp->y);
1094
1095 if (move_sprite(SpriteNum, sintable[NORM_ANGLE(tang+512)] >> 7, sintable[tang] >> 7,
1096 0L, u->ceiling_dist, u->floor_dist, CLIPMASK_ACTOR, ACTORMOVETICS))
1097 sp->ang = NORM_ANGLE((sp->ang + 1024) + (RANDOM_NEG(256, 6) >> 6));
1098 else
1099 sp->ang = NORM_ANGLE(tang + (RANDOM_NEG(256, 6) >> 6));
1100
1101 DoActorSetSpeed(SpriteNum, FAST_SPEED);
1102
1103 //u->jump_speed = -800;
1104 PickJumpMaxSpeed(SpriteNum, -400); // was -800
1105
1106 SET(u->Flags, SPR_JUMPING);
1107 RESET(u->Flags, SPR_FALLING);
1108
1109 // set up individual actor jump gravity
1110 u->jump_grav = 17; // was 8
1111
1112 // if I didn't do this here they get stuck in the air sometimes
1113 DoActorZrange(SpriteNum);
1114
1115 DoJump(SpriteNum);
1116
1117 return 0;
1118 }
1119
1120 int
DoRipperMoveJump(short SpriteNum)1121 DoRipperMoveJump(short SpriteNum)
1122 {
1123 USERp u = User[SpriteNum];
1124
1125 if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1126 {
1127 if (TEST(u->Flags, SPR_JUMPING))
1128 DoJump(SpriteNum);
1129 else
1130 DoFall(SpriteNum);
1131 }
1132
1133 if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1134 {
1135 if (DoRipperQuickJump(SpriteNum))
1136 return 0;
1137
1138 InitActorDecide(SpriteNum);
1139 }
1140
1141 DoRipperMoveHang(SpriteNum);
1142 return 0;
1143 }
1144
1145 //
1146 // STD MOVEMENT
1147 //
1148
1149 int
DoRipperQuickJump(short SpriteNum)1150 DoRipperQuickJump(short SpriteNum)
1151 {
1152 USERp u = User[SpriteNum];
1153
1154 // Tests to see if ripper is on top of a player/enemy and then immediatly
1155 // does another jump
1156
1157 if (u->lo_sp)
1158 {
1159 SPRITEp tsp = u->lo_sp;
1160
1161 if (TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY))
1162 {
1163 NewStateGroup(SpriteNum, sg_RipperJumpAttack);
1164 // move past the first state
1165 u->Tics = 30;
1166 return TRUE;
1167 }
1168 }
1169
1170 return FALSE;
1171 }
1172
1173
1174 int
NullRipper(short SpriteNum)1175 NullRipper(short SpriteNum)
1176 {
1177 USERp u = User[SpriteNum];
1178
1179 if (TEST(u->Flags,SPR_SLIDING))
1180 DoActorSlide(SpriteNum);
1181
1182 DoActorSectorDamage(SpriteNum);
1183
1184 return 0;
1185 }
1186
1187
DoRipperPain(short SpriteNum)1188 int DoRipperPain(short SpriteNum)
1189 {
1190 USERp u = User[SpriteNum];
1191
1192 NullRipper(SpriteNum);
1193
1194 if ((u->WaitTics -= ACTORMOVETICS) <= 0)
1195 InitActorDecide(SpriteNum);
1196 return 0;
1197 }
1198
1199
1200 // CTW MODIFICATION
1201 //int DoRipperRipHeart(SpriteNum)
DoRipperRipHeart(short SpriteNum)1202 int DoRipperRipHeart(short SpriteNum)
1203 // CTW MODIFICATION END
1204 {
1205 SPRITEp sp = &sprite[SpriteNum];
1206 USERp u = User[SpriteNum];
1207
1208 SPRITEp tsp = u->tgt_sp;
1209
1210 NewStateGroup(SpriteNum, sg_RipperHeart);
1211 u->WaitTics = 6 * 120;
1212
1213 // player face ripper
1214 tsp->ang = getangle(sp->x - tsp->x, sp->y - tsp->y);
1215 return 0;
1216 }
1217
1218 // CTW MODIFICATION
1219 //int DoRipperStandHeart(SpriteNum)
DoRipperStandHeart(short SpriteNum)1220 int DoRipperStandHeart(short SpriteNum)
1221 // CTW MODIFICATION END
1222 {
1223 USERp u = User[SpriteNum];
1224
1225 NullRipper(SpriteNum);
1226
1227 if ((u->WaitTics -= ACTORMOVETICS) <= 0)
1228 NewStateGroup(SpriteNum, sg_RipperRun);
1229 return 0;
1230 }
1231
RipperHatch(short Weapon)1232 void RipperHatch(short Weapon)
1233 {
1234 SPRITEp wp = &sprite[Weapon];
1235
1236 short New,i;
1237 SPRITEp np;
1238 USERp nu;
1239 #define MAX_RIPPERS 1
1240 short rip_ang[MAX_RIPPERS];
1241
1242 rip_ang[0] = RANDOM_P2(2048);
1243 // rip_ang[1] = NORM_ANGLE(rip_ang[0] + 1024 + (RANDOM_P2(512) - 256));
1244
1245 for (i = 0; i < MAX_RIPPERS; i++)
1246 {
1247 New = COVERinsertsprite(wp->sectnum, STAT_DEFAULT);
1248 np = &sprite[New];
1249 memset(np,0,sizeof(SPRITE));
1250 np->sectnum = wp->sectnum;
1251 np->statnum = STAT_DEFAULT;
1252 np->x = wp->x;
1253 np->y = wp->y;
1254 np->z = wp->z;
1255 np->owner = -1;
1256 //np->xrepeat = np->yrepeat = 36;
1257 np->xrepeat = np->yrepeat = 64;
1258 np->ang = rip_ang[i];
1259 np->pal = 0;
1260 SetupRipper(New);
1261 nu = User[New];
1262
1263 // make immediately active
1264 SET(nu->Flags, SPR_ACTIVE);
1265
1266 NewStateGroup(New, nu->ActorActionSet->Jump);
1267 nu->ActorActionFunc = DoActorMoveJump;
1268 DoActorSetSpeed(New, FAST_SPEED);
1269 PickJumpMaxSpeed(New, -600);
1270
1271 SET(nu->Flags, SPR_JUMPING);
1272 RESET(nu->Flags, SPR_FALLING);
1273
1274 nu->jump_grav = 8;
1275
1276 // if I didn't do this here they get stuck in the air sometimes
1277 DoActorZrange(New);
1278
1279 DoJump(New);
1280 }
1281 }
1282
1283 int
DoRipperMove(short SpriteNum)1284 DoRipperMove(short SpriteNum)
1285 {
1286 USERp u = User[SpriteNum];
1287
1288 if (u->scale_speed)
1289 {
1290 DoScaleSprite(SpriteNum);
1291 }
1292
1293 if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1294 {
1295 if (TEST(u->Flags, SPR_JUMPING))
1296 DoJump(SpriteNum);
1297 else
1298 DoFall(SpriteNum);
1299 }
1300
1301 // if on a player/enemy sprite jump quickly
1302 if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1303 {
1304 if (DoRipperQuickJump(SpriteNum))
1305 return 0;
1306
1307 KeepActorOnFloor(SpriteNum);
1308 }
1309
1310 if (TEST(u->Flags, SPR_SLIDING))
1311 DoActorSlide(SpriteNum);
1312
1313 if (u->track >= 0)
1314 ActorFollowTrack(SpriteNum, ACTORMOVETICS);
1315 else
1316 (*u->ActorActionFunc)(SpriteNum);
1317
1318 DoActorSectorDamage(SpriteNum);
1319 return 0;
1320 }
1321
1322
1323 #include "saveable.h"
1324
1325 static saveable_code saveable_ripper_code[] =
1326 {
1327 SAVE_CODE(SetupRipper),
1328 SAVE_CODE(GetJumpHeight),
1329 SAVE_CODE(PickJumpSpeed),
1330 SAVE_CODE(PickJumpMaxSpeed),
1331
1332 SAVE_CODE(InitRipperHang),
1333 SAVE_CODE(DoRipperHang),
1334 SAVE_CODE(DoRipperMoveHang),
1335 SAVE_CODE(DoRipperHangJF),
1336
1337 SAVE_CODE(DoRipperBeginJumpAttack),
1338 SAVE_CODE(DoRipperMoveJump),
1339
1340 SAVE_CODE(DoRipperQuickJump),
1341 SAVE_CODE(NullRipper),
1342 SAVE_CODE(DoRipperPain),
1343 SAVE_CODE(DoRipperRipHeart),
1344 SAVE_CODE(DoRipperStandHeart),
1345 SAVE_CODE(RipperHatch),
1346 SAVE_CODE(DoRipperMove),
1347 };
1348
1349 static saveable_data saveable_ripper_data[] =
1350 {
1351 SAVE_DATA(RipperBattle),
1352 SAVE_DATA(RipperOffense),
1353 SAVE_DATA(RipperBroadcast),
1354 SAVE_DATA(RipperSurprised),
1355 SAVE_DATA(RipperEvasive),
1356 SAVE_DATA(RipperLostTarget),
1357 SAVE_DATA(RipperCloseRange),
1358
1359 SAVE_DATA(RipperPersonality),
1360
1361 SAVE_DATA(RipperAttrib),
1362
1363 SAVE_DATA(s_RipperRun),
1364 SAVE_DATA(sg_RipperRun),
1365 SAVE_DATA(s_RipperStand),
1366 SAVE_DATA(sg_RipperStand),
1367 SAVE_DATA(s_RipperSwipe),
1368 SAVE_DATA(sg_RipperSwipe),
1369 SAVE_DATA(s_RipperSpew),
1370 SAVE_DATA(sg_RipperSpew),
1371 SAVE_DATA(s_RipperHeart),
1372 SAVE_DATA(sg_RipperHeart),
1373 SAVE_DATA(s_RipperHang),
1374 SAVE_DATA(sg_RipperHang),
1375 SAVE_DATA(s_RipperPain),
1376 SAVE_DATA(sg_RipperPain),
1377 SAVE_DATA(s_RipperJump),
1378 SAVE_DATA(sg_RipperJump),
1379 SAVE_DATA(s_RipperFall),
1380 SAVE_DATA(sg_RipperFall),
1381 SAVE_DATA(s_RipperJumpAttack),
1382 SAVE_DATA(sg_RipperJumpAttack),
1383 SAVE_DATA(s_RipperHangJump),
1384 SAVE_DATA(sg_RipperHangJump),
1385 SAVE_DATA(s_RipperHangFall),
1386 SAVE_DATA(sg_RipperHangFall),
1387 SAVE_DATA(s_RipperDie),
1388 SAVE_DATA(s_RipperDead),
1389 SAVE_DATA(sg_RipperDie),
1390 SAVE_DATA(sg_RipperDead),
1391 SAVE_DATA(s_RipperDeathJump),
1392 SAVE_DATA(s_RipperDeathFall),
1393 SAVE_DATA(sg_RipperDeathJump),
1394 SAVE_DATA(sg_RipperDeathFall),
1395
1396 SAVE_DATA(RipperActionSet),
1397 SAVE_DATA(RipperBrownActionSet),
1398 };
1399
1400 saveable_module saveable_ripper =
1401 {
1402 // code
1403 saveable_ripper_code,
1404 SIZ(saveable_ripper_code),
1405
1406 // data
1407 saveable_ripper_data,
1408 SIZ(saveable_ripper_data)
1409 };
1410