1 /***************************************************************************
2 ****************************************************************************
3 ****************************************************************************
4 * Nighthawk
5 * Copyright (C) 1996-2004 Jason Nunn et al
6 * Developed by Jason Nunn et al (see README for Acknowledgements)
7 *
8 * Project head and maintainer--
9 * Eric Gillespie (The Viking)
10 * Email: viking667@users.sourceforge.net
11 * http://night-hawk.sourceforge.net
12 *
13 * Original Author--
14 * Jason Nunn
15 * http://jsno.leal.com.au
16 *
17 * C/- Jason Nunn
18 * PO Box 15
19 * Birdwood SA 5234
20 * Australia
21 *
22 * This software is Open Source GPL. Please read COPYING notice.
23 * ==================================================================
24 * droid routines (for individual types) object routines
25 *
26 * 1xx Cleaning
27 * 2xx Logistic/Servant
28 * 3xx Messenger
29 * 4xx Maintenance
30 * 5xx Medical
31 * 6xx Sentinel
32 * 7xx Battle
33 * 8xx Navigational
34 * 9xx Command
35 *
36 ****************************************************************************
37 ****************************************************************************
38 ***************************************************************************/
39 #include "defs.h"
40 #include "protos.p"
41
42 #include "tdroid_1xx.h"
43 #include "tdroid_2xx.h"
44 #include "tdroid_3xx.h"
45 #include "tdroid_4xx.h"
46 #include "tdroid_5xx.h"
47 #include "tdroid_6xx.h"
48 #include "tdroid_7xx.h"
49 #include "tdroid_8xx.h"
50 #include "tdroid_9xx.h"
51
52 #define MASK ~0x3
53
54 /***************************************************************************
55 *
56 ***************************************************************************/
tdroid_108(void)57 tdroid_108::tdroid_108(void)
58 {
59 memcpy(&stats, &droid_stats[DROID_108], sizeof(tdroid_stats));
60 count = 0;
61 droid_cmd_list = NULL;
62 droid_cmd_list_ptr = NULL;
63 }
64
~tdroid_108(void)65 tdroid_108::~tdroid_108(void)
66 {
67 free_all_cmd(&droid_cmd_list);
68 }
69
append_cmd(tdroid_cmd_list ** ptr,int cmd,int d1,int d2)70 int tdroid_108::append_cmd(tdroid_cmd_list **ptr, int cmd, int d1, int d2)
71 {
72 int r = 0;
73
74 if(*ptr == NULL)
75 {
76 *ptr = (tdroid_cmd_list *)alloc_mem(sizeof(tdroid_cmd_list));
77 (*ptr)->cmd = cmd;
78 (*ptr)->d1 = d1;
79 (*ptr)->d2 = d2;
80 (*ptr)->next = NULL;
81 r = 1;
82 droid_cmd_list_ptr = droid_cmd_list;
83 }
84 else
85 r = append_cmd(&((*ptr)->next), cmd, d1, d2);
86
87 return r;
88 }
89
free_all_cmd(tdroid_cmd_list ** ptr)90 void tdroid_108::free_all_cmd(tdroid_cmd_list **ptr)
91 {
92 if(*ptr != NULL)
93 {
94 free_all_cmd(&((*ptr)->next));
95 free(*ptr);
96 *ptr = NULL;
97 }
98 }
99
set_dir_vect(float vx,float vy)100 void tdroid_108::set_dir_vect(float vx, float vy)
101 {
102 float d, s1, s2;
103
104 s1 = fabs(vx);
105 s2 = fabs(vy);
106 if(s1 < s2)
107 s1 = s2;
108
109 if(s1 > stats.speed)
110 s1 = stats.speed;
111 else
112 s1 /= 2;
113
114 if(vy != 0)
115 d = atan(vx / vy);
116 else
117 d = atan(vx);
118
119 pos_dx = sin(d) * s1;
120 pos_dy = cos(d) * s1;
121
122 if(vy < 0)
123 {
124 pos_dx *= -1;
125 pos_dy *= -1;
126 }
127 }
128
next_cmd(void)129 void tdroid_108::next_cmd(void)
130 {
131 if(droid_cmd_list_ptr->next == NULL)
132 droid_cmd_list_ptr = droid_cmd_list;
133 else
134 droid_cmd_list_ptr = droid_cmd_list_ptr->next;
135 count = 0;
136 }
137
bg_calc(void)138 void tdroid_108::bg_calc(void)
139 {
140 int ix, iy;
141
142 if(state == 0)
143 {
144 switch(droid_cmd_list_ptr->cmd)
145 {
146 case 'g':
147 ix = (int)rint(pos_x) & MASK;
148 iy = (int)rint(pos_y) & MASK;
149 if((ix == (droid_cmd_list_ptr->d1 & MASK)) &&
150 (iy == (droid_cmd_list_ptr->d2 & MASK)))
151 {
152 pos_dx = 0;
153 pos_dy = 0;
154 pos_x = droid_cmd_list_ptr->d1;
155 pos_y = droid_cmd_list_ptr->d2;
156 next_cmd();
157 }
158 else
159 set_dir_vect(
160 (float)droid_cmd_list_ptr->d1 - pos_x,
161 (float)droid_cmd_list_ptr->d2 - pos_y);
162 break;
163
164 case 'w':
165 friction();
166 if(count >= droid_cmd_list_ptr->d1)
167 next_cmd();
168 else
169 count++;
170 break;
171 }
172 }
173
174 tdroid::bg_calc();
175 }
176
177 /***************************************************************************
178 *
179 ***************************************************************************/
tdroid_176(void)180 tdroid_176::tdroid_176(void)
181 {
182 memcpy(&stats, &droid_stats[DROID_176], sizeof(tdroid_stats));
183 }
184
185 /***************************************************************************
186 *
187 ***************************************************************************/
tdroid_261(void)188 tdroid_261::tdroid_261(void)
189 {
190 memcpy(&stats, &droid_stats[DROID_261], sizeof(tdroid_stats));
191 }
192
tdroid_275(void)193 tdroid_275::tdroid_275(void)
194 {
195 memcpy(&stats, &droid_stats[DROID_275], sizeof(tdroid_stats));
196 }
197
198 /***************************************************************************
199 *
200 ***************************************************************************/
tdroid_355(void)201 tdroid_355::tdroid_355(void)
202 {
203 memcpy(&stats, &droid_stats[DROID_355], sizeof(tdroid_stats));
204 }
205
tdroid_368(void)206 tdroid_368::tdroid_368(void)
207 {
208 memcpy(&stats, &droid_stats[DROID_368], sizeof(tdroid_stats));
209 }
210
211 /***************************************************************************
212 *
213 ***************************************************************************/
tdroid_423(void)214 tdroid_423::tdroid_423(void)
215 {
216 memcpy(&stats, &droid_stats[DROID_423], sizeof(tdroid_stats));
217 }
218
tdroid_467(void)219 tdroid_467::tdroid_467(void)
220 {
221 memcpy(&stats, &droid_stats[DROID_467], sizeof(tdroid_stats));
222 }
223
tdroid_489(void)224 tdroid_489::tdroid_489(void)
225 {
226 memcpy(&stats, &droid_stats[DROID_489], sizeof(tdroid_stats));
227 }
228
229 /***************************************************************************
230 *
231 ***************************************************************************/
tdroid_513(void)232 tdroid_513::tdroid_513(void)
233 {
234 memcpy(&stats, &droid_stats[DROID_513], sizeof(tdroid_stats));
235 attack_droid = NULL;
236 }
237
attack(void)238 void tdroid_513::attack(void)
239 {
240 if((state == 0) && (attack_droid != NULL) && !captured)
241 {
242 if(attack_droid->state == 0)
243 create_laser(
244 (int)(attack_droid->pos_x - pos_x),
245 (int)(attack_droid->pos_y - pos_y));
246
247 attack_droid = NULL;
248 }
249 }
250
bg_calc(void)251 void tdroid_513::bg_calc(void)
252 {
253 tdroid_108::bg_calc();
254 attack();
255 }
256
257 /***************************************************************************
258 *
259 ***************************************************************************/
tdroid_520(void)260 tdroid_520::tdroid_520(void)
261 {
262 memcpy(&stats, &droid_stats[DROID_520], sizeof(tdroid_stats));
263 }
264
tdroid_599(void)265 tdroid_599::tdroid_599(void)
266 {
267 memcpy(&stats, &droid_stats[DROID_599], sizeof(tdroid_stats));
268 }
269
270 /***************************************************************************
271 *
272 ***************************************************************************/
tdroid_606(void)273 tdroid_606::tdroid_606(void)
274 {
275 memcpy(&stats, &droid_stats[DROID_606], sizeof(tdroid_stats));
276 attack_wait = 0.0;
277 // voice_c = 0;
278 // voice_type = FX_6XX_VOICE;
279 }
280
281
target_not_hidden(tentity * d)282 int tdroid_606::target_not_hidden(tentity *d)
283 {
284 float tmp, dx, dy, tx = pos_x, ty = pos_y;
285 int a, i;
286
287 dx = d->pos_x - pos_x;
288 dy = d->pos_y - pos_y;
289 i = (int)rint(fabs(dx));
290 tmp = fabs(dy);
291
292 if(i < tmp)
293 i = (int)rint(tmp);
294 if(i == 0)
295 return 0;
296
297 i <<= 3;
298 dx /= i;
299 dy /= i;
300
301 for(a = 0; a < i; a++)
302 {
303 tflr_bm *spr;
304 int sx, sy;
305
306 tx += dx;
307 ty += dy;
308 sx = (int)(rint(tx) / SPRITE_SIZE_X);
309 sy = (int)(rint(ty) / SPRITE_SIZE_Y);
310
311 if((sx >= 0) && (sx < floor_ptr->fmap_x_size) &&
312 (sy >= 0) && (sy < floor_ptr->fmap_y_size))
313 {
314 spr =
315 flr_bm + *(floor_ptr->fmap + (sy * floor_ptr->fmap_x_size) + sx);
316
317 if(spr->bound == 'y')
318 return 0;
319 }
320 else
321 return 1;
322 }
323
324 return 1;
325 }
326
attack(void)327 void tdroid_606::attack(void)
328 {
329 if((state == 0) && !captured)
330 {
331 if(attack_droid != NULL)
332 {
333 if(attack_droid->state == 0)
334 create_laser(
335 (int)(attack_droid->pos_x - pos_x),
336 (int)(attack_droid->pos_y - pos_y));
337
338 attack_droid = NULL;
339 }
340 else
341 if((floor_ptr == droids[0]->floor_ptr) && (!droids[0]->state))
342 if(attack_wait <= 0.0)
343 {
344 attack_wait = stats.attack_rate;
345 if(target_not_hidden(droids[0]))
346 {
347 create_laser(
348 (int)(droids[0]->pos_x - pos_x),
349 (int)(droids[0]->pos_y - pos_y));
350
351 // if(!voice_c)
352 // voice_c = 40;
353 }
354 }
355 else
356 attack_wait -= get_time_lapse();
357 }
358
359 // if(voice_c)
360 // {
361 // if(voice_c == 1)
362 // do_sound(voice_type,256);
363 // voice_c--;
364 // }
365 }
366
367 /***************************************************************************
368 *
369 ***************************************************************************/
tdroid_691(void)370 tdroid_691::tdroid_691(void)
371 {
372 memcpy(&stats, &droid_stats[DROID_691], sizeof(tdroid_stats));
373 }
374
tdroid_693(void)375 tdroid_693::tdroid_693(void)
376 {
377 memcpy(&stats, &droid_stats[DROID_693], sizeof(tdroid_stats));
378 }
379
380 /***************************************************************************
381 *
382 ***************************************************************************/
tdroid_719(void)383 tdroid_719::tdroid_719(void)
384 {
385 memcpy(&stats, &droid_stats[DROID_719], sizeof(tdroid_stats));
386 direction = 0;
387 do_nothing_count = 0;
388 // voice_type = FX_7XX_VOICE;
389 }
390
move(void)391 void tdroid_719::move(void)
392 {
393 float cpx, cpy;
394 tflr_bm *spr;
395
396 friction();
397 cpx = pos_x;
398 cpy = pos_y;
399
400 switch(direction)
401 {
402 case 1:
403 cpx += SPRITE_HSIZE_X;
404 break;
405
406 case 2:
407 cpx -= SPRITE_HSIZE_X;
408 break;
409
410 case 3:
411 cpy += SPRITE_HSIZE_Y;
412 break;
413
414 case 4:
415 cpy -= SPRITE_HSIZE_Y;
416 break;
417 }
418
419 spr =
420 flr_bm + *(floor_ptr->fmap +
421 ((int)(rint(cpy) / SPRITE_SIZE_Y) * floor_ptr->fmap_x_size) +
422 (int)(rint(cpx) / SPRITE_SIZE_X));
423
424 if(spr->bound == 'y')
425 direction = random() & 0x7;
426 else
427 {
428 switch(direction)
429 {
430 case 1:
431 pos_dx = stats.speed;
432 pos_dy = 0;
433 break;
434
435 case 2:
436 pos_dx = -stats.speed;
437 pos_dy = 0;
438 break;
439
440 case 3:
441 pos_dx = 0;
442 pos_dy = stats.speed;
443 break;
444
445 case 4:
446 pos_dx = 0;
447 pos_dy = -stats.speed;
448 break;
449
450 default:
451 pos_dx = 0;
452 pos_dy = 0;
453 break;
454 }
455 }
456
457 if((pos_dx == 0) && (pos_dy == 0))
458 {
459 if(!do_nothing_count)
460 {
461 do_nothing_count = 50;
462 direction = random() & 0x7;
463 }
464 else
465 do_nothing_count--;
466 }
467 }
468
bg_calc(void)469 void tdroid_719::bg_calc(void)
470 {
471 move();
472 tdroid::bg_calc();
473 attack();
474 }
475
476 /***************************************************************************
477 *
478 ***************************************************************************/
tdroid_720(void)479 tdroid_720::tdroid_720(void)
480 {
481 memcpy(&stats, &droid_stats[DROID_720], sizeof(tdroid_stats));
482 }
483
tdroid_766(void)484 tdroid_766::tdroid_766(void)
485 {
486 memcpy(&stats, &droid_stats[DROID_766], sizeof(tdroid_stats));
487 }
488
tdroid_799(void)489 tdroid_799::tdroid_799(void)
490 {
491 memcpy(&stats, &droid_stats[DROID_799], sizeof(tdroid_stats));
492 }
493
494 /***************************************************************************
495 *
496 ***************************************************************************/
tdroid_805(void)497 tdroid_805::tdroid_805(void)
498 {
499 memcpy(&stats, &droid_stats[DROID_805], sizeof(tdroid_stats));
500 evase = 0;
501 // voice_c = 80;
502 }
503
attack(void)504 void tdroid_805::attack(void)
505 {
506 if((state == 0) && (attack_droid != NULL))
507 {
508 if(attack_droid->state == 0)
509 {
510 if(attack_wait <= 0.0)
511 {
512 if(evase)
513 {
514 attack_wait = stats.attack_rate;
515
516 if(target_not_hidden(attack_droid))
517 create_laser(
518 (int)(attack_droid->pos_x - pos_x),
519 (int)(attack_droid->pos_y - pos_y));
520 }
521 else
522 {
523 evase = 1;
524 // do_sound(FX_DROID_EVASE,40);
525 }
526 }
527 else
528 {
529 attack_wait -= get_time_lapse();
530
531 // if(evase)
532 // if(!voice_c)
533 // {
534 // voice_c = 80;
535 // do_sound(FX_8XX_VOICE,40);
536 // }
537 // else
538 // voice_c--;
539 }
540 }
541 else
542 attack_droid = NULL;
543 }
544 }
545
546 /***************************************************************************
547 *
548 ***************************************************************************/
tdroid_810(void)549 tdroid_810::tdroid_810(void)
550 {
551 memcpy(&stats, &droid_stats[DROID_810], sizeof(tdroid_stats));
552 }
553
tdroid_820(void)554 tdroid_820::tdroid_820(void)
555 {
556 memcpy(&stats, &droid_stats[DROID_820], sizeof(tdroid_stats));
557 }
558
tdroid_899(void)559 tdroid_899::tdroid_899(void)
560 {
561 memcpy(&stats, &droid_stats[DROID_899], sizeof(tdroid_stats));
562 }
563
564 /***************************************************************************
565 *
566 ***************************************************************************/
tdroid_933(void)567 tdroid_933::tdroid_933(void)
568 {
569 memcpy(&stats, &droid_stats[DROID_933], sizeof(tdroid_stats));
570 }
571
tdroid_949(void)572 tdroid_949::tdroid_949(void)
573 {
574 memcpy(&stats, &droid_stats[DROID_949], sizeof(tdroid_stats));
575 }
576
tdroid_999(void)577 tdroid_999::tdroid_999(void)
578 {
579 memcpy(&stats, &droid_stats[DROID_999], sizeof(tdroid_stats));
580 }
581