474 lines
9.6 KiB
C++
474 lines
9.6 KiB
C++
|
|
||
|
//**************************************************************************
|
||
|
//**
|
||
|
//** p_anim.c : Heretic 2 : Raven Software, Corp.
|
||
|
//**
|
||
|
//** $RCSfile: p_anim.c,v $
|
||
|
//** $Revision: 1.9 $
|
||
|
//** $Date: 95/07/17 18:50:37 $
|
||
|
//** $Author: bgokey $
|
||
|
//**
|
||
|
//**************************************************************************
|
||
|
|
||
|
// HEADER FILES ------------------------------------------------------------
|
||
|
|
||
|
#include "h2def.h"
|
||
|
#include "p_local.h"
|
||
|
|
||
|
// MACROS ------------------------------------------------------------------
|
||
|
|
||
|
#define ANIM_SCRIPT_NAME "ANIMDEFS"
|
||
|
#define MAX_ANIM_DEFS 20
|
||
|
#define MAX_FRAME_DEFS 96
|
||
|
#define ANIM_FLAT 0
|
||
|
#define ANIM_TEXTURE 1
|
||
|
#define SCI_FLAT "flat"
|
||
|
#define SCI_TEXTURE "texture"
|
||
|
#define SCI_PIC "pic"
|
||
|
#define SCI_TICS "tics"
|
||
|
#define SCI_RAND "rand"
|
||
|
|
||
|
#define LIGHTNING_SPECIAL 198
|
||
|
#define LIGHTNING_SPECIAL2 199
|
||
|
#define SKYCHANGE_SPECIAL 200
|
||
|
|
||
|
// TYPES -------------------------------------------------------------------
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int index;
|
||
|
int tics;
|
||
|
} frameDef_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int type;
|
||
|
int index;
|
||
|
int tics;
|
||
|
int currentFrameDef;
|
||
|
int startFrameDef;
|
||
|
int endFrameDef;
|
||
|
} animDef_t;
|
||
|
|
||
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||
|
|
||
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||
|
|
||
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||
|
|
||
|
static void P_LightningFlash(void);
|
||
|
|
||
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||
|
|
||
|
extern fixed_t Sky1ColumnOffset;
|
||
|
extern fixed_t Sky2ColumnOffset;
|
||
|
extern int Sky1Texture;
|
||
|
extern boolean DoubleSky;
|
||
|
|
||
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||
|
|
||
|
fixed_t Sky1ScrollDelta;
|
||
|
fixed_t Sky2ScrollDelta;
|
||
|
|
||
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||
|
|
||
|
static animDef_t AnimDefs[MAX_ANIM_DEFS];
|
||
|
static frameDef_t FrameDefs[MAX_FRAME_DEFS];
|
||
|
static int AnimDefCount;
|
||
|
static boolean LevelHasLightning;
|
||
|
static int NextLightningFlash;
|
||
|
static int LightningFlash;
|
||
|
static int *LightningLightLevels;
|
||
|
|
||
|
// CODE --------------------------------------------------------------------
|
||
|
|
||
|
//==========================================================================
|
||
|
//
|
||
|
// P_AnimateSurfaces
|
||
|
//
|
||
|
//==========================================================================
|
||
|
|
||
|
void P_AnimateSurfaces(void)
|
||
|
{
|
||
|
int i;
|
||
|
animDef_t *ad;
|
||
|
line_t *line;
|
||
|
|
||
|
// Animate flats and textures
|
||
|
for(i = 0; i < AnimDefCount; i++)
|
||
|
{
|
||
|
ad = &AnimDefs[i];
|
||
|
ad->tics--;
|
||
|
if(ad->tics == 0)
|
||
|
{
|
||
|
if(ad->currentFrameDef == ad->endFrameDef)
|
||
|
{
|
||
|
ad->currentFrameDef = ad->startFrameDef;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ad->currentFrameDef++;
|
||
|
}
|
||
|
ad->tics = FrameDefs[ad->currentFrameDef].tics;
|
||
|
if(ad->tics > 255)
|
||
|
{ // Random tics
|
||
|
ad->tics = (ad->tics>>16)
|
||
|
+P_Random()%((ad->tics&0xff00)>>8);
|
||
|
}
|
||
|
if(ad->type == ANIM_FLAT)
|
||
|
{
|
||
|
flattranslation[ad->index] =
|
||
|
FrameDefs[ad->currentFrameDef].index;
|
||
|
}
|
||
|
else
|
||
|
{ // Texture
|
||
|
texturetranslation[ad->index] =
|
||
|
FrameDefs[ad->currentFrameDef].index;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update scrolling textures
|
||
|
for(i = 0; i < numlinespecials; i++)
|
||
|
{
|
||
|
line = linespeciallist[i];
|
||
|
switch(line->special)
|
||
|
{
|
||
|
case 100: // Scroll_Texture_Left
|
||
|
sides[line->sidenum[0]].textureoffset += line->arg1<<10;
|
||
|
break;
|
||
|
case 101: // Scroll_Texture_Right
|
||
|
sides[line->sidenum[0]].textureoffset -= line->arg1<<10;
|
||
|
break;
|
||
|
case 102: // Scroll_Texture_Up
|
||
|
sides[line->sidenum[0]].rowoffset += line->arg1<<10;
|
||
|
break;
|
||
|
case 103: // Scroll_Texture_Down
|
||
|
sides[line->sidenum[0]].rowoffset -= line->arg1<<10;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update sky column offsets
|
||
|
Sky1ColumnOffset += Sky1ScrollDelta;
|
||
|
Sky2ColumnOffset += Sky2ScrollDelta;
|
||
|
|
||
|
if(LevelHasLightning)
|
||
|
{
|
||
|
if(!NextLightningFlash || LightningFlash)
|
||
|
{
|
||
|
P_LightningFlash();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NextLightningFlash--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==========================================================================
|
||
|
//
|
||
|
// P_LightningFlash
|
||
|
//
|
||
|
//==========================================================================
|
||
|
|
||
|
static void P_LightningFlash(void)
|
||
|
{
|
||
|
int i;
|
||
|
sector_t *tempSec;
|
||
|
int *tempLight;
|
||
|
boolean foundSec;
|
||
|
int flashLight;
|
||
|
|
||
|
if(LightningFlash)
|
||
|
{
|
||
|
LightningFlash--;
|
||
|
if(LightningFlash)
|
||
|
{
|
||
|
tempLight = LightningLightLevels;
|
||
|
tempSec = sectors;
|
||
|
for(i = 0; i < numsectors; i++, tempSec++)
|
||
|
{
|
||
|
if(tempSec->ceilingpic == skyflatnum
|
||
|
|| tempSec->special == LIGHTNING_SPECIAL
|
||
|
|| tempSec->special == LIGHTNING_SPECIAL2)
|
||
|
{
|
||
|
if(*tempLight < tempSec->lightlevel-4)
|
||
|
{
|
||
|
tempSec->lightlevel -= 4;
|
||
|
}
|
||
|
tempLight++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{ // remove the alternate lightning flash special
|
||
|
tempLight = LightningLightLevels;
|
||
|
tempSec = sectors;
|
||
|
for(i = 0; i < numsectors; i++, tempSec++)
|
||
|
{
|
||
|
if(tempSec->ceilingpic == skyflatnum
|
||
|
|| tempSec->special == LIGHTNING_SPECIAL
|
||
|
|| tempSec->special == LIGHTNING_SPECIAL2)
|
||
|
{
|
||
|
tempSec->lightlevel = *tempLight;
|
||
|
tempLight++;
|
||
|
}
|
||
|
}
|
||
|
Sky1Texture = P_GetMapSky1Texture(gamemap);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
LightningFlash = (P_Random()&7)+8;
|
||
|
flashLight = 200+(P_Random()&31);
|
||
|
tempSec = sectors;
|
||
|
tempLight = LightningLightLevels;
|
||
|
foundSec = false;
|
||
|
for(i = 0; i < numsectors; i++, tempSec++)
|
||
|
{
|
||
|
if(tempSec->ceilingpic == skyflatnum
|
||
|
|| tempSec->special == LIGHTNING_SPECIAL
|
||
|
|| tempSec->special == LIGHTNING_SPECIAL2)
|
||
|
{
|
||
|
*tempLight = tempSec->lightlevel;
|
||
|
if(tempSec->special == LIGHTNING_SPECIAL)
|
||
|
{
|
||
|
tempSec->lightlevel += 64;
|
||
|
if(tempSec->lightlevel > flashLight)
|
||
|
{
|
||
|
tempSec->lightlevel = flashLight;
|
||
|
}
|
||
|
}
|
||
|
else if(tempSec->special == LIGHTNING_SPECIAL2)
|
||
|
{
|
||
|
tempSec->lightlevel += 32;
|
||
|
if(tempSec->lightlevel > flashLight)
|
||
|
{
|
||
|
tempSec->lightlevel = flashLight;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tempSec->lightlevel = flashLight;
|
||
|
}
|
||
|
if(tempSec->lightlevel < *tempLight)
|
||
|
{
|
||
|
tempSec->lightlevel = *tempLight;
|
||
|
}
|
||
|
tempLight++;
|
||
|
foundSec = true;
|
||
|
}
|
||
|
}
|
||
|
if(foundSec)
|
||
|
{
|
||
|
Sky1Texture = P_GetMapSky2Texture(gamemap); // set alternate sky
|
||
|
S_StartSound(NULL, SFX_THUNDER_CRASH);
|
||
|
}
|
||
|
// Calculate the next lighting flash
|
||
|
if(!NextLightningFlash)
|
||
|
{
|
||
|
if(P_Random() < 50)
|
||
|
{ // Immediate Quick flash
|
||
|
NextLightningFlash = (P_Random()&15)+16;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(P_Random() < 128 && !(leveltime&32))
|
||
|
{
|
||
|
NextLightningFlash = ((P_Random()&7)+2)*35;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NextLightningFlash = ((P_Random()&15)+5)*35;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==========================================================================
|
||
|
//
|
||
|
// P_ForceLightning
|
||
|
//
|
||
|
//==========================================================================
|
||
|
|
||
|
void P_ForceLightning(void)
|
||
|
{
|
||
|
NextLightningFlash = 0;
|
||
|
}
|
||
|
|
||
|
//==========================================================================
|
||
|
//
|
||
|
// P_InitLightning
|
||
|
//
|
||
|
//==========================================================================
|
||
|
|
||
|
void P_InitLightning(void)
|
||
|
{
|
||
|
int i;
|
||
|
int secCount;
|
||
|
|
||
|
if(!P_GetMapLightning(gamemap))
|
||
|
{
|
||
|
LevelHasLightning = false;
|
||
|
LightningFlash = 0;
|
||
|
return;
|
||
|
}
|
||
|
LightningFlash = 0;
|
||
|
secCount = 0;
|
||
|
for(i = 0; i < numsectors; i++)
|
||
|
{
|
||
|
if(sectors[i].ceilingpic == skyflatnum
|
||
|
|| sectors[i].special == LIGHTNING_SPECIAL
|
||
|
|| sectors[i].special == LIGHTNING_SPECIAL2)
|
||
|
{
|
||
|
secCount++;
|
||
|
}
|
||
|
}
|
||
|
if(secCount)
|
||
|
{
|
||
|
LevelHasLightning = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LevelHasLightning = false;
|
||
|
return;
|
||
|
}
|
||
|
LightningLightLevels = (int *)Z_Malloc(secCount*sizeof(int), PU_LEVEL,
|
||
|
NULL);
|
||
|
NextLightningFlash = ((P_Random()&15)+5)*35; // don't flash at level start
|
||
|
}
|
||
|
|
||
|
//==========================================================================
|
||
|
//
|
||
|
// P_InitFTAnims
|
||
|
//
|
||
|
// Initialize flat and texture animation lists.
|
||
|
//
|
||
|
//==========================================================================
|
||
|
|
||
|
void P_InitFTAnims(void)
|
||
|
{
|
||
|
int base;
|
||
|
int mod;
|
||
|
int fd;
|
||
|
animDef_t *ad;
|
||
|
boolean ignore;
|
||
|
boolean done;
|
||
|
|
||
|
fd = 0;
|
||
|
ad = AnimDefs;
|
||
|
AnimDefCount = 0;
|
||
|
SC_Open(ANIM_SCRIPT_NAME);
|
||
|
while(SC_GetString())
|
||
|
{
|
||
|
if(AnimDefCount == MAX_ANIM_DEFS)
|
||
|
{
|
||
|
I_Error("P_InitFTAnims: too many AnimDefs.");
|
||
|
}
|
||
|
if(SC_Compare(SCI_FLAT))
|
||
|
{
|
||
|
ad->type = ANIM_FLAT;
|
||
|
}
|
||
|
else if(SC_Compare(SCI_TEXTURE))
|
||
|
{
|
||
|
ad->type = ANIM_TEXTURE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SC_ScriptError(NULL);
|
||
|
}
|
||
|
SC_MustGetString(); // Name
|
||
|
ignore = false;
|
||
|
if(ad->type == ANIM_FLAT)
|
||
|
{
|
||
|
if(W_CheckNumForName(sc_String) == -1)
|
||
|
{
|
||
|
ignore = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ad->index = R_FlatNumForName(sc_String);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{ // Texture
|
||
|
if(R_CheckTextureNumForName(sc_String) == -1)
|
||
|
{
|
||
|
ignore = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ad->index = R_TextureNumForName(sc_String);
|
||
|
}
|
||
|
}
|
||
|
ad->startFrameDef = fd;
|
||
|
done = false;
|
||
|
while(done == false)
|
||
|
{
|
||
|
if(SC_GetString())
|
||
|
{
|
||
|
if(SC_Compare(SCI_PIC))
|
||
|
{
|
||
|
if(fd == MAX_FRAME_DEFS)
|
||
|
{
|
||
|
I_Error("P_InitFTAnims: too many FrameDefs.");
|
||
|
}
|
||
|
SC_MustGetNumber();
|
||
|
if(ignore == false)
|
||
|
{
|
||
|
FrameDefs[fd].index = ad->index+sc_Number-1;
|
||
|
}
|
||
|
SC_MustGetString();
|
||
|
if(SC_Compare(SCI_TICS))
|
||
|
{
|
||
|
SC_MustGetNumber();
|
||
|
if(ignore == false)
|
||
|
{
|
||
|
FrameDefs[fd].tics = sc_Number;
|
||
|
fd++;
|
||
|
}
|
||
|
}
|
||
|
else if(SC_Compare(SCI_RAND))
|
||
|
{
|
||
|
SC_MustGetNumber();
|
||
|
base = sc_Number;
|
||
|
SC_MustGetNumber();
|
||
|
if(ignore == false)
|
||
|
{
|
||
|
mod = sc_Number-base+1;
|
||
|
FrameDefs[fd].tics = (base<<16)+(mod<<8);
|
||
|
fd++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SC_ScriptError(NULL);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SC_UnGet();
|
||
|
done = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
done = true;
|
||
|
}
|
||
|
}
|
||
|
if((ignore == false) && (fd-ad->startFrameDef < 2))
|
||
|
{
|
||
|
I_Error("P_InitFTAnims: AnimDef has framecount < 2.");
|
||
|
}
|
||
|
if(ignore == false)
|
||
|
{
|
||
|
ad->endFrameDef = fd-1;
|
||
|
ad->currentFrameDef = ad->endFrameDef;
|
||
|
ad->tics = 1; // Force 1st game tic to animate
|
||
|
AnimDefCount++;
|
||
|
ad++;
|
||
|
}
|
||
|
}
|
||
|
SC_Close();
|
||
|
}
|