csgo-plugins/AdvancedTargeting/scripting/AdvancedTargeting.sp
2020-03-25 20:09:12 +02:00

611 lines
14 KiB
SourcePawn

#pragma semicolon 1
#pragma dynamic 128*1024
#include <sourcemod>
#include <sdktools>
#include <SteamWorks>
#include <cstrike>
#include <AdvancedTargeting>
#undef REQUIRE_PLUGIN
#include <AdvancedTargeting>
#include <voiceannounce_ex>
#define REQUIRE_PLUGIN
#undef REQUIRE_EXTENSIONS
#tryinclude <voice>
#define REQUIRE_EXTENSIONS
#pragma newdecls required
Handle g_FriendsArray[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
bool g_Plugin_voiceannounce_ex = false;
bool g_Extension_Voice = false;
bool g_bLateLoad = false;
#include <SteamAPI.secret> //#define STEAM_API_KEY here
public Plugin myinfo =
{
name = "Advanced Targeting",
author = "BotoX + Obus",
description = "Adds extra targeting methods",
version = "1.3",
url = "https://github.com/CSSZombieEscape/sm-plugins/tree/master/AdvancedTargeting/"
}
public void OnPluginStart()
{
AddMultiTargetFilter("@admins", Filter_Admin, "Admins", false);
AddMultiTargetFilter("@!admins", Filter_NotAdmin, "Not Admins", false);
AddMultiTargetFilter("@friends", Filter_Friends, "Steam Friends", false);
AddMultiTargetFilter("@!friends", Filter_NotFriends, "Not Steam Friends", false);
AddMultiTargetFilter("@random", Filter_Random, "a Random Player", false);
AddMultiTargetFilter("@randomct", Filter_RandomCT, "a Random CT", false);
AddMultiTargetFilter("@randomt", Filter_RandomT, "a Random T", false);
AddMultiTargetFilter("@alivect", Filter_AliveCT, "Alive Humans", false);
AddMultiTargetFilter("@alivet", Filter_AliveT, "Alive Zombies", false);
AddMultiTargetFilter("@talking", Filter_Talking, "Talking", false);
AddMultiTargetFilter("@!talking", Filter_NotTalking, "Not Talking", false);
AddMultiTargetFilter("@speaking", Filter_Talking, "Talking", false);
AddMultiTargetFilter("@!speaking", Filter_NotTalking, "Not Talking", false);
RegConsoleCmd("sm_admins", Command_Admins, "Currently online admins.");
RegConsoleCmd("sm_friends", Command_Friends, "Currently online friends.");
if(g_bLateLoad)
{
char sSteam32ID[32];
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) &&
GetClientAuthId(i, AuthId_Steam2, sSteam32ID, sizeof(sSteam32ID)))
{
OnClientAuthorized(i, sSteam32ID);
}
}
}
}
public void OnPluginEnd()
{
RemoveMultiTargetFilter("@admins", Filter_Admin);
RemoveMultiTargetFilter("@!admins", Filter_NotAdmin);
RemoveMultiTargetFilter("@friends", Filter_Friends);
RemoveMultiTargetFilter("@!friends", Filter_NotFriends);
RemoveMultiTargetFilter("@random", Filter_Random);
RemoveMultiTargetFilter("@randomct", Filter_RandomCT);
RemoveMultiTargetFilter("@randomt", Filter_RandomT);
RemoveMultiTargetFilter("@alivect", Filter_AliveCT);
RemoveMultiTargetFilter("@alivet", Filter_AliveT);
RemoveMultiTargetFilter("@talking", Filter_Talking);
RemoveMultiTargetFilter("@!talking", Filter_NotTalking);
RemoveMultiTargetFilter("@speaking", Filter_Talking);
RemoveMultiTargetFilter("@!speaking", Filter_NotTalking);
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("IsClientFriend", Native_IsClientFriend);
CreateNative("ReadClientFriends", Native_ReadClientFriends);
RegPluginLibrary("AdvancedTargeting");
g_bLateLoad = late;
return APLRes_Success;
}
public void OnAllPluginsLoaded()
{
g_Plugin_voiceannounce_ex = LibraryExists("voiceannounce_ex");
g_Extension_Voice = LibraryExists("Voice");
LogMessage("AdvancedTargeting capabilities:\nVoiceAnnounce: %s\nVoice: %s",
(g_Plugin_voiceannounce_ex ? "loaded" : "not loaded"),
(g_Extension_Voice ? "loaded" : "not loaded"));
}
public void OnLibraryAdded(const char[] name)
{
if(StrEqual(name, "voiceannounce_ex"))
g_Plugin_voiceannounce_ex = true;
else if(StrEqual(name, "Voice"))
g_Extension_Voice = true;
}
public void OnLibraryRemoved(const char[] name)
{
if(StrEqual(name, "voiceannounce_ex"))
g_Plugin_voiceannounce_ex = false;
else if(StrEqual(name, "Voice"))
g_Extension_Voice = false;
}
public Action Command_Admins(int client, int args)
{
char aBuf[1024];
char aBuf2[MAX_NAME_LENGTH];
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && GetAdminFlag(GetUserAdmin(i), Admin_Generic))
{
GetClientName(i, aBuf2, sizeof(aBuf2));
StrCat(aBuf, sizeof(aBuf), aBuf2);
StrCat(aBuf, sizeof(aBuf), ", ");
}
}
if(strlen(aBuf))
{
aBuf[strlen(aBuf) - 2] = 0;
ReplyToCommand(client, "[SM] Admins currently online: %s", aBuf);
}
else
ReplyToCommand(client, "[SM] Admins currently online: none");
return Plugin_Handled;
}
public Action Command_Friends(int client, int args)
{
if(!client)
return Plugin_Handled;
if(g_FriendsArray[client] == INVALID_HANDLE)
{
PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!");
return Plugin_Handled;
}
char aBuf[1024];
char aBuf2[MAX_NAME_LENGTH];
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i))
{
int Steam3ID = GetSteamAccountID(i);
if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1)
{
GetClientName(i, aBuf2, sizeof(aBuf2));
StrCat(aBuf, sizeof(aBuf), aBuf2);
StrCat(aBuf, sizeof(aBuf), ", ");
}
}
}
if(strlen(aBuf))
{
aBuf[strlen(aBuf) - 2] = 0;
PrintToChat(client, "[SM] Friends currently online: %s", aBuf);
}
else
PrintToChat(client, "[SM] Friends currently online: none");
return Plugin_Handled;
}
public bool Filter_AliveCT(const char[] sPattern, Handle hClients, int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == CS_TEAM_CT && IsPlayerAlive(i))
{
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_AliveT(const char[] sPattern, Handle hClients, int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == CS_TEAM_T && IsPlayerAlive(i))
{
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_Admin(const char[] sPattern, Handle hClients, int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && GetAdminFlag(GetUserAdmin(i), Admin_Generic))
{
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_NotAdmin(const char[] sPattern, Handle hClients, int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && !GetAdminFlag(GetUserAdmin(i), Admin_Generic))
{
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_Friends(const char[] sPattern, Handle hClients, int client)
{
if(g_FriendsArray[client] == INVALID_HANDLE)
{
PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!");
return false;
}
for(int i = 1; i <= MaxClients; i++)
{
if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i))
{
int Steam3ID = GetSteamAccountID(i);
if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1)
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_NotFriends(const char[] sPattern, Handle hClients, int client)
{
if(g_FriendsArray[client] == INVALID_HANDLE)
{
PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!");
return false;
}
for(int i = 1; i <= MaxClients; i++)
{
if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i))
{
int Steam3ID = GetSteamAccountID(i);
if(FindValueInArray(g_FriendsArray[client], Steam3ID) == -1)
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_Random(const char[] sPattern, Handle hClients, int client)
{
int iRand = GetRandomInt(1, MaxClients);
if(IsClientInGame(iRand) && IsPlayerAlive(iRand))
PushArrayCell(hClients, iRand);
else
Filter_Random(sPattern, hClients, client);
return true;
}
public bool Filter_RandomCT(const char[] sPattern, Handle hClients, int client)
{
int iCTCount = GetTeamClientCount(CS_TEAM_CT);
if(!iCTCount)
return false;
int[] iCTs = new int[iCTCount];
int iCurIndex;
for(int i = 1; i <= MaxClients; i++)
{
if(!IsClientInGame(i) || GetClientTeam(i) != CS_TEAM_CT)
continue;
if(!IsPlayerAlive(i))
{
iCTCount--;
continue;
}
iCTs[iCurIndex] = i;
iCurIndex++;
}
PushArrayCell(hClients, iCTs[GetRandomInt(0, iCTCount-1)]);
return true;
}
public bool Filter_RandomT(const char[] sPattern, Handle hClients, int client)
{
int iTCount = GetTeamClientCount(CS_TEAM_T);
if(!iTCount)
return false;
int[] iTs = new int[iTCount];
int iCurIndex;
for(int i = 1; i <= MaxClients; i++)
{
if(!IsClientInGame(i) || GetClientTeam(i) != CS_TEAM_T)
continue;
if(!IsPlayerAlive(i))
{
iTCount--;
continue;
}
iTs[iCurIndex] = i;
iCurIndex++;
}
PushArrayCell(hClients, iTs[GetRandomInt(0, iTCount-1)]);
return true;
}
stock bool _IsClientSpeaking(int client)
{
#if defined _voiceannounceex_included_
if(g_Plugin_voiceannounce_ex)
return IsClientSpeaking(client);
#endif
#if defined _voice_included
if(g_Extension_Voice)
return IsClientTalking(client);
#endif
return false;
}
public bool Filter_Talking(const char[] sPattern, Handle hClients, int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && _IsClientSpeaking(i))
{
PushArrayCell(hClients, i);
}
}
return true;
}
public bool Filter_NotTalking(const char[] sPattern, Handle hClients, int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsFakeClient(i) && !_IsClientSpeaking(i))
{
PushArrayCell(hClients, i);
}
}
return true;
}
public void OnClientAuthorized(int client, const char[] auth)
{
if(IsFakeClient(client))
return;
char sSteam64ID[32];
Steam32IDtoSteam64ID(auth, sSteam64ID, sizeof(sSteam64ID));
static char sRequest[256];
FormatEx(sRequest, sizeof(sRequest), "http://api.steampowered.com/ISteamUser/GetFriendList/v0001/?key=%s&steamid=%s&relationship=friend&format=vdf", STEAM_API_KEY, sSteam64ID);
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest);
if (!hRequest ||
!SteamWorks_SetHTTPRequestContextValue(hRequest, client) ||
!SteamWorks_SetHTTPCallbacks(hRequest, OnTransferComplete) ||
!SteamWorks_SendHTTPRequest(hRequest))
{
CloseHandle(hRequest);
}
}
public void OnClientDisconnect(int client)
{
if(g_FriendsArray[client] != INVALID_HANDLE)
CloseHandle(g_FriendsArray[client]);
g_FriendsArray[client] = INVALID_HANDLE;
}
public int OnTransferComplete(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, int client)
{
if(bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
{
// Private profile or maybe steam down?
//LogError("SteamAPI HTTP Response failed: %d", eStatusCode);
CloseHandle(hRequest);
return;
}
int Length;
SteamWorks_GetHTTPResponseBodySize(hRequest, Length);
char[] sData = new char[Length];
SteamWorks_GetHTTPResponseBodyData(hRequest, sData, Length);
//SteamWorks_GetHTTPResponseBodyCallback(hRequest, APIWebResponse, client);
CloseHandle(hRequest);
APIWebResponse(sData, client);
}
public void APIWebResponse(const char[] sData, int client)
{
KeyValues Response = new KeyValues("SteamAPIResponse");
if(!Response.ImportFromString(sData, "SteamAPIResponse"))
{
LogError("ImportFromString(sData, \"SteamAPIResponse\") failed.");
delete Response;
return;
}
if(!Response.JumpToKey("friends"))
{
LogError("JumpToKey(\"friends\") failed.");
delete Response;
return;
}
// No friends?
if(!Response.GotoFirstSubKey())
{
//LogError("GotoFirstSubKey() failed.");
delete Response;
return;
}
if(g_FriendsArray[client] != INVALID_HANDLE)
CloseHandle(g_FriendsArray[client]);
g_FriendsArray[client] = CreateArray();
char sCommunityID[32];
do
{
Response.GetString("steamid", sCommunityID, sizeof(sCommunityID));
PushArrayCell(g_FriendsArray[client], Steam64toSteam3(sCommunityID));
}
while(Response.GotoNextKey());
delete Response;
}
stock bool Steam32IDtoSteam64ID(const char[] sSteam32ID, char[] sSteam64ID, int Size)
{
if(strlen(sSteam32ID) < 11 || strncmp(sSteam32ID[0], "STEAM_0:", 8))
{
sSteam64ID[0] = 0;
return false;
}
int iUpper = 765611979;
int isSteam64ID = StringToInt(sSteam32ID[10]) * 2 + 60265728 + sSteam32ID[8] - 48;
int iDiv = isSteam64ID / 100000000;
int iIdx = 9 - (iDiv ? (iDiv / 10 + 1) : 0);
iUpper += iDiv;
IntToString(isSteam64ID, sSteam64ID[iIdx], Size - iIdx);
iIdx = sSteam64ID[9];
IntToString(iUpper, sSteam64ID, Size);
sSteam64ID[9] = iIdx;
return true;
}
stock int Steam64toSteam3(const char[] sSteam64ID)
{
if(strlen(sSteam64ID) != 17)
return 0;
// convert SteamID64 to array of integers
int aSteam64ID[17];
for(int i = 0; i < 17; i++)
aSteam64ID[i] = sSteam64ID[i] - 48;
// subtract individual SteamID64 identifier (0x0110000100000000)
int aSteam64IDIdent[] = {7, 6, 5, 6, 1, 1, 9, 7, 9, 6, 0, 2, 6, 5, 7, 2, 8};
int Carry = 0;
for(int i = 16; i >= 0; i--)
{
if(aSteam64ID[i] < aSteam64IDIdent[i] + Carry)
{
aSteam64ID[i] = aSteam64ID[i] - aSteam64IDIdent[i] - Carry + 10;
Carry = 1;
}
else
{
aSteam64ID[i] = aSteam64ID[i] - aSteam64IDIdent[i] - Carry;
Carry = 0;
}
}
char aBuf[17];
int j = 0;
bool ZereosDone = false;
for(int i = 0; i < 17; i++)
{
if(!ZereosDone && !aSteam64ID[i])
continue;
ZereosDone = true;
aBuf[j++] = aSteam64ID[i] + 48;
}
return StringToInt(aBuf);
}
public int Native_IsClientFriend(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
int friend = GetNativeCell(2);
if(client > MaxClients || client <= 0 || friend > MaxClients || friend <= 0)
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid.");
return -1;
}
if(!IsClientInGame(client) || !IsClientInGame(friend))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not in-game.");
return -1;
}
if(IsFakeClient(client) || IsFakeClient(friend))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is fake-client.");
return -1;
}
if(g_FriendsArray[client] == INVALID_HANDLE)
return -1;
if(IsClientAuthorized(friend))
{
int Steam3ID = GetSteamAccountID(friend);
if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1)
return 1;
}
return 0;
}
public int Native_ReadClientFriends(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if(client > MaxClients || client <= 0)
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid.");
return -1;
}
if(g_FriendsArray[client] != INVALID_HANDLE)
return 1;
return 0;
}