Beispiel #1
0
//*****************************************************************************
//
void LASTMANSTANDING_TimeExpired( void )
{
	LONG				lHighestHealth = 0;
	bool				bTie = false;
	bool				bFoundPlayer = false;
	LONG				lWinner = -1;
	DHUDMessageFadeOut	*pMsg;
	char				szString[64];

	// Don't end the level if we're not in a game.
	if ( LASTMANSTANDING_GetState( ) != LMSS_INPROGRESS )
		return;

	// Try to find the player with the highest health.
	if ( lastmanstanding )
	{
		TArray<ULONG> possibleWinners;
		for ( unsigned int i = 0; i < MAXPLAYERS; ++i )
			possibleWinners.Push ( i );

		// [BB] Find the player with the most lives left.
		PLAYER_SelectPlayersWithHighestValue ( PLAYER_GetLivesLeft, possibleWinners );
		// [BB] If more than one player has the most lives left, select the player with the highest lives.
		if ( possibleWinners.Size() != 1 )
			PLAYER_SelectPlayersWithHighestValue ( PLAYER_GetHealth, possibleWinners );

		// [BB] If more then one player have the most lives and also the same health, then the game it a tie.
		if ( possibleWinners.Size() == 1 )
			lWinner = possibleWinners[0];
		else
		{
			lWinner = MAXPLAYERS;
			bTie = true;
		}
	}
	else if ( teamlms )
	{
		if ( LASTMANSTANDING_TeamsWithAlivePlayersOn( ) == 1 )
		{
			for ( ULONG i = 0; i < teams.Size( ); i++ )
			{
				if ( TEAM_CountLivingAndRespawnablePlayers( i ) )
					lWinner = i;
			}
		}
		else
		{
			lWinner = teams.Size( );
			bTie = true;
		}
	}

	// If for some reason we don't have any players, just end the map like normal.
	if ( lWinner == -1 )
	{
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
			SERVER_Printf( PRINT_HIGH, "%s\n", GStrings( "TXT_TIMELIMIT" ));
		else
			Printf( "%s\n", GStrings( "TXT_TIMELIMIT" ));

		GAME_SetEndLevelDelay( 5 * TICRATE );
		return;
	}

	// If there was a tie, then go into sudden death!
	if ( bTie )
	{
		// Only print the message the instant we reach sudden death.
		if ( level.time == (int)( timelimit * TICRATE * 60 ))
		{
			sprintf( szString, "\\cdSUDDEN DEATH!" );
			V_ColorizeString( szString );

			if ( NETWORK_GetState( ) != NETSTATE_SERVER )
			{
				// Display the HUD message.
				pMsg = new DHUDMessageFadeOut( BigFont, szString,
					160.4f,
					75.0f,
					320,
					200,
					CR_RED,
					3.0f,
					2.0f );

				StatusBar->AttachMessage( pMsg, MAKE_ID('C','N','T','R') );
			}
			else
			{
				SERVERCOMMANDS_PrintHUDMessageFadeOut( szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f, "BigFont", false, MAKE_ID('C','N','T','R') );
			}
		}

		return;
	}

	// Also, do the win sequence for the player.
	LASTMANSTANDING_DoWinSequence( lWinner );

	// Give the winner a win.
	if ( lastmanstanding )
		PLAYER_SetWins( &players[lWinner], players[lWinner].ulWins + 1 );
	// [BB] In a team game of course give the win to the winning team.
	if ( teamlms )
		TEAM_SetWinCount( lWinner, TEAM_GetWinCount( lWinner ) + 1, false );

	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		SERVER_Printf( PRINT_HIGH, "%s\n", GStrings( "TXT_TIMELIMIT" ));
	else
		Printf( "%s\n", GStrings( "TXT_TIMELIMIT" ));

	GAME_SetEndLevelDelay( 5 * TICRATE );
}
Beispiel #2
0
//*****************************************************************************
//
void LASTMANSTANDING_Tick( void )
{
	// Not in LMS mode.
	if (( lastmanstanding == false ) && ( teamlms == false ))
		return;

	switch ( g_LMSState )
	{
	case LMSS_WAITINGFORPLAYERS:

		if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
			( CLIENTDEMO_IsPlaying( )))
		{
			break;
		}

		if ( lastmanstanding )
		{
			// Two players are here now, being the countdown!
			if ( GAME_CountActivePlayers( ) >= 2 )
			{
				if ( sv_lmscountdowntime > 0 )
					LASTMANSTANDING_StartCountdown(( sv_lmscountdowntime * TICRATE ) - 1 );
				else
					LASTMANSTANDING_StartCountdown(( 10 * TICRATE ) - 1 );
			}
		}

		if ( teamlms )
		{
			if ( TEAM_TeamsWithPlayersOn( ) > 1 )
			{
				if ( sv_lmscountdowntime > 0 )
					LASTMANSTANDING_StartCountdown(( sv_lmscountdowntime * TICRATE ) - 1 );
				else
					LASTMANSTANDING_StartCountdown(( 10 * TICRATE ) - 1 );
			}
		}
		break;
	case LMSS_COUNTDOWN:

		if ( g_ulLMSCountdownTicks )
		{
			g_ulLMSCountdownTicks--;

			// FIGHT!
			if (( g_ulLMSCountdownTicks == 0 ) &&
				( NETWORK_GetState( ) != NETSTATE_CLIENT ) &&
				( CLIENTDEMO_IsPlaying( ) == false ))
			{
				LASTMANSTANDING_DoFight( );
			}
			// Play "3... 2... 1..." sounds.
			else if ( g_ulLMSCountdownTicks == ( 3 * TICRATE ))
				ANNOUNCER_PlayEntry( cl_announcer, "Three" );
			else if ( g_ulLMSCountdownTicks == ( 2 * TICRATE ))
				ANNOUNCER_PlayEntry( cl_announcer, "Two" );
			else if ( g_ulLMSCountdownTicks == ( 1 * TICRATE ))
				ANNOUNCER_PlayEntry( cl_announcer, "One" );
		}
		break;
	case LMSS_INPROGRESS:

		if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
			( CLIENTDEMO_IsPlaying( )))
		{
			break;
		}

		// Check to see how many men are left standing.
		if ( lastmanstanding )
		{
			// If only one man is left standing, somebody just won!
			if ( GAME_CountLivingAndRespawnablePlayers( ) == 1 )
			{
				LONG	lWinner;

				lWinner = LASTMANSTANDING_GetLastManStanding( );
				if ( lWinner != -1 )
				{
					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
						SERVER_Printf( PRINT_HIGH, "%s \\c-wins!\n", players[lWinner].userinfo.netname );
					else
					{
						Printf( "%s \\c-wins!\n", players[lWinner].userinfo.netname );

						if ( lWinner == consoleplayer )
							ANNOUNCER_PlayEntry( cl_announcer, "YouWin" );
					}

					// Give the winner a win.
					PLAYER_SetWins( &players[lWinner], players[lWinner].ulWins + 1 );

					// Pause for five seconds for the win sequence.
					LASTMANSTANDING_DoWinSequence( lWinner );
					GAME_SetEndLevelDelay( 5 * TICRATE );
				}
			}
			// If NOBODY is left standing, it's a draw game!
			else if ( GAME_CountLivingAndRespawnablePlayers( ) == 0 )
			{
				ULONG	ulIdx;

				for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ )
				{
					if (( playeringame[ulIdx] ) && ( PLAYER_IsTrueSpectator( &players[ulIdx] ) == false ))
						break;
				}

				if ( ulIdx != MAXPLAYERS )
				{
					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
						SERVER_Printf( PRINT_HIGH, "DRAW GAME!\n" );
					else
						Printf( "DRAW GAME!\n" );

					// Pause for five seconds for the win sequence.
					LASTMANSTANDING_DoWinSequence( MAXPLAYERS );
					GAME_SetEndLevelDelay( 5 * TICRATE );
				}
			}
		}

		// Check to see how many men are left standing on each team.
		if ( teamlms )
		{
			if ( LASTMANSTANDING_TeamsWithAlivePlayersOn( ) <= 1)
			{
				LONG	lWinner;

				lWinner = LASTMANSTANDING_TeamGetLastManStanding( );
				if ( lWinner != -1 )
				{
					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
						SERVER_Printf( PRINT_HIGH, "%s \\c-wins!\n", TEAM_GetName( lWinner ));
					else
					{
						Printf( "%s \\c-wins!\n", TEAM_GetName( lWinner ));

						if ( players[consoleplayer].bOnTeam && ( lWinner == (LONG)players[consoleplayer].ulTeam ))
							ANNOUNCER_PlayEntry( cl_announcer, "YouWin" );
					}

					// Give the team a win.
					TEAM_SetWinCount( lWinner, TEAM_GetWinCount( lWinner ) + 1, false );

					// [BB] Every player who is still alive also gets a win.
					for ( ULONG ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ )
					{
						if ( playeringame[ulIdx] && ( players[ulIdx].bOnTeam ) && ( players[ulIdx].bSpectating == false ) && PLAYER_IsAliveOrCanRespawn ( &players[ulIdx] ) )
							PLAYER_SetWins( &players[ulIdx], players[ulIdx].ulWins + 1 );
					}

					// Pause for five seconds for the win sequence.
					LASTMANSTANDING_DoWinSequence( lWinner );
					GAME_SetEndLevelDelay( 5 * TICRATE );
				}
				// If NOBODY is left standing, it's a draw game!
				else
				{
					ULONG	ulIdx;

					for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ )
					{
						if (( playeringame[ulIdx] ) && ( PLAYER_IsTrueSpectator( &players[ulIdx] ) == false ))
							break;
					}

					if ( ulIdx != MAXPLAYERS )
					{
						if ( NETWORK_GetState( ) == NETSTATE_SERVER )
							SERVER_Printf( PRINT_HIGH, "DRAW GAME!\n" );
						else
							Printf( "DRAW GAME!\n" );

						// Pause for five seconds for the win sequence.
						LASTMANSTANDING_DoWinSequence( teams.Size( ) );
						GAME_SetEndLevelDelay( 5 * TICRATE );
					}
				}
			}
		}
		break;
	default:
		break;
	}
}
Beispiel #3
0
//*****************************************************************************
//
void JOINQUEUE_PopQueue( LONG lNumSlots )
{
	ULONG	ulIdx;

	// Nothing to do if there's nobody waiting in the queue.
	if ( g_lJoinQueue[0].ulPlayer == MAXPLAYERS )
		return;

	// [BB] Players are not allowed to join.
	if ( GAMEMODE_PreventPlayersFromJoining() )
		return;

	// Try to find the next person in line.
	ulIdx = 0;
	while ( 1 )
	{
		// Found end of list.
		if (( ulIdx == MAXPLAYERS ) ||
			( g_lJoinQueue[ulIdx].ulPlayer == MAXPLAYERS ) ||
			( lNumSlots == 0 ))
		{
			break;
		}

		// [BB] Since we possibly just let somebody waiting in line join, check if more persons are allowed to join now.
		if ( GAMEMODE_PreventPlayersFromJoining() )
			break;

		// Found a player waiting in line. They will now join the game!
		if ( playeringame[g_lJoinQueue[ulIdx].ulPlayer] )
		{
			// [K6] Reset their AFK timer now - they may have been waiting in the queue silently and we don't want to kick them.
			SERVER_GetClient( g_lJoinQueue[ulIdx].ulPlayer )->lLastActionTic = gametic;
			PLAYER_SpectatorJoinsGame ( &players[g_lJoinQueue[ulIdx].ulPlayer] );

			// [BB/Spleen] The "lag interval" is only half of the "spectate info send" interval. Account for this here.
			if (( gametic - SERVER_GetClient( g_lJoinQueue[ulIdx].ulPlayer )->ulLastCommandTic ) <= 2*TICRATE )
				SERVER_GetClient( g_lJoinQueue[ulIdx].ulPlayer )->ulClientGameTic +=
				( gametic - SERVER_GetClient( g_lJoinQueue[ulIdx].ulPlayer )->ulLastCommandTic );

			if ( GAMEMODE_GetFlags( GAMEMODE_GetCurrentMode( )) & GMF_PLAYERSONTEAMS )
			{
				if ( TEAM_CheckIfValid ( g_lJoinQueue[ulIdx].ulTeam ) )
					PLAYER_SetTeam( &players[g_lJoinQueue[ulIdx].ulPlayer], g_lJoinQueue[ulIdx].ulTeam, true );
				else
					PLAYER_SetTeam( &players[g_lJoinQueue[ulIdx].ulPlayer], TEAM_ChooseBestTeamForPlayer( ), true );
			}

			// Begin the duel countdown.
			if ( duel )
			{
				// [BB] Skip countdown and map reset if the map is supposed to be a lobby.
				if ( GAMEMODE_IsLobbyMap( ) )
					DUEL_SetState( DS_INDUEL );
				else if ( sv_duelcountdowntime > 0 )
					DUEL_StartCountdown(( sv_duelcountdowntime * TICRATE ) - 1 );
				else
					DUEL_StartCountdown(( 10 * TICRATE ) - 1 );
			}
			// Begin the LMS countdown.
			else if ( lastmanstanding )
			{
				if ( sv_lmscountdowntime > 0 )
					LASTMANSTANDING_StartCountdown(( sv_lmscountdowntime * TICRATE ) - 1 );
				else
					LASTMANSTANDING_StartCountdown(( 10 * TICRATE ) - 1 );
			}
			else
			{
				if ( NETWORK_GetState( ) == NETSTATE_SERVER )
					SERVER_Printf( PRINT_HIGH, "%s \\c-joined the game.\n", players[g_lJoinQueue[ulIdx].ulPlayer].userinfo.netname );
				else
					Printf( "%s \\c-joined the game.\n", players[g_lJoinQueue[ulIdx].ulPlayer].userinfo.netname );
			}

			JOINQUEUE_RemovePlayerAtPosition ( ulIdx );

			if ( lNumSlots > 0 )
				lNumSlots--;
		}
		else
			ulIdx++;
	}

	// If we're the server, tell everyone their new position in line.
	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		SERVERCOMMANDS_SetQueuePosition( );
}
Beispiel #4
0
//*****************************************************************************
//
void JOINQUEUE_PlayerLeftGame( bool bWantPop )
{
	bool	bPop = true;

	// If we're in a duel, revert to the "waiting for players" state.
	// [BB] But only do so if there are less then two duelers left (probably JOINQUEUE_PlayerLeftGame was called mistakenly).
	if ( duel && ( DUEL_CountActiveDuelers( ) < 2 ) )
		DUEL_SetState( DS_WAITINGFORPLAYERS );

	// If only one (or zero) person is left, go back to "waiting for players".
	if ( lastmanstanding )
	{
		// Someone just won by default!
		if (( GAME_CountLivingAndRespawnablePlayers( ) == 1 ) && ( LASTMANSTANDING_GetState( ) == LMSS_INPROGRESS ))
		{
			LONG	lWinner;

			lWinner = LASTMANSTANDING_GetLastManStanding( );
			if ( lWinner != -1 )
			{
				if ( NETWORK_GetState( ) == NETSTATE_SERVER )
					SERVER_Printf( PRINT_HIGH, "%s \\c-wins!\n", players[lWinner].userinfo.netname );
				else
				{
					Printf( "%s \\c-wins!\n", players[lWinner].userinfo.netname );

					if ( lWinner == consoleplayer )
						ANNOUNCER_PlayEntry( cl_announcer, "YouWin" );
				}

				// Give the winner a win.
				PLAYER_SetWins( &players[lWinner], players[lWinner].ulWins + 1 );

				// Pause for five seconds for the win sequence.
				LASTMANSTANDING_DoWinSequence( lWinner );
			}

			// Join queue will be popped upon state change.
			bPop = false;

			GAME_SetEndLevelDelay( 5 * TICRATE );
		}
		else if ( SERVER_CalcNumNonSpectatingPlayers( MAXPLAYERS ) <= 1 )
			LASTMANSTANDING_SetState( LMSS_WAITINGFORPLAYERS );
	}

	if ( teamlms )
	{
		// Someone just won by default!
		if (( LASTMANSTANDING_GetState( ) == LMSS_INPROGRESS ) && LASTMANSTANDING_TeamsWithAlivePlayersOn( ) <= 1)
		{
			LONG	lWinner;

			lWinner = LASTMANSTANDING_TeamGetLastManStanding( );
			if ( lWinner != -1 )
			{
				if ( NETWORK_GetState( ) == NETSTATE_SERVER )
					SERVER_Printf( PRINT_HIGH, "%s \\c-wins!\n", TEAM_GetName( lWinner ));
				else
				{
					Printf( "%s \\c-wins!\n", TEAM_GetName( lWinner ));

					if ( players[consoleplayer].bOnTeam && ( lWinner == (LONG)players[consoleplayer].ulTeam ))
						ANNOUNCER_PlayEntry( cl_announcer, "YouWin" );
				}

				// Give the team a win.
				TEAM_SetWinCount( lWinner, TEAM_GetWinCount( lWinner ) + 1, false );

				// Pause for five seconds for the win sequence.
				LASTMANSTANDING_DoWinSequence( lWinner );
			}

			// Join queue will be popped upon state change.
			bPop = false;

			GAME_SetEndLevelDelay( 5 * TICRATE );
		}
		else if ( TEAM_TeamsWithPlayersOn( ) <= 1 )
			LASTMANSTANDING_SetState( LMSS_WAITINGFORPLAYERS );
	}

	// If we're in possession mode, revert to the "waiting for players" state
	// [BB] when there are less than two players now.
	if ( possession && ( SERVER_CalcNumNonSpectatingPlayers( MAXPLAYERS ) < 2 ))
		POSSESSION_SetState( PSNS_WAITINGFORPLAYERS );

	if ( teampossession && ( TEAM_TeamsWithPlayersOn( ) <= 1 ) )
		POSSESSION_SetState( PSNS_WAITINGFORPLAYERS );

	// If we're in invasion mode, revert to the "waiting for players" state.
	if ( invasion && ( SERVER_CalcNumNonSpectatingPlayers( MAXPLAYERS ) < 1 ))
		INVASION_SetState( IS_WAITINGFORPLAYERS );

	// If we're in survival co-op mode, revert to the "waiting for players" state.
	if ( survival && ( SERVER_CalcNumNonSpectatingPlayers( MAXPLAYERS ) < 1 ))
		SURVIVAL_SetState( SURVS_WAITINGFORPLAYERS );

	// Potentially let one person join the game.
	if ( bPop && bWantPop )
		JOINQUEUE_PopQueue( 1 );
}
Beispiel #5
0
//*****************************************************************************
//
bool CALLVOTE_VoteNo( ULONG ulPlayer )
{
	ULONG	ulIdx;
	ULONG	ulNumYes;
	ULONG	ulNumNo;

	// Don't allow the vote unless we're in the middle of a vote.
	if ( g_VoteState != VOTESTATE_INVOTE )
		return ( false );

	// [RC] If this is our vote, hide the vote screen soon.
	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) && ( static_cast<LONG>(ulPlayer) == consoleplayer ) )
		g_ulShowVoteScreenTicks = 1 * TICRATE;

	// [RC] Vote callers can cancel their votes by voting "no".
	if ( ulPlayer == g_ulVoteCaller && ( NETWORK_GetState( ) == NETSTATE_SERVER ))
	{
		// [BB] If a player canceled his own vote, don't prevent others from making this type of vote again.
		g_PreviousVotes.back( ).ulVoteType = NUM_VOTECMDS;

		SERVER_Printf( PRINT_HIGH, "Vote caller cancelled the vote.\n" );
		g_bVoteCancelled = true;
		g_bVotePassed = false;
		callvote_EndVote( );
		return ( true );
	}

	// Also, don't allow spectator votes if the server has them disabled.
	if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( sv_nocallvote == 2 && players[ulPlayer].bSpectating ))
	{
		SERVER_PrintfPlayer( PRINT_HIGH, ulPlayer, "This server requires spectators to join the game to vote.\n" );
		return false;
	}

	// If this player has already voted, ignore his vote.
	for ( ulIdx = 0; ulIdx < ( MAXPLAYERS / 2 ) + 1; ulIdx++ )
	{
		if ( g_ulPlayersWhoVotedYes[ulIdx] == ulPlayer )
			return ( false );

		if ( g_ulPlayersWhoVotedNo[ulIdx] == ulPlayer )
			return ( false );

		// If this person matches the IP of a person who already voted, don't let him vote.
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		{
			if ( g_ulPlayersWhoVotedYes[ulIdx] < MAXPLAYERS )
			{
				if ( NETWORK_CompareAddress( SERVER_GetClient( g_ulPlayersWhoVotedYes[ulIdx] )->Address, SERVER_GetClient( ulPlayer )->Address, true ))
					return ( false );
			}

			if ( g_ulPlayersWhoVotedNo[ulIdx] < MAXPLAYERS )
			{
				if ( NETWORK_CompareAddress( SERVER_GetClient( g_ulPlayersWhoVotedNo[ulIdx] )->Address, SERVER_GetClient( ulPlayer )->Address, true ))
					return ( false );
			}
		}
	}

	// Add this player's vote.
	for ( ulIdx = 0; ulIdx < ( MAXPLAYERS / 2 ) + 1; ulIdx++ )
	{
		if ( g_ulPlayersWhoVotedNo[ulIdx] == MAXPLAYERS )
		{
			g_ulPlayersWhoVotedNo[ulIdx] = ulPlayer;
			break;
		}
	}

	// Display the message in the console.
	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		Printf( "%s\\c- (%s) votes \"no\".\n", players[ulPlayer].userinfo.netname, NETWORK_AddressToString( SERVER_GetClient( ulPlayer )->Address ));
	else
		Printf( "%s\\c- votes \"no\".\n", players[ulPlayer].userinfo.netname );

	// Nothing more to do here for clients.
	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
		( CLIENTDEMO_IsPlaying( )))
	{
		return ( true );
	}
	
	SERVERCOMMANDS_PlayerVote( ulPlayer, false );

	ulNumYes = callvote_CountPlayersWhoVotedYes( );
	ulNumNo = callvote_CountPlayersWhoVotedNo( );

	// If more than half of the total eligible voters have voted, we must have a majority!
	if ( MAX( ulNumYes, ulNumNo ) > ( CALLVOTE_CountNumEligibleVoters( ) / 2 ))
	{
		g_bVotePassed = ( ulNumYes > ulNumNo );

		callvote_EndVote( );
	}

	return ( true );
}
Beispiel #6
0
void cht_Give (player_t *player, const char *name, int amount)
{
	enum { ALL_NO, ALL_YES, ALL_YESYES } giveall;
	int i;
	const PClass *type;

	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		SERVER_Printf( PRINT_HIGH, "%s is a cheater: give %s\n", player->userinfo.netname, name );
	else if (player != &players[consoleplayer])
		Printf ("%s is a cheater: give %s\n", player->userinfo.netname, name);

	if (player->mo == NULL || player->health <= 0)
	{
		return;
	}

	giveall = ALL_NO;
	if (stricmp (name, "all") == 0)
	{
		giveall = ALL_YES;
	}
	else if (stricmp (name, "everything") == 0)
	{
		giveall = ALL_YESYES;
	}

	if (stricmp (name, "health") == 0)
	{
		if (amount > 0)
		{
			if (player->mo)
			{
				player->mo->health += amount;
	  			player->health = player->mo->health;
			}
			else
			{
				player->health += amount;
			}
		}
		else
		{
			if (player->mo != NULL)
			{
				player->health = player->mo->health = player->mo->GetMaxHealth();
			}
			else
			{
				player->health = deh.GodHealth;
			}
		}
		// [BB]: The server has to inform the clients that this player's health has changed.
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		{
			ULONG playerIdx = static_cast<ULONG> ( player - players );
			SERVERCOMMANDS_SetPlayerHealth( playerIdx );
		}
	}

	if (giveall || stricmp (name, "backpack") == 0)
	{
		// Select the correct type of backpack based on the game
		type = PClass::FindClass(gameinfo.backpacktype);
		if (type != NULL)
		{
			GiveSpawner (player, type, 1);
		}

		if (!giveall)
			return;
	}

	if (giveall || stricmp (name, "ammo") == 0)
	{
		// Find every unique type of ammo. Give it to the player if
		// he doesn't have it already, and set each to its maximum.
		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
		{
			const PClass *type = PClass::m_Types[i];

			if (type->ParentClass == RUNTIME_CLASS(AAmmo))
			{
				AInventory *ammo = player->mo->FindInventory (type);
				if (ammo == NULL)
				{
					ammo = static_cast<AInventory *>(Spawn (type, 0, 0, 0, NO_REPLACE));
					ammo->AttachToOwner (player->mo);
					ammo->Amount = ammo->MaxAmount;
				}
				else if (ammo->Amount < ammo->MaxAmount)
				{
					ammo->Amount = ammo->MaxAmount;
				}
				// [BB] This construction is more or less a hack, but at least the give cheats are now working.
				SERVER_GiveInventoryToPlayer( player, ammo );
			}
		}

		if (!giveall)
			return;
	}

	if (giveall || stricmp (name, "armor") == 0)
	{
		if (gameinfo.gametype != GAME_Hexen)
		{
			ABasicArmorPickup *armor = Spawn<ABasicArmorPickup> (0,0,0, NO_REPLACE);
			armor->SaveAmount = 100*deh.BlueAC;
			armor->SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : FRACUNIT/2;
			if (!armor->CallTryPickup (player->mo))
			{
				armor->Destroy ();
			}
			else
			{
				// [BB] This construction is more or less a hack, but at least the give cheats are now working.
				SERVER_GiveInventoryToPlayer( player, armor );
			}
		}
		else
		{
			for (i = 0; i < 4; ++i)
			{
				AHexenArmor *armor = Spawn<AHexenArmor> (0,0,0, NO_REPLACE);
				armor->health = i;
				armor->Amount = 0;
				if (!armor->CallTryPickup (player->mo))
				{
					armor->Destroy ();
				}
				else
				{
					// [BB] This construction is more or less a hack, but at least the give cheats are now working.
					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
					{
						SERVER_GiveInventoryToPlayer( player, armor );
						SERVERCOMMANDS_SyncHexenArmorSlots ( static_cast<ULONG> ( player - players ) );
					}
				}
			}
		}

		if (!giveall)
			return;
	}

	if (giveall || stricmp (name, "keys") == 0)
	{
		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
		{
			if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
			{
				AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]);
				if (key->KeyNumber != 0)
				{
					key = static_cast<AKey *>(Spawn (PClass::m_Types[i], 0,0,0, NO_REPLACE));
					if (!key->CallTryPickup (player->mo))
					{
						key->Destroy ();
					}
					else
					{
						// [BB] This construction is more or less a hack, but at least the give cheats are now working.
						SERVER_GiveInventoryToPlayer( player, key );
					}
				}
			}
		}
		if (!giveall)
			return;
	}

	if (giveall || stricmp (name, "weapons") == 0 || stricmp (name, "stdweapons") == 0)
	{
		// [BB] Don't give the ST weapons if this it true. Useful if you want
		// to start a game in the middle of a Doom coop megawad for example.
		bool stdweapons = (stricmp (name, "stdweapons") == 0);

		AWeapon *savedpending = player->PendingWeapon;
		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
		{
			type = PClass::m_Types[i];
			// Don't give replaced weapons unless the replacement was done by Dehacked.
			if (type != RUNTIME_CLASS(AWeapon) &&
				type->IsDescendantOf (RUNTIME_CLASS(AWeapon)) &&
				(type->ActorInfo->GetReplacement() == type->ActorInfo ||
				 type->ActorInfo->GetReplacement()->Class->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup))))

			{
				// Give the weapon only if it belongs to the current game or
				// is in a weapon slot. 
				if (type->ActorInfo->GameFilter == GAME_Any || 
					(type->ActorInfo->GameFilter & gameinfo.gametype) ||	
					player->weapons.LocateWeapon(type, NULL, NULL))
				{
				if (stdweapons)
				{
					const char *WeaponName = type->TypeName.GetChars();
					if ( !stricmp (WeaponName, "Railgun")
					     || !stricmp (WeaponName, "Minigun")
					     || !stricmp (WeaponName, "GrenadeLauncher")
					     || !stricmp (WeaponName, "Bfg10K") )
						continue;
				}

					AWeapon *def = (AWeapon*)GetDefaultByType (type);
					if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON))
					{
						GiveSpawner (player, type, 1);
					}
				}
			}
		}
		player->PendingWeapon = savedpending;

		// [BB] If we're the server, also tell the client to restore the original weapon.
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		{
			// [BB] We need to make sure that the client has its old weapon up instantly.
			// Since there is no net command for this and I don't want to add another net command
			// just for this cheat, we use a workaround here.
			const bool playerHasInstantWeapSwitch = !!(player->cheats & CF_INSTANTWEAPSWITCH);
			const ULONG ulPlayer = static_cast<ULONG>( player - players );
			if ( playerHasInstantWeapSwitch == false )
			{
				player->cheats |= CF_INSTANTWEAPSWITCH;
				SERVERCOMMANDS_SetPlayerCheats( ulPlayer );
			}
			SERVERCOMMANDS_WeaponChange( ulPlayer );
			if ( playerHasInstantWeapSwitch == false )
			{
				player->cheats &= ~CF_INSTANTWEAPSWITCH;
				SERVERCOMMANDS_SetPlayerCheats( ulPlayer );
			}
		}

		if (!giveall)
			return;
	}

	if (giveall || stricmp (name, "artifacts") == 0)
	{
		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
		{
			type = PClass::m_Types[i];
			if (type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
			{
				AInventory *def = (AInventory*)GetDefaultByType (type);
				if (def->Icon.isValid() && def->MaxAmount > 1 &&
					!type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)) &&
					!type->IsDescendantOf (RUNTIME_CLASS(APowerup)) &&
					!type->IsDescendantOf (RUNTIME_CLASS(AArmor)))
				{
					GiveSpawner (player, type, amount <= 0 ? def->MaxAmount : amount);
				}
			}
		}
		if (!giveall)
			return;
	}

	if (giveall || stricmp (name, "puzzlepieces") == 0)
	{
		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
		{
			type = PClass::m_Types[i];
			if (type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)))
			{
				AInventory *def = (AInventory*)GetDefaultByType (type);
				if (def->Icon.isValid())
				{
					GiveSpawner (player, type, amount <= 0 ? def->MaxAmount : amount);
				}
			}
		}
		if (!giveall)
			return;
	}

	if (giveall)
		return;

	type = PClass::FindClass (name);
	if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
	{
		if (player == &players[consoleplayer])
			Printf ("Unknown item \"%s\"\n", name);
	}
	else
	{
		GiveSpawner (player, type, amount);
	}
	return;
}
Beispiel #7
0
void cht_DoCheat (player_t *player, int cheat)
{
	static const char * BeholdPowers[9] =
	{
		"PowerInvulnerable",
		"PowerStrength",
		"PowerInvisibility",
		"PowerIronFeet",
		"MapRevealer",
		"PowerLightAmp",
		"PowerShadow",
		"PowerMask",
		"PowerTargeter",
	};
	const PClass *type;
	AInventory *item;
	const char *msg = "";
	char msgbuild[32];
	int i;

	switch (cheat)
	{
	case CHT_IDDQD:
		if (!(player->cheats & CF_GODMODE) && player->playerstate == PST_LIVE)
		{
			if (player->mo)
				player->mo->health = deh.GodHealth;

			player->health = deh.GodHealth;
		}
		// fall through to CHT_GOD
	case CHT_GOD:
		player->cheats ^= CF_GODMODE;
		if (gameinfo.gametype != GAME_Chex)
		{
			if (player->cheats & CF_GODMODE)
				msg = GStrings("STSTR_DQDON");
			else
				msg = GStrings("STSTR_DQDOFF");
		}
		else
		{
			if (player->cheats & CF_GODMODE)
				msg = GStrings("STSTR_CDQDON");
			else
				msg = GStrings("STSTR_CDQDOFF");
		}
		if ( NETWORK_GetState( ) != NETSTATE_SERVER )
			SB_state = screen->GetPageCount ();
		break;

	case CHT_BUDDHA:
		player->cheats ^= CF_BUDDHA;
		if (player->cheats & CF_BUDDHA)
			msg = GStrings("TXT_BUDDHAON");
		else
			msg = GStrings("TXT_BUDDHAOFF");
		break;

	case CHT_NOCLIP:
		player->cheats ^= CF_NOCLIP;
		if (player->cheats & CF_NOCLIP)
			msg = GStrings("STSTR_NCON");
		else
			msg = GStrings("STSTR_NCOFF");
		break;

	case CHT_NOVELOCITY:
		player->cheats ^= CF_NOVELOCITY;
		if (player->cheats & CF_NOVELOCITY)
			msg = GStrings("TXT_LEADBOOTSON");
		else
			msg = GStrings("TXT_LEADBOOTSOFF");
		break;

	case CHT_FLY:
		if (player->mo != NULL)
		{
			player->cheats ^= CF_FLY;
			if (player->cheats & CF_FLY)
			{
				player->mo->flags |= MF_NOGRAVITY;
				player->mo->flags2 |= MF2_FLY;
				msg = GStrings("TXT_LIGHTER");
			}
			else
			{
				player->mo->flags &= ~MF_NOGRAVITY;
				player->mo->flags2 &= ~MF2_FLY;
				msg = GStrings("TXT_GRAVITY");
			}
		}
		break;

	case CHT_MORPH:
		msg = cht_Morph (player, PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer), true);
		break;

	case CHT_NOTARGET:
		player->cheats ^= CF_NOTARGET;
		if (player->cheats & CF_NOTARGET)
			msg = "notarget ON";
		else
			msg = "notarget OFF";
		break;

	case CHT_ANUBIS:
		player->cheats ^= CF_FRIGHTENING;
		if (player->cheats & CF_FRIGHTENING)
			msg = "\"Quake with fear!\"";
		else
			msg = "No more ogre armor";
		break;

	case CHT_CHASECAM:
		player->cheats ^= CF_CHASECAM;
		if (player->cheats & CF_CHASECAM)
			msg = "chasecam ON";
		else
			msg = "chasecam OFF";
		R_ResetViewInterpolation ();
		break;

	case CHT_CHAINSAW:
		if (player->mo != NULL && player->health >= 0)
		{
			type = PClass::FindClass ("Chainsaw");
			if (player->mo->FindInventory (type) == NULL)
			{
				player->mo->GiveInventoryType (type);
			}
			if(gameinfo.gametype != GAME_Chex)
				msg = GStrings("STSTR_CHOPPERS");
			else
				msg = GStrings("STSTR_CCHOPPERS");
		}
		// [RH] The original cheat also set powers[pw_invulnerability] to true.
		// Since this is a timer and not a boolean, it effectively turned off
		// the invulnerability powerup, although it looks like it was meant to
		// turn it on.
		break;

	case CHT_POWER:
		if (player->mo != NULL && player->health >= 0)
		{
			item = player->mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2));
			if (item != NULL)
			{
				item->Destroy ();
				msg = GStrings("TXT_CHEATPOWEROFF");
			}
			else
			{
				player->mo->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2));
				msg = GStrings("TXT_CHEATPOWERON");
			}
		}
		break;

	case CHT_IDKFA:
		cht_Give (player, "backpack");
		cht_Give (player, "weapons");
		cht_Give (player, "ammo");
		cht_Give (player, "keys");
		cht_Give (player, "armor");
		if(gameinfo.gametype != GAME_Chex)
			msg = GStrings("STSTR_KFAADDED");
		else
			msg = GStrings("STSTR_CKFAADDED");
		break;

	case CHT_IDFA:
		cht_Give (player, "backpack");
		cht_Give (player, "weapons");
		cht_Give (player, "ammo");
		cht_Give (player, "armor");
		if(gameinfo.gametype != GAME_Chex)
			msg = GStrings("STSTR_FAADDED");
		else
			msg = GStrings("STSTR_CFAADDED");
		break;

	case CHT_BEHOLDV:
	case CHT_BEHOLDS:
	case CHT_BEHOLDI:
	case CHT_BEHOLDR:
	case CHT_BEHOLDA:
	case CHT_BEHOLDL:
	case CHT_PUMPUPI:
	case CHT_PUMPUPM:
	case CHT_PUMPUPT:
		i = cheat - CHT_BEHOLDV;

		if (i == 4)
		{
			level.flags2 ^= LEVEL2_ALLMAP;
		}
		else if (player->mo != NULL && player->health >= 0)
		{
			item = player->mo->FindInventory (BeholdPowers[i]);
			if (item == NULL)
			{
				if (i != 0)
				{
					cht_Give(player, BeholdPowers[i]);
					if (cheat == CHT_BEHOLDS)
					{
						P_GiveBody (player->mo, -100);
					}
				}
				else
				{
					// Let's give the item here so that the power doesn't need colormap information.
					cht_Give(player, "InvulnerabilitySphere");
				}
			}
			else
			{
				item->Destroy ();
			}
		}
		msg = GStrings("STSTR_BEHOLDX");
		break;

	case CHT_MASSACRE:
		{
			int killcount = P_Massacre ();
			// killough 3/22/98: make more intelligent about plural
			// Ty 03/27/98 - string(s) *not* externalized
			mysnprintf (msgbuild, countof(msgbuild), "%d Monster%s Killed", killcount, killcount==1 ? "" : "s");
			msg = msgbuild;
		}
		break;

	case CHT_HEALTH:
		if (player->mo != NULL && player->playerstate == PST_LIVE)
		{
			player->health = player->mo->health = player->mo->GetDefault()->health;
			msg = GStrings("TXT_CHEATHEALTH");
		}
		break;

	case CHT_KEYS:
		cht_Give (player, "keys");
		msg = GStrings("TXT_CHEATKEYS");
		break;

	// [GRB]
	case CHT_RESSURECT:
		if (player->playerstate != PST_LIVE && player->mo != NULL)
		{
			if (player->mo->IsKindOf(RUNTIME_CLASS(APlayerChunk)))
			{
				Printf("Unable to resurrect. Player is no longer connected to its body.\n");
			}
			else
			{
				player->playerstate = PST_LIVE;
				player->health = player->mo->health = player->mo->GetDefault()->health;
				player->viewheight = ((APlayerPawn *)player->mo->GetDefault())->ViewHeight;
				player->mo->flags = player->mo->GetDefault()->flags;
				player->mo->flags2 = player->mo->GetDefault()->flags2;
				player->mo->flags3 = player->mo->GetDefault()->flags3;
				player->mo->flags4 = player->mo->GetDefault()->flags4;
				player->mo->flags5 = player->mo->GetDefault()->flags5;
				player->mo->renderflags &= ~RF_INVISIBLE;
				player->mo->height = player->mo->GetDefault()->height;
				player->mo->special1 = 0;	// required for the Hexen fighter's fist attack. 
											// This gets set by AActor::Die as flag for the wimpy death and must be reset here.
				player->mo->SetState (player->mo->SpawnState);
				if (!(player->mo->flags2 & MF2_DONTTRANSLATE))
				{
					player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
				}
				player->mo->DamageType = NAME_None;
//				player->mo->GiveDefaultInventory();
				if (player->ReadyWeapon != NULL)
				{
					P_SetPsprite(player, ps_weapon, player->ReadyWeapon->GetUpState());
				}

				if (player->morphTics > 0)
				{
					P_UndoPlayerMorph(player, player);
				}

			}
		}
		break;

	case CHT_GIMMIEA:
		cht_Give (player, "ArtiInvulnerability");
		msg = "Valador's Ring of Invunerability";
		break;

	case CHT_GIMMIEB:
		cht_Give (player, "ArtiInvisibility");
		msg = "Shadowsphere";
		break;

	case CHT_GIMMIEC:
		cht_Give (player, "ArtiHealth");
		msg = "Quartz Flask";
		break;

	case CHT_GIMMIED:
		cht_Give (player, "ArtiSuperHealth");
		msg = "Mystic Urn";
		break;

	case CHT_GIMMIEE:
		cht_Give (player, "ArtiTomeOfPower");
		msg = "Tyketto's Tome of Power";
		break;

	case CHT_GIMMIEF:
		cht_Give (player, "ArtiTorch");
		msg = "Torch";
		break;

	case CHT_GIMMIEG:
		cht_Give (player, "ArtiTimeBomb");
		msg = "Delmintalintar's Time Bomb of the Ancients";
		break;

	case CHT_GIMMIEH:
		cht_Give (player, "ArtiEgg");
		msg = "Torpol's Morph Ovum";
		break;

	case CHT_GIMMIEI:
		cht_Give (player, "ArtiFly");
		msg = "Inhilicon's Wings of Wrath";
		break;

	case CHT_GIMMIEJ:
		cht_Give (player, "ArtiTeleport");
		msg = "Darchala's Chaos Device";
		break;

	case CHT_GIMMIEZ:
		for (int i=0;i<16;i++)
		{
			cht_Give (player, "artifacts");
		}
		msg = "All artifacts!";
		break;

	case CHT_TAKEWEAPS:
		if (player->morphTics || player->mo == NULL || player->mo->health <= 0)
		{
			return;
		}
		{
			// Take away all weapons that are either non-wimpy or use ammo.
			AInventory **invp = &player->mo->Inventory, **lastinvp;
			for (item = *invp; item != NULL; item = *invp)
			{
				lastinvp = invp;
				invp = &(*invp)->Inventory;
				if (item->IsKindOf (RUNTIME_CLASS(AWeapon)))
				{
					AWeapon *weap = static_cast<AWeapon *> (item);
					if (!(weap->WeaponFlags & WIF_WIMPY_WEAPON) ||
						weap->AmmoType1 != NULL)
					{
						item->Destroy ();
						invp = lastinvp;
					}
				}
			}
		}
		msg = GStrings("TXT_CHEATIDKFA");
		break;

	case CHT_NOWUDIE:
		cht_Suicide (player);
		msg = GStrings("TXT_CHEATIDDQD");
		break;

	case CHT_ALLARTI:
		for (int i=0;i<25;i++)
		{
			cht_Give (player, "artifacts");
		}
		msg = GStrings("TXT_CHEATARTIFACTS3");
		break;

	case CHT_PUZZLE:
		cht_Give (player, "puzzlepieces");
		msg = GStrings("TXT_CHEATARTIFACTS3");
		break;

	case CHT_MDK:
		if (player->mo == NULL)
		{
			Printf ("What do you want to kill outside of a game?\n");
		}
		// else if (!deathmatch)
		{
			// Don't allow this in deathmatch even with cheats enabled, because it's
			// a very very cheap kill.
			// [Dusk] <jino> and summoning 5000 bfg balls isn't?
			P_LineAttack (player->mo, player->mo->angle, PLAYERMISSILERANGE,
				P_AimLineAttack (player->mo, player->mo->angle, PLAYERMISSILERANGE), TELEFRAG_DAMAGE,
				NAME_MDK, NAME_BulletPuff);
		}
		break;

	case CHT_DONNYTRUMP:
		cht_Give (player, "HealthTraining");
		msg = GStrings("TXT_MIDASTOUCH");
		break;

	case CHT_LEGO:
		if (player->mo != NULL && player->health >= 0)
		{
			int oldpieces = ASigil::GiveSigilPiece (player->mo);
			item = player->mo->FindInventory (RUNTIME_CLASS(ASigil));

			if (item != NULL)
			{
				if (oldpieces == 5)
				{
					item->Destroy ();
				}
				else
				{
					player->PendingWeapon = static_cast<AWeapon *> (item);
				}
			}
		}
		break;

	case CHT_PUMPUPH:
		cht_Give (player, "MedPatch");
		cht_Give (player, "MedicalKit");
		cht_Give (player, "SurgeryKit");
		msg = GStrings("TXT_GOTSTUFF");
		break;

	case CHT_PUMPUPP:
		cht_Give (player, "AmmoSatchel");
		msg = GStrings("TXT_GOTSTUFF");
		break;

	case CHT_PUMPUPS:
		cht_Give (player, "UpgradeStamina", 10);
		cht_Give (player, "UpgradeAccuracy");
		msg = GStrings("TXT_GOTSTUFF");
		break;

	case CHT_CLEARFROZENPROPS:
		player->cheats &= ~(CF_FROZEN|CF_TOTALLYFROZEN);
		msg = "Frozen player properties turned off";
		break;

/* [BB] Skulltag doesn't use this.
	case CHT_FREEZE:
		bglobal.changefreeze ^= 1;
		if (bglobal.freeze ^ bglobal.changefreeze)
		{
			msg = GStrings("TXT_FREEZEON");
		}
		else
		{
			msg = GStrings("TXT_FREEZEOFF");
		}
		break;
*/
	}

	if (!*msg)              // [SO] Don't print blank lines!
		return;

	if( ( cheat != CHT_CHASECAM )
		|| ( !( GAMEMODE_GetFlags( GAMEMODE_GetCurrentMode( )) & GMF_COOPERATIVE )
			&& ( player->bSpectating == false ) && !(dmflags2 & DF2_CHASECAM))){
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
			SERVER_Printf( PRINT_HIGH, "%s is a cheater: %s\n", player->userinfo.netname, msg );
		else if ( player == &players[consoleplayer] || CLIENTDEMO_IsFreeSpectatorPlayer( player ) )
			Printf ("%s\n", msg);
		// [BB] The server already ensures that all clients see the cheater message.
		else if ( NETWORK_GetState( ) != NETSTATE_CLIENT )
			Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg);
	}
}