4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
#include "system.h"
 
 
2
#include "prototyp.h"
 
 
3
#include "stratdef.h"
 
 
4
#include "particlegenerator.h"
 
 
5
#include "pvisible.h"
 
 
6
#include "particle.h"
 
 
7
#include "lighting.h"
 
 
8
#include <assert.h>
 
 
9
#include <stdlib.h>
 
 
10
 
 
 
11
void ParticleGeneratorBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
 
 
12
{
 
 
13
    assert(sbptr);
 
 
14
    assert(bhdata);
 
 
15
 
 
 
16
    PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = malloc(sizeof(PARTICLE_GENERATOR_BEHAV_BLOCK));
 
 
17
 
 
 
18
    if(!pargen)
 
 
19
    {
 
 
20
        RemoveBehaviourStrategy(sbptr);
 
 
21
        return;
 
 
22
    }
 
 
23
 
 
 
24
    sbptr->dataptr = pargen;
 
 
25
    pargen->bhvr_type = I_BehaviourParticleGenerator;
 
 
26
 
 
 
27
    PARTICLE_GENERATOR_TOOLS_TEMPLATE* pg_tt = (PARTICLE_GENERATOR_TOOLS_TEMPLATE*)bhdata;
 
 
28
 
 
 
29
    //copy stuff from tools template
 
 
30
    COPY_NAME(sbptr->SBname, pg_tt->nameID);
 
 
31
    pargen->position = pg_tt->position;
 
 
32
    pargen->orientation = pg_tt->orientation;
 
 
33
    pargen->particle = pg_tt->particle;
 
 
34
    pargen->active = pg_tt->active;
 
 
35
    pargen->sound = pg_tt->sound;
 
 
36
 
 
 
37
    //find the generator's module
 
 
38
    sbptr->containingModule = ModuleFromPosition(&pargen->position, NULL);
 
 
39
 
 
 
40
    assert(sbptr->containingModule);
 
 
41
 
 
 
42
    if(pargen->sound)
 
 
43
        pargen->sound->playing = pargen->active;
 
 
44
 
 
 
45
    //see if generator has a parent object
 
 
46
    pargen->parent_sbptr = FindSBWithName(pg_tt->parentID);
 
 
47
 
 
 
48
    if(pargen->parent_sbptr)
 
 
49
    {
 
 
50
        if(pargen->parent_sbptr->DynPtr)
 
 
51
        {
 
 
52
            //work out generator's relative position
 
 
53
            MATRIXCH m = pargen->parent_sbptr->DynPtr->OrientMat;
 
 
54
            TransposeMatrixCH(&m);
 
 
55
 
 
 
56
            pargen->relative_position = pargen->position;
 
 
57
            pargen->relative_orientation = pargen->orientation;
 
 
58
 
 
 
59
            pargen->relative_position.vx -= pargen->parent_sbptr->DynPtr->Position.vx;
 
 
60
            pargen->relative_position.vy -= pargen->parent_sbptr->DynPtr->Position.vy;
 
 
61
            pargen->relative_position.vz -= pargen->parent_sbptr->DynPtr->Position.vz;
 
 
62
 
 
 
63
            RotateVector(&pargen->relative_position,&m);
 
 
64
 
 
 
65
            MatrixMultiply(&pargen->relative_orientation, &m, &pargen->relative_orientation);
 
 
66
        }
 
 
67
        else
 
 
68
        {
 
 
69
            //parent object has no dynamics block
 
 
70
            //so it can't be used
 
 
71
            pargen->parent_sbptr = 0;
 
 
72
        }
 
 
73
    }
 
 
74
 
 
 
75
    pargen->frequency = pg_tt->frequency;
 
 
76
    pargen->timer = pargen->frequency;
 
 
77
    pargen->probability = pg_tt->probability;
 
 
78
    pargen->speed = pg_tt->speed;
 
 
79
}
 
 
80
 
 
 
81
void ParticleGeneratorBehaveFun(STRATEGYBLOCK* sbptr)
 
 
82
{
 
 
83
    PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbptr->dataptr;
 
 
84
    assert((pargen->bhvr_type == I_BehaviourParticleGenerator));
 
 
85
 
 
 
86
    if(pargen->parent_sbptr)
 
 
87
    {
 
 
88
        //generator has parent object , update position 
 
 
89
        if(pargen->parent_sbptr->destroyed_but_preserved)
 
 
90
        {
 
 
91
            //parent object destroyed
 
 
92
            //switch off generator if active and return
 
 
93
            if(pargen->active)
 
 
94
            {
 
 
95
                pargen->active = 0;
 
 
96
 
 
 
97
                if(pargen->sound)
 
 
98
                    Stop_Track_Sound(pargen->sound);
 
 
99
            }
 
 
100
        return;
 
 
101
        }
 
 
102
        else
 
 
103
        {
 
 
104
            DYNAMICSBLOCK *dynPtr = pargen->parent_sbptr->DynPtr;
 
 
105
            assert(dynPtr);
 
 
106
 
 
 
107
            //update orientation
 
 
108
            MatrixMultiply(&pargen->relative_orientation,&dynPtr->OrientMat,&pargen->orientation);
 
 
109
 
 
 
110
            pargen->position = pargen->relative_position;
 
 
111
            RotateVector(&pargen->position,&dynPtr->OrientMat);    
 
 
112
 
 
 
113
            pargen->position.vx += dynPtr->Position.vx;
 
 
114
            pargen->position.vy += dynPtr->Position.vy;
 
 
115
            pargen->position.vz += dynPtr->Position.vz;
 
 
116
 
 
 
117
            //update containing module from parent
 
 
118
            sbptr->containingModule = pargen->parent_sbptr->containingModule;
 
 
119
        }
 
 
120
    }
 
 
121
 
 
 
122
    if(pargen->active)
 
 
123
    {
 
 
124
        //update timer
 
 
125
        pargen->timer -= NormalFrameTime;
 
 
126
 
 
 
127
        if(pargen->sound)
 
 
128
            Update_Track_Sound(pargen->sound,&pargen->position); //update sound
 
 
129
 
 
 
130
        if(!sbptr->containingModule)
 
 
131
            sbptr->containingModule = ModuleFromPosition(&pargen->position, NULL);
 
 
132
 
 
 
133
        assert(sbptr->containingModule);
 
 
134
 
 
 
135
        if(ModuleCurrVisArray[sbptr->containingModule->m_index])
 
 
136
        {
 
 
137
            //if containing module is near create particles.
 
 
138
 
 
 
139
            switch(pargen->particle)
 
 
140
            {
 
 
141
                case PARTICLE_SPARK:
 
 
142
                {
 
 
143
                    if(pargen->timer < 0)
 
 
144
                    {
 
 
145
                        if((FastRandom() & 0xffff) <= pargen->probability)
 
 
146
                        {
 
 
147
                            //create sparks
 
 
148
                            //like MakeSprayOfSparks , but in z direction
 
 
149
                            int noOfSparks = 15;
 
 
150
                            do
 
 
151
                            {
 
 
152
                                VECTORCH velocity;
 
 
153
                                velocity.vx = (FastRandom()&2047)-1024;
 
 
154
                                velocity.vy = (FastRandom()&2047)-1024;
 
 
155
                                velocity.vz = (FastRandom()&2047);
 
 
156
                                RotateVector(&velocity, &pargen->orientation);
 
 
157
                                MakeParticle(&pargen->position, &velocity, pargen->particle);    
 
 
158
 
 
 
159
                            } while(--noOfSparks);
 
 
160
 
 
 
161
                            MakeLightElement(&pargen->position, LIGHTELEMENT_ELECTRICAL_SPARKS);
 
 
162
 
 
 
163
                            //if the generator has a non-looping sound , we should play it now
 
 
164
                            if(pargen->sound && !pargen->sound->loop)
 
 
165
                                Start_Track_Sound(pargen->sound, &pargen->position);
 
 
166
                        }
 
 
167
                    }
 
 
168
                }
 
 
169
                break;
 
 
170
                case PARTICLE_FLAME:
 
 
171
                    //add light effect
 
 
172
                    MakeLightElement(&pargen->position, LIGHTELEMENT_PARGEN_FLAME);
 
 
173
                    //and fall throgh to next section
 
 
174
                case PARTICLE_STEAM:
 
 
175
                case PARTICLE_BLACKSMOKE:
 
 
176
                {
 
 
177
                    while(pargen->timer < 0)
 
 
178
                    {
 
 
179
                        VECTORCH velocity;
 
 
180
                        VECTORCH position = pargen->position;
 
 
181
 
 
 
182
                        pargen->timer += pargen->frequency;
 
 
183
 
 
 
184
                        //get a velocity of magnitude in the region of speed
 
 
185
                        velocity.vx = ((FastRandom()&1023) - 512);
 
 
186
                        velocity.vy = ((FastRandom()&1023) - 512);
 
 
187
                        velocity.vz = MUL_FIXED(pargen->speed, (ONE_FIXED+(FastRandom()&0x3fff)));
 
 
188
 
 
 
189
                        RotateVector(&velocity, &pargen->orientation);
 
 
190
 
 
 
191
                        //allow particle to have had part of a frames movement already
 
 
192
                        int offset = FastRandom() % NormalFrameTime;
 
 
193
                        position.vx += MUL_FIXED(offset, velocity.vx);
 
 
194
                        position.vy += MUL_FIXED(offset, velocity.vy);
 
 
195
                        position.vz += MUL_FIXED(offset, velocity.vz);
 
 
196
 
 
 
197
                        MakeParticle(&position,&velocity, pargen->particle);    
 
 
198
                    }
 
 
199
                }
 
 
200
                default:
 
 
201
                break;
 
 
202
            }
 
 
203
        }
 
 
204
 
 
 
205
        if(pargen->timer < 0)    
 
 
206
            pargen->timer = pargen->frequency+(pargen->timer % pargen->frequency);
 
 
207
    }
 
 
208
}
 
 
209
 
 
 
210
void SendRequestToParticleGenerator(STRATEGYBLOCK* sbptr, int state)
 
 
211
{
 
 
212
    PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = sbptr->dataptr;
 
 
213
    assert(pargen);
 
 
214
 
 
 
215
    if(state)
 
 
216
    {
 
 
217
        //if generator has a parent object that has been destroyed , then it can't be switched on
 
 
218
        if(pargen->parent_sbptr && pargen->parent_sbptr->destroyed_but_preserved)
 
 
219
            return;
 
 
220
 
 
 
221
        pargen->active = 1;
 
 
222
 
 
 
223
        if(pargen->sound && pargen->sound->loop)
 
 
224
            Start_Track_Sound(pargen->sound,&pargen->position);
 
 
225
    }
 
 
226
    else
 
 
227
    {
 
 
228
        pargen->active = 0;
 
 
229
        if(pargen->sound)
 
 
230
            Stop_Track_Sound(pargen->sound);
 
 
231
    }
 
 
232
}
 
 
233
 
 
 
234
#include "savegame.h"
 
 
235
 
 
 
236
typedef struct particle_generator_save_block
 
 
237
{
 
 
238
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
239
 
 
 
240
    VECTORCH position;
 
 
241
    MATRIXCH orientation; 
 
 
242
 
 
 
243
    VECTORCH relative_position;     //relative to parent object (if it exists)
 
 
244
    MATRIXCH relative_orientation; //relative to parent object (if it exists)
 
 
245
 
 
 
246
    int timer; //time left to next particle burst
 
 
247
 
 
 
248
    unsigned int active :1;    //is generator currently active
 
 
249
    unsigned int sound_playing :1;
 
 
250
 
 
 
251
} PARTICLE_GENERATOR_SAVE_BLOCK;
 
 
252
 
 
 
253
//defines for load/save macros
 
 
254
#define SAVELOAD_BLOCK block
 
 
255
#define SAVELOAD_BEHAV pargen
 
 
256
 
 
 
257
void LoadStrategy_ParticleGenerator(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
258
{
 
 
259
    PARTICLE_GENERATOR_SAVE_BLOCK* block = (PARTICLE_GENERATOR_SAVE_BLOCK*) header; 
 
 
260
 
 
 
261
    //check the size of the save block
 
 
262
    if(header->size != sizeof(*block))
 
 
263
            return;
 
 
264
 
 
 
265
    //find the existing strategy block
 
 
266
    STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname);
 
 
267
    if(!sbPtr)
 
 
268
        return;
 
 
269
 
 
 
270
    //make sure the strategy found is of the right type
 
 
271
    if(sbPtr->type != I_BehaviourParticleGenerator)
 
 
272
        return;
 
 
273
 
 
 
274
    PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
275
 
 
 
276
    //start copying stuff
 
 
277
    COPYELEMENT_LOAD(position)
 
 
278
    COPYELEMENT_LOAD(orientation)
 
 
279
    COPYELEMENT_LOAD(relative_position)
 
 
280
    COPYELEMENT_LOAD(relative_orientation)
 
 
281
    COPYELEMENT_LOAD(timer)
 
 
282
    COPYELEMENT_LOAD(active)
 
 
283
 
 
 
284
    if(pargen->sound)
 
 
285
    {
 
 
286
        pargen->sound->playing = block->sound_playing;
 
 
287
        Load_SoundState(&pargen->sound->activ_no);
 
 
288
    }
 
 
289
}
 
 
290
 
 
 
291
void SaveStrategy_ParticleGenerator(STRATEGYBLOCK* sbPtr)
 
 
292
{
 
 
293
    PARTICLE_GENERATOR_SAVE_BLOCK *block;
 
 
294
    PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
295
 
 
 
296
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
297
 
 
 
298
    //start copying stuff
 
 
299
    COPYELEMENT_SAVE(position)
 
 
300
    COPYELEMENT_SAVE(orientation)
 
 
301
    COPYELEMENT_SAVE(relative_position)
 
 
302
    COPYELEMENT_SAVE(relative_orientation)
 
 
303
    COPYELEMENT_SAVE(timer)
 
 
304
    COPYELEMENT_SAVE(active)
 
 
305
 
 
 
306
    if(pargen->sound)
 
 
307
    {
 
 
308
        block->sound_playing = pargen->sound->playing;
 
 
309
        Save_SoundState(&pargen->sound->activ_no);
 
 
310
    }
 
 
311
}