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);
|
|
} |