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

Last change on this file since 120 was 120, checked in by Sam Hocevar, 12 years ago
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.hpp"
13#include "level.hpp"
14#include "game.hpp"
15#include "id.hpp"
16#include "signals.hpp"
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.