source: abuse/trunk/src/cop.cpp @ 2

Last change on this file since 2 was 2, checked in by Sam Hocevar, 14 years ago
  • imported original 0.7.0 tarball
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
471      player_move(o,xm,ym,but);
472      if (ym<0 && !oyvel && o->yvel()<0)             // if they just jumped, make them go higher
473      o->set_yvel(o->yvel()+o->yvel()/3);
474      o->lvars[in_climbing_area]=in;
475
476      o->lvars[last2_x]=o->x;
477      o->lvars[last2_x]=o->y;
478    } break;
479    case SNEAKY_POWER :
480    {
481      if (registered)
482      {
483        if (o->lvars[used_special_power]<15)
484          o->lvars[used_special_power]++;
485      }
486    } break;
487  }
488}
489
490static int climb_off_handler(game_object *o)
491{
492  if (o->next_picture())
493    o->controller()->pan_y-=4;
494  else
495  {
496    o->y-=28;
497    o->controller()->pan_y+=28;
498    o->controller()->last_y-=28;
499    o->set_state(stopped);
500  }
501  return 0;
502}
503
504
505static int climb_on_handler(game_object *o)
506{
507  if (o->next_picture())
508    o->controller()->pan_y+=4;
509  else
510    o->set_state((character_state)S_climbing);
511  return 0;
512}
513
514static int climb_handler(game_object *o, int xm, int ym, int but)
515{
516  int yd=o->lvars[in_climbing_area];  // see how from the top we are
517  o->lvars[in_climbing_area]=0;          // set 0, ladders will set back to proper if still in area
518  if (o->state==S_climb_off)
519    climb_off_handler(o);
520  else if (o->state==S_climb_on)
521    climb_on_handler(o); 
522  else
523  {
524    if (o->state==S_climbing)
525    {
526      if (ym>0)                       // going down
527      {
528
529        if (o->current_frame==0) o->current_frame=9;
530          o->current_frame--;   
531
532/*      if (o->lvars[special_power]==FAST_POWER)
533        {
534          long xv=0,yv=4;
535          o->try_move(o->x,o->y,xv,yv,1);
536          if (yv==4)
537            o->y+=3;
538          else
539          {
540            o->set_gravity(1);
541            o->set_state(run_jump_fall);
542          }
543        }
544        else */ o->y+=3;
545       
546
547      } else if (ym<0)
548      {
549        if (yd<32)
550          o->set_state((character_state)S_climb_off);
551        else
552        {
553          if (!o->next_picture()) o->set_state((character_state)S_climbing);
554          o->y-=3;
555        }
556      }
557      if (xm)                     // trying to get off the ladder, check to see if that's ok
558      {
559        long x2=0,y2=-20;
560        o->try_move(o->x,o->y,x2,y2,3);
561        if (y2==-20)
562        {
563          o->set_gravity(1);
564          if (ym>=0)
565            o->set_state(run_jump_fall);
566          else
567          { o->set_state(run_jump);
568            o->set_yvel(get_ability(o->otype,jump_yvel));         
569          }
570        }
571      }
572    }  else if (ym>0 && yd<10)
573    {
574      o->y+=28;
575      o->controller()->pan_y-=28;
576      o->controller()->last_y+=28;
577      o->set_state((character_state)S_climb_on);
578    }
579    else if (o->yvel()>=0 && (ym>0 || (ym<0 && yd>8)))
580    {
581      o->set_state((character_state)S_climbing);
582      o->set_gravity(0);
583      o->set_xvel(0);
584      o->set_yvel(0);
585      o->set_xacel(0);
586      o->set_yacel(0);
587      return 0;
588    } else
589    {
590      o->next_picture();
591      return o->mover(xm,ym,but);
592    }
593  }
594  return 0;
595}
596
597
598void *cop_mover(int xm, int ym, int but)
599{
600
601  int ret=0;
602  game_object *o=current_object,*top;
603  if (o->controller() && o->controller()->freeze_time) 
604  {
605    o->controller()->freeze_time--;
606    if (but || o->controller()->key_down(JK_SPACE) || o->controller()->key_down(JK_ENTER))
607      o->controller()->freeze_time=0;
608  }
609  else
610  {
611    if (!o->total_objects())                  // if no top create one
612    {
613      top=create(S_MGUN_TOP,o->x,o->y,0,0);
614      current_level->add_object_after(top,o);   
615      o->add_object(top);
616      top->add_object(o);
617    } else top=o->get_object(0);
618
619    if (o->yvel()>10)
620    {
621      o->set_yacel(0);
622      o->set_yvel(o->yvel()-1);            // terminal velocity
623    }
624
625    if (o->aistate()==0)  // just started, wait for button
626    {
627      o->set_aistate(1);   
628    } else if (o->aistate()==1)         // normal play
629    {
630      if (o->hp()==0)
631      {
632        o->set_aistate(2);                // go to deing state
633        o->set_state(dead);     
634      }
635      else
636      {
637        if (o->hp()<40 && (current_level->tick_counter()%16)==0) // if low on health play heart beat   
638          the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
639        else if (o->hp()<15 && (current_level->tick_counter()%8)==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()<7 && (current_level->tick_counter()%4)==0) // if low on health play heart beat
642          the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
643
644        if (but&1)
645        do_special_power(o,xm,ym,but,top);
646        else
647        undo_special_power(o);
648        ret=player_move(o,xm,ym,but);
649        top->x=o->x;
650        top->y=o->y+29-top->picture()->height();
651       
652        if ((but&2) && !o->lvars[is_teleporting] && o->state!=S_climbing && o->state!=S_climb_off)
653        {
654          void *args=NULL;
655          p_ref r1(args);
656          view *v=o->controller();
657
658          push_onto_list(new_lisp_number(v->weapon_total(v->current_weapon)),args);
659          push_onto_list(l_FIRE,args);
660
661          current_object=top;
662          void *ret=eval_function((lisp_symbol *)figures[top->otype]->get_fun(OFUN_USER_FUN),args);       
663          current_object=o;
664          v->add_ammo(v->current_weapon,lnumber_value(ret));   
665        }
666      }
667    } else if (o->aistate()==3)
668    {
669      if (!o->controller() || o->controller()->key_down(JK_SPACE))
670      {
671        eval_function((lisp_symbol *)l_restart_player,NULL);  // call teh user function to reset the player
672        o->controller()->reset_player();
673        o->set_aistate(0);     
674      } else if (o->controller() && o->controller()->local_player())
675        the_game->show_help(symbol_str("space_cont"));
676
677    } else o->set_aistate(o->aistate()+1);
678  }
679
680  return new_lisp_number(ret);
681}
682
683
684
685void *ladder_ai()
686{
687  view *f=player_list;
688  game_object *o=current_object;
689  if (o->total_objects())
690  {
691    game_object *other=o->get_object(0);
692    for (;f;f=f->next)
693    {
694      int mex=f->focus->x;
695      int mey=f->focus->y;
696     
697      if (o->x<=mex && o->y<=mey && other->x>=mex && other->y>=mey)
698      {
699        if (f->focus->state==S_climbing)
700          f->focus->x=(o->x+other->x)/2;
701        f->focus->lvars[in_climbing_area]=mey-o->y;     
702      }
703    }
704  }
705  return true_symbol;
706}
707
708
709
710void *player_draw(int just_fired_var, int num)
711{
712  game_object *o=current_object;
713  if (num==0)
714  {
715    if (o->lvars[just_fired_var])
716    {
717      o->draw_tint(S_bright_tint);
718      o->lvars[just_fired_var]=0;
719    } else
720      o->drawer();
721  }
722  else
723  {
724    if (o->lvars[just_fired_var])
725    {
726      o->draw_double_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)),S_bright_tint);
727      o->lvars[just_fired_var]=0;
728    } else
729      o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)));
730  }
731  return NULL;
732}
733
734
735void *top_draw()
736{
737  game_object *o=current_object;
738  if (o->total_objects())
739  {
740    game_object *bot=o->get_object(0);
741    if (bot->state==stopped  || bot->state==running ||
742        bot->state==run_jump || bot->state==run_jump_fall ||
743        bot->state==end_run_jump)
744    {
745      int oldy=o->y;
746      o->x=bot->x;
747      if (bot->direction<0)
748        o->x+=4;
749      o->y=bot->y+29-bot->picture()->height();
750
751      void *ret=NULL;
752      p_ref r1(ret);
753
754      push_onto_list(new_lisp_number(bot->controller()->player_number),ret);
755
756      if (bot->lvars[special_power]==SNEAKY_POWER)
757      {
758        if (bot->lvars[used_special_power]==0)
759          player_draw(top_just_fired,bot->controller()->player_number);
760        else if (bot->lvars[used_special_power]<15)
761          o->draw_trans(bot->lvars[used_special_power],16);
762        else
763          o->draw_predator();
764      } else
765        eval_function((lisp_symbol *)l_player_draw,ret);
766     
767      o->y=oldy;
768      if (bot->direction<0)
769        o->x-=4;
770    }
771  }
772  return NULL;
773}
774
775
776
777void *bottom_draw()
778{
779  game_object *o=current_object;
780
781  if (o->lvars[r_ramp] || o->lvars[g_ramp] || o->lvars[b_ramp])
782  {
783    int r=o->lvars[r_ramp];
784    if (r>7) r-=7;
785    else r=0;
786    o->lvars[r_ramp]=r;
787
788    int g=o->lvars[g_ramp];
789    if (g>7) g-=7;
790    else g=0;
791    o->lvars[g_ramp]=g;
792
793    int b=o->lvars[b_ramp];
794    if (b>7) b-=7;
795    else b=0;
796    o->lvars[b_ramp]=b;
797
798    palette *p=pal->copy();
799    uchar *addr=(uchar *)p->addr();
800    int ra,ga,ba;
801   
802    for (int i=0;i<256;i++)
803    {
804      ra=(int)*addr+r; if (ra>255) ra=255; else if (ra<0) r=0; *addr=(uchar)ra; addr++;
805      ga=(int)*addr+g; if (ga>255) ga=255; else if (ga<0) g=0; *addr=(uchar)ga; addr++;
806      ba=(int)*addr+b; if (ba>255) ba=255; else if (ba<0) b=0; *addr=(uchar)ba; addr++;
807    }
808    p->load();
809    delete p;
810  }
811
812  if (o->aistate()>0)
813  {
814    switch (o->lvars[special_power])
815    {
816      case NO_POWER :
817      { player_draw(just_fired,o->controller()->player_number); } break;
818
819      case HEALTH_POWER :
820      {
821        player_draw(just_fired,o->controller()->player_number);
822        if (o->controller() && o->controller()->local_player())
823          cash.img(S_health_image)->put_image(screen,o->controller()->cx2-20,
824                                            o->controller()->cy1+5,1);
825      } break;
826      case FAST_POWER :
827      {
828        eval_function((lisp_symbol *)l_draw_fast,NULL);
829        int old_state=o->state;
830        switch (o->state)
831        {
832          case stopped : o->state=(character_state)S_fast_stopped; break;
833          case running : o->state=(character_state)S_fast_running; break;
834          case start_run_jump : o->state=(character_state)S_fast_start_run_jump; break;
835          case run_jump : o->state=(character_state)S_fast_run_jump; break;
836          case run_jump_fall : o->state=(character_state)S_fast_run_jump_fall; break;
837          case end_run_jump : o->state=(character_state)S_fast_end_run_jump; break;
838        }
839
840        player_draw(just_fired,o->controller()->player_number);
841        o->state=(character_state)old_state;
842        if (o->controller() && o->controller()->local_player())
843          cash.img(S_fast_image)->put_image(screen,o->controller()->cx2-20,
844                                            o->controller()->cy1+5,1);
845      } break;
846      case FLY_POWER :
847      {
848        int old_state=o->state;
849        switch (o->state)
850        {
851          case stopped : o->state=(character_state)S_fly_stopped; break;
852          case running : o->state=(character_state)S_fly_running; break;
853          case start_run_jump : o->state=(character_state)S_fly_start_run_jump; break;
854          case run_jump : o->state=(character_state)S_fly_run_jump; break;
855          case run_jump_fall : o->state=(character_state)S_fly_run_jump_fall; break;
856          case end_run_jump : o->state=(character_state)S_fly_end_run_jump; break;
857        }
858
859        player_draw(just_fired,o->controller()->player_number);
860        o->state=(character_state)old_state;
861
862        if (o->controller() && o->controller()->local_player())
863          cash.img(S_fly_image)->put_image(screen,o->controller()->cx2-20,
864                                            o->controller()->cy1+5,1);
865      } break;
866      case SNEAKY_POWER :
867      {
868        if (o->lvars[used_special_power]==0)
869          player_draw(just_fired,o->controller()->player_number);
870        else if (o->lvars[used_special_power]<15)
871          o->draw_trans(o->lvars[used_special_power],16);
872        else
873          o->draw_predator();
874         
875        if (o->controller() && o->controller()->local_player())
876          cash.img(S_sneaky_image)->put_image(screen,o->controller()->cx2-20,
877                                            o->controller()->cy1+5,1);
878      } break;
879    }   
880  }
881  return NULL;
882}
883
884
885
886void *sgun_ai()
887{
888  game_object *o=current_object;
889
890  if (o->lvars[sgb_lifetime]==0)
891    return NULL;
892  o->lvars[sgb_lifetime]--;
893
894  o->lvars[sgb_lastx]=o->x;
895  o->lvars[sgb_lasty]=o->y;
896  o->lvars[sgb_speed]=o->lvars[sgb_speed]*6/5;
897 
898  long ang=o->lvars[sgb_angle];
899  long mag=o->lvars[sgb_speed];
900
901  long xvel=(lisp_cos(ang))*(mag);
902  current_object->set_xvel(xvel>>16);
903  current_object->set_fxvel((xvel&0xffff)>>8);
904  long yvel=-(lisp_sin(ang))*(mag);
905  current_object->set_yvel(yvel>>16);
906  current_object->set_fyvel((yvel&0xffff)>>8);     
907
908
909  int whit=0;
910  game_object *who=o->bmove(whit, o->total_objects() ? o->get_object(0) : 0);
911
912  if (whit || (who && figures[who->otype]->get_cflag(CFLAG_UNACTIVE_SHIELD) && who->total_objects() &&
913               who->get_object(0)->aistate()==0))
914  {
915    o->lvars[sgb_lifetime]=0;
916    game_object *n=create(S_EXPLODE5,o->x+jrand()%4,o->y+jrand()%4);
917    current_level->add_object(n);   
918  } else if (who && figures[who->otype]->get_cflag(CFLAG_HURTABLE))
919  {
920    o->lvars[sgb_lifetime]=0;
921    game_object *n=create(S_EXPLODE3,o->x+jrand()%4,o->y+jrand()%4);
922    current_level->add_object(n);       
923     who->do_damage(5,o,o->x,o->y,(lisp_cos(ang)*10)>>16,(lisp_sin(ang)*10)>>16);
924  }
925  return true_symbol;
926}
927
928
929
930void *mover_ai()
931{
932  game_object *o=current_object;
933  if (o->total_objects()==2)
934  {
935    if (o->aistate()<2)
936    {
937      game_object *obj=o->get_object(1);
938      o->remove_object(obj);
939      game_object *d=o->get_object(0);
940      d->add_object(obj);
941      d->set_aistate(d->aitype());
942    } else
943    {
944      o->set_aistate(o->aistate()-1);
945      game_object *d=o->get_object(0);
946      game_object *obj=o->get_object(1);     
947
948      obj->x=d->x-(d->x-o->x)*o->aistate()/o->aitype();
949      obj->y=d->y-(d->y-o->y)*o->aistate()/o->aitype();
950    }
951  }
952  return true_symbol;
953}       
954
955
956void *respawn_ai()
957{
958 game_object *o=current_object;
959 int x=o->total_objects();
960 if (x)
961 {
962   game_object *last=o->get_object(x-1);
963   if (last->x==o->x && last->y==o->y)
964   {
965     if (last->fade_count())
966       last->set_fade_count(last->fade_count()-1);
967     o->set_aistate_time(0);
968   } else if (o->aistate_time()>o->xvel())
969   {
970     int type=o->get_object(jrandom(x))->otype;
971     game_object *n=create(type,o->x,o->y);
972     current_level->add_object(n);
973     o->add_object(n);
974     n->set_fade_count(15);
975     o->set_aistate_time(0);
976   }
977 }
978 return true_symbol;
979}
980
981static int compare_players(const void *a, const void *b)
982{
983  if  ( ((view **)a)[0]->kills > ((view **)b)[0]->kills)
984    return -1;
985  else if  ( ((view **)a)[0]->kills < ((view **)b)[0]->kills)
986    return 1;
987  else if (((view **)a)[0]->player_number > ((view **)b)[0]->player_number)
988    return -1;
989  else if (((view **)a)[0]->player_number < ((view **)b)[0]->player_number)
990    return 1;
991  else return 0; 
992}
993
994void *score_draw()
995{
996  view *sorted_players[16],*local=NULL;
997  int tp=0;
998  view *f=player_list;
999  for (;f;f=f->next)
1000  {
1001    sorted_players[tp]=f;
1002    tp++;
1003    if (f->local_player()) local=f;
1004  }
1005
1006  JCFont *fnt=eh->font();
1007  if (local)
1008  {
1009    qsort(sorted_players,tp,sizeof(view *),compare_players);
1010
1011    int x=local->cx1;
1012    int y=local->cy1;
1013    char msg[100];
1014
1015    int i;
1016    for (i=0;i<tp;i++)
1017    {
1018      int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),sorted_players[i]->player_number)); 
1019      sprintf(msg,"%3ld %s",sorted_players[i]->kills,sorted_players[i]->name);
1020      if (sorted_players[i]==local)
1021        strcat(msg," <<");
1022
1023      fnt->put_string(screen,x,y,msg,color);
1024      y+=fnt->height();
1025    }
1026  }
1027  return NULL;
1028}
1029
1030
1031extern void fade_in(image *im, int steps);
1032extern void fade_out(int steps);
1033
1034void *show_kills()
1035{
1036  fade_out(8);
1037  eh->set_mouse_position(0,0);
1038  screen->clear();
1039  image *im=cash.img(cash.reg("art/frame.spe","end_level_screen",SPEC_IMAGE,1));
1040  im->put_image(screen,0,0);
1041  int x1=im->width()+1,y1=0,y2=screen->height();
1042  JCFont *fnt=eh->font();
1043 
1044  view *v=player_list; int tp=0,i;
1045  for (v=player_list;v;v=v->next) tp++;
1046
1047  int y=(y1+y2)/2-(tp+2)*fnt->height()/2,x=x1+10;
1048  char *header_str=symbol_str("score_header");
1049  fnt->put_string(screen,x,y,header_str,eh->bright_color());
1050  y+=fnt->height();
1051
1052  screen->wiget_bar(x,y+2,x+strlen(header_str)*fnt->width(),y+fnt->height()-3,
1053                     eh->bright_color(),eh->medium_color(),eh->dark_color());
1054  y+=fnt->height();
1055  v=player_list;
1056  for (i=0;i<tp;i++)
1057  {
1058    enum { NAME_LEN=18 } ;
1059    int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),v->player_number)); 
1060    char max_name[NAME_LEN];
1061    strncpy(max_name,v->name,NAME_LEN-1);
1062    max_name[NAME_LEN-1]=0;
1063    char msg[100];
1064
1065
1066    sprintf(msg,"%-17s %3ld  %3ld",max_name,v->kills,v->tkills+v->kills);
1067    fnt->put_string(screen,x,y,msg,color);
1068
1069    y+=fnt->height();
1070    v=v->next;
1071  }
1072 
1073  eh->flush_screen();
1074  milli_wait(4000);   // wait 4 seconds
1075
1076  return NULL;
1077}
1078
1079
Note: See TracBrowser for help on using the repository browser.