147 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
| #pragma newdecls required
 | |
| 
 | |
| #include <sourcemod>
 | |
| #include <sdktools>
 | |
| #include <dhooks>
 | |
| 
 | |
| Handle hSelectSpawnPoint;
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public Plugin myinfo =
 | |
| {
 | |
| 	name         = "RandomizeSpawns",
 | |
| 	author       = "zaCade",
 | |
| 	description  = "Randomize player spawns.",
 | |
| 	version      = "1.0.0"
 | |
| };
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPluginStart()
 | |
| {
 | |
| 	Handle hGameConf;
 | |
| 	if ((hGameConf = LoadGameConfigFile("RandomizeSpawns.games")) == INVALID_HANDLE)
 | |
| 	{
 | |
| 		SetFailState("Couldn't load \"RandomizeSpawns.games\" game config!");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	//
 | |
| 	int iOffset;
 | |
| 	if ((iOffset = GameConfGetOffset(hGameConf, "SelectSpawnPoint")) == -1)
 | |
| 	{
 | |
| 		CloseHandle(hGameConf);
 | |
| 		SetFailState("GameConfGetOffset(hGameConf, \"SelectSpawnPoint\") failed!");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if ((hSelectSpawnPoint = DHookCreate(iOffset, HookType_Entity, ReturnType_CBaseEntity, ThisPointer_CBaseEntity, OnPlayerSelectSpawnPoint)) == INVALID_HANDLE)
 | |
| 	{
 | |
| 		CloseHandle(hGameConf);
 | |
| 		SetFailState("DHookCreate(iOffset, HookType_Entity, ReturnType_CBaseEntity, ThisPointer_CBaseEntity, OnPlayerSelectSpawnPoint) failed!");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	// Late load.
 | |
| 	for (int client = 1; client <= MaxClients; client++)
 | |
| 	{
 | |
| 		if (IsClientInGame(client))
 | |
| 		{
 | |
| 			OnClientPutInServer(client);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	CloseHandle(hGameConf);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnClientPutInServer(int client)
 | |
| {
 | |
| 	DHookEntity(hSelectSpawnPoint, false, client);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public int RandomizeSpawnPoints(int elem1, int elem2, int[] array, Handle hndl)
 | |
| {
 | |
| 	return GetRandomInt(-1, 1);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public MRESReturn OnPlayerSelectSpawnPoint(int client, Handle hReturn)
 | |
| {
 | |
| 	if (IsValidEntity(client) && !IsClientInGame(client))
 | |
| 		return MRES_Ignored;
 | |
| 
 | |
| 	static int spawnPoints[128];
 | |
| 	static int spawnCount;
 | |
| 
 | |
| 	if (!spawnCount)
 | |
| 	{
 | |
| 		int spawnPoint = INVALID_ENT_REFERENCE;
 | |
| 		while ((spawnPoint = FindEntityByClassname(spawnPoint, "info_player_*")) != INVALID_ENT_REFERENCE)
 | |
| 		{
 | |
| 			char sClassname[64];
 | |
| 			GetEntityClassname(spawnPoint, sClassname, sizeof(sClassname));
 | |
| 
 | |
| 			if (StrEqual(sClassname, "info_player_terrorist", true) || StrEqual(sClassname, "info_player_counterterrorist", true))
 | |
| 			{
 | |
| 				spawnPoints[spawnCount++] = spawnPoint;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (spawnCount)
 | |
| 	{
 | |
| 		int spawnCountAttempts;
 | |
| 		while (spawnCountAttempts >= spawnCount)
 | |
| 		{
 | |
| 			SortCustom1D(spawnPoints, spawnCount, RandomizeSpawnPoints);
 | |
| 
 | |
| 			int spawnPoint = spawnPoints[0];
 | |
| 			if (IsValidEntity(spawnPoint) && IsValidPlayerSpawn(client, spawnPoint))
 | |
| 			{
 | |
| 				DHookSetReturn(hReturn, spawnPoint);
 | |
| 				return MRES_Supercede;
 | |
| 			}
 | |
| 
 | |
| 			spawnCountAttempts++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return MRES_Ignored;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock bool IsValidPlayerSpawn(int client, int spawnPoint)
 | |
| {
 | |
| 	float clientMins[3];
 | |
| 	float clientMaxs[3];
 | |
| 	GetClientMins(client, clientMins);
 | |
| 	GetClientMaxs(client, clientMaxs);
 | |
| 
 | |
| 	float spawnPointOrigin[3];
 | |
| 	GetEntPropVector(spawnPoint, Prop_Send, "m_vecOrigin", spawnPointOrigin);
 | |
| 
 | |
| 	TR_TraceHullFilter(spawnPointOrigin, spawnPointOrigin, clientMins, clientMaxs, MASK_PLAYERSOLID, IsValidPlayerSpawnFilter);
 | |
| 
 | |
| 	return !TR_DidHit();
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public bool IsValidPlayerSpawnFilter(int entity, int contentsMask)
 | |
| {
 | |
| 	return view_as<bool>(entity);
 | |
| } |