Comm animation processing rewrite; cleaner and meaner; a bunch of bugs fixed, and some probably added ;)
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3305 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
Changes towards version 0.7:
|
Changes towards version 0.7:
|
||||||
|
- Comm animation processing rewrite, bugs fixed - Alex
|
||||||
- Added graphics context debugging function - SvdB
|
- Added graphics context debugging function - SvdB
|
||||||
- Thread down-throttling and game sleep when inactive (currently disabled),
|
- Thread down-throttling and game sleep when inactive (currently disabled),
|
||||||
(bug #1070), from Flandry
|
(bug #1070), from Flandry
|
||||||
|
|||||||
+52
-111
@@ -53,6 +53,8 @@ LOCDATA CommData;
|
|||||||
int cur_comm;
|
int cur_comm;
|
||||||
UNICODE shared_phrase_buf[2048];
|
UNICODE shared_phrase_buf[2048];
|
||||||
|
|
||||||
|
static BOOLEAN TalkingFinished;
|
||||||
|
|
||||||
typedef struct response_entry
|
typedef struct response_entry
|
||||||
{
|
{
|
||||||
RESPONSE_REF response_ref;
|
RESPONSE_REF response_ref;
|
||||||
@@ -87,7 +89,6 @@ static const UNICODE * volatile last_subtitle;
|
|||||||
static CONTEXT TextCacheContext;
|
static CONTEXT TextCacheContext;
|
||||||
static FRAME TextCacheFrame;
|
static FRAME TextCacheFrame;
|
||||||
|
|
||||||
volatile BOOLEAN ClearSummary;
|
|
||||||
|
|
||||||
RECT CommWndRect = {
|
RECT CommWndRect = {
|
||||||
// default values; actually inited by HailAlien()
|
// default values; actually inited by HailAlien()
|
||||||
@@ -382,51 +383,6 @@ DrawSISComWindow (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
DrawAlienFrame (FRAME aframe, SEQUENCE *pSeq)
|
|
||||||
{
|
|
||||||
COUNT i;
|
|
||||||
STAMP s;
|
|
||||||
ANIMATION_DESC *ADPtr;
|
|
||||||
|
|
||||||
s.origin.x = -SAFE_X;
|
|
||||||
s.origin.y = 0;
|
|
||||||
s.frame = CommData.AlienFrame;
|
|
||||||
if (s.frame == 0)
|
|
||||||
s.frame = aframe;
|
|
||||||
|
|
||||||
BatchGraphics ();
|
|
||||||
DrawStamp (&s);
|
|
||||||
i = CommData.NumAnimations;
|
|
||||||
ADPtr = &CommData.AlienAmbientArray[i];
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
--ADPtr;
|
|
||||||
|
|
||||||
if (!(ADPtr->AnimFlags & ANIM_MASK))
|
|
||||||
{
|
|
||||||
s.frame = SetAbsFrameIndex (s.frame, ADPtr->StartIndex);
|
|
||||||
DrawStamp (&s);
|
|
||||||
ADPtr->AnimFlags |= ANIM_DISABLED;
|
|
||||||
}
|
|
||||||
else if (pSeq)
|
|
||||||
{
|
|
||||||
if (pSeq->AnimType == PICTURE_ANIM)
|
|
||||||
{
|
|
||||||
s.frame = pSeq->AnimObj.CurFrame;
|
|
||||||
DrawStamp (&s);
|
|
||||||
}
|
|
||||||
--pSeq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (aframe && CommData.AlienFrame && aframe != CommData.AlienFrame)
|
|
||||||
{
|
|
||||||
s.frame = aframe;
|
|
||||||
DrawStamp (&s);
|
|
||||||
}
|
|
||||||
UnbatchGraphics ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
init_communication (void)
|
init_communication (void)
|
||||||
{
|
{
|
||||||
@@ -553,13 +509,11 @@ SpewPhrases (COUNT wait_track)
|
|||||||
BOOLEAN ContinuityBreak;
|
BOOLEAN ContinuityBreak;
|
||||||
DWORD TimeIn;
|
DWORD TimeIn;
|
||||||
COUNT which_track;
|
COUNT which_track;
|
||||||
FRAME F;
|
|
||||||
BOOLEAN rewind = FALSE;
|
BOOLEAN rewind = FALSE;
|
||||||
|
|
||||||
TimeIn = GetTimeCounter ();
|
TimeIn = GetTimeCounter ();
|
||||||
|
|
||||||
ContinuityBreak = FALSE;
|
ContinuityBreak = FALSE;
|
||||||
F = CommData.AlienFrame;
|
|
||||||
if (wait_track == 0)
|
if (wait_track == 0)
|
||||||
{ // Restarting with a rewind
|
{ // Restarting with a rewind
|
||||||
wait_track = (COUNT)~0;
|
wait_track = (COUNT)~0;
|
||||||
@@ -636,12 +590,10 @@ SpewPhrases (COUNT wait_track)
|
|||||||
else if (optSmoothScroll == OPT_3DO)
|
else if (optSmoothScroll == OPT_3DO)
|
||||||
FastForward_Smooth ();
|
FastForward_Smooth ();
|
||||||
ContinuityBreak = TRUE;
|
ContinuityBreak = TRUE;
|
||||||
// XXX: Ugly hack: This causes all animations (talking and ambient)
|
// XXX: This causes all animations (talking and ambient)
|
||||||
// in ambient_anim_task to stop progressing. I see no reason why
|
// in ambient_anim_task to stop progressing. I see no reason why
|
||||||
// the animations cannot continue while seeking. This hack has
|
// the animations cannot continue while seeking.
|
||||||
// spawned a multitude of workarounds in the comm code, and IMHO
|
PauseAnimTask = TRUE;
|
||||||
// should be removed.
|
|
||||||
CommData.AlienFrame = 0;
|
|
||||||
}
|
}
|
||||||
else if (left || rewind)
|
else if (left || rewind)
|
||||||
{
|
{
|
||||||
@@ -652,8 +604,8 @@ SpewPhrases (COUNT wait_track)
|
|||||||
else if (optSmoothScroll == OPT_3DO)
|
else if (optSmoothScroll == OPT_3DO)
|
||||||
FastReverse_Smooth ();
|
FastReverse_Smooth ();
|
||||||
ContinuityBreak = TRUE;
|
ContinuityBreak = TRUE;
|
||||||
// XXX: See ugly hack discussion above
|
// XXX: See pause discussion above
|
||||||
CommData.AlienFrame = 0;
|
PauseAnimTask = TRUE;
|
||||||
}
|
}
|
||||||
else if (ContinuityBreak)
|
else if (ContinuityBreak)
|
||||||
{
|
{
|
||||||
@@ -663,20 +615,20 @@ SpewPhrases (COUNT wait_track)
|
|||||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
|
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // XXX: See ugly hack discussion above
|
{ // XXX: See pause discussion above
|
||||||
// Additionally, this used to have a buggy guard condition, which
|
// Additionally, this used to have a buggy guard condition, which
|
||||||
// would cause the animations to remain paused in a couple cases
|
// would cause the animations to remain paused in a couple cases
|
||||||
// after seeking back to the beginning.
|
// after seeking back to the beginning.
|
||||||
// Broken cases were: Syreen "several hours later" and Starbase
|
// Broken cases were: Syreen "several hours later" and Starbase
|
||||||
// VUX Beast analysis by the scientist.
|
// VUX Beast analysis by the scientist.
|
||||||
CommData.AlienFrame = F;
|
PauseAnimTask = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
which_track = PlayingTrack ();
|
which_track = PlayingTrack ();
|
||||||
|
|
||||||
} while (ContinuityBreak || (which_track && which_track <= wait_track));
|
} while (ContinuityBreak || (which_track && which_track <= wait_track));
|
||||||
|
|
||||||
CommData.AlienFrame = F;
|
PauseAnimTask = FALSE;
|
||||||
ClearSubtitles ();
|
ClearSubtitles ();
|
||||||
|
|
||||||
if (!which_track || wait_track == (COUNT)~0)
|
if (!which_track || wait_track == (COUNT)~0)
|
||||||
@@ -696,22 +648,17 @@ DoTalkSegue (COUNT wait_track)
|
|||||||
BOOLEAN done;
|
BOOLEAN done;
|
||||||
|
|
||||||
// Transition animation to talking state, if necessary
|
// Transition animation to talking state, if necessary
|
||||||
if (CommData.AlienTalkDesc.NumFrames)
|
if (wantTalkingAnim () && haveTalkingAnim ())
|
||||||
{
|
{
|
||||||
if (!(CommData.AlienTransitionDesc.AnimFlags & TALK_INTRO))
|
if (haveTransitionAnim ())
|
||||||
{
|
setRunIntroAnim ();
|
||||||
CommData.AlienTransitionDesc.AnimFlags |= TALK_INTRO;
|
|
||||||
if (CommData.AlienTransitionDesc.NumFrames)
|
|
||||||
CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags &= ~PAUSE_TALKING;
|
setRunTalkingAnim ();
|
||||||
if (CommData.AlienTalkDesc.NumFrames)
|
|
||||||
CommData.AlienTalkDesc.AnimFlags |= WAIT_TALKING;
|
while (runningIntroAnim ())
|
||||||
while (CommData.AlienTalkDesc.AnimFlags & TALK_INTRO)
|
|
||||||
{ // wait until the transition finishes
|
{ // wait until the transition finishes
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
TaskSwitch ();
|
SleepThread (ONE_SECOND / 30);
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -719,14 +666,8 @@ DoTalkSegue (COUNT wait_track)
|
|||||||
done = !SpewPhrases (wait_track);
|
done = !SpewPhrases (wait_track);
|
||||||
|
|
||||||
// transition back to silent, if necessary
|
// transition back to silent, if necessary
|
||||||
if (CommData.AlienTalkDesc.NumFrames)
|
if (runningTalkingAnim ())
|
||||||
{
|
setStopTalkingAnim ();
|
||||||
// must set the TALK_DONE flag so that the animation task
|
|
||||||
// releases WAIT_TALKING from AlienTalkDesc
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
|
||||||
if ((CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING))
|
|
||||||
CommData.AlienTalkDesc.AnimFlags |= PAUSE_TALKING;
|
|
||||||
}
|
|
||||||
|
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
@@ -734,13 +675,15 @@ DoTalkSegue (COUNT wait_track)
|
|||||||
static void
|
static void
|
||||||
FlushTalkSegue (void)
|
FlushTalkSegue (void)
|
||||||
{
|
{
|
||||||
|
WaitForNoInput (ONE_SECOND / 2);
|
||||||
FlushInput ();
|
FlushInput ();
|
||||||
while (AnyButtonPress (TRUE))
|
|
||||||
TaskSwitch ();
|
|
||||||
|
|
||||||
|
// Wait until the animation task stops "talking"
|
||||||
do
|
do
|
||||||
TaskSwitch ();
|
SleepThread (ONE_SECOND / 30);
|
||||||
while (CommData.AlienTalkDesc.AnimFlags & PAUSE_TALKING);
|
while (runningTalkingAnim ());
|
||||||
|
|
||||||
|
TalkingFinished = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -749,8 +692,7 @@ AlienTalkSegue (COUNT wait_track)
|
|||||||
BOOLEAN done;
|
BOOLEAN done;
|
||||||
|
|
||||||
// this skips any talk segues that follow an aborted one
|
// this skips any talk segues that follow an aborted one
|
||||||
if ((GLOBAL (CurrentActivity) & CHECK_ABORT)
|
if ((GLOBAL (CurrentActivity) & CHECK_ABORT) || TalkingFinished)
|
||||||
|| (CommData.AlienTransitionDesc.AnimFlags & TALK_DONE))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
@@ -758,7 +700,7 @@ AlienTalkSegue (COUNT wait_track)
|
|||||||
if (!pCurInputState->Initialized)
|
if (!pCurInputState->Initialized)
|
||||||
{
|
{
|
||||||
SetColorMap (GetColorMapAddress (CommData.AlienColorMap));
|
SetColorMap (GetColorMapAddress (CommData.AlienColorMap));
|
||||||
DrawAlienFrame (CommData.AlienFrame, NULL);
|
DrawAlienFrame (NULL, 0, TRUE);
|
||||||
UpdateSpeechGraphics (TRUE);
|
UpdateSpeechGraphics (TRUE);
|
||||||
|
|
||||||
if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE
|
if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE
|
||||||
@@ -807,8 +749,9 @@ AlienTalkSegue (COUNT wait_track)
|
|||||||
DWORD TimeOut;
|
DWORD TimeOut;
|
||||||
|
|
||||||
TimeOut = GetTimeCounter () + (ONE_SECOND >> 1);
|
TimeOut = GetTimeCounter () + (ONE_SECOND >> 1);
|
||||||
/* if (CommData.NumAnimations) */
|
// Anim task processes not only ambient animations, but also
|
||||||
pCurInputState->AnimTask = StartCommAnimTask ();
|
// talking animations and subtitles
|
||||||
|
pCurInputState->AnimTask = StartCommAnimTask ();
|
||||||
|
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
SleepThreadUntil (TimeOut);
|
SleepThreadUntil (TimeOut);
|
||||||
@@ -825,15 +768,9 @@ AlienTalkSegue (COUNT wait_track)
|
|||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
FlushTalkSegue ();
|
FlushTalkSegue ();
|
||||||
|
|
||||||
if (done || wait_track == (COUNT)~0)
|
if (!done && wait_track != (COUNT)~0)
|
||||||
{ // all done talking here
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // there is more to come
|
{ // there is more to come
|
||||||
CommData.AlienTransitionDesc.AnimFlags &= ~TALK_DONE;
|
TalkingFinished = FALSE;
|
||||||
// allow a transition to talking state again later
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags &= ~TALK_INTRO;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1000,7 +937,7 @@ SelectResponse (ENCOUNTER_STATE *pES)
|
|||||||
|
|
||||||
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
||||||
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE);
|
TalkingFinished = FALSE;
|
||||||
pES->num_responses = 0;
|
pES->num_responses = 0;
|
||||||
(*pES->response_list[pES->cur_response].response_func)
|
(*pES->response_list[pES->cur_response].response_func)
|
||||||
(pES->response_list[pES->cur_response].response_ref);
|
(pES->response_list[pES->cur_response].response_ref);
|
||||||
@@ -1024,7 +961,7 @@ SelectConversationSummary (ENCOUNTER_STATE *pES)
|
|||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
RefreshResponses (pES);
|
RefreshResponses (pES);
|
||||||
ClearSummary = TRUE;
|
clear_subtitles = TRUE;
|
||||||
PauseAnimTask = FALSE;
|
PauseAnimTask = FALSE;
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
@@ -1060,9 +997,7 @@ PlayerResponseInput (ENCOUNTER_STATE *pES)
|
|||||||
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
FeedbackPlayerPhrase (pES->phrase_buf);
|
FeedbackPlayerPhrase (pES->phrase_buf);
|
||||||
// reset transition state
|
TalkingFinished = FALSE;
|
||||||
CommData.AlienTransitionDesc.AnimFlags &=
|
|
||||||
~(TALK_INTRO | TALK_DONE);
|
|
||||||
DoTalkSegue (0);
|
DoTalkSegue (0);
|
||||||
|
|
||||||
if (!(GLOBAL (CurrentActivity) & CHECK_ABORT))
|
if (!(GLOBAL (CurrentActivity) & CHECK_ABORT))
|
||||||
@@ -1073,9 +1008,6 @@ PlayerResponseInput (ENCOUNTER_STATE *pES)
|
|||||||
|
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
FlushTalkSegue ();
|
FlushTalkSegue ();
|
||||||
// done one way or the other
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (PulsedInputState.menu[KEY_MENU_UP])
|
else if (PulsedInputState.menu[KEY_MENU_UP])
|
||||||
response = (BYTE)((response + (BYTE)(pES->num_responses - 1))
|
response = (BYTE)((response + (BYTE)(pES->num_responses - 1))
|
||||||
@@ -1119,7 +1051,8 @@ DoCommunication (ENCOUNTER_STATE *pES)
|
|||||||
{
|
{
|
||||||
SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT);
|
SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT);
|
||||||
|
|
||||||
if (!(CommData.AlienTransitionDesc.AnimFlags & TALK_DONE))
|
// First, finish playing all queued tracks if not done yet
|
||||||
|
if (!TalkingFinished)
|
||||||
AlienTalkSegue ((COUNT)~0);
|
AlienTalkSegue ((COUNT)~0);
|
||||||
|
|
||||||
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
||||||
@@ -1141,14 +1074,10 @@ DoCommunication (ENCOUNTER_STATE *pES)
|
|||||||
{
|
{
|
||||||
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
// reset transition state
|
TalkingFinished = FALSE;
|
||||||
CommData.AlienTransitionDesc.AnimFlags &=
|
|
||||||
~(TALK_INTRO | TALK_DONE);
|
|
||||||
DoTalkSegue (0);
|
DoTalkSegue (0);
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
FlushTalkSegue ();
|
FlushTalkSegue ();
|
||||||
// done one way or the other
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
|
||||||
|
|
||||||
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
||||||
break;
|
break;
|
||||||
@@ -1172,7 +1101,6 @@ DoCommunication (ENCOUNTER_STATE *pES)
|
|||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
pES->AnimTask = 0;
|
pES->AnimTask = 0;
|
||||||
}
|
}
|
||||||
CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE);
|
|
||||||
|
|
||||||
SetContext (SpaceContext);
|
SetContext (SpaceContext);
|
||||||
DestroyContext (TaskContext);
|
DestroyContext (TaskContext);
|
||||||
@@ -1243,6 +1171,8 @@ HailAlien (void)
|
|||||||
pCurInputState = &ES;
|
pCurInputState = &ES;
|
||||||
memset (pCurInputState, 0, sizeof (*pCurInputState));
|
memset (pCurInputState, 0, sizeof (*pCurInputState));
|
||||||
|
|
||||||
|
TalkingFinished = FALSE;
|
||||||
|
|
||||||
ES.InputFunc = DoCommunication;
|
ES.InputFunc = DoCommunication;
|
||||||
PlayerFont = LoadFont (PLAYER_FONT);
|
PlayerFont = LoadFont (PLAYER_FONT);
|
||||||
|
|
||||||
@@ -1443,7 +1373,9 @@ InitCommunication (CONVERSATION which_comm)
|
|||||||
status != YEHAT_REBEL_SHIP ? which_comm :
|
status != YEHAT_REBEL_SHIP ? which_comm :
|
||||||
YEHAT_REBEL_CONVERSATION);
|
YEHAT_REBEL_CONVERSATION);
|
||||||
if (LocDataPtr)
|
if (LocDataPtr)
|
||||||
|
{ // We make a copy here
|
||||||
CommData = *LocDataPtr;
|
CommData = *LocDataPtr;
|
||||||
|
}
|
||||||
|
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
@@ -1717,3 +1649,12 @@ CheckSubtitles (void)
|
|||||||
}
|
}
|
||||||
UnlockMutex (subtitle_mutex);
|
UnlockMutex (subtitle_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EnableTalkingAnim (BOOLEAN enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
CommData.AlienTalkDesc.AnimFlags &= ~PAUSE_TALKING;
|
||||||
|
else
|
||||||
|
CommData.AlienTalkDesc.AnimFlags |= PAUSE_TALKING;
|
||||||
|
}
|
||||||
|
|||||||
+68
-3
@@ -28,10 +28,73 @@
|
|||||||
|
|
||||||
#include "commanim.h"
|
#include "commanim.h"
|
||||||
|
|
||||||
extern void DrawAlienFrame (FRAME aframe, SEQUENCE *pSeq);
|
|
||||||
|
|
||||||
extern LOCDATA CommData;
|
extern LOCDATA CommData;
|
||||||
extern volatile BOOLEAN ClearSummary;
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
haveTalkingAnim (void)
|
||||||
|
{
|
||||||
|
return CommData.AlienTalkDesc.NumFrames > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
haveTransitionAnim (void)
|
||||||
|
{
|
||||||
|
return CommData.AlienTransitionDesc.NumFrames > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
wantTalkingAnim (void)
|
||||||
|
{
|
||||||
|
return !(CommData.AlienTalkDesc.AnimFlags & PAUSE_TALKING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
setRunTalkingAnim (void)
|
||||||
|
{
|
||||||
|
CommData.AlienTalkDesc.AnimFlags |= WAIT_TALKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
clearRunTalkingAnim (void)
|
||||||
|
{
|
||||||
|
CommData.AlienTalkDesc.AnimFlags &= ~WAIT_TALKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
runningTalkingAnim (void)
|
||||||
|
{
|
||||||
|
return (CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
setRunIntroAnim (void)
|
||||||
|
{
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags |= TALK_INTRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
runningIntroAnim (void)
|
||||||
|
{
|
||||||
|
return (CommData.AlienTransitionDesc.AnimFlags & TALK_INTRO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
setStopTalkingAnim (void)
|
||||||
|
{
|
||||||
|
CommData.AlienTalkDesc.AnimFlags |= TALK_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
clearStopTalkingAnim (void)
|
||||||
|
{
|
||||||
|
CommData.AlienTalkDesc.AnimFlags &= ~TALK_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
signaledStopTalkingAnim (void)
|
||||||
|
{
|
||||||
|
return CommData.AlienTalkDesc.AnimFlags & TALK_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -45,6 +108,8 @@ extern BOOLEAN HaveSubtitlesChanged (void);
|
|||||||
|
|
||||||
extern RECT CommWndRect; /* comm window rect */
|
extern RECT CommWndRect; /* comm window rect */
|
||||||
|
|
||||||
|
extern void EnableTalkingAnim (BOOLEAN enable);
|
||||||
|
|
||||||
#endif /* _COMM_H */
|
#endif /* _COMM_H */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -838,14 +838,13 @@ Intro (void)
|
|||||||
|
|
||||||
if (!GET_GAME_STATE (MET_ORZ_BEFORE))
|
if (!GET_GAME_STATE (MET_ORZ_BEFORE))
|
||||||
{
|
{
|
||||||
BYTE N;
|
|
||||||
|
|
||||||
SET_GAME_STATE (MET_ORZ_BEFORE, 1);
|
SET_GAME_STATE (MET_ORZ_BEFORE, 1);
|
||||||
|
|
||||||
N = CommData.AlienTalkDesc.NumFrames;
|
// Disable talking anim and run the computer report
|
||||||
CommData.AlienTalkDesc.NumFrames = 0;
|
EnableTalkingAnim (FALSE);
|
||||||
AlienTalkSegue (1);
|
AlienTalkSegue (1);
|
||||||
CommData.AlienTalkDesc.NumFrames = N;
|
// Run whatever is left with talking anim
|
||||||
|
EnableTalkingAnim (TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1291,11 +1291,10 @@ DiscussDevices (BOOLEAN TalkAbout)
|
|||||||
// Run all tracks upto the Vux Beast scientist's report
|
// Run all tracks upto the Vux Beast scientist's report
|
||||||
AlienTalkSegue (VuxBeastIndex - 1);
|
AlienTalkSegue (VuxBeastIndex - 1);
|
||||||
// Disable Commander's speech animation and run the report
|
// Disable Commander's speech animation and run the report
|
||||||
i = CommData.AlienTalkDesc.NumFrames;
|
EnableTalkingAnim (FALSE);
|
||||||
CommData.AlienTalkDesc.NumFrames = 0;
|
|
||||||
AlienTalkSegue (VuxBeastIndex);
|
AlienTalkSegue (VuxBeastIndex);
|
||||||
// Enable Commander's speech animation and run the rest
|
// Enable Commander's speech animation and run the rest
|
||||||
CommData.AlienTalkDesc.NumFrames = i;
|
EnableTalkingAnim (TRUE);
|
||||||
AlienTalkSegue ((COUNT)~0);
|
AlienTalkSegue ((COUNT)~0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,9 +123,12 @@ SelectAlienZOQ (void)
|
|||||||
{
|
{
|
||||||
if (LastAlien != ZOQ_ALIEN)
|
if (LastAlien != ZOQ_ALIEN)
|
||||||
{
|
{
|
||||||
|
// Transition to neutral state first if Pik was talking
|
||||||
|
if (LastAlien != FOT_ALIEN)
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
||||||
LastAlien = ZOQ_ALIEN;
|
LastAlien = ZOQ_ALIEN;
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags |= TALK_INTRO;
|
||||||
CommData.AlienTransitionDesc.StartIndex = FOT_TO_ZOQ;
|
CommData.AlienTransitionDesc.StartIndex = FOT_TO_ZOQ;
|
||||||
CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO;
|
|
||||||
CommData.AlienTalkDesc.StartIndex = ZOQ_TALK_INDEX;
|
CommData.AlienTalkDesc.StartIndex = ZOQ_TALK_INDEX;
|
||||||
CommData.AlienTalkDesc.NumFrames = ZOQ_TALK_FRAMES;
|
CommData.AlienTalkDesc.NumFrames = ZOQ_TALK_FRAMES;
|
||||||
CommData.AlienAmbientArray[1].AnimFlags &= ~WAIT_TALKING;
|
CommData.AlienAmbientArray[1].AnimFlags &= ~WAIT_TALKING;
|
||||||
@@ -142,9 +145,12 @@ SelectAlienPIK (void)
|
|||||||
{
|
{
|
||||||
if (LastAlien != PIK_ALIEN)
|
if (LastAlien != PIK_ALIEN)
|
||||||
{
|
{
|
||||||
|
// Transition to neutral state first if Zoq was talking
|
||||||
|
if (LastAlien != FOT_ALIEN)
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
||||||
LastAlien = PIK_ALIEN;
|
LastAlien = PIK_ALIEN;
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags |= TALK_INTRO;
|
||||||
CommData.AlienTransitionDesc.StartIndex = FOT_TO_PIK;
|
CommData.AlienTransitionDesc.StartIndex = FOT_TO_PIK;
|
||||||
CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO;
|
|
||||||
CommData.AlienTalkDesc.StartIndex = PIK_TALK_INDEX;
|
CommData.AlienTalkDesc.StartIndex = PIK_TALK_INDEX;
|
||||||
CommData.AlienTalkDesc.NumFrames = PIK_TALK_FRAMES;
|
CommData.AlienTalkDesc.NumFrames = PIK_TALK_FRAMES;
|
||||||
CommData.AlienAmbientArray[1].AnimFlags |= WAIT_TALKING;
|
CommData.AlienAmbientArray[1].AnimFlags |= WAIT_TALKING;
|
||||||
|
|||||||
+484
-382
@@ -44,118 +44,371 @@ static int ambient_anim_task (void *data);
|
|||||||
|
|
||||||
volatile BOOLEAN PauseAnimTask = FALSE;
|
volatile BOOLEAN PauseAnimTask = FALSE;
|
||||||
|
|
||||||
|
static inline DWORD
|
||||||
|
randomFrameRate (SEQUENCE *pSeq)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
return ADPtr->BaseFrameRate +
|
||||||
|
TFB_Random () % (ADPtr->RandomFrameRate + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline DWORD
|
||||||
|
randomRestartRate (SEQUENCE *pSeq)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
return ADPtr->BaseRestartRate +
|
||||||
|
TFB_Random () % (ADPtr->RandomRestartRate + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline COUNT
|
||||||
|
randomFrameIndex (SEQUENCE *pSeq, COUNT from)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
return from + TFB_Random () % (ADPtr->NumFrames - from);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SetUpSequence (SEQUENCE *pSeq)
|
SetupAmbientSequences (SEQUENCE *pSeq, COUNT Num)
|
||||||
{
|
{
|
||||||
COUNT i;
|
COUNT i;
|
||||||
ANIMATION_DESC *ADPtr;
|
|
||||||
|
for (i = 0; i < Num; ++i, ++pSeq)
|
||||||
i = CommData.NumAnimations;
|
|
||||||
pSeq = &pSeq[i];
|
|
||||||
ADPtr = &CommData.AlienAmbientArray[i];
|
|
||||||
while (i--)
|
|
||||||
{
|
{
|
||||||
--ADPtr;
|
ANIMATION_DESC *ADPtr = &CommData.AlienAmbientArray[i];
|
||||||
--pSeq;
|
|
||||||
|
|
||||||
|
memset (pSeq, 0, sizeof (*pSeq));
|
||||||
|
|
||||||
|
pSeq->ADPtr = ADPtr;
|
||||||
if (ADPtr->AnimFlags & COLORXFORM_ANIM)
|
if (ADPtr->AnimFlags & COLORXFORM_ANIM)
|
||||||
pSeq->AnimType = COLOR_ANIM;
|
pSeq->AnimType = COLOR_ANIM;
|
||||||
else
|
else
|
||||||
pSeq->AnimType = PICTURE_ANIM;
|
pSeq->AnimType = PICTURE_ANIM;
|
||||||
pSeq->Direction = UP_DIR;
|
pSeq->Direction = UP_DIR;
|
||||||
pSeq->FramesLeft = ADPtr->NumFrames;
|
pSeq->FramesLeft = ADPtr->NumFrames;
|
||||||
if (pSeq->AnimType == COLOR_ANIM)
|
// Default: first frame is neutral
|
||||||
pSeq->AnimObj.CurCMap = SetAbsColorMapIndex (
|
|
||||||
CommData.AlienColorMap, ADPtr->StartIndex);
|
|
||||||
else
|
|
||||||
pSeq->AnimObj.CurFrame = SetAbsFrameIndex (
|
|
||||||
CommData.AlienFrame, ADPtr->StartIndex);
|
|
||||||
|
|
||||||
if (ADPtr->AnimFlags & RANDOM_ANIM)
|
if (ADPtr->AnimFlags & RANDOM_ANIM)
|
||||||
{
|
{ // Set a random frame/colormap
|
||||||
if (pSeq->AnimType == COLOR_ANIM)
|
pSeq->NextIndex = TFB_Random () % ADPtr->NumFrames;
|
||||||
pSeq->AnimObj.CurCMap =
|
|
||||||
SetRelColorMapIndex (pSeq->AnimObj.CurCMap,
|
|
||||||
(COUNT)((COUNT)TFB_Random () % pSeq->FramesLeft));
|
|
||||||
else
|
|
||||||
pSeq->AnimObj.CurFrame =
|
|
||||||
SetRelFrameIndex (pSeq->AnimObj.CurFrame,
|
|
||||||
(COUNT)((COUNT)TFB_Random () % pSeq->FramesLeft));
|
|
||||||
}
|
}
|
||||||
else if (ADPtr->AnimFlags & YOYO_ANIM)
|
else if (ADPtr->AnimFlags & YOYO_ANIM)
|
||||||
{
|
{ // Skip the first frame/colormap (it's neutral)
|
||||||
|
pSeq->NextIndex = 1;
|
||||||
--pSeq->FramesLeft;
|
--pSeq->FramesLeft;
|
||||||
if (pSeq->AnimType == COLOR_ANIM)
|
}
|
||||||
pSeq->AnimObj.CurCMap =
|
else if (ADPtr->AnimFlags & CIRCULAR_ANIM)
|
||||||
SetRelColorMapIndex (pSeq->AnimObj.CurCMap, 1);
|
{ // Exception that makes everything more painful:
|
||||||
else
|
// *Last* frame is neutral
|
||||||
pSeq->AnimObj.CurFrame =
|
pSeq->CurIndex = ADPtr->NumFrames - 1;
|
||||||
IncFrameIndex (pSeq->AnimObj.CurFrame);
|
pSeq->NextIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSeq->Alarm = ADPtr->BaseRestartRate
|
pSeq->Alarm = randomRestartRate (pSeq) + 1;
|
||||||
+ ((COUNT)TFB_Random () % (ADPtr->RandomRestartRate + 1)) + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SetupTalkSequence (SEQUENCE *pSeq, ANIMATION_DESC *ADPtr)
|
||||||
|
{
|
||||||
|
memset (pSeq, 0, sizeof (*pSeq));
|
||||||
|
// Initially disabled, and until needed
|
||||||
|
ADPtr->AnimFlags |= ANIM_DISABLED;
|
||||||
|
pSeq->ADPtr = ADPtr;
|
||||||
|
pSeq->AnimType = PICTURE_ANIM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
animAtNeutralIndex (SEQUENCE *pSeq)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
if (ADPtr->AnimFlags & CIRCULAR_ANIM)
|
||||||
|
{ // CIRCULAR_ANIM's neutral frame is the last
|
||||||
|
return pSeq->NextIndex == 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // All others, neutral frame is the first
|
||||||
|
return pSeq->CurIndex == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
conflictsWithTalkingAnim (SEQUENCE *pSeq)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
return ADPtr->AnimFlags & CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ProcessColormapAnims (SEQUENCE *pSeq, COUNT Num)
|
||||||
|
{
|
||||||
|
COUNT i;
|
||||||
|
|
||||||
|
for (i = 0; i < Num; ++i, ++pSeq)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
if ((ADPtr->AnimFlags & ANIM_DISABLED)
|
||||||
|
|| pSeq->AnimType != COLOR_ANIM
|
||||||
|
|| !pSeq->Change)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
XFormColorMap (GetColorMapAddress (
|
||||||
|
SetAbsColorMapIndex (CommData.AlienColorMap,
|
||||||
|
ADPtr->StartIndex + pSeq->CurIndex)),
|
||||||
|
pSeq->Alarm - 1);
|
||||||
|
pSeq->Change = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
AdvanceAmbientSequence (SEQUENCE *pSeq)
|
||||||
|
{
|
||||||
|
BOOLEAN active;
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
--pSeq->FramesLeft;
|
||||||
|
// YOYO_ANIM does not actually end until it comes back
|
||||||
|
// in reverse direction, even if FramesLeft gets to 0 here
|
||||||
|
if (pSeq->FramesLeft
|
||||||
|
|| ((ADPtr->AnimFlags & YOYO_ANIM) && pSeq->NextIndex != 0))
|
||||||
|
{
|
||||||
|
active = TRUE;
|
||||||
|
pSeq->Alarm = randomFrameRate (pSeq) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // animation ended
|
||||||
|
active = FALSE;
|
||||||
|
pSeq->Alarm = randomRestartRate (pSeq) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will draw the next frame or change to next colormap
|
||||||
|
pSeq->CurIndex = pSeq->NextIndex;
|
||||||
|
pSeq->Change = TRUE;
|
||||||
|
|
||||||
|
if (pSeq->FramesLeft == 0)
|
||||||
|
{ // Animation ended
|
||||||
|
// Set it up for the next round
|
||||||
|
pSeq->FramesLeft = ADPtr->NumFrames;
|
||||||
|
|
||||||
|
if (ADPtr->AnimFlags & YOYO_ANIM)
|
||||||
|
{ // YOYO_ANIM never draws the first frame
|
||||||
|
// ("first" depends on direction)
|
||||||
|
--pSeq->FramesLeft;
|
||||||
|
pSeq->Direction = -pSeq->Direction;
|
||||||
|
}
|
||||||
|
else if (ADPtr->AnimFlags & CIRCULAR_ANIM)
|
||||||
|
{ // Rewind the CIRCULAR_ANIM
|
||||||
|
// NextIndex will be brought to 0 just below
|
||||||
|
pSeq->NextIndex = -1;
|
||||||
|
}
|
||||||
|
// RANDOM_ANIM is setup just below
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ADPtr->AnimFlags & RANDOM_ANIM)
|
||||||
|
pSeq->NextIndex = randomFrameIndex (pSeq, 0);
|
||||||
|
else
|
||||||
|
pSeq->NextIndex += pSeq->Direction;
|
||||||
|
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ResetSequence (SEQUENCE *pSeq)
|
||||||
|
{
|
||||||
|
// Reset the animation and cause a redraw of the neutral frame,
|
||||||
|
// assuming it is not ANIM_DISABLED
|
||||||
|
// NOTE: This does not handle CIRCULAR_ANIM properly
|
||||||
|
pSeq->Direction = NO_DIR;
|
||||||
|
pSeq->CurIndex = 0;
|
||||||
|
pSeq->Change = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AdvanceTalkingSequence (SEQUENCE *pSeq, DWORD ElapsedTicks)
|
||||||
|
{
|
||||||
|
// We use the actual descriptor for flags processing and
|
||||||
|
// a copied one for drawing. A copied one is updated only
|
||||||
|
// when it is safe to do so.
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
if (pSeq->Direction == NO_DIR)
|
||||||
|
{ // just starting now
|
||||||
|
pSeq->Direction = UP_DIR;
|
||||||
|
// It's now safe to pick up new Talk descriptor if changed
|
||||||
|
// (e.g. Zoq and Pik taking turns to talk)
|
||||||
|
if (CommData.AlienTalkDesc.StartIndex != ADPtr->StartIndex)
|
||||||
|
{ // copy the new one
|
||||||
|
*ADPtr = CommData.AlienTalkDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (pSeq->CurIndex == 0);
|
||||||
|
pSeq->Alarm = 0; // now!
|
||||||
|
ADPtr->AnimFlags &= ~ANIM_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSeq->Alarm > ElapsedTicks)
|
||||||
|
{ // Not time yet
|
||||||
|
pSeq->Alarm -= ElapsedTicks;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time to start or advance the animation
|
||||||
|
pSeq->Alarm = randomFrameRate (pSeq);
|
||||||
|
pSeq->Change = TRUE;
|
||||||
|
// Talking animation is like RANDOM_ANIM, except that
|
||||||
|
// random frames always alternate with the neutral one
|
||||||
|
// The animation does not stop until we reset it
|
||||||
|
if (pSeq->CurIndex == 0)
|
||||||
|
{ // random frame next
|
||||||
|
pSeq->CurIndex = randomFrameIndex (pSeq, 1);
|
||||||
|
pSeq->Alarm += randomRestartRate (pSeq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // neutral frame next
|
||||||
|
pSeq->CurIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
AdvanceTransitSequence (SEQUENCE *pSeq, DWORD ElapsedTicks)
|
||||||
|
{
|
||||||
|
BOOLEAN done = FALSE;
|
||||||
|
// We use the actual descriptor for flags processing and
|
||||||
|
// a copied one for drawing. A copied one is updated only
|
||||||
|
// when it is safe to do so.
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
if (pSeq->Direction == NO_DIR)
|
||||||
|
{ // just starting now
|
||||||
|
pSeq->Alarm = 0; // now!
|
||||||
|
ADPtr->AnimFlags &= ~ANIM_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSeq->Alarm > ElapsedTicks)
|
||||||
|
{ // Not time yet
|
||||||
|
pSeq->Alarm -= ElapsedTicks;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time to start or advance the animation
|
||||||
|
pSeq->Change = TRUE;
|
||||||
|
|
||||||
|
if (pSeq->Direction == NO_DIR)
|
||||||
|
{ // just starting now
|
||||||
|
pSeq->FramesLeft = ADPtr->NumFrames;
|
||||||
|
// Both INTRO and DONE may be set at the same time,
|
||||||
|
// when e.g. Zoq and Pik are taking turns to talk
|
||||||
|
// Process the DONE transition first to go into
|
||||||
|
// a neutral state before switching over.
|
||||||
|
if (CommData.AlienTransitionDesc.AnimFlags & TALK_DONE)
|
||||||
|
{
|
||||||
|
pSeq->Direction = DOWN_DIR;
|
||||||
|
pSeq->CurIndex = ADPtr->NumFrames - 1;
|
||||||
|
}
|
||||||
|
else if (CommData.AlienTransitionDesc.AnimFlags & TALK_INTRO)
|
||||||
|
{
|
||||||
|
pSeq->Direction = UP_DIR;
|
||||||
|
// It's now safe to pick up new Transition descriptor if changed
|
||||||
|
// (e.g. Zoq and Pik taking turns to talk)
|
||||||
|
if (CommData.AlienTransitionDesc.StartIndex
|
||||||
|
!= ADPtr->StartIndex)
|
||||||
|
{ // copy the new one
|
||||||
|
*ADPtr = CommData.AlienTransitionDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSeq->CurIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--pSeq->FramesLeft;
|
||||||
|
if (pSeq->FramesLeft == 0)
|
||||||
|
{ // animation is done
|
||||||
|
if (pSeq->Direction == UP_DIR)
|
||||||
|
{ // done with TALK_INTRO transition
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags &= ~TALK_INTRO;
|
||||||
|
}
|
||||||
|
else if (pSeq->Direction == DOWN_DIR)
|
||||||
|
{ // done with TALK_DONE transition
|
||||||
|
CommData.AlienTransitionDesc.AnimFlags &= ~TALK_DONE;
|
||||||
|
|
||||||
|
// Done with all transition frames
|
||||||
|
ADPtr->AnimFlags |= ANIM_DISABLED;
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
pSeq->Direction = NO_DIR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // next frame
|
||||||
|
pSeq->Alarm = randomFrameRate (pSeq);
|
||||||
|
pSeq->CurIndex += pSeq->Direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ambient_anim_task (void *data)
|
ambient_anim_task (void *data)
|
||||||
{
|
{
|
||||||
SIZE TalkAlarm;
|
|
||||||
FRAME TalkFrame;
|
|
||||||
FRAME ResetTalkFrame = NULL;
|
|
||||||
FRAME TransitionFrame = NULL;
|
|
||||||
FRAME AnimFrame[MAX_ANIMATIONS];
|
|
||||||
COUNT i;
|
COUNT i;
|
||||||
DWORD LastTime;
|
TimeCount LastTime;
|
||||||
FRAME CommFrame;
|
SEQUENCE Sequences[MAX_ANIMATIONS + 2];
|
||||||
SEQUENCE Sequencer[MAX_ANIMATIONS];
|
// 2 extra for Talk and Transition animations
|
||||||
ANIMATION_DESC TalkBuffer = CommData.AlienTalkDesc;
|
|
||||||
SEQUENCE *pSeq;
|
SEQUENCE *pSeq;
|
||||||
ANIMATION_DESC *ADPtr;
|
|
||||||
DWORD ActiveMask;
|
DWORD ActiveMask;
|
||||||
// Bit mask of all animations that are currently active.
|
// Bit mask of all animations that are currently active.
|
||||||
// Bit 'i' is set if the animation with index 'i' is active.
|
// Bit 'i' is set if the animation with index 'i' is active.
|
||||||
DWORD LastOscillTime;
|
DWORD LastOscillTime;
|
||||||
Task task = (Task) data;
|
Task task = (Task) data;
|
||||||
BOOLEAN TransitionDone = FALSE;
|
|
||||||
BOOLEAN TalkFrameChanged = FALSE;
|
|
||||||
BOOLEAN FrameChanged[MAX_ANIMATIONS];
|
|
||||||
BOOLEAN ColorChange = FALSE;
|
BOOLEAN ColorChange = FALSE;
|
||||||
|
|
||||||
while ((CommFrame = CommData.AlienFrame) == 0
|
ANIMATION_DESC TalkDesc;
|
||||||
&& !Task_ReadState (task, TASK_EXIT))
|
ANIMATION_DESC TransitDesc;
|
||||||
|
SEQUENCE* Talk;
|
||||||
|
SEQUENCE* Transit;
|
||||||
|
COUNT FirstAmbient;
|
||||||
|
COUNT TotalSequences;
|
||||||
|
|
||||||
|
while (!CommData.AlienFrame && !Task_ReadState (task, TASK_EXIT))
|
||||||
TaskSwitch ();
|
TaskSwitch ();
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
|
||||||
memset (&DisplayArray[0], 0, sizeof (DisplayArray));
|
|
||||||
SetUpSequence (Sequencer);
|
|
||||||
UnlockMutex (GraphicsLock);
|
|
||||||
|
|
||||||
ActiveMask = 0;
|
ActiveMask = 0;
|
||||||
TalkAlarm = 0;
|
|
||||||
TalkFrame = 0;
|
// Certain data must be accessed under GraphicsLock
|
||||||
|
LockMutex (GraphicsLock);
|
||||||
|
|
||||||
|
memset (&DisplayArray[0], 0, sizeof (DisplayArray));
|
||||||
|
TalkDesc = CommData.AlienTalkDesc;
|
||||||
|
TransitDesc = CommData.AlienTransitionDesc;
|
||||||
|
|
||||||
|
// Animation sequences have to be drawn in reverse, and
|
||||||
|
// talk animations have to be drawn last (so we add them first)
|
||||||
|
TotalSequences = 0;
|
||||||
|
// Transition animation last
|
||||||
|
Transit = Sequences + TotalSequences;
|
||||||
|
SetupTalkSequence (Transit, &TransitDesc);
|
||||||
|
++TotalSequences;
|
||||||
|
// Talk animation second last
|
||||||
|
Talk = Sequences + TotalSequences;
|
||||||
|
SetupTalkSequence (Talk, &TalkDesc);
|
||||||
|
++TotalSequences;
|
||||||
|
FirstAmbient = TotalSequences;
|
||||||
|
SetupAmbientSequences (Sequences + FirstAmbient, CommData.NumAnimations);
|
||||||
|
TotalSequences += CommData.NumAnimations;
|
||||||
|
|
||||||
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
LastTime = GetTimeCounter ();
|
LastTime = GetTimeCounter ();
|
||||||
LastOscillTime = LastTime;
|
LastOscillTime = LastTime;
|
||||||
memset (FrameChanged, 0, sizeof (FrameChanged));
|
|
||||||
memset (AnimFrame, 0, sizeof (AnimFrame));
|
|
||||||
for (i = 0; i < CommData.NumAnimations; i++)
|
|
||||||
{
|
|
||||||
COUNT nextIndex;
|
|
||||||
|
|
||||||
if (CommData.AlienAmbientArray[i].AnimFlags & YOYO_ANIM)
|
|
||||||
nextIndex = CommData.AlienAmbientArray[i].StartIndex;
|
|
||||||
else
|
|
||||||
nextIndex = (CommData.AlienAmbientArray[i].StartIndex
|
|
||||||
+ CommData.AlienAmbientArray[i].NumFrames - 1);
|
|
||||||
AnimFrame[i] = SetAbsFrameIndex (CommFrame, nextIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!Task_ReadState (task, TASK_EXIT))
|
while (!Task_ReadState (task, TASK_EXIT))
|
||||||
{
|
{
|
||||||
BOOLEAN Change, CanTalk;
|
BOOLEAN CanTalk;
|
||||||
DWORD CurTime, ElapsedTicks;
|
TimeCount CurTime;
|
||||||
|
DWORD ElapsedTicks;
|
||||||
|
|
||||||
SleepThreadUntil (LastTime + ONE_SECOND / AMBIENT_ANIM_RATE);
|
SleepThreadUntil (LastTime + ONE_SECOND / AMBIENT_ANIM_RATE);
|
||||||
|
|
||||||
@@ -165,368 +418,153 @@ ambient_anim_task (void *data)
|
|||||||
ElapsedTicks = CurTime - LastTime;
|
ElapsedTicks = CurTime - LastTime;
|
||||||
LastTime = CurTime;
|
LastTime = CurTime;
|
||||||
|
|
||||||
Change = FALSE;
|
if (PauseAnimTask)
|
||||||
i = CommData.NumAnimations;
|
{ // anims not processed
|
||||||
if (CommData.AlienFrame)
|
i = CommData.NumAnimations;
|
||||||
CanTalk = TRUE;
|
CanTalk = FALSE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
CanTalk = FALSE;
|
CanTalk = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSeq = &Sequencer[i];
|
// Process ambient animations
|
||||||
ADPtr = &CommData.AlienAmbientArray[i];
|
pSeq = Sequences + FirstAmbient;
|
||||||
while (i-- && !Task_ReadState (task, TASK_EXIT))
|
for ( ; i < CommData.NumAnimations; ++i, ++pSeq)
|
||||||
{
|
{
|
||||||
--ADPtr;
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
--pSeq;
|
DWORD ActiveBit = 1L << i;
|
||||||
|
|
||||||
if (ADPtr->AnimFlags & ANIM_DISABLED)
|
if (ADPtr->AnimFlags & ANIM_DISABLED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pSeq->Direction == NO_DIR)
|
if (pSeq->Direction == NO_DIR)
|
||||||
{
|
{ // animation is paused
|
||||||
if (!(ADPtr->AnimFlags
|
if (!conflictsWithTalkingAnim (pSeq))
|
||||||
& CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING))
|
{ // start it up
|
||||||
{
|
|
||||||
// This animation does not conflict with the talking
|
|
||||||
// animation right now.
|
|
||||||
pSeq->Direction = UP_DIR;
|
pSeq->Direction = UP_DIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((DWORD)pSeq->Alarm > ElapsedTicks)
|
else if (pSeq->Alarm > ElapsedTicks)
|
||||||
pSeq->Alarm -= (COUNT)ElapsedTicks;
|
{ // not time yet
|
||||||
|
pSeq->Alarm -= ElapsedTicks;
|
||||||
|
}
|
||||||
|
else if (ActiveMask & ADPtr->BlockMask)
|
||||||
|
{ // animation is blocked
|
||||||
|
assert (!(ActiveMask & ActiveBit));
|
||||||
|
assert (animAtNeutralIndex (pSeq));
|
||||||
|
// reschedule
|
||||||
|
pSeq->Alarm = randomRestartRate (pSeq) + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{ // Time to start or advance the animation
|
||||||
if (!(ActiveMask & ADPtr->BlockMask)
|
if (AdvanceAmbientSequence (pSeq))
|
||||||
&& (--pSeq->FramesLeft
|
ActiveMask |= ActiveBit;
|
||||||
|| ((ADPtr->AnimFlags & YOYO_ANIM)
|
|
||||||
&& pSeq->Direction == UP_DIR)))
|
|
||||||
{
|
|
||||||
ActiveMask |= 1L << i;
|
|
||||||
pSeq->Alarm = ADPtr->BaseFrameRate
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->RandomFrameRate + 1)) + 1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
ActiveMask &= ~ActiveBit;
|
||||||
ActiveMask &= ~(1L << i);
|
|
||||||
pSeq->Alarm = ADPtr->BaseRestartRate
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->RandomRestartRate + 1)) + 1;
|
|
||||||
if (ActiveMask & ADPtr->BlockMask)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSeq->AnimType == COLOR_ANIM)
|
|
||||||
{
|
|
||||||
XFormColorMap (GetColorMapAddress (pSeq->AnimObj.CurCMap),
|
|
||||||
(COUNT) (pSeq->Alarm - 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Change = TRUE;
|
|
||||||
AnimFrame[i] = pSeq->AnimObj.CurFrame;
|
|
||||||
FrameChanged[i] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSeq->FramesLeft == 0)
|
|
||||||
{
|
|
||||||
pSeq->FramesLeft = (BYTE)(ADPtr->NumFrames - 1);
|
|
||||||
|
|
||||||
if (pSeq->Direction == DOWN_DIR)
|
|
||||||
pSeq->Direction = UP_DIR;
|
|
||||||
else if (ADPtr->AnimFlags & YOYO_ANIM)
|
|
||||||
pSeq->Direction = DOWN_DIR;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++pSeq->FramesLeft;
|
|
||||||
if (pSeq->AnimType == COLOR_ANIM)
|
|
||||||
pSeq->AnimObj.CurCMap = SetRelColorMapIndex (
|
|
||||||
pSeq->AnimObj.CurCMap,
|
|
||||||
(SWORD) (-pSeq->FramesLeft));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pSeq->AnimObj.CurFrame = SetRelFrameIndex (
|
|
||||||
pSeq->AnimObj.CurFrame,
|
|
||||||
(SWORD) (-pSeq->FramesLeft));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ADPtr->AnimFlags & RANDOM_ANIM)
|
|
||||||
{
|
|
||||||
COUNT nextIndex = ADPtr->StartIndex +
|
|
||||||
(TFB_Random () % ADPtr->NumFrames);
|
|
||||||
|
|
||||||
if (pSeq->AnimType == COLOR_ANIM)
|
|
||||||
pSeq->AnimObj.CurCMap = SetAbsColorMapIndex (
|
|
||||||
pSeq->AnimObj.CurCMap, nextIndex);
|
|
||||||
else
|
|
||||||
pSeq->AnimObj.CurFrame = SetAbsFrameIndex (
|
|
||||||
pSeq->AnimObj.CurFrame, nextIndex);
|
|
||||||
}
|
|
||||||
else if (pSeq->AnimType == COLOR_ANIM)
|
|
||||||
{
|
|
||||||
if (pSeq->Direction == UP_DIR)
|
|
||||||
pSeq->AnimObj.CurCMap = SetRelColorMapIndex (
|
|
||||||
pSeq->AnimObj.CurCMap, 1);
|
|
||||||
else
|
|
||||||
pSeq->AnimObj.CurCMap = SetRelColorMapIndex (
|
|
||||||
pSeq->AnimObj.CurCMap, -1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pSeq->Direction == UP_DIR)
|
|
||||||
pSeq->AnimObj.CurFrame =
|
|
||||||
IncFrameIndex (pSeq->AnimObj.CurFrame);
|
|
||||||
else
|
|
||||||
pSeq->AnimObj.CurFrame =
|
|
||||||
DecFrameIndex (pSeq->AnimObj.CurFrame);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSeq->AnimType == PICTURE_ANIM
|
if (pSeq->AnimType == PICTURE_ANIM && pSeq->Direction != NO_DIR
|
||||||
&& (ADPtr->AnimFlags
|
&& conflictsWithTalkingAnim (pSeq))
|
||||||
& CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING)
|
|
||||||
&& pSeq->Direction != NO_DIR)
|
|
||||||
{
|
{
|
||||||
// This is a picture animation which would conflict with
|
// We want to talk, but this is a running picture animation
|
||||||
// the talking animation, and it is not stopped yet.
|
// which conflicts with the talking animation
|
||||||
COUNT index;
|
// See if it is safe to stop it now.
|
||||||
|
if (animAtNeutralIndex (pSeq))
|
||||||
CanTalk = FALSE;
|
{ // pause the animation
|
||||||
if (!(pSeq->Direction != UP_DIR
|
|
||||||
|| (index = GetFrameIndex (pSeq->AnimObj.CurFrame)) >
|
|
||||||
ADPtr->StartIndex + 1
|
|
||||||
|| (index == ADPtr->StartIndex + 1
|
|
||||||
&& (ADPtr->AnimFlags & CIRCULAR_ANIM))))
|
|
||||||
pSeq->Direction = NO_DIR;
|
pSeq->Direction = NO_DIR;
|
||||||
|
ActiveMask &= ~ActiveBit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Otherwise, let the animation run until it's safe
|
||||||
|
CanTalk = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ADPtr = &CommData.AlienTalkDesc;
|
// Process the talking and transition animations
|
||||||
if (CanTalk
|
if (CanTalk && haveTalkingAnim () && runningTalkingAnim ())
|
||||||
&& ADPtr->NumFrames
|
|
||||||
&& (ADPtr->AnimFlags & WAIT_TALKING)
|
|
||||||
&& !(CommData.AlienTransitionDesc.AnimFlags & PAUSE_TALKING))
|
|
||||||
{
|
{
|
||||||
BOOLEAN done = FALSE;
|
BOOLEAN done = FALSE;
|
||||||
for (i = 0; i < CommData.NumAnimations; i++)
|
|
||||||
if (ActiveMask & (1L << i)
|
|
||||||
&& CommData.AlienAmbientArray[i].AnimFlags & WAIT_TALKING)
|
|
||||||
done = TRUE;
|
|
||||||
if (!done)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (ADPtr->StartIndex != TalkBuffer.StartIndex)
|
if (signaledStopTalkingAnim () && haveTransitionAnim ())
|
||||||
{
|
{ // Run the transition. We will clear everything
|
||||||
Change = TRUE;
|
// when it is done
|
||||||
ResetTalkFrame = SetAbsFrameIndex (CommFrame,
|
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
|
||||||
TalkBuffer.StartIndex);
|
|
||||||
TalkBuffer = CommData.AlienTalkDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((long)TalkAlarm > (long)ElapsedTicks)
|
|
||||||
TalkAlarm -= (SIZE)ElapsedTicks;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BYTE AFlags;
|
|
||||||
SIZE FrameRate;
|
|
||||||
|
|
||||||
if (TalkAlarm > 0)
|
|
||||||
TalkAlarm = 0;
|
|
||||||
else
|
|
||||||
TalkAlarm = -1;
|
|
||||||
|
|
||||||
AFlags = ADPtr->AnimFlags;
|
|
||||||
if (!(AFlags & (TALK_INTRO | TALK_DONE)))
|
|
||||||
{
|
|
||||||
FrameRate =
|
|
||||||
ADPtr->BaseFrameRate
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->RandomFrameRate + 1));
|
|
||||||
if (TalkAlarm < 0
|
|
||||||
|| GetFrameIndex (TalkFrame) ==
|
|
||||||
ADPtr->StartIndex)
|
|
||||||
{
|
|
||||||
TalkFrame = SetAbsFrameIndex (CommFrame,
|
|
||||||
(COUNT) (ADPtr->StartIndex + 1
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->NumFrames - 1))));
|
|
||||||
FrameRate += ADPtr->BaseRestartRate
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->RandomRestartRate + 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TalkFrame = SetAbsFrameIndex (CommFrame,
|
|
||||||
ADPtr->StartIndex);
|
|
||||||
if (ADPtr->AnimFlags & PAUSE_TALKING)
|
|
||||||
{
|
|
||||||
if (!(CommData.AlienTransitionDesc.AnimFlags
|
|
||||||
& TALK_DONE))
|
|
||||||
{
|
|
||||||
CommData.AlienTransitionDesc.AnimFlags |=
|
|
||||||
PAUSE_TALKING;
|
|
||||||
ADPtr->AnimFlags &= ~PAUSE_TALKING;
|
|
||||||
}
|
|
||||||
else if (CommData.AlienTransitionDesc.NumFrames)
|
|
||||||
ADPtr->AnimFlags |= TALK_DONE;
|
|
||||||
else
|
|
||||||
ADPtr->AnimFlags &=
|
|
||||||
~(WAIT_TALKING | PAUSE_TALKING);
|
|
||||||
|
|
||||||
FrameRate = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ADPtr = &CommData.AlienTransitionDesc;
|
|
||||||
if (AFlags & TALK_INTRO)
|
|
||||||
{
|
|
||||||
FrameRate = ADPtr->BaseFrameRate
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->RandomFrameRate + 1));
|
|
||||||
if (TalkAlarm < 0 || TransitionDone)
|
|
||||||
{
|
|
||||||
TalkFrame = SetAbsFrameIndex (CommFrame,
|
|
||||||
ADPtr->StartIndex);
|
|
||||||
TransitionDone = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
TalkFrame = IncFrameIndex (TalkFrame);
|
|
||||||
|
|
||||||
if ((BYTE)(GetFrameIndex (TalkFrame)
|
|
||||||
- ADPtr->StartIndex + 1) ==
|
|
||||||
ADPtr->NumFrames)
|
|
||||||
{
|
|
||||||
CommData.AlienTalkDesc.AnimFlags &=
|
|
||||||
~TALK_INTRO;
|
|
||||||
TransitionDone = TRUE;
|
|
||||||
}
|
|
||||||
TransitionFrame = TalkFrame;
|
|
||||||
}
|
|
||||||
else /* if (AFlags & TALK_DONE) */
|
|
||||||
{
|
|
||||||
FrameRate = ADPtr->BaseFrameRate
|
|
||||||
+ ((COUNT)TFB_Random ()
|
|
||||||
% (ADPtr->RandomFrameRate + 1));
|
|
||||||
if (TalkAlarm < 0)
|
|
||||||
TalkFrame = SetAbsFrameIndex (CommFrame,
|
|
||||||
(COUNT) (ADPtr->StartIndex
|
|
||||||
+ ADPtr->NumFrames - 1));
|
|
||||||
else
|
|
||||||
TalkFrame = DecFrameIndex (TalkFrame);
|
|
||||||
|
|
||||||
if (GetFrameIndex (TalkFrame) ==
|
|
||||||
ADPtr->StartIndex)
|
|
||||||
{
|
|
||||||
CommData.AlienTalkDesc.AnimFlags &=
|
|
||||||
~(PAUSE_TALKING | TALK_DONE);
|
|
||||||
if (ADPtr->AnimFlags & TALK_INTRO)
|
|
||||||
CommData.AlienTalkDesc.AnimFlags &=
|
|
||||||
~WAIT_TALKING;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ADPtr->AnimFlags |= PAUSE_TALKING;
|
|
||||||
ADPtr->AnimFlags &= ~TALK_DONE;
|
|
||||||
}
|
|
||||||
FrameRate = 0;
|
|
||||||
}
|
|
||||||
TransitionFrame = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TalkFrameChanged = TRUE;
|
|
||||||
|
|
||||||
Change = TRUE;
|
|
||||||
|
|
||||||
TalkAlarm = FrameRate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (done && (ADPtr->AnimFlags & PAUSE_TALKING))
|
|
||||||
|
if (CommData.AlienTransitionDesc.AnimFlags
|
||||||
|
& (TALK_INTRO | TALK_DONE))
|
||||||
|
{ // Transitioning in or out of talking
|
||||||
|
if ((CommData.AlienTransitionDesc.AnimFlags & TALK_DONE)
|
||||||
|
&& Transit->Direction == NO_DIR)
|
||||||
|
{ // This is needed when switching talking anims
|
||||||
|
ResetSequence (Talk);
|
||||||
|
}
|
||||||
|
done = AdvanceTransitSequence (Transit, ElapsedTicks);
|
||||||
|
}
|
||||||
|
else if (!signaledStopTalkingAnim ())
|
||||||
|
{ // Talking, transition is done
|
||||||
|
AdvanceTalkingSequence (Talk, ElapsedTicks);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Not talking
|
||||||
|
ResetSequence (Talk);
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signaledStopTalkingAnim () && done)
|
||||||
{
|
{
|
||||||
ADPtr->AnimFlags &= ~(WAIT_TALKING | PAUSE_TALKING);
|
clearRunTalkingAnim ();
|
||||||
|
clearStopTalkingAnim ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{ // Not talking (task may be paused)
|
||||||
|
// Disable talking anim if it is done
|
||||||
|
if (Talk->Direction == NO_DIR)
|
||||||
|
TalkDesc.AnimFlags |= ANIM_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw all animations
|
||||||
if (!PauseAnimTask)
|
if (!PauseAnimTask)
|
||||||
{
|
{
|
||||||
CONTEXT OldContext;
|
CONTEXT OldContext;
|
||||||
BOOLEAN CheckSub = FALSE;
|
|
||||||
BOOLEAN SubtitleChange;
|
BOOLEAN SubtitleChange;
|
||||||
|
BOOLEAN FullRedraw;
|
||||||
|
BOOLEAN Change;
|
||||||
|
|
||||||
// Clearing any active subtitles counts as 'change'
|
// Clearing any active subtitles counts as 'change'
|
||||||
SubtitleChange = HaveSubtitlesChanged ();
|
SubtitleChange = HaveSubtitlesChanged ();
|
||||||
|
FullRedraw = ColorChange || SubtitleChange;
|
||||||
|
|
||||||
OldContext = SetContext (TaskContext);
|
OldContext = SetContext (TaskContext);
|
||||||
|
|
||||||
if (ColorChange || ClearSummary)
|
// Colormap animations are processed separately
|
||||||
{ // Redraw the whole comm screen
|
// from picture anims (see XFormColorMap_step)
|
||||||
FRAME F;
|
ProcessColormapAnims (Sequences + FirstAmbient,
|
||||||
F = CommData.AlienFrame;
|
CommData.NumAnimations);
|
||||||
CommData.AlienFrame = CommFrame;
|
|
||||||
DrawAlienFrame (TalkFrame,
|
|
||||||
&Sequencer[CommData.NumAnimations - 1]);
|
|
||||||
CommData.AlienFrame = F;
|
|
||||||
CheckSub = TRUE;
|
|
||||||
SubtitleChange = ClearSummary;
|
|
||||||
ColorChange = FALSE;
|
|
||||||
ClearSummary = FALSE;
|
|
||||||
}
|
|
||||||
if (Change || SubtitleChange)
|
|
||||||
{
|
|
||||||
STAMP s;
|
|
||||||
s.origin.x = -SAFE_X;
|
|
||||||
s.origin.y = 0;
|
|
||||||
if (SubtitleChange)
|
|
||||||
{
|
|
||||||
s.frame = CommFrame;
|
|
||||||
DrawStamp (&s);
|
|
||||||
}
|
|
||||||
i = CommData.NumAnimations;
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
if (SubtitleChange || FrameChanged[i])
|
|
||||||
{
|
|
||||||
s.frame = AnimFrame[i];
|
|
||||||
DrawStamp (&s);
|
|
||||||
FrameChanged[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (SubtitleChange && TransitionFrame)
|
|
||||||
{
|
|
||||||
s.frame = TransitionFrame;
|
|
||||||
DrawStamp (&s);
|
|
||||||
}
|
|
||||||
if (ResetTalkFrame)
|
|
||||||
{
|
|
||||||
s.frame = ResetTalkFrame;
|
|
||||||
DrawStamp (&s);
|
|
||||||
ResetTalkFrame = NULL;
|
|
||||||
}
|
|
||||||
if (TalkFrame && TalkFrameChanged)
|
|
||||||
{
|
|
||||||
s.frame = TalkFrame;
|
|
||||||
DrawStamp (&s);
|
|
||||||
TalkFrameChanged = FALSE;
|
|
||||||
}
|
|
||||||
Change = FALSE;
|
|
||||||
CheckSub = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckSub)
|
Change = DrawAlienFrame (Sequences, TotalSequences, FullRedraw);
|
||||||
|
if (FullRedraw || Change)
|
||||||
RedrawSubtitles ();
|
RedrawSubtitles ();
|
||||||
|
|
||||||
SetContext (OldContext);
|
SetContext (OldContext);
|
||||||
|
|
||||||
|
ColorChange = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LastOscillTime + (ONE_SECOND / OSCILLOSCOPE_RATE) < CurTime)
|
if (LastOscillTime + (ONE_SECOND / OSCILLOSCOPE_RATE) < CurTime)
|
||||||
{
|
{
|
||||||
LastOscillTime = CurTime;
|
LastOscillTime = CurTime;
|
||||||
UpdateSpeechGraphics (FALSE);
|
UpdateSpeechGraphics (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnbatchGraphics ();
|
UnbatchGraphics ();
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
ColorChange = XFormColorMap_step ();
|
ColorChange = XFormColorMap_step ();
|
||||||
}
|
}
|
||||||
FinishTask (task);
|
FinishTask (task);
|
||||||
@@ -539,4 +577,68 @@ StartCommAnimTask (void)
|
|||||||
return AssignTask (ambient_anim_task, 3072, "ambient animations");
|
return AssignTask (ambient_anim_task, 3072, "ambient animations");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
DrawAlienFrame (SEQUENCE *Sequences, COUNT Num, BOOLEAN fullRedraw)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
STAMP s;
|
||||||
|
BOOLEAN Change = FALSE;
|
||||||
|
|
||||||
|
BatchGraphics ();
|
||||||
|
|
||||||
|
s.origin.x = -SAFE_X;
|
||||||
|
s.origin.y = 0;
|
||||||
|
|
||||||
|
if (fullRedraw)
|
||||||
|
{
|
||||||
|
// Draw the main frame
|
||||||
|
s.frame = CommData.AlienFrame;
|
||||||
|
DrawStamp (&s);
|
||||||
|
|
||||||
|
// Draw any static frames (has to be in reverse)
|
||||||
|
for (i = CommData.NumAnimations - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
ANIMATION_DESC *ADPtr = &CommData.AlienAmbientArray[i];
|
||||||
|
|
||||||
|
if (ADPtr->AnimFlags & ANIM_MASK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ADPtr->AnimFlags |= ANIM_DISABLED;
|
||||||
|
|
||||||
|
if (!(ADPtr->AnimFlags & COLORXFORM_ANIM))
|
||||||
|
{ // It's a static frame (e.g. Flagship picture at Starbase)
|
||||||
|
s.frame = SetAbsFrameIndex (CommData.AlienFrame,
|
||||||
|
ADPtr->StartIndex);
|
||||||
|
DrawStamp (&s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Sequences)
|
||||||
|
{ // Draw the animation sequences (has to be in reverse)
|
||||||
|
for (i = Num - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
SEQUENCE *pSeq = &Sequences[i];
|
||||||
|
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||||
|
|
||||||
|
if ((ADPtr->AnimFlags & ANIM_DISABLED)
|
||||||
|
|| pSeq->AnimType != PICTURE_ANIM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Draw current animation frame only if changed
|
||||||
|
if (!fullRedraw && !pSeq->Change)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s.frame = SetAbsFrameIndex (CommData.AlienFrame,
|
||||||
|
ADPtr->StartIndex + pSeq->CurIndex);
|
||||||
|
DrawStamp (&s);
|
||||||
|
pSeq->Change = FALSE;
|
||||||
|
|
||||||
|
Change = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnbatchGraphics ();
|
||||||
|
|
||||||
|
return Change;
|
||||||
|
}
|
||||||
|
|||||||
+81
-12
@@ -21,14 +21,81 @@
|
|||||||
#include "libs/gfxlib.h"
|
#include "libs/gfxlib.h"
|
||||||
#include "libs/tasklib.h"
|
#include "libs/tasklib.h"
|
||||||
|
|
||||||
|
// Some background: every animation has a neutral frame which returns
|
||||||
|
// the image to the state it was in before the animation began. Which
|
||||||
|
// frame is neutral depends on the animation type.
|
||||||
|
// Animation types:
|
||||||
|
#define RANDOM_ANIM (1 << 0)
|
||||||
|
// The next index is randomly chosen.
|
||||||
|
// The first frame is neutral
|
||||||
|
#define CIRCULAR_ANIM (1 << 1)
|
||||||
|
// After the last index has been reached, the animation starts over.
|
||||||
|
// The last frame is neutral. This complicates the animation task.
|
||||||
|
#define YOYO_ANIM (1 << 2)
|
||||||
|
// After the last index has been reached, the order that the
|
||||||
|
// animation frames are used is reversed.
|
||||||
|
// The first frame is neutral
|
||||||
|
#define ANIM_MASK (RANDOM_ANIM | CIRCULAR_ANIM | YOYO_ANIM)
|
||||||
|
// Mask of all animation types.
|
||||||
|
// Static frames do not have any of these flags set.
|
||||||
|
|
||||||
|
#define WAIT_TALKING (1 << 3)
|
||||||
|
// This is set in AlienTalkDesc when the talking animation is active
|
||||||
|
// or should be active.
|
||||||
|
// In AlienAmbientArray, this is set for those ambient animations
|
||||||
|
// which can not be active while the talking animation is active.
|
||||||
|
// Such animations stop at the end of the current animation cycle
|
||||||
|
// when the talking animation activates.
|
||||||
|
#define PAUSE_TALKING (1 << 4)
|
||||||
|
// Set in AlienTalkDesc when we do not want the talking animation
|
||||||
|
#define TALK_INTRO (1 << 5)
|
||||||
|
// In AlienTransitionDesc: indicates a transition to talking state
|
||||||
|
#define TALK_DONE (1 << 6)
|
||||||
|
// In AlienTransitionDesc: indicates a transition to silent state
|
||||||
|
// In AlienTalkDesc: signals the end of talking animation
|
||||||
|
#define ANIM_DISABLED (1 << 7)
|
||||||
|
|
||||||
|
#define COLORXFORM_ANIM PAUSE_TALKING
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
COUNT StartIndex;
|
||||||
|
// Index of the first image (for image animation) or
|
||||||
|
// index of the first color map (for palette animation)
|
||||||
|
BYTE NumFrames;
|
||||||
|
// Number of frames in the animation.
|
||||||
|
|
||||||
|
BYTE AnimFlags;
|
||||||
|
// One of RANDOM_ANIM, CIRCULAR_ANIM, or YOYO_ANIM
|
||||||
|
// plus flags (WAIT_TALKING, ANIM_DISABLED)
|
||||||
|
|
||||||
|
COUNT BaseFrameRate;
|
||||||
|
// Minimum interframe delay
|
||||||
|
COUNT RandomFrameRate;
|
||||||
|
// Maximum additional interframe delay
|
||||||
|
// Actual delay: BaseFrameRate + Random(0..RandomFrameRate)
|
||||||
|
COUNT BaseRestartRate;
|
||||||
|
// Minimum delay before restarting animation
|
||||||
|
COUNT RandomRestartRate;
|
||||||
|
// Maximum additional delay before restarting animation
|
||||||
|
// Actual delay: BaseRestartRate + Random(0..RandomRestartRate)
|
||||||
|
|
||||||
|
DWORD BlockMask;
|
||||||
|
// Bit mask of the indices of all animations that can not
|
||||||
|
// be active at the same time as this animation, usually,
|
||||||
|
// due to the image overlap conflicts.
|
||||||
|
} ANIMATION_DESC;
|
||||||
|
|
||||||
|
#define MAX_ANIMATIONS 20
|
||||||
|
|
||||||
|
|
||||||
#ifdef COMM_INTERNAL
|
#ifdef COMM_INTERNAL
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
UP_DIR,
|
DOWN_DIR = -1, // Animation indices are decreasing
|
||||||
// Animation indices are increasing
|
NO_DIR = 0,
|
||||||
DOWN_DIR,
|
UP_DIR = 1, // Animation indices are increasing
|
||||||
// Animation indices are decreasing
|
|
||||||
NO_DIR
|
|
||||||
} ANIM_DIR;
|
} ANIM_DIR;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@@ -42,20 +109,22 @@ typedef enum
|
|||||||
// Describes an active animation.
|
// Describes an active animation.
|
||||||
struct SEQUENCE
|
struct SEQUENCE
|
||||||
{
|
{
|
||||||
COUNT Alarm;
|
ANIMATION_DESC *ADPtr;
|
||||||
|
DWORD Alarm;
|
||||||
ANIM_DIR Direction;
|
ANIM_DIR Direction;
|
||||||
BYTE FramesLeft;
|
COUNT CurIndex;
|
||||||
|
COUNT NextIndex;
|
||||||
|
COUNT FramesLeft;
|
||||||
ANIM_TYPE AnimType;
|
ANIM_TYPE AnimType;
|
||||||
union
|
BOOLEAN Change;
|
||||||
{
|
|
||||||
FRAME CurFrame;
|
|
||||||
COLORMAP CurCMap;
|
|
||||||
} AnimObj;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct SEQUENCE SEQUENCE;
|
typedef struct SEQUENCE SEQUENCE;
|
||||||
|
|
||||||
|
// Returns TRUE if there was an animation change
|
||||||
|
extern BOOLEAN DrawAlienFrame (SEQUENCE *pSeq, COUNT Num, BOOLEAN fullRedraw);
|
||||||
|
|
||||||
void UpdateSpeechGraphics (BOOLEAN Initialize);
|
void UpdateSpeechGraphics (BOOLEAN Initialize);
|
||||||
Task StartCommAnimTask(void);
|
Task StartCommAnimTask(void);
|
||||||
|
|
||||||
|
|||||||
+6
-48
@@ -24,56 +24,9 @@
|
|||||||
#include "libs/reslib.h"
|
#include "libs/reslib.h"
|
||||||
#include "sis.h"
|
#include "sis.h"
|
||||||
#include "velocity.h"
|
#include "velocity.h"
|
||||||
|
#include "commanim.h"
|
||||||
|
|
||||||
|
|
||||||
// XXX: the following should be moved to commanim.h
|
|
||||||
// Animation types:
|
|
||||||
#define RANDOM_ANIM (1 << 0)
|
|
||||||
// The next index is randomly chosen.
|
|
||||||
#define CIRCULAR_ANIM (1 << 1)
|
|
||||||
// After the last index has been reached, the animation starts over.
|
|
||||||
#define YOYO_ANIM (1 << 2)
|
|
||||||
// After the last index has been reached, the order that the
|
|
||||||
// animation frames are used is reversed.
|
|
||||||
#define ANIM_MASK (RANDOM_ANIM | CIRCULAR_ANIM | YOYO_ANIM)
|
|
||||||
// Mask of all animation types.
|
|
||||||
|
|
||||||
#define WAIT_TALKING (1 << 3)
|
|
||||||
// This is set in AlienTalkDesc when the ambient animations should
|
|
||||||
// stop at the end of the current animation cycle.
|
|
||||||
// In AlienAmbientArray, this is set for those ambient animations
|
|
||||||
// which can not be active while the talking animation is active.
|
|
||||||
#define PAUSE_TALKING (1 << 4)
|
|
||||||
#define TALK_INTRO (1 << 5)
|
|
||||||
#define TALK_DONE (1 << 6)
|
|
||||||
|
|
||||||
#define ANIM_DISABLED (1 << 7)
|
|
||||||
|
|
||||||
#define COLORXFORM_ANIM PAUSE_TALKING
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
COUNT StartIndex;
|
|
||||||
// Index of the first image (for image animation) or
|
|
||||||
// index of the first color map (for palette animation)
|
|
||||||
BYTE NumFrames;
|
|
||||||
// Number of frames in the animation.
|
|
||||||
|
|
||||||
BYTE AnimFlags;
|
|
||||||
// One of RANDOM_ANIM, CIRCULAR_ANIM, or YOYO_ANIM
|
|
||||||
|
|
||||||
COUNT BaseFrameRate;
|
|
||||||
COUNT RandomFrameRate;
|
|
||||||
COUNT BaseRestartRate;
|
|
||||||
COUNT RandomRestartRate;
|
|
||||||
|
|
||||||
DWORD BlockMask;
|
|
||||||
// Bit mask of the indices of all animations that can not
|
|
||||||
// be active at the same time as this animation.
|
|
||||||
} ANIMATION_DESC;
|
|
||||||
|
|
||||||
#define MAX_ANIMATIONS 20
|
|
||||||
|
|
||||||
// general numbers-speech generator info
|
// general numbers-speech generator info
|
||||||
// should accomodate most common base-10 languages
|
// should accomodate most common base-10 languages
|
||||||
// many languages require various plural forms
|
// many languages require various plural forms
|
||||||
@@ -160,7 +113,12 @@ typedef struct
|
|||||||
COUNT NumAnimations;
|
COUNT NumAnimations;
|
||||||
ANIMATION_DESC AlienAmbientArray[MAX_ANIMATIONS];
|
ANIMATION_DESC AlienAmbientArray[MAX_ANIMATIONS];
|
||||||
|
|
||||||
|
// Transition animation to/from talking state;
|
||||||
|
// the first frame is neutral (sort of like YOYO_ANIM)
|
||||||
ANIMATION_DESC AlienTransitionDesc;
|
ANIMATION_DESC AlienTransitionDesc;
|
||||||
|
// Talking animation, like RANDOM_ANIM, except random frames
|
||||||
|
// always alternate with a neutral frame;
|
||||||
|
// the first frame is neutral
|
||||||
ANIMATION_DESC AlienTalkDesc;
|
ANIMATION_DESC AlienTalkDesc;
|
||||||
|
|
||||||
NUMBER_SPEECH AlienNumberSpeech;
|
NUMBER_SPEECH AlienNumberSpeech;
|
||||||
|
|||||||
Reference in New Issue
Block a user