1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2001, Sven2
6 * Copyright (c) 2017-2019, The LegacyClonk Team and contributors
7 *
8 * Distributed under the terms of the ISC license; see accompanying file
9 * "COPYING" for details.
10 *
11 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12 * See accompanying file "TRADEMARK" for details.
13 *
14 * To redistribute this file separately, substitute the full license texts
15 * for the above references.
16 */
17
18// newgfx particle system for smoke, sparks, ...
19// - everything, that is not sync-relevant
20// function pointers for drawing and executing are used
21// instead of virtual classes and a hierarchy, because
22// the latter ones couldn't be optimized using static
23// chunks
24// thus, more complex partivle behaviour should be solved via
25// objects
26// note: this particle system will always assume the owning def
27// object to be a static class named Game.Particles!
28
29#pragma once
30
31#include <C4FacetEx.h>
32#include "C4ForwardDeclarations.h"
33#include <C4Group.h>
34#include <C4Shape.h>
35
36// class predefs
37class C4ParticleDefCore;
38class C4ParticleDef;
39class C4Particle;
40class C4ParticleChunk;
41class C4ParticleList;
42class C4ParticleSystem;
43
44typedef bool(*C4ParticleProc)(C4Particle *, C4Object *); // generic particle proc
45typedef C4ParticleProc C4ParticleInitProc; // particle init proc - init and return whether particle could be created
46typedef C4ParticleProc C4ParticleExecProc; // particle execution proc - returns whether particle died
47typedef C4ParticleProc C4ParticleCollisionProc; // particle collision proc - returns whether particle died
48typedef void(*C4ParticleDrawProc)(C4Particle *, C4FacetEx &, C4Object *); // particle drawing code
49
50#define ParticleSystem Game.Particles
51
52// core for particle defs
53class C4ParticleDefCore
54{
55public:
56 StdStrBuf Name; // name
57 C4TargetRect GfxFace; // target rect for graphics; used because stup
58 int32_t MaxCount; // maximum number of particles that may coexist of this type
59 int32_t MinLifetime, MaxLifetime; // used by exec proc; number of frames this particle can exist
60 int32_t YOff; // Y-Offset for Std-particles
61 int32_t Delay; // frame delay between animation phases
62 int32_t Repeats; // number of times the animation is repeated
63 int32_t Reverse; // reverse action after it has been played
64 int32_t FadeOutLen, FadeOutDelay; // phases used for letting the particle fade out
65 int32_t RByV; // if set, rotation will be adjusted according to the movement; if 2, the particle does not move
66 int32_t Placement; // when is the particle to be drawn?
67 int32_t GravityAcc; // acceleration done by gravity
68 int32_t WindDrift;
69 int32_t VertexCount; // number of vertices - 0 or 1
70 int32_t VertexY; // y-offset of vertex; 100 is object height
71 int32_t Additive; // whether particle should be drawn additively
72 int32_t Attach; // whether the particle moves relatively to the target
73 int32_t AlphaFade; // fadeout in each frame
74 int32_t Parallaxity[2]; // parallaxity
75
76 StdStrBuf InitFn; // proc to be used for initialization
77 StdStrBuf ExecFn; // proc to be used for frame-execution
78 StdStrBuf DrawFn; // proc to be used for drawing
79 StdStrBuf CollisionFn; // proc to be called upon collision with the landscape; may be left out
80
81 C4ParticleDefCore();
82 void CompileFunc(StdCompiler *pComp);
83
84 bool Compile(const char *szSource, const char *szName); // compile from def file
85};
86
87// one particle definition
88class C4ParticleDef : public C4ParticleDefCore
89{
90public:
91 C4ParticleDef *pPrev, *pNext; // linked list members
92
93 StdStrBuf Filename; // path to group this particle was loaded from (for EM reloading)
94
95 C4FacetExSurface Gfx; // graphics
96 int32_t Length; // number of phases in gfx
97 float Aspect; // height:width
98
99 C4ParticleInitProc InitProc; // procedure called once upon creation of the particle
100 C4ParticleExecProc ExecProc; // procedure used for execution of one particle
101 C4ParticleCollisionProc CollisionProc; // procedure called upon collision with the landscape; may be nullptr
102 C4ParticleDrawProc DrawProc; // procedure used for drawing of one particle
103
104 int32_t Count; // number of particles currently existent of this kind
105
106 C4ParticleDef();
107 ~C4ParticleDef();
108
109 void Clear(); // free mem associated with this class
110
111 bool Load(C4Group &rGrp); // load particle from group; assume file to be accessed already
112 bool Reload(); // reload particle from stored position
113};
114
115// one tiny little particle
116// note: list management done by the chunk, which spares one ptr here
117// the chunk initializes the values to zero here, too; so no ctors here...
118class C4Particle
119{
120protected:
121 C4Particle *pPrev, *pNext; // previous/next particle of the same list in the buffer
122
123 void MoveList(C4ParticleList &rFrom, C4ParticleList &rTo); // move from one list to another
124
125public:
126 C4ParticleDef *pDef; // kind of particle
127 float x, y, xdir, ydir; // position and movement
128 int32_t life; // lifetime remaining for this particle
129 float a; int32_t b; // all-purpose values
130
131 friend class C4ParticleChunk;
132 friend class C4ParticleList;
133 friend class C4ParticleSystem;
134};
135
136// one chunk of particles
137// linked list is managed by owner
138class C4ParticleChunk
139{
140protected:
141 C4ParticleChunk *pNext; // single linked list
142 C4Particle Data[C4Px_BufSize]; // the particles
143
144public:
145 C4ParticleChunk();
146 ~C4ParticleChunk();
147
148 void Clear(); // clear all particles
149
150 friend class C4ParticleSystem;
151};
152
153// a subset of particles
154class C4ParticleList
155{
156public:
157 C4Particle *pFirst; // first particle in list - others follow in linked list
158
159 C4ParticleList() { pFirst = nullptr; }
160
161 void Exec(C4Object *pObj = nullptr); // execute all particles
162 void Draw(C4FacetEx &cgo, C4Object *pObj = nullptr); // draw all particles
163 void Clear(); // remove all particles
164 int32_t Remove(C4ParticleDef *pOfDef); // remove all particles of def
165
166 operator bool() { return !!pFirst; } // checks whether list contains particles
167};
168
169// the main particle system
170class C4ParticleSystem
171{
172protected:
173 C4ParticleChunk Chunk; // linked list for particle chunks
174 C4ParticleDef *pDef0, *pDefL; // linked list for particle defs
175
176 C4ParticleChunk *AddChunk(); // add a new chunk to the list
177
178 C4ParticleProc GetProc(const char *szName); // get init/exec proc for a particle type
179 C4ParticleDrawProc GetDrawProc(const char *szName); // get draw proc for a particle type
180
181public:
182 C4ParticleList FreeParticles; // list of free particles
183 C4ParticleList GlobalParticles; // list of free particles
184
185 C4ParticleDef *pSmoke; // default particle: smoke
186 C4ParticleDef *pBlast; // default particle: blast
187 C4ParticleDef *pFSpark; // default particle: firy spark
188 C4ParticleDef *pFire1; // default particle: fire base
189 C4ParticleDef *pFire2; // default particle: fire additive
190
191 C4ParticleSystem();
192 ~C4ParticleSystem();
193
194 void ClearParticles(); // remove all particles
195 void Clear(); // remove all particle definitions and particles
196
197 C4Particle *Create(C4ParticleDef *pOfDef, // create one particle of given type
198 float x, float y, float xdir = 0.0f, float ydir = 0.0f,
199 float a = 0.0f, int32_t b = 0, C4ParticleList *pPxList = nullptr, C4Object *pObj = nullptr);
200 bool Cast(C4ParticleDef *pOfDef, // create several particles with different speeds and params
201 int32_t iAmount,
202 float x, float y, int32_t level,
203 float a0 = 0.0f, uint32_t b0 = 0, float a1 = 0.0f, uint32_t b1 = 0,
204 C4ParticleList *pPxList = nullptr, C4Object *pObj = nullptr);
205
206 C4ParticleDef *GetDef(const char *szName, C4ParticleDef *pExclude = nullptr); // get particle def by name
207 void SetDefParticles(); // seek and assign default particels (smoke, etc.)
208
209 int32_t Push(C4ParticleDef *pOfDef, float dxdir, float dydir); // add movement to all particles of type
210
211 bool IsFireParticleLoaded() { return pFire1 && pFire2; }
212
213 friend class C4ParticleDef;
214 friend class C4Particle;
215 friend class C4ParticleChunk;
216};
217
218// default particle execution/drawing functions
219bool fxStdInit(C4Particle *pPrt, C4Object *pTarget);
220bool fxStdExec(C4Particle *pPrt, C4Object *pTarget);
221void fxStdDraw(C4Particle *pPrt, C4FacetEx &cgo, C4Object *pTarget);
222
223// structures used for static function maps
224struct C4ParticleProcRec
225{
226 char Name[C4Px_MaxIDLen + 1]; // name of procedure
227 C4ParticleProc Proc; // procedure
228};
229
230struct C4ParticleDrawProcRec
231{
232 char Name[C4Px_MaxIDLen + 1]; // name of procedure
233 C4ParticleDrawProc Proc; // procedure
234};
235
236extern C4ParticleProcRec C4ParticleProcMap[]; // particle init/execution function map
237extern C4ParticleDrawProcRec C4ParticleDrawProcMap[]; // particle drawing function map
238