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

Last change on this file since 492 was 492, checked in by Sam Hocevar, 12 years ago

lisp: rename core classes to slightly shorter names (LispObject? -> LObject).

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