source: abuse/trunk/src/go.cpp @ 532

Last change on this file since 532 was 532, checked in by Sam Hocevar, 11 years ago

imlib: reimplement trans_image::put_scan_line so that it uses the
common template for all blitting functions.

File size: 8.0 KB
RevLine 
[56]1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
[494]4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
[56]5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
[481]13#include "go.h"
14#include "level.h"
15#include "game.h"
16#include "id.h"
17#include "signals.h"
[2]18
19#define EL_WAIT_MOVEMENT 1           // wait for the user to press up or down
20#define EL_SKIP_SIGNAL   2
21#define EL_WAIT_SIGNAL   3
22#define EL_WAIT_SKIP     4
23
24
25void elcontrol::draw()
26{
27  if (dev & EDIT_MODE)
28    game_object::draw();
29
30}
31
[124]32ifield *elevator::make_fields(int ystart, ifield *Next)
[2]33{
[124]34  int H=10;
[2]35  return new text_field(5,ystart+H*0,ELEVATOR_SPEED,"speed",              "#####",speed,
36         new text_field(5,ystart+H*1,ELEVATOR_DIR,"heading dir",          "#####",dir,
[494]37         new text_field(5,ystart+H*2,ELEVATOR_DIRECTION,"facing dir",     "#####",direction,
[124]38            NULL)));
39}
[2]40
[124]41void elevator::gather_input(InputManager *inm)
42{
43  dir=atoi(inm->get(ELEVATOR_DIR)->read());
44  speed=atoi(inm->get(ELEVATOR_SPEED)->read());
45  direction=atoi(inm->get(ELEVATOR_DIRECTION)->read());
46  if (direction==0) direction=1;
[2]47}
48
49
50
51ifield *elcontrol::make_fields(int ystart,ifield *Next)
52{
53  int H=10;
[124]54  return new text_field(5,ystart+H*0,ELCONTROL_ALLOW_DIR,"stop dir","#####",allow_dir,NULL);
[2]55}
56
[120]57void elcontrol::gather_input(InputManager *inm)
[2]58{
[124]59  allow_dir=atoi(inm->get(ELCONTROL_ALLOW_DIR)->read());
[2]60}
61
62
63elcontrol::elcontrol(long X, long Y)
64{
65  defaults();
66  x=X;
67  y=Y;
[124]68  allow_dir=0;
[2]69}
70
71elcontrol::elcontrol(FILE *fp, unsigned char *state_remap)
72{
73  load(fp,state_remap);
[17]74  allow_dir=read_uint16(fp);
[2]75}
76
77
78
79
80
81int elevator::can_block(game_object *who)
[124]82{
[2]83  if (who!=this)
[124]84    return 1;
[2]85  else return 0;
[124]86
[2]87}
88
89
90void elevator::draw()  // draw cables above the elevator
91{
92  game_object::draw();
93  long x1,y1,x2,y2,sy1,sy2,sx,i;
[124]94  picture_space(x1,y1,x2,y2);
[2]95
96  sx=the_game->screenx(x1);
97
[124]98  sy2=the_game->screeny(y1);
[2]99  if (sy2>=the_game->viewy1)
100  {
101    long draw_to=y1-(sy2-the_game->viewy1),tmp=x;
[124]102    current_level->foreground_intersect(x,y1,tmp,draw_to);
[2]103    sy1=the_game->screeny(draw_to);
104    sy1=max(the_game->viewy1,sy1);
105    sy2=min(the_game->viewy2,sy2);
106    trans_image *p=picture();
[124]107
[494]108    for (i=sy1; i<=sy2; i++)
[532]109      p->PutScanLine(screen,sx,i,0);
[124]110  }
[2]111}
112
113
114elevator::elevator(long X, long Y)
115{
116  defaults();
117  x=X;
[124]118  y=Y;
[2]119  dir=0;
[124]120  speed=3;
[2]121}
122
123int elevator::size()
[124]124{
125  return game_object::size()+4;
[2]126}
127
128
129elevator::elevator(FILE *fp, unsigned char *state_remap)
130{
[124]131  load(fp,state_remap);
132  dir=read_uint16(fp);
133  speed=read_uint16(fp);
[2]134}
135
[124]136void elevator::save(FILE *fp)
137{
138  game_object::save(fp);
139  write_uint16(fp,dir);
140  write_uint16(fp,speed);
[2]141}
142
143
144elcontrol *elevator::find_stop()
145{
146  long x1,y1,x2,y2;
[124]147  picture_space(x1,y1,x2,y2);
[2]148  int i;
[124]149  game_object **o=current_level->obj;
[494]150  for (i=current_level->first_object(); i>=0; i=o[i]->next_active)
[124]151  {
[2]152    if (o[i]->type()==O_elcontrol)
153    {
154      int yd=o[i]->y-y;
155      if (abs(yd)<=speed && o[i]->x>x1 && o[i]->x<x2)
[124]156        return (elcontrol *)(o[i]);
[2]157    }
[124]158
[2]159  }
[124]160  return NULL;
[2]161}
162
163
164
165int elevator::decide()
166{
167  if (abs(dir)<=1)                                  // the elevator is stopped
168  {
169    switch (state)
170    {
[494]171      case stopped :
[2]172      {
173        long x1,y1,x2,y2;
[124]174    picture_space(x1,y1,x2,y2);
[2]175
176
[124]177    game_object *a=current_level->attacker(this);
[2]178                  // are we in the elevator?, if not wait for someone to get in
[124]179    if (a->x>x1+3 && a->x<x2-3 && a->y<y2 && a->y>y1+8)
180    {
181      int but,xm,ym;                          // wait for the user to press up or down
182      the_game->get_movement(but,xm,ym);      // see which way he wants to go
183      if (ym)
184      {
185        elcontrol *sp=find_stop();
186        if (ym<0 && (!sp || sp->allow_dir>=0))
187          dir=-1;
188        else if (ym>0 && (!sp || sp->allow_dir<=0))
189          dir=1;
190        if (dir)
191        {
192          if (has_sequence(start_still_jump))
193            set_state(start_still_jump);         // close the door
194          else
195            dir=dir+dir;                     // elevator doesn't have a door, start moving
196        }
[2]197      }
[124]198    }
199    break;
200      }
[2]201      case start_still_jump :
[124]202    next_picture();
203    if (end_of_sequence())                // door closed yet?
204    {
205      set_state(still_jump);              // we can start moving now
206      dir=dir+dir;
[494]207    }
[124]208    break;
[2]209      case still_jump :                       // just stopped, open the doors
[124]210    set_state(end_still_jump);
211    break;
[2]212      case end_still_jump :
[124]213    next_picture();
214    if (end_of_sequence())                // wait for doors to finish opening
215      set_state(stopped);
216    break;
[2]217      default :
[124]218    CHECK(0);
219    }
220  }
[2]221
222  if (abs(dir)>1)                     // are we moving?
223  {
224    next_picture();
225    int adder;
226    if (dir<0)                         // how much do we move this tick?
227      adder=-speed;
228    else adder=speed;
229
230    if (abs(dir)==8)                   // are we checking for stops yet?
231    {
232      elcontrol *s=find_stop();
233      if (s)                           // found one, stop or slow down
[124]234      {
235    adder=s->y-y;
236    if (!adder)
237          dir=0;
238      }
[2]239    } else dir=dir+dir;
[124]240
[2]241    if (dir)                                   // make sure move, wasn't canceled by a stop
242    {
243      if (!current_level->crush(this,0,adder)) // see if we can crush anyone (I hope so! :) )
[124]244      {
245    y+=adder;
246    current_level->push_characters(this,0,adder);
[2]247      } else dir=0;                           // we crushed, stop the elevator and wait on user
248    }
249  }
250
251  return 1;                                   // return not dead, can't kill elevators
252}
253
254
255char *sensor::aname()
256{
257  if (activate==-1)
258    return "FOCUS";
[124]259  else return object_names[activate];
[2]260}
261
262void sensor::get_activate(char *name)
263{
[124]264  int i;
265  activate=-1;  // if we can't fnd the name then go focus
[494]266  for (i=0; i<TOTAL_OBJECTS; i++)
[2]267    if (!strcmp(name,object_names[i]))
[124]268      activate=i;
[2]269}
270
271
272
273
[124]274int sensor::size()
275{
276  return game_object::size()+2*3+(strlen(aname())+2);
[2]277}
278
279
[124]280void sensor::save(FILE *fp)
281{ game_object::save(fp);
[17]282  write_uint16(fp,xrange);
283  write_uint16(fp,yrange);
[124]284  write_uint16(fp,signal);
[2]285
[17]286  write_uint8(fp,strlen(aname())+1);
[124]287  fwrite(aname(),strlen(aname())+1,1,fp);
[2]288}
289
290sensor::sensor(FILE *fp, unsigned char *state_remap)
291{
292  load(fp,state_remap);
[17]293  xrange=read_uint16(fp);
294  yrange=read_uint16(fp);
[124]295  signal=read_uint16(fp);
[2]296
297  char name[200];
[17]298  fread(name,read_uint8(fp),1,fp);
[2]299  get_activate(name);
300}
301
302int sensor::decide()
[124]303{
[2]304  int i;
305  game_object **o=current_level->obj;
306  long x1,y1,x2,y2;
307  if (activate==-1)
308  {
[124]309    current_level->attacker(this)->picture_space(x1,y1,x2,y2);
[2]310    if (x+xrange>=x1 && x-xrange<=x2 && y+yrange>=y1 && y-yrange<=y2)
[124]311      current_level->send_signal(signal);
[2]312  }
313  else
[124]314  {
[494]315    for (i=current_level->first_object(); i>=0; i=o[i]->next_active)
[2]316    {
[124]317      long x1,y1,x2,y2;
[2]318      if (o[i]->type()==activate)
[494]319      {
[124]320    o[i]->picture_space(x1,y1,x2,y2);
321    if (x+xrange>=x1 && x-xrange<=x2 && y+yrange>=y1 && y-yrange<=y2)
[494]322    {
[124]323          current_level->send_signal(signal);
324      return 1;          // only send one signal!
[494]325    }
[2]326      }
[124]327    }
[2]328  }
329  return 1;
330}
331
332
333
334
335void sensor::draw()
336{
337  if (dev & EDIT_MODE)
[124]338  {
[2]339    game_object::draw();
[124]340    int sx=the_game->screenx(x),sy=the_game->screeny(y);
341    screen->rectangle(sx-xrange,sy-yrange,sx+xrange,sy+yrange,wm->bright_color());
342  }
[2]343}
344
345
[124]346ifield *sensor::make_fields(int ystart, ifield *Next)
347{
[2]348  int H=10;
349  return new text_field(5,ystart+H*0,SENSOR_XRANGE,   "xrange",    "#####",xrange,
[124]350     new text_field(5,ystart+H*1,SENSOR_YRANGE,   "yrange",    "#####",yrange,
351     new text_field(5,ystart+H*2,SENSOR_SIGNAL,   "signal",    "#####",signal,
352     new text_field(5,ystart+H*3,SENSOR_ACTIVATE, "activator", "####################",aname(),
353            NULL))));
[2]354}
355
356
[120]357void sensor::gather_input(InputManager *inm)
[2]358{
359  xrange=atoi(inm->get(SENSOR_XRANGE)->read());
360  yrange=atoi(inm->get(SENSOR_XRANGE)->read());
361  signal=atoi(inm->get(SENSOR_SIGNAL)->read());
362  get_activate(inm->get(SENSOR_ACTIVATE)->read());
[494]363}
[2]364
Note: See TracBrowser for help on using the repository browser.