Concurrent supermelee ship selection.
New generic, unthreaded flashing code. Cleanups and comments. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2749 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
Changes towards version 0.7:
|
Changes towards version 0.7:
|
||||||
|
- Concurrent supermelee ship selection - SvdB
|
||||||
|
- New generic, unthreaded flashing code - SvdB
|
||||||
- Cleanup of 3DO ship spin support; spin speech works now - Alex
|
- Cleanup of 3DO ship spin support; spin speech works now - Alex
|
||||||
- No longer creating and mounting a temporary directory. It is no longer
|
- No longer creating and mounting a temporary directory. It is no longer
|
||||||
used, but it might be again at some point, for loadable modules. - SvdB
|
used, but it might be again at some point, for loadable modules. - SvdB
|
||||||
|
|||||||
@@ -2361,6 +2361,10 @@ Connection aborted due to version mismatch.
|
|||||||
Connection aborted due to an internal protocol error.
|
Connection aborted due to an internal protocol error.
|
||||||
|
|
||||||
|
|
||||||
|
#(Connection aborted because the remote side sent a fake signature.)
|
||||||
|
Connection aborted because the remote side sent a fake signature.
|
||||||
|
|
||||||
|
|
||||||
#(Game aborted for an unspecified reason.)
|
#(Game aborted for an unspecified reason.)
|
||||||
Game aborted for an unspecified reason.
|
Game aborted for an unspecified reason.
|
||||||
|
|
||||||
|
|||||||
@@ -3972,6 +3972,14 @@ SOURCE=..\sc2code\encount.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\sc2code\flash.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\sc2code\flash.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\sc2code\fmv.c
|
SOURCE=..\sc2code\fmv.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
uqm_SUBDIRS="comm libs planets ships"
|
uqm_SUBDIRS="comm libs planets ships"
|
||||||
uqm_CFILES="battle.c border.c build.c cleanup.c clock.c cnctdlg.c collide.c
|
uqm_CFILES="battle.c border.c build.c cleanup.c clock.c cnctdlg.c collide.c
|
||||||
comm.c commanim.c commglue.c confirm.c credits.c cyborg.c
|
comm.c commanim.c commglue.c confirm.c credits.c cyborg.c
|
||||||
demo.c displist.c dummy.c encount.c fmv.c galaxy.c gameev.c
|
demo.c displist.c dummy.c encount.c flash.c fmv.c galaxy.c gameev.c
|
||||||
gameinp.c gameopt.c gendef.c getchar.c globdata.c gravity.c
|
gameinp.c gameopt.c gendef.c getchar.c globdata.c gravity.c
|
||||||
gravwell.c grpinfo.c hyper.c init.c intel.c intro.c ipdisp.c
|
gravwell.c grpinfo.c hyper.c init.c intel.c intro.c ipdisp.c
|
||||||
load.c loadship.c master.c melee.c menu.c misc.c mouse_err.c
|
load.c loadship.c master.c melee.c menu.c misc.c mouse_err.c
|
||||||
|
|||||||
+21
-46
@@ -340,34 +340,34 @@ DoBattle (BATTLE_STATE *bs)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
COUNT
|
||||||
|
GetPlayerOrder (COUNT i)
|
||||||
|
{
|
||||||
|
// Iff 'myTurn' is set on a connection, the local party will be
|
||||||
|
// processed first.
|
||||||
|
// If neither is network controlled, the top player (1) is handled
|
||||||
|
// first.
|
||||||
|
if (((PlayerControl[0] & NETWORK_CONTROL) &&
|
||||||
|
!NetConnection_getDiscriminant (netConnections[0])) ||
|
||||||
|
((PlayerControl[1] & NETWORK_CONTROL) &&
|
||||||
|
NetConnection_getDiscriminant (netConnections[1])))
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
return 1 - i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Let each player pick his ship.
|
// Let each player pick his ship.
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
selectAllShips (SIZE num_ships)
|
selectAllShips (SIZE num_ships)
|
||||||
{
|
{
|
||||||
#ifndef NETPLAY
|
|
||||||
while (num_ships--)
|
|
||||||
{
|
|
||||||
if (!GetNextStarShip (NULL, num_ships == 1))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
#else
|
|
||||||
// On network play, what is the top player to one party may be
|
|
||||||
// the bottom player the other. To keep both sides synchronised
|
|
||||||
// the order is always the same.
|
|
||||||
SIZE order[NUM_PLAYERS];
|
|
||||||
|
|
||||||
if (num_ships == 1) {
|
if (num_ships == 1) {
|
||||||
// HyperSpace in full game.
|
// HyperSpace in full game.
|
||||||
return GetNextStarShip (NULL, 0);
|
return GetNextStarShip (NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_ships != 2)
|
#ifdef NETPLAY
|
||||||
{
|
|
||||||
log_add (log_Error, "More than two players is not supported.\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((PlayerControl[0] & NETWORK_CONTROL) &&
|
if ((PlayerControl[0] & NETWORK_CONTROL) &&
|
||||||
(PlayerControl[1] & NETWORK_CONTROL))
|
(PlayerControl[1] & NETWORK_CONTROL))
|
||||||
{
|
{
|
||||||
@@ -375,34 +375,9 @@ selectAllShips (SIZE num_ships)
|
|||||||
"controlled.\n");
|
"controlled.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iff 'myTurn' is set on a connection, the local party will be
|
|
||||||
// processed first.
|
|
||||||
// If neither is network controlled, the top player (1) is handled first.
|
|
||||||
if (((PlayerControl[0] & NETWORK_CONTROL) &&
|
|
||||||
!NetConnection_getDiscriminant (netConnections[0])) ||
|
|
||||||
((PlayerControl[1] & NETWORK_CONTROL) &&
|
|
||||||
NetConnection_getDiscriminant (netConnections[1])))
|
|
||||||
{
|
|
||||||
order[0] = 0;
|
|
||||||
order[1] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
order[0] = 1;
|
|
||||||
order[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < NUM_PLAYERS; i++)
|
|
||||||
{
|
|
||||||
if (!GetNextStarShip (NULL, order[i]))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return GetInitialStarShips ();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ extern BOOLEAN instantVictory;
|
|||||||
typedef DWORD BattleFrameCounter;
|
typedef DWORD BattleFrameCounter;
|
||||||
extern BattleFrameCounter battleFrameCount;
|
extern BattleFrameCounter battleFrameCount;
|
||||||
extern COUNT currentDeadSide;
|
extern COUNT currentDeadSide;
|
||||||
|
COUNT GetPlayerOrder (COUNT i);
|
||||||
|
#else
|
||||||
|
# define GetPlayerOrder(i) (i)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern BOOLEAN Battle (void);
|
extern BOOLEAN Battle (void);
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ typedef QUEUE_HANDLE HELEMENT;
|
|||||||
#define APPEARING (1 << 3)
|
#define APPEARING (1 << 3)
|
||||||
#define DISAPPEARING (1 << 4)
|
#define DISAPPEARING (1 << 4)
|
||||||
#define CHANGING (1 << 5)
|
#define CHANGING (1 << 5)
|
||||||
|
// The element's graphical representation has changed.
|
||||||
|
|
||||||
#define NONSOLID (1 << 6)
|
#define NONSOLID (1 << 6)
|
||||||
#define COLLISION (1 << 7)
|
#define COLLISION (1 << 7)
|
||||||
|
|||||||
@@ -0,0 +1,721 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE: A lot of this code is untested. Only highlite flash areas drawing
|
||||||
|
// directly to the screen, using a cache are currently in use.
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - Add Flash_setHighlight() to change the brightness as in
|
||||||
|
// Flash_createHighlight(), for an already created flash area.
|
||||||
|
// - Add Flash_setOverlay() to change the overlay frame as in
|
||||||
|
// Flash_createOverlay(), for an already created flash area.
|
||||||
|
|
||||||
|
|
||||||
|
#define FLASH_INTERNAL
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
#include "libs/log.h"
|
||||||
|
#include "libs/misc.h"
|
||||||
|
#include "libs/threadlib.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern void arith_frame_blit (FRAME srcFrame, const RECT *rsrc,
|
||||||
|
FRAME dstFrame, RECT *rdst, int num, int denom);
|
||||||
|
|
||||||
|
static FlashContext *Flash_create (CONTEXT gfxContext, FRAME parent);
|
||||||
|
static void Flash_fixState (FlashContext *context);
|
||||||
|
static void Flash_nextState (FlashContext *context);
|
||||||
|
static void Flash_clearCache (FlashContext *context);
|
||||||
|
static void Flash_initCache (FlashContext *context);
|
||||||
|
static void Flash_grabOriginal (FlashContext *context);
|
||||||
|
static void Flash_blendFraction (FlashContext *context, int numer, int denom,
|
||||||
|
int *resNumer, int *resDenom);
|
||||||
|
static void Flash_makeFrame (FlashContext *context,
|
||||||
|
FRAME dest, RECT *destRect, int numer, int denom);
|
||||||
|
static inline void Flash_prepareCacheFrame (FlashContext *context,
|
||||||
|
COUNT index);
|
||||||
|
static void Flash_drawFrame (FlashContext *context, FRAME frame);
|
||||||
|
static void Flash_drawCacheFrame (FlashContext *context, COUNT index);
|
||||||
|
static inline void Flash_drawUncachedFrame (FlashContext *context,
|
||||||
|
int numer, int denom);
|
||||||
|
static inline void Flash_drawCachedFrame (FlashContext *context,
|
||||||
|
int numer, int denom);
|
||||||
|
static void Flash_drawCurrentFrame (FlashContext *context);
|
||||||
|
|
||||||
|
static FlashContext *
|
||||||
|
Flash_create (CONTEXT gfxContext, FRAME parent)
|
||||||
|
{
|
||||||
|
FlashContext *context = HMalloc (sizeof (FlashContext));
|
||||||
|
|
||||||
|
context->gfxContext = gfxContext;
|
||||||
|
context->parent = parent;
|
||||||
|
|
||||||
|
context->original = 0;
|
||||||
|
|
||||||
|
context->fadeInTime = Flash_DEFAULT_FADE_IN_TIME;
|
||||||
|
context->onTime = Flash_DEFAULT_ON_TIME;
|
||||||
|
context->fadeOutTime = Flash_DEFAULT_FADE_OUT_TIME;
|
||||||
|
context->offTime = Flash_DEFAULT_OFF_TIME;
|
||||||
|
|
||||||
|
context->frameTime = 0;
|
||||||
|
|
||||||
|
context->state = FlashState_off;
|
||||||
|
context->lastStateTime = 0;
|
||||||
|
context->lastFrameTime = 0;
|
||||||
|
|
||||||
|
context->started = false;
|
||||||
|
context->paused = false;
|
||||||
|
|
||||||
|
context->cache = 0;
|
||||||
|
context->cacheSize = Flash_DEFAULT_CACHE_SIZE;
|
||||||
|
|
||||||
|
context->lastFrameIndex = (COUNT) -1;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'startNumer / denom' is the brightness in the start state of the flash.
|
||||||
|
// 'endNumer / denom' is the brightness in the end state of the flash.
|
||||||
|
// These numbers are relative to the brighness of the original image.
|
||||||
|
FlashContext *
|
||||||
|
Flash_createHighlight (CONTEXT gfxContext, FRAME parent, const RECT *rect,
|
||||||
|
int startNumer, int endNumer, int denom)
|
||||||
|
{
|
||||||
|
FlashContext *context = Flash_create (gfxContext, parent);
|
||||||
|
|
||||||
|
if (rect == NULL)
|
||||||
|
{
|
||||||
|
// No rectangle specified. Should be later with Flash_setRect()
|
||||||
|
// before calling Flash_start().
|
||||||
|
context->rect.corner.x = 0;
|
||||||
|
context->rect.corner.y = 0;
|
||||||
|
context->rect.extent.width = 0;
|
||||||
|
context->rect.extent.height = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
context->rect = *rect;
|
||||||
|
context->type = FlashType_highlight;
|
||||||
|
|
||||||
|
context->u.highlight.startNumer = startNumer;
|
||||||
|
context->u.highlight.endNumer = endNumer;
|
||||||
|
context->u.highlight.denom = denom;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashContext *
|
||||||
|
Flash_createTransition (CONTEXT gfxContext, FRAME parent,
|
||||||
|
const POINT *origin, FRAME first, FRAME final)
|
||||||
|
{
|
||||||
|
FlashContext *context = Flash_create (gfxContext, parent);
|
||||||
|
|
||||||
|
context->type = FlashType_transition;
|
||||||
|
|
||||||
|
context->u.transition.first = first;
|
||||||
|
context->u.transition.final = final;
|
||||||
|
GetFrameRect (final, &context->rect);
|
||||||
|
context->rect.corner = *origin;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashContext *
|
||||||
|
Flash_createOverlay (CONTEXT gfxContext, FRAME parent,
|
||||||
|
const POINT *origin, FRAME overlay)
|
||||||
|
{
|
||||||
|
FlashContext *context = Flash_create (gfxContext, parent);
|
||||||
|
|
||||||
|
context->type = FlashType_overlay;
|
||||||
|
|
||||||
|
context->u.overlay.frame = overlay;
|
||||||
|
GetFrameRect (overlay, &context->rect);
|
||||||
|
context->rect.corner = *origin;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_setState (FlashContext *context, FlashState state)
|
||||||
|
{
|
||||||
|
TimeCount now;
|
||||||
|
|
||||||
|
now = GetTimeCounter ();
|
||||||
|
|
||||||
|
context->state = state;
|
||||||
|
Flash_fixState (context);
|
||||||
|
Flash_drawCurrentFrame (context);
|
||||||
|
|
||||||
|
context->lastStateTime = now;
|
||||||
|
context->lastFrameTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_start (FlashContext *context)
|
||||||
|
{
|
||||||
|
if (context->started)
|
||||||
|
{
|
||||||
|
log_add (log_Warning, "Flash_start() called on already started "
|
||||||
|
"FlashContext.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flash_initCache (context);
|
||||||
|
|
||||||
|
context->started = true;
|
||||||
|
context->paused = false;
|
||||||
|
|
||||||
|
Flash_grabOriginal (context);
|
||||||
|
context->lastFrameIndex = 0;
|
||||||
|
|
||||||
|
Flash_fixState (context);
|
||||||
|
Flash_drawCurrentFrame (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_terminate (FlashContext *context)
|
||||||
|
{
|
||||||
|
if (context->started)
|
||||||
|
{
|
||||||
|
// Restore the flash rectangle:
|
||||||
|
Flash_drawFrame (context, context->original);
|
||||||
|
|
||||||
|
Flash_clearCache (context);
|
||||||
|
DestroyDrawable (ReleaseDrawable (context->original));
|
||||||
|
}
|
||||||
|
|
||||||
|
HFree (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_pause (FlashContext *context)
|
||||||
|
{
|
||||||
|
context->paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_continue (FlashContext *context)
|
||||||
|
{
|
||||||
|
context->paused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the state to the next state as long as the current state has
|
||||||
|
// a zero-time duration.
|
||||||
|
static void
|
||||||
|
Flash_fixState (FlashContext *context)
|
||||||
|
{
|
||||||
|
TimeCount stateTime;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
switch (context->state) {
|
||||||
|
case FlashState_fadeIn:
|
||||||
|
stateTime = context->fadeInTime;
|
||||||
|
break;
|
||||||
|
case FlashState_on:
|
||||||
|
stateTime = context->onTime;
|
||||||
|
break;
|
||||||
|
case FlashState_fadeOut:
|
||||||
|
stateTime = context->fadeOutTime;
|
||||||
|
break;
|
||||||
|
case FlashState_off:
|
||||||
|
stateTime = context->offTime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (stateTime != 0)
|
||||||
|
break;
|
||||||
|
context->state = (context->state + 1) & 0x3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_nextState (FlashContext *context)
|
||||||
|
{
|
||||||
|
context->state = (context->state + 1) & 0x3;
|
||||||
|
Flash_fixState (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_process (FlashContext *context)
|
||||||
|
{
|
||||||
|
TimeCount now;
|
||||||
|
|
||||||
|
if (!context->started || context->paused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
now = GetTimeCounter ();
|
||||||
|
|
||||||
|
if (context->state == FlashState_fadeIn)
|
||||||
|
{
|
||||||
|
if (now >= context->lastStateTime + context->fadeInTime)
|
||||||
|
{
|
||||||
|
Flash_nextState (context);
|
||||||
|
context->lastStateTime = now;
|
||||||
|
}
|
||||||
|
context->lastFrameTime = now;
|
||||||
|
}
|
||||||
|
else if (context->state == FlashState_on)
|
||||||
|
{
|
||||||
|
if (now < context->lastStateTime + context->onTime)
|
||||||
|
return;
|
||||||
|
Flash_nextState (context);
|
||||||
|
context->lastStateTime = now;
|
||||||
|
}
|
||||||
|
else if (context->state == FlashState_fadeOut)
|
||||||
|
{
|
||||||
|
if (now >= context->lastStateTime + context->fadeOutTime)
|
||||||
|
{
|
||||||
|
Flash_nextState (context);
|
||||||
|
context->lastStateTime = now;
|
||||||
|
}
|
||||||
|
context->lastFrameTime = now;
|
||||||
|
}
|
||||||
|
else /* context->state == FlashState_off */
|
||||||
|
{
|
||||||
|
if (now < context->lastStateTime + context->offTime)
|
||||||
|
return;
|
||||||
|
Flash_nextState (context);
|
||||||
|
context->lastStateTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flash_drawCurrentFrame (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_setSpeed (FlashContext *context, TimeCount fadeInTime,
|
||||||
|
TimeCount onTime, TimeCount fadeOutTime, TimeCount offTime)
|
||||||
|
{
|
||||||
|
context->fadeInTime = fadeInTime;
|
||||||
|
context->onTime = onTime;
|
||||||
|
context->fadeOutTime = fadeOutTime;
|
||||||
|
context->offTime = offTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the time between updates of the flash area.
|
||||||
|
void
|
||||||
|
Flash_setFrameTime (FlashContext *context, TimeCount frameTime) {
|
||||||
|
context->frameTime = frameTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the time when the flash area is to be updated.
|
||||||
|
TimeCount
|
||||||
|
Flash_nextTime (FlashContext *context)
|
||||||
|
{
|
||||||
|
if (!context->started || context->paused)
|
||||||
|
return (TimeCount) -1;
|
||||||
|
|
||||||
|
if (context->state == FlashState_fadeIn ||
|
||||||
|
context->state == FlashState_fadeOut)
|
||||||
|
{
|
||||||
|
// When we're fading in or out, we need updates during
|
||||||
|
// the fade.
|
||||||
|
return context->lastFrameTime + context->frameTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// When the flash area is completely on or off, we don't
|
||||||
|
// need an update until we're ready to change state again.
|
||||||
|
if (context->state == FlashState_on)
|
||||||
|
return context->lastStateTime + context->onTime;
|
||||||
|
else /* context->state == FlashState_off */
|
||||||
|
return context->lastStateTime + context->offTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_clearCache (FlashContext *context)
|
||||||
|
{
|
||||||
|
COUNT i;
|
||||||
|
|
||||||
|
if (context->type == FlashType_transition ||
|
||||||
|
context->type == FlashType_overlay)
|
||||||
|
{
|
||||||
|
// First frame is not allocated by the flash code, so
|
||||||
|
// we shouldn't free it.
|
||||||
|
context->cache[0] = (FRAME) 0;
|
||||||
|
}
|
||||||
|
if (context->type == FlashType_transition)
|
||||||
|
{
|
||||||
|
// Final frame is not allocated by the flash code, so
|
||||||
|
// we shouldn't free it.
|
||||||
|
context->cache[context->cacheSize - 1] = (FRAME) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < context->cacheSize; i++)
|
||||||
|
{
|
||||||
|
if (context->cache[i] != (FRAME) 0)
|
||||||
|
{
|
||||||
|
DestroyDrawable (ReleaseDrawable (context->cache[i]));
|
||||||
|
context->cache[i] = (FRAME) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_setRect (FlashContext *context, const RECT *rect)
|
||||||
|
{
|
||||||
|
if (context->started)
|
||||||
|
{
|
||||||
|
Flash_drawFrame (context, context->original);
|
||||||
|
Flash_clearCache (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
context->rect = *rect;
|
||||||
|
context->lastFrameIndex = (COUNT) -1;
|
||||||
|
|
||||||
|
if (context->started)
|
||||||
|
{
|
||||||
|
Flash_grabOriginal (context);
|
||||||
|
Flash_drawCurrentFrame (context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_getRect (FlashContext *context, RECT *rect)
|
||||||
|
{
|
||||||
|
assert (!context->type == FlashType_highlight);
|
||||||
|
|
||||||
|
*rect = context->rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call before you update the graphics in the currently flashing area.
|
||||||
|
void
|
||||||
|
Flash_preUpdate (FlashContext *context)
|
||||||
|
{
|
||||||
|
Flash_drawFrame (context, context->original);
|
||||||
|
Flash_clearCache (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call after you update the graphics in the currently flashing area.
|
||||||
|
void
|
||||||
|
Flash_postUpdate (FlashContext *context)
|
||||||
|
{
|
||||||
|
Flash_grabOriginal (context);
|
||||||
|
Flash_drawCurrentFrame (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre: context->original has been initialised.
|
||||||
|
static void
|
||||||
|
Flash_initCache (FlashContext *context)
|
||||||
|
{
|
||||||
|
COUNT i;
|
||||||
|
|
||||||
|
context->cache = HMalloc (context->cacheSize * sizeof (FRAME));
|
||||||
|
for (i = 0; i < context->cacheSize; i++)
|
||||||
|
context->cache[i] = (FRAME) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Flash_setCacheSize (FlashContext *context, COUNT size)
|
||||||
|
{
|
||||||
|
assert (size == 0 || size >= 2);
|
||||||
|
|
||||||
|
if (context->cache != NULL)
|
||||||
|
{
|
||||||
|
Flash_clearCache (context);
|
||||||
|
HFree (context->cache);
|
||||||
|
context->cache = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->cacheSize = size;
|
||||||
|
|
||||||
|
if (size != 0)
|
||||||
|
Flash_initCache (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
COUNT
|
||||||
|
Flash_getCacheSize (const FlashContext *context)
|
||||||
|
{
|
||||||
|
return context->cacheSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_grabOriginal (FlashContext *context)
|
||||||
|
{
|
||||||
|
if (context->original != (FRAME) 0)
|
||||||
|
DestroyDrawable (ReleaseDrawable (context->original));
|
||||||
|
|
||||||
|
if (context->parent == 0)
|
||||||
|
{
|
||||||
|
// Grab from the entire screen
|
||||||
|
LockMutex (GraphicsLock);
|
||||||
|
CONTEXT oldGfxContext = SetContext (context->gfxContext);
|
||||||
|
context->original = CaptureDrawable (LoadDisplayPixmap (
|
||||||
|
&context->rect, (FRAME) 0));
|
||||||
|
SetContext (oldGfxContext);
|
||||||
|
UnlockMutex (GraphicsLock);
|
||||||
|
FlushGraphics ();
|
||||||
|
// LoadDisplayPixmap only queues the command to read
|
||||||
|
// a rectangle from the screen; a FlushGraphics()
|
||||||
|
// is necessary to ensure that it can actually be used.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Grab from a frame.
|
||||||
|
context->original = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
|
||||||
|
context->rect.extent.width, context->rect.extent.height, 1));
|
||||||
|
arith_frame_blit (context->parent, &context->rect,
|
||||||
|
context->original, NULL, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
Flash_blendFraction (FlashContext *context, int numer, int denom,
|
||||||
|
int *resNumer, int *resDenom)
|
||||||
|
{
|
||||||
|
// This function merges two fractions (F0 and F1),
|
||||||
|
// based on another fraction (P) (yielding R).
|
||||||
|
// F0 = context->u.highlight.startNumer / context->u.highlight.denom
|
||||||
|
// F1 = context->u.highlight.endNumer / context->u.highlight.denom
|
||||||
|
// P = *numer / *denom
|
||||||
|
// R = P * F1 + (1 - P) * F0
|
||||||
|
// = numer * context->u.highlight.endNumer /
|
||||||
|
// (denom * context->u.highlight.denom) +
|
||||||
|
// (denom - numer) * u.highlight.startNumer /
|
||||||
|
// denom * context->u.highlight.denom
|
||||||
|
|
||||||
|
assert (numer >= 0 && numer <= denom);
|
||||||
|
|
||||||
|
*resNumer = numer * context->u.highlight.endNumer +
|
||||||
|
(denom - numer) * context->u.highlight.startNumer;
|
||||||
|
*resDenom = denom * context->u.highlight.denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_makeFrame (FlashContext *context, FRAME dest, RECT *destRect,
|
||||||
|
int numer, int denom)
|
||||||
|
{
|
||||||
|
RECT orgRect;
|
||||||
|
orgRect.corner.x = 0;
|
||||||
|
orgRect.corner.y = 0;
|
||||||
|
orgRect.extent = context->rect.extent;
|
||||||
|
|
||||||
|
switch (context->type) {
|
||||||
|
case FlashType_highlight:
|
||||||
|
{
|
||||||
|
int blendedNumer;
|
||||||
|
int blendedDenom;
|
||||||
|
|
||||||
|
Flash_blendFraction (context, numer, denom, &blendedNumer,
|
||||||
|
&blendedDenom);
|
||||||
|
arith_frame_blit (context->original, &orgRect, dest, destRect,
|
||||||
|
blendedNumer, blendedDenom);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FlashType_transition:
|
||||||
|
{
|
||||||
|
FRAME first;
|
||||||
|
FRAME final;
|
||||||
|
|
||||||
|
first = context->u.transition.first;
|
||||||
|
if (first == (FRAME) 0)
|
||||||
|
first = context->original;
|
||||||
|
final = context->u.transition.final;
|
||||||
|
if (final == (FRAME) 0)
|
||||||
|
final = context->original;
|
||||||
|
|
||||||
|
arith_frame_blit (first, &orgRect, dest, destRect,
|
||||||
|
denom - numer, denom);
|
||||||
|
arith_frame_blit (final, &orgRect, dest, destRect,
|
||||||
|
numer, -denom);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FlashType_overlay:
|
||||||
|
arith_frame_blit (context->original, &orgRect, dest, destRect,
|
||||||
|
denom, denom);
|
||||||
|
arith_frame_blit (context->u.overlay.frame, &orgRect,
|
||||||
|
dest, destRect, numer, -denom);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Prepare an entry in the cache.
|
||||||
|
static inline void
|
||||||
|
Flash_prepareCacheFrame (FlashContext *context, COUNT index)
|
||||||
|
{
|
||||||
|
if (context->cache[index] != (FRAME) 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (index == 0 && context->type == FlashType_overlay)
|
||||||
|
context->cache[index] = context->original;
|
||||||
|
else if (index == 0 && context->type == FlashType_transition)
|
||||||
|
context->cache[index] = context->u.transition.first != (FRAME) 0 ?
|
||||||
|
context->u.transition.first : context->original;
|
||||||
|
else if (index == context->cacheSize - 1 &&
|
||||||
|
context->type == FlashType_transition)
|
||||||
|
context->cache[index] = context->u.transition.final != (FRAME) 0 ?
|
||||||
|
context->u.transition.final : context->original;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context->cache[index] = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
|
||||||
|
context->rect.extent.width, context->rect.extent.height, 1));
|
||||||
|
Flash_makeFrame (context, context->cache[index], NULL,
|
||||||
|
index, context->cacheSize - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_drawFrame (FlashContext *context, FRAME frame)
|
||||||
|
{
|
||||||
|
CONTEXT oldGfxContext;
|
||||||
|
FRAME oldFGFrame = (FRAME) 0;
|
||||||
|
STAMP stamp;
|
||||||
|
|
||||||
|
LockMutex (GraphicsLock);
|
||||||
|
oldGfxContext = SetContext (context->gfxContext);
|
||||||
|
if (context->parent != NULL)
|
||||||
|
oldFGFrame = SetContextFGFrame (context->parent);
|
||||||
|
|
||||||
|
stamp.origin = context->rect.corner;
|
||||||
|
stamp.frame = frame;
|
||||||
|
DrawStamp(&stamp);
|
||||||
|
|
||||||
|
if (context->parent != NULL)
|
||||||
|
SetContextFGFrame (oldFGFrame);
|
||||||
|
SetContext (oldGfxContext);
|
||||||
|
UnlockMutex (GraphicsLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_drawCacheFrame (FlashContext *context, COUNT index)
|
||||||
|
{
|
||||||
|
FRAME frame;
|
||||||
|
|
||||||
|
if (context->lastFrameIndex == index)
|
||||||
|
return;
|
||||||
|
|
||||||
|
frame = context->cache[index];
|
||||||
|
Flash_drawFrame (context, frame);
|
||||||
|
context->lastFrameIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
Flash_drawUncachedFrame (FlashContext *context, int numer, int denom)
|
||||||
|
{
|
||||||
|
// 'lastFrameIndex' is 0 for the first image, 1 for the final
|
||||||
|
// image, and 2 otherwise.
|
||||||
|
|
||||||
|
if (numer == 0 && context->type == FlashType_overlay)
|
||||||
|
{
|
||||||
|
if (context->lastFrameIndex != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Flash_drawFrame (context, context->original);
|
||||||
|
context->lastFrameIndex = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (numer == 0 && context->type == FlashType_transition)
|
||||||
|
{
|
||||||
|
if (context->lastFrameIndex == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Flash_drawFrame (context, context->u.transition.first);
|
||||||
|
context->lastFrameIndex = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (numer == denom && context->type == FlashType_transition)
|
||||||
|
{
|
||||||
|
if (context->lastFrameIndex == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Flash_drawFrame (context, context->u.transition.final);
|
||||||
|
context->lastFrameIndex = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->lastFrameIndex = 2;
|
||||||
|
|
||||||
|
if (context->parent == NULL)
|
||||||
|
{
|
||||||
|
// Painting to the screen; we need a temporary frame to draw to.
|
||||||
|
FRAME work;
|
||||||
|
|
||||||
|
work = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
|
||||||
|
context->rect.extent.width, context->rect.extent.height, 1));
|
||||||
|
Flash_makeFrame (context, work, NULL, numer, denom);
|
||||||
|
Flash_drawFrame (context, work);
|
||||||
|
|
||||||
|
DestroyDrawable (ReleaseDrawable (work));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Painting to another frame; we can directly draw to it.
|
||||||
|
CONTEXT oldGfxContext;
|
||||||
|
FRAME oldFGFrame;
|
||||||
|
|
||||||
|
LockMutex (GraphicsLock);
|
||||||
|
oldGfxContext = SetContext (context->gfxContext);
|
||||||
|
oldFGFrame = SetContextFGFrame (context->parent);
|
||||||
|
Flash_makeFrame (context, context->parent, &context->rect,
|
||||||
|
numer, denom);
|
||||||
|
SetContextFGFrame (oldFGFrame);
|
||||||
|
SetContext (oldGfxContext);
|
||||||
|
UnlockMutex (GraphicsLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
Flash_drawCachedFrame (FlashContext *context, int numer, int denom)
|
||||||
|
{
|
||||||
|
COUNT cachePos;
|
||||||
|
|
||||||
|
cachePos = ((context->cacheSize - 1) * numer + (denom / 2)) / denom;
|
||||||
|
Flash_prepareCacheFrame (context, cachePos);
|
||||||
|
Flash_drawCacheFrame (context, cachePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Flash_drawCurrentFrame (FlashContext *context)
|
||||||
|
{
|
||||||
|
int numer;
|
||||||
|
int denom;
|
||||||
|
|
||||||
|
if (context->state == FlashState_off)
|
||||||
|
{
|
||||||
|
numer = 0;
|
||||||
|
denom = 1;
|
||||||
|
}
|
||||||
|
else if (context->state == FlashState_on)
|
||||||
|
{
|
||||||
|
numer = 1;
|
||||||
|
denom = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TimeCount now = GetTimeCounter ();
|
||||||
|
|
||||||
|
if (context->state == FlashState_fadeIn)
|
||||||
|
denom = (int) context->fadeInTime;
|
||||||
|
else
|
||||||
|
denom = (int) context->fadeOutTime;
|
||||||
|
|
||||||
|
numer = (int) (now - context->lastStateTime);
|
||||||
|
|
||||||
|
if (numer > denom)
|
||||||
|
numer = denom;
|
||||||
|
|
||||||
|
if (context->state == FlashState_fadeOut)
|
||||||
|
numer = (int) context->fadeOutTime - numer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->cacheSize == 0)
|
||||||
|
Flash_drawUncachedFrame (context, numer, denom);
|
||||||
|
else
|
||||||
|
Flash_drawCachedFrame (context, numer, denom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FLASH_H
|
||||||
|
#define _FLASH_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code can draw three kinds of flashing areas.
|
||||||
|
* - a rectangular highlight area. The brightness of the area oscilates.
|
||||||
|
* - an overlay; an image is overlayed over an area, with oscilating
|
||||||
|
* brightness.
|
||||||
|
* - a transition/cross-fade between two images.
|
||||||
|
*
|
||||||
|
* NB. The graphics lock should not be held when any of the Flash functions
|
||||||
|
* is called.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* // We create the flash context; it is used to manipulate the flash
|
||||||
|
* // rectangle while it exists.
|
||||||
|
* FlashContext *fc = Flash_createHighlight (context, (FRAME) 0, rect,
|
||||||
|
* 2, 3, 2);
|
||||||
|
*
|
||||||
|
* // We change the flashing speed from the defaults.
|
||||||
|
* Flash_setSpeed (ONE_SECOND, ONE_SECOND, ONE_SECOND, ONE_SECOND);
|
||||||
|
*
|
||||||
|
* // During cross-fades, update 8 times per second.
|
||||||
|
* Flash_setFrameTime (gmstate.player[playerI].flashContext,
|
||||||
|
* ONE_SECOND / 8);
|
||||||
|
*
|
||||||
|
* // We start the flashing. The default is to start from the "off" state.
|
||||||
|
* Flash_start (fc);
|
||||||
|
*
|
||||||
|
* // Some other stuff happens
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* // The user has activated the selection. We pause for instance while
|
||||||
|
* // a pop-up window is active.
|
||||||
|
* Flash_pause (fc);
|
||||||
|
*
|
||||||
|
* // We set the flashing rectangle full on, to indicate the current
|
||||||
|
* // selection while the popup is active.
|
||||||
|
* Flash_setState (FlashState_on);
|
||||||
|
* ...
|
||||||
|
* // Continue the flashing.
|
||||||
|
* Flash_continue (fc);
|
||||||
|
* ...
|
||||||
|
* // Modifying the graphics of the area that is flashing:
|
||||||
|
* void Flash_preUpdate (fc);
|
||||||
|
* ... // do Drawing
|
||||||
|
* void Flash_postUpdate (fc);
|
||||||
|
* ...
|
||||||
|
* // We're done. Terminating the flash restores the flash area to its
|
||||||
|
* // original state.
|
||||||
|
* Flash_terminate (fc);
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Periodically, Flash_process() should be called on the flash context,
|
||||||
|
* so that the flashing square is updated.
|
||||||
|
* You can use Flash_nextTime() to determine when the next update is needed,
|
||||||
|
* or just call Flash_process() to try (it does no updates if not needed).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libs/gfxlib.h"
|
||||||
|
#include "libs/timelib.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FlashState_fadeIn = 0,
|
||||||
|
// Someway between on and off, going towards on.
|
||||||
|
FlashState_on = 1,
|
||||||
|
// The overlay image is visible at 100% opacity.
|
||||||
|
FlashState_fadeOut = 2,
|
||||||
|
// Someway between on and off, going towards off.
|
||||||
|
FlashState_off = 3,
|
||||||
|
// The overlay image is not visible.
|
||||||
|
} FlashState;
|
||||||
|
|
||||||
|
typedef struct FlashContext FlashContext;
|
||||||
|
|
||||||
|
#ifdef FLASH_INTERNAL
|
||||||
|
typedef enum {
|
||||||
|
FlashType_highlight,
|
||||||
|
FlashType_transition,
|
||||||
|
FlashType_overlay,
|
||||||
|
} FlashType;
|
||||||
|
|
||||||
|
struct FlashContext {
|
||||||
|
CONTEXT gfxContext;
|
||||||
|
// The graphics context used for drawing.
|
||||||
|
FRAME parent;
|
||||||
|
// The frame that contains the flash rectangle.
|
||||||
|
|
||||||
|
RECT rect;
|
||||||
|
// The rectangle to flash.
|
||||||
|
|
||||||
|
FRAME original;
|
||||||
|
// The original contents of the flash area.
|
||||||
|
|
||||||
|
FlashType type;
|
||||||
|
// The type of flash animation.
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int startNumer;
|
||||||
|
// Numerator for the brightness for the on state.
|
||||||
|
int endNumer;
|
||||||
|
// Numerator for the brightness for the off state.
|
||||||
|
int denom;
|
||||||
|
// Denominator for the brightness.
|
||||||
|
} highlight;
|
||||||
|
struct {
|
||||||
|
FRAME first;
|
||||||
|
// The first image from the transition (cross-fade).
|
||||||
|
// (FRAME) 0 means that the original is to be used.
|
||||||
|
FRAME final;
|
||||||
|
// The last image from the transition.
|
||||||
|
// (FRAME) 0 means that the original is to be used.
|
||||||
|
} transition;
|
||||||
|
struct {
|
||||||
|
FRAME frame;
|
||||||
|
} overlay;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
TimeCount fadeInTime;
|
||||||
|
TimeCount onTime;
|
||||||
|
TimeCount fadeOutTime;
|
||||||
|
TimeCount offTime;
|
||||||
|
|
||||||
|
TimeCount frameTime;
|
||||||
|
|
||||||
|
FlashState state;
|
||||||
|
TimeCount lastStateTime;
|
||||||
|
// Time of the last state change.
|
||||||
|
TimeCount lastFrameTime;
|
||||||
|
// Time of the last frame draw.
|
||||||
|
|
||||||
|
BOOLEAN started : 1;
|
||||||
|
BOOLEAN paused : 1;
|
||||||
|
|
||||||
|
FRAME *cache;
|
||||||
|
COUNT cacheSize;
|
||||||
|
|
||||||
|
COUNT lastFrameIndex;
|
||||||
|
// Last frame drawn; used to determine whether a frame needs to
|
||||||
|
// be redawn. If a cache is used, this is the index in the cache.
|
||||||
|
// If no cache is used, this is either 0, 1, or 2, for
|
||||||
|
// the respectively first, last, or other frame for the flash
|
||||||
|
// animation.
|
||||||
|
};
|
||||||
|
|
||||||
|
# define Flash_DEFAULT_FADE_IN_TIME 0
|
||||||
|
# define Flash_DEFAULT_ON_TIME (ONE_SECOND / 8)
|
||||||
|
# define Flash_DEFAULT_FADE_OUT_TIME 0
|
||||||
|
# define Flash_DEFAULT_OFF_TIME (ONE_SECOND / 8)
|
||||||
|
|
||||||
|
# define Flash_DEFAULT_CACHE_SIZE 9
|
||||||
|
#endif /* FLASH_INTERNAL */
|
||||||
|
|
||||||
|
|
||||||
|
FlashContext *Flash_createHighlight (CONTEXT gfxContext, FRAME parent,
|
||||||
|
const RECT *rect, int startNumer, int endNumer, int denom);
|
||||||
|
FlashContext *Flash_createTransition (CONTEXT gfxContext, FRAME parent,
|
||||||
|
const POINT *origin, FRAME first, FRAME final);
|
||||||
|
FlashContext *Flash_createOverlay (CONTEXT gfxContext, FRAME parent,
|
||||||
|
const POINT *origin, FRAME overlay);
|
||||||
|
|
||||||
|
void Flash_setState (FlashContext *context, FlashState state);
|
||||||
|
void Flash_start (FlashContext *context);
|
||||||
|
void Flash_terminate (FlashContext *context);
|
||||||
|
void Flash_pause (FlashContext *context);
|
||||||
|
void Flash_continue (FlashContext *context);
|
||||||
|
void Flash_process (FlashContext *context);
|
||||||
|
void Flash_setSpeed (FlashContext *context, TimeCount fadeInTime,
|
||||||
|
TimeCount onTime, TimeCount fadeOutTime, TimeCount offTime);
|
||||||
|
void Flash_setFrameTime (FlashContext *context, TimeCount frameTime);
|
||||||
|
TimeCount Flash_nextTime (FlashContext *context);
|
||||||
|
void Flash_setRect (FlashContext *context, const RECT *rect);
|
||||||
|
void Flash_getRect (FlashContext *context, RECT *rect);
|
||||||
|
void Flash_preUpdate (FlashContext *context);
|
||||||
|
void Flash_postUpdate (FlashContext *context);
|
||||||
|
void Flash_setCacheSize (FlashContext *context, COUNT size);
|
||||||
|
COUNT Flash_getCacheSize (const FlashContext *context);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _FLASH_H */
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
#define FLAGSHIP_STRING_COUNT 13
|
#define FLAGSHIP_STRING_COUNT 13
|
||||||
#define ORBITSCAN_STRING_COUNT 19
|
#define ORBITSCAN_STRING_COUNT 19
|
||||||
#define MAINMENU_STRING_COUNT 57
|
#define MAINMENU_STRING_COUNT 57
|
||||||
#define NETMELEE_STRING_COUNT 18
|
#define NETMELEE_STRING_COUNT 19
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STAR_STRING_BASE = 0,
|
STAR_STRING_BASE = 0,
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
#define UMGAH_BCS_MASK_PMAP_ANIM 0x13c04702L
|
#define UMGAH_BCS_MASK_PMAP_ANIM 0x13c04702L
|
||||||
#define MELEE_SCREEN_PMAP_ANIM 0x14204802L
|
#define MELEE_SCREEN_PMAP_ANIM 0x14204802L
|
||||||
#define MELEE_PICK_MASK_PMAP_ANIM 0x14404902L
|
#define MELEE_PICK_MASK_PMAP_ANIM 0x14404902L
|
||||||
|
// melee/melee.ani
|
||||||
#define SEGUE_PMAP_ANIM 0x14604a02L
|
#define SEGUE_PMAP_ANIM 0x14604a02L
|
||||||
#define SC2_PICK_PMAP_ANIM 0x14804b02L
|
#define SC2_PICK_PMAP_ANIM 0x14804b02L
|
||||||
#define RESTART_PMAP_ANIM 0x18204c02L
|
#define RESTART_PMAP_ANIM 0x18204c02L
|
||||||
|
|||||||
+31
-14
@@ -146,7 +146,6 @@ InitShips (void)
|
|||||||
InitDisplayList ();
|
InitDisplayList ();
|
||||||
InitGalaxy ();
|
InitGalaxy ();
|
||||||
|
|
||||||
num_ships = NUM_SIDES;
|
|
||||||
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
|
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
|
||||||
{
|
{
|
||||||
ReinitQueue (&race_q[0]);
|
ReinitQueue (&race_q[0]);
|
||||||
@@ -156,7 +155,7 @@ InitShips (void)
|
|||||||
|
|
||||||
LoadHyperspace ();
|
LoadHyperspace ();
|
||||||
|
|
||||||
--num_ships;
|
num_ships = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -193,6 +192,8 @@ InitShips (void)
|
|||||||
for (i = 0; i < NUM_PLANETS; ++i)
|
for (i = 0; i < NUM_PLANETS; ++i)
|
||||||
spawn_planet ();
|
spawn_planet ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_ships = NUM_SIDES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushInput ();
|
// FlushInput ();
|
||||||
@@ -200,10 +201,34 @@ InitShips (void)
|
|||||||
return (num_ships);
|
return (num_ships);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count the crew elements in the display list.
|
||||||
|
static COUNT
|
||||||
|
CountCrewElements (void)
|
||||||
|
{
|
||||||
|
COUNT result;
|
||||||
|
HELEMENT hElement, hNextElement;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (hElement = GetHeadElement ();
|
||||||
|
hElement != 0; hElement = hNextElement)
|
||||||
|
{
|
||||||
|
ELEMENT *ElementPtr;
|
||||||
|
|
||||||
|
LockElement (hElement, &ElementPtr);
|
||||||
|
hNextElement = GetSuccElement (ElementPtr);
|
||||||
|
if (ElementPtr->state_flags & CREW_OBJECT)
|
||||||
|
++result;
|
||||||
|
|
||||||
|
UnlockElement (hElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UninitShips (void)
|
UninitShips (void)
|
||||||
{
|
{
|
||||||
BYTE crew_retrieved;
|
COUNT crew_retrieved;
|
||||||
SIZE i;
|
SIZE i;
|
||||||
HELEMENT hElement, hNextElement;
|
HELEMENT hElement, hNextElement;
|
||||||
STARSHIP *SPtr[NUM_PLAYERS];
|
STARSHIP *SPtr[NUM_PLAYERS];
|
||||||
@@ -216,17 +241,7 @@ UninitShips (void)
|
|||||||
SPtr[i] = 0;
|
SPtr[i] = 0;
|
||||||
|
|
||||||
// Count the crew floating in space.
|
// Count the crew floating in space.
|
||||||
crew_retrieved = 0;
|
crew_retrieved = CountCrewElements();
|
||||||
for (hElement = GetHeadElement ();
|
|
||||||
hElement != 0; hElement = hNextElement)
|
|
||||||
{
|
|
||||||
ELEMENT *ElementPtr;
|
|
||||||
LockElement (hElement, &ElementPtr);
|
|
||||||
hNextElement = GetSuccElement (ElementPtr);
|
|
||||||
if (ElementPtr->state_flags & CREW_OBJECT)
|
|
||||||
++crew_retrieved;
|
|
||||||
UnlockElement (hElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (hElement = GetHeadElement ();
|
for (hElement = GetHeadElement ();
|
||||||
hElement != 0; hElement = hNextElement)
|
hElement != 0; hElement = hNextElement)
|
||||||
@@ -278,6 +293,8 @@ UninitShips (void)
|
|||||||
else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER
|
else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER
|
||||||
&& !(GLOBAL (CurrentActivity) & CHECK_ABORT))
|
&& !(GLOBAL (CurrentActivity) & CHECK_ABORT))
|
||||||
{
|
{
|
||||||
|
// XXX: What is the reason for this? At least for SuperMelee,
|
||||||
|
// it has no purpose (it will return immediately).
|
||||||
for (i = NUM_PLAYERS - 1; i >= 0; --i)
|
for (i = NUM_PLAYERS - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
if (SPtr[i])
|
if (SPtr[i])
|
||||||
|
|||||||
@@ -255,8 +255,8 @@ void fill_frame_rgb (FRAME FramePtr, Uint32 color, int x0, int y0,
|
|||||||
UnlockMutex (tfbImg->mutex);
|
UnlockMutex (tfbImg->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame,
|
void arith_frame_blit (FRAME srcFrame, const RECT *rsrc, FRAME dstFrame,
|
||||||
RECT *rdst, int num, int denom)
|
const RECT *rdst, int num, int denom)
|
||||||
{
|
{
|
||||||
TFB_Image *srcImg, *dstImg;
|
TFB_Image *srcImg, *dstImg;
|
||||||
SDL_Surface *src, *dst;
|
SDL_Surface *src, *dst;
|
||||||
@@ -296,7 +296,7 @@ void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame,
|
|||||||
dstRect.y = -srcFrame->HotSpot.y;
|
dstRect.y = -srcFrame->HotSpot.y;
|
||||||
dstRect.w = GetFrameWidth (srcFrame);
|
dstRect.w = GetFrameWidth (srcFrame);
|
||||||
dstRect.h = GetFrameHeight (srcFrame);
|
dstRect.h = GetFrameHeight (srcFrame);
|
||||||
drp =&dstRect;
|
drp = &dstRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+129
-101
@@ -160,6 +160,9 @@ enum
|
|||||||
#define TEAM_NAME_EDIT_CURS_COLOR \
|
#define TEAM_NAME_EDIT_CURS_COLOR \
|
||||||
WHITE_COLOR
|
WHITE_COLOR
|
||||||
|
|
||||||
|
#define LOAD_TEAM_NAME_TEXT_COLOR TEAM_NAME_TEXT_COLOR
|
||||||
|
#define LOAD_TEAM_NAME_TEXT_COLOR_HILITE TEAM_NAME_EDIT_TEXT_COLOR
|
||||||
|
|
||||||
#define PICKSHIP_TEAM_NAME_TEXT_COLOR \
|
#define PICKSHIP_TEAM_NAME_TEXT_COLOR \
|
||||||
BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)
|
BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)
|
||||||
#define PICKSHIP_TEAM_START_VALUE_COLOR \
|
#define PICKSHIP_TEAM_START_VALUE_COLOR \
|
||||||
@@ -185,7 +188,9 @@ enum
|
|||||||
|
|
||||||
FRAME PickMeleeFrame;
|
FRAME PickMeleeFrame;
|
||||||
static FRAME MeleeFrame;
|
static FRAME MeleeFrame;
|
||||||
|
// Loaded from melee/melebkgd.ani
|
||||||
static FRAME BuildPickFrame;
|
static FRAME BuildPickFrame;
|
||||||
|
// Constructed.
|
||||||
extern QUEUE master_q;
|
extern QUEUE master_q;
|
||||||
DWORD InTime;
|
DWORD InTime;
|
||||||
MELEE_STATE *pMeleeState;
|
MELEE_STATE *pMeleeState;
|
||||||
@@ -208,12 +213,14 @@ static BOOLEAN DoLoadTeam (MELEE_STATE *pMS);
|
|||||||
static void DrawFileStrings (MELEE_STATE *pMS, int HiLiteState);
|
static void DrawFileStrings (MELEE_STATE *pMS, int HiLiteState);
|
||||||
|
|
||||||
|
|
||||||
|
// These icons come from melee/melebkgd.ani
|
||||||
static void
|
static void
|
||||||
DrawMeleeIcon (COUNT which_icon)
|
DrawMeleeIcon (COUNT which_icon)
|
||||||
{
|
{
|
||||||
STAMP s;
|
STAMP s;
|
||||||
|
|
||||||
s.origin.x = s.origin.y = 0;
|
s.origin.x = 0;
|
||||||
|
s.origin.y = 0;
|
||||||
s.frame = SetAbsFrameIndex (MeleeFrame, which_icon);
|
s.frame = SetAbsFrameIndex (MeleeFrame, which_icon);
|
||||||
DrawStamp (&s);
|
DrawStamp (&s);
|
||||||
}
|
}
|
||||||
@@ -292,7 +299,7 @@ static void
|
|||||||
DrawShipBoxCurrent (MELEE_STATE *pMS, BOOLEAN HiLite)
|
DrawShipBoxCurrent (MELEE_STATE *pMS, BOOLEAN HiLite)
|
||||||
{
|
{
|
||||||
FleetShipIndex index = GetShipIndex (pMS->row, pMS->col);
|
FleetShipIndex index = GetShipIndex (pMS->row, pMS->col);
|
||||||
BYTE ship = pMS->TeamImage[pMS->side].ShipList[index];
|
BYTE ship = pMS->SideState[pMS->side].TeamImage.ShipList[index];
|
||||||
DrawShipBox (pMS->side, pMS->row, pMS->col, ship, HiLite);
|
DrawShipBox (pMS->side, pMS->row, pMS->col, ship, HiLite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,6 +312,7 @@ DrawControls (COUNT which_side, BOOLEAN HiLite)
|
|||||||
if (PlayerControl[which_side] & NETWORK_CONTROL)
|
if (PlayerControl[which_side] & NETWORK_CONTROL)
|
||||||
{
|
{
|
||||||
DrawMeleeIcon (31 + (HiLite ? 1 : 0) + 2 * (1 - which_side));
|
DrawMeleeIcon (31 + (HiLite ? 1 : 0) + 2 * (1 - which_side));
|
||||||
|
/* "Network Control" */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,8 +396,8 @@ RepairMeleeFrame (RECT *pRect)
|
|||||||
|
|
||||||
DrawMeleeIcon (0); /* Entire melee screen */
|
DrawMeleeIcon (0); /* Entire melee screen */
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
DrawMeleeIcon (35);
|
DrawMeleeIcon (35); /* "Net..." (top, not highlighted) */
|
||||||
DrawMeleeIcon (37);
|
DrawMeleeIcon (37); /* "Net..." (bottom, not highlighted) */
|
||||||
#endif
|
#endif
|
||||||
DrawMeleeIcon (26); /* "Battle!" (highlighted) */
|
DrawMeleeIcon (26); /* "Battle!" (highlighted) */
|
||||||
{
|
{
|
||||||
@@ -405,7 +413,8 @@ RepairMeleeFrame (RECT *pRect)
|
|||||||
for (col = 0; col < NUM_MELEE_COLUMNS; col++)
|
for (col = 0; col < NUM_MELEE_COLUMNS; col++)
|
||||||
{
|
{
|
||||||
FleetShipIndex index = GetShipIndex (row, col);
|
FleetShipIndex index = GetShipIndex (row, col);
|
||||||
BYTE ship = pMeleeState->TeamImage[side].ShipList[index];
|
BYTE ship = pMeleeState->SideState[side].TeamImage.
|
||||||
|
ShipList[index];
|
||||||
DrawShipBox (side, row, col, ship, FALSE);
|
DrawShipBox (side, row, col, ship, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,7 +463,7 @@ DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState)
|
|||||||
|
|
||||||
SetContextFont (MicroFont);
|
SetContextFont (MicroFont);
|
||||||
|
|
||||||
lfText.pStr = pMS->TeamImage[side].TeamName;
|
lfText.pStr = pMS->SideState[side].TeamImage.TeamName;
|
||||||
lfText.baseline.y = r.corner.y + r.extent.height - 3;
|
lfText.baseline.y = r.corner.y + r.extent.height - 3;
|
||||||
|
|
||||||
lfText.baseline.x = r.corner.x + 1;
|
lfText.baseline.x = r.corner.x + 1;
|
||||||
@@ -467,7 +476,7 @@ DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState)
|
|||||||
TEXT rtText;
|
TEXT rtText;
|
||||||
UNICODE buf[30];
|
UNICODE buf[30];
|
||||||
|
|
||||||
sprintf (buf, "%d", pMS->star_bucks[side]);
|
sprintf (buf, "%d", pMS->SideState[side].star_bucks);
|
||||||
rtText.pStr = buf;
|
rtText.pStr = buf;
|
||||||
rtText.align = ALIGN_RIGHT;
|
rtText.align = ALIGN_RIGHT;
|
||||||
rtText.CharCount = (COUNT)~0;
|
rtText.CharCount = (COUNT)~0;
|
||||||
@@ -713,27 +722,30 @@ Deselect (BYTE opt)
|
|||||||
break;
|
break;
|
||||||
case LOAD_TOP:
|
case LOAD_TOP:
|
||||||
case LOAD_BOT:
|
case LOAD_BOT:
|
||||||
if (pMeleeState->InputFunc != DoLoadTeam)
|
if (pMeleeState->InputFunc != DoLoadTeam) {
|
||||||
DrawMeleeIcon (opt == LOAD_TOP ? 17 : 22);
|
DrawMeleeIcon (opt == LOAD_TOP ? 17 : 22);
|
||||||
|
/* 17: "Load" (top, not highlighted) */
|
||||||
|
/* 22: "Load" (bottom, not highlighted) */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
DrawFileStrings (pMeleeState, 0);
|
DrawFileStrings (pMeleeState, 0);
|
||||||
break;
|
break;
|
||||||
case SAVE_TOP:
|
case SAVE_TOP:
|
||||||
DrawMeleeIcon (18); /* "Save" (top; not highlighted) */
|
DrawMeleeIcon (18); /* "Save" (top, not highlighted) */
|
||||||
break;
|
break;
|
||||||
case SAVE_BOT:
|
case SAVE_BOT:
|
||||||
DrawMeleeIcon (21); /* "Save" (bottom; not highlighted) */
|
DrawMeleeIcon (21); /* "Save" (bottom, not highlighted) */
|
||||||
break;
|
break;
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
case NET_TOP:
|
case NET_TOP:
|
||||||
DrawMeleeIcon (35);
|
DrawMeleeIcon (35); /* "Net..." (top, not highlighted) */
|
||||||
break;
|
break;
|
||||||
case NET_BOT:
|
case NET_BOT:
|
||||||
DrawMeleeIcon (37);
|
DrawMeleeIcon (37); /* "Net..." (bottom, not highlighted) */
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case QUIT_BOT:
|
case QUIT_BOT:
|
||||||
DrawMeleeIcon (29);
|
DrawMeleeIcon (29); /* "Quit" (not highlighted) */
|
||||||
break;
|
break;
|
||||||
case CONTROLS_TOP:
|
case CONTROLS_TOP:
|
||||||
case CONTROLS_BOT:
|
case CONTROLS_BOT:
|
||||||
@@ -774,7 +786,11 @@ Select (BYTE opt)
|
|||||||
case LOAD_TOP:
|
case LOAD_TOP:
|
||||||
case LOAD_BOT:
|
case LOAD_BOT:
|
||||||
if (pMeleeState->InputFunc != DoLoadTeam)
|
if (pMeleeState->InputFunc != DoLoadTeam)
|
||||||
|
{
|
||||||
DrawMeleeIcon (opt == LOAD_TOP ? 19 : 24);
|
DrawMeleeIcon (opt == LOAD_TOP ? 19 : 24);
|
||||||
|
/* 19: "Load" (top, highlighted) */
|
||||||
|
/* 24: "Load" (bottom, highlighted) */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
DrawFileStrings (pMeleeState, 1);
|
DrawFileStrings (pMeleeState, 1);
|
||||||
break;
|
break;
|
||||||
@@ -786,14 +802,14 @@ Select (BYTE opt)
|
|||||||
break;
|
break;
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
case NET_TOP:
|
case NET_TOP:
|
||||||
DrawMeleeIcon (36); /* "Save" (top; highlighted) */
|
DrawMeleeIcon (36); /* "Net..." (top; highlighted) */
|
||||||
break;
|
break;
|
||||||
case NET_BOT:
|
case NET_BOT:
|
||||||
DrawMeleeIcon (38); /* "Save" (bottom; highlighted) */
|
DrawMeleeIcon (38); /* "Net..." (bottom; highlighted) */
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case QUIT_BOT:
|
case QUIT_BOT:
|
||||||
DrawMeleeIcon (30);
|
DrawMeleeIcon (30); /* "Quit" (highlighted) */
|
||||||
break;
|
break;
|
||||||
case CONTROLS_TOP:
|
case CONTROLS_TOP:
|
||||||
case CONTROLS_BOT:
|
case CONTROLS_BOT:
|
||||||
@@ -956,7 +972,8 @@ UpdateCurrentShip (MELEE_STATE *pMS)
|
|||||||
if (pMS->row == NUM_MELEE_ROWS)
|
if (pMS->row == NUM_MELEE_ROWS)
|
||||||
pMS->CurIndex = MELEE_NONE;
|
pMS->CurIndex = MELEE_NONE;
|
||||||
else
|
else
|
||||||
pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex];
|
pMS->CurIndex =
|
||||||
|
pMS->SideState[pMS->side].TeamImage.ShipList[fleetShipIndex];
|
||||||
DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex));
|
DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1109,8 +1126,8 @@ DrawFileStrings (MELEE_STATE *pMS, int HiLiteState)
|
|||||||
Text.pStr = pMS->FileList[bot].TeamName;
|
Text.pStr = pMS->FileList[bot].TeamName;
|
||||||
Text.CharCount = (COUNT)~0;
|
Text.CharCount = (COUNT)~0;
|
||||||
SetContextForeGroundColor (HiLiteState == 0 ?
|
SetContextForeGroundColor (HiLiteState == 0 ?
|
||||||
BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00)
|
LOAD_TEAM_NAME_TEXT_COLOR :
|
||||||
: BUILD_COLOR (MAKE_RGB15 (23, 24, 29), 0x00));
|
LOAD_TEAM_NAME_TEXT_COLOR_HILITE);
|
||||||
font_DrawText (&Text);
|
font_DrawText (&Text);
|
||||||
|
|
||||||
rtText.baseline.y = Text.baseline.y;
|
rtText.baseline.y = Text.baseline.y;
|
||||||
@@ -1122,7 +1139,7 @@ DrawFileStrings (MELEE_STATE *pMS, int HiLiteState)
|
|||||||
{
|
{
|
||||||
COUNT teams_left;
|
COUNT teams_left;
|
||||||
|
|
||||||
DrawMeleeIcon (28); /* Load team frame */
|
DrawMeleeIcon (28); /* The load team frame */
|
||||||
|
|
||||||
Text.baseline.y = y;
|
Text.baseline.y = y;
|
||||||
teams_left = (COUNT)(
|
teams_left = (COUNT)(
|
||||||
@@ -1151,8 +1168,7 @@ DrawFileStrings (MELEE_STATE *pMS, int HiLiteState)
|
|||||||
{
|
{
|
||||||
Text.pStr = pMS->FileList[bot - top].TeamName;
|
Text.pStr = pMS->FileList[bot - top].TeamName;
|
||||||
Text.CharCount = (COUNT)~0;
|
Text.CharCount = (COUNT)~0;
|
||||||
SetContextForeGroundColor (
|
SetContextForeGroundColor (TEAM_NAME_TEXT_COLOR);
|
||||||
BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00));
|
|
||||||
font_DrawText (&Text);
|
font_DrawText (&Text);
|
||||||
|
|
||||||
rtText.baseline.y = Text.baseline.y;
|
rtText.baseline.y = Text.baseline.y;
|
||||||
@@ -1228,10 +1244,10 @@ DoLoadTeam (MELEE_STATE *pMS)
|
|||||||
{
|
{
|
||||||
if (!PulsedInputState.menu[KEY_MENU_CANCEL])
|
if (!PulsedInputState.menu[KEY_MENU_CANCEL])
|
||||||
{
|
{
|
||||||
pMS->TeamImage[pMS->side] =
|
pMS->SideState[pMS->side].TeamImage =
|
||||||
pMS->FileList[pMS->CurIndex - pMS->TopTeamIndex];
|
pMS->FileList[pMS->CurIndex - pMS->TopTeamIndex];
|
||||||
pMS->star_bucks[pMS->side] =
|
pMS->SideState[pMS->side].star_bucks =
|
||||||
GetTeamValue (&pMS->TeamImage[pMS->side]);
|
GetTeamValue (&pMS->SideState[pMS->side].TeamImage);
|
||||||
entireFleetChanged (pMS, pMS->side);
|
entireFleetChanged (pMS, pMS->side);
|
||||||
teamStringChanged (pMS, pMS->side);
|
teamStringChanged (pMS, pMS->side);
|
||||||
}
|
}
|
||||||
@@ -1381,7 +1397,7 @@ DoSaveTeam (MELEE_STATE *pMS)
|
|||||||
uio_Stream *save_fp;
|
uio_Stream *save_fp;
|
||||||
CONTEXT OldContext;
|
CONTEXT OldContext;
|
||||||
|
|
||||||
sprintf (file, "%s.mle", pMS->TeamImage[pMS->side].TeamName);
|
sprintf (file, "%s.mle", pMS->SideState[pMS->side].TeamImage.TeamName);
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
OldContext = SetContext (ScreenContext);
|
OldContext = SetContext (ScreenContext);
|
||||||
@@ -1392,7 +1408,7 @@ DoSaveTeam (MELEE_STATE *pMS)
|
|||||||
BOOLEAN err;
|
BOOLEAN err;
|
||||||
|
|
||||||
err = (BOOLEAN)(WriteTeamImage (
|
err = (BOOLEAN)(WriteTeamImage (
|
||||||
&pMS->TeamImage[pMS->side], save_fp) == 0);
|
&pMS->SideState[pMS->side].TeamImage, save_fp) == 0);
|
||||||
if (res_CloseResFile (save_fp) == 0)
|
if (res_CloseResFile (save_fp) == 0)
|
||||||
err = TRUE;
|
err = TRUE;
|
||||||
if (err)
|
if (err)
|
||||||
@@ -1434,16 +1450,17 @@ DeleteCurrentShip (MELEE_STATE *pMS)
|
|||||||
int CurIndex;
|
int CurIndex;
|
||||||
|
|
||||||
fleetShipIndex = GetShipIndex (pMS->row, pMS->col);
|
fleetShipIndex = GetShipIndex (pMS->row, pMS->col);
|
||||||
CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex];
|
CurIndex = pMS->SideState[pMS->side].TeamImage.ShipList[fleetShipIndex];
|
||||||
hStarShip = GetStarShipFromIndex (&master_q, CurIndex);
|
hStarShip = GetStarShipFromIndex (&master_q, CurIndex);
|
||||||
StarShipPtr = LockStarShip (&master_q, hStarShip);
|
StarShipPtr = LockStarShip (&master_q, hStarShip);
|
||||||
if (StarShipPtr)
|
if (StarShipPtr)
|
||||||
{
|
{
|
||||||
pMS->star_bucks[pMS->side] -=
|
pMS->SideState[pMS->side].star_bucks -=
|
||||||
StarShipPtr->RaceDescPtr->ship_info.ship_cost;
|
StarShipPtr->RaceDescPtr->ship_info.ship_cost;
|
||||||
UnlockStarShip (&master_q, hStarShip);
|
UnlockStarShip (&master_q, hStarShip);
|
||||||
|
|
||||||
pMS->TeamImage[pMS->side].ShipList[fleetShipIndex] = MELEE_NONE;
|
pMS->SideState[pMS->side].TeamImage.ShipList[fleetShipIndex] =
|
||||||
|
MELEE_NONE;
|
||||||
}
|
}
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
GetShipBox (&r, pMS->side, pMS->row, pMS->col);
|
GetShipBox (&r, pMS->side, pMS->row, pMS->col);
|
||||||
@@ -1496,7 +1513,8 @@ DoEdit (MELEE_STATE *pMS)
|
|||||||
if (!pMS->Initialized)
|
if (!pMS->Initialized)
|
||||||
{
|
{
|
||||||
FleetShipIndex fleetShipIndex = GetShipIndex (pMS->row, pMS->col);
|
FleetShipIndex fleetShipIndex = GetShipIndex (pMS->row, pMS->col);
|
||||||
pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex];
|
pMS->CurIndex =
|
||||||
|
pMS->SideState[pMS->side].TeamImage.ShipList[fleetShipIndex];
|
||||||
DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex);
|
DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex);
|
||||||
|
|
||||||
pMS->Initialized = TRUE;
|
pMS->Initialized = TRUE;
|
||||||
@@ -1570,7 +1588,7 @@ DoEdit (MELEE_STATE *pMS)
|
|||||||
|
|
||||||
tes.Initialized = FALSE;
|
tes.Initialized = FALSE;
|
||||||
tes.MenuRepeatDelay = 0;
|
tes.MenuRepeatDelay = 0;
|
||||||
tes.BaseStr = pMS->TeamImage[pMS->side].TeamName;
|
tes.BaseStr = pMS->SideState[pMS->side].TeamImage.TeamName;
|
||||||
tes.CursorPos = 0;
|
tes.CursorPos = 0;
|
||||||
tes.MaxSize = MAX_TEAM_CHARS + 1;
|
tes.MaxSize = MAX_TEAM_CHARS + 1;
|
||||||
tes.CbParam = pMS;
|
tes.CbParam = pMS;
|
||||||
@@ -1666,9 +1684,7 @@ DoPickShip (MELEE_STATE *pMS)
|
|||||||
if (pMS->CurIndex == (BYTE)~0 && pMS->Initialized == 0)
|
if (pMS->CurIndex == (BYTE)~0 && pMS->Initialized == 0)
|
||||||
pMS->CurIndex = 0;
|
pMS->CurIndex = 0;
|
||||||
else if (pMS->CurIndex != (BYTE)~0)
|
else if (pMS->CurIndex != (BYTE)~0)
|
||||||
{
|
|
||||||
DeleteCurrentShip (pMS);
|
DeleteCurrentShip (pMS);
|
||||||
}
|
|
||||||
|
|
||||||
if (pMS->Initialized == 0)
|
if (pMS->Initialized == 0)
|
||||||
{
|
{
|
||||||
@@ -1686,7 +1702,8 @@ DoPickShip (MELEE_STATE *pMS)
|
|||||||
Deselect (EDIT_MELEE);
|
Deselect (EDIT_MELEE);
|
||||||
pMS->Initialized = TRUE;
|
pMS->Initialized = TRUE;
|
||||||
AdvanceCursor (pMS);
|
AdvanceCursor (pMS);
|
||||||
pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex];
|
pMS->CurIndex = pMS->SideState[pMS->side].TeamImage.ShipList[
|
||||||
|
fleetShipIndex];
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex));
|
DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex));
|
||||||
@@ -1705,11 +1722,12 @@ DoPickShip (MELEE_STATE *pMS)
|
|||||||
|
|
||||||
hStarShip = GetStarShipFromIndex (&master_q, pMS->CurIndex);
|
hStarShip = GetStarShipFromIndex (&master_q, pMS->CurIndex);
|
||||||
StarShipPtr = LockStarShip (&master_q, hStarShip);
|
StarShipPtr = LockStarShip (&master_q, hStarShip);
|
||||||
pMS->star_bucks[pMS->side] +=
|
pMS->SideState[pMS->side].star_bucks +=
|
||||||
StarShipPtr->RaceDescPtr->ship_info.ship_cost;
|
StarShipPtr->RaceDescPtr->ship_info.ship_cost;
|
||||||
UnlockStarShip (&master_q, hStarShip);
|
UnlockStarShip (&master_q, hStarShip);
|
||||||
|
|
||||||
pMS->TeamImage[pMS->side].ShipList[index] = pMS->CurIndex;
|
pMS->SideState[pMS->side].TeamImage.ShipList[index] =
|
||||||
|
pMS->CurIndex;
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
DrawTeamString (pMS, pMS->side, DTSHS_REPAIR);
|
DrawTeamString (pMS, pMS->side, DTSHS_REPAIR);
|
||||||
DrawShipBoxCurrent (pMS, FALSE);
|
DrawShipBoxCurrent (pMS, FALSE);
|
||||||
@@ -1972,12 +1990,14 @@ LoadMeleeInfo (MELEE_STATE *pMS)
|
|||||||
|
|
||||||
// create team building ship selection box
|
// create team building ship selection box
|
||||||
s.frame = SetAbsFrameIndex (MeleeFrame, 27);
|
s.frame = SetAbsFrameIndex (MeleeFrame, 27);
|
||||||
|
// 5x5 grid of ships to pick from
|
||||||
GetFrameRect (s.frame, &r);
|
GetFrameRect (s.frame, &r);
|
||||||
BuildPickFrame = CaptureDrawable (CreateDrawable (
|
BuildPickFrame = CaptureDrawable (CreateDrawable (
|
||||||
WANT_PIXMAP, r.extent.width, r.extent.height, 1));
|
WANT_PIXMAP, r.extent.width, r.extent.height, 1));
|
||||||
SetContextFGFrame (BuildPickFrame);
|
SetContextFGFrame (BuildPickFrame);
|
||||||
SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0));
|
SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0));
|
||||||
DrawStamp (&s);
|
DrawStamp (&s);
|
||||||
|
|
||||||
for (i = 0; i < NUM_PICK_COLS * NUM_PICK_ROWS; ++i)
|
for (i = 0; i < NUM_PICK_COLS * NUM_PICK_ROWS; ++i)
|
||||||
DrawPickIcon (i, 1);
|
DrawPickIcon (i, 1);
|
||||||
|
|
||||||
@@ -2056,14 +2076,14 @@ BuildAndDrawShipList (MELEE_STATE *pMS)
|
|||||||
|
|
||||||
// Team name at the bottom of the frame:
|
// Team name at the bottom of the frame:
|
||||||
t.align = ALIGN_CENTER;
|
t.align = ALIGN_CENTER;
|
||||||
t.pStr = pMS->TeamImage[i].TeamName;
|
t.pStr = pMS->SideState[i].TeamImage.TeamName;
|
||||||
t.CharCount = (COUNT)~0;
|
t.CharCount = (COUNT)~0;
|
||||||
SetContextFont (TinyFont);
|
SetContextFont (TinyFont);
|
||||||
SetContextForeGroundColor (PICKSHIP_TEAM_NAME_TEXT_COLOR);
|
SetContextForeGroundColor (PICKSHIP_TEAM_NAME_TEXT_COLOR);
|
||||||
font_DrawText (&t);
|
font_DrawText (&t);
|
||||||
|
|
||||||
// Total team value of the starting team:
|
// Total team value of the starting team:
|
||||||
sprintf (buf, "%d", pMS->star_bucks[i]);
|
sprintf (buf, "%d", pMS->SideState[i].star_bucks);
|
||||||
t.baseline.x = 4;
|
t.baseline.x = 4;
|
||||||
t.baseline.y = 7;
|
t.baseline.y = 7;
|
||||||
t.align = ALIGN_LEFT;
|
t.align = ALIGN_LEFT;
|
||||||
@@ -2076,7 +2096,7 @@ BuildAndDrawShipList (MELEE_STATE *pMS)
|
|||||||
{
|
{
|
||||||
BYTE StarShip;
|
BYTE StarShip;
|
||||||
|
|
||||||
StarShip = pMS->TeamImage[i].ShipList[index];
|
StarShip = pMS->SideState[i].TeamImage.ShipList[index];
|
||||||
if (StarShip == MELEE_NONE)
|
if (StarShip == MELEE_NONE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -2174,7 +2194,8 @@ StartMelee (MELEE_STATE *pMS)
|
|||||||
static void
|
static void
|
||||||
StartMeleeButtonPressed (MELEE_STATE *pMS)
|
StartMeleeButtonPressed (MELEE_STATE *pMS)
|
||||||
{
|
{
|
||||||
if (pMS->star_bucks[0] == 0 || pMS->star_bucks[1] == 0)
|
if (pMS->SideState[0].star_bucks == 0 ||
|
||||||
|
pMS->SideState[1].star_bucks == 0)
|
||||||
{
|
{
|
||||||
PlayMenuSound (MENU_SOUND_FAILURE);
|
PlayMenuSound (MENU_SOUND_FAILURE);
|
||||||
return;
|
return;
|
||||||
@@ -2184,7 +2205,7 @@ StartMeleeButtonPressed (MELEE_STATE *pMS)
|
|||||||
if ((PlayerControl[0] & NETWORK_CONTROL) &&
|
if ((PlayerControl[0] & NETWORK_CONTROL) &&
|
||||||
(PlayerControl[1] & NETWORK_CONTROL))
|
(PlayerControl[1] & NETWORK_CONTROL))
|
||||||
{
|
{
|
||||||
DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 31));
|
DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 32));
|
||||||
// "Only one side at a time can be network controlled."
|
// "Only one side at a time can be network controlled."
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2194,7 +2215,7 @@ StartMeleeButtonPressed (MELEE_STATE *pMS)
|
|||||||
((PlayerControl[0] & COMPUTER_CONTROL) &&
|
((PlayerControl[0] & COMPUTER_CONTROL) &&
|
||||||
(PlayerControl[1] & NETWORK_CONTROL)))
|
(PlayerControl[1] & NETWORK_CONTROL)))
|
||||||
{
|
{
|
||||||
DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 32));
|
DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 33));
|
||||||
// "Netplay with a computer-controlled side is currently
|
// "Netplay with a computer-controlled side is currently
|
||||||
// not possible."
|
// not possible."
|
||||||
return;
|
return;
|
||||||
@@ -2304,10 +2325,12 @@ DoConnectingDialog (MELEE_STATE *pMS)
|
|||||||
if (NetConnection_getPeerOptions (conn)->isServer)
|
if (NetConnection_getPeerOptions (conn)->isServer)
|
||||||
{
|
{
|
||||||
t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 1);
|
t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 1);
|
||||||
|
/* "Awaiting incoming connection */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 2);
|
t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 2);
|
||||||
|
/* "Awaiting outgoing connection */
|
||||||
}
|
}
|
||||||
t.baseline.y = r.corner.y + 10;
|
t.baseline.y = r.corner.y + 10;
|
||||||
t.baseline.x = SCREEN_WIDTH >> 1;
|
t.baseline.x = SCREEN_WIDTH >> 1;
|
||||||
@@ -2316,7 +2339,7 @@ DoConnectingDialog (MELEE_STATE *pMS)
|
|||||||
font_DrawText (&t);
|
font_DrawText (&t);
|
||||||
|
|
||||||
t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 18);
|
t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 18);
|
||||||
/* "Press SPACE to cancel" */
|
/* "Press SPACE to cancel" */
|
||||||
t.baseline.y += 16;
|
t.baseline.y += 16;
|
||||||
font_DrawText (&t);
|
font_DrawText (&t);
|
||||||
|
|
||||||
@@ -2547,7 +2570,7 @@ DoMelee (MELEE_STATE *pMS)
|
|||||||
case SAVE_TOP:
|
case SAVE_TOP:
|
||||||
case SAVE_BOT:
|
case SAVE_BOT:
|
||||||
pMS->side = pMS->MeleeOption == SAVE_TOP ? 0 : 1;
|
pMS->side = pMS->MeleeOption == SAVE_TOP ? 0 : 1;
|
||||||
if (pMS->star_bucks[pMS->side])
|
if (pMS->SideState[pMS->side].star_bucks)
|
||||||
DoSaveTeam (pMS);
|
DoSaveTeam (pMS);
|
||||||
else
|
else
|
||||||
PlayMenuSound (MENU_SOUND_FAILURE);
|
PlayMenuSound (MENU_SOUND_FAILURE);
|
||||||
@@ -2580,8 +2603,9 @@ DoMelee (MELEE_STATE *pMS)
|
|||||||
{
|
{
|
||||||
if (!pMS->flash_task)
|
if (!pMS->flash_task)
|
||||||
{
|
{
|
||||||
pMS->flash_task = AssignTask (flash_selection_func, 2048,
|
pMS->flash_task = AssignTask (
|
||||||
"flash melee selection");
|
flash_selection_func, 2048,
|
||||||
|
"flash melee selection");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2912,40 +2936,32 @@ LoadMeleeConfig (MELEE_STATE *pMS)
|
|||||||
{
|
{
|
||||||
uio_Stream *load_fp;
|
uio_Stream *load_fp;
|
||||||
int status;
|
int status;
|
||||||
|
COUNT side;
|
||||||
|
|
||||||
load_fp = res_OpenResFile (configDir, "melee.cfg", "rb");
|
load_fp = res_OpenResFile (configDir, "melee.cfg", "rb");
|
||||||
if (!load_fp)
|
if (!load_fp)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (LengthResFile (load_fp) != (1 + sizeof (TEAM_IMAGE)) * 2)
|
if (LengthResFile (load_fp) != (1 + sizeof (TEAM_IMAGE)) * NUM_SIDES)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
status = GetResFileChar (load_fp);
|
for (side = 0; side < NUM_SIDES; side++)
|
||||||
if (status == -1)
|
{
|
||||||
goto err;
|
status = GetResFileChar (load_fp);
|
||||||
PlayerControl[0] = (BYTE)status;
|
if (status == -1)
|
||||||
|
goto err;
|
||||||
|
PlayerControl[side] = (BYTE)status;
|
||||||
|
|
||||||
status = ReadTeamImage (&pMS->TeamImage[0], load_fp);
|
status = ReadTeamImage (&pMS->SideState[side].TeamImage, load_fp);
|
||||||
if (status == -1)
|
if (status == -1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
status = GetResFileChar (load_fp);
|
/* Do not allow netplay mode at the start. */
|
||||||
if (status == -1)
|
if (PlayerControl[side] & NETWORK_CONTROL)
|
||||||
goto err;
|
PlayerControl[side] = HUMAN_CONTROL | STANDARD_RATING;
|
||||||
PlayerControl[1] = (BYTE)status;
|
}
|
||||||
|
|
||||||
status = ReadTeamImage (&pMS->TeamImage[1], load_fp);
|
|
||||||
if (status == -1)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
res_CloseResFile (load_fp);
|
res_CloseResFile (load_fp);
|
||||||
|
|
||||||
/* Do not allow netplay mode at the start. */
|
|
||||||
if (PlayerControl[0] & NETWORK_CONTROL)
|
|
||||||
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
|
|
||||||
if (PlayerControl[1] & NETWORK_CONTROL)
|
|
||||||
PlayerControl[1] = HUMAN_CONTROL | STANDARD_RATING;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -2958,22 +2974,20 @@ int
|
|||||||
WriteMeleeConfig (MELEE_STATE *pMS)
|
WriteMeleeConfig (MELEE_STATE *pMS)
|
||||||
{
|
{
|
||||||
uio_Stream *save_fp;
|
uio_Stream *save_fp;
|
||||||
|
COUNT side;
|
||||||
|
|
||||||
save_fp = res_OpenResFile (configDir, "melee.cfg", "wb");
|
save_fp = res_OpenResFile (configDir, "melee.cfg", "wb");
|
||||||
if (!save_fp)
|
if (!save_fp)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (PutResFileChar (PlayerControl[0], save_fp) == -1)
|
for (side = 0; side < NUM_SIDES; side++)
|
||||||
goto err;
|
{
|
||||||
|
if (PutResFileChar (PlayerControl[side], save_fp) == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (WriteTeamImage (&pMS->TeamImage[0], save_fp) == 0)
|
if (WriteTeamImage (&pMS->SideState[side].TeamImage, save_fp) == 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
if (PutResFileChar (PlayerControl[1], save_fp) == -1)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (WriteTeamImage (&pMS->TeamImage[1], save_fp) == 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (!res_CloseResFile (save_fp))
|
if (!res_CloseResFile (save_fp))
|
||||||
goto err;
|
goto err;
|
||||||
@@ -3002,6 +3016,12 @@ Melee (void)
|
|||||||
MenuState.InputFunc = DoMelee;
|
MenuState.InputFunc = DoMelee;
|
||||||
MenuState.Initialized = FALSE;
|
MenuState.Initialized = FALSE;
|
||||||
|
|
||||||
|
MenuState.randomContext = RandomContext_New ();
|
||||||
|
RandomContext_SeedRandom (MenuState.randomContext,
|
||||||
|
GetTimeCounter ());
|
||||||
|
// Using the current time still leave the random state a bit
|
||||||
|
// predictable, but it is good enough.
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
{
|
{
|
||||||
COUNT player;
|
COUNT player;
|
||||||
@@ -3020,9 +3040,9 @@ Melee (void)
|
|||||||
if (LoadMeleeConfig (&MenuState) == -1)
|
if (LoadMeleeConfig (&MenuState) == -1)
|
||||||
{
|
{
|
||||||
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
|
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
|
||||||
MenuState.TeamImage[0] = MenuState.PreBuiltList[0];
|
MenuState.SideState[0].TeamImage = MenuState.PreBuiltList[0];
|
||||||
PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING;
|
PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING;
|
||||||
MenuState.TeamImage[1] = MenuState.PreBuiltList[1];
|
MenuState.SideState[1].TeamImage = MenuState.PreBuiltList[1];
|
||||||
}
|
}
|
||||||
SetPlayerInput ();
|
SetPlayerInput ();
|
||||||
teamStringChanged (&MenuState, 0);
|
teamStringChanged (&MenuState, 0);
|
||||||
@@ -3031,8 +3051,10 @@ Melee (void)
|
|||||||
entireFleetChanged (&MenuState, 1);
|
entireFleetChanged (&MenuState, 1);
|
||||||
|
|
||||||
MenuState.side = 0;
|
MenuState.side = 0;
|
||||||
MenuState.star_bucks[0] = GetTeamValue (&MenuState.TeamImage[0]);
|
MenuState.SideState[0].star_bucks =
|
||||||
MenuState.star_bucks[1] = GetTeamValue (&MenuState.TeamImage[1]);
|
GetTeamValue (&MenuState.SideState[0].TeamImage);
|
||||||
|
MenuState.SideState[1].star_bucks =
|
||||||
|
GetTeamValue (&MenuState.SideState[0].TeamImage);
|
||||||
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
|
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
|
||||||
DoInput (&MenuState, TRUE);
|
DoInput (&MenuState, TRUE);
|
||||||
|
|
||||||
@@ -3047,6 +3069,8 @@ Melee (void)
|
|||||||
DestroyDrawable (ReleaseDrawable (PickMeleeFrame));
|
DestroyDrawable (ReleaseDrawable (PickMeleeFrame));
|
||||||
PickMeleeFrame = 0;
|
PickMeleeFrame = 0;
|
||||||
|
|
||||||
|
RandomContext_Delete (MenuState.randomContext);
|
||||||
|
|
||||||
FlushInput ();
|
FlushInput ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3060,7 +3084,7 @@ teamStringChanged (MELEE_STATE *pMS, int player)
|
|||||||
size_t len;
|
size_t len;
|
||||||
size_t playerI;
|
size_t playerI;
|
||||||
|
|
||||||
name = pMS->TeamImage[player].TeamName;
|
name = pMS->SideState[player].TeamImage.TeamName;
|
||||||
len = strlen (name);
|
len = strlen (name);
|
||||||
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
{
|
{
|
||||||
@@ -3102,7 +3126,7 @@ entireFleetChanged (MELEE_STATE *pMS, int player)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Netplay_entireFleetChanged (conn, player,
|
Netplay_entireFleetChanged (conn, player,
|
||||||
pMS->TeamImage[player].ShipList, MELEE_FLEET_SIZE);
|
pMS->SideState[player].TeamImage.ShipList, MELEE_FLEET_SIZE);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void) player;
|
(void) player;
|
||||||
@@ -3130,7 +3154,7 @@ fleetShipChanged (MELEE_STATE *pMS, int player, size_t index)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Netplay_fleetShipChanged (conn, player, index,
|
Netplay_fleetShipChanged (conn, player, index,
|
||||||
pMS->TeamImage[player].ShipList[index]);
|
pMS->SideState[player].TeamImage.ShipList[index]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void) player;
|
(void) player;
|
||||||
@@ -3152,8 +3176,8 @@ updateTeamName (MELEE_STATE *pMS, COUNT side, const char *name,
|
|||||||
len = MAX_TEAM_CHARS;
|
len = MAX_TEAM_CHARS;
|
||||||
|
|
||||||
// TeamName has space for at least MAX_TEAM_CHARS + 1 bytes.
|
// TeamName has space for at least MAX_TEAM_CHARS + 1 bytes.
|
||||||
strncpy (pMS->TeamImage[side].TeamName, name, len);
|
strncpy (pMS->SideState[side].TeamImage.TeamName, name, len);
|
||||||
pMS->TeamImage[side].TeamName[len] = '\0';
|
pMS->SideState[side].TeamImage.TeamName[len] = '\0';
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
#if 0 /* DTSHS_REPAIR does not combine with other options */
|
#if 0 /* DTSHS_REPAIR does not combine with other options */
|
||||||
@@ -3178,14 +3202,14 @@ updateFleetShip (MELEE_STATE *pMS, COUNT side, COUNT index, BYTE ship)
|
|||||||
BOOLEAN isSelected;
|
BOOLEAN isSelected;
|
||||||
|
|
||||||
if (ship >= NUM_MELEE_SHIPS && ship != MELEE_NONE) {
|
if (ship >= NUM_MELEE_SHIPS && ship != MELEE_NONE) {
|
||||||
fprintf (stderr, "Invalid ship type number %d (max = %d).\n",
|
log_add (log_Warning, "Invalid ship type number %d (max = %d).\n",
|
||||||
ship, NUM_MELEE_SHIPS - 1);
|
ship, NUM_MELEE_SHIPS - 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index >= MELEE_FLEET_SIZE)
|
if (index >= MELEE_FLEET_SIZE)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Invalid ship position number %d (max = %d).\n",
|
log_add (log_Warning, "Invalid ship position number %d (max = %d).\n",
|
||||||
index, MELEE_FLEET_SIZE - 1);
|
index, MELEE_FLEET_SIZE - 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3194,11 +3218,11 @@ updateFleetShip (MELEE_STATE *pMS, COUNT side, COUNT index, BYTE ship)
|
|||||||
if (val == (COUNT) ~0)
|
if (val == (COUNT) ~0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pMS->star_bucks[side] -=
|
pMS->SideState[side].star_bucks -=
|
||||||
GetShipValue (pMS->TeamImage[side].ShipList[index]);
|
GetShipValue (pMS->SideState[side].TeamImage.ShipList[index]);
|
||||||
pMS->star_bucks[side] += val;
|
pMS->SideState[side].star_bucks += val;
|
||||||
|
|
||||||
pMS->TeamImage[side].ShipList[index] = ship;
|
pMS->SideState[side].TeamImage.ShipList[index] = ship;
|
||||||
|
|
||||||
selectedShipIndex = GetShipIndex (pMS->row, pMS->col);
|
selectedShipIndex = GetShipIndex (pMS->row, pMS->col);
|
||||||
isSelected = (pMS->MeleeOption == EDIT_MELEE) &&
|
isSelected = (pMS->MeleeOption == EDIT_MELEE) &&
|
||||||
@@ -3285,7 +3309,7 @@ connectedFeedback (NetConnection *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
abortReasonString (NetplayResetReason reason)
|
abortReasonString (NetplayAbortReason reason)
|
||||||
{
|
{
|
||||||
switch (reason)
|
switch (reason)
|
||||||
{
|
{
|
||||||
@@ -3295,8 +3319,12 @@ abortReasonString (NetplayResetReason reason)
|
|||||||
case AbortReason_versionMismatch:
|
case AbortReason_versionMismatch:
|
||||||
return GAME_STRING (NETMELEE_STRING_BASE + 26);
|
return GAME_STRING (NETMELEE_STRING_BASE + 26);
|
||||||
// "Connection aborted due to version mismatch."
|
// "Connection aborted due to version mismatch."
|
||||||
case AbortReason_protocolError:
|
case AbortReason_invalidHash:
|
||||||
return GAME_STRING (NETMELEE_STRING_BASE + 27);
|
return GAME_STRING (NETMELEE_STRING_BASE + 27);
|
||||||
|
// "Connection aborted because the remote side sent a "
|
||||||
|
// "fake signature."
|
||||||
|
case AbortReason_protocolError:
|
||||||
|
return GAME_STRING (NETMELEE_STRING_BASE + 28);
|
||||||
// "Connection aborted due to an internal protocol "
|
// "Connection aborted due to an internal protocol "
|
||||||
// "error."
|
// "error."
|
||||||
}
|
}
|
||||||
@@ -3321,13 +3349,13 @@ resetReasonString (NetplayResetReason reason)
|
|||||||
switch (reason)
|
switch (reason)
|
||||||
{
|
{
|
||||||
case ResetReason_unspecified:
|
case ResetReason_unspecified:
|
||||||
return GAME_STRING (NETMELEE_STRING_BASE + 28);
|
return GAME_STRING (NETMELEE_STRING_BASE + 29);
|
||||||
// "Game aborted for an unspecified reason."
|
// "Game aborted for an unspecified reason."
|
||||||
case ResetReason_syncLoss:
|
case ResetReason_syncLoss:
|
||||||
return GAME_STRING (NETMELEE_STRING_BASE + 29);
|
return GAME_STRING (NETMELEE_STRING_BASE + 30);
|
||||||
// "Game aborted due to loss of synchronisation."
|
// "Game aborted due to loss of synchronisation."
|
||||||
case ResetReason_manualReset:
|
case ResetReason_manualReset:
|
||||||
return GAME_STRING (NETMELEE_STRING_BASE + 30);
|
return GAME_STRING (NETMELEE_STRING_BASE + 31);
|
||||||
// "Game aborted by the remote player."
|
// "Game aborted by the remote player."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-3
@@ -22,6 +22,7 @@
|
|||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "libs/tasklib.h"
|
#include "libs/tasklib.h"
|
||||||
#include "libs/gfxlib.h"
|
#include "libs/gfxlib.h"
|
||||||
|
#include "libs/mathlib.h"
|
||||||
#include "libs/sndlib.h"
|
#include "libs/sndlib.h"
|
||||||
#include "libs/reslib.h"
|
#include "libs/reslib.h"
|
||||||
#include "netplay/packet.h"
|
#include "netplay/packet.h"
|
||||||
@@ -71,7 +72,10 @@ enum
|
|||||||
|
|
||||||
extern FRAME PickMeleeFrame;
|
extern FRAME PickMeleeFrame;
|
||||||
|
|
||||||
#define PICK_BG_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x0F), 0x01)
|
#define PICK_BG_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x0F), 0x01)
|
||||||
|
#define PICK_VALUE_COLOR BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C)
|
||||||
|
// Used for the current fleet value in the next ship selection
|
||||||
|
// in SuperMelee.
|
||||||
|
|
||||||
#define MAX_TEAM_CHARS 30
|
#define MAX_TEAM_CHARS 30
|
||||||
#define MAX_VIS_TEAMS 5
|
#define MAX_VIS_TEAMS 5
|
||||||
@@ -90,6 +94,12 @@ typedef struct
|
|||||||
* default name in starcon.txt is unknowingly mangled. */
|
* default name in starcon.txt is unknowingly mangled. */
|
||||||
} TEAM_IMAGE;
|
} TEAM_IMAGE;
|
||||||
|
|
||||||
|
struct melee_side_state
|
||||||
|
{
|
||||||
|
TEAM_IMAGE TeamImage;
|
||||||
|
COUNT star_bucks;
|
||||||
|
};
|
||||||
|
|
||||||
struct melee_state
|
struct melee_state
|
||||||
{
|
{
|
||||||
BOOLEAN (*InputFunc) (struct melee_state *pInputState);
|
BOOLEAN (*InputFunc) (struct melee_state *pInputState);
|
||||||
@@ -100,12 +110,14 @@ struct melee_state
|
|||||||
DIRENTRY TeamDE;
|
DIRENTRY TeamDE;
|
||||||
COUNT TopTeamIndex, BotTeamIndex;
|
COUNT TopTeamIndex, BotTeamIndex;
|
||||||
COUNT side, row, col;
|
COUNT side, row, col;
|
||||||
TEAM_IMAGE TeamImage[NUM_SIDES];
|
struct melee_side_state SideState[NUM_SIDES];
|
||||||
COUNT star_bucks[NUM_SIDES];
|
|
||||||
COUNT CurIndex;
|
COUNT CurIndex;
|
||||||
Task flash_task;
|
Task flash_task;
|
||||||
TEAM_IMAGE FileList[MAX_VIS_TEAMS];
|
TEAM_IMAGE FileList[MAX_VIS_TEAMS];
|
||||||
TEAM_IMAGE PreBuiltList[NUM_PREBUILT];
|
TEAM_IMAGE PreBuiltList[NUM_PREBUILT];
|
||||||
|
RandomContext *randomContext;
|
||||||
|
/* RNG state for all local random decisions, i.e. those
|
||||||
|
* decisions that are not shared among network parties. */
|
||||||
|
|
||||||
MUSIC_REF hMusic;
|
MUSIC_REF hMusic;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ static inline bool
|
|||||||
readyFlagsMeaningful(NetState state) {
|
readyFlagsMeaningful(NetState state) {
|
||||||
return state == NetState_init ||
|
return state == NetState_init ||
|
||||||
state == NetState_preBattle ||
|
state == NetState_preBattle ||
|
||||||
|
state == NetState_selectShip ||
|
||||||
state == NetState_interBattle ||
|
state == NetState_interBattle ||
|
||||||
state == NetState_inBattle ||
|
state == NetState_inBattle ||
|
||||||
state == NetState_endingBattle ||
|
state == NetState_endingBattle ||
|
||||||
|
|||||||
+476
-258
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "build.h"
|
#include "build.h"
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "intel.h"
|
#include "intel.h"
|
||||||
#include "melee.h"
|
#include "melee.h"
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "sounds.h"
|
#include "sounds.h"
|
||||||
#include "libs/inplib.h"
|
#include "libs/inplib.h"
|
||||||
|
#include "libs/log.h"
|
||||||
#include "libs/mathlib.h"
|
#include "libs/mathlib.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -44,13 +46,27 @@ struct getmelee_struct {
|
|||||||
BOOLEAN (*InputFunc) (struct getmelee_struct *pInputState);
|
BOOLEAN (*InputFunc) (struct getmelee_struct *pInputState);
|
||||||
COUNT MenuRepeatDelay;
|
COUNT MenuRepeatDelay;
|
||||||
BOOLEAN Initialized;
|
BOOLEAN Initialized;
|
||||||
HSTARSHIP hBattleShip;
|
|
||||||
COUNT row, col, ships_left, which_player;
|
struct {
|
||||||
COUNT randomIndex;
|
TimeCount timeIn;
|
||||||
|
HSTARSHIP hBattleShip;
|
||||||
|
// Chosen ship.
|
||||||
|
COUNT row;
|
||||||
|
COUNT col;
|
||||||
|
COUNT ships_left;
|
||||||
|
// Number of ships still available.
|
||||||
|
COUNT randomIndex;
|
||||||
|
// Pre-generated random number.
|
||||||
|
BOOLEAN selecting;
|
||||||
|
// Is this player selecting a ship?
|
||||||
|
BOOLEAN done;
|
||||||
|
// Has a selection been made for this player?
|
||||||
|
FlashContext *flashContext;
|
||||||
|
// Context for controlling the flash rectangle.
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
BOOLEAN remoteSelected;
|
BOOLEAN remoteSelected;
|
||||||
#endif
|
#endif
|
||||||
RECT flash_rect;
|
} player[NUM_PLAYERS];
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
@@ -117,59 +133,34 @@ queueIndexFromShip (HSTARSHIP hShip)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Pre: called does not hold the graphics lock
|
||||||
static void
|
static void
|
||||||
PickMelee_ChangedSelection (GETMELEE_STATE *gms)
|
PickMelee_ChangedSelection (GETMELEE_STATE *gms, COUNT playerI)
|
||||||
{
|
{
|
||||||
LockMutex (GraphicsLock);
|
RECT r;
|
||||||
gms->flash_rect.corner.x = PICK_X_OFFS + ((ICON_WIDTH + 2) * gms->col);
|
r.corner.x = PICK_X_OFFS + ((ICON_WIDTH + 2) * gms->player[playerI].col);
|
||||||
gms->flash_rect.corner.y = PICK_Y_OFFS + ((ICON_HEIGHT + 2) * gms->row)
|
r.corner.y = PICK_Y_OFFS + ((ICON_HEIGHT + 2) * gms->player[playerI].row)
|
||||||
+ ((1 - gms->which_player) * PICK_SIDE_OFFS);
|
+ ((1 - playerI) * PICK_SIDE_OFFS);
|
||||||
SetFlashRect (&gms->flash_rect, (FRAME)0);
|
r.extent.width = (ICON_WIDTH + 2);
|
||||||
UnlockMutex (GraphicsLock);
|
r.extent.height = (ICON_HEIGHT + 2);
|
||||||
|
Flash_setRect (gms->player[playerI].flashContext, &r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select a new ship from the fleet for battle.
|
// Auxiliary function to DoGetMelee for a single player
|
||||||
// Returns 'TRUE' if no choice has been made yet; this function is to be
|
// Returns FALSE if the player selected abort.
|
||||||
// called again later.
|
|
||||||
// Returns 'FALSE' if a choice has been made. gms->hStarShip is set
|
|
||||||
// to the chosen (or randomly selected) ship, or to 0 if 'exit' has
|
|
||||||
// been chosen.
|
|
||||||
/* TODO: Include player timeouts */
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
DoGetMelee (GETMELEE_STATE *gms)
|
DoGetMeleePlayer (GETMELEE_STATE *gms, COUNT which_player)
|
||||||
{
|
{
|
||||||
BOOLEAN left, right, up, down, select;
|
BOOLEAN left, right, up, down, select;
|
||||||
COUNT which_player = gms->which_player;
|
|
||||||
BOOLEAN done = FALSE;
|
|
||||||
|
|
||||||
SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
|
|
||||||
|
|
||||||
if (!gms->Initialized)
|
|
||||||
{
|
|
||||||
gms->Initialized = TRUE;
|
|
||||||
gms->row = 0;
|
|
||||||
gms->col = NUM_MELEE_COLS_ORIG;
|
|
||||||
|
|
||||||
PickMelee_ChangedSelection (gms);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SleepThread (ONE_SECOND / 120);
|
|
||||||
#ifdef NETPLAY
|
|
||||||
netInput ();
|
|
||||||
|
|
||||||
if (!allConnected())
|
|
||||||
goto aborted;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
|
||||||
goto aborted;
|
|
||||||
|
|
||||||
if (PlayerInput[which_player] == ComputerInput)
|
if (PlayerInput[which_player] == ComputerInput)
|
||||||
{
|
{
|
||||||
/* TODO: Make this a frame-by-frame thing. This code is currently
|
#define COMPUTER_SELECTION_DELAY (ONE_SECOND >> 1)
|
||||||
* copied from intel.c's computer_intelligence */
|
TimeCount now = GetTimeCounter ();
|
||||||
SleepThread (ONE_SECOND >> 1);
|
if (now < gms->player[which_player].timeIn +
|
||||||
|
COMPUTER_SELECTION_DELAY)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
left = right = up = down = FALSE;
|
left = right = up = down = FALSE;
|
||||||
select = TRUE;
|
select = TRUE;
|
||||||
}
|
}
|
||||||
@@ -177,8 +168,10 @@ DoGetMelee (GETMELEE_STATE *gms)
|
|||||||
else if (PlayerInput[which_player] == NetworkInput)
|
else if (PlayerInput[which_player] == NetworkInput)
|
||||||
{
|
{
|
||||||
flushPacketQueues ();
|
flushPacketQueues ();
|
||||||
if (gms->remoteSelected)
|
// Sets gms->player[which_player].remoteSelected if input
|
||||||
return FALSE;
|
// is received.
|
||||||
|
if (gms->player[which_player].remoteSelected)
|
||||||
|
gms->player[which_player].done = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -200,39 +193,47 @@ DoGetMelee (GETMELEE_STATE *gms)
|
|||||||
|
|
||||||
if (select)
|
if (select)
|
||||||
{
|
{
|
||||||
if (gms->col == NUM_MELEE_COLS_ORIG)
|
if (gms->player[which_player].col == NUM_MELEE_COLS_ORIG)
|
||||||
{
|
{
|
||||||
if (gms->row == 0)
|
// Selection is on a non-ship slot. (Random or exit).
|
||||||
|
if (gms->player[which_player].row == 0)
|
||||||
{
|
{
|
||||||
// Random ship
|
// Random ship
|
||||||
gms->hBattleShip = MeleeShipByUsedIndex (
|
gms->player[which_player].hBattleShip =
|
||||||
&race_q[which_player], gms->randomIndex);
|
MeleeShipByUsedIndex (&race_q[which_player],
|
||||||
|
gms->player[which_player].randomIndex);
|
||||||
|
PlayMenuSound (MENU_SOUND_SUCCESS);
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
reportShipSelected (gms, (COUNT)~0);
|
reportShipSelected (gms, (COUNT)~0);
|
||||||
#endif
|
#endif
|
||||||
done = TRUE;
|
gms->player[which_player].done = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Selected exit
|
// Selected exit
|
||||||
if (ConfirmExit ())
|
if (ConfirmExit ())
|
||||||
goto aborted;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Selection is on a ship slot.
|
||||||
COUNT ship_index;
|
COUNT ship_index;
|
||||||
|
HSTARSHIP ship;
|
||||||
|
|
||||||
ship_index = (gms->row * NUM_MELEE_COLS_ORIG) + gms->col;
|
ship_index = (gms->player[which_player].row * NUM_MELEE_COLS_ORIG)
|
||||||
gms->hBattleShip = MeleeShipByQueueIndex (
|
+ gms->player[which_player].col;
|
||||||
&race_q[which_player], ship_index);
|
ship = MeleeShipByQueueIndex (&race_q[which_player], ship_index);
|
||||||
if (gms->hBattleShip != 0)
|
if (ship != 0)
|
||||||
{
|
{
|
||||||
// Selection contains a ship.
|
// Selection contains a ship.
|
||||||
|
gms->player[which_player].hBattleShip = ship;
|
||||||
|
gms->player[which_player].done = true;
|
||||||
|
PlayMenuSound (MENU_SOUND_SUCCESS);
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
reportShipSelected (gms, ship_index);
|
reportShipSelected (gms, ship_index);
|
||||||
#endif
|
#endif
|
||||||
done = TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,8 +242,8 @@ DoGetMelee (GETMELEE_STATE *gms)
|
|||||||
// Process motion commands.
|
// Process motion commands.
|
||||||
COUNT new_row, new_col;
|
COUNT new_row, new_col;
|
||||||
|
|
||||||
new_row = gms->row;
|
new_row = gms->player[which_player].row;
|
||||||
new_col = gms->col;
|
new_col = gms->player[which_player].col;
|
||||||
if (left)
|
if (left)
|
||||||
{
|
{
|
||||||
if (new_col-- == 0)
|
if (new_col-- == 0)
|
||||||
@@ -264,27 +265,93 @@ DoGetMelee (GETMELEE_STATE *gms)
|
|||||||
new_row = 0;
|
new_row = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_row != gms->row || new_col != gms->col)
|
if (new_row != gms->player[which_player].row ||
|
||||||
|
new_col != gms->player[which_player].col)
|
||||||
{
|
{
|
||||||
gms->row = new_row;
|
gms->player[which_player].row = new_row;
|
||||||
gms->col = new_col;
|
gms->player[which_player].col = new_col;
|
||||||
|
|
||||||
PlayMenuSound (MENU_SOUND_MOVE);
|
PlayMenuSound (MENU_SOUND_MOVE);
|
||||||
PickMelee_ChangedSelection (gms);
|
PickMelee_ChangedSelection (gms, which_player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select a new ship from the fleet for battle.
|
||||||
|
// Returns 'TRUE' if no choice has been made yet; this function is to be
|
||||||
|
// called again later.
|
||||||
|
// Returns 'FALSE' if a choice has been made. gms->hStarShip is set
|
||||||
|
// to the chosen (or randomly selected) ship, or to 0 if 'exit' has
|
||||||
|
// been chosen.
|
||||||
|
/* TODO: Include player timeouts */
|
||||||
|
static BOOLEAN
|
||||||
|
DoGetMelee (GETMELEE_STATE *gms)
|
||||||
|
{
|
||||||
|
BOOLEAN done;
|
||||||
|
COUNT playerI;
|
||||||
|
|
||||||
|
SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
|
||||||
|
|
||||||
|
if (!gms->Initialized)
|
||||||
|
{
|
||||||
|
gms->Initialized = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
{
|
||||||
|
if (!gms->player[playerI].selecting)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!gms->player[playerI].done)
|
||||||
|
Flash_process (gms->player[playerI].flashContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
SleepThread (ONE_SECOND / 120);
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
netInput ();
|
||||||
|
|
||||||
|
if (!allConnected ())
|
||||||
|
goto aborted;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
||||||
|
goto aborted;
|
||||||
|
|
||||||
|
done = TRUE;
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
{
|
||||||
|
if (!gms->player[playerI].selecting)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!gms->player[playerI].done) {
|
||||||
|
if (!DoGetMeleePlayer (gms, playerI))
|
||||||
|
goto aborted;
|
||||||
|
|
||||||
|
if (gms->player[playerI].done)
|
||||||
|
{
|
||||||
|
Flash_terminate (gms->player[playerI].flashContext);
|
||||||
|
gms->player[playerI].flashContext = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
done = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
flushPacketQueues ();
|
flushPacketQueues ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return !done;
|
return !done;
|
||||||
|
|
||||||
aborted:
|
aborted:
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
flushPacketQueues ();
|
flushPacketQueues ();
|
||||||
#endif
|
#endif
|
||||||
gms->hBattleShip = 0;
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
gms->player[playerI].hBattleShip = 0;
|
||||||
GLOBAL (CurrentActivity) &= ~CHECK_ABORT;
|
GLOBAL (CurrentActivity) &= ~CHECK_ABORT;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -298,270 +365,422 @@ endMeleeCallback (NetConnection *conn, void *arg)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HSTARSHIP
|
static COUNT
|
||||||
GetMeleeStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
GetRaceQueueValue (const QUEUE *queue) {
|
||||||
|
COUNT result;
|
||||||
|
HSTARSHIP hBattleShip, hNextShip;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (hBattleShip = GetHeadLink (queue);
|
||||||
|
hBattleShip != 0; hBattleShip = hNextShip)
|
||||||
|
{
|
||||||
|
STARSHIP *StarShipPtr = LockStarShip (queue, hBattleShip);
|
||||||
|
hNextShip = _GetSuccLink (StarShipPtr);
|
||||||
|
|
||||||
|
if (StarShipPtr->RaceResIndex == 0)
|
||||||
|
continue; // Not active any more.
|
||||||
|
|
||||||
|
result += StarShipPtr->special_counter;
|
||||||
|
|
||||||
|
UnlockStarShip (queue, hBattleShip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cross out the icon for the dead ship.
|
||||||
|
// 'frame' is the PickMeleeFrame for the player.
|
||||||
|
// 'shipI' is the index in the ship list.
|
||||||
|
// Pre: caller holds the graphics lock.
|
||||||
|
static void
|
||||||
|
CrossOutShip (FRAME frame, COUNT shipI)
|
||||||
{
|
{
|
||||||
COUNT ships_left;
|
CONTEXT OldContext;
|
||||||
|
STAMP s;
|
||||||
|
|
||||||
|
OldContext = SetContext (OffScreenContext);
|
||||||
|
|
||||||
|
SetContextFGFrame (frame);
|
||||||
|
|
||||||
|
s.origin.x = 3 + ((ICON_WIDTH + 2) * (shipI % NUM_MELEE_COLS_ORIG));
|
||||||
|
s.origin.y = 9 + ((ICON_HEIGHT + 2) * (shipI / NUM_MELEE_COLS_ORIG));
|
||||||
|
s.frame = SetAbsFrameIndex (StatusFrame, 3);
|
||||||
|
// Cross for through the ship image.
|
||||||
|
DrawStamp (&s);
|
||||||
|
|
||||||
|
SetContext (OldContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the value of the fleet in the top right of the PickMeleeFrame.
|
||||||
|
// Pre: caller holds the graphics lock.
|
||||||
|
static void
|
||||||
|
UpdatePickMeleeFleetValue (FRAME frame, COUNT which_player)
|
||||||
|
{
|
||||||
|
CONTEXT OldContext;
|
||||||
|
COUNT value;
|
||||||
|
RECT r;
|
||||||
TEXT t;
|
TEXT t;
|
||||||
UNICODE buf[40];
|
UNICODE buf[40];
|
||||||
STAMP s;
|
|
||||||
CONTEXT OldContext;
|
|
||||||
GETMELEE_STATE gmstate;
|
|
||||||
STARSHIP *StarShipPtr;
|
|
||||||
BOOLEAN firstTime;
|
|
||||||
|
|
||||||
if (!(GLOBAL (CurrentActivity) & IN_BATTLE))
|
value = GetRaceQueueValue (&race_q[which_player]);
|
||||||
return (0);
|
|
||||||
|
OldContext = SetContext (OffScreenContext);
|
||||||
|
SetContextFGFrame (frame);
|
||||||
|
|
||||||
|
// Erase the old value text.
|
||||||
|
GetFrameRect (frame, &r);
|
||||||
|
r.extent.width -= 4;
|
||||||
|
t.baseline.x = r.extent.width;
|
||||||
|
r.corner.x = r.extent.width - (6 * 3);
|
||||||
|
r.corner.y = 2;
|
||||||
|
r.extent.width = (6 * 3);
|
||||||
|
r.extent.height = 7 - 2;
|
||||||
|
SetContextForeGroundColor (PICK_BG_COLOR);
|
||||||
|
DrawFilledRectangle (&r);
|
||||||
|
|
||||||
|
// Draw the new value text.
|
||||||
|
sprintf (buf, "%d", value);
|
||||||
|
t.baseline.y = 7;
|
||||||
|
t.align = ALIGN_RIGHT;
|
||||||
|
t.pStr = buf;
|
||||||
|
t.CharCount = (COUNT)~0;
|
||||||
|
SetContextFont (TinyFont);
|
||||||
|
SetContextForeGroundColor (PICK_VALUE_COLOR);
|
||||||
|
font_DrawText (&t);
|
||||||
|
|
||||||
|
SetContext (OldContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre: caller holds the graphics lock.
|
||||||
|
static void
|
||||||
|
DrawPickMeleeFrame (COUNT which_player)
|
||||||
|
{
|
||||||
|
CONTEXT oldContext;
|
||||||
|
STAMP s;
|
||||||
|
|
||||||
|
oldContext = SetContext (SpaceContext);
|
||||||
|
s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player);
|
||||||
|
s.origin.x = PICK_X_OFFS - 3;
|
||||||
|
s.origin.y = PICK_Y_OFFS - 9 + ((1 - which_player) * PICK_SIDE_OFFS);
|
||||||
|
DrawStamp (&s);
|
||||||
|
// Draw the selection box to screen.
|
||||||
|
|
||||||
|
SetContext (oldContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre: caller holds the graphics lock.
|
||||||
|
static void
|
||||||
|
MeleeGameOver (void)
|
||||||
|
{
|
||||||
|
COUNT playerI;
|
||||||
|
DWORD TimeOut;
|
||||||
|
BOOLEAN PressState, ButtonState;
|
||||||
|
|
||||||
|
// Show the battle result.
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
DrawPickMeleeFrame (playerI);
|
||||||
|
|
||||||
|
TimeOut = GetTimeCounter () + (ONE_SECOND * 4);
|
||||||
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
|
PressState = PulsedInputState.menu[KEY_MENU_SELECT] ||
|
||||||
|
PulsedInputState.menu[KEY_MENU_CANCEL];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UpdateInputState ();
|
||||||
|
ButtonState = PulsedInputState.menu[KEY_MENU_SELECT] ||
|
||||||
|
PulsedInputState.menu[KEY_MENU_CANCEL];
|
||||||
|
if (PressState)
|
||||||
|
{
|
||||||
|
PressState = ButtonState;
|
||||||
|
ButtonState = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskSwitch ();
|
||||||
|
} while (!(GLOBAL (CurrentActivity) & CHECK_ABORT) && (!ButtonState
|
||||||
|
&& (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL)
|
||||||
|
|| GetTimeCounter () < TimeOut)));
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
|
setStateConnections (NetState_endMelee);
|
||||||
|
localReadyConnections (endMeleeCallback, NULL, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LockMutex (GraphicsLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
MeleeShipDeath (STARSHIP *ship, COUNT which_player) {
|
||||||
|
FRAME frame;
|
||||||
|
|
||||||
|
// Deactivate fleet position.
|
||||||
|
ship->RaceResIndex = 0;
|
||||||
|
|
||||||
|
frame = SetAbsFrameIndex (PickMeleeFrame, which_player);
|
||||||
|
CrossOutShip (frame, ship->ShipFacing);
|
||||||
|
UpdatePickMeleeFleetValue (frame, which_player);
|
||||||
|
|
||||||
|
if (battle_counter[0] == 0 || battle_counter[1] == 0)
|
||||||
{
|
{
|
||||||
NetConnection *conn = netConnections[which_player];
|
// One side is out of ships. Game over.
|
||||||
|
MeleeGameOver ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
|
||||||
|
{
|
||||||
|
COUNT playerI;
|
||||||
|
BOOLEAN ok;
|
||||||
|
GETMELEE_STATE gmstate;
|
||||||
|
TimeCount now;
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
{
|
||||||
|
NetConnection *conn;
|
||||||
|
|
||||||
|
if ((playerMask & (1 << playerI)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// XXX: This does not have to be done per connection.
|
||||||
|
conn = netConnections[playerI];
|
||||||
if (conn != NULL) {
|
if (conn != NULL) {
|
||||||
BattleStateData *battleStateData;
|
BattleStateData *battleStateData;
|
||||||
battleStateData =
|
battleStateData =
|
||||||
(BattleStateData *) NetConnection_getStateData(conn);
|
(BattleStateData *) NetConnection_getStateData (conn);
|
||||||
battleStateData->getMeleeState = &gmstate;
|
battleStateData->getMeleeState = &gmstate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player);
|
ok = true;
|
||||||
|
|
||||||
OldContext = SetContext (OffScreenContext);
|
|
||||||
SetContextFGFrame (s.frame);
|
|
||||||
if (LastStarShipPtr == 0 || LastStarShipPtr->special_counter == 0)
|
|
||||||
{
|
|
||||||
COUNT cur_bucks;
|
|
||||||
HSTARSHIP hBattleShip, hNextShip;
|
|
||||||
|
|
||||||
cur_bucks = 0;
|
|
||||||
for (hBattleShip = GetHeadLink (&race_q[which_player]);
|
|
||||||
hBattleShip != 0; hBattleShip = hNextShip)
|
|
||||||
{
|
|
||||||
StarShipPtr = LockStarShip (&race_q[which_player], hBattleShip);
|
|
||||||
if (StarShipPtr == LastStarShipPtr)
|
|
||||||
{
|
|
||||||
LastStarShipPtr->RaceResIndex = 0;
|
|
||||||
|
|
||||||
gmstate.col = LastStarShipPtr->ShipFacing;
|
|
||||||
s.origin.x = 3
|
|
||||||
+ ((ICON_WIDTH + 2) * (gmstate.col % NUM_MELEE_COLS_ORIG));
|
|
||||||
s.origin.y = 9
|
|
||||||
+ ((ICON_HEIGHT + 2) * (gmstate.col / NUM_MELEE_COLS_ORIG));
|
|
||||||
s.frame = SetAbsFrameIndex (StatusFrame, 3);
|
|
||||||
DrawStamp (&s);
|
|
||||||
s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player);
|
|
||||||
}
|
|
||||||
else if (StarShipPtr->RaceResIndex)
|
|
||||||
{
|
|
||||||
cur_bucks += StarShipPtr->special_counter;
|
|
||||||
}
|
|
||||||
hNextShip = _GetSuccLink (StarShipPtr);
|
|
||||||
UnlockStarShip (&race_q[which_player], hBattleShip);
|
|
||||||
}
|
|
||||||
|
|
||||||
GetFrameRect (s.frame, &gmstate.flash_rect);
|
|
||||||
gmstate.flash_rect.extent.width -= 4;
|
|
||||||
t.baseline.x = gmstate.flash_rect.extent.width;
|
|
||||||
gmstate.flash_rect.corner.x =
|
|
||||||
gmstate.flash_rect.extent.width - (6 * 3);
|
|
||||||
gmstate.flash_rect.corner.y = 2;
|
|
||||||
gmstate.flash_rect.extent.width = (6 * 3);
|
|
||||||
gmstate.flash_rect.extent.height = 7 - 2;
|
|
||||||
SetContextForeGroundColor (PICK_BG_COLOR);
|
|
||||||
DrawFilledRectangle (&gmstate.flash_rect);
|
|
||||||
|
|
||||||
sprintf (buf, "%d", cur_bucks);
|
|
||||||
t.baseline.y = 7;
|
|
||||||
t.align = ALIGN_RIGHT;
|
|
||||||
t.pStr = buf;
|
|
||||||
t.CharCount = (COUNT)~0;
|
|
||||||
SetContextFont (TinyFont);
|
|
||||||
SetContextForeGroundColor (
|
|
||||||
BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C));
|
|
||||||
font_DrawText (&t);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetContext (SpaceContext);
|
|
||||||
|
|
||||||
s.origin.x = PICK_X_OFFS - 3;
|
|
||||||
s.origin.y = PICK_Y_OFFS - 9 + ((1 - which_player) * PICK_SIDE_OFFS);
|
|
||||||
|
|
||||||
DrawStamp (&s);
|
|
||||||
|
|
||||||
if (battle_counter[0] == 0 || battle_counter[1] == 0)
|
|
||||||
{
|
|
||||||
// One side is out of ships. Game over.
|
|
||||||
DWORD TimeOut;
|
|
||||||
BOOLEAN PressState, ButtonState;
|
|
||||||
|
|
||||||
s.origin.y = PICK_Y_OFFS - 9 + (which_player * PICK_SIDE_OFFS);
|
|
||||||
s.frame = SetAbsFrameIndex (PickMeleeFrame,
|
|
||||||
(COUNT) (1 - which_player));
|
|
||||||
DrawStamp (&s);
|
|
||||||
|
|
||||||
TimeOut = GetTimeCounter () + (ONE_SECOND * 4);
|
|
||||||
SetContext (OldContext);
|
|
||||||
UnlockMutex (GraphicsLock);
|
|
||||||
|
|
||||||
PressState = PulsedInputState.menu[KEY_MENU_SELECT] ||
|
|
||||||
PulsedInputState.menu[KEY_MENU_CANCEL];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UpdateInputState ();
|
|
||||||
ButtonState = PulsedInputState.menu[KEY_MENU_SELECT] ||
|
|
||||||
PulsedInputState.menu[KEY_MENU_CANCEL];
|
|
||||||
if (PressState)
|
|
||||||
{
|
|
||||||
PressState = ButtonState;
|
|
||||||
ButtonState = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskSwitch ();
|
|
||||||
} while (!(GLOBAL (CurrentActivity) & CHECK_ABORT) && (!ButtonState
|
|
||||||
&& (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL)
|
|
||||||
|| GetTimeCounter () < TimeOut)));
|
|
||||||
|
|
||||||
#ifdef NETPLAY
|
|
||||||
setStateConnections (NetState_endMelee);
|
|
||||||
localReadyConnections (endMeleeCallback, NULL, true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade in if we're not already faded in.
|
|
||||||
#ifdef NETPLAY
|
|
||||||
// Hack. If one side is network controlled, the top player does not have
|
|
||||||
// to be the first player to get a chance to select his ship,
|
|
||||||
// As what is top locally doesn't have to be the same as what it is
|
|
||||||
// remotely.
|
|
||||||
// This check is not so nice as it replicates the code used to decide
|
|
||||||
// which party is first in selectAllShips.
|
|
||||||
firstTime = (LastStarShipPtr == 0) && ((which_player == 0) ==
|
|
||||||
(((PlayerControl[0] & NETWORK_CONTROL) &&
|
|
||||||
!NetConnection_getDiscriminant(netConnections[0])) ||
|
|
||||||
((PlayerControl[1] & NETWORK_CONTROL) &&
|
|
||||||
NetConnection_getDiscriminant(netConnections[1]))));
|
|
||||||
#else
|
|
||||||
firstTime = LastStarShipPtr == 0 && which_player == 1;
|
|
||||||
#endif
|
|
||||||
if (firstTime)
|
|
||||||
{
|
|
||||||
BYTE fade_buf[] = {FadeAllToColor};
|
|
||||||
|
|
||||||
SleepThreadUntil (XFormColorMap
|
|
||||||
((COLORMAPPTR) fade_buf, ONE_SECOND / 2) + ONE_SECOND / 60);
|
|
||||||
FlushColorXForms ();
|
|
||||||
}
|
|
||||||
|
|
||||||
ships_left = battle_counter[which_player];
|
|
||||||
|
|
||||||
gmstate.flash_rect.extent.width = (ICON_WIDTH + 2);
|
|
||||||
gmstate.flash_rect.extent.height = (ICON_HEIGHT + 2);
|
|
||||||
|
|
||||||
|
now = GetTimeCounter ();
|
||||||
gmstate.InputFunc = DoGetMelee;
|
gmstate.InputFunc = DoGetMelee;
|
||||||
gmstate.Initialized = FALSE;
|
gmstate.Initialized = FALSE;
|
||||||
gmstate.ships_left = ships_left;
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
gmstate.which_player = which_player;
|
|
||||||
// We determine in advance which ship would be chosen if the player
|
|
||||||
// wants a random ship, to keep it simple to keep network parties
|
|
||||||
// synchronised.
|
|
||||||
gmstate.randomIndex = (COUNT)TFB_Random () % ships_left;
|
|
||||||
#ifdef NETPLAY
|
|
||||||
gmstate.remoteSelected = FALSE;
|
|
||||||
{
|
{
|
||||||
// NB. gmstate.randomIndex and gmstate.remoteSelected must be
|
gmstate.player[playerI].selecting =
|
||||||
// initialised before negotiateReadyConnections is completed,
|
(playerMask & (1 << playerI)) != 0;
|
||||||
// to ensure that it is initialised when the SelectShip packet
|
gmstate.player[playerI].ships_left = battle_counter[playerI];
|
||||||
|
|
||||||
|
// We determine in advance which ship would be chosen if the player
|
||||||
|
// wants a random ship, to keep it simple to keep network parties
|
||||||
|
// synchronised.
|
||||||
|
gmstate.player[playerI].randomIndex =
|
||||||
|
(COUNT)TFB_Random () % gmstate.player[playerI].ships_left;
|
||||||
|
gmstate.player[playerI].done = FALSE;
|
||||||
|
|
||||||
|
if (!gmstate.player[playerI].selecting)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gmstate.player[playerI].timeIn = now;
|
||||||
|
gmstate.player[playerI].row = 0;
|
||||||
|
gmstate.player[playerI].col = NUM_MELEE_COLS_ORIG;
|
||||||
|
#ifdef NETPLAY
|
||||||
|
gmstate.player[playerI].remoteSelected = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gmstate.player[playerI].flashContext =
|
||||||
|
Flash_createHighlight (ScreenContext, (FRAME) 0, NULL,
|
||||||
|
2, 3, 2);
|
||||||
|
Flash_setFrameTime (gmstate.player[playerI].flashContext,
|
||||||
|
ONE_SECOND / 16);
|
||||||
|
#ifdef NETPLAY
|
||||||
|
if (PlayerInput[playerI] == NetworkInput)
|
||||||
|
Flash_setSpeed (gmstate.player[playerI].flashContext,
|
||||||
|
ONE_SECOND / 2, 0, ONE_SECOND / 2, 0);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Flash_setSpeed (gmstate.player[playerI].flashContext,
|
||||||
|
0, ONE_SECOND / 16, 0, ONE_SECOND / 16);
|
||||||
|
}
|
||||||
|
PickMelee_ChangedSelection (&gmstate, playerI);
|
||||||
|
Flash_start (gmstate.player[playerI].flashContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
{
|
||||||
|
// NB. gmstate.player[].randomIndex and gmstate.player[].done must
|
||||||
|
// be initialised before negotiateReadyConnections is completed, to
|
||||||
|
// ensure that they are initialised when the SelectShip packet
|
||||||
// arrives.
|
// arrives.
|
||||||
bool allOk = negotiateReadyConnections (true, NetState_selectShip);
|
bool allOk = negotiateReadyConnections (true, NetState_selectShip);
|
||||||
if (!allOk)
|
if (!allOk)
|
||||||
{
|
{
|
||||||
// Some network connection has been reset.
|
// Some network connection has been reset.
|
||||||
gmstate.hBattleShip = 0;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SetDefaultMenuRepeatDelay ();
|
SetDefaultMenuRepeatDelay ();
|
||||||
|
|
||||||
|
SetContext (OffScreenContext);
|
||||||
|
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
ResetKeyRepeat ();
|
ResetKeyRepeat ();
|
||||||
DoInput (&gmstate, FALSE);
|
DoInput (&gmstate, FALSE);
|
||||||
|
WaitForSoundEnd (0);
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
SetFlashRect (NULL, (FRAME)0);
|
|
||||||
|
|
||||||
if (gmstate.hBattleShip == 0)
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
{
|
||||||
|
if (!gmstate.player[playerI].selecting)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (gmstate.player[playerI].done)
|
||||||
|
{
|
||||||
|
// Flash rectangle is already terminated.
|
||||||
|
ships[playerI] = gmstate.player[playerI].hBattleShip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Flash_terminate (gmstate.player[playerI].flashContext);
|
||||||
|
gmstate.player[playerI].flashContext = NULL;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (!negotiateReadyConnections (true, NetState_interBattle))
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
{
|
{
|
||||||
// Aborting.
|
// Aborting.
|
||||||
GLOBAL (CurrentActivity) &= ~IN_BATTLE;
|
GLOBAL (CurrentActivity) &= ~IN_BATTLE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StarShipPtr =
|
STARSHIP *StarShipPtr;
|
||||||
LockStarShip (&race_q[which_player], gmstate.hBattleShip);
|
|
||||||
OwnStarShip (StarShipPtr,
|
|
||||||
1 << which_player, StarShipPtr->captains_name_index);
|
|
||||||
StarShipPtr->captains_name_index = 0;
|
|
||||||
UnlockStarShip (&race_q[which_player], gmstate.hBattleShip);
|
|
||||||
|
|
||||||
PlayMenuSound (MENU_SOUND_SUCCESS);
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
{
|
||||||
|
if (!gmstate.player[playerI].selecting)
|
||||||
|
continue;
|
||||||
|
|
||||||
WaitForSoundEnd (0);
|
StarShipPtr = LockStarShip (&race_q[playerI], ships[playerI]);
|
||||||
|
OwnStarShip (StarShipPtr, 1 << playerI,
|
||||||
|
StarShipPtr->captains_name_index);
|
||||||
|
StarShipPtr->captains_name_index = 0;
|
||||||
|
UnlockStarShip (&race_q[playerI], ships[playerI]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
{
|
{
|
||||||
NetConnection *conn = netConnections[which_player];
|
NetConnection *conn;
|
||||||
if (conn != NULL && NetConnection_isConnected(conn))
|
|
||||||
|
if ((playerMask & (1 << playerI)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// XXX: This does not have to be done per connection.
|
||||||
|
conn = netConnections[playerI];
|
||||||
|
if (conn != NULL && NetConnection_isConnected (conn))
|
||||||
{
|
{
|
||||||
BattleStateData *battleStateData;
|
BattleStateData *battleStateData;
|
||||||
battleStateData = (BattleStateData *)
|
battleStateData =
|
||||||
NetConnection_getStateData(conn);
|
(BattleStateData *) NetConnection_getStateData (conn);
|
||||||
battleStateData->getMeleeState = NULL;
|
battleStateData->getMeleeState = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (gmstate.hBattleShip);
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
GetInitialMeleeStarShips (HSTARSHIP *result)
|
||||||
|
{
|
||||||
|
COUNT playerI;
|
||||||
|
COUNT playerMask;
|
||||||
|
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
{
|
||||||
|
FRAME frame;
|
||||||
|
frame = SetAbsFrameIndex (PickMeleeFrame, playerI);
|
||||||
|
UpdatePickMeleeFleetValue (frame, playerI);
|
||||||
|
DrawPickMeleeFrame (playerI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade in
|
||||||
|
{
|
||||||
|
BYTE fade_buf[] = {FadeAllToColor};
|
||||||
|
SleepThreadUntil (XFormColorMap
|
||||||
|
((COLORMAPPTR) fade_buf, ONE_SECOND / 2) + ONE_SECOND / 60);
|
||||||
|
FlushColorXForms ();
|
||||||
|
}
|
||||||
|
|
||||||
|
playerMask = 0;
|
||||||
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
|
playerMask |= (1 << playerI);
|
||||||
|
|
||||||
|
return GetMeleeStarShips (playerMask, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result)
|
||||||
|
{
|
||||||
|
COUNT playerMask;
|
||||||
|
HSTARSHIP ships[NUM_PLAYERS];
|
||||||
|
BOOLEAN ok;
|
||||||
|
|
||||||
|
DrawPickMeleeFrame (which_player);
|
||||||
|
|
||||||
|
playerMask = 1 << which_player;
|
||||||
|
ok = GetMeleeStarShips (playerMask, ships);
|
||||||
|
if (ok)
|
||||||
|
*result = ships[which_player];
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
// Called when a ship selection has arrived from a remote player.
|
// Called when a ship selection has arrived from a remote player.
|
||||||
bool
|
bool
|
||||||
updateMeleeSelection (GETMELEE_STATE *gms, COUNT player, COUNT ship)
|
updateMeleeSelection (GETMELEE_STATE *gms, COUNT playerI, COUNT ship)
|
||||||
{
|
{
|
||||||
if (gms == NULL)
|
if (gms == NULL || !gms->player[playerI].selecting ||
|
||||||
|
gms->player[playerI].done)
|
||||||
{
|
{
|
||||||
// This happens when we get an update message from a connection
|
// This happens when we get an update message from a connection
|
||||||
// for who we are not selecting a ship (yet?).
|
// for who we are not selecting a ship.
|
||||||
fprintf (stderr, "Unexpected ship selection packet received.\n");
|
log_add (log_Warning, "Unexpected ship selection packet "
|
||||||
|
"received.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ship == (COUNT) ~0)
|
if (ship == (COUNT) ~0)
|
||||||
{
|
{
|
||||||
// Random selection.
|
// Random selection.
|
||||||
gms->hBattleShip =
|
gms->player[playerI].hBattleShip =
|
||||||
MeleeShipByUsedIndex (&race_q[player], gms->randomIndex);
|
MeleeShipByUsedIndex (&race_q[playerI],
|
||||||
gms->remoteSelected = TRUE;
|
gms->player[playerI].randomIndex);
|
||||||
NetConnection_setState (netConnections[player], NetState_interBattle);
|
gms->player[playerI].remoteSelected = TRUE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gms->hBattleShip = MeleeShipByQueueIndex (&race_q[player], ship);
|
gms->player[playerI].hBattleShip =
|
||||||
if (gms->hBattleShip == 0)
|
MeleeShipByQueueIndex (&race_q[playerI], ship);
|
||||||
|
if (gms->player[playerI].hBattleShip == 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Invalid ship selection received from remote "
|
log_add (log_Warning, "Invalid ship selection received from remote "
|
||||||
"party.\n");
|
"party.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gms->remoteSelected = TRUE;
|
gms->player[playerI].remoteSelected = TRUE;
|
||||||
NetConnection_setState (netConnections[player], NetState_interBattle);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,7 +799,6 @@ reportShipSelected (GETMELEE_STATE *gms, COUNT index)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Netplay_selectShip (conn, index);
|
Netplay_selectShip (conn, index);
|
||||||
NetConnection_setState (conn, NetState_interBattle);
|
|
||||||
}
|
}
|
||||||
(void) gms;
|
(void) gms;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,9 @@
|
|||||||
#include "races.h"
|
#include "races.h"
|
||||||
#include "libs/compiler.h"
|
#include "libs/compiler.h"
|
||||||
|
|
||||||
HSTARSHIP GetMeleeStarShip (STARSHIP *LastStarShipPtr,
|
BOOLEAN MeleeShipDeath (STARSHIP *ship, COUNT which_player);
|
||||||
COUNT which_player);
|
BOOLEAN GetInitialMeleeStarShips (HSTARSHIP *result);
|
||||||
|
BOOLEAN GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result);
|
||||||
|
|
||||||
typedef struct getmelee_struct GETMELEE_STATE;
|
typedef struct getmelee_struct GETMELEE_STATE;
|
||||||
|
|
||||||
|
|||||||
@@ -311,7 +311,24 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
|||||||
else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
|
else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
|
||||||
{
|
{
|
||||||
// Let the player chose his own ship. (May be a computer player).
|
// Let the player chose his own ship. (May be a computer player).
|
||||||
hBattleShip = GetMeleeStarShip (LastStarShipPtr, which_player);
|
|
||||||
|
if (!(GLOBAL (CurrentActivity) & IN_BATTLE))
|
||||||
|
{
|
||||||
|
// XXX: This check should not be needed, but Uninitships()
|
||||||
|
// calls this function after the battle is over for some
|
||||||
|
// reason. Perhaps because one of the non-supermelee cases.
|
||||||
|
// (Note that the reason isn't to display the battle
|
||||||
|
// summary; that has already been done).
|
||||||
|
hBattleShip = 0;
|
||||||
|
}
|
||||||
|
else if (!MeleeShipDeath (LastStarShipPtr, which_player))
|
||||||
|
hBattleShip = 0;
|
||||||
|
// Game over.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!GetNextMeleeStarShip (which_player, &hBattleShip))
|
||||||
|
hBattleShip = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -333,6 +350,7 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
|||||||
hBattleShip = GetHeadLink (&race_q[which_player]);
|
hBattleShip = GetHeadLink (&race_q[which_player]);
|
||||||
if (which_player == 1)
|
if (which_player == 1)
|
||||||
{
|
{
|
||||||
|
// Select the next ship for the computer.
|
||||||
hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q));
|
hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q));
|
||||||
FragPtr = (SHIP_FRAGMENT*) LockStarShip (
|
FragPtr = (SHIP_FRAGMENT*) LockStarShip (
|
||||||
&GLOBAL (npc_built_ship_q), hStarShip);
|
&GLOBAL (npc_built_ship_q), hStarShip);
|
||||||
|
|||||||
@@ -364,7 +364,6 @@ ProcessCollisions (HELEMENT hSuccElement, ELEMENT *ElementPtr,
|
|||||||
if (TestElementPtr == ElementPtr)
|
if (TestElementPtr == ElementPtr)
|
||||||
{
|
{
|
||||||
UnlockElement (hTestElement);
|
UnlockElement (hTestElement);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -940,8 +939,7 @@ PostProcessQueue (VIEW_STATE view_state, SIZE scroll_x,
|
|||||||
|
|
||||||
FRAME frame =
|
FRAME frame =
|
||||||
SetAbsFrameIndex (
|
SetAbsFrameIndex (
|
||||||
ElementPtr->next.image.farray
|
ElementPtr->next.image.farray[index + 1],
|
||||||
[index + 1],
|
|
||||||
GetFrameIndex (ElementPtr->next.image.frame));
|
GetFrameIndex (ElementPtr->next.image.frame));
|
||||||
|
|
||||||
if (frame && frame->image)
|
if (frame && frame->image)
|
||||||
|
|||||||
@@ -278,6 +278,9 @@ typedef struct
|
|||||||
|
|
||||||
BYTE weapon_counter;
|
BYTE weapon_counter;
|
||||||
BYTE special_counter;
|
BYTE special_counter;
|
||||||
|
// In the ship queue: Ship cost
|
||||||
|
// In between battles: crew left
|
||||||
|
// In battle: ship dependant
|
||||||
BYTE energy_counter;
|
BYTE energy_counter;
|
||||||
|
|
||||||
BYTE ship_input_state;
|
BYTE ship_input_state;
|
||||||
@@ -596,6 +599,7 @@ extern BOOLEAN InitKernel (void);
|
|||||||
extern void DrawCaptainsWindow (STARSHIP *StarShipPtr);
|
extern void DrawCaptainsWindow (STARSHIP *StarShipPtr);
|
||||||
extern BOOLEAN GetNextStarShip (STARSHIP *LastStarShipPtr,
|
extern BOOLEAN GetNextStarShip (STARSHIP *LastStarShipPtr,
|
||||||
COUNT which_side);
|
COUNT which_side);
|
||||||
|
extern BOOLEAN GetInitialStarShips (void);
|
||||||
extern HSTARSHIP GetEncounterStarShip (STARSHIP *LastStarShipPtr,
|
extern HSTARSHIP GetEncounterStarShip (STARSHIP *LastStarShipPtr,
|
||||||
COUNT which_player);
|
COUNT which_player);
|
||||||
extern void DrawArmadaPickShip (BOOLEAN draw_salvage_frame, RECT *pPickRect);
|
extern void DrawArmadaPickShip (BOOLEAN draw_salvage_frame, RECT *pPickRect);
|
||||||
|
|||||||
+44
-1
@@ -21,6 +21,7 @@
|
|||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
#include "globdata.h"
|
#include "globdata.h"
|
||||||
#include "intel.h"
|
#include "intel.h"
|
||||||
|
#include "pickmele.h"
|
||||||
#include "races.h"
|
#include "races.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "sounds.h"
|
#include "sounds.h"
|
||||||
@@ -428,7 +429,8 @@ spawn_ship (STARSHIP *StarShipPtr)
|
|||||||
ShipElementPtr->mass_points = RDPtr->characteristics.ship_mass;
|
ShipElementPtr->mass_points = RDPtr->characteristics.ship_mass;
|
||||||
ShipElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR
|
ShipElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR
|
||||||
| (RDPtr->ship_info.ship_flags & (GOOD_GUY | BAD_GUY));
|
| (RDPtr->ship_info.ship_flags & (GOOD_GUY | BAD_GUY));
|
||||||
ShipElementPtr->turn_wait = ShipElementPtr->thrust_wait = 0;
|
ShipElementPtr->turn_wait = 0;
|
||||||
|
ShipElementPtr->thrust_wait = 0;
|
||||||
ShipElementPtr->life_span = NORMAL_LIFE;
|
ShipElementPtr->life_span = NORMAL_LIFE;
|
||||||
|
|
||||||
SetPrimType (&DisplayArray[ShipElementPtr->PrimIndex], STAMP_PRIM);
|
SetPrimType (&DisplayArray[ShipElementPtr->PrimIndex], STAMP_PRIM);
|
||||||
@@ -507,7 +509,10 @@ GetNextStarShip (STARSHIP *LastStarShipPtr, COUNT which_side)
|
|||||||
if (LastStarShipPtr)
|
if (LastStarShipPtr)
|
||||||
{
|
{
|
||||||
if (StarShipPtr == LastStarShipPtr)
|
if (StarShipPtr == LastStarShipPtr)
|
||||||
|
{
|
||||||
|
// Ship has been recycled (on infinite ship worlds).
|
||||||
LastStarShipPtr = 0;
|
LastStarShipPtr = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
StarShipPtr->hShip = LastStarShipPtr->hShip;
|
StarShipPtr->hShip = LastStarShipPtr->hShip;
|
||||||
}
|
}
|
||||||
@@ -526,3 +531,41 @@ GetNextStarShip (STARSHIP *LastStarShipPtr, COUNT which_side)
|
|||||||
return (hBattleShip != 0);
|
return (hBattleShip != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
GetInitialStarShips (void)
|
||||||
|
{
|
||||||
|
if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
|
||||||
|
{
|
||||||
|
HSTARSHIP ships[NUM_PLAYERS];
|
||||||
|
COUNT i;
|
||||||
|
|
||||||
|
if (!GetInitialMeleeStarShips (ships))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_PLAYERS; i++)
|
||||||
|
{
|
||||||
|
STARSHIP *StarShipPtr;
|
||||||
|
COUNT playerI = GetPlayerOrder (i);
|
||||||
|
|
||||||
|
StarShipPtr = LockStarShip (&race_q[playerI], ships[playerI]);
|
||||||
|
if (!spawn_ship (StarShipPtr))
|
||||||
|
{
|
||||||
|
UnlockStarShip (&race_q[which_side], ships[playerI]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
UnlockStarShip (&race_q[which_side], ships[playerI]);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
COUNT num_ships = NUM_PLAYERS;
|
||||||
|
while (num_ships--)
|
||||||
|
{
|
||||||
|
if (!GetNextStarShip (NULL, num_ships == 1))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -957,10 +957,7 @@ DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta)
|
|||||||
DrawStamp (&s);
|
DrawStamp (&s);
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
UnlockStarShip (
|
UnlockStarShip (&GLOBAL (built_ship_q), hStarShip);
|
||||||
&GLOBAL (built_ship_q),
|
|
||||||
hStarShip
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
@@ -1347,7 +1344,8 @@ flash_rect_func (void *data)
|
|||||||
GetFrameRect (flash_screen_frame, &screen_rect);
|
GetFrameRect (flash_screen_frame, &screen_rect);
|
||||||
cached_screen_frame = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
|
cached_screen_frame = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
|
||||||
screen_rect.extent.width, screen_rect.extent.height, 1));
|
screen_rect.extent.width, screen_rect.extent.height, 1));
|
||||||
screen_rect.corner.x = screen_rect.corner.y = 0;
|
screen_rect.corner.x = 0;
|
||||||
|
screen_rect.corner.y = 0;
|
||||||
arith_frame_blit (flash_screen_frame, &screen_rect,
|
arith_frame_blit (flash_screen_frame, &screen_rect,
|
||||||
cached_screen_frame, NULL, 0, 0);
|
cached_screen_frame, NULL, 0, 0);
|
||||||
UnlockMutex (flash_mutex);
|
UnlockMutex (flash_mutex);
|
||||||
@@ -1404,11 +1402,13 @@ flash_rect_func (void *data)
|
|||||||
|
|
||||||
if (fstrength < 0)
|
if (fstrength < 0)
|
||||||
{
|
{
|
||||||
|
// Subtractive blit.
|
||||||
num = -8;
|
num = -8;
|
||||||
denom = 8;
|
denom = 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Additive blit.
|
||||||
num = 8;
|
num = 8;
|
||||||
denom = -8;
|
denom = -8;
|
||||||
}
|
}
|
||||||
@@ -1563,9 +1563,11 @@ SetFlashRect (RECT *pRect, FRAME f)
|
|||||||
|
|
||||||
if (flash_rect.extent.width)
|
if (flash_rect.extent.width)
|
||||||
{
|
{
|
||||||
|
// Copy the original contents of the rectangle from the screen.
|
||||||
if (flash_screen_frame)
|
if (flash_screen_frame)
|
||||||
DestroyDrawable (ReleaseDrawable (flash_screen_frame));
|
DestroyDrawable (ReleaseDrawable (flash_screen_frame));
|
||||||
flash_screen_frame = CaptureDrawable (LoadDisplayPixmap (&flash_rect, (FRAME)0));
|
flash_screen_frame =
|
||||||
|
CaptureDrawable (LoadDisplayPixmap (&flash_rect, (FRAME)0));
|
||||||
}
|
}
|
||||||
flash_changed = 1;
|
flash_changed = 1;
|
||||||
UnlockMutex (flash_mutex);
|
UnlockMutex (flash_mutex);
|
||||||
|
|||||||
Reference in New Issue
Block a user