4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "files.h"
 
 
2
#include "stratdef.h"
 
 
3
#include "system.h"
 
 
4
#include "bh_types.h"
 
 
5
#include "pvisible.h"
 
 
6
#include "dynamics.h"
 
 
7
#include "userprofile.h"
 
 
8
#include "savegame.h"
 
 
9
#include "weapons.h"
 
 
10
#include "weaponbehaviour.h"
 
 
11
#include "npc_sentrygun.h"
 
 
12
#include <assert.h>
 
 
13
 
 
 
14
extern void *OpenGameDirectory(const char *dirname, const char *pattern, int type);
 
 
15
extern GameDirectoryFile *ScanGameDirectory(void *dir);
 
 
16
extern const SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char *);
 
 
17
extern SAVE_SLOT_HEADER SaveGameSlot[];
 
 
18
 
 
 
19
static struct
 
 
20
{
 
 
21
    char* BufferStart;
 
 
22
    char* BufferPos;
 
 
23
    int BufferSize;
 
 
24
    int BufferSpaceLeft;
 
 
25
    int BufferSpaceUsed;
 
 
26
 
 
 
27
} SaveInfo = {0,0,0,0,0};
 
 
28
 
 
 
29
static struct
 
 
30
{
 
 
31
    char* BufferStart;
 
 
32
    char* BufferPos;
 
 
33
    int BufferSize;
 
 
34
    int BufferSpaceLeft;
 
 
35
 
 
 
36
} LoadInfo = {0,0,0,0};
 
 
37
 
 
 
38
/*---------------------------------------------**
 
 
39
** externs for all the load and save functions **
 
 
40
**---------------------------------------------*/
 
 
41
extern void LoadStrategy_LiftDoor(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
42
extern void SaveStrategy_LiftDoor(STRATEGYBLOCK* sbPtr);
 
 
43
 
 
 
44
extern void LoadStrategy_SwitchDoor(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
45
extern void SaveStrategy_SwitchDoor(STRATEGYBLOCK* sbPtr);
 
 
46
 
 
 
47
extern void LoadStrategy_PlatformLift(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
48
extern void SaveStrategy_PlatformLift(STRATEGYBLOCK* sbPtr);
 
 
49
 
 
 
50
extern void LoadStrategy_BinarySwitch(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
51
extern void SaveStrategy_BinarySwitch(STRATEGYBLOCK* sbPtr);
 
 
52
 
 
 
53
extern void LoadStrategy_LinkSwitch(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
54
extern void SaveStrategy_LinkSwitch(STRATEGYBLOCK* sbPtr);
 
 
55
 
 
 
56
extern void LoadStrategy_Generator(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
57
extern void SaveStrategy_Generator(STRATEGYBLOCK* sbPtr);
 
 
58
 
 
 
59
extern void LoadHiveSettings(SAVE_BLOCK_HEADER* header);
 
 
60
extern void SaveHiveSettings();
 
 
61
 
 
 
62
extern void LoadStrategy_LightFx(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
63
extern void SaveStrategy_LightFx(STRATEGYBLOCK* sbPtr);
 
 
64
 
 
 
65
extern void LoadStrategy_PlacedSound(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
66
extern void SaveStrategy_PlacedSound(STRATEGYBLOCK* sbPtr);
 
 
67
 
 
 
68
extern void LoadStrategy_Message(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
69
extern void SaveStrategy_Message(STRATEGYBLOCK* sbPtr);
 
 
70
 
 
 
71
extern void LoadStrategy_MissionComplete(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
72
extern void SaveStrategy_MissionComplete(STRATEGYBLOCK* sbPtr);
 
 
73
 
 
 
74
extern void LoadStrategy_TrackObject(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
75
extern void SaveStrategy_TrackObject(STRATEGYBLOCK* sbPtr);
 
 
76
 
 
 
77
extern void LoadStrategy_Fan(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
78
extern void SaveStrategy_Fan(STRATEGYBLOCK* sbPtr);
 
 
79
 
 
 
80
extern void LoadStrategy_PlacedLight(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
81
extern void SaveStrategy_PlacedLight(STRATEGYBLOCK* sbPtr);
 
 
82
 
 
 
83
extern void LoadStrategy_VideoScreen(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
84
extern void SaveStrategy_VideoScreen(STRATEGYBLOCK* sbPtr);
 
 
85
 
 
 
86
extern void LoadStrategy_DeathVolume(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
87
extern void SaveStrategy_DeathVolume(STRATEGYBLOCK* sbPtr);
 
 
88
 
 
 
89
extern void LoadStrategy_ParticleGenerator(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
90
extern void SaveStrategy_ParticleGenerator(STRATEGYBLOCK* sbPtr);
 
 
91
 
 
 
92
extern void LoadStrategy_SelfDestruct(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
93
extern void SaveStrategy_SelfDestruct(STRATEGYBLOCK* sbPtr);
 
 
94
 
 
 
95
extern void LoadStrategy_Alien(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
96
extern void SaveStrategy_Alien(STRATEGYBLOCK* sbPtr);
 
 
97
 
 
 
98
extern void LoadStrategy_FaceHugger(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
99
extern void SaveStrategy_FaceHugger(STRATEGYBLOCK* sbPtr);
 
 
100
 
 
 
101
extern void LoadStrategy_Marine(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
102
extern void SaveStrategy_Marine(STRATEGYBLOCK* sbPtr);
 
 
103
 
 
 
104
extern void LoadMarineSquadState(SAVE_BLOCK_HEADER* header);
 
 
105
extern void SaveMarineSquadState();
 
 
106
 
 
 
107
extern void LoadStrategy_PlacedHierarchy(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
108
extern void SaveStrategy_PlacedHierarchy(STRATEGYBLOCK* sbPtr);
 
 
109
 
 
 
110
extern void LoadStrategy_Predator(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
111
extern void SaveStrategy_Predator(STRATEGYBLOCK* sbPtr);
 
 
112
 
 
 
113
extern void LoadStrategy_Xenoborg(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
114
extern void SaveStrategy_Xenoborg(STRATEGYBLOCK* sbPtr);
 
 
115
 
 
 
116
extern void LoadStrategy_Queen(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
117
extern void SaveStrategy_Queen(STRATEGYBLOCK* sbPtr);
 
 
118
 
 
 
119
extern void LoadStrategy_Player(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
120
extern void SaveStrategy_Player(STRATEGYBLOCK* sbPtr);
 
 
121
 
 
 
122
extern void LoadStrategy_Autogun(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
123
extern void SaveStrategy_Autogun(STRATEGYBLOCK* sbPtr);
 
 
124
 
 
 
125
extern void Load_Decals(SAVE_BLOCK_HEADER* header);
 
 
126
extern void Save_Decals();
 
 
127
 
 
 
128
extern void Load_Particles(SAVE_BLOCK_HEADER* header);
 
 
129
extern void Save_Particles();
 
 
130
 
 
 
131
extern void Load_VolumetricExplosions(SAVE_BLOCK_HEADER* header);
 
 
132
extern void Save_VolumetricExplosions();
 
 
133
 
 
 
134
extern void Load_PheromoneTrails(SAVE_BLOCK_HEADER* header);
 
 
135
extern void Save_PheromoneTrails();
 
 
136
 
 
 
137
extern void Load_LightElements(SAVE_BLOCK_HEADER* header);
 
 
138
extern void Save_LightElements();
 
 
139
 
 
 
140
extern void LoadStrategy_Flare(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
141
extern void SaveStrategy_Flare(STRATEGYBLOCK* sbPtr);
 
 
142
 
 
 
143
extern void LoadStrategy_ProxGrenade(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
144
extern void SaveStrategy_ProxGrenade(STRATEGYBLOCK* sbPtr);
 
 
145
 
 
 
146
extern void LoadStrategy_SpearBolt(SAVE_BLOCK_STRATEGY_HEADER* header);
 
 
147
extern void SaveStrategy_SpearBolt(STRATEGYBLOCK* sbPtr);
 
 
148
 
 
 
149
extern void Load_WeaponsCGlobals(SAVE_BLOCK_HEADER* header);
 
 
150
extern void Save_WeaponsCGlobals();
 
 
151
 
 
 
152
extern void Load_SoundState_NoRef(SAVE_BLOCK_HEADER* header);
 
 
153
extern void Save_SoundsWithNoReference();
 
 
154
 
 
 
155
#include "projload.hpp"
 
 
156
 
 
 
157
static STRATEGYBLOCK* Create_Pred_Disc_Pickup_For_Load()
 
 
158
{
 
 
159
    TOOLS_DATA_INANIMATEOBJECT toolsData;
 
 
160
    int discShapeIndex;
 
 
161
 
 
 
162
    {
 
 
163
        /*
 
 
164
        We need to find the shape index of the disc object. To do this , we need to
 
 
165
        get the disc head-up-display hierarchy , and search for the disc section
 
 
166
        */
 
 
167
 
 
 
168
        const SECTION* section = GetNamedHierarchyFromLibrary("pred_HUD", "disk");
 
 
169
 
 
 
170
        if(!section)
 
 
171
            return NULL;
 
 
172
 
 
 
173
        section = GetThisSection(section, "disk");
 
 
174
 
 
 
175
        if(!section)
 
 
176
            return NULL;
 
 
177
 
 
 
178
        //found the disc section
 
 
179
        discShapeIndex = section->ShapeNum;
 
 
180
    }
 
 
181
 
 
 
182
    //fill in a tools data for the disc
 
 
183
    memset(&toolsData, 0, sizeof(toolsData));
 
 
184
    toolsData.typeId = IOT_Ammo;
 
 
185
    toolsData.subType = (int)AMMO_PRED_DISC;
 
 
186
 
 
 
187
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourInanimateObject);
 
 
188
 
 
 
189
    if(!sbPtr)
 
 
190
        return NULL;
 
 
191
 
 
 
192
    sbPtr->shapeIndex = discShapeIndex;
 
 
193
 
 
 
194
    EnableBehaviourType(sbPtr, &toolsData);
 
 
195
    sbPtr->maintainVisibility = 1;
 
 
196
 
 
 
197
return sbPtr;
 
 
198
}
 
 
199
 
 
 
200
/*--------------------**
 
 
201
** Loading and Saving **
 
 
202
**--------------------*/
 
 
203
#include "savegame.h"
 
 
204
typedef struct inanimate_object_save_block
 
 
205
{
 
 
206
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
207
 
 
 
208
    INANIMATEOBJECT_TYPE typeId;
 
 
209
    int subType; /* weapon id, security level or other relevant enumerated type... */
 
 
210
 
 
 
211
    int explosionTimer; //slight time delay after destruction for explosion
 
 
212
 
 
 
213
    DAMAGEBLOCK DamageBlock;
 
 
214
    DYNAMICSBLOCK dynamics;
 
 
215
 
 
 
216
} INANIMATE_OBJECT_SAVE_BLOCK;
 
 
217
 
 
 
218
//defines for load/save macros
 
 
219
#define SAVELOAD_BLOCK block
 
 
220
#define SAVELOAD_BEHAV objectstatusptr
 
 
221
 
 
 
222
static void LoadStrategy_InanimateObject(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
223
{
 
 
224
    INANIMATE_OBJECT_SAVE_BLOCK* block = (INANIMATE_OBJECT_SAVE_BLOCK*) header; 
 
 
225
 
 
 
226
    //check the size of the save block
 
 
227
    if(header->size != sizeof(*block))
 
 
228
        return;
 
 
229
 
 
 
230
    //find the existing strategy block
 
 
231
    STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname);
 
 
232
 
 
 
233
    if(!sbPtr)
 
 
234
    {
 
 
235
        //Didn't find the object already existing.
 
 
236
        //Might be a predator disc pickup however.
 
 
237
        if(block->typeId == IOT_Weapon && block->subType == (int)WEAPON_PRED_DISC)
 
 
238
        {
 
 
239
            //okay we need to create a disc then
 
 
240
            sbPtr = Create_Pred_Disc_Pickup_For_Load();
 
 
241
        }
 
 
242
 
 
 
243
        if(!sbPtr)
 
 
244
            return;
 
 
245
    }
 
 
246
 
 
 
247
    //make sure the strategy found is of the right type
 
 
248
    if(sbPtr->type != I_BehaviourInanimateObject)
 
 
249
        return;
 
 
250
 
 
 
251
    INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = (INANIMATEOBJECT_STATUSBLOCK*)sbPtr->dataptr;
 
 
252
 
 
 
253
    //start copying stuff
 
 
254
 
 
 
255
    COPYELEMENT_LOAD(explosionTimer)
 
 
256
    COPYELEMENT_LOAD(typeId)
 
 
257
    COPYELEMENT_LOAD(subType)
 
 
258
 
 
 
259
    *sbPtr->DynPtr = block->dynamics;
 
 
260
    sbPtr->DamageBlock = block->DamageBlock;
 
 
261
}
 
 
262
 
 
 
263
static void SaveStrategy_InanimateObject(STRATEGYBLOCK* sbPtr)
 
 
264
{
 
 
265
    INANIMATE_OBJECT_SAVE_BLOCK *block;
 
 
266
    INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = (INANIMATEOBJECT_STATUSBLOCK*)sbPtr->dataptr;
 
 
267
 
 
 
268
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
269
 
 
 
270
    //start copying stuff
 
 
271
 
 
 
272
    COPYELEMENT_SAVE(explosionTimer)
 
 
273
    COPYELEMENT_SAVE(typeId)
 
 
274
    COPYELEMENT_SAVE(subType)
 
 
275
 
 
 
276
    block->dynamics = *sbPtr->DynPtr;
 
 
277
    block->dynamics.CollisionReportPtr=0;
 
 
278
 
 
 
279
    block->DamageBlock = sbPtr->DamageBlock;
 
 
280
}
 
 
281
 
 
 
282
/*--------------------**
 
 
283
** Loading and Saving **
 
 
284
**--------------------*/
 
 
285
typedef struct prox_door_save_block
 
 
286
{
 
 
287
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
288
 
 
 
289
    int door_state;
 
 
290
    int door_locked;
 
 
291
 
 
 
292
    //from the morph control
 
 
293
    int ObMorphCurrFrame;
 
 
294
    int ObMorphFlags;
 
 
295
    int ObMorphSpeed;
 
 
296
    int marineTrigger;
 
 
297
 
 
 
298
} PROX_DOOR_SAVE_BLOCK;
 
 
299
 
 
 
300
static void LoadStrategy_ProxDoor(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
301
{
 
 
302
    PROX_DOOR_SAVE_BLOCK* block = (PROX_DOOR_SAVE_BLOCK*) header; 
 
 
303
 
 
 
304
    if(header->size != sizeof(*block))
 
 
305
        return;
 
 
306
 
 
 
307
    //find the existing strategy block
 
 
308
    STRATEGYBLOCK* sbPtr = FindSBWithName(block->header.SBname);
 
 
309
 
 
 
310
    if(!sbPtr)
 
 
311
        return;
 
 
312
 
 
 
313
    //make sure the strategy found is of the right type
 
 
314
    if(sbPtr->type != I_BehaviourProximityDoor)
 
 
315
        return;
 
 
316
 
 
 
317
    PROXDOOR_BEHAV_BLOCK *doorbhv = (PROXDOOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
318
 
 
 
319
    doorbhv->door_state = block->door_state;
 
 
320
    doorbhv->door_locked = block->door_locked;
 
 
321
    doorbhv->marineTrigger = block->marineTrigger;
 
 
322
    doorbhv->PDmctrl->ObMorphCurrFrame = block->ObMorphCurrFrame;
 
 
323
    doorbhv->PDmctrl->ObMorphFlags = block->ObMorphFlags;
 
 
324
    doorbhv->PDmctrl->ObMorphSpeed = block->ObMorphSpeed;
 
 
325
 
 
 
326
    Load_SoundState(&doorbhv->SoundHandle);
 
 
327
}
 
 
328
 
 
 
329
static void SaveStrategy_ProxDoor(STRATEGYBLOCK* sbPtr)
 
 
330
{
 
 
331
    PROX_DOOR_SAVE_BLOCK *block;
 
 
332
    PROXDOOR_BEHAV_BLOCK *doorbhv  = (PROXDOOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
333
 
 
 
334
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
335
 
 
 
336
    block->door_state = doorbhv->door_state;
 
 
337
    block->door_locked = doorbhv->door_locked;
 
 
338
    block->marineTrigger = doorbhv->marineTrigger;
 
 
339
    block->ObMorphCurrFrame = doorbhv->PDmctrl->ObMorphCurrFrame;
 
 
340
    block->ObMorphFlags = doorbhv->PDmctrl->ObMorphFlags;
 
 
341
    block->ObMorphSpeed = doorbhv->PDmctrl->ObMorphSpeed;
 
 
342
 
 
 
343
    Save_SoundState(&doorbhv->SoundHandle);
 
 
344
}
 
 
345
 
 
 
346
/*-----------------------------------------------------**
 
 
347
** end of externs for all the load and save functions  **
 
 
348
**-----------------------------------------------------*/
 
 
349
 
 
 
350
/*
 
 
351
Functions for converting between ai modules and their indeces.
 
 
352
They don't really belong here , but they are only used by loading/saving at 
 
 
353
the moment.
 
 
354
*/
 
 
355
 
 
 
356
struct aimodule * GetPointerFromAIModuleIndex(int index)
 
 
357
{
 
 
358
    return (index >= 0 && index < AIModuleArraySize) ? &AIModuleArray[index] : NULL ;
 
 
359
}
 
 
360
 
 
 
361
int GetIndexFromAIModulePointer(struct aimodule* module)
 
 
362
{
 
 
363
    return (module ? module->m_index : -1);
 
 
364
}
 
 
365
 
 
 
366
void* GetPointerForSaveBlock(unsigned int size)
 
 
367
{
 
 
368
    //see if we need to enlarge the buffer to allow for this block
 
 
369
    if(size > SaveInfo.BufferSpaceLeft)
 
 
370
    {
 
 
371
        //need more space
 
 
372
        int spaceNeeded = SaveInfo.BufferSpaceUsed + size;
 
 
373
        //buffer incremented in lots of 100000 bytes (more or less)
 
 
374
        int newBufferSize = ((spaceNeeded / 100000) + 1) * 100000;
 
 
375
 
 
 
376
        char *ptr = (char*) realloc(SaveInfo.BufferStart, newBufferSize);
 
 
377
 
 
 
378
        if(NULL != ptr)
 
 
379
        {
 
 
380
            SaveInfo.BufferStart = ptr;
 
 
381
 
 
 
382
            //correct the position etc.
 
 
383
            SaveInfo.BufferPos = SaveInfo.BufferStart + SaveInfo.BufferSpaceUsed;
 
 
384
            SaveInfo.BufferSpaceLeft += (newBufferSize - SaveInfo.BufferSize);
 
 
385
            SaveInfo.BufferSize = newBufferSize;
 
 
386
        }
 
 
387
        // else pretend everything is OK? exit(EXIT_FAILURE);? return NULL;?
 
 
388
    }
 
 
389
 
 
 
390
    //get the pointer to the next part of the save buffer
 
 
391
    void* retPointer = (void*)SaveInfo.BufferPos;
 
 
392
 
 
 
393
    SaveInfo.BufferSpaceUsed += size;
 
 
394
    SaveInfo.BufferSpaceLeft -= size;
 
 
395
    SaveInfo.BufferPos += size;
 
 
396
 
 
 
397
return retPointer;
 
 
398
}
 
 
399
 
 
 
400
static void SaveStrategies()
 
 
401
{
 
 
402
    int i=0;
 
 
403
 
 
 
404
    for(; i < NumActiveStBlocks; i++)
 
 
405
    {
 
 
406
        STRATEGYBLOCK* sbPtr = ActiveStBlockList[i];
 
 
407
 
 
 
408
        switch(sbPtr->type)
 
 
409
        {
 
 
410
            case I_BehaviourMarinePlayer:
 
 
411
            case I_BehaviourPredatorPlayer:
 
 
412
            case I_BehaviourAlienPlayer:
 
 
413
                SaveStrategy_Player(sbPtr);
 
 
414
            break;
 
 
415
            case I_BehaviourLiftDoor:
 
 
416
                SaveStrategy_LiftDoor(sbPtr);
 
 
417
            break;
 
 
418
            case I_BehaviourProximityDoor:
 
 
419
                SaveStrategy_ProxDoor(sbPtr);
 
 
420
            break;
 
 
421
            case I_BehaviourSwitchDoor:
 
 
422
                SaveStrategy_SwitchDoor(sbPtr);
 
 
423
            break;
 
 
424
            case I_BehaviourPlatform:
 
 
425
                SaveStrategy_PlatformLift(sbPtr);
 
 
426
            break;
 
 
427
            case I_BehaviourBinarySwitch:
 
 
428
                SaveStrategy_BinarySwitch(sbPtr);
 
 
429
            break;
 
 
430
            case I_BehaviourLinkSwitch:
 
 
431
                SaveStrategy_LinkSwitch(sbPtr);
 
 
432
            break;
 
 
433
            case I_BehaviourGenerator:
 
 
434
                SaveStrategy_Generator(sbPtr);
 
 
435
            break;
 
 
436
            case I_BehaviourInanimateObject:
 
 
437
                SaveStrategy_InanimateObject(sbPtr);
 
 
438
            break;
 
 
439
            case I_BehaviourLightFX:
 
 
440
                SaveStrategy_LightFx(sbPtr);
 
 
441
            break;
 
 
442
            case I_BehaviourPlacedSound:
 
 
443
                SaveStrategy_PlacedSound(sbPtr);
 
 
444
            break;
 
 
445
            case I_BehaviourMessage:
 
 
446
                SaveStrategy_Message(sbPtr);
 
 
447
            break;
 
 
448
            case I_BehaviourMissionComplete:
 
 
449
                SaveStrategy_MissionComplete(sbPtr);
 
 
450
            break;
 
 
451
            case I_BehaviourTrackObject:
 
 
452
                SaveStrategy_TrackObject(sbPtr);
 
 
453
            break;
 
 
454
            case I_BehaviourFan:
 
 
455
                SaveStrategy_Fan(sbPtr);
 
 
456
            break;
 
 
457
            case I_BehaviourPlacedLight:
 
 
458
                SaveStrategy_PlacedLight(sbPtr);
 
 
459
            break;
 
 
460
            case I_BehaviourVideoScreen:
 
 
461
                SaveStrategy_VideoScreen(sbPtr);
 
 
462
            break;
 
 
463
            case I_BehaviourSelfDestruct:
 
 
464
                SaveStrategy_SelfDestruct(sbPtr);
 
 
465
            break;
 
 
466
            case I_BehaviourParticleGenerator:
 
 
467
                SaveStrategy_ParticleGenerator(sbPtr);
 
 
468
            break;
 
 
469
            case I_BehaviourDeathVolume:
 
 
470
                SaveStrategy_DeathVolume(sbPtr);
 
 
471
            break;
 
 
472
            case I_BehaviourAlien:
 
 
473
                   SaveStrategy_Alien(sbPtr);
 
 
474
            break;
 
 
475
            case I_BehaviourFaceHugger:
 
 
476
                   SaveStrategy_FaceHugger(sbPtr);
 
 
477
            break;
 
 
478
            case I_BehaviourMarine:
 
 
479
                   SaveStrategy_Marine(sbPtr);
 
 
480
            break;
 
 
481
            case I_BehaviourPlacedHierarchy:
 
 
482
                   SaveStrategy_PlacedHierarchy(sbPtr);
 
 
483
            break;
 
 
484
            case I_BehaviourPredator:
 
 
485
                   SaveStrategy_Predator(sbPtr);
 
 
486
            break;
 
 
487
            case I_BehaviourXenoborg:
 
 
488
                   SaveStrategy_Xenoborg(sbPtr);
 
 
489
            break;
 
 
490
            case I_BehaviourQueenAlien:
 
 
491
                   SaveStrategy_Queen(sbPtr);
 
 
492
            break;
 
 
493
            case I_BehaviourAutoGun:
 
 
494
                   SaveStrategy_Autogun(sbPtr);
 
 
495
            break;
 
 
496
            case I_BehaviourFlare:
 
 
497
                SaveStrategy_Flare(sbPtr);
 
 
498
            break;
 
 
499
            case I_BehaviourProximityGrenade:
 
 
500
                SaveStrategy_ProxGrenade(sbPtr);
 
 
501
            break;
 
 
502
            case I_BehaviourSpeargunBolt:
 
 
503
                SaveStrategy_SpearBolt(sbPtr);
 
 
504
            break;
 
 
505
            default:
 
 
506
            break;
 
 
507
        }
 
 
508
    }
 
 
509
}
 
 
510
 
 
 
511
static void EndLoadGame()
 
 
512
{
 
 
513
    if(LoadInfo.BufferStart)
 
 
514
        free(LoadInfo.BufferStart);
 
 
515
 
 
 
516
    LoadInfo.BufferStart = NULL;
 
 
517
    LoadInfo.BufferPos = NULL;
 
 
518
    LoadInfo.BufferSize = 0;
 
 
519
    LoadInfo.BufferSpaceLeft = 0;
 
 
520
}
 
 
521
 
 
 
522
static void LoadStrategy(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
523
{
 
 
524
    switch(header->bhvr_type)
 
 
525
    {
 
 
526
        case I_BehaviourMarinePlayer:
 
 
527
        case I_BehaviourPredatorPlayer:
 
 
528
        case I_BehaviourAlienPlayer:
 
 
529
            LoadStrategy_Player(header);
 
 
530
        break;
 
 
531
        case I_BehaviourLiftDoor:
 
 
532
            LoadStrategy_LiftDoor(header);
 
 
533
        break;
 
 
534
        case I_BehaviourProximityDoor:
 
 
535
            LoadStrategy_ProxDoor(header);
 
 
536
        break;
 
 
537
        case I_BehaviourSwitchDoor:
 
 
538
            LoadStrategy_SwitchDoor(header);
 
 
539
        break;
 
 
540
        case I_BehaviourPlatform:
 
 
541
            LoadStrategy_PlatformLift(header);
 
 
542
        break;
 
 
543
        case I_BehaviourBinarySwitch:
 
 
544
            LoadStrategy_BinarySwitch(header);
 
 
545
        break;
 
 
546
        case I_BehaviourLinkSwitch:
 
 
547
            LoadStrategy_LinkSwitch(header);
 
 
548
        break;
 
 
549
        case I_BehaviourGenerator:
 
 
550
            LoadStrategy_Generator(header);
 
 
551
        break;
 
 
552
        case I_BehaviourInanimateObject:
 
 
553
            LoadStrategy_InanimateObject(header);
 
 
554
        break;
 
 
555
        case I_BehaviourLightFX:
 
 
556
            LoadStrategy_LightFx(header);
 
 
557
        break;
 
 
558
        case I_BehaviourPlacedSound:
 
 
559
            LoadStrategy_PlacedSound(header);
 
 
560
        break;
 
 
561
        case I_BehaviourMessage:
 
 
562
            LoadStrategy_Message(header);
 
 
563
        break;
 
 
564
        case I_BehaviourMissionComplete:
 
 
565
            LoadStrategy_MissionComplete(header);
 
 
566
        break;
 
 
567
        case I_BehaviourTrackObject:
 
 
568
            LoadStrategy_TrackObject(header);
 
 
569
        break;
 
 
570
        case I_BehaviourFan:
 
 
571
            LoadStrategy_Fan(header);
 
 
572
        break;
 
 
573
        case I_BehaviourPlacedLight:
 
 
574
            LoadStrategy_PlacedLight(header);
 
 
575
        break;
 
 
576
        case I_BehaviourVideoScreen:
 
 
577
            LoadStrategy_VideoScreen(header);
 
 
578
        break;
 
 
579
        case I_BehaviourSelfDestruct:
 
 
580
            LoadStrategy_SelfDestruct(header);
 
 
581
        break;
 
 
582
        case I_BehaviourParticleGenerator:
 
 
583
            LoadStrategy_ParticleGenerator(header);
 
 
584
        break;
 
 
585
        case I_BehaviourDeathVolume:
 
 
586
            LoadStrategy_DeathVolume(header);
 
 
587
        break;
 
 
588
        case I_BehaviourAlien:
 
 
589
            LoadStrategy_Alien(header);
 
 
590
        break;
 
 
591
        case I_BehaviourFaceHugger:
 
 
592
               LoadStrategy_FaceHugger(header);
 
 
593
        break;
 
 
594
        case I_BehaviourMarine:
 
 
595
               LoadStrategy_Marine(header);
 
 
596
        break;
 
 
597
        case I_BehaviourPlacedHierarchy:
 
 
598
               LoadStrategy_PlacedHierarchy(header);
 
 
599
        break;
 
 
600
        case I_BehaviourPredator:
 
 
601
               LoadStrategy_Predator(header);
 
 
602
        break;
 
 
603
        case I_BehaviourXenoborg:
 
 
604
               LoadStrategy_Xenoborg(header);
 
 
605
        break;
 
 
606
        case I_BehaviourQueenAlien:
 
 
607
               LoadStrategy_Queen(header);
 
 
608
        break;
 
 
609
        case I_BehaviourAutoGun:
 
 
610
               LoadStrategy_Autogun(header);
 
 
611
        break;
 
 
612
        case I_BehaviourFlare:
 
 
613
            LoadStrategy_Flare(header);
 
 
614
        break;
 
 
615
        case I_BehaviourProximityGrenade:
 
 
616
            LoadStrategy_ProxGrenade(header);
 
 
617
        break;
 
 
618
        case I_BehaviourSpeargunBolt:
 
 
619
            LoadStrategy_SpearBolt(header);
 
 
620
        break;
 
 
621
        default:
 
 
622
        break;
 
 
623
    }
 
 
624
}
 
 
625
 
 
 
626
SAVE_BLOCK_HEADER* GetNextBlockIfOfType(SAVE_BLOCK_TYPE type)
 
 
627
{
 
 
628
    assert(LoadInfo.BufferPos);
 
 
629
 
 
 
630
    if(!LoadInfo.BufferSpaceLeft)
 
 
631
        return 0;
 
 
632
 
 
 
633
    //look at the next header in the buffer
 
 
634
    SAVE_BLOCK_HEADER* header = (SAVE_BLOCK_HEADER*) LoadInfo.BufferPos;
 
 
635
 
 
 
636
    if(header->size > LoadInfo.BufferSpaceLeft)
 
 
637
    {
 
 
638
        //oh dear, dodgy file
 
 
639
        assert("Invalid save game header size"==0);
 
 
640
        return 0;
 
 
641
    }
 
 
642
 
 
 
643
    //see if the header is of the type that we are after
 
 
644
    if(header->type == type)
 
 
645
    {
 
 
646
        //okay , advance the buffer position , and return this header
 
 
647
        LoadInfo.BufferPos += header->size;
 
 
648
        LoadInfo.BufferSpaceLeft -= header->size;
 
 
649
 
 
 
650
    return header;
 
 
651
    }
 
 
652
 
 
 
653
return 0;
 
 
654
}
 
 
655
 
 
 
656
/*------------------------------------**
 
 
657
** Loading and saving dead strategies **
 
 
658
**------------------------------------*/
 
 
659
 
 
 
660
typedef struct dead_strategy_save_block
 
 
661
{
 
 
662
    SAVE_BLOCK_HEADER header;
 
 
663
    char SBname[SB_NAME_LENGTH];
 
 
664
 
 
 
665
} DEAD_STRATEGY_SAVE_BLOCK;
 
 
666
 
 
 
667
static void SaveDeadStrategies()
 
 
668
{
 
 
669
    extern STRATEGYBLOCK FreeStBlockData[];
 
 
670
    int i;
 
 
671
    STRATEGYBLOCK* sbPtr = &FreeStBlockData[0];
 
 
672
 
 
 
673
    //search for all the strategies that existed at the start , and have been destroyed
 
 
674
    for(i=0; i < maxstblocks; i++ , sbPtr++)
 
 
675
    {
 
 
676
        if(sbPtr->destroyed_but_preserved)
 
 
677
        {
 
 
678
            DEAD_STRATEGY_SAVE_BLOCK* block;    
 
 
679
            GET_SAVE_BLOCK_POINTER(block);
 
 
680
 
 
 
681
            block->header.type = SaveBlock_DeadStrategy;
 
 
682
            block->header.size = sizeof(*block);
 
 
683
 
 
 
684
            COPY_NAME(block->SBname, sbPtr->SBname);
 
 
685
        }    
 
 
686
    }
 
 
687
}
 
 
688
 
 
 
689
static void LoadDeadStrategy(SAVE_BLOCK_HEADER* header)
 
 
690
{
 
 
691
    DEAD_STRATEGY_SAVE_BLOCK* block = (DEAD_STRATEGY_SAVE_BLOCK*) header;
 
 
692
 
 
 
693
    STRATEGYBLOCK* sbPtr = FindSBWithName(block->SBname);
 
 
694
 
 
 
695
    if(sbPtr)
 
 
696
        sbPtr->please_destroy_me = 1;
 
 
697
}
 
 
698
 
 
 
699
/*--------------------------------------------------------------------------------**
 
 
700
** Loading and saving miscellaneos global rubbish that  has nowhere else to live **
 
 
701
**--------------------------------------------------------------------------------*/
 
 
702
 
 
 
703
extern unsigned int IncrementalSBname;
 
 
704
extern int PlayersMaxHeightWhilstNotInContactWithGround;
 
 
705
 
 
 
706
typedef struct misc_global_save_block
 
 
707
{
 
 
708
    SAVE_BLOCK_HEADER header;
 
 
709
 
 
 
710
    unsigned int IncrementalSBname;
 
 
711
    AvP_GameStats CurrentGameStatistics;
 
 
712
    int PlayersMaxHeightWhilstNotInContactWithGround;
 
 
713
 
 
 
714
} MISC_GLOBAL_SAVE_BLOCK;
 
 
715
 
 
 
716
static void LoadMiscGlobalStuff(SAVE_BLOCK_HEADER* header)
 
 
717
{
 
 
718
    MISC_GLOBAL_SAVE_BLOCK* block = (MISC_GLOBAL_SAVE_BLOCK*) header;
 
 
719
 
 
 
720
    if(block->header.size == sizeof(*block))
 
 
721
    {
 
 
722
        IncrementalSBname = block->IncrementalSBname;
 
 
723
        CurrentGameStatistics = block->CurrentGameStatistics;
 
 
724
        PlayersMaxHeightWhilstNotInContactWithGround = block->PlayersMaxHeightWhilstNotInContactWithGround;
 
 
725
    }
 
 
726
}
 
 
727
 
 
 
728
static void SaveMiscGlobalStuff()
 
 
729
{
 
 
730
    MISC_GLOBAL_SAVE_BLOCK* block = GetPointerForSaveBlock(sizeof(*block));
 
 
731
 
 
 
732
    //fill in the header
 
 
733
    block->header.type = SaveBlock_MiscGlobal;
 
 
734
    block->header.size = sizeof(*block);
 
 
735
 
 
 
736
    block->IncrementalSBname = IncrementalSBname;
 
 
737
    block->CurrentGameStatistics = CurrentGameStatistics;
 
 
738
    block->PlayersMaxHeightWhilstNotInContactWithGround = PlayersMaxHeightWhilstNotInContactWithGround;
 
 
739
}
 
 
740
 
 
 
741
void LoadLevelHeader(SAVE_BLOCK_HEADER* header)
 
 
742
{
 
 
743
    LEVEL_SAVE_BLOCK* block =(LEVEL_SAVE_BLOCK*) header;
 
 
744
 
 
 
745
    if(block->header.size == sizeof(*block))
 
 
746
    {
 
 
747
        AvP.ElapsedHours = block->ElapsedTime_Hours;
 
 
748
        AvP.ElapsedMinutes = block->ElapsedTime_Minutes;
 
 
749
        AvP.ElapsedSeconds = block->ElapsedTime_Seconds;
 
 
750
        PlayerStatus.saves_left = block->NumberOfSavesLeft;
 
 
751
    }
 
 
752
}
 
 
753
 
 
 
754
static void GetHeaderInfoForSaveSlot(SAVE_SLOT_HEADER* save_slot, const GameDirectoryFile *gdf)
 
 
755
{
 
 
756
    LEVEL_SAVE_BLOCK block;
 
 
757
    unsigned int file_size;
 
 
758
    char filename[100];
 
 
759
 
 
 
760
    save_slot->SlotUsed = 0;
 
 
761
 
 
 
762
    sprintf(filename, "%s", gdf->filename);
 
 
763
    FILE *file = OpenGameFile(filename, 1, FILETYPE_CONFIG);
 
 
764
 
 
 
765
    if (file == NULL)
 
 
766
    {
 
 
767
        //failed to load (probably doesn't exist)
 
 
768
        return;
 
 
769
    }
 
 
770
 
 
 
771
    fseek(file, 0, SEEK_END);
 
 
772
    file_size = ftell(file);
 
 
773
    rewind(file);
 
 
774
 
 
 
775
    if(file_size < sizeof(LEVEL_SAVE_BLOCK))
 
 
776
    {
 
 
777
        //obviously not much of a save file then...
 
 
778
        fclose(file);
 
 
779
        return;
 
 
780
    }
 
 
781
 
 
 
782
    save_slot->TimeStamp = gdf->timestamp;
 
 
783
 
 
 
784
    //load the level header
 
 
785
    fread(&block, sizeof(block), 1, file);
 
 
786
    fclose(file);
 
 
787
 
 
 
788
    //a few checks
 
 
789
    if(block.header.type != SaveBlock_MainHeader || block.header.size != sizeof(block) || strncmp(block.AvP_Save_String,"AVPSAVE0",8))
 
 
790
    {
 
 
791
        //no good.
 
 
792
        return;
 
 
793
    }
 
 
794
 
 
 
795
    //appears to be a reasonable file
 
 
796
    save_slot->SlotUsed = 1;
 
 
797
    save_slot->player_type = block.player_type;
 
 
798
    save_slot->Episode = block.Episode;
 
 
799
    save_slot->ElapsedTime_Hours = block.ElapsedTime_Hours;
 
 
800
    save_slot->ElapsedTime_Minutes = block.ElapsedTime_Minutes;
 
 
801
    save_slot->ElapsedTime_Seconds = (block.ElapsedTime_Seconds >> 16);
 
 
802
    save_slot->Difficulty = block.Difficulty;
 
 
803
    save_slot->SavesLeft = block.NumberOfSavesLeft;
 
 
804
}
 
 
805
 
 
 
806
void ScanSaveSlots()
 
 
807
{
 
 
808
    char pattern[100];
 
 
809
 
 
 
810
    sprintf(pattern, "%s_?.sav", UserProfile.PlayerName);
 
 
811
    void *gd = OpenGameDirectory(".", pattern, FILETYPE_CONFIG);
 
 
812
 
 
 
813
    if (NULL != gd)
 
 
814
    {
 
 
815
        while (1)
 
 
816
        {
 
 
817
            GameDirectoryFile *gdf = ScanGameDirectory(gd);
 
 
818
 
 
 
819
            if(NULL == gdf)
 
 
820
                break;
 
 
821
 
 
 
822
            if ((gdf->attr & FILEATTR_DIRECTORY) || !(gdf->attr & FILEATTR_READABLE))
 
 
823
                continue;
 
 
824
 
 
 
825
            char *ptr = strrchr(gdf->filename, '.');
 
 
826
 
 
 
827
            if (ptr == NULL)
 
 
828
                continue;
 
 
829
 
 
 
830
            ptr--;
 
 
831
 
 
 
832
            int i = *ptr - '1';
 
 
833
 
 
 
834
            if (i >= 0 && (i < NUMBER_OF_SAVE_SLOTS))
 
 
835
                GetHeaderInfoForSaveSlot(&SaveGameSlot[i], gdf);
 
 
836
        }
 
 
837
    }
 
 
838
}
 
 
839
 
 
 
840
int LoadGameRequest = SAVELOAD_REQUEST_NONE; //slot number of game to be loaded
 
 
841
 
 
 
842
int LoadSavedGame()
 
 
843
{
 
 
844
    char filename[100];
 
 
845
    int terminal_error = 0;
 
 
846
 
 
 
847
        if(SAVELOAD_REQUEST_NONE == LoadGameRequest)
 
 
848
        return 0;
 
 
849
 
 
 
850
    sprintf(filename, "%s_%d.sav", UserProfile.PlayerName, LoadGameRequest+1);
 
 
851
    LoadGameRequest = SAVELOAD_REQUEST_NONE;
 
 
852
 
 
 
853
{
 
 
854
    FILE *file = OpenGameFile(filename, 1, FILETYPE_CONFIG);
 
 
855
 
 
 
856
    if(file == NULL)
 
 
857
    {
 
 
858
        EndLoadGame();
 
 
859
        return 1;
 
 
860
    }
 
 
861
 
 
 
862
    fseek(file, 0, SEEK_END);
 
 
863
    LoadInfo.BufferSize = ftell(file);
 
 
864
    rewind(file);
 
 
865
 
 
 
866
       if(!LoadInfo.BufferSize)
 
 
867
    {
 
 
868
        fclose(file);
 
 
869
        EndLoadGame();
 
 
870
        return 1;
 
 
871
    }
 
 
872
 
 
 
873
    //allocate buffer , and read file into memory
 
 
874
    LoadInfo.BufferStart = malloc(LoadInfo.BufferSize);
 
 
875
    fread(LoadInfo.BufferStart, LoadInfo.BufferSize, 1, file);
 
 
876
    fclose(file);
 
 
877
}
 
 
878
    LoadInfo.BufferPos = LoadInfo.BufferStart;
 
 
879
    LoadInfo.BufferSpaceLeft = LoadInfo.BufferSize;
 
 
880
 
 
 
881
    // attempt to access level header    
 
 
882
    {
 
 
883
        //read the next header
 
 
884
        SAVE_BLOCK_HEADER* header = (SAVE_BLOCK_HEADER*) LoadInfo.BufferPos;
 
 
885
 
 
 
886
        if(header->size > LoadInfo.BufferSpaceLeft)
 
 
887
        {
 
 
888
            //oh dear, dodgy file
 
 
889
            assert("Invalid save game header size"==0);
 
 
890
            terminal_error = 1;
 
 
891
        }
 
 
892
        else
 
 
893
        {
 
 
894
            //go to the next header
 
 
895
            LoadInfo.BufferPos += header->size;
 
 
896
            LoadInfo.BufferSpaceLeft -= header->size;
 
 
897
 
 
 
898
            switch(header->type)
 
 
899
            {
 
 
900
                case SaveBlock_MainHeader :
 
 
901
                    LoadLevelHeader(header);
 
 
902
                    break;
 
 
903
                default:
 
 
904
                    assert("Unrecognized save block type"==0);
 
 
905
                    terminal_error = 1;
 
 
906
            }
 
 
907
        }
 
 
908
    }
 
 
909
 
 
 
910
    //go through loading things
 
 
911
    while(LoadInfo.BufferSpaceLeft && !terminal_error)
 
 
912
    {
 
 
913
        //read the next header
 
 
914
        SAVE_BLOCK_HEADER* header = (SAVE_BLOCK_HEADER*) LoadInfo.BufferPos;
 
 
915
 
 
 
916
        if(header->size > LoadInfo.BufferSpaceLeft)
 
 
917
        {
 
 
918
            //oh dear, dodgy file
 
 
919
            assert("Invalid save game header size"==0);
 
 
920
            terminal_error = 1;
 
 
921
            break;
 
 
922
        }
 
 
923
 
 
 
924
        //go to the next header
 
 
925
        LoadInfo.BufferPos += header->size;
 
 
926
        LoadInfo.BufferSpaceLeft -= header->size;
 
 
927
 
 
 
928
        switch(header->type)
 
 
929
        {
 
 
930
            case SaveBlock_MainHeader:
 
 
931
                LoadLevelHeader(header);
 
 
932
            break;
 
 
933
            case SaveBlock_DeadStrategy:
 
 
934
                LoadDeadStrategy(header);
 
 
935
            break;
 
 
936
            case SaveBlock_Strategy:
 
 
937
                LoadStrategy((SAVE_BLOCK_STRATEGY_HEADER*) header);
 
 
938
            break;
 
 
939
            case SaveBlock_Track:
 
 
940
                //all these should be used up by the various strategy loaders
 
 
941
                assert("Unexpected track save block"==0);
 
 
942
            break;
 
 
943
            case SaveBlock_Hierarchy:
 
 
944
                //all these should be used up by the various strategy loaders
 
 
945
                //assert("Unexpected hierarchy save block"==0);
 
 
946
            break;
 
 
947
            case SaveBlock_HierarchySection:
 
 
948
                //all these should be used up by the various strategy loaders
 
 
949
                //assert("Unexpected hierarchy section save block"==0);
 
 
950
            break;
 
 
951
            case SaveBlock_HierarchyTween:
 
 
952
                //all these should be used up by the various strategy loaders
 
 
953
                assert("Unexpected hierarchy tween save block"==0);
 
 
954
            break;
 
 
955
            case SaveBlock_HierarchyDecals:
 
 
956
                //all these should be used up by the various strategy loaders
 
 
957
                //assert("Unexpected hierarchy decal save block"==0);
 
 
958
            break;
 
 
959
            case SaveBlock_HierarchyDelta:
 
 
960
                //all these should be used up by the various strategy loaders
 
 
961
                //assert("Unexpected hierarchy delta save block"==0);
 
 
962
            break;
 
 
963
            case SaveBlock_GlobalHive:
 
 
964
                LoadHiveSettings(header);
 
 
965
            break;
 
 
966
            case SaveBlock_MiscGlobal:
 
 
967
                LoadMiscGlobalStuff(header);
 
 
968
            break;
 
 
969
            case SaveBlock_MarineSquad:
 
 
970
                LoadMarineSquadState(header);
 
 
971
            break;
 
 
972
            case SaveBlock_Particles:
 
 
973
                Load_Particles(header);
 
 
974
            break;
 
 
975
            case SaveBlock_Decals:
 
 
976
                Load_Decals(header);
 
 
977
            break;
 
 
978
            case SaveBlock_PheromoneTrail:
 
 
979
                Load_PheromoneTrails(header);
 
 
980
            break;
 
 
981
            case SaveBlock_VolumetricExplosions:
 
 
982
                Load_VolumetricExplosions(header);
 
 
983
            break;
 
 
984
            case SaveBlock_LightElements:
 
 
985
                Load_LightElements(header);
 
 
986
            break;
 
 
987
            case SaveBlock_MessageHistory:
 
 
988
            break;
 
 
989
            case SaveBlock_WeaponsCGlobals:
 
 
990
                Load_WeaponsCGlobals(header);
 
 
991
            break;
 
 
992
            case SaveBlock_SoundState:
 
 
993
                Load_SoundState_NoRef(header);
 
 
994
            break;
 
 
995
            default :
 
 
996
                assert("Unrecognized save block type"==0);
 
 
997
                terminal_error = 1;
 
 
998
        }
 
 
999
    }
 
 
1000
 
 
 
1001
    if(terminal_error)
 
 
1002
    {
 
 
1003
        //the save file was screwed , restart the level to be on the safe side
 
 
1004
        puts("Error: save file is corrupt.");
 
 
1005
        return 1;
 
 
1006
    }
 
 
1007
 
 
 
1008
    EndLoadGame();
 
 
1009
 
 
 
1010
    //make sure all the containing modules are set properly
 
 
1011
    {
 
 
1012
        int sbIndex = 0;
 
 
1013
        // loop thro' the strategy block list, looking for objects that need to have their visibilities managed ...
 
 
1014
        while(sbIndex < NumActiveStBlocks)
 
 
1015
        {       
 
 
1016
            STRATEGYBLOCK *sbPtr = ActiveStBlockList[sbIndex++];
 
 
1017
 
 
 
1018
            if(sbPtr->maintainVisibility && sbPtr->DynPtr)
 
 
1019
            {
 
 
1020
                MODULE* newModule = ModuleFromPosition(&sbPtr->DynPtr->Position, sbPtr->containingModule);                              
 
 
1021
 
 
 
1022
                if(newModule)
 
 
1023
                    sbPtr->containingModule = newModule;
 
 
1024
            }
 
 
1025
        }
 
 
1026
    }
 
 
1027
 
 
 
1028
    UserProfile.active_bonus = CHEATMODE_NONACTIVE;
 
 
1029
    return 0;
 
 
1030
}
 
 
1031
 
 
 
1032
extern int episode_to_play;
 
 
1033
 
 
 
1034
void SaveLevelHeader()
 
 
1035
{
 
 
1036
    LEVEL_SAVE_BLOCK* block = (LEVEL_SAVE_BLOCK*) GetPointerForSaveBlock(sizeof(LEVEL_SAVE_BLOCK));
 
 
1037
 
 
 
1038
    //fill in the header
 
 
1039
    block->header.type = SaveBlock_MainHeader;
 
 
1040
    block->header.size = sizeof(*block);
 
 
1041
 
 
 
1042
    //fill in the main block
 
 
1043
    strncpy(block->AvP_Save_String, "AVPSAVE0", 8);
 
 
1044
 
 
 
1045
    block->player_type = AvP.PlayerType;
 
 
1046
    block->Episode = episode_to_play;
 
 
1047
    block->ElapsedTime_Hours = AvP.ElapsedHours;
 
 
1048
    block->ElapsedTime_Minutes = AvP.ElapsedMinutes;
 
 
1049
    block->ElapsedTime_Seconds = AvP.ElapsedSeconds;
 
 
1050
    block->Difficulty = AvP.Difficulty;
 
 
1051
    block->NumberOfSavesLeft = --PlayerStatus.saves_left;
 
 
1052
}
 
 
1053
 
 
 
1054
void SaveGame(int slot)
 
 
1055
{
 
 
1056
    char filename[100];
 
 
1057
 
 
 
1058
    sprintf(filename, "%s_%d.sav", UserProfile.PlayerName, slot+1);
 
 
1059
 
 
 
1060
    FILE *file = OpenGameFile(filename, 0, FILETYPE_CONFIG);
 
 
1061
 
 
 
1062
    if (file == NULL)
 
 
1063
    {
 
 
1064
        printf("Error saving file\n");
 
 
1065
        return;
 
 
1066
    }
 
 
1067
 
 
 
1068
    SaveInfo.BufferPos = SaveInfo.BufferStart;
 
 
1069
    SaveInfo.BufferSpaceLeft = SaveInfo.BufferSize;
 
 
1070
    SaveInfo.BufferSpaceUsed = 0;
 
 
1071
 
 
 
1072
    SaveLevelHeader();
 
 
1073
 
 
 
1074
    SaveDeadStrategies();
 
 
1075
    SaveStrategies();
 
 
1076
    SaveHiveSettings();
 
 
1077
    SaveMarineSquadState();
 
 
1078
    SaveMiscGlobalStuff();
 
 
1079
    Save_SoundsWithNoReference();
 
 
1080
    Save_Decals();
 
 
1081
    Save_Particles();
 
 
1082
    Save_VolumetricExplosions();
 
 
1083
    Save_PheromoneTrails();
 
 
1084
    Save_LightElements();
 
 
1085
    Save_WeaponsCGlobals();
 
 
1086
 
 
 
1087
    fwrite(SaveInfo.BufferStart, SaveInfo.BufferSpaceUsed, 1, file);
 
 
1088
 
 
 
1089
    fclose(file);
 
 
1090
}
 
 
1091
 
 
 
1092
int safetosave()
 
 
1093
{
 
 
1094
    int a;
 
 
1095
    DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr;
 
 
1096
 
 
 
1097
    if(!(dynPtr->IsInContactWithFloor || dynPtr->IsInContactWithNearlyFlatFloor))
 
 
1098
        return 0;
 
 
1099
 
 
 
1100
    for (a=0; a < NumActiveStBlocks; a++)
 
 
1101
    {
 
 
1102
        STRATEGYBLOCK *candidate = ActiveStBlockList[a];
 
 
1103
 
 
 
1104
        switch(candidate->type)
 
 
1105
        {
 
 
1106
            case I_BehaviourSpeargunBolt:
 
 
1107
            {
 
 
1108
                SPEAR_BEHAV_BLOCK *bbPtr = (SPEAR_BEHAV_BLOCK *)candidate->dataptr;
 
 
1109
 
 
 
1110
                if(!bbPtr->Stuck)
 
 
1111
                return 0;
 
 
1112
            }
 
 
1113
            break;
 
 
1114
            case I_BehaviourProximityGrenade:
 
 
1115
            {
 
 
1116
                PROX_GRENADE_BEHAV_BLOCK *bbPtr = (PROX_GRENADE_BEHAV_BLOCK *)candidate->dataptr;
 
 
1117
                DYNAMICSBLOCK *dynPtr = candidate->DynPtr;
 
 
1118
 
 
 
1119
                if(!dynPtr->IsStatic)
 
 
1120
                return 0;
 
 
1121
            }
 
 
1122
            break;
 
 
1123
            case I_BehaviourAutoGun:
 
 
1124
            {
 
 
1125
                AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(candidate->dataptr);
 
 
1126
 
 
 
1127
                if((NULL != agunStatusPointer->Target) || agunStatusPointer->Firing)
 
 
1128
                    return 0;
 
 
1129
            }
 
 
1130
            break;
 
 
1131
            case I_BehaviourMessage:
 
 
1132
            {
 
 
1133
                //MESSAGE_BEHAV_BLOCK* m_bhv = malloc(sizeof(MESSAGE_BEHAV_BLOCK));
 
 
1134
                //if(m_bhv->active) return 0;
 
 
1135
            }
 
 
1136
            break;
 
 
1137
            case I_BehaviourFrisbee:
 
 
1138
            case I_BehaviourFrisbeeEnergyBolt:
 
 
1139
            case I_BehaviourCorpse:
 
 
1140
            case I_BehaviourPredatorDisc_SeekTrack:
 
 
1141
            case I_BehaviourGrapplingHook:
 
 
1142
            case I_BehaviourHierarchicalFragment:
 
 
1143
            case I_BehaviourFragment:
 
 
1144
            case I_BehaviourRocket:
 
 
1145
            case I_BehaviourPPPlasmaBolt:
 
 
1146
            case I_BehaviourPredatorEnergyBolt:
 
 
1147
            case I_BehaviourPulseGrenade:
 
 
1148
            case I_BehaviourGrenade:
 
 
1149
            case I_BehaviourFragmentationGrenade:
 
 
1150
            case I_BehaviourMolotov:
 
 
1151
            case I_BehaviourSelfDestruct:
 
 
1152
                return 0;
 
 
1153
            case I_BehaviourAlien:
 
 
1154
            case I_BehaviourQueenAlien:
 
 
1155
            case I_BehaviourFaceHugger:
 
 
1156
            case I_BehaviourPredator:
 
 
1157
            case I_BehaviourXenoborg:
 
 
1158
            case I_BehaviourMarine:
 
 
1159
            case I_BehaviourNetGhost:
 
 
1160
            case I_BehaviourMissionComplete:
 
 
1161
        //case I_BehaviourPowerCable:
 
 
1162
            //case I_BehaviourDormantPredator:
 
 
1163
            case I_BehaviourDeathVolume:
 
 
1164
            //case I_BehaviourDummy:
 
 
1165
            {
 
 
1166
                if(NULL != candidate->DisplayBlock)
 
 
1167
                    return 0;
 
 
1168
 
 
 
1169
            }
 
 
1170
            default:
 
 
1171
            break;
 
 
1172
        }
 
 
1173
 
 
 
1174
    }
 
 
1175
 
 
 
1176
return 1;
 
 
1177
}