1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 /*
21 ==============================================================================
22
23 FLIPPER
24
25 ==============================================================================
26 */
27
28 #include "g_local.h"
29 #include "m_flipper.h"
30
31
32 static int sound_chomp;
33 static int sound_attack;
34 static int sound_pain1;
35 static int sound_pain2;
36 static int sound_death;
37 static int sound_idle;
38 static int sound_search;
39 static int sound_sight;
40
41
42 void flipper_stand (edict_t *self);
43
44 mframe_t flipper_frames_stand [] =
45 {
46 ai_stand, 0, NULL
47 };
48
49 mmove_t flipper_move_stand = {FRAME_flphor01, FRAME_flphor01, flipper_frames_stand, NULL};
50
flipper_stand(edict_t * self)51 void flipper_stand (edict_t *self)
52 {
53 self->monsterinfo.currentmove = &flipper_move_stand;
54 }
55
56 #define FLIPPER_RUN_SPEED 24
57
58 mframe_t flipper_frames_run [] =
59 {
60 ai_run, FLIPPER_RUN_SPEED, NULL, // 6
61 ai_run, FLIPPER_RUN_SPEED, NULL,
62 ai_run, FLIPPER_RUN_SPEED, NULL,
63 ai_run, FLIPPER_RUN_SPEED, NULL,
64 ai_run, FLIPPER_RUN_SPEED, NULL, // 10
65
66 ai_run, FLIPPER_RUN_SPEED, NULL,
67 ai_run, FLIPPER_RUN_SPEED, NULL,
68 ai_run, FLIPPER_RUN_SPEED, NULL,
69 ai_run, FLIPPER_RUN_SPEED, NULL,
70 ai_run, FLIPPER_RUN_SPEED, NULL,
71 ai_run, FLIPPER_RUN_SPEED, NULL,
72 ai_run, FLIPPER_RUN_SPEED, NULL,
73 ai_run, FLIPPER_RUN_SPEED, NULL,
74 ai_run, FLIPPER_RUN_SPEED, NULL,
75 ai_run, FLIPPER_RUN_SPEED, NULL, // 20
76
77 ai_run, FLIPPER_RUN_SPEED, NULL,
78 ai_run, FLIPPER_RUN_SPEED, NULL,
79 ai_run, FLIPPER_RUN_SPEED, NULL,
80 ai_run, FLIPPER_RUN_SPEED, NULL,
81 ai_run, FLIPPER_RUN_SPEED, NULL,
82 ai_run, FLIPPER_RUN_SPEED, NULL,
83 ai_run, FLIPPER_RUN_SPEED, NULL,
84 ai_run, FLIPPER_RUN_SPEED, NULL,
85 ai_run, FLIPPER_RUN_SPEED, NULL // 29
86 };
87 mmove_t flipper_move_run_loop = {FRAME_flpver06, FRAME_flpver29, flipper_frames_run, NULL};
88
flipper_run_loop(edict_t * self)89 void flipper_run_loop (edict_t *self)
90 {
91 self->monsterinfo.currentmove = &flipper_move_run_loop;
92 }
93
94 mframe_t flipper_frames_run_start [] =
95 {
96 ai_run, 8, NULL,
97 ai_run, 8, NULL,
98 ai_run, 8, NULL,
99 ai_run, 8, NULL,
100 ai_run, 8, NULL,
101 ai_run, 8, NULL
102 };
103 mmove_t flipper_move_run_start = {FRAME_flpver01, FRAME_flpver06, flipper_frames_run_start, flipper_run_loop};
104
flipper_run(edict_t * self)105 void flipper_run (edict_t *self)
106 {
107 self->monsterinfo.currentmove = &flipper_move_run_start;
108 }
109
110 /* Standard Swimming */
111 mframe_t flipper_frames_walk [] =
112 {
113 ai_walk, 4, NULL,
114 ai_walk, 4, NULL,
115 ai_walk, 4, NULL,
116 ai_walk, 4, NULL,
117 ai_walk, 4, NULL,
118 ai_walk, 4, NULL,
119 ai_walk, 4, NULL,
120 ai_walk, 4, NULL,
121 ai_walk, 4, NULL,
122 ai_walk, 4, NULL,
123 ai_walk, 4, NULL,
124 ai_walk, 4, NULL,
125 ai_walk, 4, NULL,
126 ai_walk, 4, NULL,
127 ai_walk, 4, NULL,
128 ai_walk, 4, NULL,
129 ai_walk, 4, NULL,
130 ai_walk, 4, NULL,
131 ai_walk, 4, NULL,
132 ai_walk, 4, NULL,
133 ai_walk, 4, NULL,
134 ai_walk, 4, NULL,
135 ai_walk, 4, NULL,
136 ai_walk, 4, NULL
137 };
138 mmove_t flipper_move_walk = {FRAME_flphor01, FRAME_flphor24, flipper_frames_walk, NULL};
139
flipper_walk(edict_t * self)140 void flipper_walk (edict_t *self)
141 {
142 self->monsterinfo.currentmove = &flipper_move_walk;
143 }
144
145 mframe_t flipper_frames_start_run [] =
146 {
147 ai_run, 8, NULL,
148 ai_run, 8, NULL,
149 ai_run, 8, NULL,
150 ai_run, 8, NULL,
151 ai_run, 8, flipper_run
152 };
153 mmove_t flipper_move_start_run = {FRAME_flphor01, FRAME_flphor05, flipper_frames_start_run, NULL};
154
flipper_start_run(edict_t * self)155 void flipper_start_run (edict_t *self)
156 {
157 self->monsterinfo.currentmove = &flipper_move_start_run;
158 }
159
160 mframe_t flipper_frames_pain2 [] =
161 {
162 ai_move, 0, NULL,
163 ai_move, 0, NULL,
164 ai_move, 0, NULL,
165 ai_move, 0, NULL,
166 ai_move, 0, NULL
167 };
168 mmove_t flipper_move_pain2 = {FRAME_flppn101, FRAME_flppn105, flipper_frames_pain2, flipper_run};
169
170 mframe_t flipper_frames_pain1 [] =
171 {
172 ai_move, 0, NULL,
173 ai_move, 0, NULL,
174 ai_move, 0, NULL,
175 ai_move, 0, NULL,
176 ai_move, 0, NULL
177 };
178 mmove_t flipper_move_pain1 = {FRAME_flppn201, FRAME_flppn205, flipper_frames_pain1, flipper_run};
179
flipper_bite(edict_t * self)180 void flipper_bite (edict_t *self)
181 {
182 vec3_t aim;
183
184 VectorSet (aim, MELEE_DISTANCE, 0, 0);
185 fire_hit (self, aim, 5, 0);
186 }
187
flipper_preattack(edict_t * self)188 void flipper_preattack (edict_t *self)
189 {
190 gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0);
191 }
192
193 mframe_t flipper_frames_attack [] =
194 {
195 ai_charge, 0, flipper_preattack,
196 ai_charge, 0, NULL,
197 ai_charge, 0, NULL,
198 ai_charge, 0, NULL,
199 ai_charge, 0, NULL,
200 ai_charge, 0, NULL,
201 ai_charge, 0, NULL,
202 ai_charge, 0, NULL,
203 ai_charge, 0, NULL,
204 ai_charge, 0, NULL,
205 ai_charge, 0, NULL,
206 ai_charge, 0, NULL,
207 ai_charge, 0, NULL,
208 ai_charge, 0, flipper_bite,
209 ai_charge, 0, NULL,
210 ai_charge, 0, NULL,
211 ai_charge, 0, NULL,
212 ai_charge, 0, NULL,
213 ai_charge, 0, flipper_bite,
214 ai_charge, 0, NULL
215 };
216 mmove_t flipper_move_attack = {FRAME_flpbit01, FRAME_flpbit20, flipper_frames_attack, flipper_run};
217
flipper_melee(edict_t * self)218 void flipper_melee(edict_t *self)
219 {
220 self->monsterinfo.currentmove = &flipper_move_attack;
221 }
222
flipper_pain(edict_t * self,edict_t * other,float kick,int damage)223 void flipper_pain (edict_t *self, edict_t *other, float kick, int damage)
224 {
225 int n;
226
227 if (self->health < (self->max_health / 2))
228 self->s.skinnum = 1;
229
230 if (level.time < self->pain_debounce_time)
231 return;
232
233 self->pain_debounce_time = level.time + 3;
234
235 if (skill->value == 3)
236 return; // no pain anims in nightmare
237
238 n = (rand() + 1) % 2;
239 if (n == 0)
240 {
241 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
242 self->monsterinfo.currentmove = &flipper_move_pain1;
243 }
244 else
245 {
246 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
247 self->monsterinfo.currentmove = &flipper_move_pain2;
248 }
249 }
250
flipper_dead(edict_t * self)251 void flipper_dead (edict_t *self)
252 {
253 VectorSet (self->mins, -16, -16, -24);
254 VectorSet (self->maxs, 16, 16, -8);
255 self->movetype = MOVETYPE_TOSS;
256 self->svflags |= SVF_DEADMONSTER;
257 self->nextthink = 0;
258 gi.linkentity (self);
259 }
260
261 mframe_t flipper_frames_death [] =
262 {
263 ai_move, 0, NULL,
264 ai_move, 0, NULL,
265 ai_move, 0, NULL,
266 ai_move, 0, NULL,
267 ai_move, 0, NULL,
268 ai_move, 0, NULL,
269 ai_move, 0, NULL,
270 ai_move, 0, NULL,
271 ai_move, 0, NULL,
272 ai_move, 0, NULL,
273
274 ai_move, 0, NULL,
275 ai_move, 0, NULL,
276 ai_move, 0, NULL,
277 ai_move, 0, NULL,
278 ai_move, 0, NULL,
279 ai_move, 0, NULL,
280 ai_move, 0, NULL,
281 ai_move, 0, NULL,
282 ai_move, 0, NULL,
283 ai_move, 0, NULL,
284
285 ai_move, 0, NULL,
286 ai_move, 0, NULL,
287 ai_move, 0, NULL,
288 ai_move, 0, NULL,
289 ai_move, 0, NULL,
290 ai_move, 0, NULL,
291 ai_move, 0, NULL,
292 ai_move, 0, NULL,
293 ai_move, 0, NULL,
294 ai_move, 0, NULL,
295
296 ai_move, 0, NULL,
297 ai_move, 0, NULL,
298 ai_move, 0, NULL,
299 ai_move, 0, NULL,
300 ai_move, 0, NULL,
301 ai_move, 0, NULL,
302 ai_move, 0, NULL,
303 ai_move, 0, NULL,
304 ai_move, 0, NULL,
305 ai_move, 0, NULL,
306
307 ai_move, 0, NULL,
308 ai_move, 0, NULL,
309 ai_move, 0, NULL,
310 ai_move, 0, NULL,
311 ai_move, 0, NULL,
312 ai_move, 0, NULL,
313 ai_move, 0, NULL,
314 ai_move, 0, NULL,
315 ai_move, 0, NULL,
316 ai_move, 0, NULL,
317
318 ai_move, 0, NULL,
319 ai_move, 0, NULL,
320 ai_move, 0, NULL,
321 ai_move, 0, NULL,
322 ai_move, 0, NULL,
323 ai_move, 0, NULL
324 };
325 mmove_t flipper_move_death = {FRAME_flpdth01, FRAME_flpdth56, flipper_frames_death, flipper_dead};
326
flipper_sight(edict_t * self,edict_t * other)327 void flipper_sight (edict_t *self, edict_t *other)
328 {
329 gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
330 }
331
flipper_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)332 void flipper_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
333 {
334 int n;
335
336 // check for gib
337 if (self->health <= self->gib_health)
338 {
339 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
340 for (n= 0; n < 2; n++)
341 ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
342 for (n= 0; n < 2; n++)
343 ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
344 ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
345 self->deadflag = DEAD_DEAD;
346 return;
347 }
348
349 if (self->deadflag == DEAD_DEAD)
350 return;
351
352 // regular death
353 gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
354 self->deadflag = DEAD_DEAD;
355 self->takedamage = DAMAGE_YES;
356 self->monsterinfo.currentmove = &flipper_move_death;
357 }
358
359 /*QUAKED monster_flipper (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
360 */
SP_monster_flipper(edict_t * self)361 void SP_monster_flipper (edict_t *self)
362 {
363 if (deathmatch->value)
364 {
365 G_FreeEdict (self);
366 return;
367 }
368
369 sound_pain1 = gi.soundindex ("flipper/flppain1.wav");
370 sound_pain2 = gi.soundindex ("flipper/flppain2.wav");
371 sound_death = gi.soundindex ("flipper/flpdeth1.wav");
372 sound_chomp = gi.soundindex ("flipper/flpatck1.wav");
373 sound_attack = gi.soundindex ("flipper/flpatck2.wav");
374 sound_idle = gi.soundindex ("flipper/flpidle1.wav");
375 sound_search = gi.soundindex ("flipper/flpsrch1.wav");
376 sound_sight = gi.soundindex ("flipper/flpsght1.wav");
377
378 self->movetype = MOVETYPE_STEP;
379 self->solid = SOLID_BBOX;
380 self->s.modelindex = gi.modelindex ("models/monsters/flipper/tris.md2");
381 VectorSet (self->mins, -16, -16, 0);
382 VectorSet (self->maxs, 16, 16, 32);
383
384 self->health = 50;
385 self->gib_health = -30;
386 self->mass = 100;
387
388 self->pain = flipper_pain;
389 self->die = flipper_die;
390
391 self->monsterinfo.stand = flipper_stand;
392 self->monsterinfo.walk = flipper_walk;
393 self->monsterinfo.run = flipper_start_run;
394 self->monsterinfo.melee = flipper_melee;
395 self->monsterinfo.sight = flipper_sight;
396
397 gi.linkentity (self);
398
399 self->monsterinfo.currentmove = &flipper_move_stand;
400 self->monsterinfo.scale = MODEL_SCALE;
401
402 swimmonster_start (self);
403 }
404