summaryrefslogtreecommitdiff
path: root/src/uqm/pickship.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/pickship.c')
-rw-r--r--src/uqm/pickship.c501
1 files changed, 501 insertions, 0 deletions
diff --git a/src/uqm/pickship.c b/src/uqm/pickship.c
new file mode 100644
index 0000000..3dcced0
--- /dev/null
+++ b/src/uqm/pickship.c
@@ -0,0 +1,501 @@
+//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 "pickship.h"
+
+#include "build.h"
+#include "colors.h"
+#include "controls.h"
+#include "menustat.h"
+#include "supermelee/pickmele.h"
+#include "encount.h"
+#include "battle.h"
+#include "races.h"
+#include "resinst.h"
+#include "nameref.h"
+#include "settings.h"
+#include "setup.h"
+#include "sounds.h"
+#include "libs/mathlib.h"
+
+
+#define NUM_PICK_SHIP_ROWS 2
+#define NUM_PICK_SHIP_COLUMNS 6
+
+#define ICON_WIDTH 16
+#define ICON_HEIGHT 16
+
+#define FLAGSHIP_X_OFFS 65
+#define FLAGSHIP_Y_OFFS 4
+#define FLAGSHIP_WIDTH 22
+#define FLAGSHIP_HEIGHT 48
+
+static BOOLEAN
+DoPickBattleShip (MENU_STATE *pMS)
+{
+ if (GLOBAL (CurrentActivity) & CHECK_ABORT)
+ {
+ pMS->CurFrame = 0;
+ return (FALSE);
+ }
+
+ SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
+
+ if (!pMS->Initialized)
+ {
+ pMS->Initialized = TRUE;
+ pMS->InputFunc = DoPickBattleShip;
+
+
+ goto ChangeSelection;
+ }
+ else if (PulsedInputState.menu[KEY_MENU_SELECT])
+ {
+ if ((HSTARSHIP)pMS->CurFrame)
+ {
+ PlayMenuSound (MENU_SOUND_SUCCESS);
+ return (FALSE);
+ }
+ }
+ else
+ {
+ COORD new_row, new_col;
+ int dx = 0, dy = 0;
+ if (PulsedInputState.menu[KEY_MENU_RIGHT]) dx = 1;
+ if (PulsedInputState.menu[KEY_MENU_LEFT]) dx = -1;
+ if (PulsedInputState.menu[KEY_MENU_UP]) dy = -1;
+ if (PulsedInputState.menu[KEY_MENU_DOWN]) dy = 1;
+
+ new_col = pMS->first_item.x + dx;
+ new_row = pMS->first_item.y + dy;
+ if (new_row != pMS->first_item.y
+ || new_col != pMS->first_item.x)
+ {
+ RECT r;
+ TEXT t;
+ COUNT crew_level, max_crew;
+ COUNT ship_index;
+ HSTARSHIP hBattleShip, hNextShip;
+ STARSHIP *StarShipPtr;
+
+ if (new_col < 0)
+ new_col = NUM_PICK_SHIP_COLUMNS;
+ else if (new_col > NUM_PICK_SHIP_COLUMNS)
+ new_col = 0;
+
+ if (new_row < 0)
+ new_row = NUM_PICK_SHIP_ROWS - 1;
+ else if (new_row == NUM_PICK_SHIP_ROWS)
+ new_row = 0;
+
+ PlayMenuSound (MENU_SOUND_MOVE);
+
+
+#ifdef NEVER
+ SetContextForeGroundColor (
+ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x1D));
+ DrawRectangle (&pMS->flash_rect0);
+#endif /* NEVER */
+ pMS->first_item.y = new_row;
+ pMS->first_item.x = new_col;
+
+ChangeSelection:
+ if (pMS->first_item.x == (NUM_PICK_SHIP_COLUMNS >> 1))
+ {
+ pMS->flash_rect0.corner.x =
+ pMS->flash_rect1.corner.x - 2 + FLAGSHIP_X_OFFS;
+ pMS->flash_rect0.corner.y =
+ pMS->flash_rect1.corner.y - 2 + FLAGSHIP_Y_OFFS;
+ pMS->flash_rect0.extent.width = FLAGSHIP_WIDTH + 4;
+ pMS->flash_rect0.extent.height = FLAGSHIP_HEIGHT + 4;
+
+ hBattleShip = GetTailLink (&race_q[0]); /* Flagship */
+ }
+ else
+ {
+ new_col = pMS->first_item.x;
+ pMS->flash_rect0.corner.x = 5 + pMS->flash_rect1.corner.x - 2
+ + ((ICON_WIDTH + 4) * new_col);
+ if (new_col > (NUM_PICK_SHIP_COLUMNS >> 1))
+ {
+ --new_col;
+ pMS->flash_rect0.corner.x += FLAGSHIP_WIDTH - ICON_WIDTH;
+ }
+ pMS->flash_rect0.corner.y = 16 + pMS->flash_rect1.corner.y - 2
+ + ((ICON_HEIGHT + 4) * pMS->first_item.y);
+ pMS->flash_rect0.extent.width = ICON_WIDTH + 4;
+ pMS->flash_rect0.extent.height = ICON_HEIGHT + 4;
+
+ ship_index = (pMS->first_item.y * NUM_PICK_SHIP_COLUMNS)
+ + new_col;
+
+ for (hBattleShip = GetHeadLink (&race_q[0]);
+ hBattleShip != GetTailLink (&race_q[0]);
+ hBattleShip = hNextShip)
+ {
+ StarShipPtr = LockStarShip (&race_q[0], hBattleShip);
+ if (StarShipPtr->index == ship_index
+ && (StarShipPtr->SpeciesID != NO_ID))
+ {
+ UnlockStarShip (&race_q[0], hBattleShip);
+ break;
+ }
+
+ hNextShip = _GetSuccLink (StarShipPtr);
+ UnlockStarShip (&race_q[0], hBattleShip);
+ }
+
+ if (hBattleShip == GetTailLink (&race_q[0]))
+ hBattleShip = 0;
+ }
+
+ pMS->CurFrame = (FRAME)hBattleShip;
+
+ SetContextForeGroundColor (BLACK_COLOR);
+ r.corner.x = pMS->flash_rect1.corner.x + 6;
+ r.corner.y = pMS->flash_rect1.corner.y + 5;
+ r.extent.width = ((ICON_WIDTH + 4) * 3) - 4;
+ r.extent.height = 7;
+ DrawFilledRectangle (&r);
+
+ if (hBattleShip == 0)
+ {
+ crew_level = 0;
+ max_crew = 0;
+ // Satisfy compiler.
+ }
+ else
+ {
+ SetContextFont (TinyFont);
+
+ t.baseline.x = r.corner.x + (r.extent.width >> 1);
+ t.baseline.y = r.corner.y + (r.extent.height - 1);
+ t.align = ALIGN_CENTER;
+
+ StarShipPtr = LockStarShip (&race_q[0], hBattleShip);
+ if (StarShipPtr->captains_name_index == 0)
+ {
+ t.pStr = GLOBAL_SIS (CommanderName);
+ t.CharCount = (COUNT)~0;
+ crew_level = GLOBAL_SIS (CrewEnlisted);
+ max_crew = GetCrewPodCapacity ();
+ }
+ else
+ {
+ STRING locString;
+
+ locString = SetAbsStringTableIndex (
+ StarShipPtr->race_strings,
+ StarShipPtr->captains_name_index);
+ t.pStr = (UNICODE *)GetStringAddress (locString);
+ t.CharCount = GetStringLength (locString);
+ crew_level = StarShipPtr->crew_level;
+ max_crew = StarShipPtr->max_crew;
+ }
+ UnlockStarShip (&race_q[0], hBattleShip);
+
+ SetContextForeGroundColor (
+ BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x0C));
+ font_DrawText (&t);
+ SetContextForeGroundColor (BLACK_COLOR);
+ }
+
+ r.corner.x += (ICON_WIDTH + 4)
+ * ((NUM_PICK_SHIP_COLUMNS >> 1) + 1)
+ + FLAGSHIP_WIDTH - ICON_WIDTH;
+ DrawFilledRectangle (&r);
+
+ if (crew_level)
+ {
+ char buf[80];
+
+ t.baseline.x = r.corner.x + (r.extent.width >> 1);
+ t.pStr = buf;
+ t.CharCount = (COUNT)~0;
+ if (crew_level >= max_crew)
+ sprintf (buf, "%u", crew_level);
+ else
+ sprintf (buf, "%u/%u", crew_level, max_crew);
+ SetContextForeGroundColor (
+ BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02));
+ font_DrawText (&t);
+ }
+
+ SetFlashRect (NULL);
+ SetFlashRect (&pMS->flash_rect0);
+ }
+ }
+
+ SleepThread (ONE_SECOND / 30);
+
+ return (TRUE);
+}
+
+static HSTARSHIP
+GetArmadaStarShip (void)
+{
+ RECT pick_r;
+ CONTEXT OldContext;
+ HSTARSHIP hBattleShip;
+
+ if (battle_counter[1] == 0)
+ {
+ // No opponents left.
+ return 0;
+ }
+
+// MenuSounds = CaptureSound (LoadSound (MENU_SOUNDS));
+
+OldContext = SetContext (SpaceContext);
+ DrawArmadaPickShip (FALSE, &pick_r);
+
+ {
+ MENU_STATE MenuState;
+
+ MenuState.InputFunc = DoPickBattleShip;
+ MenuState.Initialized = FALSE;
+ MenuState.first_item.x = NUM_PICK_SHIP_COLUMNS >> 1;
+ MenuState.first_item.y = 0;
+ MenuState.CurFrame = 0;
+ MenuState.flash_rect1.corner = pick_r.corner;
+ MenuState.flash_rect1.extent.width = 0;
+
+ SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
+ DoInput (&MenuState, FALSE);
+
+ SetFlashRect (NULL);
+
+ hBattleShip = (HSTARSHIP)MenuState.CurFrame;
+ }
+
+ if (hBattleShip)
+ {
+ if (hBattleShip == GetTailLink (&race_q[0]))
+ { // Player chose SIS. There will be no more choices.
+ battle_counter[RPG_PLAYER_NUM] = 1;
+ }
+
+ WaitForSoundEnd (0);
+ }
+
+// DestroySound (ReleaseSound (MenuSounds));
+
+SetContext (OldContext);
+
+ return (hBattleShip);
+}
+
+// Get the next ship to use.
+HSTARSHIP
+GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
+{
+ if (inHQSpace ())
+ {
+ assert (which_player == RPG_PLAYER_NUM);
+ // SIS for the Hyperspace flight
+ return GetHeadLink (&race_q[which_player]);
+ }
+ else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
+ {
+ // Let the player chose their own ship. (May be a computer player).
+ HSTARSHIP hBattleShip;
+
+ if (battle_counter[0] == 0 || battle_counter[1] == 0)
+ { // One side is out of ships. Game over.
+ return 0;
+ }
+
+ if (!GetNextMeleeStarShip (which_player, &hBattleShip))
+ return 0;
+
+ return hBattleShip;
+ }
+ else
+ {
+ // Full game.
+ if (which_player == RPG_PLAYER_NUM)
+ { // Human player in a full game.
+ if (LastStarShipPtr == 0 && battle_counter[which_player] == 1)
+ { // First time picking a ship and player has no escorts
+ // SIS is the last ship in queue (though there is only one)
+ return GetTailLink (&race_q[which_player]);
+ }
+ else if (battle_counter[which_player])
+ { // Player still has ships left
+ return GetArmadaStarShip ();
+ }
+ else if (LastStarShipPtr != 0)
+ { // last ship was the flagship
+#define RUN_AWAY_FUEL_COST (5 * FUEL_TANK_SCALE)
+ if (LastStarShipPtr->crew_level == 0)
+ { // Died in the line of duty
+ GLOBAL_SIS (CrewEnlisted) = (COUNT)~0;
+ }
+ else
+ { // Player ran away
+ if (GLOBAL_SIS (FuelOnBoard) > RUN_AWAY_FUEL_COST)
+ GLOBAL_SIS (FuelOnBoard) -= RUN_AWAY_FUEL_COST;
+ else
+ GLOBAL_SIS (FuelOnBoard) = 0;
+ }
+ }
+ return 0;
+ }
+ else
+ { // NPC player in a full game
+ if (FleetIsInfinite (which_player))
+ {
+ if (LastStarShipPtr != 0)
+ { // The current STARSHIP is reused for the next one;
+ // update with new info
+ // XXX: Note that if Syreen had a homeworld you could
+ // fight, all Syreen ships there would be crewed to
+ // the maximum, instead of the normal level
+ LastStarShipPtr->crew_level = LastStarShipPtr->max_crew;
+ LastStarShipPtr->playerNr = which_player;
+ LastStarShipPtr->captains_name_index = PickCaptainName ();
+ }
+ battle_counter[which_player]++;
+
+ return GetHeadLink (&race_q[which_player]);
+ }
+
+ // Get the next ship for the computer
+ if (LastStarShipPtr != 0)
+ return _GetSuccLink (LastStarShipPtr);
+
+ // Get the very first ship for the computer
+ return GetHeadLink (&race_q[which_player]);
+ }
+ }
+}
+
+void
+DrawArmadaPickShip (BOOLEAN draw_salvage_frame, RECT *pPickRect)
+{
+#define PICK_NAME_HEIGHT 6
+ //COUNT i;
+ HSTARSHIP hBattleShip, hNextShip;
+ STARSHIP *StarShipPtr;
+ RECT r, pick_r;
+ STAMP s;
+ TEXT t;
+ CONTEXT OldContext;
+ FRAME PickFrame;
+
+ OldContext = SetContext (SpaceContext);
+
+ PickFrame = CaptureDrawable (LoadGraphic (SC2_PICK_PMAP_ANIM));
+
+ BatchGraphics ();
+
+ s.frame = PickFrame;
+ SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0));
+ GetFrameRect (s.frame, &pick_r);
+ GetContextClipRect (&r);
+ pick_r.corner.x = (r.extent.width >> 1) - (pick_r.extent.width >> 1);
+ pick_r.corner.y = (r.extent.height >> 1) - (pick_r.extent.height >> 1);
+
+ if (!draw_salvage_frame)
+ *pPickRect = pick_r;
+ else
+ {
+ s.origin.x = r.extent.width >> 1;
+ s.frame = IncFrameIndex (s.frame);
+ SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0));
+ GetFrameRect (s.frame, &r);
+ s.origin.x -= r.extent.width >> 1;
+ s.origin.y = pick_r.corner.y - (r.extent.height >> 1);
+ DrawStamp (&s);
+ s.frame = DecFrameIndex (s.frame);
+ pick_r.corner.y = s.origin.y + r.extent.height;
+
+ r.corner.x = pick_r.corner.x;
+ r.corner.y = s.origin.y;
+ *pPickRect = r;
+ }
+ s.origin = pick_r.corner;
+ DrawStamp (&s);
+
+ t.baseline.x = pick_r.corner.x + (pick_r.extent.width >> 1);
+ t.baseline.y = pick_r.corner.y + pick_r.extent.height - 5;
+ t.align = ALIGN_CENTER;
+ t.pStr = GLOBAL_SIS (ShipName);
+ t.CharCount = (COUNT)~0;
+ SetContextForeGroundColor (
+ BUILD_COLOR (MAKE_RGB15 (0x12, 0x12, 0x12), 0x17));
+ SetContextFont (StarConFont);
+ font_DrawText (&t);
+
+ r.extent.width = ICON_WIDTH;
+ r.extent.height = ICON_HEIGHT;
+ for (hBattleShip = GetHeadLink (&race_q[0]);
+ hBattleShip != 0; hBattleShip = hNextShip)
+ {
+ StarShipPtr = LockStarShip (&race_q[0], hBattleShip);
+
+ if (StarShipPtr->captains_name_index)
+ { // Escort ship, not SIS
+ COUNT ship_index;
+
+ ship_index = StarShipPtr->index;
+
+ s.origin.x = pick_r.corner.x
+ + (5 + ((ICON_WIDTH + 4)
+ * (ship_index % NUM_PICK_SHIP_COLUMNS)));
+ if ((ship_index % NUM_PICK_SHIP_COLUMNS) >=
+ (NUM_PICK_SHIP_COLUMNS >> 1))
+ s.origin.x += FLAGSHIP_WIDTH + 4;
+ s.origin.y = pick_r.corner.y
+ + (16 + ((ICON_HEIGHT + 4)
+ * (ship_index / NUM_PICK_SHIP_COLUMNS)));
+ s.frame = StarShipPtr->icons;
+ r.corner = s.origin;
+ SetContextForeGroundColor (BLACK_COLOR);
+ DrawFilledRectangle (&r);
+ if ((StarShipPtr->SpeciesID != NO_ID) || (StarShipPtr->crew_level == 0))
+ {
+ DrawStamp (&s);
+ if (StarShipPtr->SpeciesID == NO_ID)
+ {
+ /* Dead ship - mark with an X. */
+ s.origin.x -= 1;
+ s.frame = SetAbsFrameIndex (StatusFrame, 3);
+ DrawStamp (&s);
+ }
+ }
+ else
+ {
+ /* Ship ran away */
+ SetContextForeGroundColor (
+ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01));
+ DrawFilledStamp (&s);
+ }
+ }
+
+ hNextShip = _GetSuccLink (StarShipPtr);
+ UnlockStarShip (&race_q[0], hBattleShip);
+ }
+
+ UnbatchGraphics ();
+
+ DestroyDrawable (ReleaseDrawable (PickFrame));
+
+ SetContext (OldContext);
+}
+