4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "system.h"
 
 
2
#include "stratdef.h"
 
 
3
#include "bh_types.h"
 
 
4
#include "lighting.h"
 
 
5
#include "dynamics.h"
 
 
6
#include <stdio.h>
 
 
7
#include <assert.h>
 
 
8
#include "sfx.h"
 
 
9
 
 
 
10
#define MAX_NO_OF_LIGHTELEMENTS 500
 
 
11
 
 
 
12
extern int CloakingPhase;
 
 
13
extern int NumActiveBlocks;
 
 
14
extern DISPLAYBLOCK *ActiveBlockList[];
 
 
15
extern EULER HeadOrientation;
 
 
16
 
 
 
17
static VECTORCH RotatingLightPosition;
 
 
18
LIGHTELEMENT LightElementStorage[MAX_NO_OF_LIGHTELEMENTS];
 
 
19
static int LightScale = ONE_FIXED;
 
 
20
 
 
 
21
int NumActiveLightElements;
 
 
22
 
 
 
23
void AddLightingEffectToObject(DISPLAYBLOCK *objectPtr, enum LIGHTING_EFFECTS_ID lfxID)
 
 
24
{
 
 
25
    LIGHTBLOCK *lightPtr = AddLightBlock(objectPtr, NULL);
 
 
26
 
 
 
27
    if (NULL == lightPtr)
 
 
28
        return;
 
 
29
 
 
 
30
    switch(lfxID)
 
 
31
    {
 
 
32
        case LFX_EXPLOSION:
 
 
33
        {
 
 
34
            lightPtr->LightBright = ONE_FIXED*4;
 
 
35
            lightPtr->LightFlags = 0;
 
 
36
            lightPtr->LightRange = EXPLOSION_LIGHT_RANGE; 
 
 
37
            lightPtr->RedScale = 255 * 256;
 
 
38
            lightPtr->RedScale = 5 * 56;
 
 
39
            lightPtr->GreenScale = 220 * 256;
 
 
40
            lightPtr->BlueScale = 0;
 
 
41
        }
 
 
42
        break;
 
 
43
        case LFX_BIGEXPLOSION:
 
 
44
        {
 
 
45
            lightPtr->LightBright = ONE_FIXED << 2;
 
 
46
            lightPtr->LightFlags = 0;
 
 
47
            lightPtr->LightRange = EXPLOSION_LIGHT_RANGE; 
 
 
48
            lightPtr->RedScale = 255 * 256;
 
 
49
            lightPtr->GreenScale = 120*  256;
 
 
50
            lightPtr->BlueScale = 0;
 
 
51
        }
 
 
52
        break;
 
 
53
        case LFX_MUZZLEFLASH:
 
 
54
        {
 
 
55
            lightPtr->LightBright = 65536 - (FastRandom()&32767);
 
 
56
            lightPtr->LightFlags = LFlag_Deallocate;
 
 
57
            //lightPtr->LightRange = 10000; /* ? */
 
 
58
            lightPtr->LightRange = 20000; /* ? */
 
 
59
            lightPtr->RedScale = 255 * 256;
 
 
60
            lightPtr->GreenScale = 230 * 256;
 
 
61
            lightPtr->BlueScale = 200 * 256;
 
 
62
        }
 
 
63
        break;
 
 
64
        case LFX_ROCKETJET:
 
 
65
        {
 
 
66
            lightPtr->LightBright = ONE_FIXED*3/4;
 
 
67
            lightPtr->LightFlags = 0;
 
 
68
            lightPtr->LightRange = 5000; /* ? */
 
 
69
            lightPtr->RedScale = 255 * 256;
 
 
70
            lightPtr->GreenScale = 255 * 256;
 
 
71
            lightPtr->BlueScale= 128 * 256;
 
 
72
        }
 
 
73
        break;
 
 
74
        case LFX_FLARE:
 
 
75
        {
 
 
76
            lightPtr->LightBright = 0;
 
 
77
            lightPtr->LightFlags = 0;
 
 
78
            lightPtr->LightRange = 10000; /* ? */
 
 
79
            lightPtr->RedScale = 255 * 256;
 
 
80
            lightPtr->GreenScale = 200 * 256;
 
 
81
            lightPtr->BlueScale = 255 * 256;
 
 
82
        }
 
 
83
        break;
 
 
84
        case LFX_XENO_FIRING:
 
 
85
        {
 
 
86
            lightPtr->LightBright = 226100;
 
 
87
            lightPtr->LightFlags = LFlag_Deallocate;
 
 
88
            lightPtr->LightRange = 5000; /* ? */
 
 
89
            lightPtr->RedScale = 255 * 256;
 
 
90
            lightPtr->GreenScale = 64 * 256;
 
 
91
            lightPtr->BlueScale=255 * 256;
 
 
92
        }
 
 
93
        break;
 
 
94
        case LFX_PLASMA_BOLT:
 
 
95
        {
 
 
96
            lightPtr->LightBright = ONE_FIXED/4;
 
 
97
            lightPtr->LightFlags = 0;
 
 
98
            lightPtr->LightRange = 10000;
 
 
99
            lightPtr->RedScale = 200 * 256;
 
 
100
            lightPtr->GreenScale = 255 * 256;
 
 
101
            lightPtr->BlueScale = 255 * 256;
 
 
102
        }
 
 
103
        break;
 
 
104
        case LFX_OBJECTONFIRE:
 
 
105
        {
 
 
106
            lightPtr->LightBright = 16484 - (FastRandom()&4095);
 
 
107
            lightPtr->LightFlags = LFlag_Deallocate | LFlag_Thermal;
 
 
108
            lightPtr->LightRange = 10000;
 
 
109
            lightPtr->RedScale = 255*256;
 
 
110
            lightPtr->GreenScale = 110 * 256;
 
 
111
            lightPtr->BlueScale = 50* 256;
 
 
112
        }
 
 
113
    }
 
 
114
}
 
 
115
 
 
 
116
static LIGHTELEMENT* AllocateLightElement()
 
 
117
{
 
 
118
    return (NumActiveLightElements < MAX_NO_OF_LIGHTELEMENTS) ? &LightElementStorage[NumActiveLightElements++] : NULL;
 
 
119
}
 
 
120
 
 
 
121
void MakeLightElement(const VECTORCH *positionPtr, enum LIGHTELEMENT_BEHAVIOUR_ID behaviourID)
 
 
122
{
 
 
123
    LIGHTELEMENT *lightElementPtr = AllocateLightElement();
 
 
124
 
 
 
125
    if (NULL != lightElementPtr)
 
 
126
    {
 
 
127
        LIGHTBLOCK *lightPtr = &lightElementPtr->LightBlock;
 
 
128
        lightElementPtr->BehaviourID = behaviourID;
 
 
129
        lightElementPtr->LightBlock.LightWorld = *positionPtr;
 
 
130
        lightElementPtr->LifeTime = ONE_FIXED;
 
 
131
        lightPtr->LightFlags = 0;
 
 
132
 
 
 
133
        switch (behaviourID)
 
 
134
        {
 
 
135
            case LIGHTELEMENT_ROTATING:
 
 
136
                RotatingLightPosition = *positionPtr;
 
 
137
            break;
 
 
138
            case LIGHTELEMENT_ALIEN_TEETH:
 
 
139
            {
 
 
140
                lightPtr->LightBright = ONE_FIXED/2;
 
 
141
                lightPtr->LightRange = 200; 
 
 
142
                lightPtr->RedScale = lightPtr->GreenScale = lightPtr->BlueScale = ONE_FIXED;
 
 
143
 
 
 
144
                {
 
 
145
                    VECTORCH position;
 
 
146
                    position.vx = MUL_FIXED(200,GetSin((CloakingPhase)&4095));
 
 
147
                    position.vy = MUL_FIXED(200,GetCos((CloakingPhase)&4095));
 
 
148
                    position.vz = 80+MUL_FIXED(50,GetCos((CloakingPhase/2)&4095));
 
 
149
                    {
 
 
150
                        MATRIXCH myMat = Global_VDB.VDB_Mat;
 
 
151
                        TransposeMatrixCH(&myMat);
 
 
152
                        RotateVector(&position, &myMat);    
 
 
153
                        position.vx += Global_VDB.VDB_World.vx;
 
 
154
                        position.vy += Global_VDB.VDB_World.vy;
 
 
155
                        position.vz += Global_VDB.VDB_World.vz;
 
 
156
                    }
 
 
157
 
 
 
158
                    lightElementPtr->LightBlock.LightWorld = position;
 
 
159
                }
 
 
160
 
 
 
161
                lightElementPtr->LifeTime = 0;
 
 
162
            }
 
 
163
            break;
 
 
164
            case LIGHTELEMENT_ALIEN_TEETH2:
 
 
165
            {
 
 
166
                lightPtr->LightBright = ONE_FIXED/2;
 
 
167
                lightPtr->LightRange = 200; 
 
 
168
                lightPtr->RedScale = lightPtr->GreenScale = lightPtr->BlueScale = ONE_FIXED;
 
 
169
 
 
 
170
                {
 
 
171
                    VECTORCH position;
 
 
172
                    position.vx = MUL_FIXED(200,GetSin((CloakingPhase/3+2048)&4095));
 
 
173
                    position.vy = MUL_FIXED(200,GetCos((CloakingPhase/3+2048)&4095));
 
 
174
                    position.vz = 80+MUL_FIXED(50,GetCos((CloakingPhase/2+2048)&4095));
 
 
175
                    {
 
 
176
                        MATRIXCH myMat = Global_VDB.VDB_Mat;
 
 
177
                        TransposeMatrixCH(&myMat);
 
 
178
                        RotateVector(&position, &myMat);    
 
 
179
                        position.vx += Global_VDB.VDB_World.vx;
 
 
180
                        position.vy += Global_VDB.VDB_World.vy;
 
 
181
                        position.vz += Global_VDB.VDB_World.vz;
 
 
182
                    }
 
 
183
 
 
 
184
                    lightElementPtr->LightBlock.LightWorld = position;
 
 
185
                }
 
 
186
 
 
 
187
                lightElementPtr->LifeTime = 0;
 
 
188
            }
 
 
189
            default:
 
 
190
            break;
 
 
191
        }
 
 
192
    }
 
 
193
}
 
 
194
 
 
 
195
void UpdateRunTimeLights()
 
 
196
{
 
 
197
    int i,j;
 
 
198
 
 
 
199
    for(i=0; i < NumActiveBlocks; i++)
 
 
200
    {
 
 
201
        DISPLAYBLOCK *dptr = ActiveBlockList[i];
 
 
202
 
 
 
203
        if( (dptr->SpecialFXFlags & SFXFLAG_ONFIRE) || ( dptr->ObStrategyBlock && dptr->ObStrategyBlock->DamageBlock.IsOnFire) )
 
 
204
            AddLightingEffectToObject(dptr, LFX_OBJECTONFIRE);
 
 
205
 
 
 
206
        for(j = 0; j < dptr->ObNumLights; j++)
 
 
207
        {
 
 
208
            LIGHTBLOCK *lptr = dptr->ObLights[j];
 
 
209
 
 
 
210
            /* Calculate the light's location */
 
 
211
            if(!(lptr->LightFlags & LFlag_AbsPos))
 
 
212
                lptr->LightWorld = dptr->ObWorld;
 
 
213
 
 
 
214
            assert(lptr->LightRange != 0);
 
 
215
            lptr->BrightnessOverRange = DIV_FIXED(MUL_FIXED(lptr->LightBright, LightScale), lptr->LightRange);
 
 
216
        }
 
 
217
    }
 
 
218
 
 
 
219
    i = NumActiveLightElements;
 
 
220
    LIGHTELEMENT *lightElementPtr = LightElementStorage;
 
 
221
 
 
 
222
    while(i--)
 
 
223
    {
 
 
224
        LIGHTBLOCK *lightPtr = &lightElementPtr->LightBlock;
 
 
225
 
 
 
226
        switch(lightElementPtr->BehaviourID)
 
 
227
        {
 
 
228
            case LIGHTELEMENT_MOLTENMETAL:
 
 
229
            {
 
 
230
                lightPtr->LightBright = ONE_FIXED/4;
 
 
231
                //lightPtr->LightFlags;
 
 
232
                lightPtr->LightRange = EXPLOSION_LIGHT_RANGE; 
 
 
233
                lightPtr->RedScale = 255 * 256;
 
 
234
                lightPtr->GreenScale = 120 * 256;
 
 
235
                lightPtr->BlueScale = 0;
 
 
236
            }
 
 
237
            break;
 
 
238
            case LIGHTELEMENT_PLASMACASTERHIT:
 
 
239
            {
 
 
240
                //lightPtr->LightFlags;
 
 
241
                lightPtr->LightRange = EXPLOSION_LIGHT_RANGE; 
 
 
242
 
 
 
243
                if (lightElementPtr->LifeTime == ONE_FIXED)
 
 
244
                {
 
 
245
                    lightPtr->LightBright = ONE_FIXED*4;
 
 
246
                    lightPtr->RedScale = 0; //0 * 256;
 
 
247
                    lightPtr->GreenScale = 255 * 256;
 
 
248
                    lightPtr->BlueScale = 255 * 256;
 
 
249
                }
 
 
250
                else
 
 
251
                {
 
 
252
                    lightPtr->LightBright = lightElementPtr->LifeTime / 2;
 
 
253
                    lightPtr->LightRange = 1 + MUL_FIXED(EXPLOSION_LIGHT_RANGE, lightElementPtr->LifeTime);
 
 
254
                    lightPtr->RedScale = 255 * 256;
 
 
255
                    lightPtr->GreenScale = 120 * 256;
 
 
256
                    lightPtr->BlueScale = 0; //0 * 256;
 
 
257
                }
 
 
258
 
 
 
259
                lightElementPtr->LifeTime -= NormalFrameTime *4;
 
 
260
            }
 
 
261
            break;
 
 
262
            case LIGHTELEMENT_FROMFMV:
 
 
263
            {                         
 
 
264
                extern int FmvColourRed;
 
 
265
                extern int FmvColourGreen;
 
 
266
                extern int FmvColourBlue;
 
 
267
 
 
 
268
                lightPtr->LightBright = ONE_FIXED*4;
 
 
269
                //lightPtr->LightFlags;
 
 
270
                lightPtr->LightRange = 15000; 
 
 
271
 
 
 
272
                lightPtr->RedScale = FmvColourRed;
 
 
273
                lightPtr->GreenScale = FmvColourGreen;
 
 
274
                lightPtr->BlueScale = FmvColourBlue;
 
 
275
            }
 
 
276
            break;
 
 
277
            case LIGHTELEMENT_EXPLOSION:
 
 
278
            {
 
 
279
                //lightPtr->LightFlags;
 
 
280
                //lightPtr->RedScale = 255 * 256;
 
 
281
                lightPtr->RedScale = 155 * 256;
 
 
282
                lightPtr->GreenScale = 120 * 256;
 
 
283
                lightPtr->BlueScale = 0;
 
 
284
 
 
 
285
                {
 
 
286
                    int scale = lightElementPtr->LifeTime * 4;
 
 
287
 
 
 
288
                    if (scale < ONE_FIXED)
 
 
289
                    {
 
 
290
                        lightPtr->LightRange = 1 + MUL_FIXED(EXPLOSION_LIGHT_RANGE, scale);
 
 
291
                        lightPtr->LightBright = scale * 8;
 
 
292
                    }
 
 
293
                    else 
 
 
294
                    {
 
 
295
                        lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;
 
 
296
                        lightPtr->LightBright = ONE_FIXED*8;
 
 
297
                    }
 
 
298
                }
 
 
299
 
 
 
300
                if (PlayerStatus.Alive)
 
 
301
                {
 
 
302
                    VECTORCH d = lightElementPtr->LightBlock.LightWorld;
 
 
303
                    d.vx -= Global_VDB.VDB_World.vx;
 
 
304
                    d.vy -= Global_VDB.VDB_World.vy;
 
 
305
                    d.vz -= Global_VDB.VDB_World.vz;
 
 
306
                    int m = Approximate3dMagnitude(&d);
 
 
307
 
 
 
308
                    if (m < ONE_FIXED)
 
 
309
                    {
 
 
310
                        int maxTilt = MUL_FIXED((ONE_FIXED - m) >> 9, lightElementPtr->LifeTime); 
 
 
311
                        int halfTilt = maxTilt / 2;
 
 
312
 
 
 
313
                        if (maxTilt)
 
 
314
                        {
 
 
315
                            HeadOrientation.EulerX = (FastRandom() % maxTilt) - halfTilt;
 
 
316
                            HeadOrientation.EulerY = (FastRandom() % maxTilt) - halfTilt;
 
 
317
                            HeadOrientation.EulerZ = (FastRandom() % maxTilt) - halfTilt;
 
 
318
 
 
 
319
                            if (HeadOrientation.EulerX < 0)
 
 
320
                                HeadOrientation.EulerX += 4096;
 
 
321
 
 
 
322
                            if (HeadOrientation.EulerY < 0)
 
 
323
                                HeadOrientation.EulerY += 4096;
 
 
324
 
 
 
325
                            if (HeadOrientation.EulerZ < 0)
 
 
326
                                HeadOrientation.EulerZ += 4096;
 
 
327
                        }
 
 
328
                    }
 
 
329
                }
 
 
330
 
 
 
331
                lightElementPtr->LifeTime -= NormalFrameTime;
 
 
332
            }
 
 
333
            break;
 
 
334
            case LIGHTELEMENT_ELECTRICAL_EXPLOSION:
 
 
335
            {
 
 
336
                int scale = ONE_FIXED*5/4-lightElementPtr->LifeTime;
 
 
337
 
 
 
338
                lightPtr->LightFlags = LFlag_Electrical;
 
 
339
 
 
 
340
                if (scale > 65536)
 
 
341
                    scale = 65536;
 
 
342
 
 
 
343
                scale = ONE_FIXED - scale;
 
 
344
 
 
 
345
                lightPtr->RedScale = scale;
 
 
346
                lightPtr->GreenScale = ONE_FIXED;
 
 
347
                lightPtr->BlueScale = ONE_FIXED;
 
 
348
                lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;// 1+MUL_FIXED(EXPLOSION_LIGHT_RANGE,scale);
 
 
349
                lightPtr->LightBright = scale*16;
 
 
350
 
 
 
351
                lightElementPtr->LifeTime -= NormalFrameTime;
 
 
352
            }
 
 
353
            break;
 
 
354
            case LIGHTELEMENT_ELECTRICAL_SPARKS:
 
 
355
            {
 
 
356
                int scale = lightElementPtr->LifeTime;
 
 
357
 
 
 
358
                lightPtr->LightFlags = LFlag_Electrical;
 
 
359
 
 
 
360
                if (scale == ONE_FIXED)
 
 
361
                {
 
 
362
                    lightPtr->RedScale = ONE_FIXED;
 
 
363
                    lightPtr->GreenScale = ONE_FIXED;
 
 
364
                    lightPtr->BlueScale = ONE_FIXED;
 
 
365
                }
 
 
366
                else
 
 
367
                {
 
 
368
                    lightPtr->RedScale = 0;
 
 
369
                    lightPtr->GreenScale = scale/2;
 
 
370
                    lightPtr->BlueScale = scale;
 
 
371
                }
 
 
372
                lightPtr->LightRange = 4000;// 1+MUL_FIXED(EXPLOSION_LIGHT_RANGE,scale);
 
 
373
                lightPtr->LightBright = scale;
 
 
374
 
 
 
375
                lightElementPtr->LifeTime -= NormalFrameTime * 2;
 
 
376
            }
 
 
377
            break;
 
 
378
            case LIGHTELEMENT_ROTATING:
 
 
379
            {
 
 
380
                lightPtr->LightBright = ONE_FIXED/2;
 
 
381
                //lightPtr->LightFlags;
 
 
382
                lightPtr->LightRange = 10000; 
 
 
383
 
 
 
384
                lightPtr->RedScale = ONE_FIXED;
 
 
385
                lightPtr->GreenScale = ONE_FIXED;
 
 
386
                lightPtr->BlueScale =  ONE_FIXED;
 
 
387
 
 
 
388
                lightElementPtr->LightBlock.LightWorld = PlayerStatus.DisplayBlock->ObWorld;//RotatingLightPosition;
 
 
389
                lightElementPtr->LightBlock.LightWorld.vy -= 2200;                      
 
 
390
            }
 
 
391
            break;
 
 
392
            case LIGHTELEMENT_PARGEN_FLAME:
 
 
393
            {
 
 
394
                if(lightElementPtr->LifeTime == ONE_FIXED)
 
 
395
                {
 
 
396
                    lightElementPtr->LifeTime = 1;
 
 
397
 
 
 
398
                    //lightPtr->LightFlags;
 
 
399
                    //lightPtr->RedScale=      255*256;
 
 
400
                    //lightPtr->GreenScale= 120*256;
 
 
401
                    lightPtr->RedScale=      255*(200+(CloakingPhase%56));
 
 
402
                    lightPtr->GreenScale= 120*(200+((CloakingPhase/8)%56));
 
 
403
                    lightPtr->BlueScale=  0;
 
 
404
                    lightPtr->LightRange = 6000;
 
 
405
                    lightPtr->LightBright = ONE_FIXED;
 
 
406
                }
 
 
407
                else
 
 
408
                {
 
 
409
                    lightElementPtr->LifeTime = 0;
 
 
410
                }
 
 
411
            }
 
 
412
            default:
 
 
413
            break;
 
 
414
        }
 
 
415
 
 
 
416
        lightPtr->BrightnessOverRange = DIV_FIXED(MUL_FIXED(lightPtr->LightBright, LightScale), lightPtr->LightRange);
 
 
417
 
 
 
418
        if (lightElementPtr->LifeTime <= 0)
 
 
419
            *lightElementPtr = LightElementStorage[--NumActiveLightElements];
 
 
420
        else
 
 
421
            lightElementPtr++;
 
 
422
    }
 
 
423
}                                                                            
 
 
424
/*--------------------------**
 
 
425
** Load/Save Light Elements **
 
 
426
**--------------------------*/
 
 
427
#include "savegame.h"
 
 
428
 
 
 
429
typedef struct light_element_save_block_header
 
 
430
{
 
 
431
    SAVE_BLOCK_HEADER header;
 
 
432
 
 
 
433
    int NumActiveLightElements;
 
 
434
 
 
 
435
    //followed by array of light elements
 
 
436
 
 
 
437
} LIGHT_ELEMENT_SAVE_BLOCK_HEADER;
 
 
438
 
 
 
439
void Load_LightElements(SAVE_BLOCK_HEADER* header)
 
 
440
{
 
 
441
    int i;
 
 
442
    LIGHT_ELEMENT_SAVE_BLOCK_HEADER* block = (LIGHT_ELEMENT_SAVE_BLOCK_HEADER*) header;
 
 
443
    LIGHTELEMENT* saved_light_element = (LIGHTELEMENT*) (block+1);
 
 
444
    int expected_size;
 
 
445
 
 
 
446
    //make sure the block is the correct size
 
 
447
    expected_size = sizeof(*block);
 
 
448
    expected_size += sizeof(LIGHTELEMENT) * block->NumActiveLightElements;
 
 
449
 
 
 
450
    if(header->size != expected_size)
 
 
451
        return;
 
 
452
 
 
 
453
    for(i=0; i < block->NumActiveLightElements; i++)
 
 
454
    {
 
 
455
        LIGHTELEMENT* light_element = AllocateLightElement();
 
 
456
 
 
 
457
        if(light_element) 
 
 
458
            *light_element = *saved_light_element++;    
 
 
459
    }
 
 
460
}
 
 
461
 
 
 
462
void Save_LightElements()
 
 
463
{
 
 
464
    if(NumActiveLightElements)
 
 
465
    {
 
 
466
        int i;
 
 
467
        LIGHT_ELEMENT_SAVE_BLOCK_HEADER* block;
 
 
468
        //get memory for header
 
 
469
        GET_SAVE_BLOCK_POINTER(block);
 
 
470
 
 
 
471
        //fill in header
 
 
472
        block->header.type = SaveBlock_LightElements;
 
 
473
        block->header.size = sizeof(*block) + NumActiveLightElements * sizeof(LIGHTELEMENT);
 
 
474
        block->NumActiveLightElements = NumActiveLightElements;
 
 
475
 
 
 
476
        //now save the light elements
 
 
477
        for(i=0; i < NumActiveLightElements; i++)
 
 
478
        {
 
 
479
            LIGHTELEMENT* light = GET_SAVE_BLOCK_POINTER(light);
 
 
480
            *light = LightElementStorage[i];    
 
 
481
        }
 
 
482
    }
 
 
483
}