source: abuse/tags/pd/abuse/src/cop.c @ 528

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