source: abuse/tags/pd/macabuse/src/cop.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 31.9 KB
Line 
1#include "lisp.hpp"
2#include "lisp_gc.hpp"
3#include "compiled.hpp"
4#include "objects.hpp"
5#include "level.hpp"
6#include "game.hpp"
7#include "jrand.hpp"
8#include "clisp.hpp"
9#include "ant.hpp"
10#include "key_cfg.hpp"
11
12enum { point_angle, fire_delay1 };
13
14#define SHOTGUN  10
15#define GRENADE  2
16#define ROCKET   3
17#define PLASMA   4
18#define FIREBOMB 5
19#define DFRIS    6
20#define LSABER   7
21
22extern int registered;
23
24signed char small_fire_off[24*2]=  // x & y offset from character to end of gun.
25  { 17,20,     // 1
26    17,23,     // 2
27    17,28,     
28    15,33,     
29    11,39,     // 5
30    7,43,
31    -3,44,     // 7
32    -10,42,   
33    -16,39,
34    -20,34,
35    -20,28,
36    -20,25,
37    -19,20,
38    -19,16,
39    -16,14,
40    -14,11,
41    -11,9,
42    -7,8,
43    -3,8,
44    2,8,
45    6,9,
46    10,10,
47    14,13,
48    16,15 };
49
50signed char large_fire_off[24*2]=
51  { 18,25,
52    17,30,
53    15,34,
54    14,36,
55    10,39,
56    7,41,
57    4,42,
58    -3,41,
59    -8,39,
60    -11,37,
61    -14,33,
62    -16,30,
63    -18,25,
64    -17,21,
65    -14,17,
66    -11,15,
67    -7,13,
68    -4,12,
69    3,12,
70    9,12,
71    12,15,
72    14,16,
73    15,18,
74    16,21 };
75 
76
77enum { in_climbing_area,
78        disable_top_draw,
79        just_hit,
80        ship_pan_x,
81        special_power,
82        used_special_power,
83        last1_x, last1_y,
84        last2_x, last2_y,
85        has_saved_this_level,
86        r_ramp, g_ramp, b_ramp,
87        is_teleporting,
88       just_fired};
89
90
91enum { sgb_speed,
92       sgb_angle,
93       sgb_lastx,
94       sgb_lasty,
95       sgb_bright_color,
96       sgb_medium_color,
97       sgb_lifetime };
98
99enum { NO_POWER,
100       FAST_POWER,
101       FLY_POWER,
102       SNEAKY_POWER,
103       HEALTH_POWER } ;
104
105enum { top_point_angle,
106       top_fire_delay1,
107       top_just_fired };
108
109inline int angle_diff(int a1, int a2)
110{
111  if (a1<a2)
112  { if ((a2-a1)<180)
113      return a2-a1;
114    else return 360-a2+a1;
115  } else
116  {
117    if ((a1-a2)<180)
118      return a1-a2;
119    else return 360-a1+a2;
120  }
121  return 0;
122}
123
124extern char *symbol_str(char *name);
125
126void *top_ai()
127{
128  game_object *o=current_object;
129  if (o->total_objects())            // make sure we are linked to the main character
130  { 
131    game_object *q=o->get_object(0);
132
133    view *v=q->controller();
134    if (v)
135    {
136      if (!v->freeze_time)
137      {
138        o->direction=1;                 // always face right
139
140        if (q->direction<0)
141          q->x+=4;
142        int i;
143        signed char *fire_off=o->otype==S_DFRIS_TOP ? large_fire_off :
144                                        (o->otype==S_ROCKET_TOP ? large_fire_off :
145                                         (o->otype==S_BFG_TOP ? large_fire_off : small_fire_off));
146        signed char *f=fire_off,*fb;
147        int best_diff=200,best_num;
148        int iy=f[1],ix=f[6*2];
149       
150        int best_angle=lisp_atan2(q->y-iy-v->pointer_y,v->pointer_x-q->x-ix);
151        for (i=0;i<24;i++,f+=2)             // check all the angles to see which would best fit animation wise
152        {
153          int this_angle=lisp_atan2(f[1]-iy,f[0]-ix);
154          int this_diff=angle_diff(this_angle,best_angle);
155          if (this_diff<best_diff)
156          {
157            best_diff=this_diff;
158            best_num=i;
159            fb=f;
160          }
161        }
162
163
164        // if the pointer is too close to the player go with the angle shown, not the angle through the pointer
165        if (abs(q->y-fb[1]-v->pointer_y)<45 & abs(v->pointer_x-q->x+fb[0])<40)
166          o->lvars[point_angle]=lisp_atan2(fb[1]-iy,fb[0]-ix);
167        else
168          o->lvars[point_angle]=lisp_atan2(q->y-fb[1]-v->pointer_y,v->pointer_x-(q->x+fb[0]));
169       
170
171        if (q->direction<0)
172          q->x-=4;
173
174        o->x=q->x;
175        o->y=q->y+29-q->picture()->height();
176
177        rand_on+=o->lvars[point_angle];
178        o->current_frame=best_num;
179
180
181        if (o->lvars[fire_delay1])
182          o->lvars[fire_delay1]--;
183
184        o->otype=weapon_types[v->current_weapon];  // switch to correct top part   
185      }
186    }
187  }
188  return true_symbol;
189}
190
191
192int player_fire_weapon(game_object *o, int type, game_object *target, int angle, signed char *fire_off)
193{
194
195  if (!o->total_objects()) return 0;
196  game_object *other=o->get_object(0);
197  int ox=other->x,oy=other->y;
198  if (other->direction<0) other->x+=4;
199
200  int firex=other->x+fire_off[o->current_frame*2];
201  int firey=other->y-fire_off[o->current_frame*2+1];
202 
203
204 
205  // fire try to move up to gun level
206
207  long x2=o->x,y2=firey;
208//  current_level->foreground_intersect(other->x,other->y,x2,y2);      // find first location we can actuall "see"
209//  current_level->all_boundary_setback(o,other->x,other->y,x2,y2);       // to make we don't fire through walls
210  other->y=y2;
211
212  if (other->y==firey)             // now try to move out to end of gun if we were not blocked above
213  {
214    x2=firex;
215    current_level->foreground_intersect(other->x,other->y,x2,y2);      // find first location we can actuall "see"
216    current_level->all_boundary_setback(other,other->x,other->y,x2,y2);       // to make we don't fire through walls
217    o->x=x2;
218  }
219
220  void *list=NULL;
221  p_ref r1(list);
222  push_onto_list(new_lisp_pointer(target),list);
223  push_onto_list(new_lisp_number(angle),list);
224  push_onto_list(new_lisp_number(y2),list);
225  push_onto_list(new_lisp_number(x2),list);
226  push_onto_list(new_lisp_number(type),list);
227  push_onto_list(new_lisp_pointer(o->get_object(0)),list);
228  eval_function((lisp_symbol *)l_fire_object,list);
229  o->lvars[top_just_fired]=1;
230  other->lvars[just_fired]=1;
231  other->x=ox;
232  other->y=oy;
233
234  return 1;
235}
236
237
238
239void *laser_ufun(void *args)
240{
241  game_object *o=current_object;
242  p_ref r1(args);
243  void *signal=CAR(args);  args=CDR(args);
244  void *ret=NULL;
245
246  if (signal==l_FIRE)
247  {
248    if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
249    {
250      long value=lnumber_value(eval(CAR(args)));
251      if (value)                                   // do we have ammo ?
252      {
253        o->lvars[fire_delay1]=3;
254        if (player_fire_weapon(o,SHOTGUN,NULL,o->lvars[point_angle],small_fire_off))
255          ret=new_lisp_number(-1);
256        else ret=new_lisp_number(0);
257      } else
258      {
259        o->lvars[fire_delay1]=5;                  // no ammo, set large fire delay for next shot
260        player_fire_weapon(o,SHOTGUN,NULL,o->lvars[point_angle],small_fire_off);
261        ret=new_lisp_number(0);
262      }
263    } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
264  }
265  return ret;
266}
267
268
269static int ammo_type(int otype)
270{
271  if (otype==S_GRENADE_TOP)
272    return GRENADE;
273  else if (otype==S_FIREBOMB_TOP)
274    return FIREBOMB;
275  else if (otype==S_DFRIS_TOP)
276    return DFRIS;
277  else return SHOTGUN;
278}
279
280
281void *top_ufun(void *args)                       // generic top character ai GRENADE && FIREBOMB
282{
283  game_object *o=current_object;
284  p_ref r1(args);
285  void *signal=CAR(args);  args=CDR(args);
286  void *ret=NULL;
287
288  if (signal==l_FIRE)
289  {
290    if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
291    {
292      long value=lnumber_value(eval(CAR(args)));
293      if (value)                                   // do we have ammo ?
294      {
295        o->lvars[fire_delay1]=6;
296        if (player_fire_weapon(o,ammo_type(o->otype),NULL,o->lvars[point_angle],
297                               o->otype==DFRIS ? large_fire_off : small_fire_off ))       
298          ret=new_lisp_number(-1);
299        else ret=new_lisp_number(0);
300      } else ret=new_lisp_number(0);
301    } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
302  }
303  return ret;
304}
305
306static int climb_handler(game_object *, int xm, int ym, int but);
307
308void *plaser_ufun(void *args)
309{
310  game_object *o=current_object;
311  p_ref r1(args);
312  void *signal=CAR(args);  args=CDR(args);
313  void *ret=NULL;
314
315  if (signal==l_FIRE)
316  {
317    if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
318    {
319      long value=lnumber_value(eval(CAR(args)));
320      if (value)                                   // do we have ammo ?
321      {
322        o->lvars[fire_delay1]=2;
323        if (player_fire_weapon(o,PLASMA,NULL,o->lvars[point_angle],small_fire_off))       
324          ret=new_lisp_number(-1);
325        else ret=new_lisp_number(0);
326      } else ret=new_lisp_number(0);
327    } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
328  }
329  return ret;
330}
331
332void *lsaber_ufun(void *args)
333{
334  game_object *o=current_object;
335  p_ref r1(args);
336  void *signal=CAR(args);  args=CDR(args);
337  void *ret=NULL;
338
339  if (signal==l_FIRE)
340  {
341    if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
342    {
343      long value=lnumber_value(eval(CAR(args)));
344      if (value)                                   // do we have ammo ?
345      {
346        o->lvars[fire_delay1]=1;
347        if (player_fire_weapon(o,LSABER,NULL,o->lvars[point_angle]+(current_level->tick_counter()&7)-8,
348                               small_fire_off))
349          ret=new_lisp_number(-1);
350        else ret=new_lisp_number(0);
351      } else ret=new_lisp_number(0);
352    } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
353  }
354  return ret;
355}
356
357
358
359void *player_rocket_ufun(void *args)
360{
361  game_object *o=current_object;
362  p_ref r1(args);
363  void *signal=CAR(args);  args=CDR(args);
364  void *ret=NULL;
365  int xd,yd,cl=0xfffffff,d;
366  if (signal==l_FIRE)
367  {
368    if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
369    {
370      long value=lnumber_value(eval(CAR(args)));
371      if (value)                                   // do we have ammo ?
372      {
373        o->lvars[fire_delay1]=6;
374        game_object *target=NULL,*p,*bot=o->total_objects() ? o->get_object(0) : 0;
375        if (bad_guy_array)
376        {
377          game_object *other=current_object->total_objects() ? current_object->get_object(0) : 0;
378          for (p=current_level->first_active_object();p;p=p->next_active)
379          {
380            xd=abs(p->x-o->x);
381            yd=abs(p->y-o->y);
382            if (xd<160 && yd<130 && bad_guy_array[p->otype] && p!=other)
383            {
384              if (p->targetable() &&             
385                  !(p->otype==S_ROCKET && p->total_objects() && p->get_object(0)==bot))  // don't track onto own missles
386              {
387                d=xd*xd+yd*yd;
388                if (d<cl)
389                {
390                  cl=d;
391                  target=p;
392                }
393              }
394            }
395          }
396        }
397        if (player_fire_weapon(o,ROCKET,target,o->lvars[point_angle],large_fire_off))     
398          ret=new_lisp_number(-1);
399        else ret=new_lisp_number(0);
400
401      } else ret=new_lisp_number(0);
402    } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
403  }
404  return ret;
405}
406
407static int player_move(game_object *o, int xm, int ym, int but)
408{
409  if (!o->lvars[in_climbing_area])
410  {
411    if (o->state==S_climbing)
412    {
413      o->set_gravity(1);
414      o->set_state(run_jump_fall);
415    }
416    o->next_picture();
417    return o->mover(xm,ym,but);
418  } else return climb_handler(o,xm,ym,but);
419     
420}
421
422
423static void undo_special_power(game_object *o)
424{
425  switch (o->lvars[special_power])
426  {
427    case SNEAKY_POWER :
428    {
429      if (o->lvars[used_special_power]>0)
430        o->lvars[used_special_power]--;
431    } break;
432    case FAST_POWER :
433    {
434      o->lvars[used_special_power]=0;
435    } break;
436  }
437}
438
439static void do_special_power(game_object *o, int xm, int ym, int but, game_object *top)
440{
441  switch (o->lvars[special_power])
442  {
443    case FLY_POWER :
444    {
445      if (registered)
446      {
447        game_object *cloud=create(S_CLOUD,o->x+o->direction*-10,o->y+jrand()%5);
448        if (current_level)
449        current_level->add_object(cloud);
450        o->set_state(run_jump);
451        o->set_gravity(1);
452        o->set_yacel(0);
453        if (o->yvel()>0) o->set_yvel(o->yvel()/2);
454        if (ym<0)
455        o->set_yvel(o->yvel()-3);
456        else
457        o->set_yvel(o->yvel()-2);
458        the_game->play_sound(S_FLY_SND,32,o->x,o->y);
459      }
460    } break;
461    case FAST_POWER :
462    {
463      if ((current_level->tick_counter()%16)==0)
464      the_game->play_sound(S_SPEED_SND,100,o->x,o->y);
465
466      o->lvars[used_special_power]=1;
467      o->lvars[last1_x]=o->x;
468      o->lvars[last1_y]=o->y;
469      long oyvel=o->yvel();
470      int in=o->lvars[in_climbing_area];
471      int ok;
472
473
474      player_move(o,xm,ym,but);
475      if (ym<0 && !oyvel && o->yvel()<0)             // if they just jumped, make them go higher
476      o->set_yvel(o->yvel()+o->yvel()/3);
477      o->lvars[in_climbing_area]=in;
478
479      o->lvars[last2_x]=o->x;
480      o->lvars[last2_x]=o->y;
481    } break;
482    case SNEAKY_POWER :
483    {
484      if (registered)
485      {
486        if (o->lvars[used_special_power]<15)
487          o->lvars[used_special_power]++;
488      }
489    } break;
490  }
491}
492
493static int climb_off_handler(game_object *o)
494{
495  if (o->next_picture())
496    o->controller()->pan_y-=4;
497  else
498  {
499    o->y-=28;
500    o->controller()->pan_y+=28;
501    o->controller()->last_y-=28;
502    o->set_state(stopped);
503  }
504  return 0;
505}
506
507
508static int climb_on_handler(game_object *o)
509{
510  if (o->next_picture())
511    o->controller()->pan_y+=4;
512  else
513    o->set_state((character_state)S_climbing);
514  return 0;
515}
516
517static int climb_handler(game_object *o, int xm, int ym, int but)
518{
519  int yd=o->lvars[in_climbing_area];  // see how from the top we are
520  o->lvars[in_climbing_area]=0;          // set 0, ladders will set back to proper if still in area
521  if (o->state==S_climb_off)
522    climb_off_handler(o);
523  else if (o->state==S_climb_on)
524    climb_on_handler(o); 
525  else
526  {
527    if (o->state==S_climbing)
528    {
529      if (ym>0)                       // going down
530      {
531
532        if (o->current_frame==0) o->current_frame=9;
533          o->current_frame--;   
534
535/*      if (o->lvars[special_power]==FAST_POWER)
536        {
537          long xv=0,yv=4;
538          o->try_move(o->x,o->y,xv,yv,1);
539          if (yv==4)
540            o->y+=3;
541          else
542          {
543            o->set_gravity(1);
544            o->set_state(run_jump_fall);
545          }
546        }
547        else */ o->y+=3;
548       
549
550      } else if (ym<0)
551      {
552        if (yd<32)
553          o->set_state((character_state)S_climb_off);
554        else
555        {
556          if (!o->next_picture()) o->set_state((character_state)S_climbing);
557          o->y-=3;
558        }
559      }
560      if (xm)                     // trying to get off the ladder, check to see if that's ok
561      {
562        long x2=0,y2=-20;
563        o->try_move(o->x,o->y,x2,y2,3);
564        if (y2==-20)
565        {
566          o->set_gravity(1);
567          if (ym>=0)
568            o->set_state(run_jump_fall);
569          else
570          { o->set_state(run_jump);
571            o->set_yvel(get_ability(o->otype,jump_yvel));         
572          }
573        }
574      }
575    }  else if (ym>0 && yd<10)
576    {
577      o->y+=28;
578      o->controller()->pan_y-=28;
579      o->controller()->last_y+=28;
580      o->set_state((character_state)S_climb_on);
581    }
582    else if (o->yvel()>=0 && (ym>0 || (ym<0 && yd>8)))
583    {
584      o->set_state((character_state)S_climbing);
585      o->set_gravity(0);
586      o->set_xvel(0);
587      o->set_yvel(0);
588      o->set_xacel(0);
589      o->set_yacel(0);
590      return 0;
591    } else
592    {
593      o->next_picture();
594      return o->mover(xm,ym,but);
595    }
596  }
597  return 0;
598}
599
600
601void *cop_mover(int xm, int ym, int but)
602{
603
604  int ret=0;
605  game_object *o=current_object,*top;
606  if (o->controller() && o->controller()->freeze_time) 
607  {
608    o->controller()->freeze_time--;
609    if (but || o->controller()->key_down(JK_SPACE) || o->controller()->key_down(JK_ENTER))
610      o->controller()->freeze_time=0;
611  }
612  else
613  {
614    if (!o->total_objects())                  // if no top create one
615    {
616      top=create(S_MGUN_TOP,o->x,o->y,0,0);
617      current_level->add_object_after(top,o);   
618      o->add_object(top);
619      top->add_object(o);
620    } else top=o->get_object(0);
621
622    if (o->yvel()>10)
623    {
624      o->set_yacel(0);
625      o->set_yvel(o->yvel()-1);            // terminal velocity
626    }
627
628    if (o->aistate()==0)  // just started, wait for button
629    {
630      o->set_aistate(1);   
631    } else if (o->aistate()==1)         // normal play
632    {
633      if (o->hp()==0)
634      {
635        o->set_aistate(2);                // go to deing state
636        o->set_state(dead);     
637      }
638      else
639      {
640        if (o->hp()<40 && (current_level->tick_counter()%16)==0) // if low on health play heart beat   
641          the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
642        else if (o->hp()<15 && (current_level->tick_counter()%8)==0) // if low on health play heart beat
643          the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
644        else if (o->hp()<7 && (current_level->tick_counter()%4)==0) // if low on health play heart beat
645          the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
646
647        if (but&1)
648        do_special_power(o,xm,ym,but,top);
649        else
650        undo_special_power(o);
651        ret=player_move(o,xm,ym,but);
652        top->x=o->x;
653        top->y=o->y+29-top->picture()->height();
654       
655        if ((but&2) && !o->lvars[is_teleporting] && o->state!=S_climbing && o->state!=S_climb_off)
656        {
657          void *args=NULL;
658          p_ref r1(args);
659          view *v=o->controller();
660
661          push_onto_list(new_lisp_number(v->weapon_total(v->current_weapon)),args);
662          push_onto_list(l_FIRE,args);
663
664          current_object=top;
665          void *ret=eval_function((lisp_symbol *)figures[top->otype]->get_fun(OFUN_USER_FUN),args);       
666          current_object=o;
667          v->add_ammo(v->current_weapon,lnumber_value(ret));   
668        }
669      }
670    } else if (o->aistate()==3)
671    {
672      if (!o->controller() || o->controller()->key_down(JK_SPACE))
673      {
674         int old_kills=o->controller()->kills;   // this i s bit of a hack, save the kills
675        eval_function((lisp_symbol *)l_restart_player,NULL);  // call teh user function to reset the player
676        o->controller()->reset_player();
677        if (player_list->next)
678          o->controller()->kills=old_kills;  // if a multiplayer game restore their kills
679        o->set_aistate(0);     
680      } else if (o->controller() && o->controller()->local_player())
681        the_game->show_help(symbol_str("space_cont"));
682
683    } else o->set_aistate(o->aistate()+1);
684  }
685
686  return new_lisp_number(ret);
687}
688
689
690
691void *ladder_ai()
692{
693  view *f=player_list;
694  game_object *o=current_object;
695  if (o->total_objects())
696  {
697    game_object *other=o->get_object(0);
698    for (;f;f=f->next)
699    {
700      int mex=f->focus->x;
701      int mey=f->focus->y;
702     
703      if (o->x<=mex && o->y<=mey && other->x>=mex && other->y>=mey)
704      {
705        if (f->focus->state==S_climbing)
706          f->focus->x=(o->x+other->x)/2;
707        f->focus->lvars[in_climbing_area]=mey-o->y;     
708      }
709    }
710  }
711  return true_symbol;
712}
713
714
715
716void *player_draw(int just_fired_var, int num)
717{
718  game_object *o=current_object;
719  if (num==0)
720  {
721    if (o->lvars[just_fired_var])
722    {
723      o->draw_tint(S_bright_tint);
724      o->lvars[just_fired_var]=0;
725    } else
726      o->drawer();
727  }
728  else
729  {
730    if (o->lvars[just_fired_var])
731    {
732      o->draw_double_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)),S_bright_tint);
733      o->lvars[just_fired_var]=0;
734    } else
735      o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)));
736  }
737  return NULL;
738}
739
740
741void *top_draw()
742{
743  game_object *o=current_object;
744  if (o->total_objects())
745  {
746    game_object *bot=o->get_object(0);
747    if (bot->state==stopped  || bot->state==running ||
748        bot->state==run_jump || bot->state==run_jump_fall ||
749        bot->state==end_run_jump)
750    {
751      int oldy=o->y;
752      o->x=bot->x;
753      if (bot->direction<0)
754        o->x+=4;
755      o->y=bot->y+29-bot->picture()->height();
756
757      void *ret=NULL;
758      p_ref r1(ret);
759
760      push_onto_list(new_lisp_number(bot->controller()->player_number),ret);
761
762      if (bot->lvars[special_power]==SNEAKY_POWER)
763      {
764        if (bot->lvars[used_special_power]==0)
765          player_draw(top_just_fired,bot->controller()->player_number);
766        else if (bot->lvars[used_special_power]<15)
767          o->draw_trans(bot->lvars[used_special_power],16);
768        else
769          o->draw_predator();
770      } else
771        eval_function((lisp_symbol *)l_player_draw,ret);
772     
773      o->y=oldy;
774      if (bot->direction<0)
775        o->x-=4;
776    }
777  }
778  return NULL;
779}
780
781
782
783void *bottom_draw()
784{
785  game_object *o=current_object;
786
787  if (o->lvars[r_ramp] || o->lvars[g_ramp] || o->lvars[b_ramp])
788  {
789    int r=o->lvars[r_ramp];
790    if (r>7) r-=7;
791    else r=0;
792    o->lvars[r_ramp]=r;
793
794    int g=o->lvars[g_ramp];
795    if (g>7) g-=7;
796    else g=0;
797    o->lvars[g_ramp]=g;
798
799    int b=o->lvars[b_ramp];
800    if (b>7) b-=7;
801    else b=0;
802    o->lvars[b_ramp]=b;
803
804    palette *p=pal->copy();
805    uchar *addr=(uchar *)p->addr();
806    int ra,ga,ba;
807   
808    for (int i=0;i<256;i++)
809    {
810      ra=(int)*addr+r; if (ra>255) ra=255; else if (ra<0) r=0; *addr=(uchar)ra; addr++;
811      ga=(int)*addr+g; if (ga>255) ga=255; else if (ga<0) g=0; *addr=(uchar)ga; addr++;
812      ba=(int)*addr+b; if (ba>255) ba=255; else if (ba<0) b=0; *addr=(uchar)ba; addr++;
813    }
814    p->load();
815    delete p;
816  }
817
818  if (o->aistate()>0)
819  {
820    switch (o->lvars[special_power])
821    {
822      case NO_POWER :
823      { player_draw(just_fired,o->controller()->player_number); } break;
824
825      case HEALTH_POWER :
826      {
827        player_draw(just_fired,o->controller()->player_number);
828        if (o->controller() && o->controller()->local_player())
829          cash.img(S_health_image)->put_image(screen,o->controller()->cx2-20,
830                                            o->controller()->cy1+5,1);
831      } break;
832      case FAST_POWER :
833      {
834        eval_function((lisp_symbol *)l_draw_fast,NULL);
835        int old_state=o->state;
836        switch (o->state)
837        {
838          case stopped : o->state=(character_state)S_fast_stopped; break;
839          case running : o->state=(character_state)S_fast_running; break;
840          case start_run_jump : o->state=(character_state)S_fast_start_run_jump; break;
841          case run_jump : o->state=(character_state)S_fast_run_jump; break;
842          case run_jump_fall : o->state=(character_state)S_fast_run_jump_fall; break;
843          case end_run_jump : o->state=(character_state)S_fast_end_run_jump; break;
844        }
845
846        player_draw(just_fired,o->controller()->player_number);
847        o->state=(character_state)old_state;
848        if (o->controller() && o->controller()->local_player())
849          cash.img(S_fast_image)->put_image(screen,o->controller()->cx2-20,
850                                            o->controller()->cy1+5,1);
851      } break;
852      case FLY_POWER :
853      {
854        int old_state=o->state;
855        switch (o->state)
856        {
857          case stopped : o->state=(character_state)S_fly_stopped; break;
858          case running : o->state=(character_state)S_fly_running; break;
859          case start_run_jump : o->state=(character_state)S_fly_start_run_jump; break;
860          case run_jump : o->state=(character_state)S_fly_run_jump; break;
861          case run_jump_fall : o->state=(character_state)S_fly_run_jump_fall; break;
862          case end_run_jump : o->state=(character_state)S_fly_end_run_jump; break;
863        }
864
865        player_draw(just_fired,o->controller()->player_number);
866        o->state=(character_state)old_state;
867
868        if (o->controller() && o->controller()->local_player())
869          cash.img(S_fly_image)->put_image(screen,o->controller()->cx2-20,
870                                            o->controller()->cy1+5,1);
871      } break;
872      case SNEAKY_POWER :
873      {
874        if (o->lvars[used_special_power]==0)
875          player_draw(just_fired,o->controller()->player_number);
876        else if (o->lvars[used_special_power]<15)
877          o->draw_trans(o->lvars[used_special_power],16);
878        else
879          o->draw_predator();
880         
881        if (o->controller() && o->controller()->local_player())
882          cash.img(S_sneaky_image)->put_image(screen,o->controller()->cx2-20,
883                                            o->controller()->cy1+5,1);
884      } break;
885    }   
886  }
887  return NULL;
888}
889
890
891
892void *sgun_ai()
893{
894  game_object *o=current_object;
895
896  if (o->lvars[sgb_lifetime]==0)
897    return NULL;
898  o->lvars[sgb_lifetime]--;
899
900  o->lvars[sgb_lastx]=o->x;
901  o->lvars[sgb_lasty]=o->y;
902  o->lvars[sgb_speed]=o->lvars[sgb_speed]*6/5;
903 
904  long ang=o->lvars[sgb_angle];
905  long mag=o->lvars[sgb_speed];
906
907  long xvel=(lisp_cos(ang))*(mag);
908  current_object->set_xvel(xvel>>16);
909  current_object->set_fxvel((xvel&0xffff)>>8);
910  long yvel=-(lisp_sin(ang))*(mag);
911  current_object->set_yvel(yvel>>16);
912  current_object->set_fyvel((yvel&0xffff)>>8);     
913
914
915  int whit=0;
916  game_object *who=o->bmove(whit, o->total_objects() ? o->get_object(0) : 0);
917
918  if (whit || (who && figures[who->otype]->get_cflag(CFLAG_UNACTIVE_SHIELD) && who->total_objects() &&
919               who->get_object(0)->aistate()==0))
920  {
921    o->lvars[sgb_lifetime]=0;
922    game_object *n=create(S_EXPLODE5,o->x+jrand()%4,o->y+jrand()%4);
923    current_level->add_object(n);   
924  } else if (who && figures[who->otype]->get_cflag(CFLAG_HURTABLE))
925  {
926    o->lvars[sgb_lifetime]=0;
927    game_object *n=create(S_EXPLODE3,o->x+jrand()%4,o->y+jrand()%4);
928    current_level->add_object(n);       
929     who->do_damage(5,o,o->x,o->y,(lisp_cos(ang)*10)>>16,(lisp_sin(ang)*10)>>16);
930  }
931  return true_symbol;
932}
933
934
935
936void *mover_ai()
937{
938  game_object *o=current_object;
939  if (o->total_objects()==2)
940  {
941    if (o->aistate()<2)
942    {
943      game_object *obj=o->get_object(1);
944      o->remove_object(obj);
945      game_object *d=o->get_object(0);
946      d->add_object(obj);
947      d->set_aistate(d->aitype());
948    } else
949    {
950      o->set_aistate(o->aistate()-1);
951      game_object *d=o->get_object(0);
952      game_object *obj=o->get_object(1);     
953
954      obj->x=d->x-(d->x-o->x)*o->aistate()/o->aitype();
955      obj->y=d->y-(d->y-o->y)*o->aistate()/o->aitype();
956    }
957  }
958  return true_symbol;
959}       
960
961
962void *respawn_ai()
963{
964 game_object *o=current_object;
965 int x=o->total_objects();
966 if (x)
967 {
968   game_object *last=o->get_object(x-1);
969   if (last->x==o->x && last->y==o->y)
970   {
971     if (last->fade_count())
972       last->set_fade_count(last->fade_count()-1);
973     o->set_aistate_time(0);
974   } else if (o->aistate_time()>o->xvel())
975   {
976     int type=o->get_object(jrandom(x))->otype;
977     game_object *n=create(type,o->x,o->y);
978     current_level->add_object(n);
979     o->add_object(n);
980     n->set_fade_count(15);
981     o->set_aistate_time(0);
982   }
983 }
984 return true_symbol;
985}
986
987static int compare_players(const void *a, const void *b)
988{
989  if  ( ((view **)a)[0]->kills > ((view **)b)[0]->kills)
990    return -1;
991  else if  ( ((view **)a)[0]->kills < ((view **)b)[0]->kills)
992    return 1;
993  else if (((view **)a)[0]->player_number > ((view **)b)[0]->player_number)
994    return -1;
995  else if (((view **)a)[0]->player_number < ((view **)b)[0]->player_number)
996    return 1;
997  else return 0; 
998}
999
1000void *score_draw()
1001{
1002  view *sorted_players[16],*local=NULL;
1003  int tp=0;
1004  view *f=player_list;
1005  for (;f;f=f->next)
1006  {
1007    sorted_players[tp]=f;
1008    tp++;
1009    if (f->local_player()) local=f;
1010  }
1011
1012  JCFont *fnt=eh->frame_font();
1013  if (local)
1014  {
1015    qsort(sorted_players,tp,sizeof(view *),compare_players);
1016
1017    int x=local->cx1;
1018    int y=local->cy1;
1019    char msg[100];
1020
1021    int i;
1022    for (i=0;i<tp;i++)
1023    {
1024      int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),sorted_players[i]->player_number)); 
1025      sprintf(msg,"%3d %s",sorted_players[i]->kills,sorted_players[i]->name);
1026      if (sorted_players[i]==local)
1027        strcat(msg," <<");
1028
1029      fnt->put_string(screen,x,y,msg,color);
1030      y+=fnt->height();
1031    }
1032  }
1033  return NULL;
1034}
1035
1036
1037extern void fade_in(image *im, int steps);
1038extern void fade_out(int steps);
1039
1040void *show_kills()
1041{
1042  fade_out(8);
1043  eh->set_mouse_position(0,0);
1044  screen->clear();
1045
1046  switch_mode(VMODE_640x480);
1047
1048  int xp,yp;
1049  load_image_into_screen("art/frame.spe","end_level_screen",xp,yp);
1050
1051  int x1=xp+342,y1=yp,x2=xp+639,y2=yp+294;
1052
1053  JCFont *fnt=eh->font();
1054  fade_in(NULL,16);
1055 
1056  view *v=player_list; int tp=0,i;
1057  for (v=player_list;v;v=v->next) tp++;
1058
1059  int y=(y1+y2)/2-(tp+2)*fnt->height()/2,x=x1+10;
1060  char *header_str=symbol_str("score_header");
1061  fnt->put_string(screen,x,y,header_str,eh->bright_color());
1062  y+=fnt->height();
1063
1064  screen->wiget_bar(x,y+2,x+strlen(header_str)*fnt->width(),y+fnt->height()-3,
1065                     eh->bright_color(),eh->medium_color(),eh->dark_color());
1066  y+=fnt->height();
1067  v=player_list;
1068  for (i=0;i<tp;i++)
1069  {
1070    enum { NAME_LEN=18 } ;
1071    int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),v->player_number)); 
1072    char max_name[NAME_LEN];
1073    strncpy(max_name,v->name,NAME_LEN-1);
1074    max_name[NAME_LEN-1]=0;
1075    char msg[100];
1076
1077
1078    sprintf(msg,"%-17s %3d  %3d",max_name,v->kills,v->tkills+v->kills);
1079    fnt->put_string(screen,x,y,msg,color);
1080
1081    y+=fnt->height();
1082    v=v->next;
1083  }
1084 
1085  eh->flush_screen();
1086  milli_wait(4000);   // wait 4 seconds
1087
1088  return NULL;
1089}
1090
1091
1092
1093static void give_weapons(game_object *player, ushort otype)
1094{
1095  view *v=player->controller();
1096  if (!v)
1097  {
1098    lbreak("object has no controller");
1099    exit(0);
1100  }
1101
1102  int w_type=-1;
1103
1104  if (otype==lnumber_value(symbol_value(l_MBULLET_ICON5)) || otype==lnumber_value(symbol_value(l_MBULLET_ICON20)))
1105    w_type=0;
1106
1107  else if (otype==lnumber_value(symbol_value(l_GRENADE_ICON2)) || otype==lnumber_value(symbol_value(l_GRENADE_ICON10)))
1108    w_type=1;
1109
1110  else if (otype==lnumber_value(symbol_value(l_ROCKET_ICON2)) || otype==lnumber_value(symbol_value(l_ROCKET_ICON5)))
1111    w_type=2;
1112
1113  else if (otype==lnumber_value(symbol_value(l_FBOMB_ICON1)) || otype==lnumber_value(symbol_value(l_FBOMB_ICON5)))
1114    w_type=3;
1115
1116  else if (otype==lnumber_value(symbol_value(l_PLASMA_ICON20)) || otype==lnumber_value(symbol_value(l_PLASMA_ICON50)))
1117    w_type=4;
1118
1119  else if (otype==lnumber_value(symbol_value(l_LSABER_ICON50)) || otype==lnumber_value(symbol_value(l_LSABER_ICON100)))
1120    w_type=5;
1121
1122  else if (otype==lnumber_value(symbol_value(l_DFRIS_ICON4)) || otype==lnumber_value(symbol_value(l_DFRIS_ICON10)))
1123    w_type=6;
1124
1125
1126  if (w_type!=-1)
1127  {   
1128    if (!v->has_weapon(w_type))
1129    {
1130      v->give_weapon(w_type);
1131      if (symbol_value(l_change_on_pickup))
1132        v->current_weapon=w_type;
1133    }
1134
1135
1136
1137    v->add_ammo(w_type,get_ability(otype,start_hp));
1138  }
1139}
1140
1141void *weapon_icon_ai()
1142{
1143  game_object *o=current_object;
1144  int try_fall=0;
1145
1146
1147  if (o->aistate()==0) // state 0 means we are stationary
1148  {
1149    if (o->total_objects()==0)
1150    {
1151      if ((jrand()%4)==0)  // check to see if we should fall approx ever 4 ticks
1152        try_fall=1;
1153    } else if (o->get_object(0)->aistate()==1)  // see if the object we are attached to is on
1154      try_fall=1;
1155  } else if (o->aistate()==1) // state 1 means we are currently falling
1156    try_fall=1;
1157
1158
1159  if (try_fall)
1160  {
1161    long x2=0,y2=10;
1162    game_object *who=o->try_move(o->x,o->y,x2,y2,3);                // see if we can fall
1163   
1164
1165    if (y2==0)
1166    {
1167      if (who)
1168        o->set_aistate(0);     // we are on top of another object and we need to continue checking for falling
1169      else o->set_aistate(2);  // we are on the ground, don't check for flaling anymore
1170    } else
1171    {
1172      o->y+=y2;
1173      o->set_aistate(1);  // we are in flight, continue falling       
1174    }
1175  }
1176
1177 
1178  long x1,y1,x2,y2,xp1,yp1,xp2,yp2;
1179
1180  game_object *player=current_level->attacker(current_object);
1181  player->picture_space(x1,y1,x2,y2);
1182  current_object->picture_space(xp1,yp1,xp2,yp2);
1183  if (!(xp1>x2 || xp2<x1 || yp1>y2 || yp2<y1))
1184  {
1185    the_game->play_sound(lnumber_value(symbol_value(l_ammo_snd)),127,o->x,o->y);
1186    give_weapons(player,o->otype);
1187    return NULL;
1188  }
1189 
1190  return true_symbol;
1191}
1192
1193
1194
1195void *on_draw()
1196{
1197  game_object *o=current_object;
1198  if (o->total_objects()==0 || o->get_object(0)->aistate() || (dev&EDIT_MODE))
1199    o->drawer(); 
1200  return 0;
1201}
1202
1203void *tp2_ai()
1204{
1205  enum { tp_waiting, tp_fading };
1206
1207
1208  game_object *o=current_object;
1209  if (o->total_objects())
1210  {
1211    if (o->aistate()==0)  // wait for player to activate us
1212    {
1213      game_object *p=current_level->attacker(o);
1214
1215      if (p->x>o->x-15 && p->x<o->x+15 && p->y>o->y-30 && p->y<o->y && p->controller()->y_suggestion>0)
1216      {
1217        o->add_object(p);
1218        o->set_aistate(tp_fading);
1219        the_game->play_sound(lnumber_value(symbol_value(l_TELEPORTER_SND)),127,o->x,o->y);
1220        o->set_state(running);
1221      }
1222    } else
1223    {
1224      game_object *p=o->get_object(1);
1225      if (o->next_picture())
1226      {
1227        p->x=o->x;
1228        p->y=o->y-16;
1229        int f=o->current_frame<16 ? o->current_frame : 15;
1230
1231        p->set_fade_count(f);
1232        p->get_object(0)->set_fade_count(f);
1233        p->lvars[is_teleporting]=1;     
1234      } else
1235      {
1236        p->x=o->get_object(0)->x;
1237        p->y=o->get_object(0)->y-16;
1238        p->lvars[is_teleporting]=0;
1239        p->set_fade_count(0);
1240        p->get_object(0)->set_fade_count(0);
1241        o->remove_object(p);
1242        o->set_aistate(tp_waiting);
1243      }
1244    }
1245  }
1246  return true_symbol;
1247}
1248
1249
1250
1251void *push_char(void *args)
1252{
1253  long xa=lnumber_value(CAR(args));
1254  long ya=lnumber_value(CAR(args));
1255
1256  game_object *o=current_object;
1257  game_object *p=current_level->attacker(o);
1258 
1259  if (p->y<=o->y && abs(p->y-o->y)<ya && abs(p->x-o->x)<xa)
1260  {
1261    long amount;
1262    if (p->x>o->x)
1263      amount=xa-(p->x-o->x);
1264    else amount=(o->x-p->x)-xa;
1265    long yv=0;
1266    p->try_move(p->x,p->y,amount,yv,3);
1267    p->x+=amount;
1268  }
1269        return 0;
1270}
1271
1272void *gun_draw()
1273{
1274  game_object *o=current_object;
1275  o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_gun_tints),o->aitype())));
1276  return 0;
1277}
1278 
1279
1280void *ant_draw()
1281{
1282  game_object *o=current_object;
1283  if (o->aitype()==0)
1284    o->drawer();
1285  else
1286    o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_ant_tints),o->aitype())));
1287  return 0;
1288}
1289
1290void *middle_draw()
1291{
1292  game_object *o=current_object;
1293  int y=o->y;
1294  o->y+=o->picture()->height()/2;
1295  o->drawer();
1296  o->y=y;
1297  return 0;
1298}
1299
1300void *exp_draw()
1301{
1302  game_object *o=current_object;
1303  if (o->aitype()==0)
1304    middle_draw();
1305  return 0;
1306}
1307
1308void *exp_ai()
1309{
1310  game_object *o=current_object;
1311  if (o->aitype()==0)
1312  {
1313    if (o->next_picture())
1314      return true_symbol;
1315    else return 0;
1316  }       
1317  else
1318  {
1319    o->set_aitype(o->aitype()-1);
1320    return true_symbol;
1321  }
1322}
Note: See TracBrowser for help on using the repository browser.