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