/*
* shavit's Timer - Miscellaneous
* by: shavit
*
* This file is part of shavit's Timer.
*
* 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 .
*
*/
#include
#include
#include
#include
#include
#undef REQUIRE_EXTENSIONS
#include
#include
#include
#include
#include
#undef REQUIRE_PLUGIN
#include
#pragma newdecls required
#pragma semicolon 1
#pragma dynamic 524288
#define CP_ANGLES (1 << 0)
#define CP_VELOCITY (1 << 1)
#define CP_DEFAULT (CP_ANGLES|CP_VELOCITY)
enum struct player_cpcache_t
{
int iCheckpoints;
int iCurrentCheckpoint;
}
enum struct persistent_data_t
{
int iSteamID;
float fDisconnectTime;
float fPosition[3];
float fAngles[3];
MoveType iMoveType;
float fGravity;
float fSpeed;
timer_snapshot_t aSnapshot;
int iTargetname;
int iClassname;
ArrayList aFrames;
int iPreFrames;
int iTimerPreFrames;
bool bPractice;
}
typedef StopTimerCallback = function void (int data);
// game specific
EngineVersion gEV_Type = Engine_Unknown;
int gI_Ammo = -1;
char gS_RadioCommands[][] = { "coverme", "takepoint", "holdpos", "regroup", "followme", "takingfire", "go", "fallback", "sticktog",
"getinpos", "stormfront", "report", "roger", "enemyspot", "needbackup", "sectorclear", "inposition", "reportingin",
"getout", "negative", "enemydown", "compliment", "thanks", "cheer", "go_a", "go_b", "sorry", "needrop" };
bool gB_Hide[MAXPLAYERS+1];
bool gB_Late = false;
int gI_GroundEntity[MAXPLAYERS+1];
int gI_LastShot[MAXPLAYERS+1];
ArrayList gA_Advertisements = null;
int gI_AdvertisementsCycle = 0;
char gS_CurrentMap[192];
int gI_Style[MAXPLAYERS+1];
Function gH_AfterWarningMenu[MAXPLAYERS+1];
bool gB_ClosedKZCP[MAXPLAYERS+1];
player_cpcache_t gA_CheckpointsCache[MAXPLAYERS+1];
int gI_CheckpointsSettings[MAXPLAYERS+1];
StringMap gSM_Checkpoints = null;
ArrayList gA_Targetnames = null;
ArrayList gA_Classnames = null;
// save states
bool gB_SaveStatesSegmented[MAXPLAYERS+1];
float gF_SaveStateData[MAXPLAYERS+1][3][3];
timer_snapshot_t gA_SaveStates[MAXPLAYERS+1];
bool gB_SaveStates[MAXPLAYERS+1];
char gS_SaveStateTargetname[MAXPLAYERS+1][32];
ArrayList gA_SaveFrames[MAXPLAYERS+1];
ArrayList gA_PersistentData = null;
// cookies
Handle gH_HideCookie = null;
Handle gH_CheckpointsCookie = null;
// cvars
Convar gCV_GodMode = null;
Convar gCV_PreSpeed = null;
Convar gCV_HideTeamChanges = null;
Convar gCV_RespawnOnTeam = null;
Convar gCV_RespawnOnRestart = null;
Convar gCV_StartOnSpawn = null;
Convar gCV_PrestrafeLimit = null;
Convar gCV_HideRadar = null;
Convar gCV_TeleportCommands = null;
Convar gCV_NoWeaponDrops = null;
Convar gCV_NoBlock = null;
Convar gCV_NoBlood = null;
Convar gCV_AutoRespawn = null;
Convar gCV_CreateSpawnPoints = null;
Convar gCV_DisableRadio = null;
Convar gCV_Scoreboard = null;
Convar gCV_WeaponCommands = null;
Convar gCV_PlayerOpacity = null;
Convar gCV_StaticPrestrafe = null;
Convar gCV_NoclipMe = null;
Convar gCV_AdvertisementInterval = null;
Convar gCV_Checkpoints = null;
Convar gCV_RemoveRagdolls = null;
Convar gCV_ClanTag = null;
Convar gCV_DropAll = null;
Convar gCV_ResetTargetname = null;
Convar gCV_RestoreStates = null;
Convar gCV_JointeamHook = null;
Convar gCV_SpectatorList = null;
Convar gCV_MaxCP = null;
Convar gCV_MaxCP_Segmented = null;
Convar gCV_HideChatCommands = null;
Convar gCV_PersistData = null;
Convar gCV_StopTimerWarning = null;
Convar gCV_WRMessages = null;
Convar gCV_BhopSounds = null;
// external cvars
ConVar sv_disable_immunity_alpha = null;
ConVar mp_humanteam = null;
ConVar hostname = null;
ConVar hostport = null;
// forwards
Handle gH_Forwards_OnClanTagChangePre = null;
Handle gH_Forwards_OnClanTagChangePost = null;
Handle gH_Forwards_OnSave = null;
Handle gH_Forwards_OnTeleport = null;
Handle gH_Forwards_OnCheckpointMenuMade = null;
Handle gH_Forwards_OnCheckpointMenuSelect = null;
// dhooks
Handle gH_GetPlayerMaxSpeed = null;
// modules
bool gB_Rankings = false;
bool gB_Replay = false;
bool gB_Zones = false;
// timer settings
stylestrings_t gS_StyleStrings[STYLE_LIMIT];
stylesettings_t gA_StyleSettings[STYLE_LIMIT];
// chat settings
chatstrings_t gS_ChatStrings;
public Plugin myinfo =
{
name = "[shavit] Miscellaneous",
author = "shavit",
description = "Miscellaneous features for shavit's bhop timer.",
version = SHAVIT_VERSION,
url = "https://github.com/shavitush/bhoptimer"
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("Shavit_GetCheckpoint", Native_GetCheckpoint);
CreateNative("Shavit_SetCheckpoint", Native_SetCheckpoint);
CreateNative("Shavit_ClearCheckpoints", Native_ClearCheckpoints);
CreateNative("Shavit_TeleportToCheckpoint", Native_TeleportToCheckpoint);
CreateNative("Shavit_GetTotalCheckpoints", Native_GetTotalCheckpoints);
CreateNative("Shavit_OpenCheckpointMenu", Native_OpenCheckpointMenu);
CreateNative("Shavit_SaveCheckpoint", Native_SaveCheckpoint);
CreateNative("Shavit_GetCurrentCheckpoint", Native_GetCurrentCheckpoint);
CreateNative("Shavit_SetCurrentCheckpoint", Native_SetCurrentCheckpoint);
gB_Late = late;
return APLRes_Success;
}
public void OnPluginStart()
{
// forwards
gH_Forwards_OnClanTagChangePre = CreateGlobalForward("Shavit_OnClanTagChangePre", ET_Event, Param_Cell, Param_String, Param_Cell);
gH_Forwards_OnClanTagChangePost = CreateGlobalForward("Shavit_OnClanTagChangePost", ET_Event, Param_Cell, Param_String, Param_Cell);
gH_Forwards_OnSave = CreateGlobalForward("Shavit_OnSave", ET_Event, Param_Cell, Param_Cell, Param_Cell);
gH_Forwards_OnTeleport = CreateGlobalForward("Shavit_OnTeleport", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_OnCheckpointMenuMade = CreateGlobalForward("Shavit_OnCheckpointMenuMade", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_OnCheckpointMenuSelect = CreateGlobalForward("Shavit_OnCheckpointMenuSelect", ET_Event, Param_Cell, Param_Cell, Param_String, Param_Cell, Param_Cell, Param_Cell);
// cache
gEV_Type = GetEngineVersion();
sv_disable_immunity_alpha = FindConVar("sv_disable_immunity_alpha");
// spectator list
RegConsoleCmd("sm_specs", Command_Specs, "Show a list of spectators.");
RegConsoleCmd("sm_spectators", Command_Specs, "Show a list of spectators.");
// spec
RegConsoleCmd("sm_spec", Command_Spec, "Moves you to the spectators' team. Usage: sm_spec [target]");
RegConsoleCmd("sm_spectate", Command_Spec, "Moves you to the spectators' team. Usage: sm_spectate [target]");
// hide
RegConsoleCmd("sm_hide", Command_Hide, "Toggle players' hiding.");
RegConsoleCmd("sm_unhide", Command_Hide, "Toggle players' hiding.");
gH_HideCookie = RegClientCookie("shavit_hide", "Hide settings", CookieAccess_Protected);
// tpto
RegConsoleCmd("sm_tpto", Command_Teleport, "Teleport to another player. Usage: sm_tpto [target]");
RegConsoleCmd("sm_goto", Command_Teleport, "Teleport to another player. Usage: sm_goto [target]");
// weapons
RegConsoleCmd("sm_usp", Command_Weapon, "Spawn a USP.");
RegConsoleCmd("sm_glock", Command_Weapon, "Spawn a Glock.");
RegConsoleCmd("sm_knife", Command_Weapon, "Spawn a knife.");
// checkpoints
RegConsoleCmd("sm_cpmenu", Command_Checkpoints, "Opens the checkpoints menu.");
RegConsoleCmd("sm_cp", Command_Checkpoints, "Opens the checkpoints menu. Alias for sm_cpmenu.");
RegConsoleCmd("sm_checkpoint", Command_Checkpoints, "Opens the checkpoints menu. Alias for sm_cpmenu.");
RegConsoleCmd("sm_checkpoints", Command_Checkpoints, "Opens the checkpoints menu. Alias for sm_cpmenu.");
RegConsoleCmd("sm_save", Command_Save, "Saves checkpoint.");
RegConsoleCmd("sm_tele", Command_Tele, "Teleports to checkpoint. Usage: sm_tele [number]");
gH_CheckpointsCookie = RegClientCookie("shavit_checkpoints", "Checkpoints settings", CookieAccess_Protected);
gSM_Checkpoints = new StringMap();
gA_Targetnames = new ArrayList(ByteCountToCells(64));
gA_Classnames = new ArrayList(ByteCountToCells(64));
gA_PersistentData = new ArrayList(sizeof(persistent_data_t));
gI_Ammo = FindSendPropInfo("CCSPlayer", "m_iAmmo");
// noclip
RegConsoleCmd("sm_p", Command_Noclip, "Toggles noclip.");
RegConsoleCmd("sm_prac", Command_Noclip, "Toggles noclip. (sm_p alias)");
RegConsoleCmd("sm_practice", Command_Noclip, "Toggles noclip. (sm_p alias)");
RegConsoleCmd("sm_nc", Command_Noclip, "Toggles noclip. (sm_p alias)");
RegConsoleCmd("sm_noclipme", Command_Noclip, "Toggles noclip. (sm_p alias)");
AddCommandListener(CommandListener_Noclip, "+noclip");
AddCommandListener(CommandListener_Noclip, "-noclip");
// hook teamjoins
AddCommandListener(Command_Jointeam, "jointeam");
// hook radio commands instead of a global listener
for(int i = 0; i < sizeof(gS_RadioCommands); i++)
{
AddCommandListener(Command_Radio, gS_RadioCommands[i]);
}
// hooks
HookEvent("player_spawn", Player_Spawn);
HookEvent("player_team", Player_Notifications, EventHookMode_Pre);
HookEvent("player_death", Player_Notifications, EventHookMode_Pre);
HookEventEx("weapon_fire", Weapon_Fire);
AddCommandListener(Command_Drop, "drop");
AddTempEntHook("EffectDispatch", EffectDispatch);
AddTempEntHook("World Decal", WorldDecal);
AddTempEntHook((gEV_Type != Engine_TF2)? "Shotgun Shot":"Fire Bullets", Shotgun_Shot);
AddNormalSoundHook(NormalSound);
// phrases
LoadTranslations("common.phrases");
LoadTranslations("shavit-common.phrases");
LoadTranslations("shavit-misc.phrases");
// advertisements
gA_Advertisements = new ArrayList(300);
hostname = FindConVar("hostname");
hostport = FindConVar("hostport");
// cvars and stuff
gCV_GodMode = new Convar("shavit_misc_godmode", "3", "Enable godmode for players?\n0 - Disabled\n1 - Only prevent fall/world damage.\n2 - Only prevent damage from other players.\n3 - Full godmode.", 0, true, 0.0, true, 3.0);
gCV_PreSpeed = new Convar("shavit_misc_prespeed", "1", "Stop prespeeding in the start zone?\n0 - Disabled, fully allow prespeeding.\n1 - Limit relatively to prestrafelimit.\n2 - Block bunnyhopping in startzone.\n3 - Limit to prestrafelimit and block bunnyhopping.\n4 - Limit to prestrafelimit but allow prespeeding. Combine with shavit_core_nozaxisspeed 1 for SourceCode timer's behavior.", 0, true, 0.0, true, 4.0);
gCV_HideTeamChanges = new Convar("shavit_misc_hideteamchanges", "1", "Hide team changes in chat?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_RespawnOnTeam = new Convar("shavit_misc_respawnonteam", "1", "Respawn whenever a player joins a team?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_RespawnOnRestart = new Convar("shavit_misc_respawnonrestart", "1", "Respawn a dead player if they use the timer restart command?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_StartOnSpawn = new Convar("shavit_misc_startonspawn", "1", "Restart the timer for a player after they spawn?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_PrestrafeLimit = new Convar("shavit_misc_prestrafelimit", "30", "Prestrafe limitation in startzone.\nThe value used internally is style run speed + this.\ni.e. run speed of 250 can prestrafe up to 278 (+28) with regular settings.", 0, true, 0.0, false);
gCV_HideRadar = new Convar("shavit_misc_hideradar", "1", "Should the plugin hide the in-game radar?", 0, true, 0.0, true, 1.0);
gCV_TeleportCommands = new Convar("shavit_misc_tpcmds", "1", "Enable teleport-related commands? (sm_goto/sm_tpto)\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_NoWeaponDrops = new Convar("shavit_misc_noweapondrops", "1", "Remove every dropped weapon.\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_NoBlock = new Convar("shavit_misc_noblock", "1", "Disable player collision?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_NoBlood = new Convar("shavit_misc_noblood", "0", "Hide blood decals and particles?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_AutoRespawn = new Convar("shavit_misc_autorespawn", "1.5", "Seconds to wait before respawning player?\n0 - Disabled", 0, true, 0.0, true, 10.0);
gCV_CreateSpawnPoints = new Convar("shavit_misc_createspawnpoints", "6", "Amount of spawn points to add for each team.\n0 - Disabled", 0, true, 0.0, true, 32.0);
gCV_DisableRadio = new Convar("shavit_misc_disableradio", "0", "Block radio commands.\n0 - Disabled (radio commands work)\n1 - Enabled (radio commands are blocked)", 0, true, 0.0, true, 1.0);
gCV_Scoreboard = new Convar("shavit_misc_scoreboard", "1", "Manipulate scoreboard so score is -{time} and deaths are {rank})?\nDeaths part requires shavit-rankings.\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_WeaponCommands = new Convar("shavit_misc_weaponcommands", "2", "Enable sm_usp, sm_glock and sm_knife?\n0 - Disabled\n1 - Enabled\n2 - Also give infinite reserved ammo.", 0, true, 0.0, true, 2.0);
gCV_PlayerOpacity = new Convar("shavit_misc_playeropacity", "-1", "Player opacity (alpha) to set on spawn.\n-1 - Disabled\nValue can go up to 255. 0 for invisibility.", 0, true, -1.0, true, 255.0);
gCV_StaticPrestrafe = new Convar("shavit_misc_staticprestrafe", "1", "Force prestrafe for every pistol.\n250 is the default value and some styles will have 260.\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_NoclipMe = new Convar("shavit_misc_noclipme", "1", "Allow +noclip, sm_p and all the noclip commands?\n0 - Disabled\n1 - Enabled\n2 - requires 'admin_noclipme' override or ADMFLAG_CHEATS flag.", 0, true, 0.0, true, 2.0);
gCV_AdvertisementInterval = new Convar("shavit_misc_advertisementinterval", "600.0", "Interval between each chat advertisement.\nConfiguration file for those is configs/shavit-advertisements.cfg.\nSet to 0.0 to disable.\nRequires server restart for changes to take effect.", 0, true, 0.0);
gCV_Checkpoints = new Convar("shavit_misc_checkpoints", "1", "Allow players to save and teleport to checkpoints.", 0, true, 0.0, true, 1.0);
gCV_RemoveRagdolls = new Convar("shavit_misc_removeragdolls", "1", "Remove ragdolls after death?\n0 - Disabled\n1 - Only remove replay bot ragdolls.\n2 - Remove all ragdolls.", 0, true, 0.0, true, 2.0);
gCV_ClanTag = new Convar("shavit_misc_clantag", "{tr}{styletag} :: {time}", "Custom clantag for players.\n0 - Disabled\n{styletag} - style tag.\n{style} - style name.\n{time} - formatted time.\n{tr} - first letter of track.\n{rank} - player rank.", 0);
gCV_DropAll = new Convar("shavit_misc_dropall", "1", "Allow all weapons to be dropped?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_ResetTargetname = new Convar("shavit_misc_resettargetname", "0", "Reset the player's targetname upon timer start?\nRecommended to leave disabled. Enable via per-map configs when necessary.\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_RestoreStates = new Convar("shavit_misc_restorestates", "0", "Save the players' timer/position etc.. when they die/change teams,\nand load the data when they spawn?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_JointeamHook = new Convar("shavit_misc_jointeamhook", "1", "Hook `jointeam`?\n0 - Disabled\n1 - Enabled, players can instantly change teams.", 0, true, 0.0, true, 1.0);
gCV_SpectatorList = new Convar("shavit_misc_speclist", "1", "Who to show in !specs?\n0 - everyone\n1 - all admins (admin_speclisthide override to bypass)\n2 - players you can target", 0, true, 0.0, true, 2.0);
gCV_MaxCP = new Convar("shavit_misc_maxcp", "1000", "Maximum amount of checkpoints.\nNote: Very high values will result in high memory usage!", 0, true, 1.0, true, 10000.0);
gCV_MaxCP_Segmented = new Convar("shavit_misc_maxcp_seg", "10", "Maximum amount of segmented checkpoints. Make this less or equal to shavit_misc_maxcp.\nNote: Very high values will result in HUGE memory usage!", 0, true, 1.0, true, 50.0);
gCV_HideChatCommands = new Convar("shavit_misc_hidechatcmds", "1", "Hide commands from chat?\n0 - Disabled\n1 - Enabled", 0, true, 0.0, true, 1.0);
gCV_PersistData = new Convar("shavit_misc_persistdata", "300", "How long to persist timer data for disconnected users in seconds?\n-1 - Until map change\n0 - Disabled");
gCV_StopTimerWarning = new Convar("shavit_misc_stoptimerwarning", "900", "Time in seconds to display a warning before stopping the timer with noclip or !stop.\n0 - Disabled");
gCV_WRMessages = new Convar("shavit_misc_wrmessages", "3", "How many \"NEW