]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/p_anim.c
osezer patch 012
[theoddone33/hhexen.git] / base / p_anim.c
1
2 //**************************************************************************
3 //**
4 //** p_anim.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 // HEADER FILES ------------------------------------------------------------
14
15 #include "h2def.h"
16 #include "p_local.h"
17
18 // MACROS ------------------------------------------------------------------
19
20 #define ANIM_SCRIPT_NAME "ANIMDEFS"
21 #define MAX_ANIM_DEFS 20
22 #define MAX_FRAME_DEFS 96
23 #define ANIM_FLAT 0
24 #define ANIM_TEXTURE 1
25 #define SCI_FLAT "flat"
26 #define SCI_TEXTURE "texture"
27 #define SCI_PIC "pic"
28 #define SCI_TICS "tics"
29 #define SCI_RAND "rand"
30
31 #define LIGHTNING_SPECIAL       198
32 #define LIGHTNING_SPECIAL2      199
33 #define SKYCHANGE_SPECIAL       200
34
35 // TYPES -------------------------------------------------------------------
36
37 typedef struct
38 {
39         int index;
40         int tics;
41 } frameDef_t;
42
43 typedef struct
44 {
45         int type;
46         int index;
47         int tics;
48         int currentFrameDef;
49         int startFrameDef;
50         int endFrameDef;
51 } animDef_t;
52
53 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
54
55 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
56
57 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
58
59 static void P_LightningFlash(void);
60
61 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
62
63 extern fixed_t Sky1ColumnOffset;
64 extern fixed_t Sky2ColumnOffset;
65 extern int Sky1Texture;
66 extern boolean DoubleSky;
67
68 // PUBLIC DATA DEFINITIONS -------------------------------------------------
69
70 fixed_t Sky1ScrollDelta;
71 fixed_t Sky2ScrollDelta;
72
73 // PRIVATE DATA DEFINITIONS ------------------------------------------------
74
75 static animDef_t AnimDefs[MAX_ANIM_DEFS];
76 static frameDef_t FrameDefs[MAX_FRAME_DEFS];
77 static int AnimDefCount;
78 static boolean LevelHasLightning;
79 static int NextLightningFlash;
80 static int LightningFlash;
81 static int *LightningLightLevels;
82
83 // CODE --------------------------------------------------------------------
84
85 //==========================================================================
86 //
87 // P_AnimateSurfaces
88 //
89 //==========================================================================
90
91 void P_AnimateSurfaces(void)
92 {
93         int i;
94         animDef_t *ad;
95         line_t *line;
96
97         // Animate flats and textures
98         for(i = 0; i < AnimDefCount; i++)
99         {
100                 ad = &AnimDefs[i];
101                 ad->tics--;
102                 if(ad->tics == 0)
103                 {
104                         if(ad->currentFrameDef == ad->endFrameDef)
105                         {
106                                 ad->currentFrameDef = ad->startFrameDef;
107                         }
108                         else
109                         {
110                                 ad->currentFrameDef++;
111                         }
112                         ad->tics = FrameDefs[ad->currentFrameDef].tics;
113                         if(ad->tics > 255)
114                         { // Random tics
115                                 ad->tics = (ad->tics>>16)
116                                         +P_Random()%((ad->tics&0xff00)>>8);
117                         }
118                         if(ad->type == ANIM_FLAT)
119                         {
120                                 flattranslation[ad->index] =
121                                         FrameDefs[ad->currentFrameDef].index;
122                         }
123                         else
124                         { // Texture
125                                 texturetranslation[ad->index] =
126                                         FrameDefs[ad->currentFrameDef].index;
127                         }
128                 }
129         }
130
131         // Update scrolling textures
132         for(i = 0; i < numlinespecials; i++)
133         {
134                 line = linespeciallist[i];
135                 switch(line->special)
136                 {
137                         case 100: // Scroll_Texture_Left
138                                 sides[line->sidenum[0]].textureoffset += line->arg1<<10;
139                                 break;
140                         case 101: // Scroll_Texture_Right
141                                 sides[line->sidenum[0]].textureoffset -= line->arg1<<10;
142                                 break;
143                         case 102: // Scroll_Texture_Up
144                                 sides[line->sidenum[0]].rowoffset += line->arg1<<10;
145                                 break;
146                         case 103: // Scroll_Texture_Down
147                                 sides[line->sidenum[0]].rowoffset -= line->arg1<<10;
148                                 break;
149                 }
150         }
151
152         // Update sky column offsets
153         Sky1ColumnOffset += Sky1ScrollDelta;
154         Sky2ColumnOffset += Sky2ScrollDelta;
155
156         if(LevelHasLightning)
157         {
158                 if(!NextLightningFlash || LightningFlash)
159                 {
160                         P_LightningFlash();
161                 }
162                 else
163                 {
164                         NextLightningFlash--;
165                 }
166         }
167 }
168
169 //==========================================================================
170 //
171 // P_LightningFlash
172 //
173 //==========================================================================
174
175 static void P_LightningFlash(void)
176 {
177         int i;
178         sector_t *tempSec;
179         int *tempLight;
180         boolean foundSec;
181         int flashLight;
182
183         if(LightningFlash)
184         {
185                 LightningFlash--;
186                 if(LightningFlash)
187                 {
188                         tempLight = LightningLightLevels;
189                         tempSec = sectors;
190                         for(i = 0; i < numsectors; i++, tempSec++)
191                         {
192                                 if(tempSec->ceilingpic == skyflatnum 
193                                         || tempSec->special == LIGHTNING_SPECIAL
194                                         || tempSec->special == LIGHTNING_SPECIAL2)
195                                 {
196                                         if(*tempLight < tempSec->lightlevel-4)
197                                         {
198                                                 tempSec->lightlevel -= 4;
199                                         }
200                                         tempLight++;
201                                 }
202                         }
203                 }                                       
204                 else
205                 { // remove the alternate lightning flash special
206                         tempLight = LightningLightLevels;
207                         tempSec = sectors;
208                         for(i = 0; i < numsectors; i++, tempSec++)
209                         {
210                                 if(tempSec->ceilingpic == skyflatnum
211                                         || tempSec->special == LIGHTNING_SPECIAL
212                                         || tempSec->special == LIGHTNING_SPECIAL2)
213                                 {
214                                         tempSec->lightlevel = *tempLight;
215                                         tempLight++;
216                                 }
217                         }
218                         Sky1Texture = P_GetMapSky1Texture(gamemap);             
219                 }
220                 return;
221         }
222         LightningFlash = (P_Random()&7)+8;
223         flashLight = 200+(P_Random()&31);
224         tempSec = sectors;
225         tempLight = LightningLightLevels;
226         foundSec = false;
227         for(i = 0; i < numsectors; i++, tempSec++)
228         {
229                 if(tempSec->ceilingpic == skyflatnum
230                                         || tempSec->special == LIGHTNING_SPECIAL
231                                         || tempSec->special == LIGHTNING_SPECIAL2)
232                 {
233                         *tempLight = tempSec->lightlevel;
234                         if(tempSec->special == LIGHTNING_SPECIAL)
235                         { 
236                                 tempSec->lightlevel += 64;
237                                 if(tempSec->lightlevel > flashLight)
238                                 {
239                                         tempSec->lightlevel = flashLight;
240                                 }
241                         }
242                         else if(tempSec->special == LIGHTNING_SPECIAL2)
243                         {
244                                 tempSec->lightlevel += 32;
245                                 if(tempSec->lightlevel > flashLight)
246                                 {
247                                         tempSec->lightlevel = flashLight;
248                                 }
249                         }
250                         else
251                         {
252                                 tempSec->lightlevel = flashLight;
253                         }
254                         if(tempSec->lightlevel < *tempLight)
255                         {
256                                 tempSec->lightlevel = *tempLight;
257                         }
258                         tempLight++;
259                         foundSec = true;
260                 }
261         }
262         if(foundSec)
263         {
264                 Sky1Texture = P_GetMapSky2Texture(gamemap); // set alternate sky                
265                 S_StartSound(NULL, SFX_THUNDER_CRASH);
266         }
267         // Calculate the next lighting flash
268         if(!NextLightningFlash)
269         {
270                 if(P_Random() < 50)
271                 { // Immediate Quick flash
272                         NextLightningFlash = (P_Random()&15)+16;
273                 }
274                 else
275                 {
276                         if(P_Random() < 128 && !(leveltime&32))
277                         {
278                                 NextLightningFlash = ((P_Random()&7)+2)*35;
279                         }
280                         else
281                         {
282                                 NextLightningFlash = ((P_Random()&15)+5)*35;
283                         }
284                 }
285         }
286 }
287
288 //==========================================================================
289 //
290 // P_ForceLightning
291 //
292 //==========================================================================
293
294 void P_ForceLightning(void)
295 {
296         NextLightningFlash = 0;
297 }
298
299 //==========================================================================
300 //
301 // P_InitLightning
302 //
303 //==========================================================================
304
305 void P_InitLightning(void)
306 {
307         int i;
308         int secCount;
309
310         if(!P_GetMapLightning(gamemap))
311         {
312                 LevelHasLightning = false;
313                 LightningFlash = 0;
314                 return;
315         }
316         LightningFlash = 0;
317         secCount = 0;
318         for(i = 0; i < numsectors; i++)
319         {
320                 if(sectors[i].ceilingpic == skyflatnum 
321                         || sectors[i].special == LIGHTNING_SPECIAL
322                         || sectors[i].special == LIGHTNING_SPECIAL2)
323                 {
324                         secCount++;
325                 }
326         }
327         if(secCount)
328         {
329                 LevelHasLightning = true;
330         }
331         else
332         {
333                 LevelHasLightning = false;
334                 return;
335         }
336         LightningLightLevels = (int *)Z_Malloc(secCount*sizeof(int), PU_LEVEL,
337                 NULL);
338         NextLightningFlash = ((P_Random()&15)+5)*35; // don't flash at level start
339 }
340
341 //==========================================================================
342 //
343 // P_InitFTAnims
344 //
345 // Initialize flat and texture animation lists.
346 //
347 //==========================================================================
348
349 void P_InitFTAnims(void)
350 {
351         int base;
352         int mod;
353         int fd;
354         animDef_t *ad;
355         boolean ignore;
356         boolean done;
357
358         fd = 0;
359         ad = AnimDefs;
360         AnimDefCount = 0;
361         SC_Open(ANIM_SCRIPT_NAME);
362         while(SC_GetString())
363         {
364                 if(AnimDefCount == MAX_ANIM_DEFS)
365                 {
366                         I_Error("P_InitFTAnims: too many AnimDefs.");
367                 }
368                 if(SC_Compare(SCI_FLAT))
369                 {
370                         ad->type = ANIM_FLAT;
371                 }
372                 else if(SC_Compare(SCI_TEXTURE))
373                 {
374                         ad->type = ANIM_TEXTURE;
375                 }
376                 else
377                 {
378                         SC_ScriptError(NULL);
379                 }
380                 SC_MustGetString(); // Name
381                 ignore = false;
382                 if(ad->type == ANIM_FLAT)
383                 {
384                         if(W_CheckNumForName(sc_String) == -1)
385                         {
386                                 ignore = true;
387                         }
388                         else
389                         {
390                                 ad->index = R_FlatNumForName(sc_String);
391                         }
392                 }
393                 else
394                 { // Texture
395                         if(R_CheckTextureNumForName(sc_String) == -1)
396                         {
397                                 ignore = true;
398                         }
399                         else
400                         {
401                                 ad->index = R_TextureNumForName(sc_String);
402                         }
403                 }
404                 ad->startFrameDef = fd;
405                 done = false;
406                 while(done == false)
407                 {
408                         if(SC_GetString())
409                         {
410                                 if(SC_Compare(SCI_PIC))
411                                 {
412                                         if(fd == MAX_FRAME_DEFS)
413                                         {
414                                                 I_Error("P_InitFTAnims: too many FrameDefs.");
415                                         }
416                                         SC_MustGetNumber();
417                                         if(ignore == false)
418                                         {
419                                                 FrameDefs[fd].index = ad->index+sc_Number-1;
420                                         }
421                                         SC_MustGetString();
422                                         if(SC_Compare(SCI_TICS))
423                                         {
424                                                 SC_MustGetNumber();
425                                                 if(ignore == false)
426                                                 {
427                                                         FrameDefs[fd].tics = sc_Number;
428                                                         fd++;
429                                                 }
430                                         }
431                                         else if(SC_Compare(SCI_RAND))
432                                         {
433                                                 SC_MustGetNumber();
434                                                 base = sc_Number;
435                                                 SC_MustGetNumber();
436                                                 if(ignore == false)
437                                                 {
438                                                         mod = sc_Number-base+1;
439                                                         FrameDefs[fd].tics = (base<<16)+(mod<<8);
440                                                         fd++;
441                                                 }
442                                         }
443                                         else
444                                         {
445                                                 SC_ScriptError(NULL);
446                                         }
447                                 }
448                                 else
449                                 {
450                                         SC_UnGet();
451                                         done = true;
452                                 }
453                         }
454                         else
455                         {
456                                 done = true;
457                         }
458                 }
459                 if((ignore == false) && (fd-ad->startFrameDef < 2))
460                 {
461                         I_Error("P_InitFTAnims: AnimDef has framecount < 2.");
462                 }
463                 if(ignore == false)
464                 {
465                         ad->endFrameDef = fd-1;
466                         ad->currentFrameDef = ad->endFrameDef;
467                         ad->tics = 1; // Force 1st game tic to animate
468                         AnimDefCount++;
469                         ad++;
470                 }
471         }
472         SC_Close();
473 }
474