Files
commandergenius/project/jni/application/sc2/src/uqm/status.c
T

583 lines
15 KiB
C

//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* 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.
*/
#include "status.h"
#include "colors.h"
#include "globdata.h"
#include "races.h"
#include "ship.h"
#include "setup.h"
#include "options.h"
#include "init.h"
// for NUM_PLAYERS
#include <stdio.h>
#include <string.h>
COORD status_y_offsets[NUM_PLAYERS];
void
InitStatusOffsets (void)
{
// XXX: We have to jump through these hoops because GOOD_GUY_YOFFS is
// not a constant, contrary to what its name suggests.
status_y_offsets[0] = GOOD_GUY_YOFFS; // bottom player
status_y_offsets[1] = BAD_GUY_YOFFS; // top player
}
static void
CaptainsWindow (CAPTAIN_STUFF *CSPtr, COORD y,
STATUS_FLAGS delta_status_flags, STATUS_FLAGS cur_status_flags,
COUNT Pass)
{
STAMP Stamp;
Stamp.origin.x = CAPTAIN_XOFFS;
Stamp.origin.y = y + CAPTAIN_YOFFS;
if (delta_status_flags & LEFT)
{
Stamp.frame = CSPtr->turn;
if (!(delta_status_flags & RIGHT))
{
Stamp.frame = SetRelFrameIndex (Stamp.frame, 3);
if (Pass == 2)
{
if (cur_status_flags & LEFT)
Stamp.frame = IncFrameIndex (Stamp.frame);
else
Stamp.frame = DecFrameIndex (Stamp.frame);
}
}
else if (cur_status_flags & RIGHT)
{
if (Pass == 1)
Stamp.frame = SetRelFrameIndex (Stamp.frame, 3);
else
Stamp.frame = IncFrameIndex (Stamp.frame);
DrawStamp (&Stamp);
Stamp.frame = DecFrameIndex (Stamp.frame);
}
else
{
if (Pass == 1)
Stamp.frame = IncFrameIndex (Stamp.frame);
else
Stamp.frame = SetRelFrameIndex (Stamp.frame, 3);
DrawStamp (&Stamp);
Stamp.frame = IncFrameIndex (Stamp.frame);
}
DrawStamp (&Stamp);
}
else if (delta_status_flags & RIGHT)
{
Stamp.frame = CSPtr->turn;
Stamp.frame = IncFrameIndex (Stamp.frame);
if (Pass == 2)
{
if (cur_status_flags & RIGHT)
Stamp.frame = DecFrameIndex (Stamp.frame);
else
Stamp.frame = IncFrameIndex (Stamp.frame);
}
DrawStamp (&Stamp);
}
if (delta_status_flags & THRUST)
{
Stamp.frame = CSPtr->thrust;
if (Pass == 1)
Stamp.frame = IncFrameIndex (Stamp.frame);
else if (cur_status_flags & THRUST)
Stamp.frame = SetRelFrameIndex (Stamp.frame, 2);
DrawStamp (&Stamp);
}
if (delta_status_flags & WEAPON)
{
Stamp.frame = CSPtr->weapon;
if (Pass == 1)
Stamp.frame = IncFrameIndex (Stamp.frame);
else if (cur_status_flags & WEAPON)
Stamp.frame = SetRelFrameIndex (Stamp.frame, 2);
DrawStamp (&Stamp);
}
if (delta_status_flags & SPECIAL)
{
Stamp.frame = CSPtr->special;
if (Pass == 1)
Stamp.frame = IncFrameIndex (Stamp.frame);
else if (cur_status_flags & SPECIAL)
Stamp.frame = SetRelFrameIndex (Stamp.frame, 2);
DrawStamp (&Stamp);
}
}
void
DrawBattleCrewAmount (SHIP_INFO *ShipInfoPtr, COORD y_offs)
{
#define MAX_CREW_DIGITS 3
RECT r;
TEXT t;
UNICODE buf[40];
t.baseline.x = BATTLE_CREW_X + 2;
if (optWhichMenu == OPT_PC)
t.baseline.x -= 8;
t.baseline.y = BATTLE_CREW_Y + y_offs;
t.align = ALIGN_LEFT;
t.pStr = buf;
t.CharCount = (COUNT)~0;
r.corner.x = t.baseline.x;
r.corner.y = t.baseline.y - 5;
r.extent.width = 6 * MAX_CREW_DIGITS + 6;
r.extent.height = 5;
sprintf (buf, "%u", ShipInfoPtr->crew_level);
SetContextFont (StarConFont);
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08));
DrawFilledRectangle (&r);
SetContextForeGroundColor (BLACK_COLOR);
font_DrawText (&t);
}
void
DrawCaptainsWindow (STARSHIP *StarShipPtr)
{
COORD y;
COORD y_offs;
RECT r;
STAMP s;
FRAME Frame;
RACE_DESC *RDPtr;
RDPtr = StarShipPtr->RaceDescPtr;
Frame = RDPtr->ship_data.captain_control.background;
if (Frame)
{
Frame = SetAbsFrameIndex (Frame, 0);
RDPtr->ship_data.captain_control.background = Frame;
Frame = SetRelFrameIndex (Frame, 1);
RDPtr->ship_data.captain_control.turn = Frame;
Frame = SetRelFrameIndex (Frame, 5);
RDPtr->ship_data.captain_control.thrust = Frame;
Frame = SetRelFrameIndex (Frame, 3);
RDPtr->ship_data.captain_control.weapon = Frame;
Frame = SetRelFrameIndex (Frame, 3);
RDPtr->ship_data.captain_control.special = Frame;
}
BatchGraphics ();
assert (StarShipPtr->playerNr >= 0);
y_offs = status_y_offsets[StarShipPtr->playerNr];
r.corner.x = CAPTAIN_XOFFS - 2;
r.corner.y = y_offs + SHIP_INFO_HEIGHT;
r.extent.width = STATUS_WIDTH - CAPTAIN_XOFFS;
r.extent.height = SHIP_STATUS_HEIGHT - CAPTAIN_YOFFS + 2;
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08));
DrawFilledRectangle (&r);
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F));
r.corner.x = 1;
r.corner.y = y_offs + SHIP_INFO_HEIGHT;
r.extent.width = 1;
r.extent.height = (SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT - 2);
DrawFilledRectangle (&r);
r.corner.x = 0;
++r.extent.height;
DrawFilledRectangle (&r);
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19));
r.corner.x = STATUS_WIDTH - 1;
r.corner.y = y_offs + SHIP_INFO_HEIGHT;
r.extent.width = 1;
r.extent.height = SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT;
DrawFilledRectangle (&r);
r.corner.x = STATUS_WIDTH - 2;
DrawFilledRectangle (&r);
r.corner.x = 1;
r.extent.width = STATUS_WIDTH - 2;
r.corner.y = y_offs + (SHIP_STATUS_HEIGHT - 2);
r.extent.height = 1;
DrawFilledRectangle (&r);
r.corner.x = 0;
++r.extent.width;
++r.corner.y;
DrawFilledRectangle (&r);
y = y_offs + CAPTAIN_YOFFS;
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F));
r.corner.x = 59;
r.corner.y = y;
r.extent.width = 1;
r.extent.height = 30;
DrawFilledRectangle (&r);
r.corner.x = 3;
r.corner.y += 30;
r.extent.width = 57;
r.extent.height = 1;
DrawFilledRectangle (&r);
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19));
r.corner.x = 3;
r.extent.width = 57;
r.corner.y = y - 1;
r.extent.height = 1;
DrawFilledRectangle (&r);
r.corner.x = 3;
r.extent.width = 1;
r.corner.y = y;
r.extent.height = 30;
DrawFilledRectangle (&r);
s.frame = RDPtr->ship_data.captain_control.background;
s.origin.x = CAPTAIN_XOFFS;
s.origin.y = y;
DrawStamp (&s);
if (StarShipPtr->captains_name_index == 0
&& StarShipPtr->playerNr == RPG_PLAYER_NUM)
{ // This is SIS
TEXT t;
t.baseline.x = STATUS_WIDTH >> 1;
t.baseline.y = y + 6;
t.align = ALIGN_CENTER;
t.pStr = GLOBAL_SIS (CommanderName);
t.CharCount = (COUNT)~0;
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02));
SetContextFont (TinyFont);
font_DrawText (&t);
}
if (RDPtr->ship_info.max_crew > MAX_CREW_SIZE ||
RDPtr->ship_info.ship_flags & PLAYER_CAPTAIN)
{
// All crew doesn't fit in the graphics; print a number.
// Always print a number for the SIS in the full game.
DrawBattleCrewAmount (&RDPtr->ship_info, y_offs);
}
UnbatchGraphics ();
}
BOOLEAN
DeltaEnergy (ELEMENT *ElementPtr, SIZE energy_delta)
{
BOOLEAN retval;
STARSHIP *StarShipPtr;
SHIP_INFO *ShipInfoPtr;
retval = TRUE;
GetElementStarShip (ElementPtr, &StarShipPtr);
ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info;
if (energy_delta >= 0)
{
if ((BYTE)(ShipInfoPtr->energy_level + (BYTE)energy_delta) >
ShipInfoPtr->max_energy)
energy_delta = ShipInfoPtr->max_energy
- ShipInfoPtr->energy_level;
}
else
{
if ((BYTE)-energy_delta > ShipInfoPtr->energy_level)
{
retval = FALSE;
}
}
if (!retval)
StarShipPtr->cur_status_flags |= LOW_ON_ENERGY;
else
{
StarShipPtr->cur_status_flags &= ~LOW_ON_ENERGY;
StarShipPtr->energy_counter =
StarShipPtr->RaceDescPtr->characteristics.energy_wait;
DeltaStatistics (ShipInfoPtr, status_y_offsets[StarShipPtr->playerNr],
0, energy_delta);
}
return (retval);
}
BOOLEAN
DeltaCrew (ELEMENT *ElementPtr, SIZE crew_delta)
{
BOOLEAN retval;
STARSHIP *StarShipPtr;
SHIP_INFO *ShipInfoPtr;
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE
&& ElementPtr->playerNr == NPC_PLAYER_NUM)
return (TRUE); /* Samatra can't be crew-modified */
retval = TRUE;
GetElementStarShip (ElementPtr, &StarShipPtr);
ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info;
if (crew_delta > 0)
{
ElementPtr->crew_level += crew_delta;
if (ElementPtr->crew_level > ShipInfoPtr->max_crew)
{
crew_delta = ShipInfoPtr->max_crew - ShipInfoPtr->crew_level;
ElementPtr->crew_level = ShipInfoPtr->max_crew;
}
}
else if (crew_delta < 0)
{
if (ElementPtr->crew_level > (COUNT)-crew_delta)
ElementPtr->crew_level += crew_delta;
else
{
crew_delta = -(SIZE)ElementPtr->crew_level;
ElementPtr->crew_level = 0;
retval = FALSE;
}
}
DeltaStatistics (ShipInfoPtr, status_y_offsets[StarShipPtr->playerNr],
crew_delta, 0);
return (retval);
}
void
PreProcessStatus (ELEMENT *ShipPtr)
{
STARSHIP *StarShipPtr;
GetElementStarShip (ShipPtr, &StarShipPtr);
if (StarShipPtr->captains_name_index
|| StarShipPtr->playerNr == RPG_PLAYER_NUM)
{ // All except Sa-Matra, no captain's window there
STATUS_FLAGS old_status_flags, cur_status_flags;
CAPTAIN_STUFF *CSPtr;
cur_status_flags = StarShipPtr->cur_status_flags;
old_status_flags = StarShipPtr->old_status_flags;
old_status_flags ^= cur_status_flags;
CSPtr = &StarShipPtr->RaceDescPtr->ship_data.captain_control;
old_status_flags &= (LEFT | RIGHT | THRUST | WEAPON | SPECIAL);
if (old_status_flags)
{
assert (StarShipPtr->playerNr >= 0);
CaptainsWindow (CSPtr, status_y_offsets[StarShipPtr->playerNr],
old_status_flags, cur_status_flags, 1);
}
}
}
void
PostProcessStatus (ELEMENT *ShipPtr)
{
STARSHIP *StarShipPtr;
GetElementStarShip (ShipPtr, &StarShipPtr);
if (StarShipPtr->captains_name_index
|| StarShipPtr->playerNr == RPG_PLAYER_NUM)
{ // All except Sa-Matra, no captain's window there
COORD y;
STATUS_FLAGS cur_status_flags, old_status_flags;
cur_status_flags = StarShipPtr->cur_status_flags;
assert (StarShipPtr->playerNr >= 0);
y = status_y_offsets[StarShipPtr->playerNr];
if (ShipPtr->crew_level == 0)
{
StarShipPtr->cur_status_flags &=
~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL);
if (StarShipPtr->RaceDescPtr->ship_info.crew_level == 0)
{
BYTE i;
Color c;
RECT r;
i = (BYTE)(NUM_EXPLOSION_FRAMES * 3 - 1) - ShipPtr->life_span;
if (i <= 4)
{
static const Color flash_tab0[] =
{
BUILD_COLOR (MAKE_RGB15_INIT (0x0F, 0x00, 0x00), 0x2D),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x19, 0x19), 0x24),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x11, 0x00), 0x7B),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x1C, 0x00), 0x78),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x1F, 0x1F), 0x0F),
};
c = flash_tab0[i];
r.corner.x = CAPTAIN_XOFFS;
r.corner.y = y + CAPTAIN_YOFFS;
r.extent.width = CAPTAIN_WIDTH;
r.extent.height = CAPTAIN_HEIGHT;
}
else
{
SetContextForeGroundColor (BLACK_COLOR);
i -= 5;
if (i <= 14)
{
static const Color flash_tab1[] =
{
BUILD_COLOR (MAKE_RGB15_INIT (0x1E, 0x1F, 0x12), 0x70),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x1F, 0x0A), 0x0E),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x1F, 0x00), 0x71),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x1C, 0x00), 0x78),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x18, 0x00), 0x79),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x15, 0x00), 0x7A),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x11, 0x00), 0x7B),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x0E, 0x00), 0x7C),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x0A, 0x00), 0x7D),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x07, 0x00), 0x7E),
BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x03, 0x00), 0x7F),
BUILD_COLOR (MAKE_RGB15_INIT (0x1B, 0x00, 0x00), 0x2A),
BUILD_COLOR (MAKE_RGB15_INIT (0x17, 0x00, 0x00), 0x2B),
BUILD_COLOR (MAKE_RGB15_INIT (0x13, 0x00, 0x00), 0x2C),
BUILD_COLOR (MAKE_RGB15_INIT (0x0F, 0x00, 0x00), 0x2D),
};
c = flash_tab1[i];
r.corner.x = CAPTAIN_XOFFS + i;
r.corner.y = y + CAPTAIN_YOFFS + i;
r.extent.width = CAPTAIN_WIDTH - (i << 1);
r.extent.height = CAPTAIN_HEIGHT - (i << 1);
if (r.extent.height == 2)
++r.extent.height;
DrawRectangle (&r);
++r.corner.x;
++r.corner.y;
r.extent.width -= 2;
r.extent.height -= 2;
}
else if ((i -= 15) <= 4)
{
r.corner.y = y + (CAPTAIN_YOFFS + 15);
r.extent.width = i + 1;
r.extent.height = 1;
switch (i)
{
case 0:
r.corner.x = CAPTAIN_XOFFS + 15;
i = CAPTAIN_WIDTH - ((15 + 1) << 1);
c = BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C);
break;
case 1:
r.corner.x = CAPTAIN_XOFFS + 16;
i = CAPTAIN_WIDTH - ((17 + 1) << 1);
c = BUILD_COLOR (MAKE_RGB15 (0x07, 0x00, 0x00), 0x2F);
break;
case 2:
r.corner.x = CAPTAIN_XOFFS + 18;
i = CAPTAIN_WIDTH - ((20 + 1) << 1);
c = BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A);
break;
case 3:
r.corner.x = CAPTAIN_XOFFS + 21;
i = CAPTAIN_WIDTH - ((24 + 1) << 1);
c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x29);
break;
case 4:
r.corner.x = CAPTAIN_XOFFS + 25;
i = 1;
r.extent.width = 2;
c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x50, 0x05), 0x28);
break;
default:
// Should not happen.
c = UNDEFINED_COLOR; // Keeping compiler quiet.
break;
}
DrawFilledRectangle (&r);
r.corner.x += i + r.extent.width;
DrawFilledRectangle (&r);
r.corner.x -= i;
r.extent.width = i;
}
else
{
if ((i -= 5) > 2)
c = BLACK_COLOR;
else
{
static const Color flash_tab2[] =
{
BUILD_COLOR (MAKE_RGB15_INIT (0x17, 0x00, 0x00), 0x2B),
BUILD_COLOR (MAKE_RGB15_INIT (0x0F, 0x00, 0x00), 0x2D),
BUILD_COLOR (MAKE_RGB15_INIT (0x0B, 0x00, 0x00), 0x2E),
};
c = flash_tab2[i];
}
r.corner.x = CAPTAIN_XOFFS
+ (CAPTAIN_WIDTH >> 1);
r.corner.y = y + CAPTAIN_YOFFS
+ ((CAPTAIN_HEIGHT + 1) >> 1);
r.extent.width = 1;
r.extent.height = 1;
}
}
SetContextForeGroundColor (c);
DrawFilledRectangle (&r);
}
}
old_status_flags = StarShipPtr->old_status_flags;
old_status_flags = (old_status_flags ^ cur_status_flags) &
(LEFT | RIGHT | THRUST | WEAPON | SPECIAL | LOW_ON_ENERGY);
if (old_status_flags)
{
if (old_status_flags & LOW_ON_ENERGY)
{
if (!(cur_status_flags & LOW_ON_ENERGY))
DrawCrewFuelString (y, 1);
else
DrawCrewFuelString (y, -1);
}
old_status_flags &= (LEFT | RIGHT | THRUST | WEAPON | SPECIAL);
if (old_status_flags)
{
CaptainsWindow (
&StarShipPtr->RaceDescPtr->ship_data.captain_control,
y, old_status_flags, cur_status_flags, 2);
}
}
StarShipPtr->old_status_flags = cur_status_flags;
}
}