Account for ship death in Supermelee early to keep the scores correct after a simultaneous destruction of last ships in each fleet; some ship selection refactoring; bug #437
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3543 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
+77
-5
@@ -89,6 +89,15 @@ DoSelectAction (MENU_STATE *pMS)
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static QUEUE *
|
||||
GetShipFragQueueForPlayer (COUNT playerNr)
|
||||
{
|
||||
if (playerNr == RPG_PLAYER_NUM)
|
||||
return &GLOBAL (built_ship_q);
|
||||
else
|
||||
return &GLOBAL (npc_built_ship_q);
|
||||
}
|
||||
|
||||
// Called by comm code to intialize battle fleets during encounter
|
||||
void
|
||||
BuildBattle (COUNT which_player)
|
||||
@@ -106,10 +115,9 @@ BuildBattle (COUNT which_player)
|
||||
return;
|
||||
}
|
||||
|
||||
if (which_player == RPG_PLAYER_NUM)
|
||||
pQueue = &GLOBAL (built_ship_q);
|
||||
else
|
||||
{
|
||||
if (which_player != RPG_PLAYER_NUM)
|
||||
{ // This function is called first for the NPC character
|
||||
// and this is when a centerpiece is loaded
|
||||
switch (LOBYTE (GLOBAL (CurrentActivity)))
|
||||
{
|
||||
case IN_LAST_BATTLE:
|
||||
@@ -124,8 +132,8 @@ BuildBattle (COUNT which_player)
|
||||
load_gravity_well (GET_GAME_STATE (BATTLE_PLANET));
|
||||
break;
|
||||
}
|
||||
pQueue = &GLOBAL (npc_built_ship_q);
|
||||
}
|
||||
pQueue = GetShipFragQueueForPlayer (which_player);
|
||||
|
||||
ReinitQueue (&race_q[which_player]);
|
||||
for (hStarShip = GetHeadLink (pQueue);
|
||||
@@ -181,6 +189,70 @@ BuildBattle (COUNT which_player)
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FleetIsInfinite (COUNT playerNr)
|
||||
{
|
||||
QUEUE *pQueue;
|
||||
HSHIPFRAG hShipFrag;
|
||||
SHIP_FRAGMENT *FragPtr;
|
||||
BOOLEAN ret;
|
||||
|
||||
pQueue = GetShipFragQueueForPlayer (playerNr);
|
||||
hShipFrag = GetHeadLink (pQueue);
|
||||
if (!hShipFrag)
|
||||
{ // Ship queue is empty in SuperMelee or for RPG player w/o escorts
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FragPtr = LockShipFrag (pQueue, hShipFrag);
|
||||
ret = (FragPtr->crew_level == INFINITE_FLEET);
|
||||
UnlockShipFrag (pQueue, hShipFrag);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateShipFragCrew (STARSHIP *StarShipPtr)
|
||||
{
|
||||
QUEUE *frag_q;
|
||||
HSHIPFRAG hShipFrag, hNextFrag;
|
||||
SHIP_FRAGMENT *frag;
|
||||
QUEUE *ship_q;
|
||||
HSTARSHIP hStarShip, hNextShip;
|
||||
STARSHIP *ship;
|
||||
|
||||
frag_q = GetShipFragQueueForPlayer (StarShipPtr->playerNr);
|
||||
ship_q = &race_q[StarShipPtr->playerNr];
|
||||
|
||||
// Find a SHIP_FRAGMENT that corresponds to the given STARSHIP
|
||||
// The ships and fragments are in the same order in two queues
|
||||
// XXX: It would probably be simpler to keep HSHIPFRAG in STARSHIP struct
|
||||
for (hShipFrag = GetHeadLink (frag_q), hStarShip = GetHeadLink (ship_q);
|
||||
hShipFrag != 0 && hStarShip != 0;
|
||||
hShipFrag = hNextFrag, hStarShip = hNextShip)
|
||||
{
|
||||
ship = LockStarShip (ship_q, hStarShip);
|
||||
hNextShip = _GetSuccLink (ship);
|
||||
frag = LockShipFrag (frag_q, hShipFrag);
|
||||
hNextFrag = _GetSuccLink (frag);
|
||||
|
||||
if (ship == StarShipPtr)
|
||||
{
|
||||
assert (frag->crew_level != INFINITE_FLEET);
|
||||
|
||||
// Record crew left after the battle */
|
||||
frag->crew_level = ship->crew_level;
|
||||
|
||||
UnlockShipFrag (frag_q, hShipFrag);
|
||||
UnlockStarShip (ship_q, hStarShip);
|
||||
break;
|
||||
}
|
||||
|
||||
UnlockShipFrag (frag_q, hShipFrag);
|
||||
UnlockStarShip (ship_q, hStarShip);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encountering an alien.
|
||||
* Draws the encounter screen, plays the red alert music, and
|
||||
|
||||
@@ -28,6 +28,7 @@ typedef struct encounter ENCOUNTER;
|
||||
#include "libs/gfxlib.h"
|
||||
#include "planets/planets.h"
|
||||
#include "element.h"
|
||||
#include "races.h"
|
||||
|
||||
|
||||
typedef HLINK HENCOUNTER;
|
||||
@@ -151,6 +152,8 @@ extern void EncounterBattle (void);
|
||||
extern void BuildBattle (COUNT which_player);
|
||||
extern COUNT InitEncounter (void);
|
||||
extern COUNT UninitEncounter (void);
|
||||
extern BOOLEAN FleetIsInfinite (COUNT playerNr);
|
||||
extern void UpdateShipFragCrew (STARSHIP *);
|
||||
|
||||
// XXX: in comm.h, temporary, until solsys generation code is redone
|
||||
extern COUNT InitCommunication (CONVERSATION which_comm);
|
||||
|
||||
+9
-11
@@ -25,6 +25,7 @@
|
||||
#include "pickship.h"
|
||||
#include "process.h"
|
||||
#include "globdata.h"
|
||||
#include "encount.h"
|
||||
#include "hyper.h"
|
||||
#include "init.h"
|
||||
#include "port.h"
|
||||
@@ -268,7 +269,7 @@ void
|
||||
UninitShips (void)
|
||||
{
|
||||
COUNT crew_retrieved;
|
||||
SIZE i;
|
||||
int i;
|
||||
HELEMENT hElement, hNextElement;
|
||||
STARSHIP *SPtr[NUM_PLAYERS];
|
||||
|
||||
@@ -325,20 +326,17 @@ UninitShips (void)
|
||||
|
||||
GLOBAL (CurrentActivity) &= ~IN_BATTLE;
|
||||
|
||||
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE)
|
||||
{
|
||||
}
|
||||
else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER
|
||||
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER
|
||||
&& !(GLOBAL (CurrentActivity) & CHECK_ABORT))
|
||||
{
|
||||
// XXX: This has no purpose for SuperMelee
|
||||
// In full-game, the sole purpose of this is to record the crew
|
||||
// left in the last ship standing. The crew left is first recorded
|
||||
// into STARSHIP.crew_level just a few lines above here.
|
||||
// Encounter battle in full game.
|
||||
// Record the crew left in the last ship standing. The crew left
|
||||
// is first recorded into STARSHIP.crew_level just a few lines
|
||||
// above here.
|
||||
for (i = NUM_PLAYERS - 1; i >= 0; --i)
|
||||
{
|
||||
if (SPtr[i])
|
||||
GetEncounterStarShip (SPtr[i], i);
|
||||
if (SPtr[i] && !FleetIsInfinite (i))
|
||||
UpdateShipFragCrew (SPtr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+60
-122
@@ -23,6 +23,7 @@
|
||||
#include "controls.h"
|
||||
#include "menustat.h"
|
||||
#include "supermelee/pickmele.h"
|
||||
#include "encount.h"
|
||||
#include "battle.h"
|
||||
#include "races.h"
|
||||
#include "resinst.h"
|
||||
@@ -290,7 +291,9 @@ OldContext = SetContext (SpaceContext);
|
||||
if (hBattleShip)
|
||||
{
|
||||
if (hBattleShip == GetTailLink (&race_q[0]))
|
||||
battle_counter[0] = 1;
|
||||
{ // Player chose SIS. There will be no more choices.
|
||||
battle_counter[RPG_PLAYER_NUM] = 1;
|
||||
}
|
||||
|
||||
WaitForSoundEnd (0);
|
||||
}
|
||||
@@ -302,154 +305,89 @@ SetContext (OldContext);
|
||||
return (hBattleShip);
|
||||
}
|
||||
|
||||
static QUEUE *
|
||||
GetShipQueueForSide (COUNT sideNr)
|
||||
{
|
||||
if (sideNr == 0)
|
||||
return &GLOBAL (built_ship_q);
|
||||
else
|
||||
return &GLOBAL (npc_built_ship_q);
|
||||
}
|
||||
|
||||
// Get the next ship to use.
|
||||
HSTARSHIP
|
||||
GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
||||
{
|
||||
HSTARSHIP hBattleShip;
|
||||
|
||||
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
|
||||
{
|
||||
// Get the next ship from the battle group.
|
||||
hBattleShip = GetHeadLink (&race_q[which_player]);
|
||||
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 (!(GLOBAL (CurrentActivity) & IN_BATTLE))
|
||||
{
|
||||
// XXX: This check is needed, because UninitShips() calls
|
||||
// this function after the battle is over to record
|
||||
// the crew left in the last ship standing.
|
||||
hBattleShip = 0;
|
||||
}
|
||||
else if (!MeleeShipDeath (LastStarShipPtr, which_player))
|
||||
hBattleShip = 0;
|
||||
// Game over.
|
||||
else
|
||||
{
|
||||
if (!GetNextMeleeStarShip (which_player, &hBattleShip))
|
||||
hBattleShip = 0;
|
||||
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.
|
||||
HSHIPFRAG hStarShip;
|
||||
SHIP_FRAGMENT *FragPtr;
|
||||
|
||||
if (LastStarShipPtr == 0)
|
||||
{
|
||||
// First time picking a ship.
|
||||
if (which_player == 0 && battle_counter[0] > 1)
|
||||
{
|
||||
// The player in a full game, still having a ship left.
|
||||
hBattleShip = GetArmadaStarShip ();
|
||||
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
|
||||
{
|
||||
hBattleShip = GetHeadLink (&race_q[which_player]);
|
||||
if (which_player == 1)
|
||||
{
|
||||
// Select the next ship for the computer.
|
||||
hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q));
|
||||
FragPtr = LockShipFrag (&GLOBAL (npc_built_ship_q),
|
||||
hStarShip);
|
||||
if (FragPtr->crew_level == INFINITE_FLEET)
|
||||
{
|
||||
// Infinite number of ships.
|
||||
battle_counter[1]++;
|
||||
}
|
||||
UnlockShipFrag (&GLOBAL (npc_built_ship_q), hStarShip);
|
||||
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
|
||||
{
|
||||
QUEUE *pQueue;
|
||||
HSHIPFRAG hNextShip;
|
||||
|
||||
pQueue = GetShipQueueForSide (which_player);
|
||||
|
||||
hBattleShip = GetHeadLink (&race_q[which_player]);
|
||||
for (hStarShip = GetHeadLink (pQueue);
|
||||
hStarShip != 0; hStarShip = hNextShip)
|
||||
{ // NPC player in a full game
|
||||
if (FleetIsInfinite (which_player))
|
||||
{
|
||||
STARSHIP *SPtr;
|
||||
|
||||
SPtr = LockStarShip (&race_q[which_player], hBattleShip);
|
||||
hNextShip = _GetSuccLink (SPtr);
|
||||
UnlockStarShip (&race_q[which_player], hBattleShip);
|
||||
hBattleShip = hNextShip;
|
||||
|
||||
FragPtr = LockShipFrag (pQueue, hStarShip);
|
||||
if (SPtr == LastStarShipPtr)
|
||||
{
|
||||
if (FragPtr->crew_level != INFINITE_FLEET)
|
||||
{
|
||||
/* Record crew left after the battle */
|
||||
FragPtr->crew_level = SPtr->crew_level;
|
||||
if (GLOBAL (CurrentActivity) & IN_BATTLE)
|
||||
SPtr->SpeciesID = NO_ID;
|
||||
// deactivates the ship
|
||||
}
|
||||
else /* if infinite ships */
|
||||
{
|
||||
hBattleShip = GetTailLink (&race_q[which_player]);
|
||||
/* 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 */
|
||||
SPtr->crew_level = FragPtr->max_crew;
|
||||
SPtr->playerNr = which_player;
|
||||
SPtr->captains_name_index = PickCaptainName ();
|
||||
|
||||
battle_counter[1]++;
|
||||
}
|
||||
UnlockShipFrag (pQueue, hStarShip);
|
||||
break;
|
||||
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 ();
|
||||
}
|
||||
hNextShip = _GetSuccLink (FragPtr);
|
||||
UnlockShipFrag (pQueue, hStarShip);
|
||||
battle_counter[which_player]++;
|
||||
|
||||
return GetHeadLink (&race_q[which_player]);
|
||||
}
|
||||
|
||||
if (which_player == 0)
|
||||
{
|
||||
// Player in a full game.
|
||||
if (battle_counter[0])
|
||||
hBattleShip = GetArmadaStarShip ();
|
||||
else /* last ship was flagship */
|
||||
{
|
||||
#define RUN_AWAY_FUEL_COST (5 * FUEL_TANK_SCALE)
|
||||
hBattleShip = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
|
||||
return (hBattleShip);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -682,24 +682,17 @@ MeleeGameOver (void)
|
||||
LockMutex (GraphicsLock);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MeleeShipDeath (STARSHIP *ship, COUNT which_player) {
|
||||
void
|
||||
MeleeShipDeath (STARSHIP *ship)
|
||||
{
|
||||
FRAME frame;
|
||||
|
||||
// Deactivate fleet position.
|
||||
ship->SpeciesID = NO_ID;
|
||||
|
||||
frame = SetAbsFrameIndex (PickMeleeFrame, which_player);
|
||||
frame = SetAbsFrameIndex (PickMeleeFrame, ship->playerNr);
|
||||
CrossOutShip (frame, ship->index);
|
||||
UpdatePickMeleeFleetValue (frame, which_player);
|
||||
|
||||
if (battle_counter[0] == 0 || battle_counter[1] == 0)
|
||||
{
|
||||
// One side is out of ships. Game over.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
UpdatePickMeleeFleetValue (frame, ship->playerNr);
|
||||
}
|
||||
|
||||
// Post: the NetState for all players is NetState_interBattle
|
||||
|
||||
@@ -24,7 +24,7 @@ typedef struct getmelee_struct GETMELEE_STATE;
|
||||
#include "meleesetup.h"
|
||||
#include "libs/compiler.h"
|
||||
|
||||
BOOLEAN MeleeShipDeath (STARSHIP *ship, COUNT which_player);
|
||||
void MeleeShipDeath (STARSHIP *);
|
||||
void BuildPickMeleeFrame (void);
|
||||
void DestroyPickMeleeFrame (void);
|
||||
void FillPickMeleeFrame (MeleeSetup *setup);
|
||||
|
||||
+15
-1
@@ -27,6 +27,7 @@
|
||||
#include "status.h"
|
||||
#include "battle.h"
|
||||
#include "init.h"
|
||||
#include "supermelee/pickmele.h"
|
||||
#ifdef NETPLAY
|
||||
# include "supermelee/netplay/netmelee.h"
|
||||
# include "supermelee/netplay/netmisc.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
# include "supermelee/netplay/packetq.h"
|
||||
#endif
|
||||
#include "races.h"
|
||||
#include "encount.h"
|
||||
#include "settings.h"
|
||||
#include "sounds.h"
|
||||
#include "libs/mathlib.h"
|
||||
@@ -279,7 +281,7 @@ new_ship (ELEMENT *DeadShipPtr)
|
||||
if (DeadStarShipPtr->crew_level)
|
||||
{
|
||||
// We've just warped out. new_ship() will still be called
|
||||
// a few times, to process the trace left behind (I assume).
|
||||
// a few times, as for any "dead" ship.
|
||||
StopMusic ();
|
||||
|
||||
// Even after much investigation, I could find no purpose for
|
||||
@@ -339,6 +341,8 @@ new_ship (ELEMENT *DeadShipPtr)
|
||||
UnlockElement (hElement);
|
||||
}
|
||||
|
||||
// The ship will be "alive" for at least 2 more frames to make sure
|
||||
// the elements it owns (set up for deletion above) expire first.
|
||||
DeadShipPtr->life_span =
|
||||
MusicStarted ? (ONE_SECOND * 3) / BATTLE_FRAME_RATE : 1;
|
||||
DeadShipPtr->death_func = new_ship;
|
||||
@@ -391,6 +395,13 @@ new_ship (ELEMENT *DeadShipPtr)
|
||||
}
|
||||
#endif /* NETPLAY */
|
||||
|
||||
if (!FleetIsInfinite (DeadStarShipPtr->playerNr))
|
||||
{ // This may be a dead ship (crew_level == 0) or a warped out ship
|
||||
UpdateShipFragCrew (DeadStarShipPtr);
|
||||
// Deactivate the ship (cannot be selected)
|
||||
DeadStarShipPtr->SpeciesID = NO_ID;
|
||||
}
|
||||
|
||||
if (GetNextStarShip (DeadStarShipPtr, DeadStarShipPtr->playerNr))
|
||||
{
|
||||
#ifdef NETPLAY
|
||||
@@ -574,6 +585,9 @@ ship_death (ELEMENT *ShipPtr)
|
||||
PlaySound (SetAbsSoundIndex (GameSounds, SHIP_EXPLODES),
|
||||
CalcSoundPosition (ShipPtr), ShipPtr, GAME_SOUND_PRIORITY + 1);
|
||||
}
|
||||
|
||||
if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
|
||||
MeleeShipDeath (StarShipPtr);
|
||||
}
|
||||
|
||||
#define START_ION_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A)
|
||||
|
||||
Reference in New Issue
Block a user