Exemple #1
0
// Pre: caller holds the graphics lock.
void
MeleeGameOver (void)
{
	COUNT playerI;
	DWORD TimeOut;
	BOOLEAN PressState, ButtonState;

	// Show the battle result.
	for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
		DrawPickMeleeFrame (playerI);
	

#ifdef NETPLAY
	negotiateReadyConnections(true, NetState_inSetup);
#endif

	TimeOut = GetTimeCounter () + (ONE_SECOND * 4);

	PressState = PulsedInputState.menu[KEY_MENU_SELECT] ||
			PulsedInputState.menu[KEY_MENU_CANCEL];
	do
	{
		UpdateInputState ();
		ButtonState = PulsedInputState.menu[KEY_MENU_SELECT] ||
				PulsedInputState.menu[KEY_MENU_CANCEL];
		if (PressState)
		{
			PressState = ButtonState;
			ButtonState = FALSE;
		}

		Async_process ();
		TaskSwitch ();
	} while (!(GLOBAL (CurrentActivity) & CHECK_ABORT) && (!ButtonState
			&& (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL)
			|| GetTimeCounter () < TimeOut)));

}
Exemple #2
0
BOOLEAN
Battle (BattleFrameCallback *callback)
{
	SIZE num_ships;

	LockMutex (GraphicsLock);

#if !(DEMO_MODE || CREATE_JOURNAL)
	if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) {
		// In Supermelee, the RNG is already initialised.
		TFB_SeedRandom (GetTimeCounter ());
	}
#else /* DEMO_MODE */
	if (BattleSeed == 0)
		BattleSeed = TFB_Random ();
	TFB_SeedRandom (BattleSeed);
	BattleSeed = TFB_Random (); /* get next battle seed */
#endif /* DEMO_MODE */

	BattleSong (FALSE);
	
	num_ships = InitShips ();

	if (instantVictory)
	{
		num_ships = 0;
		battle_counter[0] = 1;
		battle_counter[1] = 0;
		instantVictory = FALSE;
	}
	
	if (num_ships)
	{
		BATTLE_STATE bs;

		GLOBAL (CurrentActivity) |= IN_BATTLE;
		battle_counter[0] = CountLinks (&race_q[0]);
		battle_counter[1] = CountLinks (&race_q[1]);
		
		if (optMeleeScale != TFB_SCALE_STEP)
			SetGraphicScaleMode (optMeleeScale);

		setupBattleInputOrder ();
#ifdef NETPLAY
		initBattleInputBuffers ();
#ifdef NETPLAY_CHECKSUM
		initChecksumBuffers ();
#endif  /* NETPLAY_CHECKSUM */
		battleFrameCount = 0;
		ResetWinnerStarShip ();
		setBattleStateConnections (&bs);
#endif  /* NETPLAY */

		if (!selectAllShips (num_ships)) {
			GLOBAL (CurrentActivity) |= CHECK_ABORT;

			goto AbortBattle;
		}

		BattleSong (TRUE);
		bs.NextTime = 0;
#ifdef NETPLAY
		initBattleStateDataConnections ();
		{
			bool allOk = negotiateReadyConnections (true, NetState_inBattle);
			if (!allOk) {
				GLOBAL (CurrentActivity) |= CHECK_ABORT;
				goto AbortBattle;
			}
		}
#endif  /* NETPLAY */
		bs.InputFunc = DoBattle;
		bs.frame_cb = callback;
		bs.first_time = (BOOLEAN)(LOBYTE (GLOBAL (CurrentActivity)) ==
				IN_HYPERSPACE);

		UnlockMutex (GraphicsLock);
		DoInput (&bs, FALSE);
		LockMutex (GraphicsLock);

AbortBattle:
		if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
		{
			if (GLOBAL (CurrentActivity) & CHECK_ABORT)
			{
				// Do not return to the main menu when a game is aborted,
				// (just to the supermelee menu).
#ifdef NETPLAY
				UnlockMutex (GraphicsLock);
				waitResetConnections(NetState_inSetup);
						// A connection may already be in inSetup (set from
						// GetMeleeStarship). This is not a problem, although
						// it will generate a warning in debug mode.
				LockMutex (GraphicsLock);
#endif

				GLOBAL (CurrentActivity) &= ~CHECK_ABORT;
			}
			else
			{
				// Show the result of the battle.
				MeleeGameOver ();
			}
		}

#ifdef NETPLAY
		uninitBattleInputBuffers();
#ifdef NETPLAY_CHECKSUM
		uninitChecksumBuffers ();
#endif  /* NETPLAY_CHECKSUM */
		setBattleStateConnections (NULL);
#endif  /* NETPLAY */

		StopDitty ();
		StopMusic ();
		StopSound ();
	}

	UninitShips ();
	FreeBattleSong ();

	UnlockMutex (GraphicsLock);
	
	return (BOOLEAN) (num_ships < 0);
}
Exemple #3
0
// This function is called when dead ship element's life_span reaches 0
void
new_ship (ELEMENT *DeadShipPtr)
{
	STARSHIP *DeadStarShipPtr;

	GetElementStarShip (DeadShipPtr, &DeadStarShipPtr);

	if (!readyForBattleEnd ())
	{
		DeadShipPtr->state_flags &= ~DISAPPEARING;
		++DeadShipPtr->life_span;

		// Keep the winner alive longer, or in a simultaneous destruction
		// tie, keep the other dead ship alive so that readyForBattleEnd()
		// is called for only one ship at a time.
		// When a ship has been destroyed, each side of a network
		// connection waits until the other side is ready.
		// When two ships die at the same time, this is handled for one
		// ship after the other.
		checkOtherShipLifeSpan (DeadShipPtr);
		return;
	}

	// Once a ship is being picked, we do not care about the winner anymore
	winnerStarShip = NULL;

	{
		BOOLEAN RestartMusic;

		StopDitty ();
		StopMusic ();
		StopSound ();

		SetElementStarShip (DeadShipPtr, 0);
		RestartMusic = OpponentAlive (DeadStarShipPtr);

		if (DeadStarShipPtr->RaceDescPtr->uninit_func != NULL)
			(*DeadStarShipPtr->RaceDescPtr->uninit_func) (
					DeadStarShipPtr->RaceDescPtr);
		free_ship (DeadStarShipPtr->RaceDescPtr, TRUE, TRUE);
		DeadStarShipPtr->RaceDescPtr = 0;
		
		// Graphics are batched while the draw queue is processed,
		// but we are going to draw the ship selection box now
		UnbatchGraphics ();

#ifdef NETPLAY
		initBattleStateDataConnections ();
		{
			bool allOk =
					negotiateReadyConnections (true, NetState_interBattle);
					// We are already in NetState_interBattle, but all
					// sides just need to pass this checkpoint before
					// going on.
			if (!allOk)
			{
				// Some network connection has been reset.
				GLOBAL (CurrentActivity) &= ~IN_BATTLE;
				BatchGraphics ();
				return;
			}
		}
#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
			{
				bool allOk =
						negotiateReadyConnections (true, NetState_inBattle);
				if (!allOk)
				{
					// Some network connection has been reset.
					GLOBAL (CurrentActivity) &= ~IN_BATTLE;
					BatchGraphics ();
					return;
				}
			}
#endif
			if (RestartMusic)
				BattleSong (TRUE);
		}
		else if (battle_counter[0] == 0 || battle_counter[1] == 0)
		{
			// One player is out of ships. The battle is over.
			GLOBAL (CurrentActivity) &= ~IN_BATTLE;
		}
#ifdef NETPLAY
		else
		{
			// Battle has been aborted.
			GLOBAL (CurrentActivity) |= CHECK_ABORT;
		}
#endif
		BatchGraphics ();
	}
}
Exemple #4
0
// Post: the NetState for all players is NetState_interBattle
static BOOLEAN
GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
{
	COUNT playerI;
	BOOLEAN ok;
	GETMELEE_STATE gmstate;
	TimeCount now;
	COUNT i;

#ifdef NETPLAY
	for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
	{
		NetConnection *conn;

		if ((playerMask & (1 << playerI)) == 0)
			continue;

		// XXX: This does not have to be done per connection.
		conn = netConnections[playerI];
		if (conn != NULL) {
			BattleStateData *battleStateData;
			battleStateData =
					(BattleStateData *) NetConnection_getStateData (conn);
			battleStateData->getMeleeState = &gmstate;
		}
	}
#endif
	
	ok = true;

	now = GetTimeCounter ();
	gmstate.InputFunc = DoGetMelee;
	gmstate.Initialized = FALSE;
	for (i = 0; i < NUM_PLAYERS; ++i)
	{
		// We have to use TFB_Random() results in specific order
		playerI = GetPlayerOrder (i);
		gmstate.player[playerI].selecting =
				(playerMask & (1 << playerI)) != 0;
		gmstate.player[playerI].ships_left = battle_counter[playerI];

		// We determine in advance which ship would be chosen if the player
		// wants a random ship, to keep it simple to keep network parties
		// synchronised.
		gmstate.player[playerI].randomIndex =
				(COUNT)TFB_Random () % gmstate.player[playerI].ships_left;
		gmstate.player[playerI].done = FALSE;

		if (!gmstate.player[playerI].selecting)
			continue;

		gmstate.player[playerI].timeIn = now;
		gmstate.player[playerI].row = 0;
		gmstate.player[playerI].col = NUM_PICKMELEE_COLUMNS;
#ifdef NETPLAY
		gmstate.player[playerI].remoteSelected = FALSE;
#endif

		gmstate.player[playerI].flashContext =
				Flash_createHighlight (ScreenContext, NULL);
		Flash_setMergeFactors (gmstate.player[playerI].flashContext,
				2, 3, 2);
		Flash_setFrameTime (gmstate.player[playerI].flashContext,
				ONE_SECOND / 16);
#ifdef NETPLAY
		if (PlayerControl[playerI] & NETWORK_CONTROL)
			Flash_setSpeed (gmstate.player[playerI].flashContext,
					ONE_SECOND / 2, 0, ONE_SECOND / 2, 0);
		else
#endif
		{
			Flash_setSpeed (gmstate.player[playerI].flashContext,
					0, ONE_SECOND / 16, 0, ONE_SECOND / 16);
		}
		PickMelee_ChangedSelection (&gmstate, playerI);
		Flash_start (gmstate.player[playerI].flashContext);
	}

#ifdef NETPLAY
	{
		// NB. gmstate.player[].randomIndex and gmstate.player[].done must
		// be initialised before negotiateReadyConnections is completed, to
		// ensure that they are initialised when the SelectShip packet
		// arrives.
		bool allOk = negotiateReadyConnections (true, NetState_selectShip);
		if (!allOk)
		{
			// Some network connection has been reset.
			ok = false;
		}
	}
#endif
	SetDefaultMenuRepeatDelay ();
	
	SetContext (OffScreenContext);


	DoInput (&gmstate, FALSE);
	WaitForSoundEnd (0);


	for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
	{
		if (!gmstate.player[playerI].selecting)
			continue;
		
		if (gmstate.player[playerI].done)
		{
			// Flash rectangle is already terminated.
			ships[playerI] = gmstate.player[playerI].hBattleShip;
		}
		else
		{
			Flash_terminate (gmstate.player[playerI].flashContext);
			gmstate.player[playerI].flashContext = NULL;
			ok = false;
		}
	}

#ifdef NETPLAY
	if (ok)
	{
		if (!negotiateReadyConnections (true, NetState_interBattle))
			ok = false;
	}
	else
		setStateConnections (NetState_interBattle);
#endif

	if (!ok)
	{
		// Aborting.
		GLOBAL (CurrentActivity) &= ~IN_BATTLE;
	}

#ifdef NETPLAY
	for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
	{
		NetConnection *conn;

		if ((playerMask & (1 << playerI)) == 0)
			continue;

		// XXX: This does not have to be done per connection.
		conn = netConnections[playerI];
		if (conn != NULL && NetConnection_isConnected (conn))
		{
			BattleStateData *battleStateData;
			battleStateData =
					(BattleStateData *) NetConnection_getStateData (conn);
			battleStateData->getMeleeState = NULL;
		}
	}
#endif

	return ok;
}