diff options
Diffstat (limited to 'src/uqm/pickship.c')
-rw-r--r-- | src/uqm/pickship.c | 501 |
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); +} + |