4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "system.h"
 
 
2
#include "stratdef.h"
 
 
3
#include "bh_types.h"
 
 
4
#include "weapons.h"
 
 
5
#include "switchdoor.h"
 
 
6
#include "savegame.h"
 
 
7
#include <assert.h>
 
 
8
#include <stdlib.h>
 
 
9
 
 
 
10
extern void UpdateMorphing(MORPHCTRL *mcptr);
 
 
11
 
 
 
12
/*---------------------Patrick 12/3/97-------------------------
 
 
13
  Initialisation of a switch door....
 
 
14
  NB asumes that all switch doors start in a 'closed' state
 
 
15
  -------------------------------------------------------------*/
 
 
16
void InitialiseSwitchDoor(void* bhdata, STRATEGYBLOCK* sbPtr)
 
 
17
{
 
 
18
    /* create a switch door data block */
 
 
19
    SWITCH_DOOR_BEHAV_BLOCK *switchDoorBehaviourPtr = malloc(sizeof(SWITCH_DOOR_BEHAV_BLOCK));
 
 
20
 
 
 
21
    if (!switchDoorBehaviourPtr)
 
 
22
    {
 
 
23
        RemoveBehaviourStrategy(sbPtr);
 
 
24
        return;
 
 
25
    }
 
 
26
 
 
 
27
    switchDoorBehaviourPtr->myBehaviourType = I_BehaviourSwitchDoor;
 
 
28
    sbPtr->dataptr = (void *)switchDoorBehaviourPtr;    
 
 
29
    /* cast the tools data for access */
 
 
30
    SWITCH_DOOR_TOOLS_TEMPLATE *switchDoorToolsData = (SWITCH_DOOR_TOOLS_TEMPLATE *)bhdata;    
 
 
31
 
 
 
32
    /* Set up a new Morph Control */
 
 
33
    MORPHFRAME *morphFrame = malloc(sizeof(MORPHFRAME));
 
 
34
 
 
 
35
    if (!morphFrame)
 
 
36
    {
 
 
37
        RemoveBehaviourStrategy(sbPtr);
 
 
38
        return;
 
 
39
    }
 
 
40
 
 
 
41
    morphFrame->mf_shape1 = switchDoorToolsData->shapeOpen;
 
 
42
    morphFrame->mf_shape2 = switchDoorToolsData->shapeClosed;
 
 
43
    MORPHHEADER *morphHeader = malloc(sizeof(MORPHHEADER));
 
 
44
 
 
 
45
    if (!morphHeader)
 
 
46
    {
 
 
47
        free(morphFrame);
 
 
48
        RemoveBehaviourStrategy(sbPtr);
 
 
49
        return;
 
 
50
    }
 
 
51
 
 
 
52
    morphHeader->mph_numframes = 1;
 
 
53
    morphHeader->mph_maxframes = ONE_FIXED;
 
 
54
    morphHeader->mph_frames = morphFrame;
 
 
55
 
 
 
56
    MORPHCTRL *morphCtrl = malloc(sizeof(MORPHCTRL));
 
 
57
 
 
 
58
    if (!morphCtrl)
 
 
59
    {
 
 
60
        free(morphFrame);
 
 
61
        free(morphHeader);
 
 
62
        RemoveBehaviourStrategy(sbPtr);
 
 
63
        return;
 
 
64
    }
 
 
65
 
 
 
66
    morphCtrl->ObMorphCurrFrame = 0;
 
 
67
    morphCtrl->ObMorphFlags = 0;
 
 
68
    morphCtrl->ObMorphSpeed = 0;
 
 
69
    morphCtrl->ObMorphHeader = morphHeader;
 
 
70
    switchDoorBehaviourPtr->morfControl = sbPtr->morphctrl = morphCtrl;
 
 
71
 
 
 
72
    /* set up my module, and it's morph controls */
 
 
73
    COPY_NAME(sbPtr->SBname, switchDoorToolsData->nameID);
 
 
74
    {
 
 
75
        extern SCENEMODULE MainScene;
 
 
76
        MREF mref = switchDoorToolsData->myModule;
 
 
77
        ConvertModuleNameToPointer(&mref, MainScene.sm_marray);
 
 
78
        assert(mref.mref_ptr);
 
 
79
        assert(mref.mref_ptr->m_mapptr);
 
 
80
        mref.mref_ptr->m_sbptr = sbPtr;
 
 
81
        sbPtr->moptr = mref.mref_ptr;
 
 
82
    }
 
 
83
 
 
 
84
    sbPtr->moptr->m_flags &= ~m_flag_open;    
 
 
85
 
 
 
86
    /* set up some other behaviour block stuff */
 
 
87
    COPY_NAME(switchDoorBehaviourPtr->linkedDoorName, switchDoorToolsData->linkedDoorName);
 
 
88
    switchDoorBehaviourPtr->doorState = I_door_closed;
 
 
89
    switchDoorBehaviourPtr->linkedDoorPtr = NULL;
 
 
90
    switchDoorBehaviourPtr->requestOpen = 0;
 
 
91
    switchDoorBehaviourPtr->requestClose = 0;
 
 
92
    switchDoorBehaviourPtr->openTimer = 0;
 
 
93
    switchDoorBehaviourPtr->SoundHandle = SOUND_NOACTIVEINDEX;
 
 
94
    CloseDoor(sbPtr->morphctrl, DOOR_CLOSEFASTSPEED);    
 
 
95
 
 
 
96
    {
 
 
97
        // Work out the door sound pitch
 
 
98
 
 
 
99
        int maxX = mainshapelist[morphFrame->mf_shape2]->shapemaxx;
 
 
100
        int maxY = mainshapelist[morphFrame->mf_shape2]->shapemaxy;
 
 
101
        int maxZ = mainshapelist[morphFrame->mf_shape2]->shapemaxz;
 
 
102
 
 
 
103
        int doorSize = maxX + maxY + maxZ;
 
 
104
 
 
 
105
        if (doorSize < 3000)
 
 
106
            doorSize = 3000;
 
 
107
        else if (doorSize > 8000)
 
 
108
            doorSize = 8000;
 
 
109
 
 
 
110
        doorSize = (3000 - doorSize) >> 4;
 
 
111
 
 
 
112
        switchDoorBehaviourPtr->doorType = doorSize; 
 
 
113
    }
 
 
114
}
 
 
115
 
 
 
116
int AnythingInMyModule(MODULE* my_mod)
 
 
117
{
 
 
118
    // simple overlap test
 
 
119
    // this used within level - find objects in module
 
 
120
    // all will have sbs
 
 
121
    int i = 0;
 
 
122
 
 
 
123
    int max_x = my_mod->m_maxx + my_mod->m_world.vx;
 
 
124
    int min_x = my_mod->m_minx + my_mod->m_world.vx;
 
 
125
    int max_y = my_mod->m_maxy + my_mod->m_world.vy;
 
 
126
    int min_y = my_mod->m_miny + my_mod->m_world.vy;
 
 
127
    int max_z = my_mod->m_maxz + my_mod->m_world.vz;
 
 
128
    int min_z = my_mod->m_minz + my_mod->m_world.vz;
 
 
129
 
 
 
130
    for(; i < NumActiveStBlocks; i++)
 
 
131
    {
 
 
132
        STRATEGYBLOCK *sbptr = ActiveStBlockList[i];
 
 
133
        DYNAMICSBLOCK *dynptr = sbptr->DynPtr;
 
 
134
 
 
 
135
        if(dynptr)
 
 
136
        {
 
 
137
            VECTORCH obj_world = dynptr->Position;
 
 
138
 
 
 
139
            if((obj_world.vx < max_x) && (obj_world.vx > min_x)
 
 
140
            && (obj_world.vz < max_z) && (obj_world.vz > min_z)
 
 
141
            && (obj_world.vy < max_y) && (obj_world.vy > min_y))
 
 
142
            {
 
 
143
                CauseDamageToObject(sbptr, &damage_profiles[FALLINGDAMAGE], (100 * NormalFrameTime), NULL);
 
 
144
                return sbptr->DamageBlock.Indestructable;
 
 
145
            }
 
 
146
        }
 
 
147
    }
 
 
148
 
 
 
149
return 0;
 
 
150
}
 
 
151
 
 
 
152
/*---------------------Patrick 13/3/97-------------------------
 
 
153
  Switch door behaviour function.
 
 
154
  -------------------------------------------------------------*/
 
 
155
void SwitchDoorBehaviour(STRATEGYBLOCK* sbPtr)
 
 
156
{
 
 
157
    int linkedDoorIsClosed = 1;
 
 
158
 
 
 
159
     assert(sbPtr);
 
 
160
    SWITCH_DOOR_BEHAV_BLOCK *doorBehaviour = (SWITCH_DOOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
161
    assert(doorBehaviour);
 
 
162
    MORPHCTRL *mCtrl = doorBehaviour->morfControl;
 
 
163
    assert(mCtrl);
 
 
164
    MODULE *mPtr = sbPtr->moptr;
 
 
165
    assert(mPtr);
 
 
166
 
 
 
167
    /* update morphing.... */
 
 
168
    UpdateMorphing(mCtrl);
 
 
169
 
 
 
170
     /* get state of linked door: if there isn't a linked door, 'linkeddoorisclosed' 
 
 
171
     remains true so that there is no obstruction to operation of this door.
 
 
172
 
 
 
173
     NB can't use 'GetState' here, as it returns true only if the door is fully open
 
 
174
     (used by the NPC's).  Here, we need to determine if the door is closed (which is 
 
 
175
     not the same as !open) */
 
 
176
 
 
 
177
    if(doorBehaviour->linkedDoorPtr)
 
 
178
    {
 
 
179
        if(((SWITCH_DOOR_BEHAV_BLOCK *)doorBehaviour->linkedDoorPtr->dataptr)->doorState != I_door_closed)
 
 
180
                linkedDoorIsClosed = 0;
 
 
181
     }
 
 
182
 
 
 
183
     switch(doorBehaviour->doorState)
 
 
184
    {
 
 
185
        case I_door_opening:
 
 
186
        {    
 
 
187
            /* assert(linkedDoorIsClosed);    */
 
 
188
            /* check if we've got a close request */
 
 
189
 
 
 
190
            if(doorBehaviour->requestClose && !AnythingInMyModule(sbPtr->moptr)) 
 
 
191
            {
 
 
192
                if(sbPtr->DisplayBlock)
 
 
193
                    CloseDoor(mCtrl, DOOR_CLOSESLOWSPEED);
 
 
194
                else
 
 
195
                    CloseDoor(mCtrl, DOOR_CLOSEFASTSPEED);
 
 
196
 
 
 
197
                doorBehaviour->doorState = I_door_closing;
 
 
198
            }
 
 
199
            else if(mCtrl->ObMorphFlags & mph_flag_finished) 
 
 
200
            {
 
 
201
                /* already opening, so just allow the door to continue... */
 
 
202
                //door has finished opening
 
 
203
                doorBehaviour->doorState = I_door_open;
 
 
204
                doorBehaviour->openTimer = DOOR_FAROPENTIME;
 
 
205
 
 
 
206
                if (doorBehaviour->SoundHandle != SOUND_NOACTIVEINDEX)
 
 
207
                {
 
 
208
                    Sound_Play(SID_DOOREND, "dp", &mPtr->m_world,doorBehaviour->doorType);
 
 
209
                        Sound_Stop(doorBehaviour->SoundHandle);
 
 
210
                }
 
 
211
            }
 
 
212
        }
 
 
213
        break;
 
 
214
        case I_door_closing:
 
 
215
        {
 
 
216
            /* assert(linkedDoorIsClosed);    */
 
 
217
            /* check if we've got an open request, or anything has jumped in */
 
 
218
            if(doorBehaviour->requestOpen || AnythingInMyModule(sbPtr->moptr))
 
 
219
            {
 
 
220
                //have to start opening again
 
 
221
                if(sbPtr->DisplayBlock)
 
 
222
                    OpenDoor(mCtrl, DOOR_OPENSLOWSPEED);
 
 
223
                else
 
 
224
                    OpenDoor(mCtrl, DOOR_OPENFASTSPEED);
 
 
225
 
 
 
226
                doorBehaviour->doorState = I_door_opening;
 
 
227
 
 
 
228
                Sound_Play(SID_DOORSTART, "dp", &mPtr->m_world, doorBehaviour->doorType);
 
 
229
                 Sound_Play(SID_DOORMID, "delp", &mPtr->m_world, &doorBehaviour->SoundHandle, doorBehaviour->doorType);
 
 
230
            }
 
 
231
            else if(mCtrl->ObMorphFlags & mph_flag_finished)
 
 
232
            {
 
 
233
                /* check if we've finished closing */
 
 
234
                doorBehaviour->doorState = I_door_closed;
 
 
235
                mPtr->m_flags &= ~m_flag_open;
 
 
236
 
 
 
237
                if (doorBehaviour->SoundHandle!=SOUND_NOACTIVEINDEX)
 
 
238
                {
 
 
239
                    Sound_Play(SID_DOOREND,"dp",&mPtr->m_world,doorBehaviour->doorType);
 
 
240
                        Sound_Stop(doorBehaviour->SoundHandle);
 
 
241
                }
 
 
242
            }
 
 
243
        }
 
 
244
        break;
 
 
245
        case I_door_open:
 
 
246
        {
 
 
247
            /* assert(linkedDoorIsClosed);    */        
 
 
248
            /*if we've got a close request , set the open timer to 0 
 
 
249
                so the door will start closing*/
 
 
250
            if(doorBehaviour->requestClose)
 
 
251
                doorBehaviour->openTimer = 0;
 
 
252
 
 
 
253
            /* check our timer to see if it's time to close*/
 
 
254
            if(doorBehaviour->openTimer <= 0)
 
 
255
            {
 
 
256
                /* make sure there's nothing inside the door module before closing */
 
 
257
                if(!AnythingInMyModule(sbPtr->moptr))
 
 
258
                {
 
 
259
                    if(sbPtr->DisplayBlock)
 
 
260
                        CloseDoor(mCtrl, DOOR_CLOSESLOWSPEED);
 
 
261
                    else
 
 
262
                        CloseDoor(mCtrl, DOOR_CLOSEFASTSPEED);
 
 
263
 
 
 
264
                    doorBehaviour->doorState = I_door_closing;
 
 
265
                    doorBehaviour->openTimer = 0;
 
 
266
 
 
 
267
                    Sound_Play(SID_DOORSTART, "dp", &mPtr->m_world, doorBehaviour->doorType);
 
 
268
                     Sound_Play(SID_DOORMID, "delp", &mPtr->m_world, &doorBehaviour->SoundHandle, doorBehaviour->doorType);
 
 
269
                }
 
 
270
            }
 
 
271
            else
 
 
272
            {
 
 
273
                doorBehaviour->openTimer -= NormalFrameTime;
 
 
274
            }
 
 
275
        }
 
 
276
        break;
 
 
277
        case I_door_closed:
 
 
278
        {
 
 
279
            if(doorBehaviour->requestOpen && linkedDoorIsClosed)
 
 
280
            {
 
 
281
                /* just open the door */
 
 
282
                if(sbPtr->DisplayBlock)
 
 
283
                    OpenDoor(mCtrl, DOOR_OPENSLOWSPEED);
 
 
284
                else
 
 
285
                    OpenDoor(mCtrl, DOOR_OPENFASTSPEED);
 
 
286
 
 
 
287
                doorBehaviour->doorState = I_door_opening;
 
 
288
                mPtr->m_flags |= m_flag_open;
 
 
289
 
 
 
290
                Sound_Play(SID_DOORSTART,"dp",&mPtr->m_world,doorBehaviour->doorType);
 
 
291
                 Sound_Play(SID_DOORMID,"delp",&mPtr->m_world,&doorBehaviour->SoundHandle,doorBehaviour->doorType);
 
 
292
            }
 
 
293
        }
 
 
294
    }
 
 
295
 
 
 
296
    /* must reset this every frame */
 
 
297
    doorBehaviour->requestOpen = 0;
 
 
298
    doorBehaviour->requestClose = 0;
 
 
299
}
 
 
300
 
 
 
301
/*--------------------**
 
 
302
** Loading and Saving **
 
 
303
**--------------------*/
 
 
304
typedef struct switch_door_save_block
 
 
305
{
 
 
306
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
307
 
 
 
308
    DOOR_STATES doorState;
 
 
309
    int openTimer;
 
 
310
    unsigned int requestOpen :1;
 
 
311
    unsigned int requestClose :1;
 
 
312
 
 
 
313
    //from the morph control
 
 
314
    int ObMorphCurrFrame;
 
 
315
    int ObMorphFlags;
 
 
316
    int ObMorphSpeed;
 
 
317
 
 
 
318
} SWITCH_DOOR_SAVE_BLOCK;
 
 
319
 
 
 
320
//defines for load/save macros
 
 
321
#define SAVELOAD_BLOCK block
 
 
322
#define SAVELOAD_BEHAV doorbhv
 
 
323
 
 
 
324
void LoadStrategy_SwitchDoor(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
325
{
 
 
326
    SWITCH_DOOR_SAVE_BLOCK* block = (SWITCH_DOOR_SAVE_BLOCK*) header; 
 
 
327
 
 
 
328
    if(header->size != sizeof(*block))
 
 
329
        return;
 
 
330
 
 
 
331
    //find the existing strategy block
 
 
332
    STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname);
 
 
333
 
 
 
334
    if(!sbPtr)
 
 
335
        return;
 
 
336
 
 
 
337
    //make sure the strategy found is of the right type
 
 
338
    if(sbPtr->type != I_BehaviourSwitchDoor)
 
 
339
        return;
 
 
340
 
 
 
341
    SWITCH_DOOR_BEHAV_BLOCK *doorbhv = (SWITCH_DOOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
342
 
 
 
343
    COPYELEMENT_LOAD(doorState)
 
 
344
    COPYELEMENT_LOAD(openTimer)
 
 
345
    COPYELEMENT_LOAD(requestOpen)
 
 
346
    COPYELEMENT_LOAD(requestClose)
 
 
347
 
 
 
348
    doorbhv->morfControl->ObMorphCurrFrame = block->ObMorphCurrFrame;
 
 
349
    doorbhv->morfControl->ObMorphFlags = block->ObMorphFlags;
 
 
350
    doorbhv->morfControl->ObMorphSpeed = block->ObMorphSpeed;
 
 
351
 
 
 
352
    Load_SoundState(&doorbhv->SoundHandle);
 
 
353
}
 
 
354
 
 
 
355
void SaveStrategy_SwitchDoor(STRATEGYBLOCK* sbPtr)
 
 
356
{
 
 
357
    SWITCH_DOOR_SAVE_BLOCK *block;
 
 
358
    SWITCH_DOOR_BEHAV_BLOCK *doorbhv = (SWITCH_DOOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
359
 
 
 
360
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
361
 
 
 
362
    COPYELEMENT_SAVE(doorState)
 
 
363
    COPYELEMENT_SAVE(openTimer)
 
 
364
    COPYELEMENT_SAVE(requestOpen)
 
 
365
    COPYELEMENT_SAVE(requestClose)
 
 
366
 
 
 
367
    block->ObMorphCurrFrame = doorbhv->morfControl->ObMorphCurrFrame;
 
 
368
    block->ObMorphFlags = doorbhv->morfControl->ObMorphFlags;
 
 
369
    block->ObMorphSpeed = doorbhv->morfControl->ObMorphSpeed;
 
 
370
 
 
 
371
    Save_SoundState(&doorbhv->SoundHandle);
 
 
372
}