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

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