00001
00002 #include "revolt.h"
00003 #include "main.h"
00004 #include "geom.h"
00005 #include "dx.h"
00006 #include "texture.h"
00007 #include "model.h"
00008 #include "smoke.h"
00009
00010
00011
00012 static long UsedSmokeCount;
00013 static SMOKE *SmokeList;
00014 static SMOKE *UsedSmokeHead;
00015 static SMOKE *FreeSmokeHead;
00016
00018
00020
00021 long InitSmoke(void)
00022 {
00023 long i;
00024
00025
00026
00027 SmokeList = (SMOKE*)malloc(sizeof(SMOKE) * MAX_SMOKES);
00028 if (!SmokeList)
00029 {
00030 Box("ERROR", "Can't alloc memory for smoke engine", MB_OK);
00031 QuitGame = TRUE;
00032 return FALSE;
00033 }
00034
00035
00036
00037 UsedSmokeHead = NULL;
00038
00039
00040
00041 FreeSmokeHead = SmokeList;
00042
00043 for (i = 0 ; i < MAX_SMOKES ; i++)
00044 {
00045 SmokeList[i].Prev = &SmokeList[i - 1];
00046 SmokeList[i].Next = &SmokeList[i + 1];
00047 }
00048
00049
00050
00051 SmokeList[0].Prev = NULL;
00052 SmokeList[MAX_SMOKES - 1].Next = NULL;
00053
00054
00055
00056 UsedSmokeCount = 0;
00057
00058
00059
00060 return TRUE;
00061 }
00062
00064
00066
00067 void KillSmoke(void)
00068 {
00069 free(SmokeList);
00070 }
00071
00073
00075
00076 SMOKE *AllocSmoke(void)
00077 {
00078 SMOKE *smoke;
00079
00080
00081
00082 if (!FreeSmokeHead)
00083 {
00084 return NULL;
00085 }
00086
00087
00088
00089 smoke = FreeSmokeHead;
00090 FreeSmokeHead = smoke->Next;
00091
00092 if (FreeSmokeHead)
00093 {
00094 FreeSmokeHead->Prev = NULL;
00095 }
00096
00097
00098
00099 smoke->Prev = NULL;
00100 smoke->Next = UsedSmokeHead;
00101 UsedSmokeHead = smoke;
00102
00103 if (smoke->Next)
00104 {
00105 smoke->Next->Prev = smoke;
00106 }
00107
00108
00109
00110 UsedSmokeCount++;
00111
00112
00113
00114 return smoke;
00115 }
00116
00118
00120
00121 void FreeSmoke(SMOKE *smoke)
00122 {
00123
00124
00125
00126 if (!smoke)
00127 {
00128 return;
00129 }
00130
00131
00132
00133 if (smoke->Prev)
00134 {
00135 smoke->Prev->Next = smoke->Next;
00136 }
00137 else
00138 {
00139 UsedSmokeHead = smoke->Next;
00140 }
00141
00142 if (smoke->Next)
00143 {
00144 smoke->Next->Prev = smoke->Prev;
00145 }
00146
00147
00148
00149 smoke->Prev = NULL;
00150 smoke->Next = FreeSmokeHead;
00151 FreeSmokeHead = smoke;
00152
00153 if (smoke->Next)
00154 {
00155 smoke->Next->Prev = smoke;
00156 }
00157
00158
00159
00160 UsedSmokeCount--;
00161 }
00162
00164
00166
00167 long CreateSmoke(VEC *pos, VEC *dir, REAL size, REAL growrate, REAL age, REAL spinstart, REAL spinrate, long rgb)
00168 {
00169 SMOKE *smoke;
00170
00171
00172
00173 smoke = AllocSmoke();
00174 if (!smoke)
00175 {
00176 return FALSE;
00177 }
00178
00179
00180
00181 smoke->Pos = *pos;
00182 smoke->Dir = *dir;
00183 smoke->GrowRate = growrate;
00184 smoke->AgeStart = smoke->Age = age;
00185 smoke->Spin = spinstart;
00186 smoke->SpinRate = spinrate;
00187
00188
00189
00190 smoke->Poly.Xsize = size;
00191 smoke->Poly.Ysize = size;
00192 smoke->Poly.U = 0.0f / 256.0f;
00193 smoke->Poly.V = 0.0f / 256.0f;
00194 smoke->Poly.Usize = 64.0f / 256.0f;
00195 smoke->Poly.Vsize = 64.0f / 256.0f;
00196 smoke->Poly.Tpage = TPAGE_FX1;
00197 smoke->rgb = rgb;
00198
00199
00200
00201 return TRUE;
00202 }
00203
00205
00207
00208 void ProcessSmoke(void)
00209 {
00210 long per;
00211 SMOKE *smoke;
00212 SMOKE smoketemp;
00213
00214
00215
00216 if (!UsedSmokeCount)
00217 return;
00218
00219
00220
00221 for (smoke = UsedSmokeHead ; smoke ; smoke = smoke->Next)
00222 {
00223
00224
00225
00226 smoke->Age -= TimeFactor;
00227 if (smoke->Age < 0)
00228 {
00229 smoketemp.Next = smoke->Next;
00230 FreeSmoke(smoke);
00231 smoke = &smoketemp;
00232 continue;
00233 }
00234
00235
00236
00237 smoke->Spin += smoke->SpinRate * TimeFactor;
00238 RotMatrixZ(&smoke->Matrix, smoke->Spin);
00239
00240
00241
00242 smoke->Pos.v[X] += smoke->Dir.v[X] * TimeFactor;
00243 smoke->Pos.v[Y] += smoke->Dir.v[Y] * TimeFactor;
00244 smoke->Pos.v[Z] += smoke->Dir.v[Z] * TimeFactor;
00245
00246
00247
00248 smoke->Poly.Xsize += smoke->GrowRate * TimeFactor;
00249 smoke->Poly.Ysize += smoke->GrowRate * TimeFactor;
00250
00251
00252
00253 FTOL(smoke->Age * 100 / smoke->AgeStart, per);
00254 smoke->Poly.RGB = smoke->rgb;
00255 ModelChangeGouraud((MODEL_RGB*)&smoke->Poly.RGB, per);
00256 }
00257 }
00258
00260
00262
00263 void DrawSmoke(void)
00264 {
00265 SMOKE *smoke;
00266
00267
00268
00269 if (!UsedSmokeCount)
00270 return;
00271
00272
00273
00274 ALPHA_ON();
00275 ALPHA_SRC(D3DBLEND_ONE);
00276 ALPHA_DEST(D3DBLEND_ONE);
00277
00278 ZWRITE_OFF();
00279
00280
00281
00282 for (smoke = UsedSmokeHead ; smoke ; smoke = smoke->Next)
00283 {
00284 DrawFacingPolyRot(&smoke->Pos, &smoke->Matrix, &smoke->Poly, -1, 0.0f);
00285 }
00286 }