source: abuse/tags/pd/macabuse/src/go.c @ 49

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