Initial commit
This commit is contained in:
2
scripting/temp/.gitignore
vendored
Normal file
2
scripting/temp/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.smx
|
||||
discord_api.zip
|
2482
scripting/temp/BossSpawns.sp
Normal file
2482
scripting/temp/BossSpawns.sp
Normal file
File diff suppressed because it is too large
Load Diff
379
scripting/temp/admin-sql-prefetch.sp
Normal file
379
scripting/temp/admin-sql-prefetch.sp
Normal file
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SQL Admins Plugin (Prefetch)
|
||||
* Prefetches admins from an SQL database without threading.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
/* We like semicolons */
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "SQL Admins (Prefetch)",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Reads all admins from SQL",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
public void OnRebuildAdminCache(AdminCachePart part)
|
||||
{
|
||||
/* First try to get a database connection */
|
||||
char error[255];
|
||||
Database db;
|
||||
|
||||
if (SQL_CheckConfig("admins"))
|
||||
{
|
||||
db = SQL_Connect("admins", true, error, sizeof(error));
|
||||
} else {
|
||||
db = SQL_Connect("default", true, error, sizeof(error));
|
||||
}
|
||||
|
||||
if (db == null)
|
||||
{
|
||||
LogError("Could not connect to database \"default\": %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (part == AdminCache_Overrides)
|
||||
{
|
||||
FetchOverrides(db);
|
||||
} else if (part == AdminCache_Groups) {
|
||||
FetchGroups(db);
|
||||
} else if (part == AdminCache_Admins) {
|
||||
FetchUsers(db);
|
||||
}
|
||||
|
||||
delete db;
|
||||
}
|
||||
|
||||
void FetchUsers(Database db)
|
||||
{
|
||||
char query[255], error[255];
|
||||
DBResultSet rs;
|
||||
|
||||
Format(query, sizeof(query), "SELECT id, authtype, identity, password, flags, name, immunity FROM sm_admins");
|
||||
if ((rs = SQL_Query(db, query)) == null)
|
||||
{
|
||||
SQL_GetError(db, error, sizeof(error));
|
||||
LogError("FetchUsers() query failed: %s", query);
|
||||
LogError("Query error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
char authtype[16];
|
||||
char identity[80];
|
||||
char password[80];
|
||||
char flags[32];
|
||||
char name[80];
|
||||
int immunity;
|
||||
AdminId adm;
|
||||
GroupId grp;
|
||||
int id;
|
||||
|
||||
/* Keep track of a mapping from admin DB IDs to internal AdminIds to
|
||||
* enable group lookups en masse */
|
||||
StringMap htAdmins = new StringMap();
|
||||
char key[16];
|
||||
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
id = rs.FetchInt(0);
|
||||
IntToString(id, key, sizeof(key));
|
||||
rs.FetchString(1, authtype, sizeof(authtype));
|
||||
rs.FetchString(2, identity, sizeof(identity));
|
||||
rs.FetchString(3, password, sizeof(password));
|
||||
rs.FetchString(4, flags, sizeof(flags));
|
||||
rs.FetchString(5, name, sizeof(name));
|
||||
immunity = rs.FetchInt(6);
|
||||
|
||||
/* Use a pre-existing admin if we can */
|
||||
if ((adm = FindAdminByIdentity(authtype, identity)) == INVALID_ADMIN_ID)
|
||||
{
|
||||
adm = CreateAdmin(name);
|
||||
if (!adm.BindIdentity(authtype, identity))
|
||||
{
|
||||
LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
htAdmins.SetValue(key, adm);
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s,%d):%d", id, authtype, identity, password, flags, name, immunity, adm);
|
||||
#endif
|
||||
|
||||
/* See if this admin wants a password */
|
||||
if (password[0] != '\0')
|
||||
{
|
||||
adm.SetPassword(password);
|
||||
}
|
||||
|
||||
/* Apply each flag */
|
||||
int len = strlen(flags);
|
||||
AdminFlag flag;
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
if (!FindFlagByChar(flags[i], flag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
adm.SetFlag(flag, true);
|
||||
}
|
||||
|
||||
adm.ImmunityLevel = immunity;
|
||||
}
|
||||
|
||||
delete rs;
|
||||
|
||||
Format(query, sizeof(query), "SELECT ag.admin_id AS id, g.name FROM sm_admins_groups ag JOIN sm_groups g ON ag.group_id = g.id ORDER BY id, inherit_order ASC");
|
||||
if ((rs = SQL_Query(db, query)) == null)
|
||||
{
|
||||
SQL_GetError(db, error, sizeof(error));
|
||||
LogError("FetchUsers() query failed: %s", query);
|
||||
LogError("Query error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
char group[80];
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
IntToString(rs.FetchInt(0), key, sizeof(key));
|
||||
rs.FetchString(1, group, sizeof(group));
|
||||
|
||||
if (htAdmins.GetValue(key, adm))
|
||||
{
|
||||
if ((grp = FindAdmGroup(group)) == INVALID_GROUP_ID)
|
||||
{
|
||||
/* Group wasn't found, don't bother with it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
adm.InheritGroup(grp);
|
||||
}
|
||||
}
|
||||
|
||||
delete rs;
|
||||
delete htAdmins;
|
||||
}
|
||||
|
||||
void FetchGroups(Database db)
|
||||
{
|
||||
char query[255];
|
||||
DBResultSet rs;
|
||||
|
||||
Format(query, sizeof(query), "SELECT flags, name, immunity_level FROM sm_groups");
|
||||
|
||||
if ((rs = SQL_Query(db, query)) == null)
|
||||
{
|
||||
char error[255];
|
||||
SQL_GetError(db, error, sizeof(error));
|
||||
LogError("FetchGroups() query failed: %s", query);
|
||||
LogError("Query error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now start fetching groups */
|
||||
char flags[32];
|
||||
char name[128];
|
||||
int immunity;
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, flags, sizeof(flags));
|
||||
rs.FetchString(1, name, sizeof(name));
|
||||
immunity = rs.FetchInt(2);
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Adding group (%d, %s, %s)", immunity, flags, name);
|
||||
#endif
|
||||
|
||||
/* Find or create the group */
|
||||
GroupId grp;
|
||||
if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID)
|
||||
{
|
||||
grp = CreateAdmGroup(name);
|
||||
}
|
||||
|
||||
/* Add flags from the database to the group */
|
||||
int num_flag_chars = strlen(flags);
|
||||
for (int i=0; i<num_flag_chars; i++)
|
||||
{
|
||||
AdminFlag flag;
|
||||
if (!FindFlagByChar(flags[i], flag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
grp.SetFlag(flag, true);
|
||||
}
|
||||
|
||||
/* Set the immunity level this group has */
|
||||
grp.ImmunityLevel = immunity;
|
||||
}
|
||||
|
||||
delete rs;
|
||||
|
||||
/**
|
||||
* Get immunity in a big lump. This is a nasty query but it gets the job done.
|
||||
*/
|
||||
int len = 0;
|
||||
len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi");
|
||||
len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id ");
|
||||
len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id");
|
||||
|
||||
if ((rs = SQL_Query(db, query)) == null)
|
||||
{
|
||||
char error[255];
|
||||
SQL_GetError(db, error, sizeof(error));
|
||||
LogError("FetchGroups() query failed: %s", query);
|
||||
LogError("Query error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
char group1[80];
|
||||
char group2[80];
|
||||
GroupId grp, other;
|
||||
|
||||
rs.FetchString(0, group1, sizeof(group1));
|
||||
rs.FetchString(1, group2, sizeof(group2));
|
||||
|
||||
if (((grp = FindAdmGroup(group1)) == INVALID_GROUP_ID)
|
||||
|| (other = FindAdmGroup(group2)) == INVALID_GROUP_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
grp.AddGroupImmunity(other);
|
||||
#if defined _DEBUG
|
||||
PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", grp, other);
|
||||
#endif
|
||||
}
|
||||
|
||||
delete rs;
|
||||
|
||||
/**
|
||||
* Fetch overrides in a lump query.
|
||||
*/
|
||||
Format(query, sizeof(query), "SELECT g.name, go.type, go.name, go.access FROM sm_group_overrides go LEFT JOIN sm_groups g ON go.group_id = g.id");
|
||||
|
||||
if ((rs = SQL_Query(db, query)) == null)
|
||||
{
|
||||
char error[255];
|
||||
SQL_GetError(db, error, sizeof(error));
|
||||
LogError("FetchGroups() query failed: %s", query);
|
||||
LogError("Query error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
char type[16];
|
||||
char cmd[64];
|
||||
char access[16];
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, name, sizeof(name));
|
||||
rs.FetchString(1, type, sizeof(type));
|
||||
rs.FetchString(2, cmd, sizeof(cmd));
|
||||
rs.FetchString(3, access, sizeof(access));
|
||||
|
||||
GroupId grp;
|
||||
if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OverrideType o_type = Override_Command;
|
||||
if (StrEqual(type, "group"))
|
||||
{
|
||||
o_type = Override_CommandGroup;
|
||||
}
|
||||
|
||||
OverrideRule o_rule = Command_Deny;
|
||||
if (StrEqual(access, "allow"))
|
||||
{
|
||||
o_rule = Command_Allow;
|
||||
}
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", grp, cmd, o_type, o_rule);
|
||||
#endif
|
||||
|
||||
grp.AddCommandOverride(cmd, o_type, o_rule);
|
||||
}
|
||||
|
||||
delete rs;
|
||||
}
|
||||
|
||||
void FetchOverrides(Database db)
|
||||
{
|
||||
char query[255];
|
||||
DBResultSet rs;
|
||||
|
||||
Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
|
||||
|
||||
if ((rs = SQL_Query(db, query)) == null)
|
||||
{
|
||||
char error[255];
|
||||
SQL_GetError(db, error, sizeof(error));
|
||||
LogError("FetchOverrides() query failed: %s", query);
|
||||
LogError("Query error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
char type[64];
|
||||
char name[64];
|
||||
char flags[32];
|
||||
int flag_bits;
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, type, sizeof(type));
|
||||
rs.FetchString(1, name, sizeof(name));
|
||||
rs.FetchString(2, flags, sizeof(flags));
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
|
||||
#endif
|
||||
|
||||
flag_bits = ReadFlagString(flags);
|
||||
if (StrEqual(type, "command"))
|
||||
{
|
||||
AddCommandOverride(name, Override_Command, flag_bits);
|
||||
} else if (StrEqual(type, "group")) {
|
||||
AddCommandOverride(name, Override_CommandGroup, flag_bits);
|
||||
}
|
||||
}
|
||||
|
||||
delete rs;
|
||||
}
|
847
scripting/temp/admin-sql-threaded.sp
Normal file
847
scripting/temp/admin-sql-threaded.sp
Normal file
@@ -0,0 +1,847 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SQL Admins Plugin (Threaded)
|
||||
* Fetches admins from an SQL database dynamically.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
/* We like semicolons */
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "SQL Admins (Threaded)",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Reads admins from SQL dynamically",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
/**
|
||||
* Notes:
|
||||
*
|
||||
* 1) All queries in here are high priority. This is because the admin stuff
|
||||
* is very important. Do not take this to mean that in your script,
|
||||
* everything should be high priority.
|
||||
*
|
||||
* 2) All callbacks are locked with "sequence numbers." This is to make sure
|
||||
* that multiple calls to sm_reloadadmins and the like do not make us
|
||||
* store the results from two or more callbacks accidentally. Instead, we
|
||||
* check the sequence number in each callback with the current "allowed"
|
||||
* sequence number, and if it doesn't match, the callback is cancelled.
|
||||
*
|
||||
* 3) Sequence numbers for groups and overrides are not cleared unless there
|
||||
* was a 100% success in the fetch. This is so we can potentially implement
|
||||
* connection retries in the future.
|
||||
*
|
||||
* 4) Sequence numbers for the user cache are ignored except for being
|
||||
* non-zero, which means players in-game should be re-checked for admin
|
||||
* powers.
|
||||
*/
|
||||
|
||||
Database hDatabase = null; /** Database connection */
|
||||
int g_sequence = 0; /** Global unique sequence number */
|
||||
int ConnectLock = 0; /** Connect sequence number */
|
||||
int RebuildCachePart[3] = {0}; /** Cache part sequence numbers */
|
||||
int PlayerSeq[MAXPLAYERS+1]; /** Player-specific sequence numbers */
|
||||
bool PlayerAuth[MAXPLAYERS+1]; /** Whether a player has been "pre-authed" */
|
||||
|
||||
//#define _DEBUG
|
||||
|
||||
public void OnMapEnd()
|
||||
{
|
||||
/**
|
||||
* Clean up on map end just so we can start a fresh connection when we need it later.
|
||||
*/
|
||||
delete hDatabase;
|
||||
}
|
||||
|
||||
public bool OnClientConnect(int client, char[] rejectmsg, int maxlen)
|
||||
{
|
||||
PlayerSeq[client] = 0;
|
||||
PlayerAuth[client] = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
PlayerSeq[client] = 0;
|
||||
PlayerAuth[client] = false;
|
||||
}
|
||||
|
||||
public void OnDatabaseConnect(Database db, const char[] error, any data)
|
||||
{
|
||||
#if defined _DEBUG
|
||||
PrintToServer("OnDatabaseConnect(%x, %d) ConnectLock=%d", db, data, ConnectLock);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If this happens to be an old connection request, ignore it.
|
||||
*/
|
||||
if (data != ConnectLock || hDatabase != null)
|
||||
{
|
||||
delete db;
|
||||
return;
|
||||
}
|
||||
|
||||
ConnectLock = 0;
|
||||
hDatabase = db;
|
||||
|
||||
/**
|
||||
* See if the connection is valid. If not, don't un-mark the caches
|
||||
* as needing rebuilding, in case the next connection request works.
|
||||
*/
|
||||
if (hDatabase == null)
|
||||
{
|
||||
LogError("Failed to connect to database: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if we need to get any of the cache stuff now.
|
||||
*/
|
||||
int sequence;
|
||||
if ((sequence = RebuildCachePart[AdminCache_Overrides]) != 0)
|
||||
{
|
||||
FetchOverrides(hDatabase, sequence);
|
||||
}
|
||||
if ((sequence = RebuildCachePart[AdminCache_Groups]) != 0)
|
||||
{
|
||||
FetchGroups(hDatabase, sequence);
|
||||
}
|
||||
if ((sequence = RebuildCachePart[AdminCache_Admins]) != 0)
|
||||
{
|
||||
FetchUsersWeCan(hDatabase);
|
||||
}
|
||||
}
|
||||
|
||||
void RequestDatabaseConnection()
|
||||
{
|
||||
ConnectLock = ++g_sequence;
|
||||
if (SQL_CheckConfig("admins"))
|
||||
{
|
||||
Database.Connect(OnDatabaseConnect, "admins", ConnectLock);
|
||||
} else {
|
||||
Database.Connect(OnDatabaseConnect, "default", ConnectLock);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnRebuildAdminCache(AdminCachePart part)
|
||||
{
|
||||
/**
|
||||
* Mark this part of the cache as being rebuilt. This is used by the
|
||||
* callback system to determine whether the results should still be
|
||||
* used.
|
||||
*/
|
||||
int sequence = ++g_sequence;
|
||||
RebuildCachePart[part] = sequence;
|
||||
|
||||
/**
|
||||
* If we don't have a database connection, we can't do any lookups just yet.
|
||||
*/
|
||||
if (!hDatabase)
|
||||
{
|
||||
/**
|
||||
* Ask for a new connection if we need it.
|
||||
*/
|
||||
if (!ConnectLock)
|
||||
{
|
||||
RequestDatabaseConnection();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (part == AdminCache_Overrides)
|
||||
{
|
||||
FetchOverrides(hDatabase, sequence);
|
||||
} else if (part == AdminCache_Groups) {
|
||||
FetchGroups(hDatabase, sequence);
|
||||
} else if (part == AdminCache_Admins) {
|
||||
FetchUsersWeCan(hDatabase);
|
||||
}
|
||||
}
|
||||
|
||||
public Action OnClientPreAdminCheck(int client)
|
||||
{
|
||||
PlayerAuth[client] = true;
|
||||
|
||||
/**
|
||||
* Play nice with other plugins. If there's no database, don't delay the
|
||||
* connection process. Unfortunately, we can't attempt anything else and
|
||||
* we just have to hope either the database is waiting or someone will type
|
||||
* sm_reloadadmins.
|
||||
*/
|
||||
if (hDatabase == null)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similarly, if the cache is in the process of being rebuilt, don't delay
|
||||
* the user's normal connection flow. The database will soon auth the user
|
||||
* normally.
|
||||
*/
|
||||
if (RebuildCachePart[AdminCache_Admins] != 0)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* If someone has already assigned an admin ID (bad bad bad), don't
|
||||
* bother waiting.
|
||||
*/
|
||||
if (GetUserAdmin(client) != INVALID_ADMIN_ID)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
FetchUser(hDatabase, client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void OnReceiveUserGroups(Database db, DBResultSet rs, const char[] error, any data)
|
||||
{
|
||||
DataPack pk = view_as<DataPack>(data);
|
||||
pk.Reset();
|
||||
|
||||
int client = pk.ReadCell();
|
||||
int sequence = pk.ReadCell();
|
||||
|
||||
/**
|
||||
* Make sure it's the same client.
|
||||
*/
|
||||
if (PlayerSeq[client] != sequence)
|
||||
{
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
AdminId adm = view_as<AdminId>(pk.ReadCell());
|
||||
|
||||
/**
|
||||
* Someone could have sneakily changed the admin id while we waited.
|
||||
*/
|
||||
if (GetUserAdmin(client) != adm)
|
||||
{
|
||||
NotifyPostAdminCheck(client);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if we got results.
|
||||
*/
|
||||
if (rs == null)
|
||||
{
|
||||
char query[255];
|
||||
pk.ReadString(query, sizeof(query));
|
||||
LogError("SQL error receiving user: %s", error);
|
||||
LogError("Query dump: %s", query);
|
||||
NotifyPostAdminCheck(client);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
char name[80];
|
||||
GroupId grp;
|
||||
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, name, sizeof(name));
|
||||
|
||||
if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Binding user group (%d, %d, %d, %s, %d)", client, sequence, adm, name, grp);
|
||||
#endif
|
||||
|
||||
adm.InheritGroup(grp);
|
||||
}
|
||||
|
||||
/**
|
||||
* We're DONE! Omg.
|
||||
*/
|
||||
NotifyPostAdminCheck(client);
|
||||
delete pk;
|
||||
}
|
||||
|
||||
public void OnReceiveUser(Database db, DBResultSet rs, const char[] error, any data)
|
||||
{
|
||||
DataPack pk = view_as<DataPack>(data);
|
||||
pk.Reset();
|
||||
|
||||
int client = pk.ReadCell();
|
||||
|
||||
/**
|
||||
* Check if this is the latest result request.
|
||||
*/
|
||||
int sequence = pk.ReadCell();
|
||||
if (PlayerSeq[client] != sequence)
|
||||
{
|
||||
/* Discard everything, since we're out of sequence. */
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we need to use the results, make sure they succeeded.
|
||||
*/
|
||||
if (rs == null)
|
||||
{
|
||||
char query[255];
|
||||
pk.ReadString(query, sizeof(query));
|
||||
LogError("SQL error receiving user: %s", error);
|
||||
LogError("Query dump: %s", query);
|
||||
RunAdminCacheChecks(client);
|
||||
NotifyPostAdminCheck(client);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
int num_accounts = rs.RowCount;
|
||||
if (num_accounts == 0)
|
||||
{
|
||||
RunAdminCacheChecks(client);
|
||||
NotifyPostAdminCheck(client);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
char authtype[16];
|
||||
char identity[80];
|
||||
char password[80];
|
||||
char flags[32];
|
||||
char name[80];
|
||||
int immunity, id;
|
||||
AdminId adm;
|
||||
|
||||
/**
|
||||
* Cache user info -- [0] = db id, [1] = cache id, [2] = groups
|
||||
*/
|
||||
int[][] user_lookup = new int[num_accounts][3];
|
||||
int total_users = 0;
|
||||
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
id = rs.FetchInt(0);
|
||||
rs.FetchString(1, authtype, sizeof(authtype));
|
||||
rs.FetchString(2, identity, sizeof(identity));
|
||||
rs.FetchString(3, password, sizeof(password));
|
||||
rs.FetchString(4, flags, sizeof(flags));
|
||||
rs.FetchString(5, name, sizeof(name));
|
||||
immunity = rs.FetchInt(7);
|
||||
|
||||
/* For dynamic admins we clear anything already in the cache. */
|
||||
if ((adm = FindAdminByIdentity(authtype, identity)) != INVALID_ADMIN_ID)
|
||||
{
|
||||
RemoveAdmin(adm);
|
||||
}
|
||||
|
||||
adm = CreateAdmin(name);
|
||||
if (!adm.BindIdentity(authtype, identity))
|
||||
{
|
||||
LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
|
||||
continue;
|
||||
}
|
||||
|
||||
user_lookup[total_users][0] = id;
|
||||
user_lookup[total_users][1] = view_as<int>(adm);
|
||||
user_lookup[total_users][2] = rs.FetchInt(6);
|
||||
total_users++;
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s,%d):%d:%d", id, authtype, identity, password, flags, name, immunity, adm, user_lookup[total_users-1][2]);
|
||||
#endif
|
||||
|
||||
/* See if this admin wants a password */
|
||||
if (password[0] != '\0')
|
||||
{
|
||||
adm.SetPassword(password);
|
||||
}
|
||||
|
||||
adm.ImmunityLevel = immunity;
|
||||
|
||||
/* Apply each flag */
|
||||
int len = strlen(flags);
|
||||
AdminFlag flag;
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
if (!FindFlagByChar(flags[i], flag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
adm.SetFlag(flag, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try binding the user.
|
||||
*/
|
||||
int group_count = 0;
|
||||
RunAdminCacheChecks(client);
|
||||
adm = GetUserAdmin(client);
|
||||
id = 0;
|
||||
|
||||
|
||||
for (int i=0; i<total_users; i++)
|
||||
{
|
||||
if (user_lookup[i][1] == view_as<int>(adm))
|
||||
{
|
||||
id = user_lookup[i][0];
|
||||
group_count = user_lookup[i][2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Binding client (%d, %d) resulted in: (%d, %d, %d)", client, sequence, id, adm, group_count);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If we can't verify that we assigned a database admin, or the user has no
|
||||
* groups, don't bother doing anything.
|
||||
*/
|
||||
if (!id || !group_count)
|
||||
{
|
||||
NotifyPostAdminCheck(client);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has groups -- we need to fetch them!
|
||||
*/
|
||||
char query[255];
|
||||
Format(query, sizeof(query), "SELECT g.name FROM sm_admins_groups ag JOIN sm_groups g ON ag.group_id = g.id WHERE ag.admin_id = %d", id);
|
||||
|
||||
pk.Reset();
|
||||
pk.WriteCell(client);
|
||||
pk.WriteCell(sequence);
|
||||
pk.WriteCell(adm);
|
||||
pk.WriteString(query);
|
||||
|
||||
db.Query(OnReceiveUserGroups, query, pk, DBPrio_High);
|
||||
}
|
||||
|
||||
void FetchUser(Database db, int client)
|
||||
{
|
||||
char name[MAX_NAME_LENGTH];
|
||||
char safe_name[(MAX_NAME_LENGTH * 2) - 1];
|
||||
char steamid[32];
|
||||
char steamidalt[32];
|
||||
char ipaddr[24];
|
||||
|
||||
/**
|
||||
* Get authentication information from the client.
|
||||
*/
|
||||
GetClientName(client, name, sizeof(name));
|
||||
GetClientIP(client, ipaddr, sizeof(ipaddr));
|
||||
|
||||
steamid[0] = '\0';
|
||||
if (GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid)))
|
||||
{
|
||||
if (StrEqual(steamid, "STEAM_ID_LAN"))
|
||||
{
|
||||
steamid[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
db.Escape(name, safe_name, sizeof(safe_name));
|
||||
|
||||
/**
|
||||
* Construct the query using the information the user gave us.
|
||||
*/
|
||||
char query[512];
|
||||
int len = 0;
|
||||
|
||||
len += Format(query[len], sizeof(query)-len, "SELECT a.id, a.authtype, a.identity, a.password, a.flags, a.name, COUNT(ag.group_id), immunity");
|
||||
len += Format(query[len], sizeof(query)-len, " FROM sm_admins a LEFT JOIN sm_admins_groups ag ON a.id = ag.admin_id WHERE ");
|
||||
len += Format(query[len], sizeof(query)-len, " (a.authtype = 'ip' AND a.identity = '%s')", ipaddr);
|
||||
len += Format(query[len], sizeof(query)-len, " OR (a.authtype = 'name' AND a.identity = '%s')", safe_name);
|
||||
if (steamid[0] != '\0')
|
||||
{
|
||||
strcopy(steamidalt, sizeof(steamidalt), steamid);
|
||||
steamidalt[6] = (steamid[6] == '0') ? '1' : '0';
|
||||
|
||||
len += Format(query[len], sizeof(query)-len, " OR (a.authtype = 'steam' AND (a.identity = '%s' OR a.identity = '%s'))", steamid, steamidalt);
|
||||
}
|
||||
len += Format(query[len], sizeof(query)-len, " GROUP BY a.id");
|
||||
|
||||
/**
|
||||
* Send the actual query.
|
||||
*/
|
||||
PlayerSeq[client] = ++g_sequence;
|
||||
|
||||
DataPack pk = new DataPack();
|
||||
pk.WriteCell(client);
|
||||
pk.WriteCell(PlayerSeq[client]);
|
||||
pk.WriteString(query);
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Sending user query: %s", query);
|
||||
#endif
|
||||
|
||||
db.Query(OnReceiveUser, query, pk, DBPrio_High);
|
||||
}
|
||||
|
||||
void FetchUsersWeCan(Database db)
|
||||
{
|
||||
for (int i=1; i<=MaxClients; i++)
|
||||
{
|
||||
if (PlayerAuth[i] && GetUserAdmin(i) == INVALID_ADMIN_ID)
|
||||
{
|
||||
FetchUser(db, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This round of updates is done. Go in peace.
|
||||
*/
|
||||
RebuildCachePart[AdminCache_Admins] = 0;
|
||||
}
|
||||
|
||||
public void OnReceiveGroupImmunity(Database db, DBResultSet rs, const char[] error, any data)
|
||||
{
|
||||
DataPack pk = view_as<DataPack>(data);
|
||||
pk.Reset();
|
||||
|
||||
/**
|
||||
* Check if this is the latest result request.
|
||||
*/
|
||||
int sequence = pk.ReadCell();
|
||||
if (RebuildCachePart[AdminCache_Groups] != sequence)
|
||||
{
|
||||
/* Discard everything, since we're out of sequence. */
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we need to use the results, make sure they succeeded.
|
||||
*/
|
||||
if (rs == null)
|
||||
{
|
||||
char query[255];
|
||||
pk.ReadString(query, sizeof(query));
|
||||
LogError("SQL error receiving group immunity: %s", error);
|
||||
LogError("Query dump: %s", query);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're done with the pack forever. */
|
||||
delete pk;
|
||||
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
char group1[80];
|
||||
char group2[80];
|
||||
GroupId grp, other;
|
||||
|
||||
rs.FetchString(0, group1, sizeof(group1));
|
||||
rs.FetchString(1, group2, sizeof(group2));
|
||||
|
||||
if (((grp = FindAdmGroup(group1)) == INVALID_GROUP_ID)
|
||||
|| (other = FindAdmGroup(group2)) == INVALID_GROUP_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
grp.AddGroupImmunity(other);
|
||||
#if defined _DEBUG
|
||||
PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", grp, other);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Clear the sequence so another connect doesn't refetch */
|
||||
RebuildCachePart[AdminCache_Groups] = 0;
|
||||
}
|
||||
|
||||
public void OnReceiveGroupOverrides(Database db, DBResultSet rs, const char[] error, any data)
|
||||
{
|
||||
DataPack pk = view_as<DataPack>(data);
|
||||
pk.Reset();
|
||||
|
||||
/**
|
||||
* Check if this is the latest result request.
|
||||
*/
|
||||
int sequence = pk.ReadCell();
|
||||
if (RebuildCachePart[AdminCache_Groups] != sequence)
|
||||
{
|
||||
/* Discard everything, since we're out of sequence. */
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we need to use the results, make sure they succeeded.
|
||||
*/
|
||||
if (rs == null)
|
||||
{
|
||||
char query[255];
|
||||
pk.ReadString(query, sizeof(query));
|
||||
LogError("SQL error receiving group overrides: %s", error);
|
||||
LogError("Query dump: %s", query);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the overrides.
|
||||
*/
|
||||
char name[80];
|
||||
char type[16];
|
||||
char command[64];
|
||||
char access[16];
|
||||
GroupId grp;
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, name, sizeof(name));
|
||||
rs.FetchString(1, type, sizeof(type));
|
||||
rs.FetchString(2, command, sizeof(command));
|
||||
rs.FetchString(3, access, sizeof(access));
|
||||
|
||||
/* Find the group. This is actually faster than doing the ID lookup. */
|
||||
if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID)
|
||||
{
|
||||
/* Oh well, just ignore it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
OverrideType o_type = Override_Command;
|
||||
if (StrEqual(type, "group"))
|
||||
{
|
||||
o_type = Override_CommandGroup;
|
||||
}
|
||||
|
||||
OverrideRule o_rule = Command_Deny;
|
||||
if (StrEqual(access, "allow"))
|
||||
{
|
||||
o_rule = Command_Allow;
|
||||
}
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", grp, command, o_type, o_rule);
|
||||
#endif
|
||||
|
||||
grp.AddCommandOverride(command, o_type, o_rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* It's time to get the group immunity list.
|
||||
*/
|
||||
int len = 0;
|
||||
char query[256];
|
||||
len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi");
|
||||
len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id ");
|
||||
len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id");
|
||||
|
||||
pk.Reset();
|
||||
pk.WriteCell(sequence);
|
||||
pk.WriteString(query);
|
||||
|
||||
db.Query(OnReceiveGroupImmunity, query, pk, DBPrio_High);
|
||||
}
|
||||
|
||||
public void OnReceiveGroups(Database db, DBResultSet rs, const char[] error, any data)
|
||||
{
|
||||
DataPack pk = view_as<DataPack>(data);
|
||||
pk.Reset();
|
||||
|
||||
/**
|
||||
* Check if this is the latest result request.
|
||||
*/
|
||||
int sequence = pk.ReadCell();
|
||||
if (RebuildCachePart[AdminCache_Groups] != sequence)
|
||||
{
|
||||
/* Discard everything, since we're out of sequence. */
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we need to use the results, make sure they succeeded.
|
||||
*/
|
||||
if (rs == null)
|
||||
{
|
||||
char query[255];
|
||||
pk.ReadString(query, sizeof(query));
|
||||
LogError("SQL error receiving groups: %s", error);
|
||||
LogError("Query dump: %s", query);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Now start fetching groups.
|
||||
*/
|
||||
char flags[32];
|
||||
char name[128];
|
||||
int immunity;
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, flags, sizeof(flags));
|
||||
rs.FetchString(1, name, sizeof(name));
|
||||
immunity = rs.FetchInt(2);
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Adding group (%d, %s, %s)", immunity, flags, name);
|
||||
#endif
|
||||
|
||||
/* Find or create the group */
|
||||
GroupId grp;
|
||||
if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID)
|
||||
{
|
||||
grp = CreateAdmGroup(name);
|
||||
}
|
||||
|
||||
/* Add flags from the database to the group */
|
||||
int num_flag_chars = strlen(flags);
|
||||
for (int i=0; i<num_flag_chars; i++)
|
||||
{
|
||||
AdminFlag flag;
|
||||
if (!FindFlagByChar(flags[i], flag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
grp.SetFlag(flag, true);
|
||||
}
|
||||
|
||||
grp.ImmunityLevel = immunity;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's time to get the group override list.
|
||||
*/
|
||||
char query[255];
|
||||
Format(query,
|
||||
sizeof(query),
|
||||
"SELECT g.name, og.type, og.name, og.access FROM sm_group_overrides og JOIN sm_groups g ON og.group_id = g.id ORDER BY g.id DESC");
|
||||
|
||||
pk.Reset();
|
||||
pk.WriteCell(sequence);
|
||||
pk.WriteString(query);
|
||||
|
||||
db.Query(OnReceiveGroupOverrides, query, pk, DBPrio_High);
|
||||
}
|
||||
|
||||
void FetchGroups(Database db, int sequence)
|
||||
{
|
||||
char query[255];
|
||||
|
||||
Format(query, sizeof(query), "SELECT flags, name, immunity_level FROM sm_groups");
|
||||
|
||||
DataPack pk = new DataPack();
|
||||
pk.WriteCell(sequence);
|
||||
pk.WriteString(query);
|
||||
|
||||
db.Query(OnReceiveGroups, query, pk, DBPrio_High);
|
||||
}
|
||||
|
||||
public void OnReceiveOverrides(Database db, DBResultSet rs, const char[] error, any data)
|
||||
{
|
||||
DataPack pk = view_as<DataPack>(data);
|
||||
pk.Reset();
|
||||
|
||||
/**
|
||||
* Check if this is the latest result request.
|
||||
*/
|
||||
int sequence = pk.ReadCell();
|
||||
if (RebuildCachePart[AdminCache_Overrides] != sequence)
|
||||
{
|
||||
/* Discard everything, since we're out of sequence. */
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we need to use the results, make sure they succeeded.
|
||||
*/
|
||||
if (rs == null)
|
||||
{
|
||||
char query[255];
|
||||
pk.ReadString(query, sizeof(query));
|
||||
LogError("SQL error receiving overrides: %s", error);
|
||||
LogError("Query dump: %s", query);
|
||||
delete pk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* We're done with you, now.
|
||||
*/
|
||||
delete pk;
|
||||
|
||||
char type[64];
|
||||
char name[64];
|
||||
char flags[32];
|
||||
int flag_bits;
|
||||
while (rs.FetchRow())
|
||||
{
|
||||
rs.FetchString(0, type, sizeof(type));
|
||||
rs.FetchString(1, name, sizeof(name));
|
||||
rs.FetchString(2, flags, sizeof(flags));
|
||||
|
||||
#if defined _DEBUG
|
||||
PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
|
||||
#endif
|
||||
|
||||
flag_bits = ReadFlagString(flags);
|
||||
if (StrEqual(type, "command"))
|
||||
{
|
||||
AddCommandOverride(name, Override_Command, flag_bits);
|
||||
} else if (StrEqual(type, "group")) {
|
||||
AddCommandOverride(name, Override_CommandGroup, flag_bits);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the sequence so another connect doesn't refetch */
|
||||
RebuildCachePart[AdminCache_Overrides] = 0;
|
||||
}
|
||||
|
||||
void FetchOverrides(Database db, int sequence)
|
||||
{
|
||||
char query[255];
|
||||
|
||||
Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
|
||||
|
||||
DataPack pk = new DataPack();
|
||||
pk.WriteCell(sequence);
|
||||
pk.WriteString(query);
|
||||
|
||||
db.Query(OnReceiveOverrides, query, pk, DBPrio_High);
|
||||
}
|
157
scripting/temp/adminhelp.sp
Normal file
157
scripting/temp/adminhelp.sp
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Admin Help Plugin
|
||||
* Displays and searches SourceMod commands and descriptions.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
#define COMMANDS_PER_PAGE 10
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Admin Help",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Display command information",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("adminhelp.phrases");
|
||||
RegConsoleCmd("sm_help", HelpCmd, "Displays SourceMod commands and descriptions");
|
||||
RegConsoleCmd("sm_searchcmd", HelpCmd, "Searches SourceMod commands");
|
||||
}
|
||||
|
||||
public Action HelpCmd(int client, int args)
|
||||
{
|
||||
char arg[64], CmdName[20];
|
||||
int PageNum = 1;
|
||||
bool DoSearch;
|
||||
|
||||
GetCmdArg(0, CmdName, sizeof(CmdName));
|
||||
|
||||
if (GetCmdArgs() >= 1)
|
||||
{
|
||||
GetCmdArg(1, arg, sizeof(arg));
|
||||
StringToIntEx(arg, PageNum);
|
||||
PageNum = (PageNum <= 0) ? 1 : PageNum;
|
||||
}
|
||||
|
||||
DoSearch = (strcmp("sm_help", CmdName) == 0) ? false : true;
|
||||
|
||||
if (GetCmdReplySource() == SM_REPLY_TO_CHAT)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "See console for output");
|
||||
}
|
||||
|
||||
char Name[64];
|
||||
char Desc[255];
|
||||
char NoDesc[128];
|
||||
int Flags;
|
||||
Handle CmdIter = GetCommandIterator();
|
||||
|
||||
FormatEx(NoDesc, sizeof(NoDesc), "%T", "No description available", client);
|
||||
|
||||
if (DoSearch)
|
||||
{
|
||||
int i = 1;
|
||||
while (ReadCommandIterator(CmdIter, Name, sizeof(Name), Flags, Desc, sizeof(Desc)))
|
||||
{
|
||||
if ((StrContains(Name, arg, false) != -1) && CheckCommandAccess(client, Name, Flags))
|
||||
{
|
||||
PrintToConsole(client, "[%03d] %s - %s", i++, Name, (Desc[0] == '\0') ? NoDesc : Desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
PrintToConsole(client, "%t", "No matching results found");
|
||||
}
|
||||
} else {
|
||||
PrintToConsole(client, "%t", "SM help commands");
|
||||
|
||||
/* Skip the first N commands if we need to */
|
||||
if (PageNum > 1)
|
||||
{
|
||||
int i;
|
||||
int EndCmd = (PageNum-1) * COMMANDS_PER_PAGE - 1;
|
||||
for (i=0; ReadCommandIterator(CmdIter, Name, sizeof(Name), Flags, Desc, sizeof(Desc)) && i<EndCmd; )
|
||||
{
|
||||
if (CheckCommandAccess(client, Name, Flags))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
PrintToConsole(client, "%t", "No commands available");
|
||||
delete CmdIter;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start printing the commands to the client */
|
||||
int i;
|
||||
int StartCmd = (PageNum-1) * COMMANDS_PER_PAGE;
|
||||
for (i=0; ReadCommandIterator(CmdIter, Name, sizeof(Name), Flags, Desc, sizeof(Desc)) && i<COMMANDS_PER_PAGE; )
|
||||
{
|
||||
if (CheckCommandAccess(client, Name, Flags))
|
||||
{
|
||||
i++;
|
||||
PrintToConsole(client, "[%03d] %s - %s", i+StartCmd, Name, (Desc[0] == '\0') ? NoDesc : Desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
PrintToConsole(client, "%t", "No commands available");
|
||||
} else {
|
||||
PrintToConsole(client, "%t", "Entries n - m in page k", StartCmd+1, i+StartCmd, PageNum);
|
||||
}
|
||||
|
||||
/* Test if there are more commands available */
|
||||
if (ReadCommandIterator(CmdIter, Name, sizeof(Name), Flags, Desc, sizeof(Desc)) && CheckCommandAccess(client, Name, Flags))
|
||||
{
|
||||
PrintToConsole(client, "%t", "Type sm_help to see more", PageNum+1);
|
||||
}
|
||||
}
|
||||
|
||||
delete CmdIter;
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
269
scripting/temp/adminmenu.sp
Normal file
269
scripting/temp/adminmenu.sp
Normal file
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Admin Menu Plugin
|
||||
* Creates the base admin menu, for plugins to add items to.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <topmenus>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Admin Menu",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Administration Menu",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
/* Forwards */
|
||||
Handle hOnAdminMenuReady = null;
|
||||
Handle hOnAdminMenuCreated = null;
|
||||
|
||||
/* Menus */
|
||||
TopMenu hAdminMenu;
|
||||
|
||||
/* Top menu objects */
|
||||
TopMenuObject obj_playercmds = INVALID_TOPMENUOBJECT;
|
||||
TopMenuObject obj_servercmds = INVALID_TOPMENUOBJECT;
|
||||
TopMenuObject obj_votingcmds = INVALID_TOPMENUOBJECT;
|
||||
|
||||
#include "adminmenu/dynamicmenu.sp"
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
||||
{
|
||||
CreateNative("GetAdminTopMenu", __GetAdminTopMenu);
|
||||
CreateNative("AddTargetsToMenu", __AddTargetsToMenu);
|
||||
CreateNative("AddTargetsToMenu2", __AddTargetsToMenu2);
|
||||
RegPluginLibrary("adminmenu");
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("adminmenu.phrases");
|
||||
|
||||
hOnAdminMenuCreated = CreateGlobalForward("OnAdminMenuCreated", ET_Ignore, Param_Cell);
|
||||
hOnAdminMenuReady = CreateGlobalForward("OnAdminMenuReady", ET_Ignore, Param_Cell);
|
||||
|
||||
RegAdminCmd("sm_admin", Command_DisplayMenu, ADMFLAG_GENERIC, "Displays the admin menu");
|
||||
}
|
||||
|
||||
public void OnConfigsExecuted()
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
char error[256];
|
||||
|
||||
BuildPath(Path_SM, path, sizeof(path), "configs/adminmenu_sorting.txt");
|
||||
|
||||
if (!hAdminMenu.LoadConfig(path, error, sizeof(error)))
|
||||
{
|
||||
LogError("Could not load admin menu config (file \"%s\": %s)", path, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
ParseConfigs();
|
||||
}
|
||||
|
||||
public void OnAllPluginsLoaded()
|
||||
{
|
||||
hAdminMenu = new TopMenu(DefaultCategoryHandler);
|
||||
|
||||
obj_playercmds = hAdminMenu.AddCategory("PlayerCommands", DefaultCategoryHandler);
|
||||
obj_servercmds = hAdminMenu.AddCategory("ServerCommands", DefaultCategoryHandler);
|
||||
obj_votingcmds = hAdminMenu.AddCategory("VotingCommands", DefaultCategoryHandler);
|
||||
|
||||
BuildDynamicMenu();
|
||||
|
||||
Call_StartForward(hOnAdminMenuCreated);
|
||||
Call_PushCell(hAdminMenu);
|
||||
Call_Finish();
|
||||
|
||||
Call_StartForward(hOnAdminMenuReady);
|
||||
Call_PushCell(hAdminMenu);
|
||||
Call_Finish();
|
||||
}
|
||||
|
||||
public void DefaultCategoryHandler(TopMenu topmenu,
|
||||
TopMenuAction action,
|
||||
TopMenuObject object_id,
|
||||
int param,
|
||||
char[] buffer,
|
||||
int maxlength)
|
||||
{
|
||||
if (action == TopMenuAction_DisplayTitle)
|
||||
{
|
||||
if (object_id == INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
Format(buffer, maxlength, "%T:", "Admin Menu", param);
|
||||
}
|
||||
else if (object_id == obj_playercmds)
|
||||
{
|
||||
Format(buffer, maxlength, "%T:", "Player Commands", param);
|
||||
}
|
||||
else if (object_id == obj_servercmds)
|
||||
{
|
||||
Format(buffer, maxlength, "%T:", "Server Commands", param);
|
||||
}
|
||||
else if (object_id == obj_votingcmds)
|
||||
{
|
||||
Format(buffer, maxlength, "%T:", "Voting Commands", param);
|
||||
}
|
||||
}
|
||||
else if (action == TopMenuAction_DisplayOption)
|
||||
{
|
||||
if (object_id == obj_playercmds)
|
||||
{
|
||||
Format(buffer, maxlength, "%T", "Player Commands", param);
|
||||
}
|
||||
else if (object_id == obj_servercmds)
|
||||
{
|
||||
Format(buffer, maxlength, "%T", "Server Commands", param);
|
||||
}
|
||||
else if (object_id == obj_votingcmds)
|
||||
{
|
||||
Format(buffer, maxlength, "%T", "Voting Commands", param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int __GetAdminTopMenu(Handle plugin, int numParams)
|
||||
{
|
||||
return view_as<int>(hAdminMenu);
|
||||
}
|
||||
|
||||
public int __AddTargetsToMenu(Handle plugin, int numParams)
|
||||
{
|
||||
bool alive_only = false;
|
||||
|
||||
if (numParams >= 4)
|
||||
{
|
||||
alive_only = GetNativeCell(4);
|
||||
}
|
||||
|
||||
return UTIL_AddTargetsToMenu(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3), alive_only);
|
||||
}
|
||||
|
||||
public int __AddTargetsToMenu2(Handle plugin, int numParams)
|
||||
{
|
||||
return UTIL_AddTargetsToMenu2(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3));
|
||||
}
|
||||
|
||||
public Action Command_DisplayMenu(int client, int args)
|
||||
{
|
||||
if (client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Command is in-game only");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
hAdminMenu.Display(client, TopMenuPosition_Start);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
stock int UTIL_AddTargetsToMenu2(Menu menu, int source_client, int flags)
|
||||
{
|
||||
char user_id[12];
|
||||
char name[MAX_NAME_LENGTH];
|
||||
char display[MAX_NAME_LENGTH+12];
|
||||
|
||||
int num_clients;
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientConnected(i) || IsClientInKickQueue(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS)
|
||||
&& IsFakeClient(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((flags & COMMAND_FILTER_CONNECTED) != COMMAND_FILTER_CONNECTED)
|
||||
&& !IsClientInGame(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((flags & COMMAND_FILTER_ALIVE) == COMMAND_FILTER_ALIVE)
|
||||
&& !IsPlayerAlive(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((flags & COMMAND_FILTER_DEAD) == COMMAND_FILTER_DEAD)
|
||||
&& IsPlayerAlive(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((source_client && ((flags & COMMAND_FILTER_NO_IMMUNITY) != COMMAND_FILTER_NO_IMMUNITY))
|
||||
&& !CanUserTarget(source_client, i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IntToString(GetClientUserId(i), user_id, sizeof(user_id));
|
||||
GetClientName(i, name, sizeof(name));
|
||||
Format(display, sizeof(display), "%s (%s)", name, user_id);
|
||||
menu.AddItem(user_id, display);
|
||||
num_clients++;
|
||||
}
|
||||
|
||||
return num_clients;
|
||||
}
|
||||
|
||||
stock int UTIL_AddTargetsToMenu(Menu menu, int source_client, bool in_game_only, bool alive_only)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (!in_game_only)
|
||||
{
|
||||
flags |= COMMAND_FILTER_CONNECTED;
|
||||
}
|
||||
|
||||
if (alive_only)
|
||||
{
|
||||
flags |= COMMAND_FILTER_ALIVE;
|
||||
}
|
||||
|
||||
return UTIL_AddTargetsToMenu2(menu, source_client, flags);
|
||||
}
|
317
scripting/temp/advertisements.sp
Normal file
317
scripting/temp/advertisements.sp
Normal file
@@ -0,0 +1,317 @@
|
||||
#include <sourcemod>
|
||||
#include <colorvariables>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <updater>
|
||||
#include "advertisements/topcolors.sp"
|
||||
|
||||
#pragma newdecls required
|
||||
#pragma semicolon 1
|
||||
|
||||
#define PL_VERSION "2.0.2"
|
||||
#define UPDATE_URL "http://ErikMinekus.github.io/sm-advertisements/update.txt"
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Advertisements",
|
||||
author = "Tsunami",
|
||||
description = "Display advertisements",
|
||||
version = PL_VERSION,
|
||||
url = "http://www.tsunami-productions.nl"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Globals
|
||||
*/
|
||||
KeyValues g_hAdvertisements;
|
||||
ConVar g_hEnabled;
|
||||
ConVar g_hFile;
|
||||
ConVar g_hInterval;
|
||||
Handle g_hTimer;
|
||||
|
||||
|
||||
/**
|
||||
* Plugin Forwards
|
||||
*/
|
||||
public void OnPluginStart()
|
||||
{
|
||||
CreateConVar("sm_advertisements_version", PL_VERSION, "Display advertisements", FCVAR_NOTIFY);
|
||||
g_hEnabled = CreateConVar("sm_advertisements_enabled", "1", "Enable/disable displaying advertisements.");
|
||||
g_hFile = CreateConVar("sm_advertisements_file", "advertisements.txt", "File to read the advertisements from.");
|
||||
g_hInterval = CreateConVar("sm_advertisements_interval", "30", "Amount of seconds between advertisements.");
|
||||
|
||||
g_hFile.AddChangeHook(ConVarChange_File);
|
||||
g_hInterval.AddChangeHook(ConVarChange_Interval);
|
||||
|
||||
RegServerCmd("sm_advertisements_reload", Command_ReloadAds, "Reload the advertisements");
|
||||
|
||||
AddTopColors();
|
||||
|
||||
if (LibraryExists("updater")) {
|
||||
Updater_AddPlugin(UPDATE_URL);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
ParseAds();
|
||||
|
||||
g_hTimer = CreateTimer(g_hInterval.IntValue * 1.0, Timer_DisplayAd, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
public void OnLibraryAdded(const char[] name)
|
||||
{
|
||||
if (StrEqual(name, "updater")) {
|
||||
Updater_AddPlugin(UPDATE_URL);
|
||||
}
|
||||
}
|
||||
|
||||
public void ConVarChange_File(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
ParseAds();
|
||||
}
|
||||
|
||||
public void ConVarChange_Interval(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
if (g_hTimer) {
|
||||
KillTimer(g_hTimer);
|
||||
}
|
||||
|
||||
g_hTimer = CreateTimer(g_hInterval.IntValue * 1.0, Timer_DisplayAd, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commands
|
||||
*/
|
||||
public Action Command_ReloadAds(int args)
|
||||
{
|
||||
ParseAds();
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Menu Handlers
|
||||
*/
|
||||
public int Handler_DoNothing(Menu menu, MenuAction action, int param1, int param2) {}
|
||||
|
||||
|
||||
/**
|
||||
* Timers
|
||||
*/
|
||||
public Action Timer_DisplayAd(Handle timer)
|
||||
{
|
||||
if (!g_hEnabled.BoolValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
char sCenter[1024], sChat[1024], sHint[1024], sMenu[1024], sTop[1024], sFlags[16];
|
||||
g_hAdvertisements.GetString("center", sCenter, sizeof(sCenter));
|
||||
g_hAdvertisements.GetString("chat", sChat, sizeof(sChat));
|
||||
g_hAdvertisements.GetString("hint", sHint, sizeof(sHint));
|
||||
g_hAdvertisements.GetString("menu", sMenu, sizeof(sMenu));
|
||||
g_hAdvertisements.GetString("top", sTop, sizeof(sTop));
|
||||
g_hAdvertisements.GetString("flags", sFlags, sizeof(sFlags), "none");
|
||||
int iFlags = ReadFlagString(sFlags);
|
||||
bool bAdmins = StrEqual(sFlags, ""),
|
||||
bFlags = !StrEqual(sFlags, "none");
|
||||
|
||||
if (sCenter[0]) {
|
||||
ProcessVariables(sCenter);
|
||||
CRemoveColors(sCenter, sizeof(sCenter));
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++) {
|
||||
if (IsClientInGame(i) && !IsFakeClient(i) &&
|
||||
((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) ||
|
||||
(bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) {
|
||||
PrintCenterText(i, sCenter);
|
||||
|
||||
DataPack hCenterAd;
|
||||
CreateDataTimer(1.0, Timer_CenterAd, hCenterAd, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
|
||||
hCenterAd.WriteCell(i);
|
||||
hCenterAd.WriteString(sCenter);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sHint[0]) {
|
||||
ProcessVariables(sHint);
|
||||
CRemoveColors(sHint, sizeof(sHint));
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++) {
|
||||
if (IsClientInGame(i) && !IsFakeClient(i) &&
|
||||
((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) ||
|
||||
(bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) {
|
||||
PrintHintText(i, sHint);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sMenu[0]) {
|
||||
ProcessVariables(sMenu);
|
||||
CRemoveColors(sMenu, sizeof(sMenu));
|
||||
|
||||
Panel hPl = new Panel();
|
||||
hPl.DrawText(sMenu);
|
||||
hPl.CurrentKey = 10;
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++) {
|
||||
if (IsClientInGame(i) && !IsFakeClient(i) &&
|
||||
((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) ||
|
||||
(bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) {
|
||||
hPl.Send(i, Handler_DoNothing, 10);
|
||||
}
|
||||
}
|
||||
|
||||
delete hPl;
|
||||
}
|
||||
if (sChat[0]) {
|
||||
bool bTeamColor = StrContains(sChat, "{teamcolor}", false) != -1;
|
||||
|
||||
ProcessVariables(sChat);
|
||||
CProcessVariables(sChat, sizeof(sChat));
|
||||
CAddWhiteSpace(sChat, sizeof(sChat));
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++) {
|
||||
if (IsClientInGame(i) && !IsFakeClient(i) &&
|
||||
((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) ||
|
||||
(bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) {
|
||||
if (bTeamColor) {
|
||||
CSayText2(i, sChat, i);
|
||||
} else {
|
||||
PrintToChat(i, sChat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sTop[0]) {
|
||||
int iStart = 0,
|
||||
aColor[4] = {255, 255, 255, 255};
|
||||
|
||||
ParseTopColor(sTop, iStart, aColor);
|
||||
ProcessVariables(sTop[iStart]);
|
||||
|
||||
KeyValues hKv = new KeyValues("Stuff", "title", sTop[iStart]);
|
||||
hKv.SetColor4("color", aColor);
|
||||
hKv.SetNum("level", 1);
|
||||
hKv.SetNum("time", 10);
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++) {
|
||||
if (IsClientInGame(i) && !IsFakeClient(i) &&
|
||||
((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) ||
|
||||
(bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) {
|
||||
CreateDialog(i, hKv, DialogType_Msg);
|
||||
}
|
||||
}
|
||||
|
||||
delete hKv;
|
||||
}
|
||||
|
||||
if (!g_hAdvertisements.GotoNextKey()) {
|
||||
g_hAdvertisements.Rewind();
|
||||
g_hAdvertisements.GotoFirstSubKey();
|
||||
}
|
||||
}
|
||||
|
||||
public Action Timer_CenterAd(Handle timer, DataPack pack)
|
||||
{
|
||||
char sCenter[1024];
|
||||
static int iCount = 0;
|
||||
|
||||
pack.Reset();
|
||||
int iClient = pack.ReadCell();
|
||||
pack.ReadString(sCenter, sizeof(sCenter));
|
||||
|
||||
if (!IsClientInGame(iClient) || ++iCount >= 5) {
|
||||
iCount = 0;
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
PrintCenterText(iClient, sCenter);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stocks
|
||||
*/
|
||||
void ParseAds()
|
||||
{
|
||||
delete g_hAdvertisements;
|
||||
g_hAdvertisements = CreateKeyValues("Advertisements");
|
||||
|
||||
char sFile[64], sPath[PLATFORM_MAX_PATH];
|
||||
g_hFile.GetString(sFile, sizeof(sFile));
|
||||
BuildPath(Path_SM, sPath, sizeof(sPath), "configs/%s", sFile);
|
||||
|
||||
if (!FileExists(sPath)) {
|
||||
SetFailState("File Not Found: %s", sPath);
|
||||
}
|
||||
|
||||
g_hAdvertisements.ImportFromFile(sPath);
|
||||
g_hAdvertisements.GotoFirstSubKey();
|
||||
}
|
||||
|
||||
void ProcessVariables(char sText[1024])
|
||||
{
|
||||
char sBuffer[64];
|
||||
if (StrContains(sText, "\\n") != -1) {
|
||||
Format(sBuffer, sizeof(sBuffer), "%c", 13);
|
||||
ReplaceString(sText, sizeof(sText), "\\n", sBuffer);
|
||||
}
|
||||
|
||||
if (StrContains(sText, "{currentmap}", false) != -1) {
|
||||
GetCurrentMap(sBuffer, sizeof(sBuffer));
|
||||
ReplaceString(sText, sizeof(sText), "{currentmap}", sBuffer, false);
|
||||
}
|
||||
|
||||
if (StrContains(sText, "{date}", false) != -1) {
|
||||
FormatTime(sBuffer, sizeof(sBuffer), "%m/%d/%Y");
|
||||
ReplaceString(sText, sizeof(sText), "{date}", sBuffer, false);
|
||||
}
|
||||
|
||||
if (StrContains(sText, "{time}", false) != -1) {
|
||||
FormatTime(sBuffer, sizeof(sBuffer), "%I:%M:%S%p");
|
||||
ReplaceString(sText, sizeof(sText), "{time}", sBuffer, false);
|
||||
}
|
||||
|
||||
if (StrContains(sText, "{time24}", false) != -1) {
|
||||
FormatTime(sBuffer, sizeof(sBuffer), "%H:%M:%S");
|
||||
ReplaceString(sText, sizeof(sText), "{time24}", sBuffer, false);
|
||||
}
|
||||
|
||||
if (StrContains(sText, "{timeleft}", false) != -1) {
|
||||
int iMins, iSecs, iTimeLeft;
|
||||
if (GetMapTimeLeft(iTimeLeft) && iTimeLeft > 0) {
|
||||
iMins = iTimeLeft / 60;
|
||||
iSecs = iTimeLeft % 60;
|
||||
}
|
||||
|
||||
Format(sBuffer, sizeof(sBuffer), "%d:%02d", iMins, iSecs);
|
||||
ReplaceString(sText, sizeof(sText), "{timeleft}", sBuffer, false);
|
||||
}
|
||||
|
||||
ConVar hConVar;
|
||||
char sConVar[64], sSearch[64], sReplace[64];
|
||||
int iEnd = -1, iStart = StrContains(sText, "{"), iStart2;
|
||||
while (iStart != -1) {
|
||||
iEnd = StrContains(sText[iStart + 1], "}");
|
||||
if (iEnd == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
strcopy(sConVar, iEnd + 1, sText[iStart + 1]);
|
||||
Format(sSearch, sizeof(sSearch), "{%s}", sConVar);
|
||||
|
||||
if ((hConVar = FindConVar(sConVar))) {
|
||||
hConVar.GetString(sReplace, sizeof(sReplace));
|
||||
ReplaceString(sText, sizeof(sText), sSearch, sReplace, false);
|
||||
}
|
||||
|
||||
iStart2 = StrContains(sText[iStart + 1], "{");
|
||||
if (iStart2 == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
iStart += iStart2 + 1;
|
||||
}
|
||||
}
|
120
scripting/temp/antiflood.sp
Normal file
120
scripting/temp/antiflood.sp
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Anti-Flood Plugin
|
||||
* Protects against chat flooding.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Anti-Flood",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Protects against chat flooding",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
float g_LastTime[MAXPLAYERS + 1] = {0.0, ...}; /* Last time player used say or say_team */
|
||||
int g_FloodTokens[MAXPLAYERS + 1] = {0, ...}; /* Number of flood tokens player has */
|
||||
|
||||
ConVar sm_flood_time; /* Handle to sm_flood_time convar */
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
sm_flood_time = CreateConVar("sm_flood_time", "0.75", "Amount of time allowed between chat messages");
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client)
|
||||
{
|
||||
g_LastTime[client] = 0.0;
|
||||
g_FloodTokens[client] = 0;
|
||||
}
|
||||
|
||||
float max_chat;
|
||||
|
||||
public bool OnClientFloodCheck(int client)
|
||||
{
|
||||
max_chat = sm_flood_time.FloatValue;
|
||||
|
||||
if (max_chat <= 0.0
|
||||
|| CheckCommandAccess(client, "sm_flood_access", ADMFLAG_ROOT, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_LastTime[client] >= GetGameTime())
|
||||
{
|
||||
/* If player has 3 or more flood tokens, block their message */
|
||||
if (g_FloodTokens[client] >= 3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnClientFloodResult(int client, bool blocked)
|
||||
{
|
||||
if (max_chat <= 0.0
|
||||
|| CheckCommandAccess(client, "sm_flood_access", ADMFLAG_ROOT, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float curTime = GetGameTime();
|
||||
float newTime = curTime + max_chat;
|
||||
|
||||
if (g_LastTime[client] >= curTime)
|
||||
{
|
||||
/* If the last message was blocked, update their time limit */
|
||||
if (blocked)
|
||||
{
|
||||
newTime += 3.0;
|
||||
}
|
||||
/* Add one flood token when player goes over chat time limit */
|
||||
else if (g_FloodTokens[client] < 3)
|
||||
{
|
||||
g_FloodTokens[client]++;
|
||||
}
|
||||
}
|
||||
else if (g_FloodTokens[client] > 0)
|
||||
{
|
||||
/* Remove one flood token when player chats within time limit (slow decay) */
|
||||
g_FloodTokens[client]--;
|
||||
}
|
||||
|
||||
g_LastTime[client] = newTime;
|
||||
}
|
933
scripting/temp/backpack-tf.sp
Normal file
933
scripting/temp/backpack-tf.sp
Normal file
@@ -0,0 +1,933 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <steamtools>
|
||||
#include <advanced_motd>
|
||||
|
||||
#define PLUGIN_VERSION "2.11.1"
|
||||
#define BACKPACK_TF_URL "http://backpack.tf/api/IGetPrices/v3/"
|
||||
#define ITEM_EARBUDS 143
|
||||
#define ITEM_REFINED 5002
|
||||
#define ITEM_KEY 5021
|
||||
#define ITEM_CRATE 5022
|
||||
#define ITEM_SALVAGED_CRATE 5068
|
||||
#define ITEM_HAUNTED_SCRAP 267
|
||||
#define ITEM_HEADTAKER 266
|
||||
#define QUALITY_UNIQUE "6"
|
||||
#define QUALITY_UNUSUAL "5"
|
||||
#define NOTIFICATION_SOUND "replay/downloadcomplete.wav"
|
||||
|
||||
public Plugin:myinfo = {
|
||||
name = "[TF2] backpack.tf Price Check",
|
||||
author = "Dr. McKay",
|
||||
description = "Provides a price check command for use with backpack.tf",
|
||||
version = PLUGIN_VERSION,
|
||||
url = "http://www.doctormckay.com"
|
||||
};
|
||||
|
||||
new lastCacheTime;
|
||||
new cacheTime;
|
||||
new Handle:backpackTFPricelist;
|
||||
|
||||
new Handle:qualityNameTrie;
|
||||
new Handle:unusualNameTrie;
|
||||
|
||||
new Handle:cvarBPCommand;
|
||||
new Handle:cvarDisplayUpdateNotification;
|
||||
new Handle:cvarDisplayChangedPrices;
|
||||
new Handle:cvarHudXPos;
|
||||
new Handle:cvarHudYPos;
|
||||
new Handle:cvarHudRed;
|
||||
new Handle:cvarHudGreen;
|
||||
new Handle:cvarHudBlue;
|
||||
new Handle:cvarHudHoldTime;
|
||||
new Handle:cvarMenuHoldTime;
|
||||
new Handle:cvarAPIKey;
|
||||
new Handle:cvarTag;
|
||||
|
||||
new Handle:hudText;
|
||||
new Handle:sv_tags;
|
||||
|
||||
new Float:budsToKeys;
|
||||
new Float:keysToRef;
|
||||
new Float:refToUsd;
|
||||
|
||||
#define UPDATE_FILE "backpack-tf.txt"
|
||||
#define CONVAR_PREFIX "backpack_tf"
|
||||
|
||||
#include "mckayupdater.sp"
|
||||
|
||||
public OnPluginStart() {
|
||||
cvarBPCommand = CreateConVar("backpack_tf_bp_command", "1", "Enables the !bp command for use with backpack.tf");
|
||||
cvarDisplayUpdateNotification = CreateConVar("backpack_tf_display_update_notification", "1", "Display a notification to clients when the cached price list has been updated?");
|
||||
cvarDisplayChangedPrices = CreateConVar("backpack_tf_display_changed_prices", "1", "If backpack_tf_display_update_notification is set to 1, display all prices that changed since the last update?");
|
||||
cvarHudXPos = CreateConVar("backpack_tf_update_notification_x_pos", "-1.0", "X position for HUD text from 0.0 to 1.0, -1.0 = center", _, true, -1.0, true, 1.0);
|
||||
cvarHudYPos = CreateConVar("backpack_tf_update_notification_y_pos", "0.1", "Y position for HUD text from 0.0 to 1.0, -1.0 = center", _, true, -1.0, true, 1.0);
|
||||
cvarHudRed = CreateConVar("backpack_tf_update_notification_red", "0", "Red value of HUD text", _, true, 0.0, true, 255.0);
|
||||
cvarHudGreen = CreateConVar("backpack_tf_update_notification_green", "255", "Green value of HUD text", _, true, 0.0, true, 255.0);
|
||||
cvarHudBlue = CreateConVar("backpack_tf_update_notification_blue", "0", "Blue value of HUD text", _, true, 0.0, true, 255.0);
|
||||
cvarHudHoldTime = CreateConVar("backpack_tf_update_notification_message_time", "5", "Seconds to keep each message in the update ticker on the screen", _, true, 0.0);
|
||||
cvarMenuHoldTime = CreateConVar("backpack_tf_menu_open_time", "0", "Time to keep the price panel open for, 0 = forever");
|
||||
cvarAPIKey = CreateConVar("backpack_tf_api_key", "", "API key obtained at http://backpack.tf/api/register/", FCVAR_PROTECTED);
|
||||
cvarTag = CreateConVar("backpack_tf_add_tag", "1", "If 1, adds the backpack.tf tag to your server's sv_tags, which is required to be listed on http://backpack.tf/servers", _, true, 0.0, true, 1.0);
|
||||
AutoExecConfig();
|
||||
|
||||
LoadTranslations("backpack-tf.phrases");
|
||||
|
||||
sv_tags = FindConVar("sv_tags");
|
||||
|
||||
RegConsoleCmd("sm_bp", Command_Backpack, "Usage: sm_bp <player>");
|
||||
RegConsoleCmd("sm_backpack", Command_Backpack, "Usage: sm_backpack <player>");
|
||||
|
||||
RegConsoleCmd("sm_pc", Command_PriceCheck, "Usage: sm_pc <item>");
|
||||
RegConsoleCmd("sm_pricecheck", Command_PriceCheck, "Usage: sm_pricecheck <item>");
|
||||
|
||||
RegAdminCmd("sm_updateprices", Command_UpdatePrices, ADMFLAG_ROOT, "Updates backpack.tf prices");
|
||||
|
||||
qualityNameTrie = CreateTrie();
|
||||
SetTrieString(qualityNameTrie, "0", "Normal");
|
||||
SetTrieString(qualityNameTrie, "1", "Genuine");
|
||||
SetTrieString(qualityNameTrie, "2", "rarity2");
|
||||
SetTrieString(qualityNameTrie, "3", "Vintage");
|
||||
SetTrieString(qualityNameTrie, "4", "rarity3");
|
||||
SetTrieString(qualityNameTrie, "5", "Unusual");
|
||||
SetTrieString(qualityNameTrie, "6", "Unique");
|
||||
SetTrieString(qualityNameTrie, "7", "Community");
|
||||
SetTrieString(qualityNameTrie, "8", "Valve");
|
||||
SetTrieString(qualityNameTrie, "9", "Self-Made");
|
||||
SetTrieString(qualityNameTrie, "10", "Customized");
|
||||
SetTrieString(qualityNameTrie, "11", "Strange");
|
||||
SetTrieString(qualityNameTrie, "12", "Completed");
|
||||
SetTrieString(qualityNameTrie, "13", "Haunted");
|
||||
SetTrieString(qualityNameTrie, "14", "Collector's");
|
||||
SetTrieString(qualityNameTrie, "300", "Uncraftable Vintage"); // custom for backpack.tf
|
||||
SetTrieString(qualityNameTrie, "600", "Uncraftable"); // custom for backpack.tf
|
||||
SetTrieString(qualityNameTrie, "1100", "Uncraftable Strange"); // custom for backpack.tf
|
||||
SetTrieString(qualityNameTrie, "1300", "Uncraftable Haunted"); // custom for backpack.tf
|
||||
|
||||
unusualNameTrie = CreateTrie();
|
||||
// Original effects
|
||||
SetTrieString(unusualNameTrie, "6", "Green Confetti");
|
||||
SetTrieString(unusualNameTrie, "7", "Purple Confetti");
|
||||
SetTrieString(unusualNameTrie, "8", "Haunted Ghosts");
|
||||
SetTrieString(unusualNameTrie, "9", "Green Energy");
|
||||
SetTrieString(unusualNameTrie, "10", "Purple Energy");
|
||||
SetTrieString(unusualNameTrie, "11", "Circling TF Logo");
|
||||
SetTrieString(unusualNameTrie, "12", "Massed Flies");
|
||||
SetTrieString(unusualNameTrie, "13", "Burning Flames");
|
||||
SetTrieString(unusualNameTrie, "14", "Scorching Flames");
|
||||
SetTrieString(unusualNameTrie, "15", "Searing Plasma");
|
||||
SetTrieString(unusualNameTrie, "16", "Vivid Plasma");
|
||||
SetTrieString(unusualNameTrie, "17", "Sunbeams");
|
||||
SetTrieString(unusualNameTrie, "18", "Circling Peace Sign");
|
||||
SetTrieString(unusualNameTrie, "19", "Circling Heart");
|
||||
// Batch 2
|
||||
SetTrieString(unusualNameTrie, "29", "Stormy Storm");
|
||||
SetTrieString(unusualNameTrie, "30", "Blizzardy Storm");
|
||||
SetTrieString(unusualNameTrie, "31", "Nuts n' Bolts");
|
||||
SetTrieString(unusualNameTrie, "32", "Orbiting Planets");
|
||||
SetTrieString(unusualNameTrie, "33", "Orbiting Fire");
|
||||
SetTrieString(unusualNameTrie, "34", "Bubbling");
|
||||
SetTrieString(unusualNameTrie, "35", "Smoking");
|
||||
SetTrieString(unusualNameTrie, "36", "Steaming");
|
||||
// Halloween
|
||||
SetTrieString(unusualNameTrie, "37", "Flaming Lantern");
|
||||
SetTrieString(unusualNameTrie, "38", "Cloudy Moon");
|
||||
SetTrieString(unusualNameTrie, "39", "Cauldron Bubbles");
|
||||
SetTrieString(unusualNameTrie, "40", "Eerie Orbiting Fire");
|
||||
SetTrieString(unusualNameTrie, "43", "Knifestorm");
|
||||
SetTrieString(unusualNameTrie, "44", "Misty Skull");
|
||||
SetTrieString(unusualNameTrie, "45", "Harvest Moon");
|
||||
SetTrieString(unusualNameTrie, "46", "It's A Secret To Everybody");
|
||||
SetTrieString(unusualNameTrie, "47", "Stormy 13th Hour");
|
||||
// Batch 3
|
||||
SetTrieString(unusualNameTrie, "56", "Kill-a-Watt");
|
||||
SetTrieString(unusualNameTrie, "57", "Terror-Watt");
|
||||
SetTrieString(unusualNameTrie, "58", "Cloud 9");
|
||||
SetTrieString(unusualNameTrie, "59", "Aces High");
|
||||
SetTrieString(unusualNameTrie, "60", "Dead Presidents");
|
||||
SetTrieString(unusualNameTrie, "61", "Miami Nights");
|
||||
SetTrieString(unusualNameTrie, "62", "Disco Beat Down");
|
||||
// Robo-effects
|
||||
SetTrieString(unusualNameTrie, "63", "Phosphorous");
|
||||
SetTrieString(unusualNameTrie, "64", "Sulphurous");
|
||||
SetTrieString(unusualNameTrie, "65", "Memory Leak");
|
||||
SetTrieString(unusualNameTrie, "66", "Overclocked");
|
||||
SetTrieString(unusualNameTrie, "67", "Electrostatic");
|
||||
SetTrieString(unusualNameTrie, "68", "Power Surge");
|
||||
SetTrieString(unusualNameTrie, "69", "Anti-Freeze");
|
||||
SetTrieString(unusualNameTrie, "70", "Time Warp");
|
||||
SetTrieString(unusualNameTrie, "71", "Green Black Hole");
|
||||
SetTrieString(unusualNameTrie, "72", "Roboactive");
|
||||
// Halloween 2013
|
||||
SetTrieString(unusualNameTrie, "73", "Arcana");
|
||||
SetTrieString(unusualNameTrie, "74", "Spellbound");
|
||||
SetTrieString(unusualNameTrie, "75", "Chiroptera Venenata");
|
||||
SetTrieString(unusualNameTrie, "76", "Poisoned Shadows");
|
||||
SetTrieString(unusualNameTrie, "77", "Something Burning This Way Comes");
|
||||
SetTrieString(unusualNameTrie, "78", "Hellfire");
|
||||
SetTrieString(unusualNameTrie, "79", "Darkblaze");
|
||||
SetTrieString(unusualNameTrie, "80", "Demonflame");
|
||||
// Halloween 2014
|
||||
SetTrieString(unusualNameTrie, "81", "Bonzo The All-Gnawing");
|
||||
SetTrieString(unusualNameTrie, "82", "Amaranthine");
|
||||
SetTrieString(unusualNameTrie, "83", "Stare From Beyond");
|
||||
SetTrieString(unusualNameTrie, "84", "The Ooze");
|
||||
SetTrieString(unusualNameTrie, "85", "Ghastly Ghosts Jr");
|
||||
SetTrieString(unusualNameTrie, "86", "Haunted Phantasm Jr");
|
||||
// EOTL
|
||||
SetTrieString(unusualNameTrie, "87", "Frostbite");
|
||||
SetTrieString(unusualNameTrie, "88", "Molten Mallard");
|
||||
SetTrieString(unusualNameTrie, "89", "Morning Glory");
|
||||
SetTrieString(unusualNameTrie, "90", "Death at Dusk");
|
||||
// Taunt effects
|
||||
SetTrieString(unusualNameTrie, "3001", "Showstopper");
|
||||
SetTrieString(unusualNameTrie, "3002", "Showstopper");
|
||||
SetTrieString(unusualNameTrie, "3003", "Holy Grail");
|
||||
SetTrieString(unusualNameTrie, "3004", "'72");
|
||||
SetTrieString(unusualNameTrie, "3005", "Fountain of Delight");
|
||||
SetTrieString(unusualNameTrie, "3006", "Screaming Tiger");
|
||||
SetTrieString(unusualNameTrie, "3007", "Skill Gotten Gains");
|
||||
SetTrieString(unusualNameTrie, "3008", "Midnight Whirlwind");
|
||||
SetTrieString(unusualNameTrie, "3009", "Silver Cyclone");
|
||||
SetTrieString(unusualNameTrie, "3010", "Mega Strike");
|
||||
// Halloween 2014 taunt effects
|
||||
SetTrieString(unusualNameTrie, "3011", "Haunted Phantasm");
|
||||
SetTrieString(unusualNameTrie, "3012", "Ghastly Ghosts");
|
||||
|
||||
hudText = CreateHudSynchronizer();
|
||||
}
|
||||
|
||||
public OnConfigsExecuted() {
|
||||
CreateTimer(2.0, Timer_AddTag); // Let everything load first
|
||||
}
|
||||
|
||||
public Action:Timer_AddTag(Handle:timer) {
|
||||
if(!GetConVarBool(cvarTag)) {
|
||||
return;
|
||||
}
|
||||
decl String:value[512];
|
||||
GetConVarString(sv_tags, value, sizeof(value));
|
||||
TrimString(value);
|
||||
if(strlen(value) == 0) {
|
||||
SetConVarString(sv_tags, "backpack.tf");
|
||||
return;
|
||||
}
|
||||
decl String:tags[64][64];
|
||||
new total = ExplodeString(value, ",", tags, sizeof(tags), sizeof(tags[]));
|
||||
for(new i = 0; i < total; i++) {
|
||||
if(StrEqual(tags[i], "backpack.tf")) {
|
||||
return; // Tag found, nothing to do here
|
||||
}
|
||||
}
|
||||
StrCat(value, sizeof(value), ",backpack.tf");
|
||||
SetConVarString(sv_tags, value);
|
||||
}
|
||||
|
||||
public OnMapStart() {
|
||||
PrecacheSound(NOTIFICATION_SOUND);
|
||||
}
|
||||
|
||||
public Steam_FullyLoaded() {
|
||||
CreateTimer(1.0, Timer_Update); // In case of late-loads
|
||||
}
|
||||
|
||||
GetCachedPricesAge() {
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "data/backpack-tf.txt");
|
||||
if(!FileExists(path)) {
|
||||
return -1;
|
||||
}
|
||||
new Handle:kv = CreateKeyValues("Response");
|
||||
if(!FileToKeyValues(kv, path)) {
|
||||
CloseHandle(kv);
|
||||
return -1;
|
||||
}
|
||||
new offset = KvGetNum(kv, "time_offset", 1337); // The actual offset can be positive, negative, or zero, so we'll just use 1337 as a default since that's unlikely
|
||||
new time = KvGetNum(kv, "current_time");
|
||||
CloseHandle(kv);
|
||||
if(offset == 1337 || time == 0) {
|
||||
return -1;
|
||||
}
|
||||
return GetTime() - time;
|
||||
}
|
||||
|
||||
public Action:Timer_Update(Handle:timer) {
|
||||
new age = GetCachedPricesAge();
|
||||
if(age != -1 && age < 900) { // 15 minutes
|
||||
LogMessage("Locally saved pricing data is %d minutes old, bypassing backpack.tf query", age / 60);
|
||||
if(backpackTFPricelist != INVALID_HANDLE) {
|
||||
CloseHandle(backpackTFPricelist);
|
||||
}
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "data/backpack-tf.txt");
|
||||
backpackTFPricelist = CreateKeyValues("Response");
|
||||
FileToKeyValues(backpackTFPricelist, path);
|
||||
|
||||
budsToKeys = GetConversion(ITEM_EARBUDS);
|
||||
keysToRef = GetConversion(ITEM_KEY);
|
||||
KvRewind(backpackTFPricelist);
|
||||
refToUsd = KvGetFloat(backpackTFPricelist, "refined_usd_value");
|
||||
|
||||
CreateTimer(float(3600 - age), Timer_Update);
|
||||
return;
|
||||
}
|
||||
|
||||
decl String:key[32];
|
||||
GetConVarString(cvarAPIKey, key, sizeof(key));
|
||||
if(strlen(key) == 0) {
|
||||
LogError("No API key set. Fill in your API key and reload the plugin.");
|
||||
return;
|
||||
}
|
||||
new HTTPRequestHandle:request = Steam_CreateHTTPRequest(HTTPMethod_GET, BACKPACK_TF_URL);
|
||||
Steam_SetHTTPRequestGetOrPostParameter(request, "key", key);
|
||||
Steam_SetHTTPRequestGetOrPostParameter(request, "format", "vdf");
|
||||
Steam_SetHTTPRequestGetOrPostParameter(request, "names", "1");
|
||||
Steam_SendHTTPRequest(request, OnBackpackTFComplete);
|
||||
}
|
||||
|
||||
public OnBackpackTFComplete(HTTPRequestHandle:request, bool:successful, HTTPStatusCode:status) {
|
||||
if(status != HTTPStatusCode_OK || !successful) {
|
||||
if(status == HTTPStatusCode_BadRequest) {
|
||||
LogError("backpack.tf API failed: You have not set an API key");
|
||||
Steam_ReleaseHTTPRequest(request);
|
||||
CreateTimer(600.0, Timer_Update); // Set this for 10 minutes instead of 1 minute
|
||||
return;
|
||||
} else if(status == HTTPStatusCode_Forbidden) {
|
||||
LogError("backpack.tf API failed: Your API key is invalid");
|
||||
Steam_ReleaseHTTPRequest(request);
|
||||
CreateTimer(600.0, Timer_Update); // Set this for 10 minutes instead of 1 minute
|
||||
return;
|
||||
} else if(status == HTTPStatusCode_PreconditionFailed) {
|
||||
decl String:retry[16];
|
||||
Steam_GetHTTPResponseHeaderValue(request, "Retry-After", retry, sizeof(retry));
|
||||
LogError("backpack.tf API failed: We are being rate-limited by backpack.tf, next request allowed in %s seconds", retry);
|
||||
} else if(status >= HTTPStatusCode_InternalServerError) {
|
||||
LogError("backpack.tf API failed: An internal server error occurred");
|
||||
} else if(status == HTTPStatusCode_OK && !successful) {
|
||||
LogError("backpack.tf API failed: backpack.tf returned an OK response but no data");
|
||||
} else if(status != HTTPStatusCode_Invalid) {
|
||||
LogError("backpack.tf API failed: Unknown error (status code %d)", _:status);
|
||||
} else {
|
||||
LogError("backpack.tf API failed: Unable to connect to server or server returned no data");
|
||||
}
|
||||
Steam_ReleaseHTTPRequest(request);
|
||||
CreateTimer(60.0, Timer_Update); // try again!
|
||||
return;
|
||||
}
|
||||
decl String:path[256];
|
||||
BuildPath(Path_SM, path, sizeof(path), "data/backpack-tf.txt");
|
||||
|
||||
Steam_WriteHTTPResponseBody(request, path);
|
||||
Steam_ReleaseHTTPRequest(request);
|
||||
LogMessage("backpack.tf price list successfully downloaded!");
|
||||
|
||||
CreateTimer(3600.0, Timer_Update);
|
||||
|
||||
if(backpackTFPricelist != INVALID_HANDLE) {
|
||||
CloseHandle(backpackTFPricelist);
|
||||
}
|
||||
backpackTFPricelist = CreateKeyValues("Response");
|
||||
FileToKeyValues(backpackTFPricelist, path);
|
||||
lastCacheTime = cacheTime;
|
||||
cacheTime = KvGetNum(backpackTFPricelist, "current_time");
|
||||
|
||||
new offset = GetTime() - cacheTime;
|
||||
KvSetNum(backpackTFPricelist, "time_offset", offset);
|
||||
KeyValuesToFile(backpackTFPricelist, path);
|
||||
|
||||
budsToKeys = GetConversion(ITEM_EARBUDS);
|
||||
keysToRef = GetConversion(ITEM_KEY);
|
||||
KvRewind(backpackTFPricelist);
|
||||
refToUsd = KvGetFloat(backpackTFPricelist, "refined_usd_value");
|
||||
|
||||
if(!GetConVarBool(cvarDisplayUpdateNotification)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(lastCacheTime == 0) { // first download
|
||||
new Handle:array = CreateArray(128);
|
||||
PushArrayString(array, "#Type_command");
|
||||
SetHudTextParams(GetConVarFloat(cvarHudXPos), GetConVarFloat(cvarHudYPos), GetConVarFloat(cvarHudHoldTime), GetConVarInt(cvarHudRed), GetConVarInt(cvarHudGreen), GetConVarInt(cvarHudBlue), 255);
|
||||
for(new i = 1; i <= MaxClients; i++) {
|
||||
if(!IsClientInGame(i)) {
|
||||
continue;
|
||||
}
|
||||
ShowSyncHudText(i, hudText, "%t", "Price list updated");
|
||||
EmitSoundToClient(i, NOTIFICATION_SOUND);
|
||||
}
|
||||
CreateTimer(GetConVarFloat(cvarHudHoldTime), Timer_DisplayHudText, array, TIMER_REPEAT);
|
||||
return;
|
||||
}
|
||||
|
||||
PrepPriceKv();
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
new bool:isNegative = false;
|
||||
new lastUpdate, Float:valueOld, Float:valueOldHigh, Float:value, Float:valueHigh, Float:difference;
|
||||
decl String:defindex[16], String:qualityIndex[32], String:quality[32], String:name[64], String:message[128], String:currency[32], String:currencyOld[32], String:oldPrice[64], String:newPrice[64];
|
||||
new Handle:array = CreateArray(128);
|
||||
PushArrayString(array, "#Type_command");
|
||||
if(GetConVarBool(cvarDisplayChangedPrices)) {
|
||||
do {
|
||||
// loop through items
|
||||
KvGetSectionName(backpackTFPricelist, defindex, sizeof(defindex));
|
||||
if(StringToInt(defindex) == ITEM_REFINED) {
|
||||
continue; // Skip over refined price changes
|
||||
}
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
do {
|
||||
// loop through qualities
|
||||
KvGetSectionName(backpackTFPricelist, qualityIndex, sizeof(qualityIndex));
|
||||
if(StrEqual(qualityIndex, "item_info")) {
|
||||
KvGetString(backpackTFPricelist, "item_name", name, sizeof(name));
|
||||
continue;
|
||||
}
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
do {
|
||||
// loop through instances (series #s, effects)
|
||||
lastUpdate = KvGetNum(backpackTFPricelist, "last_change");
|
||||
if(lastUpdate == 0 || lastUpdate < lastCacheTime) {
|
||||
continue; // hasn't updated
|
||||
}
|
||||
valueOld = KvGetFloat(backpackTFPricelist, "value_old");
|
||||
valueOldHigh = KvGetFloat(backpackTFPricelist, "value_high_old");
|
||||
value = KvGetFloat(backpackTFPricelist, "value");
|
||||
valueHigh = KvGetFloat(backpackTFPricelist, "value_high");
|
||||
|
||||
KvGetString(backpackTFPricelist, "currency", currency, sizeof(currency));
|
||||
KvGetString(backpackTFPricelist, "currency_old", currencyOld, sizeof(currencyOld));
|
||||
|
||||
if(strlen(currency) == 0 || strlen(currencyOld) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FormatPriceRange(valueOld, valueOldHigh, currency, oldPrice, sizeof(oldPrice), StrEqual(qualityIndex, QUALITY_UNUSUAL));
|
||||
FormatPriceRange(value, valueHigh, currency, newPrice, sizeof(newPrice), StrEqual(qualityIndex, QUALITY_UNUSUAL));
|
||||
|
||||
// Get an average so we can determine if it went up or down
|
||||
if(valueOldHigh != 0.0) {
|
||||
valueOld = FloatDiv(FloatAdd(valueOld, valueOldHigh), 2.0);
|
||||
}
|
||||
|
||||
if(valueHigh != 0.0) {
|
||||
value = FloatDiv(FloatAdd(value, valueHigh), 2.0);
|
||||
}
|
||||
|
||||
// Get prices in terms of refined now so we can determine if it went up or down
|
||||
if(StrEqual(currencyOld, "earbuds")) {
|
||||
valueOld = FloatMul(FloatMul(valueOld, budsToKeys), keysToRef);
|
||||
} else if(StrEqual(currencyOld, "keys")) {
|
||||
valueOld = FloatMul(valueOld, keysToRef);
|
||||
}
|
||||
|
||||
if(StrEqual(currency, "earbuds")) {
|
||||
value = FloatMul(FloatMul(value, budsToKeys), keysToRef);
|
||||
} else if(StrEqual(currency, "keys")) {
|
||||
value = FloatMul(value, keysToRef);
|
||||
}
|
||||
|
||||
difference = FloatSub(value, valueOld);
|
||||
if(difference < 0.0) {
|
||||
isNegative = true;
|
||||
difference = FloatMul(difference, -1.0);
|
||||
} else {
|
||||
isNegative = false;
|
||||
}
|
||||
|
||||
// Format a quality name
|
||||
if(StrEqual(qualityIndex, QUALITY_UNIQUE)) {
|
||||
Format(quality, sizeof(quality), ""); // if quality is unique, don't display a quality
|
||||
} else if(StrEqual(qualityIndex, QUALITY_UNUSUAL) && (StringToInt(defindex) != ITEM_HAUNTED_SCRAP && StringToInt(defindex) != ITEM_HEADTAKER)) {
|
||||
decl String:effect[16];
|
||||
KvGetSectionName(backpackTFPricelist, effect, sizeof(effect));
|
||||
if(!GetTrieString(unusualNameTrie, effect, quality, sizeof(quality))) {
|
||||
LogError("Unknown unusual effect: %s in OnBackpackTFComplete. Please report this!", effect);
|
||||
decl String:kvPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, kvPath, sizeof(kvPath), "data/backpack-tf.%d.txt", GetTime());
|
||||
if(!FileExists(kvPath)) {
|
||||
KeyValuesToFile(backpackTFPricelist, kvPath);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if(!GetTrieString(qualityNameTrie, qualityIndex, quality, sizeof(quality))) {
|
||||
LogError("Unknown quality index: %s. Please report this!", qualityIndex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Format(message, sizeof(message), "%s%s%s: %s #From %s #To %s", quality, StrEqual(quality, "") ? "" : " ", name, isNegative ? "#Down" : "#Up", oldPrice, newPrice);
|
||||
PushArrayString(array, message);
|
||||
|
||||
} while(KvGotoNextKey(backpackTFPricelist)); // end: instances
|
||||
KvGoBack(backpackTFPricelist);
|
||||
|
||||
} while(KvGotoNextKey(backpackTFPricelist)); // end: qualities
|
||||
KvGoBack(backpackTFPricelist);
|
||||
|
||||
} while(KvGotoNextKey(backpackTFPricelist)); // end: items
|
||||
}
|
||||
|
||||
SetHudTextParams(GetConVarFloat(cvarHudXPos), GetConVarFloat(cvarHudYPos), GetConVarFloat(cvarHudHoldTime), GetConVarInt(cvarHudRed), GetConVarInt(cvarHudGreen), GetConVarInt(cvarHudBlue), 255);
|
||||
for(new i = 1; i <= MaxClients; i++) {
|
||||
if(!IsClientInGame(i)) {
|
||||
continue;
|
||||
}
|
||||
ShowSyncHudText(i, hudText, "%t", "Price list updated");
|
||||
EmitSoundToClient(i, NOTIFICATION_SOUND);
|
||||
}
|
||||
CreateTimer(GetConVarFloat(cvarHudHoldTime), Timer_DisplayHudText, array, TIMER_REPEAT);
|
||||
}
|
||||
|
||||
Float:GetConversion(defindex) {
|
||||
decl String:buffer[32];
|
||||
PrepPriceKv();
|
||||
IntToString(defindex, buffer, sizeof(buffer));
|
||||
KvJumpToKey(backpackTFPricelist, buffer);
|
||||
KvJumpToKey(backpackTFPricelist, "6");
|
||||
KvJumpToKey(backpackTFPricelist, "0");
|
||||
new Float:value = KvGetFloat(backpackTFPricelist, "value");
|
||||
new Float:valueHigh = KvGetFloat(backpackTFPricelist, "value_high");
|
||||
if(valueHigh == 0.0) {
|
||||
return value;
|
||||
}
|
||||
return FloatDiv(FloatAdd(value, valueHigh), 2.0);
|
||||
}
|
||||
|
||||
FormatPrice(Float:price, const String:currency[], String:output[], maxlen, bool:includeCurrency = true, bool:forceBuds = false) {
|
||||
new String:outputCurrency[32];
|
||||
if(StrEqual(currency, "metal")) {
|
||||
Format(outputCurrency, sizeof(outputCurrency), "refined");
|
||||
} else if(StrEqual(currency, "keys")) {
|
||||
Format(outputCurrency, sizeof(outputCurrency), "key");
|
||||
} else if(StrEqual(currency, "earbuds")) {
|
||||
Format(outputCurrency, sizeof(outputCurrency), "bud");
|
||||
} else if(StrEqual(currency, "usd")) {
|
||||
if(forceBuds) {
|
||||
Format(outputCurrency, sizeof(outputCurrency), "earbuds"); // This allows us to force unusual price ranges to display buds only
|
||||
}
|
||||
ConvertUSD(price, outputCurrency, sizeof(outputCurrency));
|
||||
} else {
|
||||
ThrowError("Unknown currency: %s", currency);
|
||||
}
|
||||
|
||||
if(FloatIsInt(price)) {
|
||||
Format(output, maxlen, "%d", RoundToFloor(price));
|
||||
} else {
|
||||
Format(output, maxlen, "%.2f", price);
|
||||
}
|
||||
|
||||
if(!includeCurrency) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(StrEqual(output, "1") || StrEqual(currency, "metal")) {
|
||||
Format(output, maxlen, "%s %s", output, outputCurrency);
|
||||
} else {
|
||||
Format(output, maxlen, "%s %ss", output, outputCurrency);
|
||||
}
|
||||
}
|
||||
|
||||
FormatPriceRange(Float:low, Float:high, const String:currency[], String:output[], maxlen, bool:forceBuds = false) {
|
||||
if(high == 0.0) {
|
||||
FormatPrice(low, currency, output, maxlen, true, forceBuds);
|
||||
return;
|
||||
}
|
||||
decl String:buffer[32];
|
||||
FormatPrice(low, currency, output, maxlen, false, forceBuds);
|
||||
FormatPrice(high, currency, buffer, sizeof(buffer), true, forceBuds);
|
||||
Format(output, maxlen, "%s-%s", output, buffer);
|
||||
}
|
||||
|
||||
ConvertUSD(&Float:price, String:outputCurrency[], maxlen) {
|
||||
new Float:budPrice = FloatMul(FloatMul(refToUsd, keysToRef), budsToKeys);
|
||||
if(price < budPrice && !StrEqual(outputCurrency, "earbuds")) {
|
||||
new Float:keyPrice = FloatMul(refToUsd, keysToRef);
|
||||
price = FloatDiv(price, keyPrice);
|
||||
Format(outputCurrency, maxlen, "key");
|
||||
} else {
|
||||
price = FloatDiv(price, budPrice);
|
||||
Format(outputCurrency, maxlen, "bud");
|
||||
}
|
||||
}
|
||||
|
||||
bool:FloatIsInt(Float:input) {
|
||||
return float(RoundToFloor(input)) == input;
|
||||
}
|
||||
|
||||
public Action:Timer_DisplayHudText(Handle:timer, any:array) {
|
||||
if(GetArraySize(array) == 0) {
|
||||
CloseHandle(array);
|
||||
return Plugin_Stop;
|
||||
}
|
||||
decl String:text[128], String:display[128];
|
||||
GetArrayString(array, 0, text, sizeof(text));
|
||||
SetHudTextParams(GetConVarFloat(cvarHudXPos), GetConVarFloat(cvarHudYPos), GetConVarFloat(cvarHudHoldTime), GetConVarInt(cvarHudRed), GetConVarInt(cvarHudGreen), GetConVarInt(cvarHudBlue), 255);
|
||||
for(new i = 1; i <= MaxClients; i++) {
|
||||
if(!IsClientInGame(i)) {
|
||||
continue;
|
||||
}
|
||||
PerformTranslationTokenReplacement(i, text, display, sizeof(display));
|
||||
ShowSyncHudText(i, hudText, display);
|
||||
}
|
||||
RemoveFromArray(array, 0);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
PerformTranslationTokenReplacement(client, const String:message[], String:output[], maxlen) {
|
||||
SetGlobalTransTarget(client);
|
||||
strcopy(output, maxlen, message);
|
||||
decl String:buffer[64];
|
||||
|
||||
Format(buffer, maxlen, "%t", "Type !pc for a price check");
|
||||
ReplaceString(output, maxlen, "#Type_command", buffer);
|
||||
|
||||
Format(buffer, maxlen, "%t", "Up");
|
||||
ReplaceString(output, maxlen, "#Up", buffer);
|
||||
|
||||
Format(buffer, maxlen, "%t", "Down");
|
||||
ReplaceString(output, maxlen, "#Down", buffer);
|
||||
|
||||
Format(buffer, maxlen, "%t", "From");
|
||||
ReplaceString(output, maxlen, "#From", buffer);
|
||||
|
||||
Format(buffer, maxlen, "%t", "To");
|
||||
ReplaceString(output, maxlen, "#To", buffer);
|
||||
}
|
||||
|
||||
PrepPriceKv() {
|
||||
KvRewind(backpackTFPricelist);
|
||||
KvJumpToKey(backpackTFPricelist, "prices");
|
||||
}
|
||||
|
||||
public Action:Command_PriceCheck(client, args) {
|
||||
if(backpackTFPricelist == INVALID_HANDLE) {
|
||||
decl String:key[32];
|
||||
GetConVarString(cvarAPIKey, key, sizeof(key));
|
||||
if(strlen(key) == 0) {
|
||||
ReplyToCommand(client, "\x04[SM] \x01The server administrator has not filled in their API key yet. Please contact the server administrator.");
|
||||
} else {
|
||||
ReplyToCommand(client, "\x04[SM] \x01%t.", "The price list has not loaded yet");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
if(args == 0) {
|
||||
new Handle:menu = CreateMenu(Handler_ItemSelection);
|
||||
SetMenuTitle(menu, "Price Check");
|
||||
PrepPriceKv();
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
decl String:name[128];
|
||||
do {
|
||||
if(!KvJumpToKey(backpackTFPricelist, "item_info")) {
|
||||
continue;
|
||||
}
|
||||
KvGetString(backpackTFPricelist, "item_name", name, sizeof(name));
|
||||
if(KvGetNum(backpackTFPricelist, "proper_name") == 1) {
|
||||
Format(name, sizeof(name), "The %s", name);
|
||||
}
|
||||
AddMenuItem(menu, name, name);
|
||||
KvGoBack(backpackTFPricelist);
|
||||
} while(KvGotoNextKey(backpackTFPricelist));
|
||||
DisplayMenu(menu, client, GetConVarInt(cvarMenuHoldTime));
|
||||
return Plugin_Handled;
|
||||
}
|
||||
new resultDefindex = -1;
|
||||
decl String:defindex[8], String:name[128], String:itemName[128];
|
||||
GetCmdArgString(name, sizeof(name));
|
||||
new bool:exact = StripQuotes(name);
|
||||
PrepPriceKv();
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
new Handle:matches;
|
||||
if(!exact) {
|
||||
matches = CreateArray(128);
|
||||
}
|
||||
do {
|
||||
KvGetSectionName(backpackTFPricelist, defindex, sizeof(defindex));
|
||||
if(!KvJumpToKey(backpackTFPricelist, "item_info")) {
|
||||
continue;
|
||||
}
|
||||
KvGetString(backpackTFPricelist, "item_name", itemName, sizeof(itemName));
|
||||
if(KvGetNum(backpackTFPricelist, "proper_name") == 1) {
|
||||
Format(itemName, sizeof(itemName), "The %s", itemName);
|
||||
}
|
||||
KvGoBack(backpackTFPricelist);
|
||||
if(exact) {
|
||||
if(StrEqual(itemName, name, false)) {
|
||||
resultDefindex = StringToInt(defindex);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(StrContains(itemName, name, false) != -1) {
|
||||
resultDefindex = StringToInt(defindex); // In case this is the only match, we store the resulting defindex here so that we don't need to search to find it again
|
||||
PushArrayString(matches, itemName);
|
||||
}
|
||||
}
|
||||
} while(KvGotoNextKey(backpackTFPricelist));
|
||||
if(!exact && GetArraySize(matches) > 1) {
|
||||
new Handle:menu = CreateMenu(Handler_ItemSelection);
|
||||
SetMenuTitle(menu, "Search Results");
|
||||
new size = GetArraySize(matches);
|
||||
for(new i = 0; i < size; i++) {
|
||||
GetArrayString(matches, i, itemName, sizeof(itemName));
|
||||
AddMenuItem(menu, itemName, itemName);
|
||||
}
|
||||
DisplayMenu(menu, client, GetConVarInt(cvarMenuHoldTime));
|
||||
CloseHandle(matches);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
if(!exact) {
|
||||
CloseHandle(matches);
|
||||
}
|
||||
if(resultDefindex == -1) {
|
||||
ReplyToCommand(client, "\x04[SM] \x01No matching item was found.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
// At this point, we know that we've found our item. Its defindex is stored in resultDefindex as a cell
|
||||
// defindex was used to store the defindex of every item as we searched it, so it's not reliable
|
||||
if(resultDefindex == ITEM_REFINED) {
|
||||
SetGlobalTransTarget(client);
|
||||
new Handle:menu = CreateMenu(Handler_PriceListMenu);
|
||||
SetMenuTitle(menu, "%t\n%t\n%t\n ", "Price check", itemName, "Prices are estimates only", "Prices courtesy of backpack.tf");
|
||||
decl String:buffer[32];
|
||||
Format(buffer, sizeof(buffer), "Unique: $%.2f USD", refToUsd);
|
||||
AddMenuItem(menu, "", buffer);
|
||||
DisplayMenu(menu, client, GetConVarInt(cvarMenuHoldTime));
|
||||
return Plugin_Handled;
|
||||
}
|
||||
new bool:isCrate = (resultDefindex == ITEM_CRATE || resultDefindex == ITEM_SALVAGED_CRATE);
|
||||
new bool:onlyOneUnusual = (resultDefindex == ITEM_HEADTAKER || resultDefindex == ITEM_HAUNTED_SCRAP);
|
||||
PrepPriceKv();
|
||||
IntToString(resultDefindex, defindex, sizeof(defindex));
|
||||
KvJumpToKey(backpackTFPricelist, defindex);
|
||||
KvJumpToKey(backpackTFPricelist, "item_info");
|
||||
KvGetString(backpackTFPricelist, "item_name", itemName, sizeof(itemName));
|
||||
if(KvGetNum(backpackTFPricelist, "proper_name") == 1) {
|
||||
Format(itemName, sizeof(itemName), "The %s", itemName);
|
||||
}
|
||||
KvGotoNextKey(backpackTFPricelist);
|
||||
|
||||
SetGlobalTransTarget(client);
|
||||
new Handle:menu = CreateMenu(Handler_PriceListMenu);
|
||||
SetMenuTitle(menu, "%t\n%t\n%t\n ", "Price check", itemName, "Prices are estimates only", "Prices courtesy of backpack.tf");
|
||||
new bool:unusualDisplayed = false;
|
||||
new Float:value, Float:valueHigh;
|
||||
decl String:currency[32], String:qualityIndex[16], String:quality[16], String:series[8], String:price[32], String:buffer[64];
|
||||
do {
|
||||
KvGetSectionName(backpackTFPricelist, qualityIndex, sizeof(qualityIndex));
|
||||
if(StrEqual(qualityIndex, "item_info") || StrEqual(qualityIndex, "alt_defindex")) {
|
||||
continue;
|
||||
}
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
do {
|
||||
if(StrEqual(qualityIndex, QUALITY_UNUSUAL) && !onlyOneUnusual) {
|
||||
if(!unusualDisplayed) {
|
||||
AddMenuItem(menu, defindex, "Unusual: View Effects");
|
||||
unusualDisplayed = true;
|
||||
}
|
||||
} else {
|
||||
value = KvGetFloat(backpackTFPricelist, "value");
|
||||
valueHigh = KvGetFloat(backpackTFPricelist, "value_high");
|
||||
KvGetString(backpackTFPricelist, "currency", currency, sizeof(currency));
|
||||
FormatPriceRange(value, valueHigh, currency, price, sizeof(price));
|
||||
|
||||
if(!GetTrieString(qualityNameTrie, qualityIndex, quality, sizeof(quality))) {
|
||||
LogError("Unknown quality index: %s. Please report this!", qualityIndex);
|
||||
continue;
|
||||
}
|
||||
if(isCrate) {
|
||||
KvGetSectionName(backpackTFPricelist, series, sizeof(series));
|
||||
if(StrEqual(series, "0")) {
|
||||
continue;
|
||||
}
|
||||
if(StrEqual(qualityIndex, QUALITY_UNIQUE)) {
|
||||
Format(buffer, sizeof(buffer), "Series %s: %s", series, price);
|
||||
} else {
|
||||
Format(buffer, sizeof(buffer), "%s: Series %s: %s", quality, series, price);
|
||||
}
|
||||
} else {
|
||||
Format(buffer, sizeof(buffer), "%s: %s", quality, price);
|
||||
}
|
||||
AddMenuItem(menu, "", buffer, ITEMDRAW_DISABLED);
|
||||
}
|
||||
} while(KvGotoNextKey(backpackTFPricelist));
|
||||
KvGoBack(backpackTFPricelist);
|
||||
} while(KvGotoNextKey(backpackTFPricelist));
|
||||
DisplayMenu(menu, client, GetConVarInt(cvarMenuHoldTime));
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Handler_ItemSelection(Handle:menu, MenuAction:action, client, param) {
|
||||
if(action == MenuAction_End) {
|
||||
CloseHandle(menu);
|
||||
}
|
||||
if(action != MenuAction_Select) {
|
||||
return;
|
||||
}
|
||||
decl String:selection[128];
|
||||
GetMenuItem(menu, param, selection, sizeof(selection));
|
||||
FakeClientCommand(client, "sm_pricecheck \"%s\"", selection);
|
||||
}
|
||||
|
||||
public Handler_PriceListMenu(Handle:menu, MenuAction:action, client, param) {
|
||||
if(action == MenuAction_End) {
|
||||
CloseHandle(menu);
|
||||
}
|
||||
if(action != MenuAction_Select) {
|
||||
return;
|
||||
}
|
||||
decl String:defindex[32];
|
||||
GetMenuItem(menu, param, defindex, sizeof(defindex));
|
||||
|
||||
decl String:name[64];
|
||||
PrepPriceKv();
|
||||
KvJumpToKey(backpackTFPricelist, defindex);
|
||||
KvJumpToKey(backpackTFPricelist, "item_info");
|
||||
KvGetString(backpackTFPricelist, "item_name", name, sizeof(name));
|
||||
if(KvGetNum(backpackTFPricelist, "proper_name") == 1) {
|
||||
Format(name, sizeof(name), "The Unusual %s", name);
|
||||
} else {
|
||||
Format(name, sizeof(name), "Unusual %s", name);
|
||||
}
|
||||
KvGoBack(backpackTFPricelist);
|
||||
|
||||
if(!KvJumpToKey(backpackTFPricelist, QUALITY_UNUSUAL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KvGotoFirstSubKey(backpackTFPricelist);
|
||||
|
||||
SetGlobalTransTarget(client);
|
||||
new Handle:menu2 = CreateMenu(Handler_PriceListMenu);
|
||||
SetMenuTitle(menu2, "%t\n%t\n%t\n ", "Price check", name, "Prices are estimates only", "Prices courtesy of backpack.tf");
|
||||
decl String:effect[8], String:effectName[64], String:message[128], String:price[64], String:currency[32];
|
||||
new Float:value, Float:valueHigh;
|
||||
do {
|
||||
KvGetSectionName(backpackTFPricelist, effect, sizeof(effect));
|
||||
if(!GetTrieString(unusualNameTrie, effect, effectName, sizeof(effectName))) {
|
||||
LogError("Unknown unusual effect: %s in Handler_PriceListMenu. Please report this!", effect);
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "data/backpack-tf.%d.txt", GetTime());
|
||||
if(!FileExists(path)) {
|
||||
KeyValuesToFile(backpackTFPricelist, path);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
value = KvGetFloat(backpackTFPricelist, "value");
|
||||
valueHigh = KvGetFloat(backpackTFPricelist, "value_high");
|
||||
KvGetString(backpackTFPricelist, "currency", currency, sizeof(currency));
|
||||
if(StrEqual(currency, "")) {
|
||||
continue;
|
||||
}
|
||||
FormatPriceRange(value, valueHigh, currency, price, sizeof(price), true);
|
||||
|
||||
Format(message, sizeof(message), "%s: %s", effectName, price);
|
||||
AddMenuItem(menu2, "", message, ITEMDRAW_DISABLED);
|
||||
} while(KvGotoNextKey(backpackTFPricelist));
|
||||
DisplayMenu(menu2, client, GetConVarInt(cvarMenuHoldTime));
|
||||
}
|
||||
|
||||
public Action:Command_Backpack(client, args) {
|
||||
if(!GetConVarBool(cvarBPCommand)) {
|
||||
return Plugin_Continue;
|
||||
}
|
||||
new target;
|
||||
if(args == 0) {
|
||||
target = GetClientAimTarget(client);
|
||||
if(target <= 0) {
|
||||
DisplayClientMenu(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
} else {
|
||||
decl String:arg1[MAX_NAME_LENGTH];
|
||||
GetCmdArg(1, arg1, sizeof(arg1));
|
||||
target = FindTargetEx(client, arg1, true, false, false);
|
||||
if(target == -1) {
|
||||
DisplayClientMenu(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
decl String:steamID[64];
|
||||
Steam_GetCSteamIDForClient(target, steamID, sizeof(steamID)); // we could use the regular Steam ID, but we already have SteamTools, so we can just bypass backpack.tf's redirect directly
|
||||
decl String:url[256];
|
||||
Format(url, sizeof(url), "http://backpack.tf/profiles/%s", steamID);
|
||||
AdvMOTD_ShowMOTDPanel(client, "backpack.tf", url, MOTDPANEL_TYPE_URL, true, true, true, OnMOTDFailure);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public OnMOTDFailure(client, MOTDFailureReason:reason) {
|
||||
switch(reason) {
|
||||
case MOTDFailure_Disabled: PrintToChat(client, "\x04[SM] \x01You cannot view backpacks with HTML MOTDs disabled.");
|
||||
case MOTDFailure_Matchmaking: PrintToChat(client, "\x04[SM] \x01You cannot view backpacks after joining via Quickplay.");
|
||||
case MOTDFailure_QueryFailed: PrintToChat(client, "\x04[SM] \x01Unable to open backpack.");
|
||||
}
|
||||
}
|
||||
|
||||
DisplayClientMenu(client) {
|
||||
new Handle:menu = CreateMenu(Handler_ClientMenu);
|
||||
SetMenuTitle(menu, "Select Player");
|
||||
decl String:name[MAX_NAME_LENGTH], String:index[8];
|
||||
for(new i = 1; i <= MaxClients; i++) {
|
||||
if(!IsClientInGame(i) || IsFakeClient(i)) {
|
||||
continue;
|
||||
}
|
||||
GetClientName(i, name, sizeof(name));
|
||||
IntToString(GetClientUserId(i), index, sizeof(index));
|
||||
AddMenuItem(menu, index, name);
|
||||
}
|
||||
DisplayMenu(menu, client, GetConVarInt(cvarMenuHoldTime));
|
||||
}
|
||||
|
||||
public Handler_ClientMenu(Handle:menu, MenuAction:action, client, param) {
|
||||
if(action == MenuAction_End) {
|
||||
CloseHandle(menu);
|
||||
}
|
||||
if(action != MenuAction_Select) {
|
||||
return;
|
||||
}
|
||||
decl String:selection[32];
|
||||
GetMenuItem(menu, param, selection, sizeof(selection));
|
||||
FakeClientCommand(client, "sm_backpack #%s", selection);
|
||||
}
|
||||
|
||||
public Action:Command_UpdatePrices(client, args) {
|
||||
new age = GetCachedPricesAge();
|
||||
if(age != -1 && age < 900) { // 15 minutes
|
||||
ReplyToCommand(client, "\x04[SM] \x01The price list cannot be updated more frequently than every 15 minutes. It is currently %d minutes old.", age / 60);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
ReplyToCommand(client, "\x04[SM] \x01Updating backpack.tf prices...");
|
||||
Timer_Update(INVALID_HANDLE);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
FindTargetEx(client, const String:target[], bool:nobots = false, bool:immunity = true, bool:replyToError = true) {
|
||||
decl String:target_name[MAX_TARGET_LENGTH];
|
||||
decl target_list[1], target_count, bool:tn_is_ml;
|
||||
|
||||
new flags = COMMAND_FILTER_NO_MULTI;
|
||||
if(nobots) {
|
||||
flags |= COMMAND_FILTER_NO_BOTS;
|
||||
}
|
||||
if(!immunity) {
|
||||
flags |= COMMAND_FILTER_NO_IMMUNITY;
|
||||
}
|
||||
|
||||
if((target_count = ProcessTargetString(
|
||||
target,
|
||||
client,
|
||||
target_list,
|
||||
1,
|
||||
flags,
|
||||
target_name,
|
||||
sizeof(target_name),
|
||||
tn_is_ml)) > 0)
|
||||
{
|
||||
return target_list[0];
|
||||
} else {
|
||||
if(replyToError) {
|
||||
ReplyToTargetError(client, target_count);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
87
scripting/temp/baseballhell_randomgm.cs
Normal file
87
scripting/temp/baseballhell_randomgm.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#define PLUGIN_NAME "Baseball Hell Randomizer"
|
||||
#define PLUGIN_AUTHOR "SirDovahBearYT"
|
||||
#define PLUGIN_DESCRIPTION "Picks a random gamemode every 60 seconds"
|
||||
#define PLUGIN_VERSION "1.2.0"
|
||||
#define GONG "misc/halloween/strongman_bell_01.wav"
|
||||
bool Running;
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = PLUGIN_NAME,
|
||||
author = PLUGIN_AUTHOR,
|
||||
description = PLUGIN_DESCRIPTION,
|
||||
version = PLUGIN_VERSION,
|
||||
url = "http://www.sourcemod.net"
|
||||
};
|
||||
|
||||
public OnPluginStart()
|
||||
{
|
||||
PrecacheSound(GONG, true);
|
||||
Running = false;
|
||||
while(Running == false)
|
||||
{
|
||||
CreateTimer(60.0, Command_RandomExec);
|
||||
Running = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_RandomExec(Handle timer)
|
||||
{
|
||||
new RandomNumbersArray[7] = {1,2,3,4,5,6,7};
|
||||
new randomnum = GetRandomInt(1, 7);
|
||||
if (randomnum == 1)
|
||||
{
|
||||
ServerCommand("baseballhell_mode SCOUT_PLAY_ALL_WEAPONS");
|
||||
ServerCommand("sm_csay SCOUT PLAYS WITH ALL WEAPONS!");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
if (randomnum == 2)
|
||||
{
|
||||
ServerCommand("baseballhell_mode SCOUT_PLAY_BAT_ONLY");
|
||||
ServerCommand("sm_csay SCOUT PLAYS WITH BAT ONLY!");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
if (randomnum == 3)
|
||||
{
|
||||
ServerCommand("baseballhell_mode ALL_PLAY_ALL_WEAPONS");
|
||||
ServerCommand("sm_csay ALL CLASSES PLAY ALL WEAPONS!");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
if (randomnum == 4)
|
||||
{
|
||||
ServerCommand("baseballhell_mode ALL_PLAY_BAT_ONLY");
|
||||
ServerCommand("sm_csay EVERYONE PLAYS BAT ONLY");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
if (randomnum == 5)
|
||||
{
|
||||
ServerCommand("baseballhell_mode FLAK_CANNON");
|
||||
ServerCommand("sm_csay FLAK CANNONS FOR ALL!");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
if (randomnum == 6)
|
||||
{
|
||||
ServerCommand("baseballhell_mode HUNTSMAN");
|
||||
ServerCommand("sm_csay RAPID FIRE HUNTSMANS INCOMING!");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
if (randomnum == 7)
|
||||
{
|
||||
ServerCommand("baseballhell_mode ROCKETMAN");
|
||||
ServerCommand("sm_csay VALVE ROCKET LAUNCHERS FOR ALL!");
|
||||
EmitSoundToAll(GONG);
|
||||
Running = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Running = false;
|
||||
}
|
||||
}
|
384
scripting/temp/basebans.sp
Normal file
384
scripting/temp/basebans.sp
Normal file
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Basic Commands Plugin
|
||||
* Implements basic admin commands.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Basic Ban Commands",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Basic Banning Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
TopMenu hTopMenu;
|
||||
|
||||
int g_BanTarget[MAXPLAYERS+1];
|
||||
int g_BanTargetUserId[MAXPLAYERS+1];
|
||||
int g_BanTime[MAXPLAYERS+1];
|
||||
|
||||
bool g_IsWaitingForChatReason[MAXPLAYERS+1];
|
||||
KeyValues g_hKvBanReasons;
|
||||
char g_BanReasonsPath[PLATFORM_MAX_PATH];
|
||||
|
||||
#include "basebans/ban.sp"
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
BuildPath(Path_SM, g_BanReasonsPath, sizeof(g_BanReasonsPath), "configs/banreasons.txt");
|
||||
|
||||
LoadBanReasons();
|
||||
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("basebans.phrases");
|
||||
LoadTranslations("core.phrases");
|
||||
|
||||
RegAdminCmd("sm_ban", Command_Ban, ADMFLAG_BAN, "sm_ban <#userid|name> <minutes|0> [reason]");
|
||||
RegAdminCmd("sm_unban", Command_Unban, ADMFLAG_UNBAN, "sm_unban <steamid|ip>");
|
||||
RegAdminCmd("sm_addban", Command_AddBan, ADMFLAG_RCON, "sm_addban <time> <steamid> [reason]");
|
||||
RegAdminCmd("sm_banip", Command_BanIp, ADMFLAG_BAN, "sm_banip <ip|#userid|name> <time> [reason]");
|
||||
|
||||
//This to manage custom ban reason messages
|
||||
RegConsoleCmd("sm_abortban", Command_AbortBan, "sm_abortban");
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
//(Re-)Load BanReasons
|
||||
LoadBanReasons();
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
g_IsWaitingForChatReason[client] = false;
|
||||
}
|
||||
|
||||
void LoadBanReasons()
|
||||
{
|
||||
delete g_hKvBanReasons;
|
||||
|
||||
g_hKvBanReasons = new KeyValues("banreasons");
|
||||
|
||||
if (g_hKvBanReasons.ImportFromFile(g_BanReasonsPath))
|
||||
{
|
||||
char sectionName[255];
|
||||
if (!g_hKvBanReasons.GetSectionName(sectionName, sizeof(sectionName)))
|
||||
{
|
||||
SetFailState("Error in %s: File corrupt or in the wrong format", g_BanReasonsPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sectionName, "banreasons") != 0)
|
||||
{
|
||||
SetFailState("Error in %s: Couldn't find 'banreasons'", g_BanReasonsPath);
|
||||
return;
|
||||
}
|
||||
|
||||
//Reset kvHandle
|
||||
g_hKvBanReasons.Rewind();
|
||||
} else {
|
||||
SetFailState("Error in %s: File not found, corrupt or in the wrong format", g_BanReasonsPath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Find the "Player Commands" category */
|
||||
TopMenuObject player_commands = hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
|
||||
|
||||
if (player_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_ban", AdminMenu_Ban, player_commands, "sm_ban", ADMFLAG_BAN);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_BanIp(int client, int args)
|
||||
{
|
||||
if (args < 2)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_banip <ip|#userid|name> <time> [reason]");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
int len, next_len;
|
||||
char Arguments[256];
|
||||
char arg[50], time[20];
|
||||
|
||||
GetCmdArgString(Arguments, sizeof(Arguments));
|
||||
len = BreakString(Arguments, arg, sizeof(arg));
|
||||
|
||||
if ((next_len = BreakString(Arguments[len], time, sizeof(time))) != -1)
|
||||
{
|
||||
len += next_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
Arguments[0] = '\0';
|
||||
}
|
||||
|
||||
if (StrEqual(arg, "0"))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cannot ban that IP");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char target_name[MAX_TARGET_LENGTH];
|
||||
int target_list[1];
|
||||
bool tn_is_ml;
|
||||
int found_client = -1;
|
||||
|
||||
if (ProcessTargetString(
|
||||
arg,
|
||||
client,
|
||||
target_list,
|
||||
1,
|
||||
COMMAND_FILTER_CONNECTED|COMMAND_FILTER_NO_MULTI,
|
||||
target_name,
|
||||
sizeof(target_name),
|
||||
tn_is_ml) > 0)
|
||||
{
|
||||
found_client = target_list[0];
|
||||
}
|
||||
|
||||
bool has_rcon;
|
||||
|
||||
if (client == 0 || (client == 1 && !IsDedicatedServer()))
|
||||
{
|
||||
has_rcon = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AdminId id = GetUserAdmin(client);
|
||||
has_rcon = (id == INVALID_ADMIN_ID) ? false : GetAdminFlag(id, Admin_RCON);
|
||||
}
|
||||
|
||||
int hit_client = -1;
|
||||
if (found_client != -1
|
||||
&& !IsFakeClient(found_client)
|
||||
&& (has_rcon || CanUserTarget(client, found_client)))
|
||||
{
|
||||
GetClientIP(found_client, arg, sizeof(arg));
|
||||
hit_client = found_client;
|
||||
}
|
||||
|
||||
if (hit_client == -1 && !has_rcon)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "No Access");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
int minutes = StringToInt(time);
|
||||
|
||||
LogAction(client,
|
||||
hit_client,
|
||||
"\"%L\" added ban (minutes \"%d\") (ip \"%s\") (reason \"%s\")",
|
||||
client,
|
||||
minutes,
|
||||
arg,
|
||||
Arguments[len]);
|
||||
|
||||
ReplyToCommand(client, "[SM] %t", "Ban added");
|
||||
|
||||
BanIdentity(arg,
|
||||
minutes,
|
||||
BANFLAG_IP,
|
||||
Arguments[len],
|
||||
"sm_banip",
|
||||
client);
|
||||
|
||||
if (hit_client != -1)
|
||||
{
|
||||
KickClient(hit_client, "Banned: %s", Arguments[len]);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_AddBan(int client, int args)
|
||||
{
|
||||
if (args < 2)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_addban <time> <steamid> [reason]");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char arg_string[256];
|
||||
char time[50];
|
||||
char authid[50];
|
||||
|
||||
GetCmdArgString(arg_string, sizeof(arg_string));
|
||||
|
||||
int len, total_len;
|
||||
|
||||
/* Get time */
|
||||
if ((len = BreakString(arg_string, time, sizeof(time))) == -1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_addban <time> <steamid> [reason]");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
total_len += len;
|
||||
|
||||
/* Get steamid */
|
||||
if ((len = BreakString(arg_string[total_len], authid, sizeof(authid))) != -1)
|
||||
{
|
||||
total_len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
total_len = 0;
|
||||
arg_string[0] = '\0';
|
||||
}
|
||||
|
||||
/* Verify steamid */
|
||||
bool idValid = false;
|
||||
if (!strncmp(authid, "STEAM_", 6) && authid[7] == ':')
|
||||
idValid = true;
|
||||
else if (!strncmp(authid, "[U:", 3))
|
||||
idValid = true;
|
||||
|
||||
if (!idValid)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Invalid SteamID specified");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
int minutes = StringToInt(time);
|
||||
|
||||
LogAction(client,
|
||||
-1,
|
||||
"\"%L\" added ban (minutes \"%d\") (id \"%s\") (reason \"%s\")",
|
||||
client,
|
||||
minutes,
|
||||
authid,
|
||||
arg_string[total_len]);
|
||||
BanIdentity(authid,
|
||||
minutes,
|
||||
BANFLAG_AUTHID,
|
||||
arg_string[total_len],
|
||||
"sm_addban",
|
||||
client);
|
||||
|
||||
ReplyToCommand(client, "[SM] %t", "Ban added");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_Unban(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_unban <steamid|ip>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char arg[50];
|
||||
GetCmdArgString(arg, sizeof(arg));
|
||||
|
||||
ReplaceString(arg, sizeof(arg), "\"", "");
|
||||
|
||||
int ban_flags;
|
||||
if (IsCharNumeric(arg[0]))
|
||||
{
|
||||
ban_flags |= BANFLAG_IP;
|
||||
}
|
||||
else
|
||||
{
|
||||
ban_flags |= BANFLAG_AUTHID;
|
||||
}
|
||||
|
||||
LogAction(client, -1, "\"%L\" removed ban (filter \"%s\")", client, arg);
|
||||
RemoveBan(arg, ban_flags, "sm_unban", client);
|
||||
|
||||
ReplyToCommand(client, "[SM] %t", "Removed bans matching", arg);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_AbortBan(int client, int args)
|
||||
{
|
||||
if(!CheckCommandAccess(client, "sm_ban", ADMFLAG_BAN))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "No Access");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
if(g_IsWaitingForChatReason[client])
|
||||
{
|
||||
g_IsWaitingForChatReason[client] = false;
|
||||
ReplyToCommand(client, "[SM] %t", "AbortBan applied successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "AbortBan not waiting for custom reason");
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
|
||||
{
|
||||
if(g_IsWaitingForChatReason[client])
|
||||
{
|
||||
g_IsWaitingForChatReason[client] = false;
|
||||
PrepareBan(client, g_BanTarget[client], g_BanTime[client], sArgs);
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
428
scripting/temp/basechat.sp
Normal file
428
scripting/temp/basechat.sp
Normal file
@@ -0,0 +1,428 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Basic Chat Plugin
|
||||
* Implements basic communication commands.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Basic Chat",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Basic Communication Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
#define CHAT_SYMBOL '@'
|
||||
|
||||
char g_ColorNames[13][10] = {"White", "Red", "Green", "Blue", "Yellow", "Purple", "Cyan", "Orange", "Pink", "Olive", "Lime", "Violet", "Lightblue"};
|
||||
int g_Colors[13][3] = {{255,255,255},{255,0,0},{0,255,0},{0,0,255},{255,255,0},{255,0,255},{0,255,255},{255,128,0},{255,0,128},{128,255,0},{0,255,128},{128,0,255},{0,128,255}};
|
||||
|
||||
ConVar g_Cvar_Chatmode;
|
||||
|
||||
EngineVersion g_GameEngine = Engine_Unknown;
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
|
||||
g_GameEngine = GetEngineVersion();
|
||||
|
||||
g_Cvar_Chatmode = CreateConVar("sm_chat_mode", "1", "Allows player's to send messages to admin chat.", 0, true, 0.0, true, 1.0);
|
||||
|
||||
RegAdminCmd("sm_say", Command_SmSay, ADMFLAG_CHAT, "sm_say <message> - sends message to all players");
|
||||
RegAdminCmd("sm_csay", Command_SmCsay, ADMFLAG_CHAT, "sm_csay <message> - sends centered message to all players");
|
||||
|
||||
/* HintText does not work on Dark Messiah */
|
||||
if (g_GameEngine != Engine_DarkMessiah)
|
||||
{
|
||||
RegAdminCmd("sm_hsay", Command_SmHsay, ADMFLAG_CHAT, "sm_hsay <message> - sends hint message to all players");
|
||||
}
|
||||
|
||||
RegAdminCmd("sm_tsay", Command_SmTsay, ADMFLAG_CHAT, "sm_tsay [color] <message> - sends top-left message to all players");
|
||||
RegAdminCmd("sm_chat", Command_SmChat, ADMFLAG_CHAT, "sm_chat <message> - sends message to admins");
|
||||
RegAdminCmd("sm_psay", Command_SmPsay, ADMFLAG_CHAT, "sm_psay <name or #userid> <message> - sends private message");
|
||||
RegAdminCmd("sm_msay", Command_SmMsay, ADMFLAG_CHAT, "sm_msay <message> - sends message as a menu panel");
|
||||
}
|
||||
|
||||
public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
|
||||
{
|
||||
int startidx;
|
||||
if (sArgs[startidx] != CHAT_SYMBOL)
|
||||
return Plugin_Continue;
|
||||
|
||||
startidx++;
|
||||
|
||||
if (strcmp(command, "say", false) == 0)
|
||||
{
|
||||
if (sArgs[startidx] != CHAT_SYMBOL) // sm_say alias
|
||||
{
|
||||
if (!CheckCommandAccess(client, "sm_say", ADMFLAG_CHAT))
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
SendChatToAll(client, sArgs[startidx]);
|
||||
LogAction(client, -1, "\"%L\" triggered sm_say (text %s)", client, sArgs[startidx]);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
startidx++;
|
||||
|
||||
if (sArgs[startidx] != CHAT_SYMBOL) // sm_psay alias
|
||||
{
|
||||
if (!CheckCommandAccess(client, "sm_psay", ADMFLAG_CHAT))
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
char arg[64];
|
||||
|
||||
int len = BreakString(sArgs[startidx], arg, sizeof(arg));
|
||||
int target = FindTarget(client, arg, true, false);
|
||||
|
||||
if (target == -1 || len == -1)
|
||||
return Plugin_Stop;
|
||||
|
||||
SendPrivateChat(client, target, sArgs[startidx+len]);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
startidx++;
|
||||
|
||||
// sm_csay alias
|
||||
if (!CheckCommandAccess(client, "sm_csay", ADMFLAG_CHAT))
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
DisplayCenterTextToAll(client, sArgs[startidx]);
|
||||
LogAction(client, -1, "\"%L\" triggered sm_csay (text %s)", client, sArgs[startidx]);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
else if (strcmp(command, "say_team", false) == 0 || strcmp(command, "say_squad", false) == 0)
|
||||
{
|
||||
if (!CheckCommandAccess(client, "sm_chat", ADMFLAG_CHAT) && !g_Cvar_Chatmode.BoolValue)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
SendChatToAdmins(client, sArgs[startidx]);
|
||||
LogAction(client, -1, "\"%L\" triggered sm_chat (text %s)", client, sArgs[startidx]);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Command_SmSay(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_say <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
SendChatToAll(client, text);
|
||||
LogAction(client, -1, "\"%L\" triggered sm_say (text %s)", client, text);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_SmCsay(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_csay <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
DisplayCenterTextToAll(client, text);
|
||||
|
||||
LogAction(client, -1, "\"%L\" triggered sm_csay (text %s)", client, text);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_SmHsay(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_hsay <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
char nameBuf[MAX_NAME_LENGTH];
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientInGame(i) || IsFakeClient(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
FormatActivitySource(client, i, nameBuf, sizeof(nameBuf));
|
||||
PrintHintText(i, "%s: %s", nameBuf, text);
|
||||
}
|
||||
|
||||
LogAction(client, -1, "\"%L\" triggered sm_hsay (text %s)", client, text);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_SmTsay(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_tsay <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192], colorStr[16];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
int len = BreakString(text, colorStr, 16);
|
||||
|
||||
int color = FindColor(colorStr);
|
||||
char nameBuf[MAX_NAME_LENGTH];
|
||||
|
||||
if (color == -1)
|
||||
{
|
||||
color = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientInGame(i) || IsFakeClient(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
FormatActivitySource(client, i, nameBuf, sizeof(nameBuf));
|
||||
SendDialogToOne(i, color, "%s: %s", nameBuf, text[len]);
|
||||
}
|
||||
|
||||
LogAction(client, -1, "\"%L\" triggered sm_tsay (text %s)", client, text);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_SmChat(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_chat <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
SendChatToAdmins(client, text);
|
||||
LogAction(client, -1, "\"%L\" triggered sm_chat (text %s)", client, text);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_SmPsay(int client, int args)
|
||||
{
|
||||
if (args < 2)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_psay <name or #userid> <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192], arg[64], message[192];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
int len = BreakString(text, arg, sizeof(arg));
|
||||
BreakString(text[len], message, sizeof(message));
|
||||
|
||||
int target = FindTarget(client, arg, true, false);
|
||||
|
||||
if (target == -1)
|
||||
return Plugin_Handled;
|
||||
|
||||
SendPrivateChat(client, target, message);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_SmMsay(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_msay <message>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[192];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
SendPanelToAll(client, text);
|
||||
|
||||
LogAction(client, -1, "\"%L\" triggered sm_msay (text %s)", client, text);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
int FindColor(const char[] color)
|
||||
{
|
||||
for (int i = 0; i < sizeof(g_ColorNames); i++)
|
||||
{
|
||||
if (strcmp(color, g_ColorNames[i], false) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SendChatToAll(int client, const char[] message)
|
||||
{
|
||||
char nameBuf[MAX_NAME_LENGTH];
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientInGame(i) || IsFakeClient(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
FormatActivitySource(client, i, nameBuf, sizeof(nameBuf));
|
||||
|
||||
PrintToChat(i, "\x04(ALL) %s: \x01%s", nameBuf, message);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayCenterTextToAll(int client, const char[] message)
|
||||
{
|
||||
char nameBuf[MAX_NAME_LENGTH];
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientInGame(i) || IsFakeClient(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
FormatActivitySource(client, i, nameBuf, sizeof(nameBuf));
|
||||
PrintCenterText(i, "%s: %s", nameBuf, message);
|
||||
}
|
||||
}
|
||||
|
||||
void SendChatToAdmins(int from, const char[] message)
|
||||
{
|
||||
int fromAdmin = CheckCommandAccess(from, "sm_chat", ADMFLAG_CHAT);
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (IsClientInGame(i) && (from == i || CheckCommandAccess(i, "sm_chat", ADMFLAG_CHAT)))
|
||||
{
|
||||
PrintToChat(i, "\x04(%sADMINS) %N: \x01%s", fromAdmin ? "" : "TO ", from, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendDialogToOne(int client, int color, const char[] text, any ...)
|
||||
{
|
||||
char message[100];
|
||||
VFormat(message, sizeof(message), text, 4);
|
||||
|
||||
KeyValues kv = new KeyValues("Stuff", "title", message);
|
||||
kv.SetColor("color", g_Colors[color][0], g_Colors[color][1], g_Colors[color][2], 255);
|
||||
kv.SetNum("level", 1);
|
||||
kv.SetNum("time", 10);
|
||||
|
||||
CreateDialog(client, kv, DialogType_Msg);
|
||||
|
||||
delete kv;
|
||||
}
|
||||
|
||||
void SendPrivateChat(int client, int target, const char[] message)
|
||||
{
|
||||
if (!client)
|
||||
{
|
||||
PrintToServer("(Private to %N) %N: %s", target, client, message);
|
||||
}
|
||||
else if (target != client)
|
||||
{
|
||||
PrintToChat(client, "\x04(Private to %N) %N: \x01%s", target, client, message);
|
||||
}
|
||||
|
||||
PrintToChat(target, "\x04(Private to %N) %N: \x01%s", target, client, message);
|
||||
LogAction(client, -1, "\"%L\" triggered sm_psay to \"%L\" (text %s)", client, target, message);
|
||||
}
|
||||
|
||||
void SendPanelToAll(int from, char[] message)
|
||||
{
|
||||
char title[100];
|
||||
Format(title, 64, "%N:", from);
|
||||
|
||||
ReplaceString(message, 192, "\\n", "\n");
|
||||
|
||||
Panel mSayPanel = new Panel();
|
||||
mSayPanel.SetTitle(title);
|
||||
mSayPanel.DrawItem("", ITEMDRAW_SPACER);
|
||||
mSayPanel.DrawText(message);
|
||||
mSayPanel.DrawItem("", ITEMDRAW_SPACER);
|
||||
|
||||
mSayPanel.CurrentKey = GetMaxPageItems(mSayPanel.Style);
|
||||
mSayPanel.DrawItem("Exit", ITEMDRAW_CONTROL);
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(IsClientInGame(i) && !IsFakeClient(i))
|
||||
{
|
||||
mSayPanel.Send(i, Handler_DoNothing, 10);
|
||||
}
|
||||
}
|
||||
|
||||
delete mSayPanel;
|
||||
}
|
||||
|
||||
public int Handler_DoNothing(Menu menu, MenuAction action, int param1, int param2)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
242
scripting/temp/basecomm.sp
Normal file
242
scripting/temp/basecomm.sp
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Communication Plugin
|
||||
* Provides fucntionality for controlling communication on the server
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
* 1
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma semicolon 1
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Basic Comm Control",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Provides methods of controlling communication.",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
bool g_Muted[MAXPLAYERS+1]; // Is the player muted?
|
||||
bool g_Gagged[MAXPLAYERS+1]; // Is the player gagged?
|
||||
|
||||
ConVar g_Cvar_Deadtalk; // Holds the handle for sm_deadtalk
|
||||
ConVar g_Cvar_Alltalk; // Holds the handle for sv_alltalk
|
||||
bool g_Hooked = false; // Tracks if we've hooked events for deadtalk
|
||||
|
||||
TopMenu hTopMenu;
|
||||
|
||||
int g_GagTarget[MAXPLAYERS+1];
|
||||
|
||||
#include "basecomm/gag.sp"
|
||||
#include "basecomm/natives.sp"
|
||||
#include "basecomm/forwards.sp"
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
||||
{
|
||||
CreateNative("BaseComm_IsClientGagged", Native_IsClientGagged);
|
||||
CreateNative("BaseComm_IsClientMuted", Native_IsClientMuted);
|
||||
CreateNative("BaseComm_SetClientGag", Native_SetClientGag);
|
||||
CreateNative("BaseComm_SetClientMute", Native_SetClientMute);
|
||||
RegPluginLibrary("basecomm");
|
||||
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("basecomm.phrases");
|
||||
|
||||
g_Cvar_Deadtalk = CreateConVar("sm_deadtalk", "0", "Controls how dead communicate. 0 - Off. 1 - Dead players ignore teams. 2 - Dead players talk to living teammates.", 0, true, 0.0, true, 2.0);
|
||||
g_Cvar_Alltalk = FindConVar("sv_alltalk");
|
||||
|
||||
RegAdminCmd("sm_mute", Command_Mute, ADMFLAG_CHAT, "sm_mute <player> - Removes a player's ability to use voice.");
|
||||
RegAdminCmd("sm_gag", Command_Gag, ADMFLAG_CHAT, "sm_gag <player> - Removes a player's ability to use chat.");
|
||||
RegAdminCmd("sm_silence", Command_Silence, ADMFLAG_CHAT, "sm_silence <player> - Removes a player's ability to use voice or chat.");
|
||||
|
||||
RegAdminCmd("sm_unmute", Command_Unmute, ADMFLAG_CHAT, "sm_unmute <player> - Restores a player's ability to use voice.");
|
||||
RegAdminCmd("sm_ungag", Command_Ungag, ADMFLAG_CHAT, "sm_ungag <player> - Restores a player's ability to use chat.");
|
||||
RegAdminCmd("sm_unsilence", Command_Unsilence, ADMFLAG_CHAT, "sm_unsilence <player> - Restores a player's ability to use voice and chat.");
|
||||
|
||||
g_Cvar_Deadtalk.AddChangeHook(ConVarChange_Deadtalk);
|
||||
g_Cvar_Alltalk.AddChangeHook(ConVarChange_Alltalk);
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Build the "Player Commands" category */
|
||||
TopMenuObject player_commands = hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
|
||||
|
||||
if (player_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_gag", AdminMenu_Gag, player_commands, "sm_gag", ADMFLAG_CHAT);
|
||||
}
|
||||
}
|
||||
|
||||
public void ConVarChange_Deadtalk(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
if (g_Cvar_Deadtalk.IntValue)
|
||||
{
|
||||
HookEvent("player_spawn", Event_PlayerSpawn, EventHookMode_Post);
|
||||
HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post);
|
||||
g_Hooked = true;
|
||||
}
|
||||
else if (g_Hooked)
|
||||
{
|
||||
UnhookEvent("player_spawn", Event_PlayerSpawn);
|
||||
UnhookEvent("player_death", Event_PlayerDeath);
|
||||
g_Hooked = false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnClientConnect(int client, char[] rejectmsg, int maxlen)
|
||||
{
|
||||
g_Gagged[client] = false;
|
||||
g_Muted[client] = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
|
||||
{
|
||||
if (client && g_Gagged[client])
|
||||
{
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void ConVarChange_Alltalk(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
int mode = g_Cvar_Deadtalk.IntValue;
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientInGame(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_Muted[i])
|
||||
{
|
||||
SetClientListeningFlags(i, VOICE_MUTED);
|
||||
}
|
||||
else if (g_Cvar_Alltalk.BoolValue)
|
||||
{
|
||||
SetClientListeningFlags(i, VOICE_NORMAL);
|
||||
}
|
||||
else if (!IsPlayerAlive(i))
|
||||
{
|
||||
if (mode == 1)
|
||||
{
|
||||
SetClientListeningFlags(i, VOICE_LISTENALL);
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
SetClientListeningFlags(i, VOICE_TEAM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
|
||||
if (!client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Muted[client])
|
||||
{
|
||||
SetClientListeningFlags(client, VOICE_MUTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetClientListeningFlags(client, VOICE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
|
||||
if (!client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Muted[client])
|
||||
{
|
||||
SetClientListeningFlags(client, VOICE_MUTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Cvar_Alltalk.BoolValue)
|
||||
{
|
||||
SetClientListeningFlags(client, VOICE_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
int mode = g_Cvar_Deadtalk.IntValue;
|
||||
if (mode == 1)
|
||||
{
|
||||
SetClientListeningFlags(client, VOICE_LISTENALL);
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
SetClientListeningFlags(client, VOICE_TEAM);
|
||||
}
|
||||
}
|
433
scripting/temp/basecommands.sp
Normal file
433
scripting/temp/basecommands.sp
Normal file
@@ -0,0 +1,433 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Basic Commands Plugin
|
||||
* Implements basic admin commands.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative 1works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Basic Commands",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Basic Admin Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
TopMenu hTopMenu;
|
||||
|
||||
Menu g_MapList;
|
||||
StringMap g_ProtectedVars;
|
||||
|
||||
#include "basecommands/kick.sp"
|
||||
#include "basecommands/reloadadmins.sp"
|
||||
#include "basecommands/cancelvote.sp"
|
||||
#include "basecommands/who.sp"
|
||||
#include "basecommands/map.sp"
|
||||
#include "basecommands/execcfg.sp"
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("plugin.basecommands");
|
||||
|
||||
RegAdminCmd("sm_kick", Command_Kick, ADMFLAG_KICK, "sm_kick <#userid|name> [reason]");
|
||||
RegAdminCmd("sm_map", Command_Map, ADMFLAG_CHANGEMAP, "sm_map <map>");
|
||||
RegAdminCmd("sm_rcon", Command_Rcon, ADMFLAG_RCON, "sm_rcon <args>");
|
||||
RegAdminCmd("sm_cvar", Command_Cvar, ADMFLAG_CONVARS, "sm_cvar <cvar> [value]");
|
||||
RegAdminCmd("sm_resetcvar", Command_ResetCvar, ADMFLAG_CONVARS, "sm_resetcvar <cvar>");
|
||||
RegAdminCmd("sm_execcfg", Command_ExecCfg, ADMFLAG_CONFIG, "sm_execcfg <filename>");
|
||||
RegAdminCmd("sm_who", Command_Who, ADMFLAG_GENERIC, "sm_who [#userid|name]");
|
||||
RegAdminCmd("sm_reloadadmins", Command_ReloadAdmins, ADMFLAG_BAN, "sm_reloadadmins");
|
||||
RegAdminCmd("sm_cancelvote", Command_CancelVote, ADMFLAG_VOTE, "sm_cancelvote");
|
||||
RegConsoleCmd("sm_revote", Command_ReVote);
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
|
||||
g_MapList = new Menu(MenuHandler_ChangeMap, MenuAction_Display);
|
||||
g_MapList.SetTitle("%T", "Please select a map", LANG_SERVER);
|
||||
g_MapList.ExitBackButton = true;
|
||||
|
||||
char mapListPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, mapListPath, sizeof(mapListPath), "configs/adminmenu_maplist.ini");
|
||||
SetMapListCompatBind("sm_map menu", mapListPath);
|
||||
|
||||
g_ProtectedVars = new StringMap();
|
||||
ProtectVar("rcon_password");
|
||||
ProtectVar("sm_show_activity");
|
||||
ProtectVar("sm_immunity_mode");
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
ParseConfigs();
|
||||
}
|
||||
|
||||
public void OnConfigsExecuted()
|
||||
{
|
||||
LoadMapList(g_MapList);
|
||||
}
|
||||
|
||||
void ProtectVar(const char[] cvar)
|
||||
{
|
||||
g_ProtectedVars.SetValue(cvar, 1);
|
||||
}
|
||||
|
||||
bool IsVarProtected(const char[] cvar)
|
||||
{
|
||||
int dummy_value;
|
||||
return g_ProtectedVars.GetValue(cvar, dummy_value);
|
||||
}
|
||||
|
||||
bool IsClientAllowedToChangeCvar(int client, const char[] cvarname)
|
||||
{
|
||||
ConVar hndl = FindConVar(cvarname);
|
||||
|
||||
bool allowed = false;
|
||||
int client_flags = client == 0 ? ADMFLAG_ROOT : GetUserFlagBits(client);
|
||||
|
||||
if (client_flags & ADMFLAG_ROOT)
|
||||
{
|
||||
allowed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hndl.Flags & FCVAR_PROTECTED)
|
||||
{
|
||||
allowed = ((client_flags & ADMFLAG_PASSWORD) == ADMFLAG_PASSWORD);
|
||||
}
|
||||
else if (StrEqual(cvarname, "sv_cheats"))
|
||||
{
|
||||
allowed = ((client_flags & ADMFLAG_CHEATS) == ADMFLAG_CHEATS);
|
||||
}
|
||||
else if (!IsVarProtected(cvarname))
|
||||
{
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Build the "Player Commands" category */
|
||||
TopMenuObject player_commands = hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
|
||||
|
||||
if (player_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_kick", AdminMenu_Kick, player_commands, "sm_kick", ADMFLAG_KICK);
|
||||
hTopMenu.AddItem("sm_who", AdminMenu_Who, player_commands, "sm_who", ADMFLAG_GENERIC);
|
||||
}
|
||||
|
||||
TopMenuObject server_commands = hTopMenu.FindCategory(ADMINMENU_SERVERCOMMANDS);
|
||||
|
||||
if (server_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_reloadadmins", AdminMenu_ReloadAdmins, server_commands, "sm_reloadadmins", ADMFLAG_BAN);
|
||||
hTopMenu.AddItem("sm_map", AdminMenu_Map, server_commands, "sm_map", ADMFLAG_CHANGEMAP);
|
||||
hTopMenu.AddItem("sm_execcfg", AdminMenu_ExecCFG, server_commands, "sm_execcfg", ADMFLAG_CONFIG);
|
||||
}
|
||||
|
||||
TopMenuObject voting_commands = hTopMenu.FindCategory(ADMINMENU_VOTINGCOMMANDS);
|
||||
|
||||
if (voting_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_cancelvote", AdminMenu_CancelVote, voting_commands, "sm_cancelvote", ADMFLAG_VOTE);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnLibraryRemoved(const char[] name)
|
||||
{
|
||||
if (strcmp(name, "adminmenu") == 0)
|
||||
{
|
||||
hTopMenu = null;
|
||||
}
|
||||
}
|
||||
|
||||
#define FLAG_STRINGS 14
|
||||
char g_FlagNames[FLAG_STRINGS][20] =
|
||||
{
|
||||
"res",
|
||||
"admin",
|
||||
"kick",
|
||||
"ban",
|
||||
"unban",
|
||||
"slay",
|
||||
"map",
|
||||
"cvars",
|
||||
"cfg",
|
||||
"chat",
|
||||
"vote",
|
||||
"pass",
|
||||
"rcon",
|
||||
"cheat"
|
||||
};
|
||||
|
||||
int CustomFlagsToString(char[] buffer, int maxlength, int flags)
|
||||
{
|
||||
char joins[6][6];
|
||||
int total;
|
||||
|
||||
for (int i=view_as<int>(Admin_Custom1); i<=view_as<int>(Admin_Custom6); i++)
|
||||
{
|
||||
if (flags & (1<<i))
|
||||
{
|
||||
IntToString(i - view_as<int>(Admin_Custom1) + 1, joins[total++], 6);
|
||||
}
|
||||
}
|
||||
|
||||
ImplodeStrings(joins, total, ",", buffer, maxlength);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void FlagsToString(char[] buffer, int maxlength, int flags)
|
||||
{
|
||||
char joins[FLAG_STRINGS+1][32];
|
||||
int total;
|
||||
|
||||
for (int i=0; i<FLAG_STRINGS; i++)
|
||||
{
|
||||
if (flags & (1<<i))
|
||||
{
|
||||
strcopy(joins[total++], 32, g_FlagNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
char custom_flags[32];
|
||||
if (CustomFlagsToString(custom_flags, sizeof(custom_flags), flags))
|
||||
{
|
||||
Format(joins[total++], 32, "custom(%s)", custom_flags);
|
||||
}
|
||||
|
||||
ImplodeStrings(joins, total, ", ", buffer, maxlength);
|
||||
}
|
||||
|
||||
public Action Command_Cvar(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
if (client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_cvar <cvar|protect> [value]");
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_cvar <cvar> [value]");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char cvarname[64];
|
||||
GetCmdArg(1, cvarname, sizeof(cvarname));
|
||||
|
||||
if (client == 0 && StrEqual(cvarname, "protect"))
|
||||
{
|
||||
if (args < 2)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_cvar <protect> <cvar>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
GetCmdArg(2, cvarname, sizeof(cvarname));
|
||||
ProtectVar(cvarname);
|
||||
ReplyToCommand(client, "[SM] %t", "Cvar is now protected", cvarname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
ConVar hndl = FindConVar(cvarname);
|
||||
if (hndl == null)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Unable to find cvar", cvarname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!IsClientAllowedToChangeCvar(client, cvarname))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "No access to cvar");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char value[255];
|
||||
if (args < 2)
|
||||
{
|
||||
hndl.GetString(value, sizeof(value));
|
||||
|
||||
ReplyToCommand(client, "[SM] %t", "Value of cvar", cvarname, value);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
GetCmdArg(2, value, sizeof(value));
|
||||
|
||||
// The server passes the values of these directly into ServerCommand, following exec. Sanitize.
|
||||
if (StrEqual(cvarname, "servercfgfile", false) || StrEqual(cvarname, "lservercfgfile", false))
|
||||
{
|
||||
int pos = StrContains(value, ";", true);
|
||||
if (pos != -1)
|
||||
{
|
||||
value[pos] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if ((hndl.Flags & FCVAR_PROTECTED) != FCVAR_PROTECTED)
|
||||
{
|
||||
ShowActivity2(client, "[SM] ", "%t", "Cvar changed", cvarname, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cvar changed", cvarname, value);
|
||||
}
|
||||
|
||||
LogAction(client, -1, "\"%L\" changed cvar (cvar \"%s\") (value \"%s\")", client, cvarname, value);
|
||||
|
||||
hndl.SetString(value, true);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_ResetCvar(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_resetcvar <cvar>");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char cvarname[64];
|
||||
GetCmdArg(1, cvarname, sizeof(cvarname));
|
||||
|
||||
ConVar hndl = FindConVar(cvarname);
|
||||
if (hndl == null)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Unable to find cvar", cvarname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!IsClientAllowedToChangeCvar(client, cvarname))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "No access to cvar");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
hndl.RestoreDefault();
|
||||
|
||||
char value[255];
|
||||
hndl.GetString(value, sizeof(value));
|
||||
|
||||
if ((hndl.Flags & FCVAR_PROTECTED) != FCVAR_PROTECTED)
|
||||
{
|
||||
ShowActivity2(client, "[SM] ", "%t", "Cvar changed", cvarname, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cvar changed", cvarname, value);
|
||||
}
|
||||
|
||||
LogAction(client, -1, "\"%L\" reset cvar (cvar \"%s\") (value \"%s\")", client, cvarname, value);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_Rcon(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_rcon <args>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char argstring[255];
|
||||
GetCmdArgString(argstring, sizeof(argstring));
|
||||
|
||||
LogAction(client, -1, "\"%L\" console command (cmdline \"%s\")", client, argstring);
|
||||
|
||||
if (client == 0) // They will already see the response in the console.
|
||||
{
|
||||
ServerCommand("%s", argstring);
|
||||
} else {
|
||||
char responseBuffer[4096];
|
||||
ServerCommandEx(responseBuffer, sizeof(responseBuffer), "%s", argstring);
|
||||
ReplyToCommand(client, responseBuffer);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_ReVote(int client, int args)
|
||||
{
|
||||
if (client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Command is in-game only");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!IsVoteInProgress())
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Vote Not In Progress");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!IsClientInVotePool(client))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cannot participate in vote");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!RedrawClientVoteMenu(client))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cannot change vote");
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
530
scripting/temp/basetriggers.sp
Normal file
530
scripting/temp/basetriggers.sp
Normal file
@@ -0,0 +1,530 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Basic Info Triggers Plugin
|
||||
* Implements basic information chat triggers like ff and timeleft.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <mapchooser>
|
||||
#define REQUIRE_PLUGIN
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Basic Info Triggers",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Adds ff, timeleft, thetime, and others.",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
ConVar g_Cvar_TriggerShow;
|
||||
ConVar g_Cvar_TimeleftInterval;
|
||||
ConVar g_Cvar_FriendlyFire;
|
||||
|
||||
Handle g_Timer_TimeShow = null;
|
||||
|
||||
ConVar g_Cvar_WinLimit;
|
||||
ConVar g_Cvar_FragLimit;
|
||||
ConVar g_Cvar_MaxRounds;
|
||||
|
||||
#define TIMELEFT_ALL_ALWAYS 0 /* Print to all players */
|
||||
#define TIMELEFT_ALL_MAYBE 1 /* Print to all players if sm_trigger_show allows */
|
||||
#define TIMELEFT_ONE 2 /* Print to a single player */
|
||||
|
||||
bool mapchooser;
|
||||
|
||||
int g_TotalRounds;
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("basetriggers.phrases");
|
||||
|
||||
g_Cvar_TriggerShow = CreateConVar("sm_trigger_show", "0", "Display triggers message to all players? (0 off, 1 on, def. 0)", 0, true, 0.0, true, 1.0);
|
||||
g_Cvar_TimeleftInterval = CreateConVar("sm_timeleft_interval", "0.0", "Display timeleft every x seconds. Default 0.", 0, true, 0.0, true, 1800.0);
|
||||
g_Cvar_FriendlyFire = FindConVar("mp_friendlyfire");
|
||||
|
||||
RegConsoleCmd("timeleft", Command_Timeleft);
|
||||
RegConsoleCmd("nextmap", Command_Nextmap);
|
||||
RegConsoleCmd("motd", Command_Motd);
|
||||
RegConsoleCmd("ff", Command_FriendlyFire);
|
||||
|
||||
g_Cvar_TimeleftInterval.AddChangeHook(ConVarChange_TimeleftInterval);
|
||||
|
||||
char folder[64];
|
||||
GetGameFolderName(folder, sizeof(folder));
|
||||
|
||||
if (strcmp(folder, "insurgency") == 0)
|
||||
{
|
||||
HookEvent("game_newmap", Event_GameStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
HookEvent("game_start", Event_GameStart);
|
||||
}
|
||||
|
||||
if (strcmp(folder, "nucleardawn") == 0)
|
||||
{
|
||||
HookEvent("round_win", Event_RoundEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HookEvent("round_end", Event_RoundEnd);
|
||||
}
|
||||
|
||||
HookEventEx("teamplay_win_panel", Event_TeamPlayWinPanel);
|
||||
HookEventEx("teamplay_restart_round", Event_TFRestartRound);
|
||||
HookEventEx("arena_win_panel", Event_TeamPlayWinPanel);
|
||||
|
||||
g_Cvar_WinLimit = FindConVar("mp_winlimit");
|
||||
g_Cvar_FragLimit = FindConVar("mp_fraglimit");
|
||||
g_Cvar_MaxRounds = FindConVar("mp_maxrounds");
|
||||
|
||||
mapchooser = LibraryExists("mapchooser");
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
g_TotalRounds = 0;
|
||||
}
|
||||
|
||||
/* Round count tracking */
|
||||
public void Event_TFRestartRound(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
/* Game got restarted - reset our round count tracking */
|
||||
g_TotalRounds = 0;
|
||||
}
|
||||
|
||||
public void Event_GameStart(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
/* Game got restarted - reset our round count tracking */
|
||||
g_TotalRounds = 0;
|
||||
}
|
||||
|
||||
public void Event_TeamPlayWinPanel(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
if (event.GetInt("round_complete") == 1 || StrEqual(name, "arena_win_panel"))
|
||||
{
|
||||
g_TotalRounds++;
|
||||
}
|
||||
}
|
||||
/* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */
|
||||
public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
g_TotalRounds++;
|
||||
}
|
||||
|
||||
public void OnLibraryRemoved(const char[] name)
|
||||
{
|
||||
if (StrEqual(name, "mapchooser"))
|
||||
{
|
||||
mapchooser = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnLibraryAdded(const char[] name)
|
||||
{
|
||||
if (StrEqual(name, "mapchooser"))
|
||||
{
|
||||
mapchooser = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ConVarChange_TimeleftInterval(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
float newval = StringToFloat(newValue);
|
||||
|
||||
if (newval < 1.0)
|
||||
{
|
||||
if (g_Timer_TimeShow != null)
|
||||
{
|
||||
KillTimer(g_Timer_TimeShow);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Timer_TimeShow != null)
|
||||
{
|
||||
KillTimer(g_Timer_TimeShow);
|
||||
g_Timer_TimeShow = CreateTimer(newval, Timer_DisplayTimeleft, _, TIMER_REPEAT);
|
||||
}
|
||||
else
|
||||
g_Timer_TimeShow = CreateTimer(newval, Timer_DisplayTimeleft, _, TIMER_REPEAT);
|
||||
}
|
||||
|
||||
public Action Timer_DisplayTimeleft(Handle timer)
|
||||
{
|
||||
ShowTimeLeft(0, TIMELEFT_ALL_ALWAYS);
|
||||
}
|
||||
|
||||
public Action Command_Timeleft(int client, int args)
|
||||
{
|
||||
ShowTimeLeft(client, TIMELEFT_ONE);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_Nextmap(int client, int args)
|
||||
{
|
||||
if (client && !IsClientInGame(client))
|
||||
return Plugin_Handled;
|
||||
|
||||
char map[PLATFORM_MAX_PATH];
|
||||
|
||||
GetNextMap(map, sizeof(map));
|
||||
|
||||
if (mapchooser && EndOfMapVoteEnabled() && !HasEndOfMapVoteFinished())
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Pending Vote");
|
||||
}
|
||||
else
|
||||
{
|
||||
GetMapDisplayName(map, map, sizeof(map));
|
||||
ReplyToCommand(client, "[SM] %t", "Next Map", map);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_Motd(int client, int args)
|
||||
{
|
||||
if (client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Command is in-game only");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!IsClientInGame(client))
|
||||
return Plugin_Handled;
|
||||
|
||||
ShowMOTDPanel(client, "Message Of The Day", "motd", MOTDPANEL_TYPE_INDEX);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_FriendlyFire(int client, int args)
|
||||
{
|
||||
if (client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Command is in-game only");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!IsClientInGame(client))
|
||||
return Plugin_Handled;
|
||||
|
||||
ShowFriendlyFire(client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void OnClientSayCommand_Post(int client, const char[] command, const char[] sArgs)
|
||||
{
|
||||
if (strcmp(sArgs, "timeleft", false) == 0)
|
||||
{
|
||||
ShowTimeLeft(client, TIMELEFT_ALL_MAYBE);
|
||||
}
|
||||
else if (strcmp(sArgs, "thetime", false) == 0)
|
||||
{
|
||||
char ctime[64];
|
||||
FormatTime(ctime, 64, NULL_STRING);
|
||||
|
||||
if (g_Cvar_TriggerShow.IntValue)
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Thetime", ctime);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChat(client,"[SM] %t", "Thetime", ctime);
|
||||
}
|
||||
}
|
||||
else if (strcmp(sArgs, "ff", false) == 0)
|
||||
{
|
||||
ShowFriendlyFire(client);
|
||||
}
|
||||
else if (strcmp(sArgs, "currentmap", false) == 0)
|
||||
{
|
||||
char map[64];
|
||||
GetCurrentMap(map, sizeof(map));
|
||||
|
||||
if (g_Cvar_TriggerShow.IntValue)
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Current Map", map);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChat(client,"[SM] %t", "Current Map", map);
|
||||
}
|
||||
}
|
||||
else if (strcmp(sArgs, "nextmap", false) == 0)
|
||||
{
|
||||
char map[PLATFORM_MAX_PATH];
|
||||
GetNextMap(map, sizeof(map));
|
||||
GetMapDisplayName(map, map, sizeof(map));
|
||||
|
||||
if (g_Cvar_TriggerShow.IntValue)
|
||||
{
|
||||
if (mapchooser && EndOfMapVoteEnabled() && !HasEndOfMapVoteFinished())
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Pending Vote");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Next Map", map);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mapchooser && EndOfMapVoteEnabled() && !HasEndOfMapVoteFinished())
|
||||
{
|
||||
PrintToChat(client, "[SM] %t", "Pending Vote");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChat(client, "[SM] %t", "Next Map", map);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(sArgs, "motd", false) == 0)
|
||||
{
|
||||
ShowMOTDPanel(client, "Message Of The Day", "motd", MOTDPANEL_TYPE_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowTimeLeft(int client, int who)
|
||||
{
|
||||
bool lastround = false;
|
||||
bool written = false;
|
||||
bool notimelimit = false;
|
||||
|
||||
char finalOutput[1024];
|
||||
|
||||
if (who == TIMELEFT_ALL_ALWAYS
|
||||
|| (who == TIMELEFT_ALL_MAYBE && g_Cvar_TriggerShow.IntValue))
|
||||
{
|
||||
client = 0;
|
||||
}
|
||||
|
||||
int timeleft;
|
||||
if (GetMapTimeLeft(timeleft))
|
||||
{
|
||||
int mins, secs;
|
||||
int timelimit;
|
||||
|
||||
if (timeleft > 0)
|
||||
{
|
||||
mins = timeleft / 60;
|
||||
secs = timeleft % 60;
|
||||
written = true;
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T %d:%02d", "Timeleft", client, mins, secs);
|
||||
}
|
||||
else if (GetMapTimeLimit(timelimit) && timelimit == 0)
|
||||
{
|
||||
notimelimit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 0 timeleft so this must be the last round */
|
||||
lastround=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lastround)
|
||||
{
|
||||
if (g_Cvar_WinLimit)
|
||||
{
|
||||
int winlimit = g_Cvar_WinLimit.IntValue;
|
||||
|
||||
if (winlimit > 0)
|
||||
{
|
||||
if (written)
|
||||
{
|
||||
int len = strlen(finalOutput);
|
||||
if (len < sizeof(finalOutput))
|
||||
{
|
||||
if (winlimit > 1)
|
||||
{
|
||||
FormatEx(finalOutput[len], sizeof(finalOutput)-len, "%T", "WinLimitAppendPlural" ,client, winlimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(finalOutput[len], sizeof(finalOutput)-len, "%T", "WinLimitAppend" ,client);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (winlimit > 1)
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "WinLimitPlural", client, winlimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "WinLimit", client);
|
||||
}
|
||||
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Cvar_FragLimit)
|
||||
{
|
||||
int fraglimit = g_Cvar_FragLimit.IntValue;
|
||||
|
||||
if (fraglimit > 0)
|
||||
{
|
||||
if (written)
|
||||
{
|
||||
int len = strlen(finalOutput);
|
||||
if (len < sizeof(finalOutput))
|
||||
{
|
||||
if (fraglimit > 1)
|
||||
{
|
||||
FormatEx(finalOutput[len], sizeof(finalOutput)-len, "%T", "FragLimitAppendPlural", client, fraglimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(finalOutput[len], sizeof(finalOutput)-len, "%T", "FragLimitAppend", client);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fraglimit > 1)
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "FragLimitPlural", client, fraglimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "FragLimit", client);
|
||||
}
|
||||
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Cvar_MaxRounds)
|
||||
{
|
||||
int maxrounds = g_Cvar_MaxRounds.IntValue;
|
||||
|
||||
if (maxrounds > 0)
|
||||
{
|
||||
int remaining = maxrounds - g_TotalRounds;
|
||||
|
||||
if (written)
|
||||
{
|
||||
int len = strlen(finalOutput);
|
||||
if (len < sizeof(finalOutput))
|
||||
{
|
||||
if (remaining > 1)
|
||||
{
|
||||
FormatEx(finalOutput[len], sizeof(finalOutput)-len, "%T", "MaxRoundsAppendPlural", client, remaining);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(finalOutput[len], sizeof(finalOutput)-len, "%T", "MaxRoundsAppend", client);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (remaining > 1)
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "MaxRoundsPlural", client, remaining);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "MaxRounds", client);
|
||||
}
|
||||
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastround)
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "LastRound", client);
|
||||
}
|
||||
else if (notimelimit && !written)
|
||||
{
|
||||
FormatEx(finalOutput, sizeof(finalOutput), "%T", "NoTimelimit", client);
|
||||
}
|
||||
|
||||
if (who == TIMELEFT_ALL_ALWAYS
|
||||
|| (who == TIMELEFT_ALL_MAYBE && g_Cvar_TriggerShow.IntValue))
|
||||
{
|
||||
PrintToChatAll("[SM] %s", finalOutput);
|
||||
}
|
||||
else if (client != 0 && IsClientInGame(client))
|
||||
{
|
||||
PrintToChat(client, "[SM] %s", finalOutput);
|
||||
}
|
||||
|
||||
if (client == 0)
|
||||
{
|
||||
PrintToServer("[SM] %s", finalOutput);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowFriendlyFire(int client)
|
||||
{
|
||||
if (g_Cvar_FriendlyFire)
|
||||
{
|
||||
char phrase[24];
|
||||
if (g_Cvar_FriendlyFire.BoolValue)
|
||||
{
|
||||
strcopy(phrase, sizeof(phrase), "Friendly Fire On");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcopy(phrase, sizeof(phrase), "Friendly Fire Off");
|
||||
}
|
||||
|
||||
if (g_Cvar_TriggerShow.IntValue)
|
||||
{
|
||||
PrintToChatAll("[SM] %t", phrase);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChat(client,"[SM] %t", phrase);
|
||||
}
|
||||
}
|
||||
}
|
418
scripting/temp/basevotes.sp
Normal file
418
scripting/temp/basevotes.sp
Normal file
@@ -0,0 +1,418 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Basic Votes Plugin
|
||||
* Implements basic vote commands.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Basic Votes",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Basic Vote Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
#define VOTE_NO "###no###"
|
||||
#define VOTE_YES "###yes###"
|
||||
|
||||
Menu g_hVoteMenu = null;
|
||||
|
||||
ConVar g_Cvar_Limits[3] = {null, ...};
|
||||
//ConVar g_Cvar_VoteSay = null;
|
||||
|
||||
enum voteType
|
||||
{
|
||||
map,
|
||||
kick,
|
||||
ban,
|
||||
question
|
||||
}
|
||||
|
||||
voteType g_voteType = question;
|
||||
|
||||
// Menu API does not provide us with a way to pass multiple peices of data with a single
|
||||
// choice, so some globals are used to hold stuff.
|
||||
//
|
||||
#define VOTE_CLIENTID 0
|
||||
#define VOTE_USERID 1
|
||||
int g_voteClient[2]; /* Holds the target's client id and user id */
|
||||
|
||||
#define VOTE_NAME 0
|
||||
#define VOTE_AUTHID 1
|
||||
#define VOTE_IP 2
|
||||
char g_voteInfo[3][65]; /* Holds the target's name, authid, and IP */
|
||||
|
||||
char g_voteArg[256]; /* Used to hold ban/kick reasons or vote questions */
|
||||
|
||||
|
||||
TopMenu hTopMenu;
|
||||
|
||||
#include "basevotes/votekick.sp"
|
||||
#include "basevotes/voteban.sp"
|
||||
#include "basevotes/votemap.sp"
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("basevotes.phrases");
|
||||
LoadTranslations("plugin.basecommands");
|
||||
LoadTranslations("basebans.phrases");
|
||||
|
||||
RegAdminCmd("sm_votemap", Command_Votemap, ADMFLAG_VOTE|ADMFLAG_CHANGEMAP, "sm_votemap <mapname> [mapname2] ... [mapname5] ");
|
||||
RegAdminCmd("sm_votekick", Command_Votekick, ADMFLAG_VOTE|ADMFLAG_KICK, "sm_votekick <player> [reason]");
|
||||
RegAdminCmd("sm_voteban", Command_Voteban, ADMFLAG_VOTE|ADMFLAG_BAN, "sm_voteban <player> [reason]");
|
||||
RegAdminCmd("sm_vote", Command_Vote, ADMFLAG_VOTE, "sm_vote <question> [Answer1] [Answer2] ... [Answer5]");
|
||||
|
||||
/*
|
||||
g_Cvar_Show = FindConVar("sm_vote_show");
|
||||
if (g_Cvar_Show == null)
|
||||
{
|
||||
g_Cvar_Show = CreateConVar("sm_vote_show", "1", "Show player's votes? Default on.", 0, true, 0.0, true, 1.0);
|
||||
}
|
||||
*/
|
||||
|
||||
g_Cvar_Limits[0] = CreateConVar("sm_vote_map", "0.60", "percent required for successful map vote.", 0, true, 0.05, true, 1.0);
|
||||
g_Cvar_Limits[1] = CreateConVar("sm_vote_kick", "0.60", "percent required for successful kick vote.", 0, true, 0.05, true, 1.0);
|
||||
g_Cvar_Limits[2] = CreateConVar("sm_vote_ban", "0.60", "percent required for successful ban vote.", 0, true, 0.05, true, 1.0);
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
|
||||
g_SelectedMaps = new ArrayList(ByteCountToCells(PLATFORM_MAX_PATH));
|
||||
|
||||
g_MapList = new Menu(MenuHandler_Map, MenuAction_DrawItem|MenuAction_Display);
|
||||
g_MapList.SetTitle("%T", "Please select a map", LANG_SERVER);
|
||||
g_MapList.ExitBackButton = true;
|
||||
|
||||
char mapListPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, mapListPath, sizeof(mapListPath), "configs/adminmenu_maplist.ini");
|
||||
SetMapListCompatBind("sm_votemap menu", mapListPath);
|
||||
}
|
||||
|
||||
public void OnConfigsExecuted()
|
||||
{
|
||||
g_mapCount = LoadMapList(g_MapList);
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Build the "Voting Commands" category */
|
||||
TopMenuObject voting_commands = hTopMenu.FindCategory(ADMINMENU_VOTINGCOMMANDS);
|
||||
|
||||
if (voting_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_votekick", AdminMenu_VoteKick, voting_commands, "sm_votekick", ADMFLAG_VOTE|ADMFLAG_KICK);
|
||||
hTopMenu.AddItem("sm_voteban", AdminMenu_VoteBan, voting_commands, "sm_voteban", ADMFLAG_VOTE|ADMFLAG_BAN);
|
||||
hTopMenu.AddItem("sm_votemap", AdminMenu_VoteMap, voting_commands, "sm_votemap", ADMFLAG_VOTE|ADMFLAG_CHANGEMAP);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_Vote(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_vote <question> [Answer1] [Answer2] ... [Answer5]");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (IsVoteInProgress())
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Vote in Progress");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!TestVoteDelay(client))
|
||||
{
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char text[256];
|
||||
GetCmdArgString(text, sizeof(text));
|
||||
|
||||
char answers[5][64];
|
||||
int answerCount;
|
||||
int len = BreakString(text, g_voteArg, sizeof(g_voteArg));
|
||||
int pos = len;
|
||||
|
||||
while (args > 1 && pos != -1 && answerCount < 5)
|
||||
{
|
||||
pos = BreakString(text[len], answers[answerCount], sizeof(answers[]));
|
||||
answerCount++;
|
||||
|
||||
if (pos != -1)
|
||||
{
|
||||
len += pos;
|
||||
}
|
||||
}
|
||||
|
||||
LogAction(client, -1, "\"%L\" initiated a generic vote.", client);
|
||||
ShowActivity2(client, "[SM] ", "%t", "Initiate Vote", g_voteArg);
|
||||
|
||||
g_voteType = question;
|
||||
|
||||
g_hVoteMenu = new Menu(Handler_VoteCallback, MENU_ACTIONS_ALL);
|
||||
g_hVoteMenu.SetTitle("%s?", g_voteArg);
|
||||
|
||||
if (answerCount < 2)
|
||||
{
|
||||
g_hVoteMenu.AddItem(VOTE_YES, "Yes");
|
||||
g_hVoteMenu.AddItem(VOTE_NO, "No");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < answerCount; i++)
|
||||
{
|
||||
g_hVoteMenu.AddItem(answers[i], answers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
g_hVoteMenu.ExitButton = false;
|
||||
g_hVoteMenu.DisplayVoteToAll(20);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public int Handler_VoteCallback(Menu menu, MenuAction action, int param1, int param2)
|
||||
{
|
||||
if (action == MenuAction_End)
|
||||
{
|
||||
VoteMenuClose();
|
||||
}
|
||||
else if (action == MenuAction_Display)
|
||||
{
|
||||
if (g_voteType != question)
|
||||
{
|
||||
char title[64];
|
||||
menu.GetTitle(title, sizeof(title));
|
||||
|
||||
char buffer[255];
|
||||
Format(buffer, sizeof(buffer), "%T", title, param1, g_voteInfo[VOTE_NAME]);
|
||||
|
||||
Panel panel = view_as<Panel>(param2);
|
||||
panel.SetTitle(buffer);
|
||||
}
|
||||
}
|
||||
else if (action == MenuAction_DisplayItem)
|
||||
{
|
||||
char display[64];
|
||||
menu.GetItem(param2, "", 0, _, display, sizeof(display));
|
||||
|
||||
if (strcmp(display, "No") == 0 || strcmp(display, "Yes") == 0)
|
||||
{
|
||||
char buffer[255];
|
||||
Format(buffer, sizeof(buffer), "%T", display, param1);
|
||||
|
||||
return RedrawMenuItem(buffer);
|
||||
}
|
||||
}
|
||||
/* else if (action == MenuAction_Select)
|
||||
{
|
||||
VoteSelect(menu, param1, param2);
|
||||
}*/
|
||||
else if (action == MenuAction_VoteCancel && param1 == VoteCancel_NoVotes)
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "No Votes Cast");
|
||||
}
|
||||
else if (action == MenuAction_VoteEnd)
|
||||
{
|
||||
char item[64], display[64];
|
||||
float percent, limit;
|
||||
int votes, totalVotes;
|
||||
|
||||
GetMenuVoteInfo(param2, votes, totalVotes);
|
||||
menu.GetItem(param1, item, sizeof(item), _, display, sizeof(display));
|
||||
|
||||
if (strcmp(item, VOTE_NO) == 0 && param1 == 1)
|
||||
{
|
||||
votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
|
||||
}
|
||||
|
||||
percent = GetVotePercent(votes, totalVotes);
|
||||
|
||||
if (g_voteType != question)
|
||||
{
|
||||
limit = g_Cvar_Limits[g_voteType].FloatValue;
|
||||
}
|
||||
|
||||
/* :TODO: g_voteClient[userid] needs to be checked */
|
||||
|
||||
// A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
|
||||
if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1))
|
||||
{
|
||||
/* :TODO: g_voteClient[userid] should be used here and set to -1 if not applicable.
|
||||
*/
|
||||
LogAction(-1, -1, "Vote failed.");
|
||||
PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Vote Successful", RoundToNearest(100.0*percent), totalVotes);
|
||||
|
||||
switch (g_voteType)
|
||||
{
|
||||
case (question):
|
||||
{
|
||||
if (strcmp(item, VOTE_NO) == 0 || strcmp(item, VOTE_YES) == 0)
|
||||
{
|
||||
strcopy(item, sizeof(item), display);
|
||||
}
|
||||
|
||||
PrintToChatAll("[SM] %t", "Vote End", g_voteArg, item);
|
||||
}
|
||||
|
||||
case (map):
|
||||
{
|
||||
// single-vote items don't use the display item
|
||||
char displayName[PLATFORM_MAX_PATH];
|
||||
GetMapDisplayName(item, displayName, sizeof(displayName));
|
||||
LogAction(-1, -1, "Changing map to %s due to vote.", item);
|
||||
PrintToChatAll("[SM] %t", "Changing map", displayName);
|
||||
DataPack dp;
|
||||
CreateDataTimer(5.0, Timer_ChangeMap, dp);
|
||||
dp.WriteString(item);
|
||||
}
|
||||
|
||||
case (kick):
|
||||
{
|
||||
if (g_voteArg[0] == '\0')
|
||||
{
|
||||
strcopy(g_voteArg, sizeof(g_voteArg), "Votekicked");
|
||||
}
|
||||
|
||||
PrintToChatAll("[SM] %t", "Kicked target", "_s", g_voteInfo[VOTE_NAME]);
|
||||
LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote kick successful, kicked \"%L\" (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg);
|
||||
|
||||
ServerCommand("kickid %d \"%s\"", g_voteClient[VOTE_USERID], g_voteArg);
|
||||
}
|
||||
|
||||
case (ban):
|
||||
{
|
||||
if (g_voteArg[0] == '\0')
|
||||
{
|
||||
strcopy(g_voteArg, sizeof(g_voteArg), "Votebanned");
|
||||
}
|
||||
|
||||
PrintToChatAll("[SM] %t", "Banned player", g_voteInfo[VOTE_NAME], 30);
|
||||
LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote ban successful, banned \"%L\" (minutes \"30\") (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg);
|
||||
|
||||
BanClient(g_voteClient[VOTE_CLIENTID],
|
||||
30,
|
||||
BANFLAG_AUTO,
|
||||
g_voteArg,
|
||||
"Banned by vote",
|
||||
"sm_voteban");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void VoteSelect(Menu menu, int param1, int param2 = 0)
|
||||
{
|
||||
if (g_Cvar_VoteShow.IntValue == 1)
|
||||
{
|
||||
char voter[64], junk[64], choice[64];
|
||||
GetClientName(param1, voter, sizeof(voter));
|
||||
menu.GetItem(param2, junk, sizeof(junk), _, choice, sizeof(choice));
|
||||
PrintToChatAll("[SM] %T", "Vote Select", LANG_SERVER, voter, choice);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void VoteMenuClose()
|
||||
{
|
||||
delete g_hVoteMenu;
|
||||
g_hVoteMenu = null;
|
||||
}
|
||||
|
||||
float GetVotePercent(int votes, int totalVotes)
|
||||
{
|
||||
return FloatDiv(float(votes),float(totalVotes));
|
||||
}
|
||||
|
||||
bool TestVoteDelay(int client)
|
||||
{
|
||||
int delay = CheckVoteDelay();
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
if (delay > 60)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Action Timer_ChangeMap(Handle timer, DataPack dp)
|
||||
{
|
||||
char mapname[65];
|
||||
|
||||
dp.Reset();
|
||||
dp.ReadString(mapname, sizeof(mapname));
|
||||
|
||||
ForceChangeLevel(mapname, "sm_votemap Result");
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
551
scripting/temp/beskeleton.sp
Normal file
551
scripting/temp/beskeleton.sp
Normal file
@@ -0,0 +1,551 @@
|
||||
#include <sdkhooks>
|
||||
#include <tf2_stocks>
|
||||
#include <tf2items>
|
||||
|
||||
#pragma newdecls required;
|
||||
|
||||
#define MODEL_SKELETON "models/bots/skeleton_sniper_boss/skeleton_sniper_boss.mdl"
|
||||
#define PLUGIN_VERSION "1.2"
|
||||
|
||||
bool g_bSpecial[MAXPLAYERS + 1];
|
||||
bool g_bSkeleton[MAXPLAYERS + 1];
|
||||
TFTeam g_iOldTeam[MAXPLAYERS + 1];
|
||||
|
||||
Handle g_hCvarStompDamage;
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "[TF2] Be The Skeleton King!",
|
||||
author = "Pelipoika",
|
||||
description = "Spooky scary skeleton",
|
||||
version = PLUGIN_VERSION,
|
||||
url = ""
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
AddTempEntHook("TFBlood", TempHook);
|
||||
|
||||
RegAdminCmd("sm_beskeleton", Command_Skeleton, ADMFLAG_ROOT);
|
||||
|
||||
HookEvent("post_inventory_application", Event_SkeletonDeath);
|
||||
HookEvent("player_death", Event_SkeletonDeath, EventHookMode_Pre);
|
||||
|
||||
CreateConVar("tf2_beskeleton_version", PLUGIN_VERSION, "Be the Skeleton King version", FCVAR_NOTIFY|FCVAR_DONTRECORD|FCVAR_SPONLY);
|
||||
g_hCvarStompDamage = CreateConVar("tf2_beskeleton_stompdamage", "120", "Movement speed penalty when carrying a bomb", FCVAR_NOTIFY|FCVAR_DONTRECORD, true, 0.0, true, 1.0);
|
||||
|
||||
for (int client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
if(client > 0 && client <= MaxClients && IsClientInGame(client))
|
||||
{
|
||||
g_bSkeleton[client] = false;
|
||||
g_bSpecial[client] = false;
|
||||
g_iOldTeam[client] = TF2_GetClientTeam(client);
|
||||
|
||||
SDKHook(client, SDKHook_OnTakeDamageAlive, TakeDamage);
|
||||
}
|
||||
}
|
||||
|
||||
AddNormalSoundHook(SkeletonSH);
|
||||
}
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
||||
{
|
||||
CreateNative("BeSkeletonKing_MakeSkeleton", Native_SetSkeleton);
|
||||
CreateNative("BeSkeletonKing_IsSkeleton", Native_IsSkeleton);
|
||||
RegPluginLibrary("beskeleton");
|
||||
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
public Action TempHook(const char[] te_name, const Players[], int numClients, float delay)
|
||||
{
|
||||
int client = TE_ReadNum("entindex");
|
||||
if (client > 0 && client <= MaxClients && IsClientInGame(client) && g_bSkeleton[client])
|
||||
{
|
||||
float m_vecOrigin[3];
|
||||
m_vecOrigin[0] = TE_ReadFloat("m_vecOrigin[0]");
|
||||
m_vecOrigin[1] = TE_ReadFloat("m_vecOrigin[1]");
|
||||
m_vecOrigin[2] = TE_ReadFloat("m_vecOrigin[2]");
|
||||
|
||||
if(GetEntProp(client, Prop_Send, "m_iTeamNum") == 0)
|
||||
{
|
||||
CreateParticle("spell_skeleton_goop_green", m_vecOrigin);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(TF2_GetClientTeam(client))
|
||||
{
|
||||
case TFTeam_Red: CreateParticle("spell_pumpkin_mirv_goop_red", m_vecOrigin);
|
||||
case TFTeam_Blue: CreateParticle("spell_pumpkin_mirv_goop_blue", m_vecOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
PrecacheModel(MODEL_SKELETON);
|
||||
|
||||
PrecacheSound("misc/halloween/skeleton_break.wav");
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client)
|
||||
{
|
||||
g_bSkeleton[client] = false;
|
||||
g_bSpecial[client] = false;
|
||||
g_iOldTeam[client] = TFTeam_Spectator;
|
||||
|
||||
SDKHook(client, SDKHook_OnTakeDamageAlive, TakeDamage);
|
||||
}
|
||||
|
||||
public Action Command_Skeleton(int client, int args)
|
||||
{
|
||||
char arg1[32], arg2[6];
|
||||
GetCmdArg(1, arg1, sizeof(arg1));
|
||||
GetCmdArg(2, arg2, sizeof(arg2));
|
||||
char target_name[MAX_TARGET_LENGTH];
|
||||
int target_list[MAXPLAYERS];
|
||||
int target_count;
|
||||
bool tn_is_ml;
|
||||
if ((target_count = ProcessTargetString(
|
||||
arg1,
|
||||
client,
|
||||
target_list,
|
||||
MAXPLAYERS,
|
||||
0,
|
||||
target_name,
|
||||
sizeof(target_name),
|
||||
tn_is_ml)) <= 0)
|
||||
{
|
||||
ReplyToTargetError(client, target_count);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
for (int i = 0; i < target_count; i++)
|
||||
{
|
||||
int player = target_list[i];
|
||||
|
||||
if(player > 0 && player <= MaxClients && IsClientInGame(player) && IsPlayerAlive(player))
|
||||
{
|
||||
if(StringToInt(arg2) == 1)
|
||||
MakeSkeleton(player, true);
|
||||
else
|
||||
MakeSkeleton(player);
|
||||
}
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action GetMaxHealth(int client, int &MaxHealth)
|
||||
{
|
||||
if (client > 0 && client <= MaxClients && IsClientInGame(client))
|
||||
{
|
||||
MaxHealth = 1000;
|
||||
return Plugin_Changed;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action SetModel(int client, const char[] model)
|
||||
{
|
||||
SetVariantString(model);
|
||||
AcceptEntityInput(client, "SetCustomModel");
|
||||
SetEntProp(client, Prop_Send, "m_bUseClassAnimations", 1);
|
||||
}
|
||||
|
||||
stock void MakeSkeleton(int client, bool spectator = false)
|
||||
{
|
||||
if(spectator)
|
||||
{
|
||||
g_iOldTeam[client] = TF2_GetClientTeam(client);
|
||||
SetEntProp(client, Prop_Send, "m_bForcedSkin", 1);
|
||||
SetEntProp(client, Prop_Send, "m_nForcedSkin", 2);
|
||||
|
||||
SetEntProp(client, Prop_Send, "m_iTeamNum", 0);
|
||||
}
|
||||
|
||||
SetVariantString("2.0");
|
||||
AcceptEntityInput(client, "SetModelScale");
|
||||
|
||||
SetModel(client, MODEL_SKELETON);
|
||||
TF2_SetPlayerClass(client, TFClass_Sniper, _, false);
|
||||
TF2_RemoveAllWearables(client);
|
||||
TF2_RemoveAllWeapons(client);
|
||||
|
||||
Handle hWeaponFists = TF2Items_CreateItem(OVERRIDE_ALL);
|
||||
TF2Items_SetClassname(hWeaponFists, "tf_weapon_club");
|
||||
TF2Items_SetItemIndex(hWeaponFists, 3);
|
||||
TF2Items_SetQuality(hWeaponFists, 6);
|
||||
TF2Items_SetAttribute(hWeaponFists, 0, 15, 0.0);
|
||||
TF2Items_SetAttribute(hWeaponFists, 1, 5, 1.65);
|
||||
TF2Items_SetAttribute(hWeaponFists, 2, 402, 1.0);
|
||||
TF2Items_SetNumAttributes(hWeaponFists, 3);
|
||||
int iEntity = TF2Items_GiveNamedItem(client, hWeaponFists);
|
||||
EquipPlayerWeapon(client, iEntity);
|
||||
CloseHandle(hWeaponFists);
|
||||
|
||||
SetEntityRenderMode(iEntity, RENDER_TRANSCOLOR);
|
||||
SetEntityRenderColor(iEntity, 255, 255, 255, 0);
|
||||
SetEntProp(iEntity, Prop_Send, "m_fEffects", 16);
|
||||
|
||||
char anim[16];
|
||||
Format(anim, 32, "spawn0%i", GetRandomInt(1, 7));
|
||||
PlayAnimation(client, anim);
|
||||
|
||||
g_bSpecial[client] = true;
|
||||
|
||||
SetNextAttack(iEntity, 2.0);
|
||||
|
||||
SDKHook(client, SDKHook_GetMaxHealth, GetMaxHealth);
|
||||
|
||||
SetEntProp(client, Prop_Send, "m_iHealth", 1000);
|
||||
|
||||
g_bSkeleton[client] = true;
|
||||
}
|
||||
|
||||
stock void PlayAnimation(int client, char[] anim)
|
||||
{
|
||||
TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, view_as<float>({0.0, 0.0, 0.0}));
|
||||
SetEntityRenderMode(client, RENDER_TRANSCOLOR);
|
||||
SetEntityRenderColor(client, 255, 255, 255, 0);
|
||||
|
||||
SetEntProp(client, Prop_Send, "m_bUseClassAnimations", 0);
|
||||
SetEntityMoveType(client, MOVETYPE_NONE);
|
||||
|
||||
float vecOrigin[3], vecAngles[3];
|
||||
GetClientAbsOrigin(client, vecOrigin);
|
||||
GetClientAbsAngles(client, vecAngles);
|
||||
vecAngles[0] = 0.0;
|
||||
|
||||
int animationentity = CreateEntityByName("prop_dynamic_override");
|
||||
if(IsValidEntity(animationentity))
|
||||
{
|
||||
DispatchKeyValueVector(animationentity, "origin", vecOrigin);
|
||||
DispatchKeyValueVector(animationentity, "angles", vecAngles);
|
||||
DispatchKeyValue(animationentity, "model", MODEL_SKELETON);
|
||||
DispatchKeyValue(animationentity, "defaultanim", anim);
|
||||
DispatchSpawn(animationentity);
|
||||
SetEntPropEnt(animationentity, Prop_Send, "m_hOwnerEntity", client);
|
||||
|
||||
if(GetEntProp(client, Prop_Send, "m_iTeamNum") == 0)
|
||||
SetEntProp(animationentity, Prop_Send, "m_nSkin", GetEntProp(client, Prop_Send, "m_nForcedSkin"));
|
||||
else
|
||||
SetEntProp(animationentity, Prop_Send, "m_nSkin", GetClientTeam(client) - 2);
|
||||
|
||||
SetEntPropFloat(animationentity, Prop_Send, "m_flModelScale", 2.0);
|
||||
|
||||
SetVariantString("OnAnimationDone !self:KillHierarchy::0.0:1");
|
||||
AcceptEntityInput(animationentity, "AddOutput");
|
||||
|
||||
HookSingleEntityOutput(animationentity, "OnAnimationDone", OnAnimationDone, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAnimationDone(const char[] output, int caller, int activator, float delay)
|
||||
{
|
||||
if(IsValidEntity(caller))
|
||||
{
|
||||
int client = GetEntPropEnt(caller, Prop_Send, "m_hOwnerEntity");
|
||||
if(client > 0 && client <= MaxClients && IsClientInGame(client) && IsPlayerAlive(client))
|
||||
{
|
||||
SetEntityMoveType(client, MOVETYPE_WALK);
|
||||
SetEntProp(client, Prop_Send, "m_bUseClassAnimations", 1);
|
||||
SetEntityRenderMode(client, RENDER_TRANSCOLOR);
|
||||
SetEntityRenderColor(client, 255, 255, 255, 255);
|
||||
|
||||
g_bSpecial[client] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Action OnPlayerRunCmd(int client, int &iButtons, int &iImpulse, float fVel[3], float fAng[3], int &iWeapon)
|
||||
{
|
||||
if (IsPlayerAlive(client))
|
||||
{
|
||||
if(iButtons & IN_ATTACK2 && !g_bSpecial[client] && g_bSkeleton[client] && GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1)
|
||||
{
|
||||
SetNextAttack(GetPlayerWeaponSlot(client, TFWeaponSlot_Melee), 2.0);
|
||||
PlayAnimation(client, "MELEE_swing3");
|
||||
g_bSpecial[client] = true;
|
||||
|
||||
float vecAngles[3], vecOrigin[3];
|
||||
GetClientAbsAngles(client, vecAngles);
|
||||
GetClientAbsOrigin(client, vecOrigin);
|
||||
vecAngles[0] = 0.0;
|
||||
|
||||
Handle pack;
|
||||
CreateDataTimer(0.75, Timer_PerformStomp, pack, TIMER_FLAG_NO_MAPCHANGE);
|
||||
WritePackCell(pack, client);
|
||||
WritePackFloat(pack, vecOrigin[0]);
|
||||
WritePackFloat(pack, vecOrigin[1]);
|
||||
WritePackFloat(pack, vecOrigin[2]);
|
||||
|
||||
WritePackFloat(pack, vecAngles[0]);
|
||||
WritePackFloat(pack, vecAngles[1]);
|
||||
WritePackFloat(pack, vecAngles[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Timer_PerformStomp(Handle timer, Handle pack)
|
||||
{
|
||||
ResetPack(pack);
|
||||
int client = ReadPackCell(pack);
|
||||
float vecAngles[3], vecOrigin[3];
|
||||
vecOrigin[0] = ReadPackFloat(pack);
|
||||
vecOrigin[1] = ReadPackFloat(pack);
|
||||
vecOrigin[2] = ReadPackFloat(pack);
|
||||
|
||||
vecAngles[0] = ReadPackFloat(pack);
|
||||
vecAngles[1] = ReadPackFloat(pack);
|
||||
vecAngles[2] = ReadPackFloat(pack);
|
||||
|
||||
float vForward[3], vLeft[3];
|
||||
GetAngleVectors(vecAngles, vForward, NULL_VECTOR, NULL_VECTOR);
|
||||
GetAngleVectors(vecAngles, NULL_VECTOR, vLeft, NULL_VECTOR);
|
||||
vecOrigin[0] += (vForward[0] * 55);
|
||||
vecOrigin[1] += (vForward[1] * 55);
|
||||
vecOrigin[2] += (vForward[2] * 55);
|
||||
|
||||
vecOrigin[0] += (vLeft[0] * -35);
|
||||
vecOrigin[1] += (vLeft[1] * -35);
|
||||
vecOrigin[2] += (vLeft[2] * -35);
|
||||
|
||||
CreateParticle("bomibomicon_ring", vecOrigin); //The effect actually comes out of his leg VALVE
|
||||
|
||||
float pos2[3], Vec[3], AngBuff[3];
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(IsClientInGame(i) && IsPlayerAlive(i) && i != client && GetClientTeam(i) != GetClientTeam(client))
|
||||
{
|
||||
GetClientAbsOrigin(i, pos2);
|
||||
|
||||
if(GetVectorDistance(vecOrigin, pos2) <= 200.0)
|
||||
{
|
||||
MakeVectorFromPoints(vecOrigin, pos2, Vec);
|
||||
GetVectorAngles(Vec, AngBuff);
|
||||
AngBuff[0] -= 30.0;
|
||||
GetAngleVectors(AngBuff, Vec, NULL_VECTOR, NULL_VECTOR);
|
||||
NormalizeVector(Vec, Vec);
|
||||
ScaleVector(Vec, 500.0);
|
||||
Vec[2] += 250.0;
|
||||
SDKHooks_TakeDamage(i, client, client, GetConVarFloat(g_hCvarStompDamage));
|
||||
TeleportEntity(i, NULL_VECTOR, NULL_VECTOR, Vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Action TakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype)
|
||||
{
|
||||
if(victim > 0 && victim <= MaxClients && IsClientInGame(victim)
|
||||
&& attacker > 0 && attacker <= MaxClients && IsClientInGame(attacker)
|
||||
&& attacker != victim)
|
||||
{
|
||||
if(g_bSkeleton[attacker])
|
||||
{
|
||||
damage = GetRandomFloat(95.0, 120.0);
|
||||
return Plugin_Changed;
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Event_SkeletonDeath(Handle hEvent, char[] name, bool dontBroadcast)
|
||||
{
|
||||
int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
|
||||
int attacker = GetEventInt(hEvent, "inflictor_entindex");
|
||||
|
||||
if(g_bSkeleton[client])
|
||||
{
|
||||
EmitSoundToAll("misc/halloween/skeleton_break.wav", client);
|
||||
|
||||
g_bSkeleton[client] = false;
|
||||
g_bSpecial[client] = false;
|
||||
|
||||
SDKUnhook(client, SDKHook_GetMaxHealth, GetMaxHealth);
|
||||
|
||||
SetEntityMoveType(client, MOVETYPE_WALK);
|
||||
SetEntProp(client, Prop_Send, "m_bUseClassAnimations", 1);
|
||||
SetEntProp(client, Prop_Send, "m_bForcedSkin", 0);
|
||||
if(GetEntProp(client, Prop_Send, "m_iTeamNum") == 0)
|
||||
{
|
||||
SetEntProp(client, Prop_Send, "m_iTeamNum", g_iOldTeam[client]);
|
||||
g_iOldTeam[client] = TFTeam_Spectator;
|
||||
}
|
||||
SetEntityRenderMode(client, RENDER_TRANSCOLOR);
|
||||
SetEntityRenderColor(client, 255, 255, 255, 255);
|
||||
|
||||
SetVariantString("");
|
||||
AcceptEntityInput(client, "SetCustomModel");
|
||||
|
||||
SetVariantString("1.0");
|
||||
AcceptEntityInput(client, "SetModelScale");
|
||||
|
||||
float vecOrigin[3];
|
||||
GetClientAbsOrigin(client, vecOrigin);
|
||||
|
||||
//Drop a Rare spellbook
|
||||
int spell = CreateEntityByName("tf_spell_pickup");
|
||||
if(IsValidEntity(spell))
|
||||
{
|
||||
DispatchKeyValueVector(spell, "origin", vecOrigin);
|
||||
DispatchKeyValueVector(spell, "basevelocity", view_as<float>({0.0, 0.0, 0.0}));
|
||||
DispatchKeyValueVector(spell, "velocity", view_as<float>({0.0, 0.0, 0.0}));
|
||||
DispatchKeyValue(spell, "powerup_model", "models/props_halloween/hwn_spellbook_upright_major.mdl");
|
||||
DispatchKeyValue(spell, "OnPlayerTouch", "!self,Kill,,0,-1");
|
||||
|
||||
DispatchSpawn(spell);
|
||||
|
||||
SetVariantString("OnUser1 !self:kill::60:1");
|
||||
AcceptEntityInput(spell, "AddOutput");
|
||||
AcceptEntityInput(spell, "FireUser1");
|
||||
|
||||
SetEntPropEnt(spell, Prop_Send, "m_hOwnerEntity", client);
|
||||
SetEntProp(spell, Prop_Data, "m_nTier", 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(attacker > 0 && attacker <= MaxClients && IsClientInGame(attacker) && g_bSkeleton[attacker])
|
||||
{
|
||||
SetEventInt(hEvent, "attacker", 0);
|
||||
SetEventString(hEvent, "weapon", "spellbook_skeleton");
|
||||
SetEventInt(hEvent, "customkill", 66);
|
||||
SetEventString(hEvent, "weapon_logclassname", "spellbook_skeleton");
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action SkeletonSH(clients[64], int &numClients, char sample[PLATFORM_MAX_PATH], int &entity, int &channel, float &volume, int &level, int &pitch, int &flags, char soundEntry[PLATFORM_MAX_PATH], int &seed)
|
||||
{
|
||||
if (entity > 0 && entity <= MaxClients && IsClientInGame(entity))
|
||||
{
|
||||
if (!g_bSkeleton[entity]) return Plugin_Continue;
|
||||
|
||||
if (StrContains(sample, "vo/sniper", false) != -1)
|
||||
{
|
||||
Format(sample, sizeof(sample), "misc/halloween/skeletons/skelly_giant_0%i.wav", GetRandomInt(1, 3));
|
||||
PrecacheSound(sample);
|
||||
EmitSoundToAll(sample, entity, channel, level, flags, volume);
|
||||
|
||||
return Plugin_Changed;
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
stock void TF2_RemoveAllWearables(int client)
|
||||
{
|
||||
int wearable = -1;
|
||||
while ((wearable = FindEntityByClassname(wearable, "tf_wearable*")) != -1)
|
||||
{
|
||||
if (IsValidEntity(wearable))
|
||||
{
|
||||
int player = GetEntPropEnt(wearable, Prop_Send, "m_hOwnerEntity");
|
||||
if (client == player)
|
||||
{
|
||||
TF2_RemoveWearable(client, wearable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((wearable = FindEntityByClassname(wearable, "vgui_screen")) != -1)
|
||||
{
|
||||
if (IsValidEntity(wearable))
|
||||
{
|
||||
int player = GetEntPropEnt(wearable, Prop_Data, "m_hOwnerEntity");
|
||||
if (client == player)
|
||||
{
|
||||
AcceptEntityInput(wearable, "Kill");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((wearable = FindEntityByClassname(wearable, "tf_powerup_bottle")) != -1)
|
||||
{
|
||||
if (IsValidEntity(wearable))
|
||||
{
|
||||
int player = GetEntPropEnt(wearable, Prop_Send, "m_hOwnerEntity");
|
||||
if (client == player)
|
||||
{
|
||||
TF2_RemoveWearable(client, wearable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((wearable = FindEntityByClassname(wearable, "tf_weapon_spellbook")) != -1)
|
||||
{
|
||||
if (IsValidEntity(wearable))
|
||||
{
|
||||
int player = GetEntPropEnt(wearable, Prop_Send, "m_hOwnerEntity");
|
||||
if (client == player)
|
||||
{
|
||||
TF2_RemoveWearable(client, wearable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stock void SetNextAttack(int weapon, float duration = 0.0)
|
||||
{
|
||||
if (!IsValidEntity(weapon)) return;
|
||||
|
||||
float next = GetGameTime() + duration;
|
||||
|
||||
SetEntPropFloat(weapon, Prop_Send, "m_flNextPrimaryAttack", next);
|
||||
SetEntPropFloat(weapon, Prop_Send, "m_flNextSecondaryAttack", next);
|
||||
}
|
||||
|
||||
stock void CreateParticle(char[] particle, float pos[3])
|
||||
{
|
||||
int tblidx = FindStringTable("ParticleEffectNames");
|
||||
char tmp[256];
|
||||
int count = GetStringTableNumStrings(tblidx);
|
||||
int stridx = INVALID_STRING_INDEX;
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
ReadStringTable(tblidx, i, tmp, sizeof(tmp));
|
||||
if(StrEqual(tmp, particle, false))
|
||||
{
|
||||
stridx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 1; i <= GetMaxClients(); i++)
|
||||
{
|
||||
if(!IsValidEntity(i)) continue;
|
||||
if(!IsClientInGame(i)) continue;
|
||||
TE_Start("TFParticleEffect");
|
||||
TE_WriteFloat("m_vecOrigin[0]", pos[0]);
|
||||
TE_WriteFloat("m_vecOrigin[1]", pos[1]);
|
||||
TE_WriteFloat("m_vecOrigin[2]", pos[2]);
|
||||
TE_WriteNum("m_iParticleSystemIndex", stridx);
|
||||
TE_WriteNum("entindex", -1);
|
||||
TE_WriteNum("m_iAttachType", 5); //Dont associate with any entity
|
||||
TE_SendToClient(i, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
public int Native_SetSkeleton(Handle plugin, int args)
|
||||
{
|
||||
MakeSkeleton(GetNativeCell(1));
|
||||
}
|
||||
|
||||
public int Native_IsSkeleton(Handle plugin, int args)
|
||||
{
|
||||
return g_bSkeleton[GetNativeCell(1)];
|
||||
}
|
163
scripting/temp/clientprefs.sp
Normal file
163
scripting/temp/clientprefs.sp
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Map Management Plugin
|
||||
* Provides all map related functionality, including map changing, map voting,
|
||||
* and nextmap.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
|
||||
#pragma semicolon 1
|
||||
#include <sourcemod>
|
||||
#include <clientprefs>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Client Preferences",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Client peferences and settings menu",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("clientprefs.phrases");
|
||||
|
||||
RegConsoleCmd("sm_cookies", Command_Cookie, "sm_cookies <name> [value]");
|
||||
RegConsoleCmd("sm_settings", Command_Settings);
|
||||
}
|
||||
|
||||
public Action Command_Cookie(int client, int args)
|
||||
{
|
||||
if (args == 0)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_cookies <name> [value]");
|
||||
ReplyToCommand(client, "[SM] %t", "Printing Cookie List");
|
||||
|
||||
/* Show list of cookies */
|
||||
Handle iter = GetCookieIterator();
|
||||
|
||||
char name[30];
|
||||
name[0] = '\0';
|
||||
char description[255];
|
||||
description[0] = '\0';
|
||||
|
||||
PrintToConsole(client, "%t:", "Cookie List");
|
||||
|
||||
CookieAccess access;
|
||||
|
||||
while (ReadCookieIterator(iter,
|
||||
name,
|
||||
sizeof(name),
|
||||
access,
|
||||
description,
|
||||
sizeof(description)) != false)
|
||||
{
|
||||
if (access < CookieAccess_Private)
|
||||
{
|
||||
PrintToConsole(client, "%s - %s", name, description);
|
||||
}
|
||||
}
|
||||
|
||||
delete iter;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (client == 0)
|
||||
{
|
||||
PrintToServer("%T", "No Console", LANG_SERVER);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char name[30];
|
||||
name[0] = '\0';
|
||||
GetCmdArg(1, name, sizeof(name));
|
||||
|
||||
Handle cookie = FindClientCookie(name);
|
||||
|
||||
if (cookie == null)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cookie not Found", name);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
CookieAccess access = GetCookieAccess(cookie);
|
||||
|
||||
if (access == CookieAccess_Private)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Cookie not Found", name);
|
||||
delete cookie;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char value[100];
|
||||
value[0] = '\0';
|
||||
|
||||
if (args == 1)
|
||||
{
|
||||
GetClientCookie(client, cookie, value, sizeof(value));
|
||||
ReplyToCommand(client, "[SM] %t", "Cookie Value", name, value);
|
||||
|
||||
delete cookie;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (access == CookieAccess_Protected)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Protected Cookie", name);
|
||||
delete cookie;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/* Set the new value of the cookie */
|
||||
|
||||
GetCmdArg(2, value, sizeof(value));
|
||||
|
||||
SetClientCookie(client, cookie, value);
|
||||
delete cookie;
|
||||
ReplyToCommand(client, "[SM] %t", "Cookie Changed Value", name, value);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_Settings(int client, int args)
|
||||
{
|
||||
if (client == 0)
|
||||
{
|
||||
PrintToServer("%T", "No Console", LANG_SERVER);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
ShowCookieMenu(client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
133
scripting/temp/donatepage.sp
Normal file
133
scripting/temp/donatepage.sp
Normal file
@@ -0,0 +1,133 @@
|
||||
#pragma semicolon 1
|
||||
#include <sourcemod>
|
||||
|
||||
#define CHOICE1 "#choice1"
|
||||
#define CHOICE2 "#choice2"
|
||||
#define CHOICE3 "#choice3"
|
||||
|
||||
/**
|
||||
* Public plugin information.
|
||||
*/
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Nova.tf Server Functions",
|
||||
author = "Sir TonyBear",
|
||||
description = "Allows public to use mandatory server commands",
|
||||
version = "1.0.2",
|
||||
url = "http://nova.tf/"
|
||||
};
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("serverinfo.phrases");
|
||||
RegConsoleCmd("sm_forums", Command_ViewForums, "Load the forums page");
|
||||
RegConsoleCmd("sm_donate", Command_DonateMenu, "Open Donate Dialog");
|
||||
RegConsoleCmd("sm_group", Command_ViewGroup, "View our Steam Group");
|
||||
RegConsoleCmd("sm_info", Command_ServerInfo, "View servers information");
|
||||
}
|
||||
|
||||
public int MenuHandler1(Menu menu, MenuAction action, int client, int param2)
|
||||
{
|
||||
switch(action)
|
||||
{
|
||||
case MenuAction_Start:
|
||||
{
|
||||
}
|
||||
|
||||
case MenuAction_Display:
|
||||
{
|
||||
char buffer[255];
|
||||
Format(buffer, sizeof(buffer), "%T", "Server Info", client);
|
||||
|
||||
Panel panel = view_as<Panel>(param2);
|
||||
panel.SetTitle(buffer);
|
||||
PrintToServer("Client %d was sent menu with panel %x", param2);
|
||||
}
|
||||
|
||||
case MenuAction_Select:
|
||||
{
|
||||
char info[32];
|
||||
menu.GetItem(param2, info, sizeof(info));
|
||||
if (StrEqual(info, CHOICE1))
|
||||
{
|
||||
FakeClientCommand(client, "sm_forums");
|
||||
}
|
||||
if (StrEqual(info, CHOICE2))
|
||||
{
|
||||
FakeClientCommand(client, "sm_donate");
|
||||
}
|
||||
if (StrEqual(info, CHOICE3))
|
||||
{
|
||||
FakeClientCommand(client, "sm_group");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
PrintToServer("Something went wrong.", param2);
|
||||
}
|
||||
}
|
||||
case MenuAction_Cancel:
|
||||
{
|
||||
PrintToServer("Client %d's menu was cancelled for reason %d", param2);
|
||||
}
|
||||
|
||||
case MenuAction_End:
|
||||
{
|
||||
delete menu;
|
||||
}
|
||||
|
||||
case MenuAction_DrawItem:
|
||||
{
|
||||
int style;
|
||||
char info[32];
|
||||
menu.GetItem(param2, info, sizeof(info), style);
|
||||
|
||||
if (StrEqual(info, CHOICE1))
|
||||
{
|
||||
return style;
|
||||
}
|
||||
else
|
||||
{
|
||||
return style;
|
||||
}
|
||||
}
|
||||
case MenuAction_DisplayItem:
|
||||
{
|
||||
int style;
|
||||
char info[32];
|
||||
menu.GetItem(param2, info, sizeof(info), style);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Action Command_ServerInfo(int client, int args)
|
||||
{
|
||||
Menu menu = new Menu(MenuHandler1, MENU_ACTIONS_ALL);
|
||||
menu.SetTitle("%T", "Menu Title", LANG_SERVER);
|
||||
menu.AddItem(CHOICE1, "View Forums");
|
||||
menu.AddItem(CHOICE2, "Donate Items");
|
||||
menu.AddItem(CHOICE3, "View Steam Group");
|
||||
menu.ExitButton = true;
|
||||
menu.Display(client, 20);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_ViewForums(int client, int args)
|
||||
{
|
||||
ShowMOTDPanel(client, "Nova.tf - Forums", "http://nova.tf/", MOTDPANEL_TYPE_URL);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_DonateMenu(int client, int args)
|
||||
{
|
||||
ShowMOTDPanel(client, "Nova.tf - Donate", "http://nova.tf/app.php/donation", MOTDPANEL_TYPE_URL);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_ViewGroup(int client, int args)
|
||||
{
|
||||
ShowMOTDPanel(client, "Nova.tf - Steam Group", "https://steamcommunity.com/groups/Nova_TF", MOTDPANEL_TYPE_URL);
|
||||
}
|
||||
|
28
scripting/temp/features.sp
Normal file
28
scripting/temp/features.sp
Normal file
@@ -0,0 +1,28 @@
|
||||
//Simple script setup
|
||||
#pragma semicolon 1
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <regex>
|
||||
#define TSF_VERSION "1.0.0"
|
||||
|
||||
//Give plugin info
|
||||
public Plugin:myinfo =
|
||||
{
|
||||
name = "Trade Server Features",
|
||||
author = "Tonybear5",
|
||||
description = "Shows client !features motd panel",
|
||||
version = "TSF_VERSION",
|
||||
url = "http://veterangiveaways.co.uk"
|
||||
};
|
||||
|
||||
//Hook into server
|
||||
public OnAllPluginsLoaded()
|
||||
{
|
||||
RegConsoleCmd("sm_features", Command_Features);
|
||||
}
|
||||
|
||||
//Show the client the features
|
||||
public Action:Command_Features(client, args)
|
||||
{
|
||||
ShowMOTDPanel(client, "Trade Server Features", "http://veterangiveaways.co.uk/showthread.php?tid=8&pid=10#pid10", MOTDPANEL_TYPE_URL);
|
||||
}
|
299
scripting/temp/funcommands.sp
Normal file
299
scripting/temp/funcommands.sp
Normal file
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Basic Fun Commands Plugin
|
||||
* Implements basic punishment commands.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Fun Commands",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Fun Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
// Admin Menu
|
||||
TopMenu hTopMenu;
|
||||
|
||||
// Sounds
|
||||
char g_BlipSound[PLATFORM_MAX_PATH];
|
||||
char g_BeepSound[PLATFORM_MAX_PATH];
|
||||
char g_FinalSound[PLATFORM_MAX_PATH];
|
||||
char g_BoomSound[PLATFORM_MAX_PATH];
|
||||
char g_FreezeSound[PLATFORM_MAX_PATH];
|
||||
|
||||
// Following are model indexes for temp entities
|
||||
int g_BeamSprite = -1;
|
||||
int g_BeamSprite2 = -1;
|
||||
int g_HaloSprite = -1;
|
||||
int g_GlowSprite = -1;
|
||||
int g_ExplosionSprite = -1;
|
||||
|
||||
// Basic color arrays for temp entities
|
||||
int redColor[4] = {255, 75, 75, 255};
|
||||
int orangeColor[4] = {255, 128, 0, 255};
|
||||
int greenColor[4] = {75, 255, 75, 255};
|
||||
int blueColor[4] = {75, 75, 255, 255};
|
||||
int whiteColor[4] = {255, 255, 255, 255};
|
||||
int greyColor[4] = {128, 128, 128, 255};
|
||||
|
||||
// UserMessageId for Fade.
|
||||
UserMsg g_FadeUserMsgId;
|
||||
|
||||
// Serial Generator for Timer Safety
|
||||
int g_Serial_Gen = 0;
|
||||
|
||||
EngineVersion g_GameEngine = Engine_Unknown;
|
||||
|
||||
// Flags used in various timers
|
||||
#define DEFAULT_TIMER_FLAGS TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE
|
||||
|
||||
// Include various commands and supporting functions
|
||||
#include "funcommands/beacon.sp"
|
||||
#include "funcommands/timebomb.sp"
|
||||
#include "funcommands/fire.sp"
|
||||
#include "funcommands/ice.sp"
|
||||
#include "funcommands/gravity.sp"
|
||||
#include "funcommands/blind.sp"
|
||||
#include "funcommands/noclip.sp"
|
||||
#include "funcommands/drug.sp"
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
if (FindPluginByFile("basefuncommands.smx") != null)
|
||||
{
|
||||
ThrowError("This plugin replaces basefuncommands. You cannot run both at once.");
|
||||
}
|
||||
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("funcommands.phrases");
|
||||
g_GameEngine = GetEngineVersion();
|
||||
g_FadeUserMsgId = GetUserMessageId("Fade");
|
||||
|
||||
RegisterCvars();
|
||||
RegisterCmds();
|
||||
HookEvents();
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterCvars()
|
||||
{
|
||||
// beacon
|
||||
g_Cvar_BeaconRadius = CreateConVar("sm_beacon_radius", "375", "Sets the radius for beacon's light rings.", 0, true, 50.0, true, 1500.0);
|
||||
|
||||
// timebomb
|
||||
g_Cvar_TimeBombTicks = CreateConVar("sm_timebomb_ticks", "10.0", "Sets how long the timebomb fuse is.", 0, true, 5.0, true, 120.0);
|
||||
g_Cvar_TimeBombRadius = CreateConVar("sm_timebomb_radius", "600", "Sets the bomb blast radius.", 0, true, 50.0, true, 3000.0);
|
||||
g_Cvar_TimeBombMode = CreateConVar("sm_timebomb_mode", "0", "Who is killed by the timebomb? 0 = Target only, 1 = Target's team, 2 = Everyone", 0, true, 0.0, true, 2.0);
|
||||
|
||||
// fire
|
||||
g_Cvar_BurnDuration = CreateConVar("sm_burn_duration", "20.0", "Sets the default duration of sm_burn and firebomb victims.", 0, true, 0.5, true, 20.0);
|
||||
g_Cvar_FireBombTicks = CreateConVar("sm_firebomb_ticks", "10.0", "Sets how long the FireBomb fuse is.", 0, true, 5.0, true, 120.0);
|
||||
g_Cvar_FireBombRadius = CreateConVar("sm_firebomb_radius", "600", "Sets the bomb blast radius.", 0, true, 50.0, true, 3000.0);
|
||||
g_Cvar_FireBombMode = CreateConVar("sm_firebomb_mode", "0", "Who is targetted by the FireBomb? 0 = Target only, 1 = Target's team, 2 = Everyone", 0, true, 0.0, true, 2.0);
|
||||
|
||||
// ice
|
||||
g_Cvar_FreezeDuration = CreateConVar("sm_freeze_duration", "10.0", "Sets the default duration for sm_freeze and freezebomb victims", 0, true, 1.0, true, 120.0);
|
||||
g_Cvar_FreezeBombTicks = CreateConVar("sm_freezebomb_ticks", "10.0", "Sets how long the freezebomb fuse is.", 0, true, 5.0, true, 120.0);
|
||||
g_Cvar_FreezeBombRadius = CreateConVar("sm_freezebomb_radius", "600", "Sets the freezebomb blast radius.", 0, true, 50.0, true, 3000.0);
|
||||
g_Cvar_FreezeBombMode = CreateConVar("sm_freezebomb_mode", "0", "Who is targetted by the freezebomb? 0 = Target only, 1 = Target's team, 2 = Everyone", 0, true, 0.0, true, 2.0);
|
||||
|
||||
AutoExecConfig(true, "funcommands");
|
||||
}
|
||||
|
||||
void RegisterCmds()
|
||||
{
|
||||
RegAdminCmd("sm_beacon", Command_Beacon, ADMFLAG_SLAY, "sm_beacon <#userid|name> [0/1]");
|
||||
RegAdminCmd("sm_timebomb", Command_TimeBomb, ADMFLAG_SLAY, "sm_timebomb <#userid|name> [0/1]");
|
||||
RegAdminCmd("sm_burn", Command_Burn, ADMFLAG_SLAY, "sm_burn <#userid|name> [time]");
|
||||
RegAdminCmd("sm_firebomb", Command_FireBomb, ADMFLAG_SLAY, "sm_firebomb <#userid|name> [0/1]");
|
||||
RegAdminCmd("sm_freeze", Command_Freeze, ADMFLAG_SLAY, "sm_freeze <#userid|name> [time]");
|
||||
RegAdminCmd("sm_freezebomb", Command_FreezeBomb, ADMFLAG_SLAY, "sm_freezebomb <#userid|name> [0/1]");
|
||||
RegAdminCmd("sm_gravity", Command_Gravity, ADMFLAG_SLAY, "sm_gravity <#userid|name> [amount] - Leave amount off to reset. Amount is 0.0 through 5.0");
|
||||
RegAdminCmd("sm_blind", Command_Blind, ADMFLAG_SLAY, "sm_blind <#userid|name> [amount] - Leave amount off to reset.");
|
||||
RegAdminCmd("sm_noclip", Command_NoClip, ADMFLAG_SLAY|ADMFLAG_CHEATS, "sm_noclip <#userid|name>");
|
||||
RegAdminCmd("sm_drug", Command_Drug, ADMFLAG_SLAY, "sm_drug <#userid|name> [0/1]");
|
||||
}
|
||||
|
||||
void HookEvents()
|
||||
{
|
||||
char folder[64];
|
||||
GetGameFolderName(folder, sizeof(folder));
|
||||
|
||||
if (strcmp(folder, "tf") == 0)
|
||||
{
|
||||
HookEvent("teamplay_win_panel", Event_RoundEnd, EventHookMode_PostNoCopy);
|
||||
HookEvent("teamplay_restart_round", Event_RoundEnd, EventHookMode_PostNoCopy);
|
||||
HookEvent("arena_win_panel", Event_RoundEnd, EventHookMode_PostNoCopy);
|
||||
}
|
||||
else if (strcmp(folder, "nucleardawn") == 0)
|
||||
{
|
||||
HookEvent("round_win", Event_RoundEnd, EventHookMode_PostNoCopy);
|
||||
}
|
||||
else
|
||||
{
|
||||
HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
Handle gameConfig = LoadGameConfigFile("funcommands.games");
|
||||
if (gameConfig == null)
|
||||
{
|
||||
SetFailState("Unable to load game config funcommands.games");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SoundBlip", g_BlipSound, sizeof(g_BlipSound)) && g_BlipSound[0])
|
||||
{
|
||||
PrecacheSound(g_BlipSound, true);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SoundBeep", g_BeepSound, sizeof(g_BeepSound)) && g_BeepSound[0])
|
||||
{
|
||||
PrecacheSound(g_BeepSound, true);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SoundFinal", g_FinalSound, sizeof(g_FinalSound)) && g_FinalSound[0])
|
||||
{
|
||||
PrecacheSound(g_FinalSound, true);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SoundBoom", g_BoomSound, sizeof(g_BoomSound)) && g_BoomSound[0])
|
||||
{
|
||||
PrecacheSound(g_BoomSound, true);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SoundFreeze", g_FreezeSound, sizeof(g_FreezeSound)) && g_FreezeSound[0])
|
||||
{
|
||||
PrecacheSound(g_FreezeSound, true);
|
||||
}
|
||||
|
||||
char buffer[PLATFORM_MAX_PATH];
|
||||
if (GameConfGetKeyValue(gameConfig, "SpriteBeam", buffer, sizeof(buffer)) && buffer[0])
|
||||
{
|
||||
g_BeamSprite = PrecacheModel(buffer);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SpriteBeam2", buffer, sizeof(buffer)) && buffer[0])
|
||||
{
|
||||
g_BeamSprite2 = PrecacheModel(buffer);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SpriteExplosion", buffer, sizeof(buffer)) && buffer[0])
|
||||
{
|
||||
g_ExplosionSprite = PrecacheModel(buffer);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SpriteGlow", buffer, sizeof(buffer)) && buffer[0])
|
||||
{
|
||||
g_GlowSprite = PrecacheModel(buffer);
|
||||
}
|
||||
|
||||
if (GameConfGetKeyValue(gameConfig, "SpriteHalo", buffer, sizeof(buffer)) && buffer[0])
|
||||
{
|
||||
g_HaloSprite = PrecacheModel(buffer);
|
||||
}
|
||||
|
||||
delete gameConfig;
|
||||
}
|
||||
|
||||
public void OnMapEnd()
|
||||
{
|
||||
KillAllBeacons();
|
||||
KillAllTimeBombs();
|
||||
KillAllFireBombs();
|
||||
KillAllFreezes();
|
||||
KillAllDrugs();
|
||||
}
|
||||
|
||||
public Action Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
KillAllBeacons();
|
||||
KillAllTimeBombs();
|
||||
KillAllFireBombs();
|
||||
KillAllFreezes();
|
||||
KillAllDrugs();
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Find the "Player Commands" category */
|
||||
TopMenuObject player_commands = hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
|
||||
|
||||
if (player_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_beacon", AdminMenu_Beacon, player_commands, "sm_beacon", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_timebomb", AdminMenu_TimeBomb, player_commands, "sm_timebomb", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_burn", AdminMenu_Burn, player_commands, "sm_burn", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_firebomb", AdminMenu_FireBomb, player_commands, "sm_firebomb", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_freeze", AdminMenu_Freeze, player_commands, "sm_freeze", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_freezebomb", AdminMenu_FreezeBomb, player_commands, "sm_freezebomb", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_gravity", AdminMenu_Gravity, player_commands, "sm_gravity", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_blind", AdminMenu_Blind, player_commands, "sm_blind", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_noclip", AdminMenu_NoClip, player_commands, "sm_noclip", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_drug", AdminMenu_Drug, player_commands, "sm_drug", ADMFLAG_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void AddTranslatedMenuItem(Menu menu, const char[] opt, const char[] phrase, int client)
|
||||
{
|
||||
char buffer[128];
|
||||
Format(buffer, sizeof(buffer), "%T", phrase, client);
|
||||
menu.AddItem(opt, buffer);
|
||||
}
|
326
scripting/temp/funvotes.sp
Normal file
326
scripting/temp/funvotes.sp
Normal file
@@ -0,0 +1,326 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Fun Votes Plugin
|
||||
* Implements extra fun vote commands.
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Fun Votes",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Fun Vote Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
#define VOTE_NO "###no###"
|
||||
#define VOTE_YES "###yes###"
|
||||
|
||||
Menu g_hVoteMenu = null;
|
||||
|
||||
ConVar g_Cvar_Limits[5] = {null, ...};
|
||||
ConVar g_Cvar_Gravity;
|
||||
ConVar g_Cvar_Alltalk;
|
||||
ConVar g_Cvar_FF;
|
||||
|
||||
// ConVar g_Cvar_Show = null;
|
||||
|
||||
enum voteType
|
||||
{
|
||||
gravity = 0,
|
||||
burn,
|
||||
slay,
|
||||
alltalk,
|
||||
ff
|
||||
};
|
||||
|
||||
voteType g_voteType = gravity;
|
||||
|
||||
// Menu API does not provide us with a way to pass multiple peices of data with a single
|
||||
// choice, so some globals are used to hold stuff.
|
||||
//
|
||||
#define VOTE_CLIENTID 0
|
||||
#define VOTE_USERID 1
|
||||
int g_voteClient[2]; /* Holds the target's client id and user id */
|
||||
|
||||
#define VOTE_NAME 0
|
||||
#define VOTE_AUTHID 1
|
||||
#define VOTE_IP 2
|
||||
char g_voteInfo[3][65]; /* Holds the target's name, authid, and IP */
|
||||
|
||||
TopMenu hTopMenu;
|
||||
|
||||
#include "funvotes/votegravity.sp"
|
||||
#include "funvotes/voteburn.sp"
|
||||
#include "funvotes/voteslay.sp"
|
||||
#include "funvotes/votealltalk.sp"
|
||||
#include "funvotes/voteff.sp"
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
if (FindPluginByFile("basefunvotes.smx") != null)
|
||||
{
|
||||
ThrowError("This plugin replaces basefuncommands. You cannot run both at once.");
|
||||
}
|
||||
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("basevotes.phrases");
|
||||
LoadTranslations("funvotes.phrases");
|
||||
LoadTranslations("funcommands.phrases");
|
||||
|
||||
RegAdminCmd("sm_votegravity", Command_VoteGravity, ADMFLAG_VOTE, "sm_votegravity <amount> [amount2] ... [amount5]");
|
||||
RegAdminCmd("sm_voteburn", Command_VoteBurn, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteburn <player>");
|
||||
RegAdminCmd("sm_voteslay", Command_VoteSlay, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteslay <player>");
|
||||
RegAdminCmd("sm_votealltalk", Command_VoteAlltalk, ADMFLAG_VOTE, "sm_votealltalk");
|
||||
RegAdminCmd("sm_voteff", Command_VoteFF, ADMFLAG_VOTE, "sm_voteff");
|
||||
|
||||
g_Cvar_Limits[0] = CreateConVar("sm_vote_gravity", "0.60", "percent required for successful gravity vote.", 0, true, 0.05, true, 1.0);
|
||||
g_Cvar_Limits[1] = CreateConVar("sm_vote_burn", "0.60", "percent required for successful burn vote.", 0, true, 0.05, true, 1.0);
|
||||
g_Cvar_Limits[2] = CreateConVar("sm_vote_slay", "0.60", "percent required for successful slay vote.", 0, true, 0.05, true, 1.0);
|
||||
g_Cvar_Limits[3] = CreateConVar("sm_vote_alltalk", "0.60", "percent required for successful alltalk vote.", 0, true, 0.05, true, 1.0);
|
||||
g_Cvar_Limits[4] = CreateConVar("sm_vote_ff", "0.60", "percent required for successful friendly fire vote.", 0, true, 0.05, true, 1.0);
|
||||
|
||||
g_Cvar_Gravity = FindConVar("sv_gravity");
|
||||
g_Cvar_Alltalk = FindConVar("sv_alltalk");
|
||||
g_Cvar_FF = FindConVar("mp_friendlyfire");
|
||||
|
||||
/*
|
||||
g_Cvar_Show = FindConVar("sm_vote_show");
|
||||
if (g_Cvar_Show == null)
|
||||
{
|
||||
g_Cvar_Show = CreateConVar("sm_vote_show", "1", "Show player's votes? Default on.", 0, true, 0.0, true, 1.0);
|
||||
}
|
||||
*/
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Build the "Voting Commands" category */
|
||||
TopMenuObject voting_commands = hTopMenu.FindCategory(ADMINMENU_VOTINGCOMMANDS);
|
||||
|
||||
if (voting_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_votegravity", AdminMenu_VoteGravity, voting_commands, "sm_votegravity", ADMFLAG_VOTE);
|
||||
hTopMenu.AddItem("sm_voteburn", AdminMenu_VoteBurn, voting_commands, "sm_voteburn", ADMFLAG_VOTE|ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_voteslay", AdminMenu_VoteSlay, voting_commands, "sm_voteslay", ADMFLAG_VOTE|ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_votealltalk", AdminMenu_VoteAllTalk, voting_commands, "sm_votealltalk", ADMFLAG_VOTE);
|
||||
hTopMenu.AddItem("sm_voteff", AdminMenu_VoteFF, voting_commands, "sm_voteff", ADMFLAG_VOTE);
|
||||
}
|
||||
}
|
||||
|
||||
public int Handler_VoteCallback(Menu menu, MenuAction action, int param1, int param2)
|
||||
{
|
||||
if (action == MenuAction_End)
|
||||
{
|
||||
VoteMenuClose();
|
||||
}
|
||||
else if (action == MenuAction_Display)
|
||||
{
|
||||
char title[64];
|
||||
menu.GetTitle(title, sizeof(title));
|
||||
|
||||
char buffer[255];
|
||||
Format(buffer, sizeof(buffer), "%T", title, param1, g_voteInfo[VOTE_NAME]);
|
||||
|
||||
Panel panel = view_as<Panel>(param2);
|
||||
panel.SetTitle(buffer);
|
||||
}
|
||||
else if (action == MenuAction_DisplayItem)
|
||||
{
|
||||
char display[64];
|
||||
menu.GetItem(param2, "", 0, _, display, sizeof(display));
|
||||
|
||||
if (strcmp(display, VOTE_NO) == 0 || strcmp(display, VOTE_YES) == 0)
|
||||
{
|
||||
char buffer[255];
|
||||
Format(buffer, sizeof(buffer), "%T", display, param1);
|
||||
|
||||
return RedrawMenuItem(buffer);
|
||||
}
|
||||
}
|
||||
/* else if (action == MenuAction_Select)
|
||||
{
|
||||
VoteSelect(menu, param1, param2);
|
||||
}*/
|
||||
else if (action == MenuAction_VoteCancel && param1 == VoteCancel_NoVotes)
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "No Votes Cast");
|
||||
}
|
||||
else if (action == MenuAction_VoteEnd)
|
||||
{
|
||||
char item[64];
|
||||
float percent, limit;
|
||||
int votes, totalVotes;
|
||||
|
||||
GetMenuVoteInfo(param2, votes, totalVotes);
|
||||
menu.GetItem(param1, item, sizeof(item));
|
||||
|
||||
if (strcmp(item, VOTE_NO) == 0 && param1 == 1)
|
||||
{
|
||||
votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
|
||||
}
|
||||
|
||||
percent = GetVotePercent(votes, totalVotes);
|
||||
|
||||
limit = g_Cvar_Limits[g_voteType].FloatValue;
|
||||
|
||||
/* :TODO: g_voteClient[userid] needs to be checked.
|
||||
*/
|
||||
|
||||
// A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
|
||||
if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1))
|
||||
{
|
||||
/* :TODO: g_voteClient[userid] should be used here and set to -1 if not applicable.
|
||||
*/
|
||||
LogAction(-1, -1, "Vote failed.");
|
||||
PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Vote Successful", RoundToNearest(100.0*percent), totalVotes);
|
||||
|
||||
switch (g_voteType)
|
||||
{
|
||||
case (gravity):
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Cvar changed", "sv_gravity", item);
|
||||
LogAction(-1, -1, "Changing gravity to %s due to vote.", item);
|
||||
g_Cvar_Gravity.IntValue = StringToInt(item);
|
||||
}
|
||||
|
||||
case (burn):
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Set target on fire", "_s", g_voteInfo[VOTE_NAME]);
|
||||
LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote burn successful, igniting \"%L\"", g_voteClient[VOTE_CLIENTID]);
|
||||
|
||||
IgniteEntity(g_voteClient[VOTE_CLIENTID], 19.8);
|
||||
}
|
||||
|
||||
case (slay):
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Slayed player", g_voteInfo[VOTE_NAME]);
|
||||
LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote slay successful, slaying \"%L\"", g_voteClient[VOTE_CLIENTID]);
|
||||
|
||||
ExtinguishEntity(g_voteClient[VOTE_CLIENTID]);
|
||||
ForcePlayerSuicide(g_voteClient[VOTE_CLIENTID]);
|
||||
}
|
||||
|
||||
case (alltalk):
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Cvar changed", "sv_alltalk", (g_Cvar_Alltalk.BoolValue ? "0" : "1"));
|
||||
LogAction(-1, -1, "Changing alltalk to %s due to vote.", (g_Cvar_Alltalk.BoolValue ? "0" : "1"));
|
||||
g_Cvar_Alltalk.BoolValue = !g_Cvar_Alltalk.BoolValue;
|
||||
}
|
||||
|
||||
case (ff):
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Cvar changed", "mp_friendlyfire", (g_Cvar_FF.BoolValue ? "0" : "1"));
|
||||
LogAction(-1, -1, "Changing friendly fire to %s due to vote.", (g_Cvar_FF.BoolValue ? "0" : "1"));
|
||||
g_Cvar_FF.BoolValue = !g_Cvar_FF.BoolValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void VoteSelect(Menu menu, int param1, int param2 = 0)
|
||||
{
|
||||
if (g_Cvar_VoteShow.IntValue == 1)
|
||||
{
|
||||
char voter[MAX_NAME_LENGTH], junk[64], choice[64];
|
||||
GetClientName(param1, voter, sizeof(voter));
|
||||
menu.GetItem(param2, junk, sizeof(junk), _, choice, sizeof(choice));
|
||||
PrintToChatAll("[SM] %T", "Vote Select", LANG_SERVER, voter, choice);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void VoteMenuClose()
|
||||
{
|
||||
delete g_hVoteMenu;
|
||||
g_hVoteMenu = null;
|
||||
}
|
||||
|
||||
float GetVotePercent(int votes, int totalVotes)
|
||||
{
|
||||
return FloatDiv(float(votes),float(totalVotes));
|
||||
}
|
||||
|
||||
bool TestVoteDelay(int client)
|
||||
{
|
||||
int delay = CheckVoteDelay();
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
if (delay > 60)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
398
scripting/temp/fusrodah.sp
Normal file
398
scripting/temp/fusrodah.sp
Normal file
@@ -0,0 +1,398 @@
|
||||
// base grab code taken from http://forums.alliedmods.net/showthread.php?t=157075 and https://forums.alliedmods.net/showthread.php?p=1946774
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <sdkhooks>
|
||||
#include <morecolors>
|
||||
|
||||
#define DRAGONBORN "shout/dragonborn.wav" // grab
|
||||
#define FUSRODAH "shout/fusrodah.wav" // throw
|
||||
|
||||
#define THROW_FORCE 10000.0
|
||||
#define GRAB_DISTANCE 250.0
|
||||
|
||||
#define PLUGIN_NAME "Dovah Shout!"
|
||||
#define PLUGIN_AUTHOR "DovahkiinYT / TheXeon"
|
||||
#define PLUGIN_VERSION "2.0.2"
|
||||
#define PLUGIN_DESCRIP "Allows Dovah to Grab Stuff"
|
||||
#define PLUGIN_CONTACT "http://steamcommunity.com/groups/FireHostv2"
|
||||
|
||||
public Plugin myinfo = {
|
||||
name = PLUGIN_NAME,
|
||||
author = PLUGIN_AUTHOR,
|
||||
description = PLUGIN_DESCRIP,
|
||||
version = PLUGIN_VERSION,
|
||||
url = PLUGIN_CONTACT
|
||||
}
|
||||
|
||||
int g_grabbed[MAXPLAYERS+10]; // track client's grabbed object
|
||||
float gDistance[MAXPLAYERS+10]; // track distance of grabbed object
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
///////////// Setup /////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
CreateConVar("tf_dovahgrab_version", PLUGIN_VERSION, PLUGIN_NAME, FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_SPONLY);
|
||||
|
||||
PrecacheSound(FUSRODAH, true);
|
||||
PrecacheSound(DRAGONBORN, true);
|
||||
|
||||
AddFileToDownloadsTable("sound/shout/fusrodah.wav");
|
||||
AddFileToDownloadsTable("sound/shout/dragonborn.wav");
|
||||
|
||||
RegConsoleCmd("sm_SetTarget", Command_Dragonborn, "Attempt to be the Dragonborn");
|
||||
RegConsoleCmd("sm_FusRoDah", Command_FusRoDah, "The Dragonborn's Words");
|
||||
RegConsoleCmd("sm_Disarm", Command_Disarm, "Disarm the pursuing");
|
||||
|
||||
HookEvent("player_death", OnPlayerSpawn);
|
||||
HookEvent("player_spawn", OnPlayerSpawn);
|
||||
HookEvent("player_team", OnPlayerSpawn);
|
||||
//Some code was here, but it was marked as unnecessary and removed.
|
||||
}
|
||||
|
||||
|
||||
stock bool:IsTargetInSightRange(client, target, Float:angle=90.0, Float:distance=0.0, bool:heightcheck=true, bool:negativeangle=false)
|
||||
{
|
||||
if(angle > 360.0 || angle < 0.0)
|
||||
ThrowError("Angle Max : 360 & Min : 0. %d isn't proper angle.", angle);
|
||||
if(!IsValidClient(client))
|
||||
ThrowError("Client is not Alive.");
|
||||
if(!IsValidClient(target))
|
||||
ThrowError("Target is not Alive.");
|
||||
|
||||
decl Float:clientpos[3], Float:targetpos[3], Float:anglevector[3], Float:targetvector[3], Float:resultangle, Float:resultdistance;
|
||||
|
||||
GetClientEyeAngles(client, anglevector);
|
||||
anglevector[0] = anglevector[2] = 0.0;
|
||||
GetAngleVectors(anglevector, anglevector, NULL_VECTOR, NULL_VECTOR);
|
||||
NormalizeVector(anglevector, anglevector);
|
||||
if(negativeangle)
|
||||
NegateVector(anglevector);
|
||||
|
||||
GetClientAbsOrigin(client, clientpos);
|
||||
GetClientAbsOrigin(target, targetpos);
|
||||
if(heightcheck && distance > 0)
|
||||
resultdistance = GetVectorDistance(clientpos, targetpos);
|
||||
clientpos[2] = targetpos[2] = 0.0;
|
||||
MakeVectorFromPoints(clientpos, targetpos, targetvector);
|
||||
NormalizeVector(targetvector, targetvector);
|
||||
|
||||
resultangle = RadToDeg(ArcCosine(GetVectorDotProduct(targetvector, anglevector)));
|
||||
|
||||
if(resultangle <= angle/2)
|
||||
{
|
||||
if(distance > 0)
|
||||
{
|
||||
if(!heightcheck)
|
||||
resultdistance = GetVectorDistance(clientpos, targetpos);
|
||||
if(distance >= resultdistance)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public void OnMapStart()
|
||||
{
|
||||
for (int client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
g_grabbed[client] = INVALID_ENT_REFERENCE;
|
||||
PrecacheSound(FUSRODAH, true);
|
||||
PrecacheSound(DRAGONBORN, true);
|
||||
AddFileToDownloadsTable("sound/shout/fusrodah.wav");
|
||||
AddFileToDownloadsTable("sound/shout/dragonborn.wav");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client)
|
||||
{
|
||||
g_grabbed[client] = INVALID_ENT_REFERENCE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
///////////// Commands /////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Action Command_Dragonborn(int client, int target)
|
||||
{
|
||||
char player_authid[32];
|
||||
GetClientAuthId(client, AuthId_Steam2, player_authid, sizeof(player_authid));
|
||||
if IsTargetInSightRange(client, target) *then
|
||||
{
|
||||
SDKHook(target, SDKHook_PreThink, OnPreThink);
|
||||
GrabObject(target);
|
||||
int grabbed = EntRefToEntIndex(g_grabbed[client]);
|
||||
if(grabbed != INVALID_ENT_REFERENCE)
|
||||
{
|
||||
CPrintToChat(client, "{orange}Arngeir: {green}You now have an entity in your sights! Now, type !FusRoDah to use the power of the Voice.");
|
||||
EmitSoundToClient(client, DRAGONBORN);
|
||||
EmitSoundToClient(client, DRAGONBORN);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
else
|
||||
{
|
||||
CPrintToChat(client, "{orange}Arngeir: {red}My dear Dragonborn, you have done something wrong! Were you not aimed at a valid target?");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CPrintToChat(client, "{orange}Arngeir: {red}You don't understand the power of the Voice.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Action Command_FusRoDah(int client, int args)
|
||||
{
|
||||
if (!IsValidClient(client))
|
||||
{
|
||||
return Plugin_Handled;
|
||||
}
|
||||
char player_authid[32];
|
||||
GetClientAuthId(client, AuthId_Steam2, player_authid, sizeof(player_authid));
|
||||
if (!StrEqual(player_authid, "STEAM_0:1:69132908", false))
|
||||
{
|
||||
CPrintToChat(client, "{orange}Arngeir: {red}Only the true Dragonborn can speak these words!");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
if(IsValidClient(client))
|
||||
{
|
||||
int grabbed = EntRefToEntIndex(g_grabbed[client]);
|
||||
if(grabbed != INVALID_ENT_REFERENCE)
|
||||
{
|
||||
ThrowObject(client, grabbed, true);
|
||||
EmitSoundToAll(FUSRODAH);
|
||||
CPrintToChatAll("{fullred}Dovahkiin: {aqua}FUS RO DAH!!!!");
|
||||
}
|
||||
else
|
||||
{
|
||||
CPrintToChat(client, "{orange}Arngeir: {red}I'm sorry Dragonborn, but you must first prepare this shout. Aim at something, and then try !SetTarget.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
public Action Command_Disarm(int client, int args)
|
||||
{
|
||||
if (!IsValidClient(client))
|
||||
{
|
||||
return Plugin_Handled;
|
||||
}
|
||||
char player_authid[32];
|
||||
GetClientAuthId(client, AuthId_Steam2, player_authid, sizeof(player_authid));
|
||||
if (!StrEqual(player_authid, "STEAM_0:1:69132908", false))
|
||||
{
|
||||
CPrintToChat(client, "{orange}Arngeir: {red}I'm sorry, but only the true Dragonborn may release an entity.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
if(IsValidClient(client))
|
||||
{
|
||||
int grabbed = EntRefToEntIndex(g_grabbed[client]);
|
||||
if(grabbed != INVALID_ENT_REFERENCE)
|
||||
{
|
||||
ThrowObject(client, grabbed, false);
|
||||
CPrintToChat(client, "{orange}Arngeir: {green}You have stopped pursuing your target! Use !SetTarget to choose a new target.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
void GrabObject(int client)
|
||||
{
|
||||
int grabbed = TraceToObject(client); // -1 for no collision, 0 for world
|
||||
|
||||
if (grabbed > 0)
|
||||
{
|
||||
if(grabbed > MaxClients)
|
||||
{
|
||||
char classname[13];
|
||||
GetEntityClassname(grabbed, classname, 13);
|
||||
|
||||
if(StrEqual(classname, "prop_physics"))
|
||||
{
|
||||
int grabber = GetEntPropEnt(grabbed, Prop_Data, "m_hPhysicsAttacker");
|
||||
if(grabber > 0 && grabber <= MaxClients && IsClientInGame(grabber))
|
||||
{
|
||||
return; // another client is grabbing this object
|
||||
}
|
||||
SetEntPropEnt(grabbed, Prop_Data, "m_hPhysicsAttacker", client);
|
||||
AcceptEntityInput(grabbed, "EnableMotion");
|
||||
}
|
||||
|
||||
SetEntityMoveType(grabbed, MOVETYPE_VPHYSICS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
SetEntityMoveType(grabbed, MOVETYPE_WALK);
|
||||
|
||||
PrintHintText(client,"Compelling %N",grabbed);
|
||||
PrintHintText(grabbed,"%N is about to FUS RO DAH you!",client);
|
||||
}
|
||||
|
||||
if(GetClientButtons(client) & IN_ATTACK2) // Store and maintain distance
|
||||
{
|
||||
float VecPos_grabbed[3], VecPos_client[3];
|
||||
GetEntPropVector(grabbed, Prop_Send, "m_vecOrigin", VecPos_grabbed);
|
||||
GetClientEyePosition(client, VecPos_client);
|
||||
gDistance[client] = GetVectorDistance(VecPos_grabbed, VecPos_client);
|
||||
}
|
||||
else
|
||||
{
|
||||
gDistance[client] = GRAB_DISTANCE; // Use prefab distance
|
||||
}
|
||||
|
||||
float fVelocity[3] = { 0.0, 0.0, 0.0 };
|
||||
|
||||
TeleportEntity(grabbed, NULL_VECTOR, NULL_VECTOR, fVelocity);
|
||||
|
||||
g_grabbed[client] = EntIndexToEntRef(grabbed);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ThrowObject(int client, int grabbed, bool fusrodah)
|
||||
{
|
||||
if(fusrodah)
|
||||
{
|
||||
float vecView[3], vecFwd[3], vecPos[3], vecVel[3];
|
||||
|
||||
GetClientEyeAngles(client, vecView);
|
||||
GetAngleVectors(vecView, vecFwd, NULL_VECTOR, NULL_VECTOR);
|
||||
GetClientEyePosition(client, vecPos);
|
||||
|
||||
vecPos[0]+=vecFwd[0]*THROW_FORCE;
|
||||
vecPos[1]+=vecFwd[1]*THROW_FORCE;
|
||||
vecPos[2]+=vecFwd[2]*THROW_FORCE;
|
||||
|
||||
GetEntPropVector(grabbed, Prop_Send, "m_vecOrigin", vecFwd);
|
||||
|
||||
SubtractVectors(vecPos, vecFwd, vecVel);
|
||||
ScaleVector(vecVel, 10.0);
|
||||
|
||||
TeleportEntity(grabbed, NULL_VECTOR, NULL_VECTOR, vecVel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
g_grabbed[client] = INVALID_ENT_REFERENCE;
|
||||
|
||||
if(grabbed > MaxClients)
|
||||
{
|
||||
char classname[13];
|
||||
GetEntityClassname(grabbed, classname, 13);
|
||||
if(StrEqual(classname, "prop_physics"))
|
||||
{
|
||||
SetEntPropEnt(grabbed, Prop_Data, "m_hPhysicsAttacker", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
///////////// Prethink /////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void OnPreThink(int client)
|
||||
{
|
||||
int grabbed = EntRefToEntIndex(g_grabbed[client]);
|
||||
if (grabbed != INVALID_ENT_REFERENCE)
|
||||
{
|
||||
float vecView[3], vecFwd[3], vecPos[3], vecVel[3];
|
||||
|
||||
GetClientEyeAngles(client, vecView);
|
||||
GetAngleVectors(vecView, vecFwd, NULL_VECTOR, NULL_VECTOR);
|
||||
GetClientEyePosition(client, vecPos);
|
||||
|
||||
vecPos[0]+=vecFwd[0]*gDistance[client];
|
||||
vecPos[1]+=vecFwd[1]*gDistance[client];
|
||||
vecPos[2]+=vecFwd[2]*gDistance[client];
|
||||
|
||||
GetEntPropVector(grabbed, Prop_Send, "m_vecOrigin", vecFwd);
|
||||
|
||||
SubtractVectors(vecPos, vecFwd, vecVel);
|
||||
ScaleVector(vecVel, 10.0);
|
||||
|
||||
TeleportEntity(grabbed, NULL_VECTOR, NULL_VECTOR, vecVel);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
///////////// Events /////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void OnPlayerSpawn(Handle event, const char[] name, bool dontBroadcast)
|
||||
{
|
||||
int client = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||
if(IsValidClient(client))
|
||||
{
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(EntRefToEntIndex(g_grabbed[i]) == client)
|
||||
{
|
||||
g_grabbed[i] = INVALID_ENT_REFERENCE; // Clear grabs on them
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
///////////// Trace /////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
public int TraceToObject(int client)
|
||||
{
|
||||
float vecClientEyePos[3], vecClientEyeAng[3];
|
||||
GetClientEyePosition(client, vecClientEyePos);
|
||||
GetClientEyeAngles(client, vecClientEyeAng);
|
||||
|
||||
TR_TraceRayFilter(vecClientEyePos, vecClientEyeAng, MASK_PLAYERSOLID, RayType_Infinite, TraceRayGrab, client);
|
||||
|
||||
return TR_GetEntityIndex(INVALID_HANDLE);
|
||||
}
|
||||
|
||||
public bool TraceRayGrab(int entityhit, int mask, any self)
|
||||
{
|
||||
if(entityhit > 0 && entityhit <= MaxClients)
|
||||
{
|
||||
if(IsPlayerAlive(entityhit) && entityhit != self)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char classname[13];
|
||||
if(GetEntityClassname(entityhit, classname, 13) && (StrEqual(classname, "prop_physics") || StrEqual(classname, "tf_ammo_pack") || StrContains(classname, "tf_projectile") || StrContains(classname, "prop_") || StrContains(classname, "func_tracktrain") || StrEqual(classname, "prop_physics_override")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsValidClient (int target)
|
||||
{
|
||||
if(target > 4096) target = EntRefToEntIndex(target);
|
||||
if(target < 1 || target > MaxClients) return false;
|
||||
if(!IsClientInGame(target)) return false;
|
||||
if(IsFakeClient(target)) return false;
|
||||
if(GetEntProp(target, Prop_Send, "m_bIsCoaching")) return false;
|
||||
return true;
|
||||
}
|
615
scripting/temp/goomba.sp
Normal file
615
scripting/temp/goomba.sp
Normal file
@@ -0,0 +1,615 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <sdkhooks>
|
||||
#include <clientprefs>
|
||||
|
||||
#define PL_NAME "Goomba Stomp Core"
|
||||
#define PL_DESC "Goomba Stomp core plugin"
|
||||
#define PL_VERSION "2.0.2"
|
||||
|
||||
#define STOMP_SOUND "goomba/stomp.wav"
|
||||
#define REBOUND_SOUND "goomba/rebound.wav"
|
||||
|
||||
#define GOOMBA_IMMUNFLAG_NONE 0
|
||||
#define GOOMBA_IMMUNFLAG_ATTACKER (1 << 0)
|
||||
#define GOOMBA_IMMUNFLAG_VICTIM (1 << 1)
|
||||
|
||||
public Plugin:myinfo =
|
||||
{
|
||||
name = PL_NAME,
|
||||
author = "Flyflo",
|
||||
description = PL_DESC,
|
||||
version = PL_VERSION,
|
||||
url = "http://www.geek-gaming.fr"
|
||||
}
|
||||
|
||||
new Handle:g_hForwardOnStomp;
|
||||
new Handle:g_hForwardOnStompPost;
|
||||
|
||||
new Handle:g_Cvar_JumpPower = INVALID_HANDLE;
|
||||
new Handle:g_Cvar_PluginEnabled = INVALID_HANDLE;
|
||||
new Handle:g_Cvar_ParticlesEnabled = INVALID_HANDLE;
|
||||
new Handle:g_Cvar_SoundsEnabled = INVALID_HANDLE;
|
||||
new Handle:g_Cvar_ImmunityEnabled = INVALID_HANDLE;
|
||||
new Handle:g_Cvar_StompMinSpeed = INVALID_HANDLE;
|
||||
|
||||
new Handle:g_Cvar_DamageLifeMultiplier = INVALID_HANDLE;
|
||||
new Handle:g_Cvar_DamageAdd = INVALID_HANDLE;
|
||||
|
||||
// Snippet from psychonic (http://forums.alliedmods.net/showpost.php?p=1294224&postcount=2)
|
||||
new Handle:sv_tags;
|
||||
|
||||
new Handle:g_Cookie_ClientPref;
|
||||
|
||||
new Goomba_Fakekill[MAXPLAYERS+1];
|
||||
|
||||
// Thx to Pawn 3-pg (https://forums.alliedmods.net/showthread.php?p=1140480#post1140480)
|
||||
new bool:g_TeleportAtFrameEnd[MAXPLAYERS+1] = false;
|
||||
new Float:g_TeleportAtFrameEnd_Vel[MAXPLAYERS+1][3];
|
||||
|
||||
public APLRes:AskPluginLoad2(Handle:hMySelf, bool:bLate, String:strError[], iMaxErrors)
|
||||
{
|
||||
RegPluginLibrary("goomba");
|
||||
|
||||
CreateNative("GoombaStomp", GoombaStomp);
|
||||
CreateNative("CheckStompImmunity", CheckStompImmunity);
|
||||
CreateNative("PlayStompSound", PlayStompSound);
|
||||
CreateNative("PlayStompReboundSound", PlayStompReboundSound);
|
||||
CreateNative("EmitStompParticles", EmitStompParticles);
|
||||
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
public OnPluginStart()
|
||||
{
|
||||
LoadTranslations("goomba.phrases");
|
||||
|
||||
g_Cvar_PluginEnabled = CreateConVar("goomba_enabled", "1.0", "Plugin On/Off", 0, true, 0.0, true, 1.0);
|
||||
|
||||
g_Cvar_SoundsEnabled = CreateConVar("goomba_sounds", "1", "Enable or disable sounds of the plugin", 0, true, 0.0, true, 1.0);
|
||||
g_Cvar_ParticlesEnabled = CreateConVar("goomba_particles", "1", "Enable or disable particles of the plugin", 0, true, 0.0, true, 1.0);
|
||||
g_Cvar_ImmunityEnabled = CreateConVar("goomba_immunity", "1", "Enable or disable the immunity system", 0, true, 0.0, true, 1.0);
|
||||
g_Cvar_JumpPower = CreateConVar("goomba_rebound_power", "300.0", "Goomba jump power", 0, true, 0.0);
|
||||
g_Cvar_StompMinSpeed = CreateConVar("goomba_minspeed", "360.0", "Minimum falling speed to kill", 0, true, 0.0, false, 0.0);
|
||||
// To remove the warning about this variable not being used
|
||||
GetConVarFloat(g_Cvar_StompMinSpeed);
|
||||
|
||||
g_Cvar_DamageLifeMultiplier = CreateConVar("goomba_dmg_lifemultiplier", "1.0", "How much damage the victim will receive based on its actual life", 0, true, 0.0, false, 0.0);
|
||||
g_Cvar_DamageAdd = CreateConVar("goomba_dmg_add", "50.0", "Add this amount of damage after goomba_dmg_lifemultiplier calculation", 0, true, 0.0, false, 0.0);
|
||||
|
||||
AutoExecConfig(true, "goomba");
|
||||
|
||||
CreateConVar("goomba_version", PL_VERSION, PL_NAME, FCVAR_PLUGIN | FCVAR_SPONLY | FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_DONTRECORD);
|
||||
|
||||
g_Cookie_ClientPref = RegClientCookie("goomba_client_pref", "", CookieAccess_Private);
|
||||
RegConsoleCmd("goomba_toggle", Cmd_GoombaToggle, "Toggle the goomba immunity client's pref.");
|
||||
RegConsoleCmd("goomba_status", Cmd_GoombaStatus, "Give the current goomba immunity setting.");
|
||||
RegConsoleCmd("goomba_on", Cmd_GoombaOn, "Enable stomp.");
|
||||
RegConsoleCmd("goomba_off", Cmd_GoombaOff, "Disable stomp.");
|
||||
|
||||
HookEvent("player_death", Event_PlayerDeath, EventHookMode_Pre);
|
||||
HookEvent("player_spawn", Event_PlayerSpawn);
|
||||
|
||||
decl String:modName[32];
|
||||
GetGameFolderName(modName, sizeof(modName));
|
||||
|
||||
HookEventEx("post_inventory_application", Event_LockerTouch);
|
||||
|
||||
g_hForwardOnStomp = CreateGlobalForward("OnStomp", ET_Event, Param_Cell, Param_Cell, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef);
|
||||
g_hForwardOnStompPost = CreateGlobalForward("OnStompPost", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Float);
|
||||
|
||||
// sv_tags stuff
|
||||
sv_tags = FindConVar("sv_tags");
|
||||
MyAddServerTag("stomp");
|
||||
HookConVarChange(g_Cvar_PluginEnabled, OnPluginChangeState);
|
||||
|
||||
// Support for plugin late loading
|
||||
for (new client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
if(IsClientInGame(client))
|
||||
{
|
||||
OnClientPutInServer(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OnPluginEnd()
|
||||
{
|
||||
MyRemoveServerTag("stomp");
|
||||
}
|
||||
|
||||
public OnMapStart()
|
||||
{
|
||||
PrecacheSound(STOMP_SOUND, true);
|
||||
PrecacheSound(REBOUND_SOUND, true);
|
||||
|
||||
decl String:stompSoundServerPath[128];
|
||||
decl String:reboundSoundServerPath[128];
|
||||
Format(stompSoundServerPath, sizeof(stompSoundServerPath), "sound/%s", STOMP_SOUND);
|
||||
Format(reboundSoundServerPath, sizeof(reboundSoundServerPath), "sound/%s", REBOUND_SOUND);
|
||||
|
||||
AddFileToDownloadsTable(stompSoundServerPath);
|
||||
AddFileToDownloadsTable(reboundSoundServerPath);
|
||||
}
|
||||
|
||||
public OnPluginChangeState(Handle:cvar, const String:oldVal[], const String:newVal[])
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_PluginEnabled))
|
||||
{
|
||||
MyAddServerTag("stomp");
|
||||
}
|
||||
else
|
||||
{
|
||||
MyRemoveServerTag("stomp");
|
||||
}
|
||||
}
|
||||
|
||||
public OnClientPutInServer(client)
|
||||
{
|
||||
SDKHook(client, SDKHook_PreThinkPost, OnPreThinkPost);
|
||||
}
|
||||
|
||||
public CheckStompImmunity(Handle:hPlugin, numParams)
|
||||
{
|
||||
if(numParams != 2)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
new client = GetNativeCell(1);
|
||||
new victim = GetNativeCell(2);
|
||||
|
||||
new result = GOOMBA_IMMUNFLAG_NONE;
|
||||
|
||||
if(GetConVarBool(g_Cvar_ImmunityEnabled))
|
||||
{
|
||||
decl String:strCookieClient[16];
|
||||
GetImmunityCookie(client, g_Cookie_ClientPref, strCookieClient, sizeof(strCookieClient));
|
||||
|
||||
decl String:strCookieVictim[16];
|
||||
GetImmunityCookie(victim, g_Cookie_ClientPref, strCookieVictim, sizeof(strCookieVictim));
|
||||
|
||||
if(StrEqual(strCookieClient, "on") || StrEqual(strCookieClient, "next_off"))
|
||||
{
|
||||
result |= GOOMBA_IMMUNFLAG_ATTACKER;
|
||||
}
|
||||
if(StrEqual(strCookieVictim, "on") || StrEqual(strCookieVictim, "next_off"))
|
||||
{
|
||||
result |= GOOMBA_IMMUNFLAG_VICTIM;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
|
||||
{
|
||||
new victim = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||
|
||||
if(Goomba_Fakekill[victim] == 1)
|
||||
{
|
||||
SetEventBool(event, "goomba", true);
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action:OnPreStomp(attacker, victim, &Float:damageMultiplier, &Float:damageBonus, &Float:reboundPower)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public GoombaStomp(Handle:hPlugin, numParams)
|
||||
{
|
||||
// If the plugin is disabled stop here
|
||||
if(!GetConVarBool(g_Cvar_PluginEnabled))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(numParams < 2 || numParams > 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the parameters
|
||||
new client = GetNativeCell(1);
|
||||
new victim = GetNativeCell(2);
|
||||
|
||||
new Float:damageMultiplier = GetConVarFloat(g_Cvar_DamageLifeMultiplier);
|
||||
new Float:damageBonus = GetConVarFloat(g_Cvar_DamageAdd);
|
||||
new Float:jumpPower = GetConVarFloat(g_Cvar_JumpPower);
|
||||
|
||||
switch(numParams)
|
||||
{
|
||||
case 3:
|
||||
damageMultiplier = GetNativeCellRef(3);
|
||||
case 4:
|
||||
damageBonus = GetNativeCellRef(4);
|
||||
case 5:
|
||||
jumpPower = GetNativeCellRef(5);
|
||||
}
|
||||
|
||||
new Float:modifiedDamageMultiplier = damageMultiplier;
|
||||
new Float:modifiedDamageBonus = damageBonus;
|
||||
new Float:modifiedJumpPower = jumpPower;
|
||||
|
||||
// Launch forward
|
||||
decl Action:stompForwardResult;
|
||||
|
||||
Call_StartForward(g_hForwardOnStomp);
|
||||
Call_PushCell(client);
|
||||
Call_PushCell(victim);
|
||||
Call_PushFloatRef(modifiedDamageMultiplier);
|
||||
Call_PushFloatRef(modifiedDamageBonus);
|
||||
Call_PushFloatRef(modifiedJumpPower);
|
||||
Call_Finish(stompForwardResult);
|
||||
|
||||
if(stompForwardResult == Plugin_Changed)
|
||||
{
|
||||
damageMultiplier = modifiedDamageMultiplier;
|
||||
damageBonus = modifiedDamageBonus;
|
||||
jumpPower = modifiedJumpPower;
|
||||
}
|
||||
else if(stompForwardResult == Plugin_Handled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(jumpPower > 0.0)
|
||||
{
|
||||
decl Float:vecAng[3], Float:vecVel[3];
|
||||
GetClientEyeAngles(client, vecAng);
|
||||
GetEntPropVector(client, Prop_Data, "m_vecVelocity", vecVel);
|
||||
vecAng[0] = DegToRad(vecAng[0]);
|
||||
vecAng[1] = DegToRad(vecAng[1]);
|
||||
vecVel[0] = jumpPower * Cosine(vecAng[0]) * Cosine(vecAng[1]);
|
||||
vecVel[1] = jumpPower * Cosine(vecAng[0]) * Sine(vecAng[1]);
|
||||
vecVel[2] = jumpPower + 100.0;
|
||||
|
||||
g_TeleportAtFrameEnd[client] = true;
|
||||
g_TeleportAtFrameEnd_Vel[client] = vecVel;
|
||||
}
|
||||
|
||||
new victim_health = GetClientHealth(victim);
|
||||
Goomba_Fakekill[victim] = 1;
|
||||
SDKHooks_TakeDamage(victim,
|
||||
client,
|
||||
client,
|
||||
victim_health * damageMultiplier + damageBonus,
|
||||
DMG_PREVENT_PHYSICS_FORCE | DMG_CRUSH | DMG_ALWAYSGIB);
|
||||
|
||||
Goomba_Fakekill[victim] = 0;
|
||||
|
||||
// Launch forward
|
||||
Call_StartForward(g_hForwardOnStompPost);
|
||||
Call_PushCell(client);
|
||||
Call_PushCell(victim);
|
||||
Call_PushFloat(damageMultiplier);
|
||||
Call_PushFloat(damageBonus);
|
||||
Call_PushFloat(jumpPower);
|
||||
Call_Finish();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PlayStompReboundSound(Handle:hPlugin, numParams)
|
||||
{
|
||||
if(numParams != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
new client = GetNativeCell(1);
|
||||
|
||||
if (IsClientInGame(client))
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_SoundsEnabled))
|
||||
{
|
||||
EmitSoundToAll(REBOUND_SOUND, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PlayStompSound(Handle:hPlugin, numParams)
|
||||
{
|
||||
if(numParams != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
new client = GetNativeCell(1);
|
||||
|
||||
if (IsClientInGame(client))
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_SoundsEnabled))
|
||||
{
|
||||
EmitSoundToClient(client, STOMP_SOUND, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EmitStompParticles(Handle:hPlugin, numParams)
|
||||
{
|
||||
if(numParams != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
new client = GetNativeCell(1);
|
||||
|
||||
if(GetConVarBool(g_Cvar_ParticlesEnabled))
|
||||
{
|
||||
new particle = AttachParticle(client, "mini_fireworks");
|
||||
if(particle != -1)
|
||||
{
|
||||
CreateTimer(5.0, Timer_DeleteParticle, EntIndexToEntRef(particle), TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OnPreThinkPost(client)
|
||||
{
|
||||
if (IsClientInGame(client) && IsPlayerAlive(client))
|
||||
{
|
||||
if(g_TeleportAtFrameEnd[client])
|
||||
{
|
||||
TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, g_TeleportAtFrameEnd_Vel[client]);
|
||||
|
||||
if(GetConVarBool(g_Cvar_SoundsEnabled))
|
||||
{
|
||||
EmitSoundToAll(REBOUND_SOUND, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_TeleportAtFrameEnd[client] = false;
|
||||
}
|
||||
|
||||
stock GetImmunityCookie(client, Handle:cookie, String:strCookie[], maxlen)
|
||||
{
|
||||
if(!AreClientCookiesCached(client))
|
||||
{
|
||||
strcopy(strCookie, maxlen, "off");
|
||||
}
|
||||
else
|
||||
{
|
||||
GetClientCookie(client, g_Cookie_ClientPref, strCookie, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
|
||||
{
|
||||
new client = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||
|
||||
// Delay the update so class specific cfg are applied.
|
||||
CreateTimer(0.1, Timer_UpdateImmunity, client);
|
||||
}
|
||||
|
||||
public Action:Event_LockerTouch(Handle:event, const String:name[], bool:dontBroadcast)
|
||||
{
|
||||
new client = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||
|
||||
// Delay the update so class specific cfg are applied (maybe not usefull for this event).
|
||||
CreateTimer(0.1, Timer_UpdateImmunity, client);
|
||||
}
|
||||
|
||||
public Action:Timer_UpdateImmunity(Handle:timer, any:client)
|
||||
{
|
||||
decl String:strCookie[16];
|
||||
GetImmunityCookie(client, g_Cookie_ClientPref, strCookie, sizeof(strCookie));
|
||||
|
||||
//-----------------------------------------------------
|
||||
// on = Immunity enabled
|
||||
// off = Immunity disabled
|
||||
// next_on = Immunity enabled on respawn
|
||||
// next_off = Immunity disabled on respawn
|
||||
//-----------------------------------------------------
|
||||
|
||||
if(StrEqual(strCookie, ""))
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "off");
|
||||
}
|
||||
else if(StrEqual(strCookie, "next_off"))
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "off");
|
||||
}
|
||||
else if(StrEqual(strCookie, "next_on"))
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "on");
|
||||
}
|
||||
}
|
||||
|
||||
public Action:Cmd_GoombaToggle(client, args)
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_ImmunityEnabled))
|
||||
{
|
||||
decl String:strCookie[16];
|
||||
GetImmunityCookie(client, g_Cookie_ClientPref, strCookie, sizeof(strCookie));
|
||||
|
||||
if(StrEqual(strCookie, "off") || StrEqual(strCookie, "next_off"))
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "next_on");
|
||||
ReplyToCommand(client, "%t", "Immun On");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "next_off");
|
||||
ReplyToCommand(client, "%t", "Immun Off");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Immun Disabled");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Cmd_GoombaOn(client, args)
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_ImmunityEnabled))
|
||||
{
|
||||
decl String:strCookie[16];
|
||||
GetImmunityCookie(client, g_Cookie_ClientPref, strCookie, sizeof(strCookie));
|
||||
|
||||
if(!StrEqual(strCookie, "off"))
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "next_off");
|
||||
ReplyToCommand(client, "%t", "Immun Off");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Immun Disabled");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Cmd_GoombaOff(client, args)
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_ImmunityEnabled))
|
||||
{
|
||||
decl String:strCookie[16];
|
||||
GetImmunityCookie(client, g_Cookie_ClientPref, strCookie, sizeof(strCookie));
|
||||
|
||||
if(!StrEqual(strCookie, "on"))
|
||||
{
|
||||
SetClientCookie(client, g_Cookie_ClientPref, "next_on");
|
||||
ReplyToCommand(client, "%t", "Immun On");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Immun Disabled");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Cmd_GoombaStatus(client, args)
|
||||
{
|
||||
if(GetConVarBool(g_Cvar_ImmunityEnabled))
|
||||
{
|
||||
decl String:strCookie[16];
|
||||
GetImmunityCookie(client, g_Cookie_ClientPref, strCookie, sizeof(strCookie));
|
||||
|
||||
if(StrEqual(strCookie, "on"))
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Status Off");
|
||||
}
|
||||
if(StrEqual(strCookie, "off"))
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Status On");
|
||||
}
|
||||
if(StrEqual(strCookie, "next_off"))
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Status Next On");
|
||||
}
|
||||
if(StrEqual(strCookie, "next_on"))
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Status Next Off");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Immun Disabled");
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Timer_DeleteParticle(Handle:timer, any:ref)
|
||||
{
|
||||
new particle = EntRefToEntIndex(ref);
|
||||
DeleteParticle(particle);
|
||||
}
|
||||
|
||||
stock AttachParticle(entity, String:particleType[])
|
||||
{
|
||||
new particle = CreateEntityByName("info_particle_system");
|
||||
decl String:tName[128];
|
||||
|
||||
if(IsValidEdict(particle))
|
||||
{
|
||||
decl Float:pos[3] ;
|
||||
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", pos);
|
||||
pos[2] += 74;
|
||||
TeleportEntity(particle, pos, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
Format(tName, sizeof(tName), "target%i", entity);
|
||||
|
||||
DispatchKeyValue(entity, "targetname", tName);
|
||||
DispatchKeyValue(particle, "targetname", "tf2particle");
|
||||
DispatchKeyValue(particle, "parentname", tName);
|
||||
DispatchKeyValue(particle, "effect_name", particleType);
|
||||
DispatchSpawn(particle);
|
||||
|
||||
SetVariantString(tName);
|
||||
SetVariantString("flag");
|
||||
ActivateEntity(particle);
|
||||
AcceptEntityInput(particle, "start");
|
||||
|
||||
return particle;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
stock DeleteParticle(any:particle)
|
||||
{
|
||||
if (particle > MaxClients && IsValidEntity(particle))
|
||||
{
|
||||
decl String:classname[256];
|
||||
GetEdictClassname(particle, classname, sizeof(classname));
|
||||
|
||||
if (StrEqual(classname, "info_particle_system", false))
|
||||
{
|
||||
AcceptEntityInput(particle, "Kill");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stock MyAddServerTag(const String:tag[])
|
||||
{
|
||||
decl String:currtags[128];
|
||||
if (sv_tags == INVALID_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetConVarString(sv_tags, currtags, sizeof(currtags));
|
||||
if (StrContains(currtags, tag) > -1)
|
||||
{
|
||||
// already have tag
|
||||
return;
|
||||
}
|
||||
|
||||
decl String:newtags[128];
|
||||
Format(newtags, sizeof(newtags), "%s%s%s", currtags, (currtags[0]!=0)?",":"", tag);
|
||||
new flags = GetConVarFlags(sv_tags);
|
||||
SetConVarFlags(sv_tags, flags & ~FCVAR_NOTIFY);
|
||||
SetConVarString(sv_tags, newtags);
|
||||
SetConVarFlags(sv_tags, flags);
|
||||
}
|
||||
|
||||
stock MyRemoveServerTag(const String:tag[])
|
||||
{
|
||||
decl String:newtags[128];
|
||||
if (sv_tags == INVALID_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetConVarString(sv_tags, newtags, sizeof(newtags));
|
||||
if (StrContains(newtags, tag) == -1)
|
||||
{
|
||||
// tag isn't on here, just bug out
|
||||
return;
|
||||
}
|
||||
|
||||
ReplaceString(newtags, sizeof(newtags), tag, "");
|
||||
ReplaceString(newtags, sizeof(newtags), ",,", "");
|
||||
new flags = GetConVarFlags(sv_tags);
|
||||
SetConVarFlags(sv_tags, flags & ~FCVAR_NOTIFY);
|
||||
SetConVarString(sv_tags, newtags);
|
||||
SetConVarFlags(sv_tags, flags);
|
||||
}
|
1225
scripting/temp/mapchooser.sp
Normal file
1225
scripting/temp/mapchooser.sp
Normal file
File diff suppressed because it is too large
Load Diff
108
scripting/temp/mckayupdater.sp
Normal file
108
scripting/temp/mckayupdater.sp
Normal file
@@ -0,0 +1,108 @@
|
||||
/****************************************
|
||||
* mckayupdater.sp
|
||||
*
|
||||
* This file is used in Dr. McKay's plugins for Updater integration
|
||||
* For more info on Dr. McKay's plugins, see http://www.doctormckay.com
|
||||
* For more info on Updater, see https://forums.alliedmods.net/showthread.php?t=169095
|
||||
* You may copy and use this file, but please be sure to change the URL to your own!
|
||||
*
|
||||
* This file does the following tasks:
|
||||
* - Adds the plugin to Updater's updating pool (using UPDATER_BASE_URL/UPDATE_FILE (UPDATE_FILE should be defined prior to including this file))
|
||||
* - Creates a cvar CONVAR_PREFIX_auto_update to control whether Updater is enabled (CONVAR_PREFIX should be defined prior to including this file)
|
||||
* - Creates a version cvar CONVAR_PREFIX_version (CONVAR_PREFIX should be defined prior to including this file)
|
||||
* - Dynamically adds "A" to the version cvar based on whether Updater is installed and working
|
||||
*
|
||||
* If you need to put code into OnAllPluginsLoaded, define ALL_PLUGINS_LOADED_FUNC with a function (doesn't need to be public) to be called inside of OnAllPluginsLoaded
|
||||
* For example, #define ALL_PLUGINS_LOADED_FUNC AllPluginsLoaded
|
||||
* AllPluginsLoaded() { ... }
|
||||
*
|
||||
* If you need to put code into OnLibraryAdded, define LIBRARY_ADDED_FUNC with a function (doesn't need to be public) to be called inside of OnLibraryAdded
|
||||
* For example, #define LIBRARY_ADDED_FUNC LibraryAdded
|
||||
* LibraryAdded(const String:name[]) { ... }
|
||||
*
|
||||
* If you need to put code into OnLibraryRemoved, define LIBRARY_REMOVED_FUNC with a function (doesn't need to be public) to be called inside of OnLibraryRemoved
|
||||
* For example, #define LIBRARY_REMOVED_FUNC LibraryRemoved
|
||||
* LibraryRemoved(const String:name[]) { ... }
|
||||
*
|
||||
* Define RELOAD_ON_UPDATE and the plugin will reload itself upon being updated
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _mckay_updater_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _mckay_updater_included
|
||||
|
||||
#if defined REQUIRE_PLUGIN
|
||||
#undef REQUIRE_PLUGIN
|
||||
#endif
|
||||
#include <updater>
|
||||
#define REQUIRE_PLUGIN
|
||||
|
||||
#define UPDATER_BASE_URL "http://hg.doctormckay.com/public-plugins/raw/default"
|
||||
|
||||
new Handle:cvarEnableUpdater;
|
||||
new Handle:cvarVersion;
|
||||
|
||||
public OnAllPluginsLoaded() {
|
||||
decl String:cvarName[64];
|
||||
Format(cvarName, sizeof(cvarName), "%s_auto_update", CONVAR_PREFIX);
|
||||
cvarEnableUpdater = CreateConVar(cvarName, "1", "Enables automatic updating (has no effect if Updater is not installed)");
|
||||
|
||||
Format(cvarName, sizeof(cvarName), "%s_version", CONVAR_PREFIX);
|
||||
cvarVersion = CreateConVar(cvarName, PLUGIN_VERSION, "Plugin Version", FCVAR_DONTRECORD|FCVAR_CHEAT|FCVAR_NOTIFY);
|
||||
|
||||
HookConVarChange(cvarEnableUpdater, CheckUpdaterStatus);
|
||||
HookConVarChange(cvarVersion, CheckUpdaterStatus);
|
||||
CheckUpdaterStatus(INVALID_HANDLE, "", "");
|
||||
|
||||
#if defined ALL_PLUGINS_LOADED_FUNC
|
||||
ALL_PLUGINS_LOADED_FUNC();
|
||||
#endif
|
||||
}
|
||||
|
||||
public OnLibraryAdded(const String:name[]) {
|
||||
CheckUpdaterStatus(INVALID_HANDLE, "", "");
|
||||
|
||||
#if defined LIBRARY_ADDED_FUNC
|
||||
LIBRARY_ADDED_FUNC(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
public OnLibraryRemoved(const String:name[]) {
|
||||
CheckUpdaterStatus(INVALID_HANDLE, "", "");
|
||||
|
||||
#if defined LIBRARY_REMOVED_FUNC
|
||||
LIBRARY_REMOVED_FUNC(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
public CheckUpdaterStatus(Handle:convar, const String:name[], const String:value[]) {
|
||||
if(cvarVersion == INVALID_HANDLE) {
|
||||
return; // Version cvar not created yet
|
||||
}
|
||||
|
||||
if(LibraryExists("updater") && GetConVarBool(cvarEnableUpdater)) {
|
||||
decl String:url[512], String:version[12];
|
||||
Format(url, sizeof(url), "%s/%s", UPDATER_BASE_URL, UPDATE_FILE);
|
||||
Updater_AddPlugin(url); // Has no effect if we're already in Updater's pool
|
||||
|
||||
Format(version, sizeof(version), "%sA", PLUGIN_VERSION);
|
||||
SetConVarString(cvarVersion, version);
|
||||
} else {
|
||||
SetConVarString(cvarVersion, PLUGIN_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
public Action:Updater_OnPluginChecking() {
|
||||
if(!GetConVarBool(cvarEnableUpdater)) {
|
||||
return Plugin_Handled;
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
#if defined RELOAD_ON_UPDATE
|
||||
public Updater_OnPluginUpdated() {
|
||||
ReloadPlugin();
|
||||
}
|
||||
#endif
|
230
scripting/temp/nextmap.sp
Normal file
230
scripting/temp/nextmap.sp
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Nextmap Plugin
|
||||
* Adds sm_nextmap cvar for changing map and nextmap chat trigger.
|
||||
*
|
||||
* SourceMod (C)2004-2014 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sourcemod>
|
||||
#include "include/nextmap.inc"
|
||||
|
||||
#pragma semicolon 1
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Nextmap",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Provides nextmap and sm_nextmap",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
int g_MapPos = -1;
|
||||
ArrayList g_MapList = null;
|
||||
int g_MapListSerial = -1;
|
||||
|
||||
int g_CurrentMapStartTime;
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
||||
{
|
||||
char game[128];
|
||||
GetGameFolderName(game, sizeof(game));
|
||||
|
||||
if (StrEqual(game, "left4dead", false)
|
||||
|| StrEqual(game, "dystopia", false)
|
||||
|| StrEqual(game, "synergy", false)
|
||||
|| StrEqual(game, "left4dead2", false)
|
||||
|| StrEqual(game, "garrysmod", false)
|
||||
|| StrEqual(game, "swarm", false)
|
||||
|| StrEqual(game, "bms", false)
|
||||
|| GetEngineVersion() == Engine_Insurgency)
|
||||
{
|
||||
strcopy(error, err_max, "Nextmap is incompatible with this game");
|
||||
return APLRes_SilentFailure;
|
||||
}
|
||||
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("nextmap.phrases");
|
||||
|
||||
int size = ByteCountToCells(PLATFORM_MAX_PATH);
|
||||
g_MapList = new ArrayList(size);
|
||||
|
||||
RegAdminCmd("sm_maphistory", Command_MapHistory, ADMFLAG_CHANGEMAP, "Shows the most recent maps played");
|
||||
RegConsoleCmd("listmaps", Command_List);
|
||||
|
||||
// Set to the current map so OnMapStart() will know what to do
|
||||
char currentMap[PLATFORM_MAX_PATH];
|
||||
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||
SetNextMap(currentMap);
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
g_CurrentMapStartTime = GetTime();
|
||||
}
|
||||
|
||||
public void OnConfigsExecuted()
|
||||
{
|
||||
char lastMap[PLATFORM_MAX_PATH], currentMap[PLATFORM_MAX_PATH];
|
||||
GetNextMap(lastMap, sizeof(lastMap));
|
||||
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||
|
||||
// Why am I doing this? If we switched to a new map, but it wasn't what we expected (Due to sm_map, sm_votemap, or
|
||||
// some other plugin/command), we don't want to scramble the map cycle. Or for example, admin switches to a custom map
|
||||
// not in mapcyclefile. So we keep it set to the last expected nextmap. - ferret
|
||||
if (strcmp(lastMap, currentMap) == 0)
|
||||
{
|
||||
FindAndSetNextMap();
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_List(int client, int args)
|
||||
{
|
||||
PrintToConsole(client, "Map Cycle:");
|
||||
|
||||
int mapCount = g_MapList.Length;
|
||||
char mapName[PLATFORM_MAX_PATH];
|
||||
for (int i = 0; i < mapCount; i++)
|
||||
{
|
||||
g_MapList.GetString(i, mapName, sizeof(mapName));
|
||||
PrintToConsole(client, "%s", mapName);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
void FindAndSetNextMap()
|
||||
{
|
||||
if (ReadMapList(g_MapList,
|
||||
g_MapListSerial,
|
||||
"mapcyclefile",
|
||||
MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT)
|
||||
== null)
|
||||
{
|
||||
if (g_MapListSerial == -1)
|
||||
{
|
||||
LogError("FATAL: Cannot load map cycle. Nextmap not loaded.");
|
||||
SetFailState("Mapcycle Not Found");
|
||||
}
|
||||
}
|
||||
|
||||
int mapCount = g_MapList.Length;
|
||||
char mapName[PLATFORM_MAX_PATH];
|
||||
|
||||
if (g_MapPos == -1)
|
||||
{
|
||||
char current[PLATFORM_MAX_PATH];
|
||||
GetCurrentMap(current, sizeof(current));
|
||||
|
||||
for (int i = 0; i < mapCount; i++)
|
||||
{
|
||||
g_MapList.GetString(i, mapName, sizeof(mapName));
|
||||
if (FindMap(mapName, mapName, sizeof(mapName)) != FindMap_NotFound &&
|
||||
strcmp(current, mapName, false) == 0)
|
||||
{
|
||||
g_MapPos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_MapPos == -1)
|
||||
g_MapPos = 0;
|
||||
}
|
||||
|
||||
g_MapPos++;
|
||||
if (g_MapPos >= mapCount)
|
||||
g_MapPos = 0;
|
||||
|
||||
g_MapList.GetString(g_MapPos, mapName, sizeof(mapName));
|
||||
SetNextMap(mapName);
|
||||
}
|
||||
|
||||
public Action Command_MapHistory(int client, int args)
|
||||
{
|
||||
int mapCount = GetMapHistorySize();
|
||||
|
||||
char mapName[PLATFORM_MAX_PATH];
|
||||
char changeReason[100];
|
||||
char timeString[100];
|
||||
char playedTime[100];
|
||||
int startTime;
|
||||
|
||||
int lastMapStartTime = g_CurrentMapStartTime;
|
||||
|
||||
PrintToConsole(client, "Map History:\n");
|
||||
PrintToConsole(client, "Map : Started : Played Time : Reason for ending");
|
||||
|
||||
GetCurrentMap(mapName, sizeof(mapName));
|
||||
PrintToConsole(client, "%02i. %s (Current Map)", 0, mapName);
|
||||
|
||||
for (int i=0; i<mapCount; i++)
|
||||
{
|
||||
GetMapHistory(i, mapName, sizeof(mapName), changeReason, sizeof(changeReason), startTime);
|
||||
|
||||
FormatTimeDuration(timeString, sizeof(timeString), GetTime() - startTime);
|
||||
FormatTimeDuration(playedTime, sizeof(playedTime), lastMapStartTime - startTime);
|
||||
|
||||
PrintToConsole(client, "%02i. %s : %s ago : %s : %s", i+1, mapName, timeString, playedTime, changeReason);
|
||||
|
||||
lastMapStartTime = startTime;
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
int FormatTimeDuration(char[] buffer, int maxlen, int time)
|
||||
{
|
||||
int days = time / 86400;
|
||||
int hours = (time / 3600) % 24;
|
||||
int minutes = (time / 60) % 60;
|
||||
int seconds = time % 60;
|
||||
|
||||
if (days > 0)
|
||||
{
|
||||
return Format(buffer, maxlen, "%id %ih %im", days, hours, (seconds >= 30) ? minutes+1 : minutes);
|
||||
}
|
||||
else if (hours > 0)
|
||||
{
|
||||
return Format(buffer, maxlen, "%ih %im", hours, (seconds >= 30) ? minutes+1 : minutes);
|
||||
}
|
||||
else if (minutes > 0)
|
||||
{
|
||||
return Format(buffer, maxlen, "%im", (seconds >= 30) ? minutes+1 : minutes);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Format(buffer, maxlen, "%is", seconds);
|
||||
}
|
||||
}
|
435
scripting/temp/nominations.sp
Normal file
435
scripting/temp/nominations.sp
Normal file
@@ -0,0 +1,435 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Rock The Vote Plugin
|
||||
* Creates a map vote when the required number of players have requested one.
|
||||
*
|
||||
* SourceMod (C)2004-2014 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sourcemod>
|
||||
#include <mapchooser>
|
||||
|
||||
#pragma semicolon 1
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Map Nominations",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Provides Map Nominations",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
ConVar g_Cvar_ExcludeOld;
|
||||
ConVar g_Cvar_ExcludeCurrent;
|
||||
|
||||
Menu g_MapMenu = null;
|
||||
ArrayList g_MapList = null;
|
||||
int g_mapFileSerial = -1;
|
||||
|
||||
#define MAPSTATUS_ENABLED (1<<0)
|
||||
#define MAPSTATUS_DISABLED (1<<1)
|
||||
#define MAPSTATUS_EXCLUDE_CURRENT (1<<2)
|
||||
#define MAPSTATUS_EXCLUDE_PREVIOUS (1<<3)
|
||||
#define MAPSTATUS_EXCLUDE_NOMINATED (1<<4)
|
||||
|
||||
StringMap g_mapTrie = null;
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("nominations.phrases");
|
||||
|
||||
int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
|
||||
g_MapList = new ArrayList(arraySize);
|
||||
|
||||
g_Cvar_ExcludeOld = CreateConVar("sm_nominate_excludeold", "1", "Specifies if the current map should be excluded from the Nominations list", 0, true, 0.00, true, 1.0);
|
||||
g_Cvar_ExcludeCurrent = CreateConVar("sm_nominate_excludecurrent", "1", "Specifies if the MapChooser excluded maps should also be excluded from Nominations", 0, true, 0.00, true, 1.0);
|
||||
|
||||
RegConsoleCmd("sm_nominate", Command_Nominate);
|
||||
|
||||
RegAdminCmd("sm_nominate_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate_addmap <mapname> - Forces a map to be on the next mapvote.");
|
||||
|
||||
g_mapTrie = new StringMap();
|
||||
}
|
||||
|
||||
public void OnConfigsExecuted()
|
||||
{
|
||||
if (ReadMapList(g_MapList,
|
||||
g_mapFileSerial,
|
||||
"nominations",
|
||||
MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER)
|
||||
== null)
|
||||
{
|
||||
if (g_mapFileSerial == -1)
|
||||
{
|
||||
SetFailState("Unable to create a valid map list.");
|
||||
}
|
||||
}
|
||||
|
||||
BuildMapMenu();
|
||||
}
|
||||
|
||||
public void OnNominationRemoved(const char[] map, int owner)
|
||||
{
|
||||
int status;
|
||||
|
||||
char resolvedMap[PLATFORM_MAX_PATH];
|
||||
FindMap(map, resolvedMap, sizeof(resolvedMap));
|
||||
|
||||
/* Is the map in our list? */
|
||||
if (!g_mapTrie.GetValue(resolvedMap, status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Was the map disabled due to being nominated */
|
||||
if ((status & MAPSTATUS_EXCLUDE_NOMINATED) != MAPSTATUS_EXCLUDE_NOMINATED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_mapTrie.SetValue(resolvedMap, MAPSTATUS_ENABLED);
|
||||
}
|
||||
|
||||
public Action Command_Addmap(int client, int args)
|
||||
{
|
||||
if (args < 1)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] Usage: sm_nominate_addmap <mapname>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char mapname[PLATFORM_MAX_PATH];
|
||||
char resolvedMap[PLATFORM_MAX_PATH];
|
||||
GetCmdArg(1, mapname, sizeof(mapname));
|
||||
|
||||
if (FindMap(mapname, resolvedMap, sizeof(resolvedMap)) == FindMap_NotFound)
|
||||
{
|
||||
// We couldn't resolve the map entry to a filename, so...
|
||||
ReplyToCommand(client, "%t", "Map was not found", mapname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char displayName[PLATFORM_MAX_PATH];
|
||||
GetMapDisplayName(resolvedMap, displayName, sizeof(displayName));
|
||||
|
||||
int status;
|
||||
if (!g_mapTrie.GetValue(resolvedMap, status))
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Map was not found", displayName);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
NominateResult result = NominateMap(resolvedMap, true, 0);
|
||||
|
||||
if (result > Nominate_Replaced)
|
||||
{
|
||||
/* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it can't be full */
|
||||
ReplyToCommand(client, "%t", "Map Already In Vote", displayName);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
||||
g_mapTrie.SetValue(resolvedMap, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
|
||||
|
||||
|
||||
ReplyToCommand(client, "%t", "Map Inserted", displayName);
|
||||
LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void OnClientSayCommand_Post(int client, const char[] command, const char[] sArgs)
|
||||
{
|
||||
if (!client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sArgs, "nominate", false) == 0)
|
||||
{
|
||||
ReplySource old = SetCmdReplySource(SM_REPLY_TO_CHAT);
|
||||
|
||||
AttemptNominate(client);
|
||||
|
||||
SetCmdReplySource(old);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_Nominate(int client, int args)
|
||||
{
|
||||
if (!client)
|
||||
{
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (args == 0)
|
||||
{
|
||||
AttemptNominate(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char mapname[PLATFORM_MAX_PATH];
|
||||
GetCmdArg(1, mapname, sizeof(mapname));
|
||||
|
||||
if (FindMap(mapname, mapname, sizeof(mapname)) == FindMap_NotFound)
|
||||
{
|
||||
// We couldn't resolve the map entry to a filename, so...
|
||||
ReplyToCommand(client, "%t", "Map was not found", mapname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char displayName[PLATFORM_MAX_PATH];
|
||||
GetMapDisplayName(mapname, displayName, sizeof(displayName));
|
||||
|
||||
int status;
|
||||
if (!g_mapTrie.GetValue(mapname, status))
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Map was not found", displayName);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
|
||||
{
|
||||
if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Can't Nominate Current Map");
|
||||
}
|
||||
|
||||
if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Map in Exclude List");
|
||||
}
|
||||
|
||||
if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Map Already Nominated");
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
NominateResult result = NominateMap(mapname, false, client);
|
||||
|
||||
if (result > Nominate_Replaced)
|
||||
{
|
||||
if (result == Nominate_AlreadyInVote)
|
||||
{
|
||||
ReplyToCommand(client, "%t", "Map Already In Vote", displayName);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[SM] %t", "Map Already Nominated");
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/* Map was nominated! - Disable the menu item and update the trie */
|
||||
|
||||
g_mapTrie.SetValue(mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
|
||||
|
||||
char name[MAX_NAME_LENGTH];
|
||||
GetClientName(client, name, sizeof(name));
|
||||
PrintToChatAll("[SM] %t", "Map Nominated", name, displayName);
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
void AttemptNominate(int client)
|
||||
{
|
||||
g_MapMenu.SetTitle("%T", "Nominate Title", client);
|
||||
g_MapMenu.Display(client, MENU_TIME_FOREVER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void BuildMapMenu()
|
||||
{
|
||||
delete g_MapMenu;
|
||||
|
||||
g_mapTrie.Clear();
|
||||
|
||||
g_MapMenu = new Menu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem);
|
||||
|
||||
char map[PLATFORM_MAX_PATH];
|
||||
|
||||
ArrayList excludeMaps;
|
||||
char currentMap[PLATFORM_MAX_PATH];
|
||||
|
||||
if (g_Cvar_ExcludeOld.BoolValue)
|
||||
{
|
||||
excludeMaps = new ArrayList(ByteCountToCells(PLATFORM_MAX_PATH));
|
||||
GetExcludeMapList(excludeMaps);
|
||||
}
|
||||
|
||||
if (g_Cvar_ExcludeCurrent.BoolValue)
|
||||
{
|
||||
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_MapList.Length; i++)
|
||||
{
|
||||
int status = MAPSTATUS_ENABLED;
|
||||
|
||||
g_MapList.GetString(i, map, sizeof(map));
|
||||
|
||||
FindMap(map, map, sizeof(map));
|
||||
|
||||
char displayName[PLATFORM_MAX_PATH];
|
||||
GetMapDisplayName(map, displayName, sizeof(displayName));
|
||||
|
||||
if (g_Cvar_ExcludeCurrent.BoolValue)
|
||||
{
|
||||
if (StrEqual(map, currentMap))
|
||||
{
|
||||
status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_CURRENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dont bother with this check if the current map check passed */
|
||||
if (g_Cvar_ExcludeOld.BoolValue && status == MAPSTATUS_ENABLED)
|
||||
{
|
||||
if (excludeMaps.FindString(map) != -1)
|
||||
{
|
||||
status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS;
|
||||
}
|
||||
}
|
||||
|
||||
g_MapMenu.AddItem(map, displayName);
|
||||
g_mapTrie.SetValue(map, status);
|
||||
}
|
||||
|
||||
g_MapMenu.ExitButton = true;
|
||||
|
||||
delete excludeMaps;
|
||||
}
|
||||
|
||||
public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int param2)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case MenuAction_Select:
|
||||
{
|
||||
char map[PLATFORM_MAX_PATH], name[MAX_NAME_LENGTH], displayName[PLATFORM_MAX_PATH];
|
||||
menu.GetItem(param2, map, sizeof(map), _, displayName, sizeof(displayName));
|
||||
|
||||
GetClientName(param1, name, sizeof(name));
|
||||
|
||||
NominateResult result = NominateMap(map, false, param1);
|
||||
|
||||
/* Don't need to check for InvalidMap because the menu did that already */
|
||||
if (result == Nominate_AlreadyInVote)
|
||||
{
|
||||
PrintToChat(param1, "[SM] %t", "Map Already Nominated");
|
||||
return 0;
|
||||
}
|
||||
else if (result == Nominate_VoteFull)
|
||||
{
|
||||
PrintToChat(param1, "[SM] %t", "Max Nominations");
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_mapTrie.SetValue(map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
|
||||
|
||||
if (result == Nominate_Replaced)
|
||||
{
|
||||
PrintToChatAll("[SM] %t", "Map Nomination Changed", name, displayName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintToChatAll("[SM] %t", "Map Nominated", name, displayName);
|
||||
}
|
||||
|
||||
case MenuAction_DrawItem:
|
||||
{
|
||||
char map[PLATFORM_MAX_PATH];
|
||||
menu.GetItem(param2, map, sizeof(map));
|
||||
|
||||
int status;
|
||||
|
||||
if (!g_mapTrie.GetValue(map, status))
|
||||
{
|
||||
LogError("Menu selection of item not in trie. Major logic problem somewhere.");
|
||||
return ITEMDRAW_DEFAULT;
|
||||
}
|
||||
|
||||
if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
|
||||
{
|
||||
return ITEMDRAW_DISABLED;
|
||||
}
|
||||
|
||||
return ITEMDRAW_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
case MenuAction_DisplayItem:
|
||||
{
|
||||
char map[PLATFORM_MAX_PATH], displayName[PLATFORM_MAX_PATH];
|
||||
menu.GetItem(param2, map, sizeof(map), _, displayName, sizeof(displayName));
|
||||
|
||||
int status;
|
||||
|
||||
if (!g_mapTrie.GetValue(map, status))
|
||||
{
|
||||
LogError("Menu selection of item not in trie. Major logic problem somewhere.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char display[PLATFORM_MAX_PATH + 64];
|
||||
|
||||
if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
|
||||
{
|
||||
if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
|
||||
{
|
||||
Format(display, sizeof(display), "%s (%T)", displayName, "Current Map", param1);
|
||||
return RedrawMenuItem(display);
|
||||
}
|
||||
|
||||
if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
|
||||
{
|
||||
Format(display, sizeof(display), "%s (%T)", displayName, "Recently Played", param1);
|
||||
return RedrawMenuItem(display);
|
||||
}
|
||||
|
||||
if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
|
||||
{
|
||||
Format(display, sizeof(display), "%s (%T)", displayName, "Nominated", param1);
|
||||
return RedrawMenuItem(display);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
98
scripting/temp/playercommands.sp
Normal file
98
scripting/temp/playercommands.sp
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Player Commands Plugin
|
||||
* Implements slap and slay commands
|
||||
*
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#include <adminmenu>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Player Commands",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Misc. Player Commands",
|
||||
version = SOURCEMOD_VERSION,
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
TopMenu hTopMenu;
|
||||
|
||||
/* Used to get the SDK / Engine version. */
|
||||
#include "playercommands/slay.sp"
|
||||
#include "playercommands/slap.sp"
|
||||
#include "playercommands/rename.sp"
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("playercommands.phrases");
|
||||
|
||||
RegAdminCmd("sm_slap", Command_Slap, ADMFLAG_SLAY, "sm_slap <#userid|name> [damage]");
|
||||
RegAdminCmd("sm_slay", Command_Slay, ADMFLAG_SLAY, "sm_slay <#userid|name>");
|
||||
RegAdminCmd("sm_rename", Command_Rename, ADMFLAG_SLAY, "sm_rename <#userid|name>");
|
||||
|
||||
/* Account for late loading */
|
||||
TopMenu topmenu;
|
||||
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
|
||||
{
|
||||
OnAdminMenuReady(topmenu);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAdminMenuReady(Handle aTopMenu)
|
||||
{
|
||||
TopMenu topmenu = TopMenu.FromHandle(aTopMenu);
|
||||
|
||||
/* Block us from being called twice */
|
||||
if (topmenu == hTopMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the Handle */
|
||||
hTopMenu = topmenu;
|
||||
|
||||
/* Find the "Player Commands" category */
|
||||
TopMenuObject player_commands = hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
|
||||
|
||||
if (player_commands != INVALID_TOPMENUOBJECT)
|
||||
{
|
||||
hTopMenu.AddItem("sm_slay", AdminMenu_Slay, player_commands, "sm_slay", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_slap", AdminMenu_Slap, player_commands, "sm_slap", ADMFLAG_SLAY);
|
||||
hTopMenu.AddItem("sm_rename", AdminMenu_Rename, player_commands, "sm_rename", ADMFLAG_SLAY);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user