rnd-20090623-1-src
[rocksndiamonds.git] / src / game_sp / Explosions.c
1 // ----------------------------------------------------------------------------
2 // Explosions.c
3 // ----------------------------------------------------------------------------
4
5 #include "Explosions.h"
6
7 static void LetExplodeFieldSP(int tsi, int cx, int dh);
8 static int subExplodeInfotron(int tsi, int cx);
9 static int subExplodeZonk(int tsi, int cx);
10
11 static char *VB_Name = "modExplosions";
12 // --- Option Explicit
13
14 // ==========================================================================
15 //                              SUBROUTINE
16 // Animate explosion
17 // ==========================================================================
18 int subAnimateExplosion(int si)
19 {
20   int subAnimateExplosion;
21
22   int ax, bx, bl, X, Y;
23
24   if (LowByte(PlayField16[si]) != fiExplosion)
25     return subAnimateExplosion;
26
27   ax = (TimerVar & 3);
28   if (ax != 0)
29     return subAnimateExplosion;
30
31   bl = HighByte(PlayField16[si]);
32   if ((bl & 0x80) != 0) // infotron explosion!
33     goto loc_g_28D0;
34
35   bl = bl + 1;
36   MovHighByte(&PlayField16[si], bl);
37   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38   X = GetStretchX(si);
39   Y = GetStretchY(si);
40   StretchedSprites.BltEx(X, Y, aniExplosion[bl]);
41   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
42   if (bl == 8)
43   {
44     PlayField16[si] = 0;
45     ExplosionShake = 0; // nothing explodes
46   } // loc_ret_g_28CF:
47
48   return subAnimateExplosion;
49
50 loc_g_28D0: // explosion produces infotron
51   bl = bl + 1;
52   if (bl == 0x89)
53   {
54     PlayField16[si] = fiInfotron;
55     MovLowByte(&ExplosionShake, 0); // nothing explodes
56     return subAnimateExplosion;
57   } // loc_g_28E3:
58
59   MovHighByte(&PlayField16[si], bl);
60   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
61   X = GetStretchX(si);
62   Y = GetStretchY(si);
63   StretchedSprites.BltEx(X, Y, aniExplosionInfo + bl - 0x80);
64   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
65
66   return subAnimateExplosion;
67 } // subAnimateExplosion
68
69 // ==========================================================================
70 //                              SUBROUTINE
71 // Explode
72 // ==========================================================================
73
74 void ExplodeFieldSP(int si)
75 {
76   int ax, al, cx, dl, dh;
77
78   ax = LowByte(PlayField16[si]);
79   if (ax == fiHardWare)
80     return;
81
82   ExplosionShake = 1; // something explodes
83   if (ax == fiMurphy)
84     KillMurphyFlag = 1;
85
86   if (ax == fiElectron)
87   {
88     cx = 0x801F; // produce infotrons
89     dl = 0xF3;
90   }
91   else // loc_g_2977:
92   {
93     cx = 0x1F; // normal explosion
94     dl = 0xD;
95   } // loc_g_297C:
96
97   LetExplodeFieldSP(si - FieldWidth - 1, cx, dl);
98   LetExplodeFieldSP(si - FieldWidth, cx, dl);
99   LetExplodeFieldSP(si - FieldWidth + 1, cx, dl);
100   LetExplodeFieldSP(si - 1, cx, dl);
101   PlayField16[si] = cx;
102   LetExplodeFieldSP(si + 1, cx, dl);
103   LetExplodeFieldSP(si + FieldWidth - 1, cx, dl);
104   LetExplodeFieldSP(si + FieldWidth, cx, dl);
105   LetExplodeFieldSP(si + FieldWidth + 1, cx, dl);
106
107 loc_g_2C3B:
108   subSoundFXExplosion();
109 } // ExplodeFieldSP
110
111 static void LetExplodeFieldSP(int tsi, int cx, int dh)
112 {
113   int al;
114
115   if (tsi < (-FieldWidth))
116     return;
117
118   al = LowByte(PlayField16[tsi]);
119   switch (al)
120   {
121     case fiHardWare:
122       return;
123
124       break;
125
126     case fiOrangeDisk:
127     case fiYellowDisk:
128     case fiSnikSnak:
129       PlayField8[tsi] = dh;
130       PlayField16[tsi] = cx;
131       break;
132
133     case fiZonk:
134       subExplodeZonk(tsi, cx);
135       break;
136
137     case fiInfotron:
138       subExplodeInfotron(tsi, cx);
139       break;
140
141     case fiElectron:
142       PlayField8[tsi] = (-dh) & 0xFF;
143       PlayField16[tsi] = 0x801F;
144       break;
145
146     case fiMurphy:
147       KillMurphyFlag = 1;
148       PlayField8[tsi] = dh;
149       PlayField16[tsi] = cx;
150       break;
151
152     default:
153       PlayField16[tsi] = cx;
154       break;
155   }
156 }
157
158 static int subExplodeZonk(int tsi, int cx)
159 {
160   static int subExplodeZonk;
161
162   int ah;
163
164   ah = HighByte(PlayField16[tsi]) & 0xF0;
165   PlayField16[tsi] = cx;
166   switch (ah)
167   {
168     case 0x10:
169     case 0x70:
170       subClearFieldDueToExplosion(tsi - FieldWidth);
171       tsi = tsi + FieldWidth;
172       if (PlayField16[tsi] == 0x9999)
173         subClearFieldDueToExplosion(tsi);
174
175       break;
176
177     case 0x20:
178       subClearFieldDueToExplosion(tsi + 1);
179       subClearFieldDueToExplosion(tsi + FieldWidth);
180       break;
181
182     case 0x30:
183       subClearFieldDueToExplosion(tsi - 1);
184       subClearFieldDueToExplosion(tsi + FieldWidth);
185       break;
186
187     case 0x50:
188       subClearFieldDueToExplosion(tsi - 1);
189       break;
190
191     case 0x60:
192       subClearFieldDueToExplosion(tsi + 1);
193       break;
194
195     case 0xFF000070: // !!! 0x70; this will never be reached! ...??
196       subClearFieldDueToExplosion(tsi + FieldWidth);
197       break;
198   }
199
200   return subExplodeZonk;
201 } // subExplodeZonk
202
203 static int subExplodeInfotron(int tsi, int cx)
204 {
205   static int subExplodeInfotron;
206
207   int ah;
208
209   ah = HighByte(PlayField16[tsi]) & 0xF0;
210   PlayField16[tsi] = cx;
211   switch (ah)
212   {
213     case 0x10:
214     case 0x70:
215       subClearFieldDueToExplosion(tsi - FieldWidth);
216       tsi = tsi + FieldWidth;
217       if (PlayField16[tsi] == 0x9999)
218         subClearFieldDueToExplosion(tsi);
219
220       break;
221
222     case 0x20:
223       subClearFieldDueToExplosion(tsi + 1);
224       tsi = tsi + FieldWidth; // differnt from zonk version
225       if (PlayField16[tsi] == 0x9999)
226         subClearFieldDueToExplosion(tsi);
227
228       break;
229
230     case 0x30:
231       subClearFieldDueToExplosion(tsi - 1);
232       tsi = tsi + FieldWidth; // differnt from zonk version
233       if (PlayField16[tsi] == 0x9999)
234         subClearFieldDueToExplosion(tsi);
235
236       break;
237
238     case 0x50:
239       subClearFieldDueToExplosion(tsi - 1);
240       break;
241
242     case 0x60:
243       subClearFieldDueToExplosion(tsi + 1);
244       break;
245
246     case 0xFF000070: // !!! 0x70; this will never be reached! ...??
247       subClearFieldDueToExplosion(tsi + FieldWidth);
248       break;
249   }
250
251   return subExplodeInfotron;
252 } // subExplodeInfotron
253
254 int subClearFieldDueToExplosion(int si)
255 {
256   int subClearFieldDueToExplosion;
257
258   int X, Y;
259
260   if (LowByte(PlayField16[si]) == fiExplosion)
261     return subClearFieldDueToExplosion;
262
263   PlayField16[si] = 0;
264   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
265   X = GetStretchX(si);
266   Y = GetStretchY(si);
267   StretchedSprites.BltEx(X, Y, fiSpace);
268   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
269
270   return subClearFieldDueToExplosion;
271 } // subClearFieldDueToExplosion
272
273 int subRedDiskReleaseExplosion()
274 {
275   int subRedDiskReleaseExplosion;
276
277   int al, X, Y, si;
278
279   al = RedDiskReleasePhase;            // Red disk release phase
280   if (al <= 1)
281     return subRedDiskReleaseExplosion;
282
283   si = RedDiskReleaseMurphyPos;
284   if (PlayField16[si] == 0) // Release red disk
285     PlayField16[si] = fiRedDisk;
286
287   // +++++++++++++++++++++++++++++++++++++++++
288   X = GetStretchX(si);
289   Y = GetStretchY(si);
290   StretchedSprites.BltEx(X, Y, fiRedDisk);
291   // +++++++++++++++++++++++++++++++++++++++++
292   RedDiskReleasePhase = RedDiskReleasePhase + 1;
293   if (RedDiskReleasePhase >= 0x28)
294   {
295     // si = RedDiskReleaseMurphyPos           ' Red disk was released here
296     ExplodeFieldSP(si);                 // Explode
297     RedDiskReleasePhase = 0;
298   }
299
300   return subRedDiskReleaseExplosion;
301 }
302
303 int subFollowUpExplosions()
304 {
305   int subFollowUpExplosions;
306
307   int ax, si;
308
309 locloop_g_2919:
310   for (si = 0; si <= LevelMax; si++)
311   {
312     ax = ByteToInt(PlayField8[si]);
313     if (ax != 0)
314     {
315       if (ax < 0)
316       {
317         ax = ax + 1;
318         PlayField8[si] = ax & 0xFF;
319         if (ax == 0)
320         {
321           PlayField16[si] = 0xFF18;
322           ExplodeFieldSP(si);                 // Explode
323         }
324
325       }
326       else
327       {
328         ax = ax - 1;
329         PlayField8[si] = ax;
330         if (ax == 0)
331           ExplodeFieldSP(si);
332       }
333     }
334   }
335
336   return subFollowUpExplosions;
337 } // subFollowUpExplosions