4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
#include "system.h"
 
 
2
#include "prototyp.h"
 
 
3
#include "stratdef.h"
 
 
4
#include "bh_types.h"
 
 
5
#include "weapons.h"
 
 
6
#include "dynamics.h"
 
 
7
#include "pvisible.h"
 
 
8
#include "lift.h"
 
 
9
#include <assert.h>
 
 
10
#include <stdlib.h>
 
 
11
 
 
 
12
extern SCENEMODULE MainScene;
 
 
13
 
 
 
14
LIFT_CONTROL_BLOCK EC_Lift_Ctrl;
 
 
15
MODULE Old_Pos_Module;
 
 
16
 
 
 
17
void LiftBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
 
 
18
{
 
 
19
    MODULE * my_mod;
 
 
20
 
 
 
21
    LIFT_BEHAV_BLOCK *lift_bhv = malloc(sizeof(LIFT_BEHAV_BLOCK));
 
 
22
 
 
 
23
    if(!lift_bhv) 
 
 
24
    {
 
 
25
        RemoveBehaviourStrategy(sbptr);
 
 
26
        return;
 
 
27
    }
 
 
28
 
 
 
29
    sbptr->dataptr = lift_bhv;
 
 
30
 
 
 
31
    lift_bhv->bhvr_type = I_BehaviourLift;
 
 
32
     LIFT_STATION* lift_stn = &lift_bhv->lift_station;
 
 
33
    LIFT_TOOLS_TEMPLATE* lift_tt = (LIFT_TOOLS_TEMPLATE*)bhdata;
 
 
34
 
 
 
35
    // Copy the name over
 
 
36
    COPY_NAME (sbptr->SBname, lift_tt->nameID);
 
 
37
 
 
 
38
    {
 
 
39
        MREF mref = lift_tt->my_module;
 
 
40
        ConvertModuleNameToPointer (&mref, MainScene.sm_marray);
 
 
41
 
 
 
42
        my_mod = mref.mref_ptr;
 
 
43
    }
 
 
44
 
 
 
45
    assert (my_mod);
 
 
46
 
 
 
47
    my_mod->m_sbptr = sbptr;
 
 
48
    sbptr->moptr = my_mod;
 
 
49
 
 
 
50
    // loaded data - first the station
 
 
51
 
 
 
52
    COPY_NAME(lift_stn->lift_call_switch_name, lift_tt->call_switch_name);
 
 
53
    COPY_NAME(lift_stn->lift_door_name, lift_tt->lift_door_name);
 
 
54
    COPY_NAME(lift_stn->lift_floor_switch_name, lift_tt->lift_floor_switch_name);
 
 
55
    COPY_NAME(lift_stn->my_sb_name, lift_tt->my_module_name);
 
 
56
 
 
 
57
    lift_stn->num_floor =    lift_tt->num_floor;
 
 
58
    lift_stn->orient = lift_tt->orient;
 
 
59
 
 
 
60
    // fill in the rest of the stn data;
 
 
61
 
 
 
62
    lift_stn->lift_call_switch = NULL;    
 
 
63
    lift_stn->lift_door = NULL;    
 
 
64
    lift_stn->lift_floor_switch = NULL;    
 
 
65
    lift_stn->lift_module = sbptr->moptr;
 
 
66
    lift_stn->starting_station = (lift_tt->lift_flags & LiftFlag_Here);
 
 
67
    lift_stn->called = 0;
 
 
68
 
 
 
69
    // fill in the behaviour block
 
 
70
 
 
 
71
    lift_bhv->control_sb = NULL;
 
 
72
    lift_bhv->controller = lift_tt->controller;
 
 
73
    COPY_NAME(lift_bhv->control_sb_name, lift_tt->control_sb_name);
 
 
74
 
 
 
75
    if(lift_bhv->controller)
 
 
76
    {
 
 
77
        LIFT_CONTROL_BLOCK* lcont = malloc(sizeof(LIFT_CONTROL_BLOCK));
 
 
78
 
 
 
79
        if(!lcont)
 
 
80
        {
 
 
81
            RemoveBehaviourStrategy(sbptr);
 
 
82
            return;
 
 
83
        }
 
 
84
 
 
 
85
        lift_bhv->lift_control = lcont;
 
 
86
 
 
 
87
        // fill in the number of floors
 
 
88
 
 
 
89
        lcont->num_stations = lift_tt->num_stations;
 
 
90
        lcont->lift_stations = malloc(sizeof(LIFT_STATION*)*lcont->num_stations);                                            
 
 
91
 
 
 
92
        if(!lcont->lift_stations) 
 
 
93
        {
 
 
94
            RemoveBehaviourStrategy(sbptr);
 
 
95
            return;
 
 
96
        }
 
 
97
 
 
 
98
        //and init that array
 
 
99
        {
 
 
100
            int i=0;
 
 
101
            while(i < lcont->num_stations)
 
 
102
            {
 
 
103
                *(lcont->lift_stations + i) = NULL;
 
 
104
                i++;
 
 
105
            }
 
 
106
        }
 
 
107
        // fill in the rest of the data
 
 
108
 
 
 
109
        *(lcont->lift_stations + lift_stn->num_floor) = lift_stn;
 
 
110
        lcont->dest_station = -1;
 
 
111
        lcont->delay_at_floor = 0;
 
 
112
        lcont->delay_between_floors = 0;
 
 
113
        lcont->motion = I_going_down;
 
 
114
        lcont->state = I_ls_waiting;
 
 
115
        lcont->curr_station = -1;
 
 
116
        lcont->prev_station = -1;
 
 
117
        lcont->SoundHandle = SOUND_NOACTIVEINDEX;
 
 
118
        lcont->floor_switches_fixed = (lift_tt->lift_flags & LiftFlag_NoTel);
 
 
119
    }
 
 
120
    else
 
 
121
    {
 
 
122
        lift_bhv->lift_control = NULL;
 
 
123
    }
 
 
124
}
 
 
125
 
 
 
126
void TeleportContents(MODULE* new_pos, MODULE* old_pos, int floor_switches_fixed)
 
 
127
{
 
 
128
    //this used within level - find objects in module
 
 
129
    // all will have sbs
 
 
130
 
 
 
131
    int i;
 
 
132
    VECTORCH mod_offset;
 
 
133
 
 
 
134
    mod_offset.vx = new_pos->m_world.vx - old_pos->m_world.vx;
 
 
135
    mod_offset.vy = new_pos->m_world.vy - old_pos->m_world.vy;
 
 
136
    mod_offset.vz = new_pos->m_world.vz - old_pos->m_world.vz;
 
 
137
 
 
 
138
    int max_x = old_pos->m_maxx + old_pos->m_world.vx;
 
 
139
    int min_x = old_pos->m_minx + old_pos->m_world.vx;
 
 
140
    int max_y = old_pos->m_maxy + old_pos->m_world.vy;
 
 
141
    int min_y = old_pos->m_miny + old_pos->m_world.vy;
 
 
142
    int max_z = old_pos->m_maxz + old_pos->m_world.vz;
 
 
143
    int min_z = old_pos->m_minz + old_pos->m_world.vz;
 
 
144
 
 
 
145
    int dest_max_x = new_pos->m_maxx + new_pos->m_world.vx -200;
 
 
146
    int dest_min_x = new_pos->m_minx + new_pos->m_world.vx +200;
 
 
147
    int dest_max_y = new_pos->m_maxy + new_pos->m_world.vy -200;
 
 
148
    int dest_min_y = new_pos->m_miny + new_pos->m_world.vy +200;
 
 
149
    int dest_max_z = new_pos->m_maxz + new_pos->m_world.vz -200;
 
 
150
    int dest_min_z = new_pos->m_minz + new_pos->m_world.vz +200;
 
 
151
 
 
 
152
    for(i = 0; i < NumActiveStBlocks; i++)
 
 
153
    {
 
 
154
        DYNAMICSBLOCK    *dynptr;            
 
 
155
        STRATEGYBLOCK    *sbptr = ActiveStBlockList[i];
 
 
156
 
 
 
157
        if(!(dynptr = sbptr->DynPtr))
 
 
158
            continue;
 
 
159
 
 
 
160
        if(floor_switches_fixed)
 
 
161
        {
 
 
162
            switch(sbptr->type)
 
 
163
            {
 
 
164
                case I_BehaviourInanimateObject:
 
 
165
                    if (((INANIMATEOBJECT_STATUSBLOCK*)sbptr->dataptr)->typeId)
 
 
166
                        break;
 
 
167
                case I_BehaviourBinarySwitch:
 
 
168
                case I_BehaviourLinkSwitch:
 
 
169
                    continue; 
 
 
170
                default:
 
 
171
                break;
 
 
172
            }
 
 
173
        }
 
 
174
 
 
 
175
        VECTORCH obj_world = dynptr->Position;
 
 
176
 
 
 
177
        if(obj_world.vx < max_x)
 
 
178
            if(obj_world.vx > min_x)
 
 
179
                if(obj_world.vz < max_z)
 
 
180
                    if(obj_world.vz > min_z)
 
 
181
                        if(obj_world.vy < max_y)
 
 
182
                            if(obj_world.vy > min_y)
 
 
183
                            {
 
 
184
                                dynptr->Position.vx += mod_offset.vx; 
 
 
185
                                dynptr->Position.vy += mod_offset.vy; 
 
 
186
                                dynptr->Position.vz += mod_offset.vz; 
 
 
187
 
 
 
188
                                dynptr->PrevPosition.vx += mod_offset.vx; 
 
 
189
                                dynptr->PrevPosition.vy += mod_offset.vy; 
 
 
190
                                dynptr->PrevPosition.vz += mod_offset.vz; 
 
 
191
 
 
 
192
                                //make sure new location is inside destination module
 
 
193
                                if(!dynptr->IsStatic)
 
 
194
                                {
 
 
195
                                    if(dynptr->Position.vx < dest_min_x) dynptr->Position.vx = dest_min_x;
 
 
196
                                    if(dynptr->Position.vy < dest_min_y) dynptr->Position.vy = dest_min_y;
 
 
197
                                    if(dynptr->Position.vz < dest_min_z) dynptr->Position.vz = dest_min_z;
 
 
198
                                    if(dynptr->Position.vx > dest_max_x) dynptr->Position.vx = dest_max_x;
 
 
199
                                    if(dynptr->Position.vy > dest_max_y) dynptr->Position.vy = dest_max_y;
 
 
200
                                    if(dynptr->Position.vz > dest_max_z) dynptr->Position.vz = dest_max_z;
 
 
201
 
 
 
202
                                    if(dynptr->PrevPosition.vx < dest_min_x) dynptr->PrevPosition.vx = dest_min_x;
 
 
203
                                    if(dynptr->PrevPosition.vy < dest_min_y) dynptr->PrevPosition.vy = dest_min_y;
 
 
204
                                    if(dynptr->PrevPosition.vz < dest_min_z) dynptr->PrevPosition.vz = dest_min_z;
 
 
205
                                    if(dynptr->PrevPosition.vx > dest_max_x) dynptr->PrevPosition.vx = dest_max_x;
 
 
206
                                    if(dynptr->PrevPosition.vy > dest_max_y) dynptr->PrevPosition.vy = dest_max_y;
 
 
207
                                    if(dynptr->PrevPosition.vz > dest_max_z) dynptr->PrevPosition.vz = dest_max_z;
 
 
208
                                }
 
 
209
 
 
 
210
                                if(sbptr->maintainVisibility)
 
 
211
                                    sbptr->containingModule = new_pos;
 
 
212
                            }
 
 
213
    }
 
 
214
}
 
 
215
 
 
 
216
void LiftBehaveFun(STRATEGYBLOCK* sbptr)
 
 
217
{
 
 
218
     assert(sbptr);
 
 
219
    LIFT_BEHAV_BLOCK *lift_bhv = (LIFT_BEHAV_BLOCK*)sbptr->dataptr;
 
 
220
    assert((lift_bhv->bhvr_type == I_BehaviourLift));
 
 
221
 
 
 
222
    LIFT_CONTROL_BLOCK *lift_ctrl = lift_bhv->lift_control;
 
 
223
 
 
 
224
    /* ALL the lift modules have a Strategy block that contains inforamtion
 
 
225
         about that particular location. Only one points to the LIFT CONTROL
 
 
226
         BLOCK
 
 
227
    */
 
 
228
 
 
 
229
    /* the lifts will work between envs as well as on the same env 
 
 
230
         so the control of the doors in the other envs sin't actually set,
 
 
231
         but a record of the postion is maintained
 
 
232
    */
 
 
233
 
 
 
234
    if(lift_bhv->controller)
 
 
235
       {
 
 
236
           // HACK    - RWH - if this is true the data is broken and this fix won't always work
 
 
237
 
 
 
238
           if(lift_ctrl->curr_station == -1)
 
 
239
               lift_ctrl->curr_station = 0;
 
 
240
 
 
 
241
           switch(lift_ctrl->state)
 
 
242
        {
 
 
243
            case I_ls_waiting:
 
 
244
            {
 
 
245
                /*** find dest and set movement direction this is always the
 
 
246
                same even if the lift is on a different floor ***/
 
 
247
                int lower_station = -1;
 
 
248
                int upper_station = -1;
 
 
249
                int i;
 
 
250
                LIFT_STATION *lift_stn;
 
 
251
 
 
 
252
                /**** find the nearest floors selected ****/
 
 
253
 
 
 
254
                // search up and down
 
 
255
                for(i = lift_ctrl->curr_station; (i >= 0) && (lower_station == -1); i --)
 
 
256
                {
 
 
257
                    lift_stn = lift_ctrl->lift_stations[i];
 
 
258
 
 
 
259
                    if(lift_stn->called)
 
 
260
                        upper_station = i;    // higher floors have lower nums
 
 
261
                }
 
 
262
 
 
 
263
                for(i = lift_ctrl->curr_station; (i < lift_ctrl->num_stations) && (upper_station == -1); i ++)
 
 
264
                {
 
 
265
                    lift_stn = lift_ctrl->lift_stations[i];
 
 
266
 
 
 
267
                    if(lift_stn->called)
 
 
268
                        lower_station = i;      // lower floors have higher nums
 
 
269
                }
 
 
270
 
 
 
271
                /****** set the    destination and the motion direction ****/
 
 
272
 
 
 
273
                if(lift_ctrl->motion == I_going_down)// higher nums
 
 
274
                {
 
 
275
                    if(lower_station != -1)
 
 
276
                    {
 
 
277
                        lift_ctrl->dest_station = lower_station;
 
 
278
                    }
 
 
279
                    else
 
 
280
                    {
 
 
281
                        lift_ctrl->dest_station = upper_station;
 
 
282
                        lift_ctrl->motion = I_going_up;
 
 
283
                    }
 
 
284
                }
 
 
285
                else if(lift_ctrl->motion == I_going_up) // lower nums
 
 
286
                {
 
 
287
                    if(upper_station != -1)
 
 
288
                    {
 
 
289
                        lift_ctrl->dest_station = upper_station;
 
 
290
                    }
 
 
291
                    else
 
 
292
                    {
 
 
293
                        lift_ctrl->dest_station = lower_station;
 
 
294
                        lift_ctrl->motion = I_going_down;
 
 
295
                    }
 
 
296
                }
 
 
297
 
 
 
298
                // now we have a station to go to, we start the lift in motion
 
 
299
                // unless we have just pressed the current floor switch again
 
 
300
 
 
 
301
                if(lift_ctrl->dest_station == lift_ctrl->curr_station)
 
 
302
                {
 
 
303
                    // we have just called the lift to the same place
 
 
304
                    lift_ctrl->dest_station = -1;
 
 
305
                    lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
306
                    lift_stn->called = 0;
 
 
307
                }
 
 
308
                else if(lift_ctrl->dest_station != -1)
 
 
309
                {
 
 
310
                    // if there is a dest, set the lift to go
 
 
311
                    // close current stations 
 
 
312
 
 
 
313
                    lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
314
 
 
 
315
                    {
 
 
316
                        lift_ctrl->prev_station = lift_ctrl->curr_station;
 
 
317
 
 
 
318
                        if(lift_stn->lift_door)
 
 
319
                        {
 
 
320
                            // no door - must be on another env
 
 
321
                            RequestState(lift_stn->lift_door, 0, 0);
 
 
322
                        }
 
 
323
                        lift_ctrl->state = I_ls_closing_door;
 
 
324
                    }
 
 
325
                }
 
 
326
            }
 
 
327
            break;
 
 
328
            case I_ls_closing_door:
 
 
329
            {
 
 
330
                // lift station for the current lift position has to 
 
 
331
                // have a closed door
 
 
332
 
 
 
333
                LIFT_STATION *pos_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
334
                //MODULE* mptr = pos_stn->lift_module;
 
 
335
 
 
 
336
                // deal with the fact that the lift is in a different env
 
 
337
 
 
 
338
                // close the door before we change state to moving                         
 
 
339
 
 
 
340
                if(!GetState(pos_stn->lift_door))
 
 
341
                {
 
 
342
                    lift_ctrl->state = I_ls_moving;
 
 
343
                    lift_ctrl->delay_between_floors = LIFT_MOVE_DELAY;
 
 
344
 
 
 
345
                    RequestState(pos_stn->lift_call_switch, 0, 0);
 
 
346
 
 
 
347
                    if(pos_stn->lift_floor_switch)
 
 
348
                        RequestState(pos_stn->lift_floor_switch, 0, 0);
 
 
349
 
 
 
350
                    //what if there is a bad guy in the lift - if there is open the door
 
 
351
                    //and reset all the switches and stations
 
 
352
                }
 
 
353
            }
 
 
354
            break;
 
 
355
            case I_ls_moving:
 
 
356
            {
 
 
357
                //int curr_station_num = lift_ctrl->curr_station;
 
 
358
                //LIFT_STATION *pos_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
359
                //MODULE* mptr = pos_stn->lift_module;
 
 
360
 
 
 
361
                lift_ctrl->delay_between_floors -= NormalFrameTime;
 
 
362
 
 
 
363
                // TRAP CHANGE OF ENVIRONMENT
 
 
364
                // we need to trap it here so we don't have the delay
 
 
365
                // between floors. However. The trap should make sure it is the nex array pos
 
 
366
 
 
 
367
                if(lift_ctrl->delay_between_floors < 0)
 
 
368
                {
 
 
369
                    if(lift_ctrl->motion == I_going_up)
 
 
370
                        lift_ctrl->curr_station--;
 
 
371
                    else
 
 
372
                        lift_ctrl->curr_station++;
 
 
373
 
 
 
374
                    assert(lift_ctrl->curr_station >= 0);
 
 
375
 
 
 
376
                    if(lift_ctrl->curr_station == lift_ctrl->dest_station)
 
 
377
                    {
 
 
378
                        // at destination
 
 
379
                        LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
380
                        LIFT_STATION *lift_stn_old = lift_ctrl->lift_stations[lift_ctrl->prev_station];
 
 
381
                        MODULE * new_pos = lift_stn_new->lift_module;
 
 
382
                        MODULE * old_pos = lift_stn_old->lift_module;
 
 
383
 
 
 
384
                        lift_ctrl->dest_station = -1;
 
 
385
                        lift_ctrl->state = I_ls_opening_door;                    
 
 
386
 
 
 
387
                        /* roxby: i have taken this out - patrick */
 
 
388
                        /* assert(mptr); */
 
 
389
                        Sound_Stop(lift_ctrl->SoundHandle);
 
 
390
 
 
 
391
                        //  door open
 
 
392
 
 
 
393
                        RequestState(lift_stn_new->lift_door, 1, 0);
 
 
394
 
 
 
395
                        lift_stn_new->called = 0;
 
 
396
 
 
 
397
                        if(old_pos)
 
 
398
                        {    
 
 
399
                            // if we don't have an old pos, we must
 
 
400
                            // be coming from another env
 
 
401
                            TeleportContents(new_pos, old_pos,lift_ctrl->floor_switches_fixed);
 
 
402
                        }
 
 
403
                    }
 
 
404
                    else 
 
 
405
                    {
 
 
406
                        // futher to go - move along now
 
 
407
                        lift_ctrl->delay_between_floors += LIFT_MOVE_DELAY;
 
 
408
                     }
 
 
409
                }
 
 
410
            }
 
 
411
            break;
 
 
412
            case I_ls_opening_door:
 
 
413
            {
 
 
414
                LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
415
 
 
 
416
                if(GetState(lift_stn_new->lift_door))
 
 
417
                {
 
 
418
                    lift_ctrl->state = I_ls_delay_at_floor;
 
 
419
                    lift_ctrl->delay_at_floor = LIFT_FLOOR_DELAY;
 
 
420
                }
 
 
421
            }
 
 
422
            break;
 
 
423
            case I_ls_delay_at_floor:
 
 
424
            {
 
 
425
                lift_ctrl->delay_at_floor -= NormalFrameTime;
 
 
426
 
 
 
427
                if(lift_ctrl->delay_at_floor < 0)
 
 
428
                {
 
 
429
                    // turn on the floor lights
 
 
430
                    LIFT_STATION *lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
 
 
431
 
 
 
432
                    RequestState(lift_stn->lift_call_switch, 1, 0);
 
 
433
 
 
 
434
                    if(lift_stn->lift_floor_switch_name[0] || lift_stn->lift_floor_switch_name[4])
 
 
435
                        RequestState(lift_stn->lift_floor_switch, 1, 0);
 
 
436
 
 
 
437
                    lift_ctrl->state = I_ls_waiting;
 
 
438
                    lift_ctrl->dest_station = -1;
 
 
439
                }
 
 
440
            }
 
 
441
            break;
 
 
442
            default:
 
 
443
                assert(2<1);
 
 
444
        }
 
 
445
       }
 
 
446
}