diff options
Diffstat (limited to 'src/uqm/status.c')
-rw-r--r-- | src/uqm/status.c | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/src/uqm/status.c b/src/uqm/status.c new file mode 100644 index 0000000..6a588a8 --- /dev/null +++ b/src/uqm/status.c @@ -0,0 +1,582 @@ +//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; + } +} + |