
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
486 lines
10 KiB
C
486 lines
10 KiB
C
#include "3dc.h"
|
|
|
|
#define UseLocalAssert Yes
|
|
#include "ourasert.h"
|
|
|
|
extern int NormalFrameTime;
|
|
extern int NumActiveBlocks;
|
|
extern DISPLAYBLOCK * ActiveBlockList[];
|
|
|
|
|
|
void CopyAnimationFrameToShape (SHAPEANIMATIONCONTROLDATA *sacd, DISPLAYBLOCK * dptr)
|
|
{
|
|
SHAPEHEADER * shp = dptr->ObShapeData;
|
|
|
|
GLOBALASSERT (sacd->current_frame >= 0);
|
|
GLOBALASSERT (sacd->current_frame < (signed)sacd->sequence->num_frames);
|
|
|
|
shp->points[0] = sacd->sequence->anim_frames[sacd->current_frame].vertices;
|
|
shp->sh_normals[0] = sacd->sequence->anim_frames[sacd->current_frame].item_normals;
|
|
}
|
|
|
|
static void CopyAnimationSequenceDataToObject (SHAPEANIMATIONSEQUENCE * sas, DISPLAYBLOCK * dptr)
|
|
{
|
|
dptr->ObRadius = sas->radius;
|
|
|
|
dptr->ObMaxX = sas->max_x;
|
|
dptr->ObMinX = sas->min_x;
|
|
|
|
dptr->ObMaxY = sas->max_y;
|
|
dptr->ObMinY = sas->min_y;
|
|
|
|
dptr->ObMaxZ = sas->max_z;
|
|
dptr->ObMinZ = sas->min_z;
|
|
}
|
|
|
|
static void ChooseNextFrame (SHAPEANIMATIONCONTROLDATA *current)
|
|
{
|
|
while (current->time_to_next_frame <= 0)
|
|
{
|
|
current->time_to_next_frame += current->seconds_per_frame;
|
|
|
|
if (current->reversed)
|
|
current->current_frame --;
|
|
else
|
|
current->current_frame ++;
|
|
|
|
current->done_a_frame = 1;
|
|
|
|
if (current->current_frame >= (signed)current->sequence->num_frames)
|
|
current->current_frame = 0;
|
|
else if (current->current_frame < 0)
|
|
current->current_frame = current->sequence->num_frames-1;
|
|
|
|
if (current->current_frame == (signed)current->end_frame
|
|
&& current->done_a_frame
|
|
&& (current->stop_at_end || current->pause_at_end))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DoShapeAnimation (DISPLAYBLOCK * dptr)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
SHAPEANIMATIONCONTROLDATA * active_sequence = &sac->current;
|
|
|
|
GLOBALASSERT (sac);
|
|
|
|
if (!sac->playing)
|
|
return;
|
|
|
|
if (active_sequence->empty)
|
|
return;
|
|
|
|
active_sequence->time_to_next_frame -= NormalFrameTime;
|
|
|
|
if (active_sequence->time_to_next_frame > 0)
|
|
return;
|
|
|
|
// At this point we may have switched to the last frame
|
|
// but still had a bit of time left on it
|
|
|
|
if ((active_sequence->current_frame == (signed)active_sequence->end_frame
|
|
&& active_sequence->done_a_frame
|
|
&& active_sequence->stop_at_end) || active_sequence->stop_now)
|
|
{
|
|
// set to next, or finished
|
|
if (sac->next.empty)
|
|
{
|
|
sac->finished = 1;
|
|
sac->playing = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
sac->next.time_to_next_frame = sac->current.time_to_next_frame;
|
|
sac->current = sac->next;
|
|
sac->next.empty = 1;
|
|
|
|
active_sequence->time_to_next_frame += active_sequence->seconds_per_frame;
|
|
ChooseNextFrame (active_sequence);
|
|
|
|
CopyAnimationSequenceDataToObject (active_sequence->sequence, dptr);
|
|
return;
|
|
}
|
|
}
|
|
else if ( active_sequence->current_frame == (signed)active_sequence->end_frame
|
|
&& active_sequence->done_a_frame
|
|
&& active_sequence->pause_at_end)
|
|
{
|
|
active_sequence->pause_at_end = 0;
|
|
sac->playing = 0;
|
|
active_sequence->done_a_frame = 0;
|
|
return;
|
|
}
|
|
|
|
ChooseNextFrame (active_sequence);
|
|
|
|
// if we have reached the last frame and we still have time
|
|
// continue else swap sequences
|
|
|
|
if (active_sequence->time_to_next_frame <= 0)
|
|
{
|
|
if (active_sequence->current_frame == (signed)active_sequence->end_frame
|
|
&& active_sequence->done_a_frame
|
|
&& active_sequence->stop_at_end)
|
|
{
|
|
// set to next, or finished
|
|
if (sac->next.empty)
|
|
{
|
|
sac->finished = 1;
|
|
sac->playing = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
sac->next.time_to_next_frame = sac->current.time_to_next_frame;
|
|
|
|
// this will change the active_sequence pointers contents
|
|
sac->current = sac->next;
|
|
CopyAnimationSequenceDataToObject (active_sequence->sequence, dptr);
|
|
|
|
|
|
// If I had a linked list (or queue) of sequences
|
|
// I may want to put the next bit of code differently
|
|
|
|
active_sequence->time_to_next_frame += active_sequence->seconds_per_frame;
|
|
|
|
ChooseNextFrame (active_sequence);
|
|
|
|
return;
|
|
}
|
|
}
|
|
else if ( active_sequence->current_frame == (signed)active_sequence->end_frame
|
|
&& active_sequence->done_a_frame
|
|
&& active_sequence->pause_at_end)
|
|
{
|
|
active_sequence->pause_at_end = 0;
|
|
sac->playing = 0;
|
|
active_sequence->done_a_frame = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Shouldn't be here
|
|
GLOBALASSERT (0);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void DoAllShapeAnimations ()
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<NumActiveBlocks; i++)
|
|
{
|
|
DISPLAYBLOCK * dptr = ActiveBlockList[i];
|
|
|
|
if (dptr->ShapeAnimControlBlock)
|
|
{
|
|
DoShapeAnimation(dptr);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
unsigned int SetShapeAnimationSequence (DISPLAYBLOCK * dptr, SHAPEANIMATIONCONTROLDATA * sacd)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
GLOBALASSERT(sac);
|
|
GLOBALASSERT(sacd);
|
|
GLOBALASSERT(sacd->sequence_no < sac->anim_header->num_sequences);
|
|
|
|
sac->next.empty = 1;
|
|
|
|
sac->playing = 1;
|
|
sac->finished = 0;
|
|
|
|
sac->current.sequence_no = sacd->sequence_no;
|
|
|
|
sac->current.reversed = sacd->reversed;
|
|
sac->current.stop_at_end = sacd->stop_at_end;
|
|
|
|
|
|
sac->current.empty = 0;
|
|
sac->current.done_a_frame = 0;
|
|
sac->current.sequence = &sac->anim_header->anim_sequences[sacd->sequence_no];
|
|
sac->current.stop_now = 0;
|
|
sac->current.pause_at_end = 0;
|
|
|
|
if (sacd->default_start_and_end_frames)
|
|
{
|
|
if (sacd->reversed)
|
|
{
|
|
sac->current.start_frame = sac->current.sequence->num_frames-1;
|
|
sac->current.end_frame = 0;
|
|
}
|
|
else
|
|
{
|
|
sac->current.start_frame = 0;
|
|
sac->current.end_frame = sac->current.sequence->num_frames-1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sac->current.start_frame = sacd->start_frame;
|
|
sac->current.end_frame = sacd->end_frame;
|
|
}
|
|
|
|
sac->current.seconds_per_frame = sacd->seconds_per_frame;
|
|
|
|
sac->current.current_frame = sac->current.start_frame;
|
|
|
|
sac->current.time_to_next_frame = sac->current.seconds_per_frame;
|
|
|
|
CopyAnimationSequenceDataToObject (sac->current.sequence, dptr);
|
|
|
|
return(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
unsigned int SetNextShapeAnimationSequence (DISPLAYBLOCK * dptr, SHAPEANIMATIONCONTROLDATA * sacd)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
GLOBALASSERT(sac);
|
|
GLOBALASSERT(sacd);
|
|
GLOBALASSERT(sacd->sequence_no < sac->anim_header->num_sequences);
|
|
|
|
|
|
if (sac->current.empty)
|
|
{
|
|
return(SetShapeAnimationSequence (dptr,sacd));
|
|
}
|
|
|
|
if (sac->finished)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
|
|
sac->next.sequence_no = sacd->sequence_no;
|
|
|
|
sac->next.reversed = sacd->reversed;
|
|
sac->next.stop_at_end = sacd->stop_at_end;
|
|
|
|
|
|
sac->next.empty = 0;
|
|
sac->next.done_a_frame = 0;
|
|
sac->next.sequence = &sac->anim_header->anim_sequences[sacd->sequence_no];
|
|
sac->next.stop_now = 0;
|
|
sac->next.pause_at_end = 0;
|
|
|
|
if (sacd->default_start_and_end_frames)
|
|
{
|
|
if (sacd->reversed)
|
|
{
|
|
sac->next.start_frame = sac->next.sequence->num_frames-1;
|
|
sac->next.end_frame = 0;
|
|
}
|
|
else
|
|
{
|
|
sac->next.start_frame = 0;
|
|
sac->next.end_frame = sac->next.sequence->num_frames-1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sac->next.start_frame = sacd->start_frame;
|
|
sac->next.end_frame = sacd->end_frame;
|
|
}
|
|
|
|
sac->next.seconds_per_frame = sacd->seconds_per_frame;
|
|
|
|
sac->next.current_frame = sac->next.start_frame;
|
|
|
|
sac->next.time_to_next_frame = sac->next.seconds_per_frame;
|
|
|
|
return(1);
|
|
|
|
|
|
}
|
|
|
|
void InitShapeAnimationController (SHAPEANIMATIONCONTROLLER * sac, SHAPEHEADER * shd)
|
|
{
|
|
GLOBALASSERT(shd);
|
|
GLOBALASSERT(shd->animation_header);
|
|
|
|
sac->current.empty = 1;
|
|
sac->next.empty = 1;
|
|
|
|
sac->anim_header = shd->animation_header;
|
|
|
|
sac->playing = 0;
|
|
|
|
}
|
|
|
|
void SetCurrentShapeAnimationToStop (DISPLAYBLOCK * dptr, unsigned long stop_now, signed long end_frame)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
GLOBALASSERT(sac);
|
|
|
|
if (stop_now)
|
|
{
|
|
sac->current.stop_now = 1;
|
|
return;
|
|
}
|
|
|
|
if (end_frame != -1)
|
|
{
|
|
GLOBALASSERT (end_frame >= 0);
|
|
GLOBALASSERT (end_frame < (signed)sac->current.sequence->num_frames);
|
|
|
|
sac->current.end_frame = end_frame;
|
|
}
|
|
|
|
sac->current.stop_at_end = 1;
|
|
|
|
}
|
|
|
|
|
|
SHAPEANIMATIONCONTROLDATA const * GetCurrentShapeAnimationSequenceData (DISPLAYBLOCK * dptr)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
if (sac)
|
|
{
|
|
if (!sac->current.empty)
|
|
return(&sac->current);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
SHAPEANIMATIONCONTROLDATA const * GetNextShapeAnimationSequenceData (DISPLAYBLOCK * dptr)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
if (sac)
|
|
{
|
|
if (!sac->next.empty)
|
|
return(&sac->next);
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
void PauseCurrentShapeAnimation (DISPLAYBLOCK * dptr, unsigned long pause_now, signed long end_frame)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
GLOBALASSERT(sac);
|
|
|
|
if (pause_now)
|
|
{
|
|
sac->playing = 0;
|
|
return;
|
|
}
|
|
|
|
if (end_frame != -1)
|
|
{
|
|
GLOBALASSERT (end_frame >= 0);
|
|
GLOBALASSERT (end_frame < (signed)sac->current.sequence->num_frames);
|
|
|
|
sac->current.end_frame = end_frame;
|
|
}
|
|
|
|
sac->current.pause_at_end = 1;
|
|
|
|
}
|
|
|
|
void RestartCurrentShapeAnimation (DISPLAYBLOCK * dptr)
|
|
{
|
|
SHAPEANIMATIONCONTROLLER * sac = dptr->ShapeAnimControlBlock;
|
|
|
|
GLOBALASSERT(sac);
|
|
|
|
sac->playing = 1;
|
|
|
|
sac->current.pause_at_end = 0;
|
|
|
|
}
|
|
|
|
|
|
void InitShapeAnimationControlData (SHAPEANIMATIONCONTROLDATA * sacd)
|
|
{
|
|
GLOBALASSERT(sacd);
|
|
|
|
sacd->seconds_per_frame = 8192;
|
|
|
|
sacd->sequence_no = 0;
|
|
|
|
sacd->default_start_and_end_frames = 1;
|
|
sacd->reversed = 0;
|
|
|
|
sacd->stop_at_end = 0;
|
|
|
|
}
|
|
|
|
unsigned int SetOrphanedShapeAnimationSequence (SHAPEANIMATIONCONTROLLER * sac, SHAPEANIMATIONCONTROLDATA * sacd)
|
|
{
|
|
|
|
GLOBALASSERT(sac);
|
|
GLOBALASSERT(sacd);
|
|
GLOBALASSERT(sacd->sequence_no < sac->anim_header->num_sequences);
|
|
|
|
sac->next.empty = 1;
|
|
|
|
sac->playing = 1;
|
|
sac->finished = 0;
|
|
|
|
sac->current.sequence_no = sacd->sequence_no;
|
|
|
|
sac->current.reversed = sacd->reversed;
|
|
sac->current.stop_at_end = sacd->stop_at_end;
|
|
|
|
|
|
sac->current.empty = 0;
|
|
sac->current.done_a_frame = 0;
|
|
sac->current.sequence = &sac->anim_header->anim_sequences[sacd->sequence_no];
|
|
sac->current.stop_now = 0;
|
|
sac->current.pause_at_end = 0;
|
|
|
|
if (sacd->default_start_and_end_frames)
|
|
{
|
|
if (sacd->reversed)
|
|
{
|
|
sac->current.start_frame = sac->current.sequence->num_frames-1;
|
|
sac->current.end_frame = 0;
|
|
}
|
|
else
|
|
{
|
|
sac->current.start_frame = 0;
|
|
sac->current.end_frame = sac->current.sequence->num_frames-1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sac->current.start_frame = sacd->start_frame;
|
|
sac->current.end_frame = sacd->end_frame;
|
|
}
|
|
|
|
sac->current.seconds_per_frame = sacd->seconds_per_frame;
|
|
|
|
sac->current.current_frame = sac->current.start_frame;
|
|
|
|
sac->current.time_to_next_frame = sac->current.seconds_per_frame;
|
|
|
|
/* CopyAnimationSequenceDataToObject (sac->current.sequence, dptr); */
|
|
|
|
return(1);
|
|
|
|
|
|
}
|