diff options
Diffstat (limited to 'src/uqm/shipstat.c')
-rw-r--r-- | src/uqm/shipstat.c | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/src/uqm/shipstat.c b/src/uqm/shipstat.c new file mode 100644 index 0000000..0405426 --- /dev/null +++ b/src/uqm/shipstat.c @@ -0,0 +1,437 @@ +//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 "colors.h" +#include "globdata.h" +#include "options.h" +#include "status.h" +#include "setup.h" +#include "libs/gfxlib.h" + + +void +DrawCrewFuelString (COORD y, SIZE state) +{ + STAMP Stamp; + + Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT; + if (state == 0) + { + Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + 6; + if (optWhichMenu == OPT_PC) + Stamp.frame = SetAbsFrameIndex (StatusFrame, 4); + else + Stamp.frame = SetAbsFrameIndex (StatusFrame, 0); + DrawStamp (&Stamp); + } + + Stamp.origin.x = ENERGY_XOFFS + (STAT_WIDTH >> 1) - 5; + if (optWhichMenu == OPT_PC) + Stamp.frame = SetAbsFrameIndex (StatusFrame, 5); + else + Stamp.frame = SetAbsFrameIndex (StatusFrame, 1); + if (state >= 0) + DrawStamp (&Stamp); + else + { +#define LOW_FUEL_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) + SetContextForeGroundColor (LOW_FUEL_COLOR); + DrawFilledStamp (&Stamp); + } +} + +static void +DrawShipNameString (UNICODE *pStr, COUNT CharCount, COORD y) +{ + TEXT Text; + FONT OldFont; + + OldFont = SetContextFont (StarConFont); + + Text.pStr = pStr; + Text.CharCount = CharCount; + Text.align = ALIGN_CENTER; + + Text.baseline.y = STARCON_TEXT_HEIGHT + 3 + y; + Text.baseline.x = STATUS_WIDTH >> 1; + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + font_DrawText (&Text); + --Text.baseline.y; + SetContextForeGroundColor (BLACK_COLOR); + font_DrawText (&Text); + + SetContextFont (OldFont); +} + +void +ClearShipStatus (COORD y) +{ + RECT r; + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); + r.corner.x = 2; + r.corner.y = 3 + y; + r.extent.width = STATUS_WIDTH - 4; + r.extent.height = SHIP_INFO_HEIGHT - 3; + DrawFilledRectangle (&r); +} + +void +OutlineShipStatus (COORD y) +{ + RECT r; + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); + r.corner.x = 0; + r.corner.y = 1 + y; + r.extent.width = STATUS_WIDTH; + r.extent.height = 1; + DrawFilledRectangle (&r); + ++r.corner.y; + --r.extent.width; + DrawFilledRectangle (&r); + r.extent.width = 1; + r.extent.height = SHIP_INFO_HEIGHT - 2; + DrawFilledRectangle (&r); + ++r.corner.x; + DrawFilledRectangle (&r); + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.x = STATUS_WIDTH - 1; + DrawFilledRectangle (&r); + r.corner.x = STATUS_WIDTH - 2; + ++r.corner.y; + --r.extent.height; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = 0; + r.corner.y = y; + r.extent.width = STATUS_WIDTH; + r.extent.height = 1; + DrawFilledRectangle (&r); +} + +void +InitShipStatus (SHIP_INFO *SIPtr, STARSHIP *StarShipPtr, RECT *pClipRect) +{ + RECT r; + COORD y = 0; // default, for Melee menu + STAMP Stamp; + CONTEXT OldContext; + RECT oldClipRect; + POINT oldOrigin = {0, 0}; + + if (StarShipPtr) // set during battle + { + assert (StarShipPtr->playerNr >= 0); + y = status_y_offsets[StarShipPtr->playerNr]; + } + + OldContext = SetContext (StatusContext); + if (pClipRect) + { + GetContextClipRect (&oldClipRect); + r = oldClipRect; + r.corner.x += pClipRect->corner.x; + r.corner.y += (pClipRect->corner.y & ~1); + r.extent = pClipRect->extent; + r.extent.height += pClipRect->corner.y & 1; + SetContextClipRect (&r); + // Offset the origin so that we draw into the cliprect + oldOrigin = SetContextOrigin (MAKE_POINT (-pClipRect->corner.x, + -(pClipRect->corner.y & ~1))); + } + + BatchGraphics (); + + OutlineShipStatus (y); + ClearShipStatus (y); + + Stamp.origin.x = (STATUS_WIDTH >> 1); + Stamp.origin.y = 31 + y; + Stamp.frame = IncFrameIndex (SIPtr->icons); + DrawStamp (&Stamp); + + { + SIZE crew_height, energy_height; + +#define MIN(a, b) (((a) <= (b)) ? (a) : (b)) + crew_height = ((MIN(SIPtr->max_crew, MAX_CREW_SIZE) + 1) & ~1) + 1; +#undef MIN + energy_height = (((SIPtr->max_energy + 1) >> 1) << 1) + 1; + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); + r.corner.x = CREW_XOFFS - 1; + r.corner.y = GAUGE_YOFFS + 1 + y; + r.extent.width = STAT_WIDTH + 2; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS - 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS + STAT_WIDTH; + r.corner.y -= energy_height; + r.extent.width = 1; + r.extent.height = energy_height; + DrawFilledRectangle (&r); + r.corner.x = CREW_XOFFS + STAT_WIDTH; + r.corner.y = (GAUGE_YOFFS + 1 + y) - crew_height; + r.extent.width = 1; + r.extent.height = crew_height; + DrawFilledRectangle (&r); + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.x = CREW_XOFFS - 1; + r.corner.y = GAUGE_YOFFS - crew_height + y; + r.extent.width = STAT_WIDTH + 2; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS - 1; + r.corner.y = GAUGE_YOFFS - energy_height + y; + DrawFilledRectangle (&r); + r.extent.width = 1; + r.extent.height = energy_height + 1; + DrawFilledRectangle (&r); + r.corner.x = CREW_XOFFS - 1; + r.corner.y = GAUGE_YOFFS - crew_height + y; + r.extent.height = crew_height + 1; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BLACK_COLOR); + + r.extent.width = STAT_WIDTH; + r.corner.x = CREW_XOFFS; + r.extent.height = crew_height; + r.corner.y = y - r.extent.height + GAUGE_YOFFS + 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS; + r.extent.height = energy_height; + r.corner.y = y - r.extent.height + GAUGE_YOFFS + 1; + DrawFilledRectangle (&r); + } + + if (!StarShipPtr || StarShipPtr->captains_name_index) + { // Any regular ship. SIS and Sa-Matra are separate. + // This includes Melee menu. + STRING locString; + + DrawCrewFuelString (y, 0); + + locString = SetAbsStringTableIndex (SIPtr->race_strings, 1); + DrawShipNameString ( + (UNICODE *)GetStringAddress (locString), + GetStringLength (locString), y); + + { + UNICODE buf[30]; + TEXT Text; + FONT OldFont; + + OldFont = SetContextFont (TinyFont); + + if (!StarShipPtr) + { // In Melee menu + sprintf (buf, "%d", SIPtr->ship_cost); + Text.pStr = buf; + Text.CharCount = (COUNT)~0; + } + else + { + locString = SetAbsStringTableIndex (SIPtr->race_strings, + StarShipPtr->captains_name_index); + Text.pStr = (UNICODE *)GetStringAddress (locString); + Text.CharCount = GetStringLength (locString); + } + Text.align = ALIGN_CENTER; + + Text.baseline.x = STATUS_WIDTH >> 1; + Text.baseline.y = y + GAUGE_YOFFS + 3; + + SetContextForeGroundColor (BLACK_COLOR); + font_DrawText (&Text); + + SetContextFont (OldFont); + } + } + else if (StarShipPtr->playerNr == RPG_PLAYER_NUM) + { // This is SIS + DrawCrewFuelString (y, 0); + DrawShipNameString (GLOBAL_SIS (ShipName), (COUNT)~0, y); + } + + { + SIZE crew_delta, energy_delta; + + crew_delta = SIPtr->crew_level; + energy_delta = SIPtr->energy_level; + // DeltaStatistics() below will add specified values to these + SIPtr->crew_level = 0; + SIPtr->energy_level = 0; + DeltaStatistics (SIPtr, y, crew_delta, energy_delta); + } + + UnbatchGraphics (); + + if (pClipRect) + { + SetContextOrigin (oldOrigin); + SetContextClipRect (&oldClipRect); + } + + SetContext (OldContext); +} + +// Pre: -crew_delta <= ShipInfoPtr->crew_level +// crew_delta <= ShipInfoPtr->max_crew - ShipInfoPtr->crew_level +void +DeltaStatistics (SHIP_INFO *ShipInfoPtr, COORD y_offs, + SIZE crew_delta, SIZE energy_delta) +{ + COORD x, y; + RECT r; + + if (crew_delta == 0 && energy_delta == 0) + return; + + x = 0; + y = GAUGE_YOFFS + y_offs; + + r.extent.width = UNIT_WIDTH; + r.extent.height = UNIT_HEIGHT; + + if (crew_delta != 0) + { + COUNT oldNumBlocks, newNumBlocks, blockI; + COUNT newCrewLevel; + +#define MIN(a, b) (((a) <= (b)) ? (a) : (b)) + oldNumBlocks = MIN(ShipInfoPtr->crew_level, MAX_CREW_SIZE); + newCrewLevel = ShipInfoPtr->crew_level + crew_delta; + newNumBlocks = MIN(newCrewLevel, MAX_CREW_SIZE); +#undef MIN + + if (crew_delta > 0) + { + r.corner.y = (y + 1) - + (((oldNumBlocks + 1) >> 1) * (UNIT_HEIGHT + 1)); +#define CREW_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02) +#define ROBOT_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) + SetContextForeGroundColor ( + (ShipInfoPtr->ship_flags & CREW_IMMUNE) ? + ROBOT_UNIT_COLOR : CREW_UNIT_COLOR); + for (blockI = oldNumBlocks; blockI < newNumBlocks; blockI++) + { + r.corner.x = x + (CREW_XOFFS + 1); + if (!(blockI & 1)) + { + r.corner.x += UNIT_WIDTH + 1; + r.corner.y -= UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + } + } + else /* crew_delta < 0 */ + { + SetContextForeGroundColor (BLACK_COLOR); + r.corner.y = (y + 1) - + (((oldNumBlocks + 2) >> 1) * (UNIT_HEIGHT + 1)); + for (blockI = oldNumBlocks; blockI > newNumBlocks; blockI--) + { + r.corner.x = x + (CREW_XOFFS + 1 + UNIT_WIDTH + 1); + if (!(blockI & 1)) + { + r.corner.x -= UNIT_WIDTH + 1; + r.corner.y += UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + } + } + + if (ShipInfoPtr->ship_flags & PLAYER_CAPTAIN) { + if (((ShipInfoPtr->crew_level > MAX_CREW_SIZE) != + (newCrewLevel > MAX_CREW_SIZE) || + ShipInfoPtr->crew_level == 0) && newCrewLevel != 0) + { + // The block indicating the captain needs to change color. +#define PLAYER_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) + SetContextForeGroundColor ( + (newCrewLevel > MAX_CREW_SIZE) ? + CREW_UNIT_COLOR : PLAYER_UNIT_COLOR); + r.corner.x = x + (CREW_XOFFS + 1) + (UNIT_WIDTH + 1); + r.corner.y = y - UNIT_HEIGHT; + DrawFilledRectangle (&r); + } + } + + ShipInfoPtr->crew_level = newCrewLevel; + if (ShipInfoPtr->max_crew > MAX_CREW_SIZE || + ShipInfoPtr->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 (ShipInfoPtr, y_offs); + } + } + + if (energy_delta != 0) + { + if (energy_delta > 0) + { +#define FUEL_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) + SetContextForeGroundColor (FUEL_UNIT_COLOR); + r.corner.y = (y + 1) - + (((ShipInfoPtr->energy_level + 1) >> 1) * (UNIT_HEIGHT + 1)); + do + { + r.corner.x = x + (ENERGY_XOFFS + 1); + if (!(ShipInfoPtr->energy_level & 1)) + { + r.corner.x += UNIT_WIDTH + 1; + r.corner.y -= UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + ++ShipInfoPtr->energy_level; + } while (--energy_delta); + } + else + { + SetContextForeGroundColor (BLACK_COLOR); + r.corner.y = (y + 1) - + (((ShipInfoPtr->energy_level + 2) >> 1) * (UNIT_HEIGHT + 1)); + do + { + r.corner.x = x + (ENERGY_XOFFS + 1 + UNIT_WIDTH + 1); + if (!(ShipInfoPtr->energy_level & 1)) + { + r.corner.x -= UNIT_WIDTH + 1; + r.corner.y += UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + --ShipInfoPtr->energy_level; + } while (++energy_delta); + } + } +} + + |