sm-plugins/RandomizeSpawns/scripting/RandomizeSpawns.sp

147 lines
4.4 KiB
SourcePawn
Raw Normal View History

2019-03-02 15:22:14 +01:00
#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);
}