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 "sprite.h"
36 #include "actor.h"
37 #include "weapon.h"
38 #include "track.h"
39 
40 short Bunny_Count = 0;
41 ANIMATOR DoActorMoveJump;
42 ANIMATOR DoBunnyMoveJump;
43 ANIMATOR DoBunnyQuickJump;
44 
45 DECISION BunnyBattle[] =
46 {
47     {748, InitActorMoveCloser},
48     {750, InitActorAlertNoise},
49     {760, InitActorAttackNoise},
50     {1024, InitActorMoveCloser}
51 };
52 
53 DECISION BunnyOffense[] =
54 {
55     {600, InitActorMoveCloser},
56     {700, InitActorAlertNoise},
57     {1024, InitActorMoveCloser}
58 };
59 
60 DECISION BunnyBroadcast[] =
61 {
62     {21, InitActorAlertNoise},
63     {51, InitActorAmbientNoise},
64     {1024, InitActorDecide}
65 };
66 
67 DECISION BunnySurprised[] =
68 {
69     {500, InitActorRunAway},
70     {701, InitActorMoveCloser},
71     {1024, InitActorDecide}
72 };
73 
74 DECISION BunnyEvasive[] =
75 {
76     {500,  InitActorWanderAround},
77     {1020, InitActorRunAway},
78     {1024, InitActorAmbientNoise}
79 };
80 
81 DECISION BunnyLostTarget[] =
82 {
83     {900, InitActorFindPlayer},
84     {1024, InitActorWanderAround}
85 };
86 
87 DECISION BunnyCloseRange[] =
88 {
89     {1024,  InitActorAttack             },
90 //    {1024,  InitActorReposition         }
91 };
92 
93 DECISION BunnyWander[] =
94 {
95     {1024, InitActorReposition}
96 };
97 
98 PERSONALITY WhiteBunnyPersonality =
99 {
100     BunnyBattle,
101     BunnyOffense,
102     BunnyBroadcast,
103     BunnySurprised,
104     BunnyEvasive,
105     BunnyLostTarget,
106     BunnyCloseRange,
107     BunnyCloseRange
108 };
109 
110 PERSONALITY BunnyPersonality =
111 {
112     BunnyEvasive,
113     BunnyEvasive,
114     BunnyEvasive,
115     BunnyWander,
116     BunnyWander,
117     BunnyWander,
118     BunnyEvasive,
119     BunnyEvasive
120 };
121 
122 ATTRIBUTE BunnyAttrib =
123 {
124     {100, 120, 140, 180},               // Speeds
125     {5, 0, -2, -4},                     // Tic Adjusts
126     3,                                  // MaxWeapons;
127     {
128         DIGI_BUNNYAMBIENT, 0, DIGI_BUNNYATTACK,
129         DIGI_BUNNYATTACK, DIGI_BUNNYDIE2, 0,
130         0,0,0,0
131     }
132 };
133 
134 ATTRIBUTE WhiteBunnyAttrib =
135 {
136     {200, 220, 340, 380},               // Speeds
137     {5, 0, -2, -4},                     // Tic Adjusts
138     3,                                  // MaxWeapons;
139     {
140         DIGI_BUNNYAMBIENT, 0, DIGI_BUNNYATTACK,
141         DIGI_BUNNYATTACK, DIGI_BUNNYDIE2, 0,
142         0,0,0,0
143     }
144 };
145 
146 //////////////////////
147 //
148 // BUNNY RUN
149 //
150 //////////////////////
151 
152 #define BUNNY_RUN_RATE 10
153 
154 ANIMATOR DoBunnyMove, NullBunny, DoActorDebris, DoBunnyGrowUp;
155 
156 STATE s_BunnyRun[5][6] =
157 {
158     {
159         {BUNNY_RUN_R0 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][1]},
160         {BUNNY_RUN_R0 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][2]},
161         {BUNNY_RUN_R0 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][3]},
162         {BUNNY_RUN_R0 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][4]},
163         {BUNNY_RUN_R0 + 4, SF_QUICK_CALL,                DoBunnyGrowUp, &s_BunnyRun[0][5]},
164         {BUNNY_RUN_R0 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][0]},
165     },
166     {
167         {BUNNY_RUN_R1 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][1]},
168         {BUNNY_RUN_R1 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][2]},
169         {BUNNY_RUN_R1 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][3]},
170         {BUNNY_RUN_R1 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][4]},
171         {BUNNY_RUN_R1 + 4, SF_QUICK_CALL,                DoBunnyGrowUp, &s_BunnyRun[1][5]},
172         {BUNNY_RUN_R1 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][0]},
173     },
174     {
175         {BUNNY_RUN_R2 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][1]},
176         {BUNNY_RUN_R2 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][2]},
177         {BUNNY_RUN_R2 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][3]},
178         {BUNNY_RUN_R2 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][4]},
179         {BUNNY_RUN_R2 + 4, SF_QUICK_CALL,                DoBunnyGrowUp, &s_BunnyRun[2][5]},
180         {BUNNY_RUN_R2 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][0]},
181     },
182     {
183         {BUNNY_RUN_R3 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][1]},
184         {BUNNY_RUN_R3 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][2]},
185         {BUNNY_RUN_R3 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][3]},
186         {BUNNY_RUN_R3 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][4]},
187         {BUNNY_RUN_R3 + 4, SF_QUICK_CALL,                DoBunnyGrowUp, &s_BunnyRun[3][5]},
188         {BUNNY_RUN_R3 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][0]},
189     },
190     {
191         {BUNNY_RUN_R4 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][1]},
192         {BUNNY_RUN_R4 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][2]},
193         {BUNNY_RUN_R4 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][3]},
194         {BUNNY_RUN_R4 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][4]},
195         {BUNNY_RUN_R4 + 4, SF_QUICK_CALL,                DoBunnyGrowUp, &s_BunnyRun[4][5]},
196         {BUNNY_RUN_R4 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][0]},
197     }
198 };
199 
200 
201 STATEp sg_BunnyRun[] =
202 {
203     &s_BunnyRun[0][0],
204     &s_BunnyRun[1][0],
205     &s_BunnyRun[2][0],
206     &s_BunnyRun[3][0],
207     &s_BunnyRun[4][0]
208 };
209 
210 //////////////////////
211 //
212 // BUNNY STAND
213 //
214 //////////////////////
215 
216 #define BUNNY_STAND_RATE 12
217 ANIMATOR DoBunnyEat;
218 
219 STATE s_BunnyStand[5][3] =
220 {
221     {
222         {BUNNY_STAND_R0 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[0][1]},
223         {BUNNY_STAND_R0 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[0][2]},
224         {BUNNY_STAND_R0 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[0][0]},
225     },
226     {
227         {BUNNY_STAND_R1 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[1][1]},
228         {BUNNY_STAND_R1 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[1][2]},
229         {BUNNY_STAND_R1 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[1][0]},
230     },
231     {
232         {BUNNY_STAND_R2 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[2][1]},
233         {BUNNY_STAND_R2 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[2][2]},
234         {BUNNY_STAND_R2 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[2][0]},
235     },
236     {
237         {BUNNY_STAND_R3 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[3][1]},
238         {BUNNY_STAND_R3 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[3][2]},
239         {BUNNY_STAND_R3 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[3][0]},
240     },
241     {
242         {BUNNY_STAND_R4 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[4][1]},
243         {BUNNY_STAND_R4 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[4][2]},
244         {BUNNY_STAND_R4 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[4][0]},
245     },
246 };
247 
248 
249 STATEp sg_BunnyStand[] =
250 {
251     s_BunnyStand[0],
252     s_BunnyStand[1],
253     s_BunnyStand[2],
254     s_BunnyStand[3],
255     s_BunnyStand[4]
256 };
257 
258 //////////////////////
259 //
260 // BUNNY GET LAYED
261 //
262 //////////////////////
263 
264 #define BUNNY_SCREW_RATE 16
265 ANIMATOR DoBunnyScrew;
266 
267 STATE s_BunnyScrew[5][2] =
268 {
269     {
270         {BUNNY_STAND_R0 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[0][1]},
271         {BUNNY_STAND_R0 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[0][0]},
272     },
273     {
274         {BUNNY_STAND_R1 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[1][1]},
275         {BUNNY_STAND_R1 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[1][0]},
276     },
277     {
278         {BUNNY_STAND_R2 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[2][1]},
279         {BUNNY_STAND_R2 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[2][0]},
280     },
281     {
282         {BUNNY_STAND_R3 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[3][1]},
283         {BUNNY_STAND_R3 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[3][0]},
284     },
285     {
286         {BUNNY_STAND_R4 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[4][1]},
287         {BUNNY_STAND_R4 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[4][0]},
288     },
289 };
290 
291 
292 STATEp sg_BunnyScrew[] =
293 {
294     s_BunnyScrew[0],
295     s_BunnyScrew[1],
296     s_BunnyScrew[2],
297     s_BunnyScrew[3],
298     s_BunnyScrew[4]
299 };
300 
301 //////////////////////
302 //
303 // BUNNY SWIPE
304 //
305 //////////////////////
306 
307 #define BUNNY_SWIPE_RATE 8
308 ANIMATOR InitActorDecide;
309 ANIMATOR InitBunnySlash;
310 
311 STATE s_BunnySwipe[5][8] =
312 {
313     {
314         {BUNNY_SWIPE_R0 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][1]},
315         {BUNNY_SWIPE_R0 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][2]},
316         {BUNNY_SWIPE_R0 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[0][3]},
317         {BUNNY_SWIPE_R0 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][4]},
318         {BUNNY_SWIPE_R0 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][5]},
319         {BUNNY_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[0][6]},
320         {BUNNY_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[0][7]},
321         {BUNNY_SWIPE_R0 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[0][7]},
322     },
323     {
324         {BUNNY_SWIPE_R1 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][1]},
325         {BUNNY_SWIPE_R1 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][2]},
326         {BUNNY_SWIPE_R1 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[1][3]},
327         {BUNNY_SWIPE_R1 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][4]},
328         {BUNNY_SWIPE_R1 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][5]},
329         {BUNNY_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[1][6]},
330         {BUNNY_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[1][7]},
331         {BUNNY_SWIPE_R1 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[1][7]},
332     },
333     {
334         {BUNNY_SWIPE_R2 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][1]},
335         {BUNNY_SWIPE_R2 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][2]},
336         {BUNNY_SWIPE_R2 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[2][3]},
337         {BUNNY_SWIPE_R2 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][4]},
338         {BUNNY_SWIPE_R2 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][5]},
339         {BUNNY_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[2][6]},
340         {BUNNY_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[2][7]},
341         {BUNNY_SWIPE_R2 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[2][7]},
342     },
343     {
344         {BUNNY_SWIPE_R3 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][1]},
345         {BUNNY_SWIPE_R3 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][2]},
346         {BUNNY_SWIPE_R3 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[3][3]},
347         {BUNNY_SWIPE_R3 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][4]},
348         {BUNNY_SWIPE_R3 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][5]},
349         {BUNNY_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[3][6]},
350         {BUNNY_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[3][7]},
351         {BUNNY_SWIPE_R3 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[3][7]},
352     },
353     {
354         {BUNNY_SWIPE_R4 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][1]},
355         {BUNNY_SWIPE_R4 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][2]},
356         {BUNNY_SWIPE_R4 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[4][3]},
357         {BUNNY_SWIPE_R4 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][4]},
358         {BUNNY_SWIPE_R4 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][5]},
359         {BUNNY_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[4][6]},
360         {BUNNY_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[4][7]},
361         {BUNNY_SWIPE_R4 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[4][7]},
362     }
363 };
364 
365 
366 STATEp sg_BunnySwipe[] =
367 {
368     &s_BunnySwipe[0][0],
369     &s_BunnySwipe[1][0],
370     &s_BunnySwipe[2][0],
371     &s_BunnySwipe[3][0],
372     &s_BunnySwipe[4][0]
373 };
374 
375 
376 //////////////////////
377 //
378 // BUNNY HEART - show players heart
379 //
380 //////////////////////
381 
382 #define BUNNY_HEART_RATE 14
383 ANIMATOR DoBunnyStandKill;
384 
385 STATE s_BunnyHeart[5][4] =
386 {
387     {
388         {BUNNY_SWIPE_R0 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[0][0]},
389     },
390     {
391         {BUNNY_SWIPE_R1 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[1][0]},
392     },
393     {
394         {BUNNY_SWIPE_R2 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[2][0]},
395     },
396     {
397         {BUNNY_SWIPE_R3 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[3][0]},
398     },
399     {
400         {BUNNY_SWIPE_R4 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[4][0]},
401     }
402 };
403 
404 
405 STATEp sg_BunnyHeart[] =
406 {
407     &s_BunnyHeart[0][0],
408     &s_BunnyHeart[1][0],
409     &s_BunnyHeart[2][0],
410     &s_BunnyHeart[3][0],
411     &s_BunnyHeart[4][0]
412 };
413 
414 //////////////////////
415 //
416 // BUNNY PAIN
417 //
418 //////////////////////
419 
420 #define BUNNY_PAIN_RATE 38
421 ANIMATOR DoBunnyPain;
422 
423 STATE s_BunnyPain[5][1] =
424 {
425     {
426         {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[0][0]},
427     },
428     {
429         {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[1][0]},
430     },
431     {
432         {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[2][0]},
433     },
434     {
435         {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[3][0]},
436     },
437     {
438         {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[4][0]},
439     }
440 };
441 
442 STATEp sg_BunnyPain[] =
443 {
444     &s_BunnyPain[0][0],
445     &s_BunnyPain[1][0],
446     &s_BunnyPain[2][0],
447     &s_BunnyPain[3][0],
448     &s_BunnyPain[4][0]
449 };
450 
451 //////////////////////
452 //
453 // BUNNY JUMP
454 //
455 //////////////////////
456 
457 #define BUNNY_JUMP_RATE 25
458 
459 STATE s_BunnyJump[5][6] =
460 {
461     {
462         {BUNNY_RUN_R0 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[0][1]},
463         {BUNNY_RUN_R0 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[0][1]},
464     },
465     {
466         {BUNNY_RUN_R1 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[1][1]},
467         {BUNNY_RUN_R1 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[1][1]},
468     },
469     {
470         {BUNNY_RUN_R2 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[2][1]},
471         {BUNNY_RUN_R2 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[2][1]},
472     },
473     {
474         {BUNNY_RUN_R3 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[3][1]},
475         {BUNNY_RUN_R3 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[3][1]},
476     },
477     {
478         {BUNNY_RUN_R4 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[4][1]},
479         {BUNNY_RUN_R4 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[4][1]},
480     }
481 };
482 
483 
484 STATEp sg_BunnyJump[] =
485 {
486     &s_BunnyJump[0][0],
487     &s_BunnyJump[1][0],
488     &s_BunnyJump[2][0],
489     &s_BunnyJump[3][0],
490     &s_BunnyJump[4][0]
491 };
492 
493 
494 //////////////////////
495 //
496 // BUNNY FALL
497 //
498 //////////////////////
499 
500 #define BUNNY_FALL_RATE 25
501 
502 STATE s_BunnyFall[5][6] =
503 {
504     {
505         {BUNNY_RUN_R0 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[0][0]},
506     },
507     {
508         {BUNNY_RUN_R1 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[1][0]},
509     },
510     {
511         {BUNNY_RUN_R2 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[2][0]},
512     },
513     {
514         {BUNNY_RUN_R3 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[3][0]},
515     },
516     {
517         {BUNNY_RUN_R4 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[4][0]},
518     }
519 };
520 
521 
522 STATEp sg_BunnyFall[] =
523 {
524     &s_BunnyFall[0][0],
525     &s_BunnyFall[1][0],
526     &s_BunnyFall[2][0],
527     &s_BunnyFall[3][0],
528     &s_BunnyFall[4][0]
529 };
530 
531 
532 //////////////////////
533 //
534 // BUNNY JUMP ATTACK
535 //
536 //////////////////////
537 
538 #define BUNNY_JUMP_ATTACK_RATE 35
539 int DoBunnyBeginJumpAttack(short SpriteNum);
540 
541 STATE s_BunnyJumpAttack[5][6] =
542 {
543     {
544         {BUNNY_RUN_R0 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[0][1]},
545         {BUNNY_RUN_R0 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[0][2]},
546         {BUNNY_RUN_R0 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[0][2]},
547     },
548     {
549         {BUNNY_RUN_R1 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[1][1]},
550         {BUNNY_RUN_R1 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[1][2]},
551         {BUNNY_RUN_R1 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[1][2]},
552     },
553     {
554         {BUNNY_RUN_R2 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[2][1]},
555         {BUNNY_RUN_R2 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[2][2]},
556         {BUNNY_RUN_R2 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[2][2]},
557     },
558     {
559         {BUNNY_RUN_R3 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[3][1]},
560         {BUNNY_RUN_R3 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[3][2]},
561         {BUNNY_RUN_R3 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[3][2]},
562     },
563     {
564         {BUNNY_RUN_R4 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[4][1]},
565         {BUNNY_RUN_R4 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[4][2]},
566         {BUNNY_RUN_R4 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[4][2]},
567     }
568 };
569 
570 
571 STATEp sg_BunnyJumpAttack[] =
572 {
573     &s_BunnyJumpAttack[0][0],
574     &s_BunnyJumpAttack[1][0],
575     &s_BunnyJumpAttack[2][0],
576     &s_BunnyJumpAttack[3][0],
577     &s_BunnyJumpAttack[4][0]
578 };
579 
580 
581 //////////////////////
582 //
583 // BUNNY DIE
584 //
585 //////////////////////
586 
587 #define BUNNY_DIE_RATE 16
588 ANIMATOR BunnySpew;
589 
590 STATE s_BunnyDie[] =
591 {
592     {BUNNY_DIE + 0, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[1]},
593     {BUNNY_DIE + 0, SF_QUICK_CALL,  BunnySpew, &s_BunnyDie[2]},
594     {BUNNY_DIE + 1, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[3]},
595     {BUNNY_DIE + 2, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[4]},
596     {BUNNY_DIE + 2, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[5]},
597     {BUNNY_DEAD, BUNNY_DIE_RATE, DoActorDebris, &s_BunnyDie[5]},
598 };
599 
600 #define BUNNY_DEAD_RATE 8
601 
602 STATE s_BunnyDead[] =
603 {
604     {BUNNY_DIE + 0, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDie[1]},
605     {BUNNY_DIE + 0, SF_QUICK_CALL,  BunnySpew, &s_BunnyDie[2]},
606     {BUNNY_DIE + 1, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDead[3]},
607     {BUNNY_DIE + 2, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDead[4]},
608     {BUNNY_DEAD, SF_QUICK_CALL, QueueFloorBlood, &s_BunnyDead[5]},
609     {BUNNY_DEAD, BUNNY_DEAD_RATE, DoActorDebris, &s_BunnyDead[5]},
610 };
611 
612 STATEp sg_BunnyDie[] =
613 {
614     s_BunnyDie
615 };
616 
617 STATEp sg_BunnyDead[] =
618 {
619     s_BunnyDead
620 };
621 
622 STATE s_BunnyDeathJump[] =
623 {
624     {BUNNY_DIE + 0, BUNNY_DIE_RATE, DoActorDeathMove, &s_BunnyDeathJump[0]}
625 };
626 
627 STATE s_BunnyDeathFall[] =
628 {
629     {BUNNY_DIE + 1, BUNNY_DIE_RATE, DoActorDeathMove, &s_BunnyDeathFall[0]}
630 };
631 
632 STATEp sg_BunnyDeathJump[] =
633 {
634     s_BunnyDeathJump
635 };
636 
637 STATEp sg_BunnyDeathFall[] =
638 {
639     s_BunnyDeathFall
640 };
641 
642 
643 /*
644 STATEp *Stand[MAX_WEAPONS];
645 STATEp *Run;
646 STATEp *Jump;
647 STATEp *Fall;
648 STATEp *Crawl;
649 STATEp *Swim;
650 STATEp *Fly;
651 STATEp *Rise;
652 STATEp *Sit;
653 STATEp *Look;
654 STATEp *Climb;
655 STATEp *Pain;
656 STATEp *Death1;
657 STATEp *Death2;
658 STATEp *Dead;
659 STATEp *DeathJump;
660 STATEp *DeathFall;
661 STATEp *CloseAttack[2];
662 STATEp *Attack[6];
663 STATEp *Special[2];
664 */
665 
666 ACTOR_ACTION_SET BunnyActionSet =
667 {
668     sg_BunnyStand,
669     sg_BunnyRun,
670     sg_BunnyJump,
671     sg_BunnyFall,
672     NULL,                               // sg_BunnyCrawl,
673     NULL,                               // sg_BunnySwim,
674     NULL,                               // sg_BunnyFly,
675     NULL,                               // sg_BunnyRise,
676     NULL,                               // sg_BunnySit,
677     NULL,                               // sg_BunnyLook,
678     NULL,                               // climb
679     sg_BunnyPain,
680     sg_BunnyDie,
681     NULL,
682     sg_BunnyDead,
683     sg_BunnyDeathJump,
684     sg_BunnyDeathFall,
685     {NULL},
686     {1024},
687     {NULL},
688     {1024},
689     {sg_BunnyHeart, sg_BunnyRun},
690     NULL,
691     NULL
692 };
693 
694 ACTOR_ACTION_SET BunnyWhiteActionSet =
695 {
696     sg_BunnyStand,
697     sg_BunnyRun,
698     sg_BunnyJump,
699     sg_BunnyFall,
700     NULL,                               // sg_BunnyCrawl,
701     NULL,                               // sg_BunnySwim,
702     NULL,                               // sg_BunnyFly,
703     NULL,                               // sg_BunnyRise,
704     NULL,                               // sg_BunnySit,
705     NULL,                               // sg_BunnyLook,
706     NULL,                               // climb
707     sg_BunnyPain,                       // pain
708     sg_BunnyDie,
709     NULL,
710     sg_BunnyDead,
711     sg_BunnyDeathJump,
712     sg_BunnyDeathFall,
713     {sg_BunnySwipe},
714     {1024},
715 //    {sg_BunnyJumpAttack, sg_BunnySwipe},
716 //    {800, 1024},
717     {sg_BunnySwipe},
718     {1024},
719     {sg_BunnyHeart, sg_BunnySwipe},
720     NULL,
721     NULL
722 };
723 
724 int
SetupBunny(short SpriteNum)725 SetupBunny(short SpriteNum)
726 {
727     SPRITEp sp = &sprite[SpriteNum];
728     USERp u;
729     ANIMATOR DoActorDecide;
730 
731     if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
732     {
733         u = User[SpriteNum];
734         ASSERT(u);
735     }
736     else
737     {
738         User[SpriteNum] = u = SpawnUser(SpriteNum, BUNNY_RUN_R0, s_BunnyRun[0]);
739         u->Health = 10;
740     }
741 
742     Bunny_Count++;
743     //if(Bunny_Count > 20)
744     //    {
745     //    KillSprite(SpriteNum);
746     //    Bunny_Count--;
747     //    return(0);
748     //    }
749 
750     ChangeState(SpriteNum, s_BunnyRun[0]);
751     u->StateEnd = s_BunnyDie;
752     u->Rot = sg_BunnyRun;
753     //sp->xrepeat = 64;
754     //sp->yrepeat = 64;
755     u->ShellNum = 0; // Not Pregnant right now
756     u->FlagOwner = 0;
757 
758     sp->clipdist = (150) >> 2;
759 
760     if (sp->pal == PALETTE_PLAYER1)
761     {
762         EnemyDefaults(SpriteNum, &BunnyWhiteActionSet, &WhiteBunnyPersonality);
763         u->Attrib = &WhiteBunnyAttrib;
764         sp->xrepeat = 96;
765         sp->yrepeat = 90;
766 
767         sp->clipdist = 200>>2;
768 
769         if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
770             u->Health = 60;
771     }
772     else if (sp->pal == PALETTE_PLAYER8) // Male Rabbit
773     {
774         EnemyDefaults(SpriteNum, &BunnyActionSet, &BunnyPersonality);
775         u->Attrib = &BunnyAttrib;
776         //sp->xrepeat = 76;
777         //sp->yrepeat = 70;
778 
779         //sp->shade = 0; // darker
780         if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
781             u->Health = 20;
782         u->Flag1 = 0;
783     }
784     else
785     {
786         // Female Rabbit
787         EnemyDefaults(SpriteNum, &BunnyActionSet, &BunnyPersonality);
788         u->Attrib = &BunnyAttrib;
789         u->spal = sp->pal = PALETTE_PLAYER0;
790         u->Flag1 = SEC(5);
791         //sp->shade = 0; // darker
792     }
793 
794     DoActorSetSpeed(SpriteNum, FAST_SPEED);
795 
796     SET(u->Flags, SPR_XFLIP_TOGGLE);
797 
798 
799     u->zclip = Z(16);
800     u->floor_dist = Z(8);
801     u->ceiling_dist = Z(8);
802     u->lo_step = Z(16);
803 
804     return 0;
805 }
806 
807 int
GetBunnyJumpHeight(short jump_speed,short jump_grav)808 GetBunnyJumpHeight(short jump_speed, short jump_grav)
809 {
810     int jump_iterations;
811     int height;
812 
813     jump_speed = labs(jump_speed);
814 
815     jump_iterations = jump_speed / (jump_grav * ACTORMOVETICS);
816 
817     height = jump_speed * jump_iterations * ACTORMOVETICS;
818 
819     height = DIV256(height);
820 
821     return DIV2(height);
822 }
823 
824 int
PickBunnyJumpSpeed(short SpriteNum,int pix_height)825 PickBunnyJumpSpeed(short SpriteNum, int pix_height)
826 {
827     USERp u = User[SpriteNum];
828 
829     ASSERT(pix_height < 128);
830 
831     u->jump_speed = -600;
832     u->jump_grav = 8;
833 
834     while (TRUE)
835     {
836         if (GetBunnyJumpHeight(u->jump_speed, u->jump_grav) > pix_height + 20)
837             break;
838 
839         u->jump_speed -= 100;
840 
841         ASSERT(u->jump_speed > -3000);
842     }
843 
844     return u->jump_speed;
845 }
846 
847 //
848 // JUMP ATTACK
849 //
850 
851 int
DoBunnyBeginJumpAttack(short SpriteNum)852 DoBunnyBeginJumpAttack(short SpriteNum)
853 {
854     SPRITEp sp = &sprite[SpriteNum];
855     USERp u = User[SpriteNum];
856     SPRITEp psp = User[SpriteNum]->tgt_sp;
857     int CanSeePlayer(short SpriteNum);
858     short tang;
859 
860     tang = getangle(psp->x - sp->x, psp->y - sp->y);
861 
862     if (move_sprite(SpriteNum, sintable[NORM_ANGLE(tang+512)] >> 7, sintable[tang] >> 7,
863                     0L, u->ceiling_dist, u->floor_dist, CLIPMASK_ACTOR, ACTORMOVETICS))
864         sp->ang = NORM_ANGLE(sp->ang + 1024) + (RANDOM_NEG(256, 6) >> 6);
865     else
866         sp->ang = NORM_ANGLE(tang + (RANDOM_NEG(256, 6) >> 6));
867 
868     DoActorSetSpeed(SpriteNum, FAST_SPEED);
869 
870     //u->jump_speed = -800;
871     PickJumpMaxSpeed(SpriteNum, -400); // was -800
872 
873     SET(u->Flags, SPR_JUMPING);
874     RESET(u->Flags, SPR_FALLING);
875 
876     // set up individual actor jump gravity
877     u->jump_grav = 17; // was 8
878 
879     // if I didn't do this here they get stuck in the air sometimes
880     DoActorZrange(SpriteNum);
881 
882     DoJump(SpriteNum);
883 
884     return 0;
885 }
886 
887 int
DoBunnyMoveJump(short SpriteNum)888 DoBunnyMoveJump(short SpriteNum)
889 {
890     SPRITEp sp = &sprite[SpriteNum];
891     USERp u = User[SpriteNum];
892 
893     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
894     {
895         int nx, ny;
896 
897         // Move while jumping
898         nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
899         ny = sp->xvel * (int) sintable[sp->ang] >> 14;
900 
901         move_actor(SpriteNum, nx, ny, 0L);
902 
903         if (TEST(u->Flags, SPR_JUMPING))
904             DoActorJump(SpriteNum);
905         else
906             DoActorFall(SpriteNum);
907     }
908 
909     DoActorZrange(SpriteNum);
910 
911     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
912     {
913 //        if (DoBunnyQuickJump(SpriteNum))
914 //            return (0);
915 
916         InitActorDecide(SpriteNum);
917     }
918 
919     return 0;
920 }
921 
922 int
DoPickCloseBunny(short SpriteNum)923 DoPickCloseBunny(short SpriteNum)
924 {
925     USERp u = User[SpriteNum],tu;
926     SPRITEp sp = &sprite[SpriteNum],tsp;
927     int dist, near_dist = 1000, a,b,c;
928     short i, nexti;
929     //short BunnyCount=0, Bunny_Result = -1;
930 
931     // if actor can still see the player
932     int look_height = SPRITEp_TOS(sp);
933     SWBOOL ICanSee = FALSE;
934 
935     TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti)
936     {
937         tsp = &sprite[i];
938         tu = User[i];
939 
940         if (sp == tsp) continue;
941 
942         if (tu->ID != BUNNY_RUN_R0) continue;
943 
944         DISTANCE(tsp->x, tsp->y, sp->x, sp->y, dist, a, b, c);
945 
946         if (dist > near_dist) continue;
947 
948         ICanSee = FAFcansee(sp->x, sp->y, look_height, sp->sectnum, tsp->x, tsp->y, SPRITEp_UPPER(tsp), tsp->sectnum);
949 
950         if (ICanSee && dist < near_dist && tu->ID == BUNNY_RUN_R0)
951         {
952             near_dist = dist;
953             u->tgt_sp = u->lo_sp = tsp;
954             //Bunny_Result = i;
955             return i;
956         }
957     }
958     return -1;
959 }
960 
961 int
DoBunnyQuickJump(short SpriteNum)962 DoBunnyQuickJump(short SpriteNum)
963 {
964     SPRITEp sp = &sprite[SpriteNum];
965     USERp u = User[SpriteNum];
966 
967     if (u->spal != PALETTE_PLAYER8) return FALSE;
968 
969     if (!u->lo_sp && u->spal == PALETTE_PLAYER8 && MoveSkip4)
970         DoPickCloseBunny(SpriteNum);
971 
972     // Random Chance of like sexes fighting
973     if (u->lo_sp)
974     {
975         short hit_sprite = u->lo_sp - sprite;
976         SPRITEp tsp = u->lo_sp;
977         USERp tu = User[hit_sprite];
978 
979         if (!tu || tu->ID != BUNNY_RUN_R0) return FALSE;
980 
981 
982         // Not mature enough yet
983         if (sp->xrepeat != 64 || sp->yrepeat != 64) return FALSE;
984         if (tsp->xrepeat != 64 || tsp->yrepeat != 64) return FALSE;
985 
986         // Kill a rival
987         // Only males fight
988         if (tu->spal == sp->pal && RANDOM_RANGE(1000) > 995)
989         {
990             if (u->spal == PALETTE_PLAYER8 && tu->spal == PALETTE_PLAYER8)
991             {
992                 PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_follow);
993                 PlaySound(DIGI_BUNNYDIE2, &tsp->x, &tsp->y, &tsp->z, v3df_follow);
994                 tu->Health = 0;
995 
996                 // Blood fountains
997                 InitBloodSpray(hit_sprite,TRUE,-1);
998 
999                 if (SpawnShrap(hit_sprite, SpriteNum))
1000                 {
1001                     SetSuicide(hit_sprite);
1002                 }
1003                 else
1004                     DoActorDie(hit_sprite, SpriteNum);
1005 
1006                 Bunny_Count--; // Bunny died
1007 
1008                 u->lo_sp = NULL;
1009                 return TRUE;
1010             }
1011         }
1012     }
1013 
1014     // Get layed!
1015     if (u->lo_sp && u->spal == PALETTE_PLAYER8) // Only males check this
1016     {
1017         short hit_sprite = u->lo_sp - sprite;
1018         SPRITEp tsp = u->lo_sp;
1019         USERp tu = User[hit_sprite];
1020 
1021 
1022         if (!tu || tu->ID != BUNNY_RUN_R0) return FALSE;
1023 
1024         // Not mature enough to mate yet
1025         if (sp->xrepeat != 64 || sp->yrepeat != 64) return FALSE;
1026         if (tsp->xrepeat != 64 || tsp->yrepeat != 64) return FALSE;
1027 
1028         if (tu->ShellNum <= 0 && tu->WaitTics <= 0 && u->WaitTics <= 0)
1029         {
1030             if (TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY))
1031             {
1032                 PLAYERp pp = NULL;
1033 
1034                 if (RANDOM_RANGE(1000) < 995 && tu->spal != PALETTE_PLAYER0) return FALSE;
1035 
1036                 DoActorPickClosePlayer(SpriteNum);
1037 
1038                 if (User[u->tgt_sp-sprite]->PlayerP)
1039                     pp = User[u->tgt_sp-sprite]->PlayerP;
1040 
1041                 if (tu->spal != PALETTE_PLAYER0)
1042                 {
1043                     if (tu->Flag1 > 0) return FALSE;
1044                     tu->FlagOwner = 1; // FAG!
1045                     tu->Flag1 = SEC(10);
1046                     if (pp)
1047                     {
1048                         short choose_snd;
1049                         int fagsnds[] = {DIGI_FAGRABBIT1,DIGI_FAGRABBIT2,DIGI_FAGRABBIT3};
1050 
1051                         if (pp == Player+myconnectindex)
1052                         {
1053                             choose_snd = STD_RANDOM_RANGE(2<<8)>>8;
1054                             if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp))
1055                                 PlayerSound(fagsnds[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_doppler|v3df_follow|v3df_dontpan,pp);
1056                         }
1057                     }
1058                 }
1059                 else
1060                 {
1061                     if (pp && RANDOM_RANGE(1000) > 200)
1062                     {
1063                         short choose_snd;
1064                         int straightsnds[] = {DIGI_RABBITHUMP1,DIGI_RABBITHUMP2,
1065                                               DIGI_RABBITHUMP3,DIGI_RABBITHUMP4};
1066 
1067                         if (pp == Player+myconnectindex)
1068                         {
1069                             choose_snd = STD_RANDOM_RANGE(3<<8)>>8;
1070                             if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp))
1071                                 PlayerSound(straightsnds[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_doppler|v3df_follow|v3df_dontpan,pp);
1072                         }
1073                     }
1074                 }
1075 
1076                 sp->x = tsp->x; // Mount up little bunny
1077                 sp->y = tsp->y;
1078                 sp->ang = tsp->ang;
1079                 sp->ang = NORM_ANGLE(sp->ang + 1024);
1080                 HelpMissileLateral(SpriteNum, 2000L);
1081                 sp->ang = tsp->ang;
1082                 u->Vis = sp->ang;  // Remember angles for later
1083                 tu->Vis = tsp->ang;
1084 
1085                 NewStateGroup(SpriteNum, sg_BunnyScrew);
1086                 NewStateGroup(hit_sprite, sg_BunnyScrew);
1087                 if (gs.ParentalLock || Global_PLock)
1088                 {
1089                     SET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' invisible
1090                     SET(tsp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' invisible
1091                 }
1092                 u->WaitTics = tu->WaitTics = SEC(10);  // Mate for this long
1093                 return TRUE;
1094             }
1095         }
1096     }
1097 
1098     return FALSE;
1099 }
1100 
1101 
1102 int
NullBunny(short SpriteNum)1103 NullBunny(short SpriteNum)
1104 {
1105     USERp u = User[SpriteNum];
1106 
1107 
1108     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1109     {
1110         if (TEST(u->Flags, SPR_JUMPING))
1111             DoActorJump(SpriteNum);
1112         else
1113             DoActorFall(SpriteNum);
1114     }
1115 
1116     // stay on floor unless doing certain things
1117     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1118         KeepActorOnFloor(SpriteNum);
1119 
1120     if (TEST(u->Flags,SPR_SLIDING))
1121         DoActorSlide(SpriteNum);
1122 
1123     DoActorSectorDamage(SpriteNum);
1124 
1125     return 0;
1126 }
1127 
1128 
DoBunnyPain(short SpriteNum)1129 int DoBunnyPain(short SpriteNum)
1130 {
1131     USERp u = User[SpriteNum];
1132 
1133     NullBunny(SpriteNum);
1134 
1135     if ((u->WaitTics -= ACTORMOVETICS) <= 0)
1136         InitActorDecide(SpriteNum);
1137     return 0;
1138 }
1139 
DoBunnyRipHeart(short SpriteNum)1140 int DoBunnyRipHeart(short SpriteNum)
1141 {
1142     SPRITEp sp = &sprite[SpriteNum];
1143     USERp u = User[SpriteNum];
1144 
1145     SPRITEp tsp = u->tgt_sp;
1146 
1147     NewStateGroup(SpriteNum, sg_BunnyHeart);
1148     u->WaitTics = 6 * 120;
1149 
1150     // player face bunny
1151     tsp->ang = getangle(sp->x - tsp->x, sp->y - tsp->y);
1152     return 0;
1153 }
1154 
DoBunnyStandKill(short SpriteNum)1155 int DoBunnyStandKill(short SpriteNum)
1156 {
1157     SPRITEp sp = &sprite[SpriteNum];
1158     USERp u = User[SpriteNum];
1159 
1160     NullBunny(SpriteNum);
1161 
1162     // Growl like the bad ass bunny you are!
1163     if (RANDOM_RANGE(1000) > 800)
1164         PlaySound(DIGI_BUNNYATTACK,&sp->x,&sp->y,&sp->z,v3df_none);
1165 
1166     if ((u->WaitTics -= ACTORMOVETICS) <= 0)
1167         NewStateGroup(SpriteNum, sg_BunnyRun);
1168     return 0;
1169 }
1170 
BunnyHatch(short Weapon)1171 void BunnyHatch(short Weapon)
1172 {
1173     SPRITEp wp = &sprite[Weapon];
1174     USERp wu = User[Weapon];
1175 
1176     short New,i;
1177     SPRITEp np;
1178     USERp nu;
1179 #define MAX_BUNNYS 1
1180     short rip_ang[MAX_BUNNYS];
1181 
1182     rip_ang[0] = RANDOM_P2(2048);
1183 
1184     for (i = 0; i < MAX_BUNNYS; i++)
1185     {
1186         New = COVERinsertsprite(wp->sectnum, STAT_DEFAULT);
1187         np = &sprite[New];
1188         memset(np,0,sizeof(SPRITE));
1189         np->sectnum = wp->sectnum;
1190         np->statnum = STAT_DEFAULT;
1191         np->x = wp->x;
1192         np->y = wp->y;
1193         np->z = wp->z;
1194         np->owner = -1;
1195         np->xrepeat = 30;  // Baby size
1196         np->yrepeat = 24;
1197         np->ang = rip_ang[i];
1198         np->pal = 0;
1199         SetupBunny(New);
1200         nu = User[New];
1201         np->shade = wp->shade;
1202 
1203         // make immediately active
1204         SET(nu->Flags, SPR_ACTIVE);
1205         if (RANDOM_RANGE(1000) > 500) // Boy or Girl?
1206             nu->spal = np->pal = PALETTE_PLAYER0; // Girl
1207         else
1208         {
1209             nu->spal = np->pal = PALETTE_PLAYER8; // Boy
1210             // Oops, mommy died giving birth to a boy
1211             if (RANDOM_RANGE(1000) > 500)
1212             {
1213                 wu->Health = 0;
1214                 Bunny_Count--; // Bunny died
1215 
1216                 // Blood fountains
1217                 InitBloodSpray(Weapon,TRUE,-1);
1218 
1219                 if (SpawnShrap(Weapon, New))
1220                 {
1221                     SetSuicide(Weapon);
1222                 }
1223                 else
1224                     DoActorDie(Weapon, New);
1225             }
1226         }
1227 
1228         nu->ShellNum = 0; // Not Pregnant right now
1229 
1230         NewStateGroup(New, nu->ActorActionSet->Jump);
1231         nu->ActorActionFunc = DoActorMoveJump;
1232         DoActorSetSpeed(New, FAST_SPEED);
1233         PickJumpMaxSpeed(New, -600);
1234 
1235         SET(nu->Flags, SPR_JUMPING);
1236         RESET(nu->Flags, SPR_FALLING);
1237 
1238         nu->jump_grav = 8;
1239 
1240         // if I didn't do this here they get stuck in the air sometimes
1241         DoActorZrange(New);
1242 
1243         DoActorJump(New);
1244     }
1245 }
1246 
BunnyHatch2(short Weapon)1247 int BunnyHatch2(short Weapon)
1248 {
1249     SPRITEp wp = &sprite[Weapon];
1250 
1251     short New;
1252     SPRITEp np;
1253     USERp nu;
1254 
1255     New = COVERinsertsprite(wp->sectnum, STAT_DEFAULT);
1256     np = &sprite[New];
1257     memset(np,0,sizeof(SPRITE));
1258     np->sectnum = wp->sectnum;
1259     np->statnum = STAT_DEFAULT;
1260     np->x = wp->x;
1261     np->y = wp->y;
1262     np->z = wp->z;
1263     np->owner = -1;
1264     np->xrepeat = 30;  // Baby size
1265     np->yrepeat = 24;
1266     np->ang = RANDOM_P2(2048);
1267     np->pal = 0;
1268     SetupBunny(New);
1269     nu = User[New];
1270     np->shade = wp->shade;
1271 
1272     // make immediately active
1273     SET(nu->Flags, SPR_ACTIVE);
1274     if (RANDOM_RANGE(1000) > 500) // Boy or Girl?
1275     {
1276         nu->spal = np->pal = PALETTE_PLAYER0; // Girl
1277         nu->Flag1 = SEC(5);
1278     }
1279     else
1280     {
1281         nu->spal = np->pal = PALETTE_PLAYER8; // Boy
1282         nu->Flag1 = 0;
1283     }
1284 
1285     nu->ShellNum = 0; // Not Pregnant right now
1286 
1287     NewStateGroup(New, nu->ActorActionSet->Jump);
1288     nu->ActorActionFunc = DoActorMoveJump;
1289     DoActorSetSpeed(New, FAST_SPEED);
1290     if (TEST_BOOL3(wp))
1291     {
1292         PickJumpMaxSpeed(New, -600-RANDOM_RANGE(600));
1293         np->xrepeat = np->yrepeat = 64;
1294         np->xvel = 150 + RANDOM_RANGE(1000);
1295         nu->Health = 1; // Easy to pop. Like shootn' skeet.
1296         np->ang -= RANDOM_RANGE(128);
1297         np->ang += RANDOM_RANGE(128);
1298     }
1299     else
1300         PickJumpMaxSpeed(New, -600);
1301 
1302     SET(nu->Flags, SPR_JUMPING);
1303     RESET(nu->Flags, SPR_FALLING);
1304 
1305     nu->jump_grav = 8;
1306     nu->FlagOwner = 0;
1307 
1308     nu->active_range = 75000; // Set it far
1309 
1310     // if I didn't do this here they get stuck in the air sometimes
1311     DoActorZrange(New);
1312 
1313     DoActorJump(New);
1314 
1315     return New;
1316 }
1317 
1318 int
DoBunnyMove(short SpriteNum)1319 DoBunnyMove(short SpriteNum)
1320 {
1321     SPRITEp sp = &sprite[SpriteNum];
1322     USERp u = User[SpriteNum];
1323 
1324     // Parental lock crap
1325     if (TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
1326         RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' back on
1327 
1328     // Sometimes they just won't die!
1329     if (u->Health <= 0)
1330         SetSuicide(SpriteNum);
1331 
1332     if (u->scale_speed)
1333     {
1334         DoScaleSprite(SpriteNum);
1335     }
1336 
1337     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1338     {
1339         if (TEST(u->Flags, SPR_JUMPING))
1340             DoActorJump(SpriteNum);
1341         else
1342             DoActorFall(SpriteNum);
1343     }
1344 
1345     // if on a player/enemy sprite jump quickly
1346     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1347     {
1348         DoBunnyQuickJump(SpriteNum);
1349     }
1350 
1351     if (TEST(u->Flags, SPR_SLIDING))
1352         DoActorSlide(SpriteNum);
1353 
1354     if (u->track >= 0)
1355         ActorFollowTrack(SpriteNum, ACTORMOVETICS);
1356     else
1357         (*u->ActorActionFunc)(SpriteNum);
1358 
1359     // stay on floor unless doing certain things
1360     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1361         KeepActorOnFloor(SpriteNum);
1362 
1363     DoActorSectorDamage(SpriteNum);
1364 
1365     if (RANDOM_RANGE(1000) > 985 && sp->pal != PALETTE_PLAYER1 && u->track < 0)
1366     {
1367         switch (sector[sp->sectnum].floorpicnum)
1368         {
1369         case 153:
1370         case 154:
1371         case 193:
1372         case 219:
1373         case 2636:
1374         case 2689:
1375         case 3561:
1376         case 3562:
1377         case 3563:
1378         case 3564:
1379             NewStateGroup(SpriteNum,sg_BunnyStand);
1380             break;
1381         default:
1382             sp->ang = NORM_ANGLE(RANDOM_RANGE(2048 << 6) >> 6);
1383             u->jump_speed = -350;
1384             DoActorBeginJump(SpriteNum);
1385             u->ActorActionFunc = DoActorMoveJump;
1386             break;
1387         }
1388     }
1389 
1390     return 0;
1391 }
1392 
1393 int
BunnySpew(short SpriteNum)1394 BunnySpew(short SpriteNum)
1395 {
1396     //InitBloodSpray(SpriteNum,TRUE,-1);
1397     InitBloodSpray(SpriteNum,TRUE,-1);
1398     return 0;
1399 }
1400 
1401 int
DoBunnyEat(short SpriteNum)1402 DoBunnyEat(short SpriteNum)
1403 {
1404     SPRITEp sp = &sprite[SpriteNum];
1405     USERp u = User[SpriteNum];
1406 
1407 
1408     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1409     {
1410         if (TEST(u->Flags, SPR_JUMPING))
1411             DoActorJump(SpriteNum);
1412         else
1413             DoActorFall(SpriteNum);
1414     }
1415 
1416     // if on a player/enemy sprite jump quickly
1417     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1418     {
1419         DoBunnyQuickJump(SpriteNum);
1420     }
1421 
1422     if (TEST(u->Flags, SPR_SLIDING))
1423         DoActorSlide(SpriteNum);
1424 
1425     // stay on floor unless doing certain things
1426     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1427         KeepActorOnFloor(SpriteNum);
1428 
1429     DoActorSectorDamage(SpriteNum);
1430 
1431     switch (sector[sp->sectnum].floorpicnum)
1432     {
1433     case 153:
1434     case 154:
1435     case 193:
1436     case 219:
1437     case 2636:
1438     case 2689:
1439     case 3561:
1440     case 3562:
1441     case 3563:
1442     case 3564:
1443         if (RANDOM_RANGE(1000) > 970)
1444             NewStateGroup(SpriteNum,sg_BunnyRun);
1445         break;
1446     default:
1447         NewStateGroup(SpriteNum,sg_BunnyRun);
1448         break;
1449     }
1450     return 0;
1451 }
1452 
1453 int
DoBunnyScrew(short SpriteNum)1454 DoBunnyScrew(short SpriteNum)
1455 {
1456     SPRITEp sp = &sprite[SpriteNum];
1457     USERp u = User[SpriteNum];
1458 
1459     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1460     {
1461         if (TEST(u->Flags, SPR_JUMPING))
1462             DoActorJump(SpriteNum);
1463         else
1464             DoActorFall(SpriteNum);
1465     }
1466 
1467     if (TEST(u->Flags, SPR_SLIDING))
1468         DoActorSlide(SpriteNum);
1469 
1470     // stay on floor unless doing certain things
1471     if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
1472         KeepActorOnFloor(SpriteNum);
1473 
1474     DoActorSectorDamage(SpriteNum);
1475 
1476     if (RANDOM_RANGE(1000) > 990) // Bunny sex sounds
1477     {
1478         if (!gs.ParentalLock && !Global_PLock)
1479             PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_follow);
1480     }
1481 
1482     u->WaitTics -= ACTORMOVETICS;
1483 
1484     if ((u->FlagOwner || u->spal == PALETTE_PLAYER0) && u->WaitTics > 0) // Keep Girl still
1485         NewStateGroup(SpriteNum,sg_BunnyScrew);
1486 
1487     if (u->spal == PALETTE_PLAYER0 && u->WaitTics <= 0) // Female has baby
1488     {
1489         u->Flag1 = SEC(5); // Count down to babies
1490         u->ShellNum = 1; // She's pregnant now
1491     }
1492 
1493     if (u->WaitTics <= 0)
1494     {
1495         RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' back on
1496         u->FlagOwner = 0;
1497         NewStateGroup(SpriteNum,sg_BunnyRun);
1498     }
1499 
1500     return 0;
1501 }
1502 
1503 int
DoBunnyGrowUp(short SpriteNum)1504 DoBunnyGrowUp(short SpriteNum)
1505 {
1506     SPRITEp sp = &sprite[SpriteNum];
1507     USERp u = User[SpriteNum];
1508 
1509     if (sp->pal == PALETTE_PLAYER1) return 0;   // Don't bother white bunnies
1510 
1511     if ((u->Counter -= ACTORMOVETICS) <= 0)
1512     {
1513         if ((++sp->xrepeat) > 64) sp->xrepeat = 64;
1514         if ((++sp->yrepeat) > 64) sp->yrepeat = 64;
1515         u->Counter = 60;
1516     }
1517 
1518     // Don't go homo too much!
1519     if (sp->pal != PALETTE_PLAYER0 && u->Flag1 > 0)
1520         u->Flag1 -= ACTORMOVETICS;
1521 
1522     // Gestation period for female rabbits
1523     if (sp->pal == PALETTE_PLAYER0 && u->ShellNum > 0)
1524     {
1525         if ((u->Flag1 -= ACTORMOVETICS) <= 0)
1526         {
1527             if (Bunny_Count < 20)
1528             {
1529                 PlaySound(DIGI_BUNNYDIE2, &sp->x, &sp->y, &sp->z, v3df_follow);
1530                 BunnyHatch(SpriteNum); // Baby time
1531             }
1532             u->ShellNum = 0; // Not pregnent anymore
1533         }
1534     }
1535 
1536     return 0;
1537 }
1538 
1539 
1540 #include "saveable.h"
1541 
1542 static saveable_code saveable_bunny_code[] =
1543 {
1544     SAVE_CODE(SetupBunny),
1545     SAVE_CODE(GetBunnyJumpHeight),
1546     SAVE_CODE(PickBunnyJumpSpeed),
1547     SAVE_CODE(DoBunnyBeginJumpAttack),
1548     SAVE_CODE(DoBunnyMoveJump),
1549     SAVE_CODE(DoPickCloseBunny),
1550     SAVE_CODE(DoBunnyQuickJump),
1551     SAVE_CODE(NullBunny),
1552     SAVE_CODE(DoBunnyPain),
1553     SAVE_CODE(DoBunnyRipHeart),
1554     SAVE_CODE(DoBunnyStandKill),
1555     SAVE_CODE(BunnyHatch),
1556     SAVE_CODE(BunnyHatch2),
1557     SAVE_CODE(DoBunnyMove),
1558     SAVE_CODE(BunnySpew),
1559     SAVE_CODE(DoBunnyEat),
1560     SAVE_CODE(DoBunnyScrew),
1561     SAVE_CODE(DoBunnyGrowUp),
1562 };
1563 
1564 static saveable_data saveable_bunny_data[] =
1565 {
1566     SAVE_DATA(BunnyBattle),
1567     SAVE_DATA(BunnyOffense),
1568     SAVE_DATA(BunnyBroadcast),
1569     SAVE_DATA(BunnySurprised),
1570     SAVE_DATA(BunnyEvasive),
1571     SAVE_DATA(BunnyLostTarget),
1572     SAVE_DATA(BunnyCloseRange),
1573     SAVE_DATA(BunnyWander),
1574 
1575     SAVE_DATA(WhiteBunnyPersonality),
1576     SAVE_DATA(BunnyPersonality),
1577 
1578     SAVE_DATA(WhiteBunnyAttrib),
1579     SAVE_DATA(BunnyAttrib),
1580 
1581     SAVE_DATA(s_BunnyRun),
1582     SAVE_DATA(sg_BunnyRun),
1583     SAVE_DATA(s_BunnyStand),
1584     SAVE_DATA(sg_BunnyStand),
1585     SAVE_DATA(s_BunnyScrew),
1586     SAVE_DATA(sg_BunnyScrew),
1587     SAVE_DATA(s_BunnySwipe),
1588     SAVE_DATA(sg_BunnySwipe),
1589     SAVE_DATA(s_BunnyHeart),
1590     SAVE_DATA(sg_BunnyHeart),
1591     SAVE_DATA(s_BunnyPain),
1592     SAVE_DATA(sg_BunnyPain),
1593     SAVE_DATA(s_BunnyJump),
1594     SAVE_DATA(sg_BunnyJump),
1595     SAVE_DATA(s_BunnyFall),
1596     SAVE_DATA(sg_BunnyFall),
1597     SAVE_DATA(s_BunnyJumpAttack),
1598     SAVE_DATA(sg_BunnyJumpAttack),
1599     SAVE_DATA(s_BunnyDie),
1600     SAVE_DATA(sg_BunnyDie),
1601     SAVE_DATA(s_BunnyDead),
1602     SAVE_DATA(sg_BunnyDead),
1603     SAVE_DATA(s_BunnyDeathJump),
1604     SAVE_DATA(sg_BunnyDeathJump),
1605     SAVE_DATA(s_BunnyDeathFall),
1606     SAVE_DATA(sg_BunnyDeathFall),
1607 
1608     SAVE_DATA(BunnyActionSet),
1609     SAVE_DATA(BunnyWhiteActionSet),
1610 };
1611 
1612 saveable_module saveable_bunny =
1613 {
1614     // code
1615     saveable_bunny_code,
1616     SIZ(saveable_bunny_code),
1617 
1618     // data
1619     saveable_bunny_data,
1620     SIZ(saveable_bunny_data)
1621 };
1622