sm-plugins/SaveLevel/scripting/SaveLevel.sp

359 lines
8.7 KiB
SourcePawn

#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <outputinfo>
#pragma newdecls required
StringMap g_PlayerLevels;
KeyValues g_Config;
KeyValues g_PropAltNames;
#define PLUGIN_VERSION "1.1"
public Plugin myinfo =
{
name = "SaveLevel",
author = "BotoX",
description = "Saves players level on maps when they disconnect and restore them on connect.",
version = PLUGIN_VERSION,
url = ""
};
public void OnPluginStart()
{
g_PropAltNames = new KeyValues("PropAltNames");
g_PropAltNames.SetString("m_iName", "targetname");
}
public void OnPluginEnd()
{
if(g_Config)
delete g_Config;
if(g_PlayerLevels)
delete g_PlayerLevels;
delete g_PropAltNames;
}
public void OnMapStart()
{
if(g_Config)
delete g_Config;
if(g_PlayerLevels)
delete g_PlayerLevels;
char sMapName[PLATFORM_MAX_PATH];
GetCurrentMap(sMapName, sizeof(sMapName));
char sConfigFile[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/savelevel/%s.cfg", sMapName);
if(!FileExists(sConfigFile))
{
LogMessage("Could not find mapconfig: \"%s\"", sConfigFile);
return;
}
LogMessage("Found mapconfig: \"%s\"", sConfigFile);
g_Config = new KeyValues("levels");
if(!g_Config.ImportFromFile(sConfigFile))
{
delete g_Config;
LogMessage("ImportFromFile() failed!");
return;
}
g_Config.Rewind();
if(!g_Config.GotoFirstSubKey())
{
delete g_Config;
LogMessage("GotoFirstSubKey() failed!");
return;
}
g_PlayerLevels = new StringMap();
}
public void OnClientPostAdminCheck(int client)
{
if(!g_PlayerLevels)
return;
char sSteamID[32];
GetClientAuthId(client, AuthId_Steam3, sSteamID, sizeof(sSteamID));
static char sTargets[128];
if(g_PlayerLevels.GetString(sSteamID, sTargets, sizeof(sTargets)))
{
g_PlayerLevels.Remove(sSteamID);
char sNames[128];
static char asTargets[4][32];
int Split = ExplodeString(sTargets, ";", asTargets, sizeof(asTargets), sizeof(asTargets[]));
g_Config.Rewind();
for(int i = 0; i < Split; i++)
{
if(!g_Config.JumpToKey(asTargets[i]))
continue;
static char sKey[32];
static char sValue[1024];
if(g_Config.JumpToKey("restore"))
{
if(g_Config.GotoFirstSubKey(false))
{
do
{
g_Config.GetSectionName(sKey, sizeof(sKey));
g_Config.GetString(NULL_STRING, sValue, sizeof(sValue));
if(StrEqual(sKey, "AddOutput", false))
{
SetVariantString(sValue);
AcceptEntityInput(client, sKey, client, client);
}
else
{
PropFieldType Type;
int NumBits;
int Offset = FindDataMapInfo(client, sKey, Type, NumBits);
if(Offset != -1)
{
if(Type == PropField_Integer)
{
int Value = StringToInt(sValue);
SetEntData(client, Offset, Value, NumBits / 8, false);
}
else if(Type == PropField_Float)
{
float Value = StringToFloat(sValue);
SetEntDataFloat(client, Offset, Value, false);
}
else if(Type == PropField_String)
{
SetEntDataString(client, Offset, sValue, strlen(sValue) + 1, false);
}
else if(Type == PropField_String_T)
{
static char sAltKey[32];
g_PropAltNames.GetString(sKey, sAltKey, sizeof(sAltKey), NULL_STRING);
if(sAltKey[0])
DispatchKeyValue(client, sAltKey, sValue);
}
}
}
}
while(g_Config.GotoNextKey(false));
g_Config.GoBack();
g_Config.GoBack();
g_Config.GetString("name", sValue, sizeof(sValue));
g_Config.GoBack();
StrCat(sNames, sizeof(sNames), sValue);
StrCat(sNames, sizeof(sNames), ", ");
}
}
}
int NamesLen = strlen(sNames);
if(NamesLen)
{
sNames[NamesLen - 2] = 0; // Cut off ', '
PrintToChatAll("\x03[SaveLevel]\x01 %N has been restored to: \x04%s", client, sNames);
}
g_Config.Rewind();
}
}
public void OnClientDisconnect(int client)
{
if(!g_Config || !g_PlayerLevels || !IsClientInGame(client))
return;
g_Config.Rewind();
g_Config.GotoFirstSubKey();
char sTargets[128];
static char sTarget[32];
static char sKey[32];
static char sValue[1024];
static char sOutput[1024];
bool Found = false;
do
{
g_Config.GetSectionName(sTarget, sizeof(sTarget));
if(!g_Config.JumpToKey("match"))
continue;
int Matches = 0;
int ExactMatches = g_Config.GetNum("ExactMatches", -1);
int MinMatches = g_Config.GetNum("MinMatches", -1);
int MaxMatches = g_Config.GetNum("MaxMatches", -1);
if(!g_Config.GotoFirstSubKey(false))
continue;
do
{
static char sSection[32];
g_Config.GetSectionName(sSection, sizeof(sSection));
if(StrEqual(sSection, "outputs"))
{
int _Matches = 0;
int _ExactMatches = g_Config.GetNum("ExactMatches", -1);
int _MinMatches = g_Config.GetNum("MinMatches", -1);
int _MaxMatches = g_Config.GetNum("MaxMatches", -1);
if(g_Config.GotoFirstSubKey(false))
{
do
{
g_Config.GetSectionName(sKey, sizeof(sKey));
g_Config.GetString(NULL_STRING, sValue, sizeof(sValue));
int Count = GetOutputCount(client, sKey);
for(int i = 0; i < Count; i++)
{
int Len = GetOutputTarget(client, sKey, i, sOutput);
sOutput[Len] = ','; Len++;
Len += GetOutputTargetInput(client, sKey, i, sOutput[Len]);
sOutput[Len] = ','; Len++;
Len += GetOutputParameter(client, sKey, i, sOutput[Len]);
if(StrEqual(sValue, sOutput))
_Matches++;
}
}
while(g_Config.GotoNextKey(false));
g_Config.GoBack();
}
g_Config.GoBack();
Matches += CalcMatches(_Matches, _ExactMatches, _MinMatches, _MaxMatches);
}
else if(StrEqual(sSection, "props"))
{
int _Matches = 0;
int _ExactMatches = g_Config.GetNum("ExactMatches", -1);
int _MinMatches = g_Config.GetNum("MinMatches", -1);
int _MaxMatches = g_Config.GetNum("MaxMatches", -1);
if(g_Config.GotoFirstSubKey(false))
{
do
{
g_Config.GetSectionName(sKey, sizeof(sKey));
g_Config.GetString(NULL_STRING, sValue, sizeof(sValue));
GetEntPropString(client, Prop_Data, sKey, sOutput, sizeof(sOutput));
if(StrEqual(sValue, sOutput))
_Matches++;
}
while(g_Config.GotoNextKey(false));
g_Config.GoBack();
}
g_Config.GoBack();
Matches += CalcMatches(_Matches, _ExactMatches, _MinMatches, _MaxMatches);
}
else if(StrEqual(sSection, "math"))
{
if(g_Config.GotoFirstSubKey(false))
{
do
{
g_Config.GetSectionName(sKey, sizeof(sKey));
g_Config.GetString(NULL_STRING, sValue, sizeof(sValue));
int Target = 0;
int Input;
int Parameter;
Input = FindCharInString(sValue[Target], ',');
sValue[Input] = 0; Input++;
Parameter = Input + FindCharInString(sValue[Input], ',');
sValue[Parameter] = 0; Parameter++;
int Value = 0;
int Count = GetOutputCount(client, sKey);
for(int i = 0; i < Count; i++)
{
int _Target = 0;
int _Input;
int _Parameter;
_Input = GetOutputTarget(client, sKey, i, sOutput[_Target]);
sOutput[_Input] = 0; _Input++;
_Parameter = _Input + GetOutputTargetInput(client, sKey, i, sOutput[_Input]);
sOutput[_Parameter] = 0; _Parameter++;
GetOutputParameter(client, sKey, i, sOutput[_Parameter]);
if(!StrEqual(sOutput[_Target], sValue[Target]))
continue;
int _Value = StringToInt(sOutput[_Parameter]);
if(StrEqual(sOutput[_Input], "add", false))
Value += _Value;
else if(StrEqual(sOutput[_Input], "subtract", false))
Value -= _Value;
}
int Result = StringToInt(sValue[Parameter]);
if(StrEqual(sValue[Input], "subtract", false))
Result *= -1;
if(Value == Result)
Matches += 1;
}
while(g_Config.GotoNextKey(false));
g_Config.GoBack();
}
g_Config.GoBack();
}
}
while(g_Config.GotoNextKey(false));
g_Config.GoBack();
if(CalcMatches(Matches, ExactMatches, MinMatches, MaxMatches))
{
if(Found)
StrCat(sTargets, sizeof(sTargets), ";");
Found = true;
StrCat(sTargets, sizeof(sTargets), sTarget);
}
}
while(g_Config.GotoNextKey());
g_Config.Rewind();
if(!Found)
return;
char sSteamID[32];
GetClientAuthId(client, AuthId_Steam3, sSteamID, sizeof(sSteamID));
g_PlayerLevels.SetString(sSteamID, sTargets, true);
}
stock int CalcMatches(int Matches, int ExactMatches, int MinMatches, int MaxMatches)
{
int Value = 0;
if((ExactMatches == -1 && MinMatches == -1 && MaxMatches == -1 && Matches) ||
Matches == ExactMatches ||
(MinMatches != -1 && MaxMatches == -1 && Matches >= MinMatches) ||
(MaxMatches != -1 && MinMatches == -1 && Matches <= MaxMatches) ||
(MinMatches != -1 && MaxMatches != -1 && Matches >= MinMatches && Matches <= MaxMatches))
{
Value++;
}
return Value;
}