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