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