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

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

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

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