mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-06 12:43:20 +00:00
Update plugins
This commit is contained in:
parent
2c99586be1
commit
daa3b26a4d
19 changed files with 611 additions and 298 deletions
BIN
plugins/adminpanel.smx
Normal file
BIN
plugins/adminpanel.smx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
387
scripting/adminpanel.sp
Normal file
387
scripting/adminpanel.sp
Normal file
|
@ -0,0 +1,387 @@
|
|||
#pragma semicolon 1
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#define PLUGIN_VERSION "0.00"
|
||||
#define UPDATE_INTERVAL 6.0
|
||||
#define UPDATE_INTERVAL_SLOW 15.0
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <ripext>
|
||||
#include <left4dhooks>
|
||||
#include <jutils>
|
||||
|
||||
#pragma newdecls required
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Admin Panel",
|
||||
author = "Jackz",
|
||||
description = "",
|
||||
version = PLUGIN_VERSION,
|
||||
url = ""
|
||||
};
|
||||
|
||||
ConVar cvar_debug;
|
||||
ConVar cvar_postAddress; char postAddress[128];
|
||||
ConVar cvar_authKey; char authKey[512];
|
||||
ConVar cvar_gamemode; char gamemode[32];
|
||||
|
||||
char currentMap[64];
|
||||
int numberOfPlayers = 0;
|
||||
int lastSuccessTime;
|
||||
int lastErrorCode;
|
||||
int uptime;
|
||||
bool fastUpdateMode = false;
|
||||
|
||||
Handle updateTimer = null;
|
||||
|
||||
char steamidCache[MAXPLAYERS+1][32];
|
||||
char nameCache[MAXPLAYERS+1][MAX_NAME_LENGTH];
|
||||
int g_icBeingHealed[MAXPLAYERS+1];
|
||||
int playerJoinTime[MAXPLAYERS+1];
|
||||
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
uptime = GetTime();
|
||||
cvar_debug = CreateConVar("sm_adminpanel_debug", "0", "Turn on debug mode", FCVAR_DONTRECORD, true, 0.0, true, 1.0);
|
||||
|
||||
cvar_postAddress = CreateConVar("sm_adminpanel_url", "", "The base address to post updates to", FCVAR_NONE);
|
||||
cvar_postAddress.AddChangeHook(OnCvarChanged);
|
||||
cvar_postAddress.GetString(postAddress, sizeof(postAddress));
|
||||
cvar_authKey = CreateConVar("sm_adminpanel_key", "", "The authentication key", FCVAR_NONE);
|
||||
cvar_authKey.AddChangeHook(OnCvarChanged);
|
||||
cvar_authKey.GetString(authKey, sizeof(authKey));
|
||||
|
||||
cvar_gamemode = FindConVar("mp_gamemode");
|
||||
cvar_gamemode.AddChangeHook(OnCvarChanged);
|
||||
cvar_gamemode.GetString(gamemode, sizeof(gamemode));
|
||||
|
||||
HookEvent("heal_success", Event_HealStop);
|
||||
HookEvent("heal_interrupted", Event_HealStop);
|
||||
HookEvent("player_first_spawn", Event_PlayerFirstSpawn);
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i)) {
|
||||
OnClientPutInServer(i);
|
||||
}
|
||||
}
|
||||
|
||||
TryStartTimer(true);
|
||||
|
||||
AutoExecConfig(true, "adminpanel");
|
||||
|
||||
RegAdminCmd("sm_panel_status", Command_PanelStatus, ADMFLAG_GENERIC);
|
||||
|
||||
}
|
||||
|
||||
#define DATE_FORMAT "%F at %I:%M %p"
|
||||
Action Command_PanelStatus(int client, int args) {
|
||||
ReplyToCommand(client, "Active: %b", updateTimer != null);
|
||||
ReplyToCommand(client, "Last Error Code: %d", lastErrorCode);
|
||||
ReplyToCommand(client, "#Players: %d", numberOfPlayers);
|
||||
ReplyToCommand(client, "Update Interval: %0f s", fastUpdateMode ? UPDATE_INTERVAL : UPDATE_INTERVAL_SLOW);
|
||||
char buffer[32];
|
||||
if(lastSuccessTime > 0)
|
||||
FormatTime(buffer, sizeof(buffer), DATE_FORMAT, lastSuccessTime);
|
||||
else
|
||||
Format(buffer, sizeof(buffer), "(none)");
|
||||
ReplyToCommand(client, "Last Success: %s", buffer);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
void TryStartTimer(bool fast = true) {
|
||||
if(numberOfPlayers > 0 && updateTimer == null && postAddress[0] != '\0' && authKey[0] != 0) {
|
||||
fastUpdateMode = fast;
|
||||
float interval = fast ? UPDATE_INTERVAL : UPDATE_INTERVAL_SLOW;
|
||||
updateTimer = CreateTimer(interval, Timer_PostStatus, _, TIMER_REPEAT);
|
||||
PrintToServer("[AdminPanel] Timer created, updating every %.1f seconds", interval);
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_HealStart(Event event, const char[] name, bool dontBroadcast) {
|
||||
int healing = GetClientOfUserId(event.GetInt("subject"));
|
||||
g_icBeingHealed[healing] = true;
|
||||
}
|
||||
public void Event_HealStop(Event event, const char[] name, bool dontBroadcast) {
|
||||
int healing = GetClientOfUserId(event.GetInt("subject"));
|
||||
g_icBeingHealed[healing] = false;
|
||||
}
|
||||
|
||||
public void Event_PlayerFirstSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
playerJoinTime[client] = GetTime();
|
||||
}
|
||||
|
||||
public void OnMapStart() {
|
||||
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||
}
|
||||
|
||||
// Player counts
|
||||
public void OnClientPutInServer(int client) {
|
||||
GetClientName(client, nameCache[client], MAX_NAME_LENGTH);
|
||||
if(!IsFakeClient(client)) {
|
||||
GetClientAuthId(client, AuthId_SteamID64, steamidCache[client], 32);
|
||||
numberOfPlayers++;
|
||||
TryStartTimer(true);
|
||||
} else {
|
||||
strcopy(steamidCache[client], 32, "BOT");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client) {
|
||||
steamidCache[client][0] = '\0';
|
||||
nameCache[client][0] = '\0';
|
||||
if(!IsFakeClient(client)) {
|
||||
numberOfPlayers--;
|
||||
if(numberOfPlayers == 0 && updateTimer != null) {
|
||||
delete updateTimer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cvar updates
|
||||
void OnCvarChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
|
||||
if(cvar_postAddress == convar) {
|
||||
strcopy(postAddress, sizeof(postAddress), newValue);
|
||||
PrintToServer("[AdminPanel] Update Url has updated");
|
||||
} else if(cvar_authKey == convar) {
|
||||
strcopy(authKey, sizeof(authKey), newValue);
|
||||
PrintToServer("[AdminPanel] Auth key has been updated");
|
||||
} else if(cvar_gamemode == convar) {
|
||||
strcopy(gamemode, sizeof(gamemode), newValue);
|
||||
}
|
||||
TryStartTimer(true);
|
||||
}
|
||||
|
||||
bool isSubmitting;
|
||||
Action Timer_PostStatus(Handle h) {
|
||||
if(isSubmitting) return Plugin_Continue;
|
||||
isSubmitting = true;
|
||||
// TODO: optimize only if someone is requesting live
|
||||
HTTPRequest req = new HTTPRequest(postAddress);
|
||||
JSONObject obj = GetObject();
|
||||
req.SetHeader("x-authtoken", authKey);
|
||||
// req.AppendFormParam("playerCount", "%d", numberOfPlayers);
|
||||
// req.AppendFormParam("map", currentMap);
|
||||
if(cvar_debug.BoolValue) PrintToServer("[AdminPanel] Submitting");
|
||||
req.Post(obj, Callback_PostStatus);
|
||||
delete obj;
|
||||
// req.PostForm(Callback_PostStatus);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
void Callback_PostStatus(HTTPResponse response, any value, const char[] error) {
|
||||
isSubmitting = false;
|
||||
if(response.Status == HTTPStatus_NoContent || response.Status == HTTPStatus_OK) {
|
||||
lastErrorCode = 0;
|
||||
lastSuccessTime = GetTime();
|
||||
if(cvar_debug.BoolValue)
|
||||
PrintToServer("[AdminPanel] Response: OK/204");
|
||||
// We have subscribers, kill timer and recreate it in fast mode (if not already):
|
||||
if(!fastUpdateMode) {
|
||||
PrintToServer("[AdminPanel] We have subscribers, increasing interval");
|
||||
if(updateTimer != null)
|
||||
delete updateTimer;
|
||||
TryStartTimer(true);
|
||||
}
|
||||
|
||||
} else if(response.Status == HTTPStatus_Gone) {
|
||||
lastErrorCode = 0;
|
||||
// We have no subscribers, kill timer and recreate it in slow mode (if not already):
|
||||
if(fastUpdateMode) {
|
||||
PrintToServer("[AdminPanel] No subscribers, decreasing interval");
|
||||
if(updateTimer != null)
|
||||
delete updateTimer;
|
||||
TryStartTimer(false);
|
||||
}
|
||||
} else {
|
||||
lastErrorCode = view_as<int>(response.Status);
|
||||
lastSuccessTime = 0;
|
||||
// TODO: backoff
|
||||
char buffer[64];
|
||||
JSONObject json = view_as<JSONObject>(response.Data);
|
||||
if(json.GetString("error", buffer, sizeof(buffer))) {
|
||||
PrintToServer("[AdminPanel] Got %d response from server: \"%s\"", view_as<int>(response.Status), buffer);
|
||||
json.GetString("message", buffer, sizeof(buffer));
|
||||
PrintToServer("[AdminPanel] Error message: \"%s\"", buffer);
|
||||
} else {
|
||||
PrintToServer("[AdminPanel] Got %d response from server: <unknown json>\n%s", view_as<int>(response.Status), error);
|
||||
}
|
||||
if(response.Status == HTTPStatus_Unauthorized || response.Status == HTTPStatus_Forbidden) {
|
||||
PrintToServer("[AdminPanel] API Key seems to be invalid, killing timer.");
|
||||
if(updateTimer != null)
|
||||
delete updateTimer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject GetObject() {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.SetInt("playerCount", numberOfPlayers);
|
||||
obj.SetString("map", currentMap);
|
||||
obj.SetString("gamemode", gamemode);
|
||||
obj.SetInt("startTime", uptime);
|
||||
obj.SetInt("commonsCount", L4D_GetCommonsCount());
|
||||
obj.SetFloat("fps", 1.0 / GetGameFrameTime());
|
||||
AddFinaleInfo(obj);
|
||||
JSONArray players = GetPlayers();
|
||||
obj.Set("players", players);
|
||||
delete players;
|
||||
obj.SetFloat("refreshInterval", UPDATE_INTERVAL);
|
||||
obj.SetInt("lastUpdateTime", GetTime());
|
||||
return obj;
|
||||
}
|
||||
|
||||
void AddFinaleInfo(JSONObject parentObj) {
|
||||
if(L4D_IsMissionFinalMap()) {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.SetBool("escapeLeaving", L4D_IsFinaleEscapeInProgress());
|
||||
obj.SetInt("finaleStage", L4D2_GetCurrentFinaleStage());
|
||||
parentObj.Set("finaleInfo", obj);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray GetPlayers() {
|
||||
JSONArray players = new JSONArray();
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) >= 2) {
|
||||
JSONObject player = GetPlayer(i);
|
||||
players.Push(player);
|
||||
delete player;
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
Action_BeingHealed = -1,
|
||||
Action_None = 0, // No use action active
|
||||
Action_Healing = 1, // Includes healing yourself or a teammate.
|
||||
Action_AmmoPack = 2, // When deploying the ammo pack that was never added into the game
|
||||
Action_Defibing = 4, // When defib'ing a dead body.
|
||||
Action_GettingDefibed = 5, // When comming back to life from a dead body.
|
||||
Action_DeployIncendiary = 6, // When deploying Incendiary ammo
|
||||
Action_DeployExplosive = 7, // When deploying Explosive ammo
|
||||
Action_PouringGas = 8, // Pouring gas into a generator
|
||||
Action_Cola = 9, // For Dead Center map 2 cola event, when handing over the cola to whitalker.
|
||||
Action_Button = 10, // Such as buttons, timed buttons, generators, etc.
|
||||
Action_UsePointScript = 11 // When using a "point_script_use_target" entity
|
||||
}
|
||||
|
||||
int GetAction(int client) {
|
||||
if(g_icBeingHealed[client]) return Action_BeingHealed;
|
||||
return view_as<int>(L4D2_GetPlayerUseAction(client));
|
||||
}
|
||||
|
||||
enum {
|
||||
Move_UnderAttack = -3,
|
||||
Move_Hanging = -2,
|
||||
Move_Incapped = -1,
|
||||
Move_Idle = 0,
|
||||
Move_Walk = 1,
|
||||
Move_Run = 2,
|
||||
Move_Crouched = 3,
|
||||
Move_Ladder = 4
|
||||
}
|
||||
|
||||
stock float GetPlayerSpeed(int client) {
|
||||
int iVelocity = FindSendPropInfo("CTerrorPlayer", "m_vecVelocity[0]");
|
||||
float velocity[3];
|
||||
GetEntDataVector(client, iVelocity, velocity);
|
||||
return GetVectorLength(velocity, false);
|
||||
}
|
||||
|
||||
int GetPlayerMovement(int client) {
|
||||
MoveType moveType = GetEntityMoveType(client);
|
||||
if(moveType == MOVETYPE_LADDER) return Move_Ladder;
|
||||
else if(GetEntProp(client, Prop_Send, "m_bDucked", 1)) return Move_Crouched;
|
||||
else if(GetEntProp(client, Prop_Send, "m_isIncapacitated", 1)) return Move_Incapped;
|
||||
else if(GetEntProp(client, Prop_Send, "m_isHangingFromLedge", 1)) return Move_Hanging;
|
||||
else if(L4D_GetPinnedSurvivor(client)) return Move_UnderAttack; // TODO: optimize for events
|
||||
float velocity = GetPlayerSpeed(client);
|
||||
if(velocity > 85.0) return Move_Run;
|
||||
else if(velocity > 1.0) return Move_Walk;
|
||||
return Move_Idle;
|
||||
}
|
||||
|
||||
// TODO: pursued by witch
|
||||
enum {
|
||||
pState_BlackAndWhite = 1,
|
||||
pState_InSaferoom = 2,
|
||||
pState_IsCalm = 4,
|
||||
pState_IsBoomed = 8
|
||||
}
|
||||
|
||||
stock bool IsPlayerBoomed(int client) {
|
||||
return (GetEntPropFloat(client, Prop_Send, "m_vomitStart") + 20.1) > GetGameTime();
|
||||
}
|
||||
|
||||
int GetPlayerStates(int client) {
|
||||
int state = 0;
|
||||
if(L4D_IsInLastCheckpoint(client) || L4D_IsInFirstCheckpoint(client))
|
||||
state |= pState_InSaferoom;
|
||||
if(GetEntProp(client, Prop_Send, "m_bIsOnThirdStrike", 1)) state |= pState_BlackAndWhite;
|
||||
if(GetEntProp(client, Prop_Send, "m_isCalm")) state |= pState_IsCalm;
|
||||
if(IsPlayerBoomed(client)) state |= pState_IsBoomed;
|
||||
return state;
|
||||
}
|
||||
|
||||
JSONObject GetPlayer(int client) {
|
||||
int team = GetClientTeam(client);
|
||||
JSONObject player = new JSONObject();
|
||||
player.SetString("steamid", steamidCache[client]);
|
||||
player.SetString("name", nameCache[client]);
|
||||
player.SetInt("team", team);
|
||||
player.SetBool("isAlive", IsPlayerAlive(client));
|
||||
player.SetInt("joinTime", playerJoinTime[client]);
|
||||
player.SetInt("permHealth", GetEntProp(client, Prop_Send, "m_iHealth"));
|
||||
if(team == 2) {
|
||||
if(IsFakeClient(client)) {
|
||||
int idlePlayer = L4D_GetIdlePlayerOfBot(client);
|
||||
if(idlePlayer > 0) {
|
||||
player.SetString("idlePlayerId", steamidCache[idlePlayer]);
|
||||
if(IsClientInGame(idlePlayer)) {
|
||||
JSONObject idlePlayerObj = GetPlayer(idlePlayer);
|
||||
player.Set("idlePlayer", idlePlayerObj);
|
||||
delete idlePlayerObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
player.SetInt("action", GetAction(client));
|
||||
player.SetInt("flowProgress", L4D2_GetVersusCompletionPlayer(client));
|
||||
player.SetFloat("flow", L4D2Direct_GetFlowDistance(client));
|
||||
player.SetBool("isPinned", L4D2_GetInfectedAttacker(client) > 0);
|
||||
player.SetInt("tempHealth", L4D_GetPlayerTempHealth(client));
|
||||
player.SetInt("states", GetPlayerStates(client));
|
||||
player.SetInt("move", GetPlayerMovement(client));
|
||||
player.SetInt("survivor", GetEntProp(client, Prop_Send, "m_survivorCharacter"));
|
||||
JSONArray weapons = GetPlayerWeapons(client);
|
||||
player.Set("weapons", weapons);
|
||||
delete weapons;
|
||||
} else if(team == 3) {
|
||||
player.SetInt("class", L4D2_GetPlayerZombieClass(client));
|
||||
player.SetInt("maxHealth", GetEntProp(client, Prop_Send, "m_iMaxHealth"));
|
||||
int victim = L4D2_GetSurvivorVictim(client);
|
||||
if(victim > 0)
|
||||
player.SetString("pinnedSurvivorId", steamidCache[victim]);
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
JSONArray GetPlayerWeapons(int client) {
|
||||
JSONArray weapons = new JSONArray();
|
||||
static char buffer[64];
|
||||
for(int slot = 0; slot < 6; slot++) {
|
||||
if(GetClientWeaponNameSmart(client, slot, buffer, sizeof(buffer))) {
|
||||
weapons.PushString(buffer);
|
||||
} else {
|
||||
weapons.PushNull();
|
||||
}
|
||||
}
|
||||
return weapons;
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
//Allow MAX_TROLLS to be defined elsewhere
|
||||
#if defined MAX_TROLLS
|
||||
#else
|
||||
#define MAX_TROLLS 50
|
||||
#define MAX_TROLLS 51
|
||||
#endif
|
||||
|
||||
enum trollModifier {
|
||||
|
@ -82,6 +82,18 @@ enum struct Troll {
|
|||
ArrayList flagNames;
|
||||
ArrayList flagPrompts;
|
||||
|
||||
Timer timerFunction;
|
||||
Handle timerHandles[MAXPLAYERS+1];
|
||||
float timerInterval;
|
||||
|
||||
void SetTimer(float interval, Timer timer) {
|
||||
this.timerInterval = interval;
|
||||
this.timerFunction = timer;
|
||||
for(int i = 0; i <= MAXPLAYERS; i++) {
|
||||
this.timerHandles[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasMod(trollModifier mod) {
|
||||
return ((this.mods >> (view_as<int>(mod)) - 1) & 1) == 1;
|
||||
}
|
||||
|
@ -208,15 +220,32 @@ enum struct Troll {
|
|||
|
||||
|
||||
void Toggle(int client, int flags) {
|
||||
ToggleTroll(client, this.name, flags);
|
||||
if(this.IsActive(client)) {
|
||||
this.Disable(client);
|
||||
} else {
|
||||
this.Enable(client, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void Enable(int client, int flags) {
|
||||
EnableTroll(client, this.name, flags);
|
||||
this.activeFlagClients[client] = flags;
|
||||
// If a timer is assigned, start it:
|
||||
if(this.timerHandles[client] != null) {
|
||||
delete this.timerHandles[client];
|
||||
PrintToServer("FTT Debug: Old timer for %N, killing", client);
|
||||
}
|
||||
if(this.timerInterval > 0.0) {
|
||||
this.timerHandles[client] = CreateTimer(this.timerInterval, this.timerFunction, GetClientUserId(client), TIMER_REPEAT);
|
||||
}
|
||||
}
|
||||
|
||||
void Disable(int client) {
|
||||
DisableTroll(client, this.name);
|
||||
this.activeFlagClients[client] = -1;
|
||||
// Stop any running timer:
|
||||
if(this.timerHandles[client] != null) {
|
||||
PrintToServer("FTT Debug: Disabling timer for %N", client);
|
||||
delete this.timerHandles[client];
|
||||
}
|
||||
}
|
||||
|
||||
bool IsActive(int client) {
|
||||
|
@ -244,7 +273,7 @@ void ResetClient(int victim, bool wipe = true) {
|
|||
if(victim == 0 || !IsClientConnected(victim)) return;
|
||||
if(wipe) {
|
||||
for(int i = 0; i <= MAX_TROLLS; i++) {
|
||||
Trolls[i].activeFlagClients[victim] = -1;
|
||||
Trolls[i].Disable(victim);
|
||||
}
|
||||
}
|
||||
noRushingUsSpeed[victim] = 1.0;
|
||||
|
@ -311,18 +340,12 @@ void GetTrollByKeyIndex(int index, Troll troll) {
|
|||
troll = Trolls[index];
|
||||
}
|
||||
|
||||
void ToggleTroll(int client, const char[] name, int flags = 0) {
|
||||
static Troll troll;
|
||||
GetTroll(name, troll);
|
||||
if(troll.IsActive(client))
|
||||
troll.activeFlagClients[client] = -1;
|
||||
else
|
||||
troll.activeFlagClients[client] = flags;
|
||||
}
|
||||
|
||||
void SetTrollFlags(int client, const char[] name, int flags = -1) {
|
||||
int index = GetTrollID(name);
|
||||
Trolls[index].activeFlagClients[client] = flags;
|
||||
if(flags == -1)
|
||||
Trolls[index].Disable(client);
|
||||
else
|
||||
Trolls[index].Enable(client, flags);
|
||||
}
|
||||
|
||||
void ApplyTroll(int victim, const char[] name, int activator, trollModifier modifier, int flags = 0, bool silent = false) {
|
||||
|
@ -334,6 +357,10 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
|
|||
return;
|
||||
}
|
||||
|
||||
if(flags > -1 && Trolls[trollIndex].timerInterval > 0.0) {
|
||||
CreateTimer(Trolls[trollIndex].timerInterval, Trolls[trollIndex].timerFunction, victim, TIMER_REPEAT);
|
||||
}
|
||||
|
||||
if(!silent && SilentMenuSelected[activator]) silent = true;
|
||||
|
||||
static int MetaInverseTrollID;
|
||||
|
|
|
@ -44,7 +44,7 @@ public int Insta_SpecialHandler(Menu menu, MenuAction action, int client, int pa
|
|||
}
|
||||
SpecialType special = view_as<SpecialType>(specialInt);
|
||||
if(inFace) {
|
||||
if(SpawnSpecialForTarget(special, target, view_as<int>(Special_OnTarget))) {
|
||||
if(SpawnSpecialForTarget(special, target, view_as<int>(Special_OnTarget | Special_SpawnDirectOnFailure))) {
|
||||
LogAction(client, target, "\"%L\" spawned Insta-%s™ on \"%L\"", client, SPECIAL_NAMES[specialInt-1], target);
|
||||
CShowActivityEx(client, "[FTT] ", "spawned {olive}Insta-%s™{default} on {olive}%N", SPECIAL_NAMES[specialInt-1], target);
|
||||
} else {
|
||||
|
@ -396,10 +396,9 @@ void ShowTrollMenu(int client, bool isComboList) {
|
|||
menu.SetTitle("Choose a player to troll");
|
||||
static char userid[8], display[64];
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && (hAllowEnemyTeam.BoolValue || GetClientTeam(i) == GetClientTeam(client))) {
|
||||
IntToString(GetClientUserId(i), userid, sizeof(userid));
|
||||
int realPlayer = L4D_GetBotOfIdlePlayer(i);
|
||||
PrintToServer("%d/%d", i, realPlayer);
|
||||
// Incase player is idle, grab their bot instead of them
|
||||
if(realPlayer > 0 && IsClientConnected(realPlayer)) {
|
||||
if(IsPlayerAlive(i))
|
||||
|
|
|
@ -45,6 +45,7 @@ stock bool SpawnSpecialForTarget(SpecialType specialType, int target, int spawnF
|
|||
float minDistance = GetIdealMinDistance(specialType);
|
||||
GetHorizontalPositionFromOrigin(pos, ang, minDistance, testPos);
|
||||
if(!FindSuitablePosition(pos, testPos, minDistance, 100)) {
|
||||
PrintToServer("[FTT] Could not find suitable position, falling back");
|
||||
if(spawnFlags & view_as<int>(Special_SpawnDirectOnFailure))
|
||||
GetClientAbsOrigin(target, pos);
|
||||
else
|
||||
|
|
|
@ -11,6 +11,25 @@ public Action Timer_ThrowTimer(Handle timer) {
|
|||
}
|
||||
int instantCommonRef[MAXPLAYERS+1];
|
||||
|
||||
Action Timer_RandomVelocity(Handle h, int client) {
|
||||
if(!IsClientConnected(client)) {
|
||||
Trolls[t_randomizeVelocityIndex].timerHandles[client] = null;
|
||||
return Plugin_Stop;
|
||||
}
|
||||
float bounds = 50.0;
|
||||
if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 2) bounds = 100.0;
|
||||
else if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 4) bounds = 200.0;
|
||||
else if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 8) bounds = 500.0;
|
||||
else if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 16) bounds = 1000.0;
|
||||
float vel[3];
|
||||
GetEntPropVector(client, Prop_Data, "m_vecVelocity", vel);
|
||||
vel[0] += GetRandomFloat(-bounds, bounds);
|
||||
vel[1] += GetRandomFloat(-bounds, bounds);
|
||||
vel[2] += GetRandomFloat(-100.0, 150.0);
|
||||
SetAbsVelocity(client, vel);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Timer_Main(Handle timer) {
|
||||
static int loopTick;
|
||||
|
||||
|
@ -40,6 +59,19 @@ public Action Timer_Main(Handle timer) {
|
|||
TeleportEntity(i, NULL_VECTOR, ang, NULL_VECTOR);
|
||||
}
|
||||
}
|
||||
if(Trolls[t_randomizeVelocityIndex].IsActive(i)) {
|
||||
float bounds = 50.0;
|
||||
if(Trolls[t_randomizeVelocityIndex].activeFlagClients[i] & 2) bounds = 100.0;
|
||||
else if(Trolls[t_randomizeVelocityIndex].activeFlagClients[i] & 4) bounds = 200.0;
|
||||
else if(Trolls[t_randomizeVelocityIndex].activeFlagClients[i] & 8) bounds = 500.0;
|
||||
else if(Trolls[t_randomizeVelocityIndex].activeFlagClients[i] & 16) bounds = 1000.0;
|
||||
float vel[3];
|
||||
GetEntPropVector(i, Prop_Data, "m_vecVelocity", vel);
|
||||
vel[0] += GetRandomFloat(-bounds, bounds);
|
||||
vel[1] += GetRandomFloat(-bounds, bounds);
|
||||
vel[2] += GetRandomFloat(-100.0, 150.0);
|
||||
SetAbsVelocity(i, vel);
|
||||
}
|
||||
if(Trolls[slowDrainIndex].IsActive(i)) {
|
||||
if(loopTick % 4 == 0) {
|
||||
int hp = GetClientHealth(i);
|
||||
|
|
|
@ -4,6 +4,7 @@ int slipperyShoesIndex = 0;
|
|||
int stickyGooIndex = 0;
|
||||
int invertedTrollIndex;
|
||||
int t_randomizeAnglesIndex;
|
||||
int t_randomizeVelocityIndex;
|
||||
// int fireSpitMagnetTrollIndex;
|
||||
|
||||
void SetupTrolls() {
|
||||
|
@ -45,7 +46,7 @@ void SetupTrolls() {
|
|||
Trolls[index].AddFlag("30% Movement Speed", false);
|
||||
Trolls[index].AddFlag("0% Movement Speed", false);
|
||||
stickyGooIndex = index;
|
||||
index = SetupTroll("Vocalize Specials", "Spawn commons on special vocals", TrollMod_Constant);
|
||||
index = SetupTroll("Vocalize Specials", "Spawn commons on special vocals", TrollMod_Constant)
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Mute Vocalization", true);
|
||||
Trolls[index].AddFlag("Do not mute", false);
|
||||
|
@ -84,6 +85,7 @@ void SetupTrolls() {
|
|||
// CATEGORY: Items
|
||||
SetCategory("Items");
|
||||
SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
|
||||
|
||||
index = SetupTroll("Spicy Gas", "Gascans player picks up just ignite. Magic.", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Always (100%)", false);
|
||||
|
@ -204,6 +206,15 @@ void SetupTrolls() {
|
|||
Trolls[index].AddFlag("Painful", false); //8
|
||||
Trolls[index].AddFlag("Seizure", false); //16
|
||||
t_randomizeAnglesIndex = index;
|
||||
index = SetupTroll("Randomize Velocity", "Randomly change their velocity", TrollMod_Constant);
|
||||
Trolls[index].SetTimer(0.1, Timer_RandomVelocity);
|
||||
Trolls[index].AddCustomFlagPrompt("Frequency:", false);
|
||||
Trolls[index].AddFlag("Loose", true); //1
|
||||
Trolls[index].AddFlag("Slippery", false); //2
|
||||
Trolls[index].AddFlag("Earthquake", false); //4
|
||||
Trolls[index].AddFlag("Severe Earthquake", false); //8
|
||||
Trolls[index].AddFlag("Bouncy Castle", false); //16
|
||||
t_randomizeVelocityIndex = index;
|
||||
|
||||
|
||||
/// CATEGORY: MISC
|
||||
|
@ -230,6 +241,7 @@ void SetupTrolls() {
|
|||
// Initialize the default flag values to -1
|
||||
for(int i = 0; i <= MAX_TROLLS; i++) {
|
||||
for(int j = 1; j <= MAXPLAYERS; j++) {
|
||||
Trolls[i].timerHandles[j] = null;
|
||||
Trolls[i].activeFlagClients[j] = -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ Handle g_hWitchAttack;
|
|||
int g_iWitchAttackVictim;
|
||||
Handle hThrowTimer;
|
||||
|
||||
ConVar hAllowEnemyTeam;
|
||||
ConVar hThrowItemInterval;
|
||||
ConVar hAutoPunish;
|
||||
ConVar hMagnetChance;
|
||||
|
|
|
@ -895,4 +895,43 @@ stock int GetSinglePlayer(int client, const char[] input, int flags = 0) {
|
|||
return -1;
|
||||
}
|
||||
return target_list[0];
|
||||
}
|
||||
}
|
||||
|
||||
static int _glowColor[3] = { 255, 255, 255 };
|
||||
|
||||
stock void GlowPoint(const float pos[3], float lifetime = 5.0) {
|
||||
PrecacheModel("models/props_fortifications/orange_cone001_reference.mdl");
|
||||
int entity = CreateEntityByName("prop_dynamic");
|
||||
DispatchKeyValue(entity, "disableshadows", "1");
|
||||
DispatchKeyValue(entity, "model", "models/props_fortifications/orange_cone001_reference.mdl");
|
||||
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
|
||||
DispatchSpawn(entity);
|
||||
L4D2_SetEntityGlow(entity, L4D2Glow_Constant, 10000, 0, _glowColor, false);
|
||||
CreateTimer(lifetime, Timer_KillEntity, entity);
|
||||
}
|
||||
|
||||
stock void GlowEntity(int entity, float lifetime = 10.0) {
|
||||
L4D2_SetEntityGlow(entity, L4D2Glow_Constant, 10000, 0, _glowColor, false);
|
||||
CreateTimer(lifetime, Timer_ClearGlow, EntIndexToEntRef(entity));
|
||||
}
|
||||
|
||||
Action Timer_ClearGlow(Handle h, int ref) {
|
||||
L4D2_RemoveEntityGlow(ref);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
stock bool CompareVector(const float a[3], const float b[3], float delta) {
|
||||
return a[0] < b[0] + delta && a[0] > b[0] - delta &&
|
||||
a[1] < b[1] + delta && a[1] > b[1] - delta &&
|
||||
a[2] < b[2] + delta && a[2] > b[2] - delta
|
||||
}
|
||||
|
||||
stock void CalculateWorldPosition(int entity, float pos[3]) {
|
||||
float mins[3], maxs[3];
|
||||
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", pos);
|
||||
GetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
|
||||
GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs);
|
||||
pos[0] = pos[0] + (mins[0] + maxs[0]) * 0.5;
|
||||
pos[1] = pos[1] + (mins[1] + maxs[1]) * 0.5;
|
||||
pos[2] = pos[2] + (mins[2] + maxs[2]) * 0.5;
|
||||
}
|
||||
|
|
|
@ -12,15 +12,13 @@ enum SocketType {
|
|||
SOCKET_RAW
|
||||
}
|
||||
|
||||
enum {
|
||||
EMPTY_HOST = 1,
|
||||
NO_HOST,
|
||||
CONNECT_ERROR,
|
||||
SEND_ERROR,
|
||||
BIND_ERROR,
|
||||
RECV_ERROR,
|
||||
LISTEN_ERROR
|
||||
}
|
||||
#define EMPTY_HOST 1
|
||||
#define NO_HOST 2
|
||||
#define CONNECT_ERROR 3
|
||||
#define SEND_ERROR 4
|
||||
#define BIND_ERROR 5
|
||||
#define RECV_ERROR 6
|
||||
#define LISTEN_ERROR 7
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -47,7 +45,7 @@ enum SocketOption {
|
|||
* @note don't forget to set your buffer sizes at least to the value passed to this function, but
|
||||
* always at least to 4096
|
||||
*
|
||||
* @param int 0(=default) to disable or max. chunk size including \0 terminator in bytes
|
||||
* @param cell_t 0(=default) to disable or max. chunk size including \0 terminator in bytes
|
||||
* @return bool true on success
|
||||
*/
|
||||
ConcatenateCallbacks = 1,
|
||||
|
@ -75,7 +73,7 @@ enum SocketOption {
|
|||
*
|
||||
* @note this option will affect all sockets from all plugins, use it with caution!
|
||||
*
|
||||
* @param int maximum amount of callbacks per gameframe
|
||||
* @param cell_t maximum amount of callbacks per gameframe
|
||||
* @return bool true on success
|
||||
*/
|
||||
CallbacksPerFrame,
|
||||
|
@ -107,7 +105,7 @@ enum SocketOption {
|
|||
* This option specifies how long a socket will wait if it's being closed and its send buffer is
|
||||
* still filled. This is a wrapper for setting SO_LINGER.
|
||||
*
|
||||
* @param int 0 (=default) to disable or time in s
|
||||
* @param cell_t 0 (=default) to disable or time in s
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketLinger,
|
||||
|
@ -123,7 +121,7 @@ enum SocketOption {
|
|||
* This option specifies how large the send buffer will be. This is a wrapper for setting
|
||||
* SO_SNDBUF.
|
||||
*
|
||||
* @param int size in bytes
|
||||
* @param cell_t size in bytes
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketSendBuffer,
|
||||
|
@ -131,7 +129,7 @@ enum SocketOption {
|
|||
* This option specifies how large the receive buffer will be. This is a wrapper for setting
|
||||
* SO_RCVBUF.
|
||||
*
|
||||
* @param int size in bytes
|
||||
* @param cell_t size in bytes
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketReceiveBuffer,
|
||||
|
@ -150,7 +148,7 @@ enum SocketOption {
|
|||
*
|
||||
* @note this can probably block the extension, use it with caution!
|
||||
*
|
||||
* @param int size in bytes
|
||||
* @param cell_t size in bytes
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketReceiveLowWatermark,
|
||||
|
@ -158,7 +156,7 @@ enum SocketOption {
|
|||
* This option specifies how long a socket will try to receive data before it times out and
|
||||
* processes the data. This is a wrapper for setting SO_RCVTIMEO.
|
||||
*
|
||||
* @param int 0 (=default) to disable or time in ms
|
||||
* @param cell_t 0 (=default) to disable or time in ms
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketReceiveTimeout,
|
||||
|
@ -168,7 +166,7 @@ enum SocketOption {
|
|||
*
|
||||
* @note this can probably block the extension, use it with caution!
|
||||
*
|
||||
* @param int size in bytes
|
||||
* @param cell_t size in bytes
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketSendLowWatermark,
|
||||
|
@ -176,7 +174,7 @@ enum SocketOption {
|
|||
* This option specifies how long a socket will try to send data before it times out and
|
||||
* retries it later. This is a wrapper for setting SO_SNDTIMEO.
|
||||
*
|
||||
* @param int 0 (=default) to disable or time in ms
|
||||
* @param cell_t 0 (=default) to disable or time in ms
|
||||
* @return bool true on success
|
||||
*/
|
||||
SocketSendTimeout,
|
||||
|
@ -189,173 +187,12 @@ enum SocketOption {
|
|||
DebugMode
|
||||
}
|
||||
|
||||
// Methodmap
|
||||
methodmap Socket < Handle {
|
||||
/**
|
||||
* Creates a new socket.
|
||||
*
|
||||
* @note this function may be relatively expensive, reuse sockets if possible
|
||||
*
|
||||
* @param SocketType protocol The protocol to use, SOCKET_TCP is default
|
||||
* @param SocketErrorCB efunc The error callback
|
||||
* @return Handle The socket handle. Returns INVALID_HANDLE on failure
|
||||
*/
|
||||
public native Socket(SocketType protocol=SOCKET_TCP, SocketErrorCB efunc);
|
||||
|
||||
/**
|
||||
* Binds the socket to a local address
|
||||
*
|
||||
* @param String hostname The hostname (or IP) to bind the socket to.
|
||||
* @param int port The port to bind the socket to.
|
||||
* @return bool true on success
|
||||
*/
|
||||
public native bool Bind(const char[] hostname, int port);
|
||||
|
||||
/**
|
||||
* Connects a socket
|
||||
*
|
||||
* @note this native is threaded, it may be still running after it executed, use the connect callback
|
||||
* @note invokes the SocketError callback with errorType = CONNECT_ERROR or EMPTY_HOST if it fails
|
||||
* @note invokes the SocketConnect callback if it succeeds
|
||||
*
|
||||
* @param SocketConnectCB cfunc The connect callback
|
||||
* @param SocketReceiveCB rfunc The receive callback
|
||||
* @param SocketDisconnectCB dfunc The disconnect callback
|
||||
* @param String hostname The hostname (or IP) to connect to.
|
||||
* @param int port The port to connect to.
|
||||
*/
|
||||
public native void Connect(SocketConnectCB cfunc, SocketReceiveCB rfunc, SocketDisconnectCB dfunc, const char[] hostname, int port);
|
||||
|
||||
/**
|
||||
* Disconnects a socket
|
||||
*
|
||||
* @note this will not close the handle, the socket will be reset to a state similar to after SocketCreate()
|
||||
* @note this won't trigger any disconnect/error callbacks
|
||||
*
|
||||
* @return bool true on success
|
||||
*/
|
||||
public native bool Disconnect();
|
||||
|
||||
/**
|
||||
* Makes a socket listen for incoming connections
|
||||
*
|
||||
* @param SocketIncomingCB ifunc The callback for incoming connections
|
||||
* @return bool true on success
|
||||
*/
|
||||
public native bool Listen(SocketIncomingCB ifunc);
|
||||
|
||||
/**
|
||||
* Sends data through the socket.
|
||||
*
|
||||
* @note specify size for binary safe operation
|
||||
* @note if size is not specified the \0 terminator will not be included
|
||||
* @note This native is threaded, it may be still running after it executed (not atomic).
|
||||
* @note Use the SendqueueEmpty callback to determine when all data has been successfully sent.
|
||||
* @note The socket extension will ensure that the data will be send in the correct order and split
|
||||
* the data if required.
|
||||
*
|
||||
* @param String data The data to send.
|
||||
*/
|
||||
public native void Send(const char[] data, int size = -1);
|
||||
|
||||
/**
|
||||
* Sends UDP data through the socket to a specific destination.
|
||||
*
|
||||
* @note specify size for binary safe operation
|
||||
* @note if size is not specified the \0 terminator will not be included
|
||||
* @note This native is threaded, it may be still running after it executed (not atomic).
|
||||
* @note Use the SendqueueEmpty callback to determine when all data has been successfully sent.
|
||||
* @note The socket extension will ensure that the data will be send in the correct order and split
|
||||
* the data if required.
|
||||
*
|
||||
* @param String data The data to send.
|
||||
* @param String hostname The hostname (or IP) to send to.
|
||||
* @param int port The port to send to.
|
||||
*/
|
||||
public native void SendTo(const char[] data, int size = -1, const char[] hostname, int port);
|
||||
|
||||
/**
|
||||
* Set a socket option.
|
||||
*
|
||||
* @param SocketOption option The option to modify (see enum SocketOption for details).
|
||||
* @param int value The value to set the option to.
|
||||
* @return int 1 on success.
|
||||
*/
|
||||
public native int SetOption(SocketOption option, int value);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket receives data
|
||||
*
|
||||
* @note this is only useful and required for child-sockets spawned by listen-sockets
|
||||
* (otherwise you already set it in SocketConnect())
|
||||
*
|
||||
* @param SocketReceiveCB rfunc The receive callback
|
||||
*/
|
||||
public native void SetReceiveCallback(SocketReceiveCB rfunc);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket sent all items in its send queue
|
||||
*
|
||||
* @note this must be called AFTER sending (queueing) the data
|
||||
* @note if no send-data is queued this will fire the callback itself
|
||||
* @note the callback is guaranteed to fire
|
||||
*
|
||||
* @param SocketDisconnectCB dfunc The disconnect callback
|
||||
*/
|
||||
public native void SetSendqueueEmptyCallback(SocketSendqueueEmptyCB sfunc);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket was properly disconnected by the remote side
|
||||
*
|
||||
* @note this is only useful and required for child-sockets spawned by listen-sockets
|
||||
* (otherwise you already set it in SocketConnect())
|
||||
*
|
||||
* @param SocketDisconnectCB dfunc The disconnect callback
|
||||
*/
|
||||
public native void SetDisconnectCallback(SocketDisconnectCB dfunc);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket triggered an error
|
||||
*
|
||||
* @note this is only useful and required for child-sockets spawned by listen-sockets
|
||||
* (otherwise you already set it in SocketCreate())
|
||||
*
|
||||
* @param SocketErrorCB efunc The error callback
|
||||
*/
|
||||
public native void SetErrorCallback(SocketErrorCB efunc);
|
||||
|
||||
/**
|
||||
* Sets the argument being passed to callbacks
|
||||
*
|
||||
* @param any arg The argument to set
|
||||
*/
|
||||
public native void SetArg(any arg);
|
||||
|
||||
/**
|
||||
* Retrieve the local system's hostname as the command "hostname" does.
|
||||
*
|
||||
* @param dest Destination string buffer to copy to.
|
||||
* @param destLen Destination buffer length (includes null terminator).
|
||||
*
|
||||
* @return 1 on success
|
||||
*/
|
||||
public static native int GetHostName(char[] dest, int destLen);
|
||||
|
||||
/**
|
||||
* Returns whether a socket is connected or not.
|
||||
*
|
||||
* @return bool The connection status
|
||||
*/
|
||||
property bool Connected {
|
||||
public native get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/******************************************* callbacks *******************************************/
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* triggered if a normal sockets finished connecting and is ready to be used
|
||||
*
|
||||
|
@ -363,20 +200,26 @@ methodmap Socket < Handle {
|
|||
* @param arg The argument set by SocketSetArg()
|
||||
* @noreturn
|
||||
*/
|
||||
typedef SocketConnectCB = function void (Socket socket, any arg);
|
||||
funcenum SocketConnectCB
|
||||
{
|
||||
public(Handle:socket, any:arg)
|
||||
};
|
||||
|
||||
/**
|
||||
* triggered if a listening socket received an incoming connection and is ready to be used
|
||||
*
|
||||
* @note The child-socket won't work until receive-, disconnect-, and errorcallback for it are set.
|
||||
*
|
||||
* @param Socket socket The socket handle pointing to the calling listen-socket
|
||||
* @param Socket newSocket The socket handle to the newly spawned child socket
|
||||
* @param Handle socket The socket handle pointing to the calling listen-socket
|
||||
* @param Handle newSocket The socket handle to the newly spawned child socket
|
||||
* @param String remoteIP The remote IP
|
||||
* @param any arg The argument set by SocketSetArg() for the listen-socket
|
||||
* @noreturn
|
||||
*/
|
||||
typedef SocketIncomingCB = function void (Socket socket, Socket newSocket, const char[] remoteIP, int remotePort, any arg);
|
||||
funcenum SocketIncomingCB
|
||||
{
|
||||
public(Handle:socket, Handle:newSocket, const String:remoteIP[], remotePort, any:arg)
|
||||
};
|
||||
|
||||
/**
|
||||
* triggered if a socket receives data
|
||||
|
@ -386,46 +229,59 @@ typedef SocketIncomingCB = function void (Socket socket, Socket newSocket, const
|
|||
* @note if not set otherwise by SocketSetOption(..., ConcatenateCallbacks, ...) receiveData will
|
||||
* never be longer than 4096 characters including \0 terminator
|
||||
*
|
||||
* @param Socket socket The socket handle pointing to the calling socket
|
||||
* @param Handle socket The socket handle pointing to the calling socket
|
||||
* @param String receiveData The data which arrived, 0-terminated at receiveData[dataSize]
|
||||
* @param int dataSize The length of the arrived data excluding the 0-termination
|
||||
* @param cell_t dataSize The length of the arrived data excluding the 0-termination
|
||||
* @param any arg The argument set by SocketSetArg() for the socket
|
||||
* @noreturn
|
||||
*/
|
||||
typedef SocketReceiveCB = function void (Socket socket, const char[] receiveData, const int dataSize, any arg);
|
||||
funcenum SocketReceiveCB
|
||||
{
|
||||
public(Handle:socket, const String:receiveData[], const dataSize, any:arg)
|
||||
};
|
||||
|
||||
/**
|
||||
* called after a socket sent all items in its send queue successfully
|
||||
*
|
||||
* @param Socket socket The socket handle pointing to the calling socket
|
||||
* @param Handle socket The socket handle pointing to the calling socket
|
||||
* @param any arg The argument set by SocketSetArg() for the socket
|
||||
* @noreturn
|
||||
*/
|
||||
typedef SocketSendqueueEmptyCB = function void (Socket socket, any arg);
|
||||
funcenum SocketSendqueueEmptyCB
|
||||
{
|
||||
public(Handle:socket, any:arg)
|
||||
};
|
||||
|
||||
/**
|
||||
* called if a socket has been properly disconnected by the remote side
|
||||
*
|
||||
* @note You should call CloseHandle(socket) or reuse the socket before this function ends
|
||||
*
|
||||
* @param Socket socket The socket handle pointing to the calling socket
|
||||
* @param Handle socket The socket handle pointing to the calling socket
|
||||
* @param any arg The argument set by SocketSetArg() for the socket
|
||||
* @noreturn
|
||||
*/
|
||||
typedef SocketDisconnectCB = function void (Socket socket, any arg);
|
||||
funcenum SocketDisconnectCB
|
||||
{
|
||||
public(Handle:socket, any:arg)
|
||||
};
|
||||
|
||||
/**
|
||||
* called if an unrecoverable error occured, close the socket without an additional call to a disconnect callback
|
||||
*
|
||||
* @note You should call CloseHandle(socket) or reuse the socket before this function ends
|
||||
*
|
||||
* @param Socket socket The socket handle pointing to the calling socket
|
||||
* @param int errorType The error type, see defines above
|
||||
* @param int errorNum The errno, see errno.h for details
|
||||
* @param Handle socket The socket handle pointing to the calling socket
|
||||
* @param cell_t errorType The error type, see defines above
|
||||
* @param cell_t errorNum The errno, see errno.h for details
|
||||
* @param any arg The argument set by SocketSetArg() for the socket
|
||||
* @noreturn
|
||||
*/
|
||||
typedef SocketErrorCB = function void (Socket socket, const int errorType, const int errorNum, any arg);
|
||||
funcenum SocketErrorCB
|
||||
{
|
||||
public(Handle:socket, const errorType, const errorNum, any:arg)
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/******************************************** natives ********************************************/
|
||||
|
@ -438,7 +294,7 @@ typedef SocketErrorCB = function void (Socket socket, const int errorType, const
|
|||
* @param socket Socket handle to check
|
||||
* @return bool The connection status
|
||||
*/
|
||||
native bool SocketIsConnected(Handle socket);
|
||||
native bool:SocketIsConnected(Handle:socket);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -448,19 +304,18 @@ native bool SocketIsConnected(Handle socket);
|
|||
*
|
||||
* @param SocketType protocol The protocol to use, SOCKET_TCP is default
|
||||
* @param SocketErrorCB efunc The error callback
|
||||
* @return Socket The socket handle. Returns INVALID_HANDLE on failure
|
||||
* @return Handle The socket handle. Returns INVALID_HANDLE on failure
|
||||
*/
|
||||
native Socket SocketCreate(SocketType protocol=SOCKET_TCP, SocketErrorCB efunc);
|
||||
native Handle:SocketCreate(SocketType:protocol=SOCKET_TCP, SocketErrorCB:efunc);
|
||||
|
||||
/**
|
||||
* Binds the socket to a local address
|
||||
*
|
||||
* @param Handle socket The handle of the socket to be used.
|
||||
* @param String hostname The hostname (or IP) to bind the socket to.
|
||||
* @param int port The port to bind the socket to.
|
||||
* @param Handle socket The handle of the socket to be used.
* @param String hostname The hostname (or IP) to bind the socket to.
|
||||
* @param cell_t port The port to bind the socket to.
|
||||
* @return bool true on success
|
||||
*/
|
||||
native bool SocketBind(Handle socket, const char[] hostname, int port);
|
||||
native bool:SocketBind(Handle:socket, const String:hostname[], port);
|
||||
|
||||
/**
|
||||
* Connects a socket
|
||||
|
@ -472,12 +327,11 @@ native bool SocketBind(Handle socket, const char[] hostname, int port);
|
|||
* @param Handle socket The handle of the socket to be used.
|
||||
* @param SocketConnectCB cfunc The connect callback
|
||||
* @param SocketReceiveCB rfunc The receive callback
|
||||
* @param SocketDisconnectCB dfunc The disconnect callback
|
||||
* @param String hostname The hostname (or IP) to connect to.
|
||||
* @param int port The port to connect to.
|
||||
* @param SocketDisconnectCB dfunc The disconnect callback
* @param String hostname The hostname (or IP) to connect to.
|
||||
* @param cell_t port The port to connect to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketConnect(Handle socket, SocketConnectCB cfunc, SocketReceiveCB rfunc, SocketDisconnectCB dfunc, const char[] hostname, int port);
|
||||
native SocketConnect(Handle:socket, SocketConnectCB:cfunc, SocketReceiveCB:rfunc, SocketDisconnectCB:dfunc, const String:hostname[], port);
|
||||
|
||||
/**
|
||||
* Disconnects a socket
|
||||
|
@ -487,7 +341,7 @@ native void SocketConnect(Handle socket, SocketConnectCB cfunc, SocketReceiveCB
|
|||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native bool SocketDisconnect(Handle socket);
|
||||
native bool:SocketDisconnect(Handle:socket);
|
||||
|
||||
/**
|
||||
* Makes a socket listen for incoming connections
|
||||
|
@ -496,7 +350,7 @@ native bool SocketDisconnect(Handle socket);
|
|||
* @param SocketIncomingCB ifunc The callback for incoming connections
|
||||
* @return bool true on success
|
||||
*/
|
||||
native bool SocketListen(Handle socket, SocketIncomingCB ifunc);
|
||||
native bool:SocketListen(Handle:socket, SocketIncomingCB:ifunc);
|
||||
|
||||
/**
|
||||
* Sends data through the socket.
|
||||
|
@ -510,12 +364,10 @@ native bool SocketListen(Handle socket, SocketIncomingCB ifunc);
|
|||
*
|
||||
* @param Handle socket The handle of the socket to be used.
|
||||
* @param String data The data to send.
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSend(Handle socket, const char[] data, int size=-1);
|
||||
* @noreturn
*/
|
||||
native SocketSend(Handle:socket, const String:data[], size=-1);
|
||||
|
||||
/**
|
||||
* Sends UDP data through the socket to a specific destination.
|
||||
/**
* Sends UDP data through the socket to a specific destination.
|
||||
*
|
||||
* @note specify size for binary safe operation
|
||||
* @note if size is not specified the \0 terminator will not be included
|
||||
|
@ -527,10 +379,9 @@ native void SocketSend(Handle socket, const char[] data, int size=-1);
|
|||
* @param Handle socket The handle of the socket to be used.
|
||||
* @param String data The data to send.
|
||||
* @param String hostname The hostname (or IP) to send to.
|
||||
* @param int port The port to send to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSendTo(Handle socket, const char[] data, int size=-1, const char[] hostname, int port);
|
||||
* @param cell_t port The port to send to.
|
||||
* @noreturn
*/
|
||||
native SocketSendTo(Handle:socket, const String:data[], size=-1, const String:hostname[], port);
|
||||
|
||||
/**
|
||||
* Set a socket option.
|
||||
|
@ -538,9 +389,8 @@ native void SocketSendTo(Handle socket, const char[] data, int size=-1, const ch
|
|||
* @param Handle socket The handle of the socket to be used. May be INVALID_HANDLE if not essential.
|
||||
* @param SocketOption option The option to modify (see enum SocketOption for details).
|
||||
* @param cellt_ value The value to set the option to.
|
||||
* @return int 1 on success.
|
||||
*/
|
||||
native int SocketSetOption(Handle socket, SocketOption option, int value);
|
||||
* @return cell_t 1 on success.
*/
|
||||
native SocketSetOption(Handle:socket, SocketOption:option, value);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -553,7 +403,7 @@ native int SocketSetOption(Handle socket, SocketOption option, int value);
|
|||
* @param SocketReceiveCB rfunc The receive callback
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSetReceiveCallback(Handle socket, SocketReceiveCB rfunc);
|
||||
native SocketSetReceiveCallback(Handle:socket, SocketReceiveCB:rfunc);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket sent all items in its send queue
|
||||
|
@ -566,7 +416,7 @@ native void SocketSetReceiveCallback(Handle socket, SocketReceiveCB rfunc);
|
|||
* @param SocketDisconnectCB dfunc The disconnect callback
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSetSendqueueEmptyCallback(Handle socket, SocketSendqueueEmptyCB sfunc);
|
||||
native SocketSetSendqueueEmptyCallback(Handle:socket, SocketSendqueueEmptyCB:sfunc);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket was properly disconnected by the remote side
|
||||
|
@ -578,7 +428,7 @@ native void SocketSetSendqueueEmptyCallback(Handle socket, SocketSendqueueEmptyC
|
|||
* @param SocketDisconnectCB dfunc The disconnect callback
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSetDisconnectCallback(Handle socket, SocketDisconnectCB dfunc);
|
||||
native SocketSetDisconnectCallback(Handle:socket, SocketDisconnectCB:dfunc);
|
||||
|
||||
/**
|
||||
* Defines the callback function for when the socket triggered an error
|
||||
|
@ -590,7 +440,7 @@ native void SocketSetDisconnectCallback(Handle socket, SocketDisconnectCB dfunc)
|
|||
* @param SocketErrorCB efunc The error callback
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSetErrorCallback(Handle socket, SocketErrorCB efunc);
|
||||
native SocketSetErrorCallback(Handle:socket, SocketErrorCB:efunc);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -600,7 +450,7 @@ native void SocketSetErrorCallback(Handle socket, SocketErrorCB efunc);
|
|||
* @param any arg The argument to set
|
||||
* @noreturn
|
||||
*/
|
||||
native void SocketSetArg(Handle socket, any arg);
|
||||
native SocketSetArg(Handle:socket, any:arg);
|
||||
|
||||
/**
|
||||
* Retrieve the local system's hostname as the command "hostname" does.
|
||||
|
@ -610,12 +460,12 @@ native void SocketSetArg(Handle socket, any arg);
|
|||
*
|
||||
* @return 1 on success
|
||||
*/
|
||||
native int SocketGetHostName(char[] dest, int destLen);
|
||||
native SocketGetHostName(String:dest[], destLen);
|
||||
|
||||
/**
|
||||
* _________________Do not edit below this line!_______________________
|
||||
*/
|
||||
public Extension __ext_socket =
|
||||
public Extension:__ext_smsock =
|
||||
{
|
||||
name = "Socket",
|
||||
file = "socket.ext",
|
||||
|
@ -630,39 +480,3 @@ public Extension __ext_socket =
|
|||
required = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_EXTENSIONS
|
||||
public void __ext_socket_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Socket.Socket");
|
||||
MarkNativeAsOptional("Socket.Bind");
|
||||
MarkNativeAsOptional("Socket.Connect");
|
||||
MarkNativeAsOptional("Socket.Disconnect");
|
||||
MarkNativeAsOptional("Socket.Listen");
|
||||
MarkNativeAsOptional("Socket.Send");
|
||||
MarkNativeAsOptional("Socket.SendTo");
|
||||
MarkNativeAsOptional("Socket.SetOption");
|
||||
MarkNativeAsOptional("Socket.SetReceiveCallback");
|
||||
MarkNativeAsOptional("Socket.SetSendqueueEmptyCallback");
|
||||
MarkNativeAsOptional("Socket.SetDisconnectCallback");
|
||||
MarkNativeAsOptional("Socket.SetErrorCallback");
|
||||
MarkNativeAsOptional("Socket.SetArg");
|
||||
MarkNativeAsOptional("Socket.GetHostName");
|
||||
MarkNativeAsOptional("Socket.Connected.get");
|
||||
MarkNativeAsOptional("SocketIsConnected");
|
||||
MarkNativeAsOptional("SocketCreate");
|
||||
MarkNativeAsOptional("SocketBind");
|
||||
MarkNativeAsOptional("SocketConnect");
|
||||
MarkNativeAsOptional("SocketDisconnect");
|
||||
MarkNativeAsOptional("SocketListen");
|
||||
MarkNativeAsOptional("SocketSend");
|
||||
MarkNativeAsOptional("SocketSendTo");
|
||||
MarkNativeAsOptional("SocketSetOption");
|
||||
MarkNativeAsOptional("SocketSetReceiveCallback");
|
||||
MarkNativeAsOptional("SocketSetSendqueueEmptyCallback");
|
||||
MarkNativeAsOptional("SocketSetDisconnectCallback");
|
||||
MarkNativeAsOptional("SocketSetErrorCallback");
|
||||
MarkNativeAsOptional("SocketSetArg");
|
||||
MarkNativeAsOptional("SocketGetHostName");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -371,9 +371,7 @@ public void OnClientPutInServer(int client) {
|
|||
}
|
||||
|
||||
public void OnClientDisconnect(int client) {
|
||||
if(!IsFakeClient(client)) {
|
||||
SaveInventory(client);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPluginEnd() {
|
||||
|
@ -1614,7 +1612,7 @@ void SaveInventory(int client) {
|
|||
PrintDebug(DEBUG_GENERIC, "Saving inventory for %N", client);
|
||||
PlayerInventory inventory;
|
||||
inventory.timestamp = GetTime();
|
||||
inventory.isAlive = IsPlayerAlive(client);
|
||||
inventory.isAlive = IsClientInGame(client) && IsPlayerAlive(client);
|
||||
playerData[client].state = State_Active;
|
||||
GetClientAbsOrigin(client, inventory.location);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
//#define DEBUG
|
||||
|
||||
#define MAIN_TIMER_INTERVAL_S 5.0
|
||||
#define MAIN_TIMER_INTERVAL_S 4.0
|
||||
#define PLUGIN_VERSION "1.0"
|
||||
#define ANTI_RUSH_DEFAULT_FREQUENCY 20.0
|
||||
#define ANTI_RUSH_FREQ_INC 0.75
|
||||
|
@ -20,7 +20,6 @@
|
|||
#include <multicolors>
|
||||
#tryinclude <l4d_anti_rush>
|
||||
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "L4D2 Feed The Trolls",
|
||||
|
@ -67,6 +66,7 @@ public void OnPluginStart() {
|
|||
g_hWitchAttack = EndPrepSDKCall();
|
||||
delete data;
|
||||
|
||||
hAllowEnemyTeam = CreateConVar("sm_ftt_select_enemy", "0", "Allow applying trolls to enemy teams", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
hThrowItemInterval = CreateConVar("sm_ftt_throw_interval", "30", "The interval in seconds to throw items. 0 to disable", FCVAR_NONE, true, 0.0);
|
||||
hThrowItemInterval.AddChangeHook(Change_ThrowInterval);
|
||||
hAutoPunish = CreateConVar("sm_ftt_autopunish_action", "0", "Setup automatic punishment of players. Add bits together\n0=Disabled, 1=Tank magnet, 2=Special magnet, 4=Swarm, 8=InstantVomit", FCVAR_NONE, true, 0.0);
|
||||
|
@ -208,15 +208,15 @@ bool IsPlayerFarDistance(int client, float distance) {
|
|||
}
|
||||
|
||||
BehaviorAction CreateWitchAttackAction(int target = 0) {
|
||||
BehaviorAction action = ActionsManager.Allocate(18556);
|
||||
SDKCall(g_hWitchAttack, action, target);
|
||||
return action;
|
||||
BehaviorAction action = ActionsManager.Allocate(18556);
|
||||
SDKCall(g_hWitchAttack, action, target);
|
||||
return action;
|
||||
}
|
||||
|
||||
Action OnWitchActionUpdate(BehaviorAction action, int actor, float interval, ActionResult result) {
|
||||
/* Change to witch attack */
|
||||
result.type = CHANGE_TO;
|
||||
result.action = CreateWitchAttackAction(g_iWitchAttackVictim);
|
||||
result.SetReason("FTT");
|
||||
return Plugin_Handled;
|
||||
/* Change to witch attack */
|
||||
result.type = CHANGE_TO;
|
||||
result.action = CreateWitchAttackAction(g_iWitchAttackVictim);
|
||||
result.SetReason("FTT");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
|
|
@ -198,6 +198,7 @@ enum struct SceneData {
|
|||
ArrayList variants;
|
||||
|
||||
void Cleanup() {
|
||||
g_MapData.activeScenes.Clear();
|
||||
SceneVariantData choice;
|
||||
for(int i = 0; i < this.variants.Length; i++) {
|
||||
this.variants.GetArray(i, choice);
|
||||
|
|
|
@ -386,10 +386,12 @@ public void Event_FinaleStart(Event event, const char[] name, bool dontBroadcast
|
|||
}
|
||||
}
|
||||
public void Frame_SwapSurvivor(int client) {
|
||||
SwapL4D1Survivor(client, true);
|
||||
if(IsClientConnected(client) && IsClientInGame(client))
|
||||
SwapL4D1Survivor(client, true);
|
||||
}
|
||||
public void Frame_RevertSwappedSurvivor(int client) {
|
||||
RevertSwappedSurvivor(client);
|
||||
if(IsClientConnected(client) && IsClientInGame(client))
|
||||
RevertSwappedSurvivor(client);
|
||||
}
|
||||
|
||||
void SwapL4D1Survivor(int client, bool showMessage) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue