Update updated part of README.md

This commit is contained in:
Jackzie 2021-04-20 21:44:43 -05:00
parent 73fa3ea30f
commit f1ad9f3865
No known key found for this signature in database
GPG key ID: 1E834FE36520537A
21 changed files with 4934 additions and 89 deletions

View file

@ -24,7 +24,7 @@ public Plugin myinfo =
url = PLUGIN_URL
};
bool g_EnteredCheckpoint = false;
ConVar g_EnteredCheckpoint;
public void OnPluginStart()
{
@ -34,28 +34,31 @@ public void OnPluginStart()
SetFailState("This plugin is for L4D/L4D2 only.");
}
HookEvent("player_entered_checkpoint", Event_PlayerEnteredCheckpoint);
HookEvent("round_start",Event_RoundStart);
HookEvent("player_left_start_area",Event_RoundStart);
g_EnteredCheckpoint = CreateConVar("awb_status", "0", "Get status of plugin", FCVAR_SPONLY | FCVAR_DONTRECORD, true, 0.0, true, 1.0);
}
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
g_EnteredCheckpoint = false;
if(g_EnteredCheckpoint.BoolValue) g_EnteredCheckpoint.BoolValue = false;
}
public void Event_PlayerEnteredCheckpoint(Event event, const char[] name, bool dontBroadcast) {
if(!g_EnteredCheckpoint) {
PrintToChatAll("boolvalue %d | client %d", g_EnteredCheckpoint.BoolValue, GetClientOfUserId(event.GetInt("userid")));
if(!g_EnteredCheckpoint.BoolValue) {
int client = GetClientOfUserId(event.GetInt("userid"));
bool playersLeft = false;
for (int i = 1; i < MaxClients;i++) {
if (client == i)continue;
if (!IsClientConnected(i)) continue;
if (client == i) continue;
if (!IsClientInGame(i)) continue;
if (GetClientTeam(i) != 2) continue;
PrintToChatAll("playersLeft: %d . clientr %d", playersLeft, i);
if(!IsFakeClient(i)) {
playersLeft = true;
break;
}
}
if(!playersLeft) {
g_EnteredCheckpoint = true;
g_EnteredCheckpoint.BoolValue = true;
CheatCommand(client,"warp_all_survivors_to_checkpoint","","");
}
}

114
scripting/BumpMineGiver.sp Normal file
View file

@ -0,0 +1,114 @@
#pragma semicolon 1
#define DEBUG
#define PLUGIN_AUTHOR ""
#define PLUGIN_VERSION "0.00"
#include <sourcemod>
#include <sdktools>
#include <cstrike>
//#include <sdkhooks>
#pragma newdecls required
ConVar g_bmgTTeam, g_bmgEnabled, g_bmgCmdLimit;
int g_bmgBumpsGiven[MAXPLAYERS+1];
public Plugin myinfo =
{
name = "BumpMineGiver",
author = PLUGIN_AUTHOR,
description = "",
version = PLUGIN_VERSION,
url = ""
};
public void OnPluginStart()
{
EngineVersion g_Game = GetEngineVersion();
if(g_Game != Engine_CSGO && g_Game != Engine_CSS)
{
SetFailState("This plugin is for CSGO/CSS only.");
}
g_bmgEnabled = CreateConVar("bmg_enabled", "1", "Should BumpMineGiver be enabled?", FCVAR_NONE, true, 0.0, true, 1.0);
g_bmgTTeam = CreateConVar("bmg_restrict_team", "0", "Should BumpMineGiver be restricted to a team? 0 - All, 1 - Terrorists, 2 - CounterTerrorists", FCVAR_NONE, true, 0.0, true, 3.0);
g_bmgCmdLimit = CreateConVar("bmg_cmdlimit", "0", "Limit of amount of bumpmines to be given with !bmp. 0: Disabled, -1: Infinity", FCVAR_NONE);
HookEvent("round_start", Event_RoundStart);
HookEvent("player_spawn", Event_PlayerSpawn);
RegConsoleCmd("sm_bmp", Command_GiveBMP, "Give yourself a bump mine");
RegConsoleCmd("sm_bmg", Command_GiveBMP, "Give yourself a bump mine");
RegAdminCmd("sm_givebmp", Command_GiveOthersBMP, ADMFLAG_CHEATS, "Give someone x amount of bump mines. Usage: sm_givebmp <user>");
AutoExecConfig();
}
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
for (int i = 0; i < sizeof(g_bmgBumpsGiven); i++) {
g_bmgBumpsGiven[i] = 0;
}
}
public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) {
if(g_bmgEnabled.BoolValue) {
int client = GetClientOfUserId(event.GetInt("userid"));
int wpn_id = GetPlayerWeaponSlot(client, 4);
int team = GetClientTeam(client);
if(g_bmgTTeam.IntValue > 0) { //1 or 2
if (team != g_bmgTTeam.IntValue) return;
}
if(wpn_id == -1) {
GivePlayerItem(client, "weapon_bumpmine");
}
}
}
public Action Command_GiveBMP(int client, int args) {
if(g_bmgCmdLimit.IntValue == 0) {
ReplyToCommand(client, "You have hit the limit of bumpmines");
return Plugin_Handled;
}
//limit is enabled, check
if(g_bmgCmdLimit.IntValue > 0) {
if(g_bmgBumpsGiven[client] > g_bmgCmdLimit.IntValue) {
ReplyToCommand(client, "You have hit the limit of bumpmines");
return Plugin_Handled;
}
}
GivePlayerItem(client, "weapon_bumpmine");
g_bmgBumpsGiven[client]++;
return Plugin_Handled;
}
public Action Command_GiveOthersBMP(int client, int args) {
if(args < 1) {
ReplyToCommand(client, "Usage: sm_givebmp <user>");
}else{
char arg1[32];
GetCmdArg(1, arg1, sizeof(arg1));
char target_name[MAX_TARGET_LENGTH];
int target_list[MAXPLAYERS], target_count;
bool tn_is_ml;
if ((target_count = ProcessTargetString(
arg1,
client,
target_list,
MAXPLAYERS,
COMMAND_FILTER_ALIVE, /* Only allow alive players */
target_name,
sizeof(target_name),
tn_is_ml)) <= 0)
{
/* This function replies to the admin with a failure message */
ReplyToTargetError(client, target_count);
return Plugin_Handled;
}
for (int i = 0; i < target_count; i++)
{
GivePlayerItem(target_list[i], "weapon_bumpmine");
LogAction(client, target_list[i], "\"%L\" gave \"%L\" a bumpmine", client, target_list[i]);
}
}
return Plugin_Handled;
}

View file

@ -0,0 +1,57 @@
#pragma semicolon 1
#pragma newdecls required
//#define DEBUG
#define PLUGIN_NAME "L4D2 Prevent Bot Movement"
#define PLUGIN_DESCRIPTION "Prevents bots from moving in the beginning of the round for a set period of time."
#define PLUGIN_AUTHOR "jackzmc"
#define PLUGIN_VERSION "1.0"
#define PLUGIN_URL ""
#include <sourcemod>
#include <sdktools>
//#include <sdkhooks>
public Plugin myinfo =
{
name = PLUGIN_NAME,
author = PLUGIN_AUTHOR,
description = PLUGIN_DESCRIPTION,
version = PLUGIN_VERSION,
url = PLUGIN_URL
};
static ConVar hSBStop, hStopTime;
public void OnPluginStart()
{
EngineVersion g_Game = GetEngineVersion();
if(g_Game != Engine_Left4Dead && g_Game != Engine_Left4Dead2)
{
SetFailState("This plugin is for L4D/L4D2 only.");
}
HookEvent("round_start",Event_RoundStart);
hStopTime = CreateConVar("sm_freeze_bot_time","20.0","How long should the bots be frozen for on beginning of round? 0 to disable",FCVAR_NONE,true,0.0);
hSBStop = FindConVar("sb_stop");
}
public void OnMapStart() {
if(hStopTime.IntValue != 0) {
PrintToChatAll("round start");
hSBStop.BoolValue = true;
CreateTimer(hStopTime.FloatValue, ResumeBots);
}
}
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
if(hStopTime.IntValue != 0) {
PrintToChatAll("round start");
hSBStop.BoolValue = true;
CreateTimer(hStopTime.FloatValue, ResumeBots);
}
}
public Action ResumeBots(Handle timer) {
PrintToChatAll("Resuming bots");
hSBStop.BoolValue = false;
}

60
scripting/csgo-misc.sp Normal file
View file

@ -0,0 +1,60 @@
#pragma semicolon 1
#define DEBUG
#define PLUGIN_AUTHOR ""
#define PLUGIN_VERSION "0.00"
#include <sourcemod>
#include <sdktools>
#include <cstrike>
//#include <sdkhooks>
#pragma newdecls required
public Plugin myinfo =
{
name = "",
author = PLUGIN_AUTHOR,
description = "",
version = PLUGIN_VERSION,
url = ""
};
public void OnPluginStart()
{
EngineVersion g_Game = GetEngineVersion();
if(g_Game != Engine_CSGO && g_Game != Engine_CSS)
{
SetFailState("This plugin is for CSGO/CSS only.");
}
RegConsoleCmd("sm_first", Command_FirstPov, "Go back to first person");
RegConsoleCmd("sm_third", Command_ThirdPov, "Go to third person");
}
public Action Command_FirstPov(int client, int args) {
if(client == 0) {
ReplyToCommand(client, "This command is for clients only");
return Plugin_Handled;
}
CheatCommand(client, "firstperson", "", "");
return Plugin_Handled;
}
public Action Command_ThirdPov(int client, int args) {
if(client == 0) {
ReplyToCommand(client, "This command is for clients only");
return Plugin_Handled;
}
CheatCommand(client, "thirdperson", "", "");
return Plugin_Handled;
}
stock void CheatCommand(int client, char[] command, char[] argument1, char[] argument2)
{
int userFlags = GetUserFlagBits(client);
SetUserFlagBits(client, ADMFLAG_ROOT);
int flags = GetCommandFlags(command);
SetCommandFlags(command, flags & ~FCVAR_CHEAT);
FakeClientCommand(client, "%s %s %s", command, argument1, argument2);
SetCommandFlags(command, flags);
SetUserFlagBits(client, userFlags);
}

View file

@ -0,0 +1,233 @@
#pragma semicolon 1
#pragma newdecls required //強制1.7以後的新語法
#include <sourcemod>
#include <sdktools>
#define MODEL_V_FIREAXE "models/weapons/melee/v_fireaxe.mdl"
#define MODEL_V_FRYING_PAN "models/weapons/melee/v_frying_pan.mdl"
#define MODEL_V_MACHETE "models/weapons/melee/v_machete.mdl"
#define MODEL_V_BASEBALL_BAT "models/weapons/melee/v_bat.mdl"
#define MODEL_V_CROWBAR "models/weapons/melee/v_crowbar.mdl"
#define MODEL_V_CRICKET_BAT "models/weapons/melee/v_cricket_bat.mdl"
#define MODEL_V_TONFA "models/weapons/melee/v_tonfa.mdl"
#define MODEL_V_KATANA "models/weapons/melee/v_katana.mdl"
#define MODEL_V_ELECTRIC_GUITAR "models/weapons/melee/v_electric_guitar.mdl"
#define MODEL_V_GOLFCLUB "models/weapons/melee/v_golfclub.mdl"
#define MODEL_V_SHIELD "models/weapons/melee/v_riotshield.mdl"
#define MODEL_V_KNIFE "models/v_models/v_knife_t.mdl"
#define MODEL_V_SHOVEL "models/weapons/melee/v_shovel.mdl"
#define MODEL_V_PITCHFORK "models/weapons/melee/v_pitchfork.mdl"
static g_PlayerSecondaryWeapons[MAXPLAYERS + 1];
public Plugin myinfo =
{
name = "L4D2 Drop Secondary",
author = "Jahze, Visor, NoBody & HarryPotter",
version = "1.8",
description = "Survivor players will drop their secondary weapon when they die",
url = "https://github.com/Attano/Equilibrium"
};
public void OnPluginStart()
{
HookEvent("round_start", OnRoundStart, EventHookMode_PostNoCopy);
HookEvent("player_use", OnPlayerUse, EventHookMode_Post);
HookEvent("player_bot_replace", player_bot_replace);
HookEvent("bot_player_replace", bot_player_replace);
HookEvent("player_death", OnPlayerDeath, EventHookMode_Pre);
HookEvent("weapon_drop", OnWeaponDrop);
HookEvent("item_pickup", OnItemPickUp);
}
public void OnRoundStart(Event event, const char[] name, bool dontBroadcast)
{
for (int i = 0; i <= MAXPLAYERS; i++)
{
g_PlayerSecondaryWeapons[i] = -1;
}
}
public Action OnPlayerUse(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("userid"));
if(client == 0 || !IsClientInGame(client) || GetClientTeam(client) != 2)
{
return;
}
int weapon = GetPlayerWeaponSlot(client, 1);
g_PlayerSecondaryWeapons[client] = (weapon == -1 ? weapon : EntIndexToEntRef(weapon));
}
public Action bot_player_replace(Event event, const char[] name, bool dontBroadcast)
{
int bot = GetClientOfUserId(event.GetInt("bot"));
int client = GetClientOfUserId(event.GetInt("player"));
g_PlayerSecondaryWeapons[client] = g_PlayerSecondaryWeapons[bot];
g_PlayerSecondaryWeapons[bot] = -1;
}
public Action player_bot_replace(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("player"));
int bot = GetClientOfUserId(event.GetInt("bot"));
g_PlayerSecondaryWeapons[bot] = g_PlayerSecondaryWeapons[client];
g_PlayerSecondaryWeapons[client] = -1;
}
public Action OnItemPickUp(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("userid"));
if(client == 0 || !IsClientInGame(client) || GetClientTeam(client) != 2)
{
return;
}
int weapon = GetPlayerWeaponSlot(client, 1);
g_PlayerSecondaryWeapons[client] = (weapon == -1 ? weapon : EntIndexToEntRef(weapon));
}
public Action OnWeaponDrop(Event event, const char[] name, bool dontBroadcast)
{
CreateTimer(0.1, ColdDown, event.GetInt("userid"));
}
public Action ColdDown(Handle timer, int client)
{
client = GetClientOfUserId(client);
if(client && IsClientInGame(client) && GetClientTeam(client) == 2)
{
int weapon = GetPlayerWeaponSlot(client, 1);
g_PlayerSecondaryWeapons[client] = (weapon == -1 ? weapon : EntIndexToEntRef(weapon));
}
}
public Action OnPlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("userid"));
if(client == 0 || !IsClientInGame(client) || GetClientTeam(client) != 2)
{
return;
}
int weapon = EntRefToEntIndex(g_PlayerSecondaryWeapons[client]);
if(weapon == INVALID_ENT_REFERENCE)
{
return;
}
char sWeapon[32];
int clip;
GetEdictClassname(weapon, sWeapon, 32);
int index = CreateEntityByName(sWeapon);
float origin[3];
float ang[3];
if (strcmp(sWeapon, "weapon_melee") == 0)
{
char melee[150];
GetEntPropString(weapon , Prop_Data, "m_ModelName", melee, sizeof(melee));
if (strcmp(melee, MODEL_V_FIREAXE) == 0)
{
DispatchKeyValue(index, "melee_script_name", "fireaxe");
}
else if (strcmp(melee, MODEL_V_FRYING_PAN) == 0)
{
DispatchKeyValue(index, "melee_script_name", "frying_pan");
}
else if (strcmp(melee, MODEL_V_MACHETE) == 0)
{
DispatchKeyValue(index, "melee_script_name", "machete");
}
else if (strcmp(melee, MODEL_V_BASEBALL_BAT) == 0)
{
DispatchKeyValue(index, "melee_script_name", "baseball_bat");
}
else if (strcmp(melee, MODEL_V_CROWBAR) == 0)
{
DispatchKeyValue(index, "melee_script_name", "crowbar");
}
else if (strcmp(melee, MODEL_V_CRICKET_BAT) == 0)
{
DispatchKeyValue(index, "melee_script_name", "cricket_bat");
}
else if (strcmp(melee, MODEL_V_TONFA) == 0)
{
DispatchKeyValue(index, "melee_script_name", "tonfa");
}
else if (strcmp(melee, MODEL_V_KATANA) == 0)
{
DispatchKeyValue(index, "melee_script_name", "katana");
}
else if (strcmp(melee, MODEL_V_ELECTRIC_GUITAR) == 0)
{
DispatchKeyValue(index, "melee_script_name", "electric_guitar");
}
else if (strcmp(melee, MODEL_V_GOLFCLUB) == 0)
{
DispatchKeyValue(index, "melee_script_name", "golfclub");
}
else if (strcmp(melee, MODEL_V_SHIELD) == 0)
{
DispatchKeyValue(index, "melee_script_name", "riotshield");
}
else if (strcmp(melee, MODEL_V_KNIFE) == 0)
{
DispatchKeyValue(index, "melee_script_name", "knife");
}
else if (strcmp(melee, MODEL_V_SHOVEL) == 0)
{
DispatchKeyValue(index, "melee_script_name", "shovel");
}
else if (strcmp(melee, MODEL_V_PITCHFORK) == 0)
{
DispatchKeyValue(index, "melee_script_name", "pitchfork");
}
else return;
}
else if (strcmp(sWeapon, "weapon_chainsaw") == 0)
{
clip = GetEntProp(weapon, Prop_Send, "m_iClip1");
}
else if (strcmp(sWeapon, "weapon_pistol") == 0 && (GetEntProp(weapon, Prop_Send, "m_isDualWielding") > 0))
{
int indexC = CreateEntityByName(sWeapon);
GetClientEyePosition(client,origin);
GetClientEyeAngles(client, ang);
GetAngleVectors(ang, ang, NULL_VECTOR,NULL_VECTOR);
NormalizeVector(ang,ang);
ScaleVector(ang, 90.0);
DispatchSpawn(indexC);
TeleportEntity(indexC, origin, NULL_VECTOR, ang);
}
else if (strcmp(sWeapon, "weapon_pistol_magnum") == 0)
{
clip = GetEntProp(weapon, Prop_Send, "m_iClip1");
}
RemovePlayerItem(client, weapon);
RemoveEntity(weapon);
GetClientEyePosition(client,origin);
GetClientEyeAngles(client, ang);
GetAngleVectors(ang, ang, NULL_VECTOR,NULL_VECTOR);
NormalizeVector(ang,ang);
ScaleVector(ang, 90.0);
DispatchSpawn(index);
TeleportEntity(index, origin, NULL_VECTOR, ang);
if (strcmp(sWeapon, "weapon_chainsaw") == 0 || strcmp(sWeapon, "weapon_pistol") == 0 || strcmp(sWeapon, "weapon_pistol_magnum") == 0)
{
SetEntProp(index, Prop_Send, "m_iClip1", clip);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,136 @@
#pragma semicolon 1
#pragma newdecls required
//#define DEBUG
#define PLUGIN_VERSION "1.0"
#define GAMEDATA "l4d_target_override"
#include <sourcemod>
#include <sdktools>
#include <left4dhooks>
enum L4D2Infected
{
L4D2Infected_None = 0,
L4D2Infected_Smoker = 1,
L4D2Infected_Boomer = 2,
L4D2Infected_Hunter = 3,
L4D2Infected_Spitter = 4,
L4D2Infected_Jockey = 5,
L4D2Infected_Charger = 6,
L4D2Infected_Witch = 7,
L4D2Infected_Tank = 8
}
public Plugin myinfo =
{
name = "L4D2 target poo",
author = "jackzmc",
description = "",
version = PLUGIN_VERSION,
url = ""
};
bool g_bIsVictim[MAXPLAYERS+1];
Handle g_hDetour;
public void OnPluginStart()
{
EngineVersion g_Game = GetEngineVersion();
if(g_Game != Engine_Left4Dead2)
{
SetFailState("This plugin is for L4D2 only.");
}
RegAdminCmd("sm_set_victim", Cmd_SetVictim, ADMFLAG_CHEATS);
HookEvent("player_death", Event_PlayerDeath);
}
public void OnPluginEnd()
{
}
public Action Cmd_SetVictim(int client, int args) {
if(args == 0) {
ReplyToCommand(client, "Please enter a player to target");
}else{
char arg1[32];
GetCmdArg(1, arg1, sizeof(arg1));
char target_name[MAX_TARGET_LENGTH];
int target_list[1], target_count;
bool tn_is_ml;
if ((target_count = ProcessTargetString(
arg1,
client,
target_list,
MAXPLAYERS,
COMMAND_FILTER_ALIVE, /* Only allow alive players */
target_name,
sizeof(target_name),
tn_is_ml)) <= 0)
{
/* This function replies to the admin with a failure message */
ReplyToTargetError(client, target_count);
return Plugin_Handled;
}
for(int i = 0; i < target_count; i++) {
int victim = target_list[i];
//g_iSITargets
g_bIsVictim[victim] = !g_bIsVictim[victim];
ReplyToCommand(client, "Successfully toggled %N victim status to: %b", victim, g_bIsVictim[victim]);
ShowActivity(client, "toggled special infected victim status for %N to %b", victim, g_bIsVictim[victim]);
}
}
return Plugin_Handled;
}
static int b_attackerTarget[MAXPLAYERS+1];
public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
// =========================
// OVERRIDE VICTIM
// =========================
L4D2Infected class = view_as<L4D2Infected>(GetEntProp(attacker, Prop_Send, "m_zombieClass"));
if(class != L4D2Infected_Tank) {
int existingTarget = GetClientOfUserId(b_attackerTarget[attacker]);
if(existingTarget > 0) {
curTarget = existingTarget;
return Plugin_Changed;
}
float closestDistance, survPos[3], spPos[3];
GetClientAbsOrigin(attacker, spPos);
int closestClient = -1;
for(int i = 1; i <= MaxClients; i++) {
if(g_bIsVictim[i] && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) {
GetClientAbsOrigin(i, survPos);
float dist = GetVectorDistance(survPos, spPos, true);
if(closestClient == -1 || dist < closestDistance) {
closestDistance = dist;
closestClient = i;
}
}
}
if(closestClient > 0) {
PrintToConsoleAll("Attacker %N new target: %N", attacker, closestClient);
b_attackerTarget[attacker] = GetClientUserId(closestClient);
curTarget = closestClient;
return Plugin_Changed;
}
}
return Plugin_Continue;
}
public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
int client = GetClientOfUserId(event.GetInt("userid"));
b_attackerTarget[client] = 0;
}
public void OnClientDisconnect(int client) {
b_attackerTarget[client] = 0;
}

View file

@ -2,11 +2,24 @@
// ====================================================================================================
Change Log:
1.0.6 (12-February-2021)
- Fixed custom model cvar typo. (thanks "weffer" for reporting)
1.0.5 (11-February-2021)
- Fixed a bug not rendering custom sprites right after turning it on.
- Added one more custom sprite option with an alpha background filling the bar.
1.0.4 (11-February-2021)
- Added custom sprite option.
1.0.3 (08-February-2021)
- Fixed missing client in-game in visibility check. (thanks to "Krufftys Killers" and "Striker black")
1.0.2 (08-February-2021)
- Fixed wrong value on max health calculation.
- Fixed sprite hiding behind tank rocks.
- Fixed sprite hiding while tank throws rocks (ability use).
- Moved visibility logic to timer.
- Moved visibility logic to timer handle.
1.0.1 (30-January-2021)
- Public release.
@ -23,7 +36,7 @@ Change Log:
#define PLUGIN_NAME "[L4D1 & L4D2] Tank HP Sprite"
#define PLUGIN_AUTHOR "Mart"
#define PLUGIN_DESCRIPTION "Shows a sprite at the tank head that goes from green to red based on its HP"
#define PLUGIN_VERSION "1.0.2"
#define PLUGIN_VERSION "1.0.5"
#define PLUGIN_URL "https://forums.alliedmods.net/showthread.php?t=330370"
// ====================================================================================================
@ -66,6 +79,7 @@ public Plugin myinfo =
// Defines
// ====================================================================================================
#define CLASSNAME_ENV_SPRITE "env_sprite"
#define CLASSNAME_ENV_TEXTURETOGGLE "env_texturetoggle"
#define CLASSNAME_TANK_ROCK "tank_rock"
#define TEAM_SPECTATOR 1
@ -102,6 +116,9 @@ static ConVar g_hCvar_DeadAlpha;
static ConVar g_hCvar_DeadScale;
static ConVar g_hCvar_DeadColor;
static ConVar g_hCvar_Team;
static ConVar g_hCvar_CustomModel;
static ConVar g_hCvar_CustomModelVMT;
static ConVar g_hCvar_CustomModelVTF;
static ConVar g_hCvar_AllSpecials;
// ====================================================================================================
@ -115,6 +132,7 @@ static bool g_bCvar_Sight;
static bool g_bCvar_AttackDelay;
static bool g_bCvar_AliveShow;
static bool g_bCvar_DeadShow;
static bool g_bCvar_CustomModel;
// ====================================================================================================
// int - Plugin Variables
@ -147,11 +165,14 @@ static char g_sCvar_DeadAlpha[4];
static char g_sCvar_DeadScale[5];
static char g_sCvar_DeadColor[12];
static char g_sCvar_FadeDistance[5];
static char g_sCvar_CustomModelVMT[100];
static char g_sCvar_CustomModelVTF[100];
// ====================================================================================================
// client - Plugin Variables
// ====================================================================================================
static int gc_iTankSpriteRef[MAXPLAYERS+1] = { INVALID_ENT_REFERENCE, ... };
static int gc_iTankSpriteFrameRef[MAXPLAYERS+1] = { INVALID_ENT_REFERENCE, ... };
static bool gc_bVisible[MAXPLAYERS+1][MAXPLAYERS+1];
static float gc_fLastAttack[MAXPLAYERS+1][MAXPLAYERS+1];
@ -185,21 +206,24 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
public void OnPluginStart()
{
CreateConVar("l4d_tank_hp_sprite_version", PLUGIN_VERSION, PLUGIN_DESCRIPTION, CVAR_FLAGS_PLUGIN_VERSION);
g_hCvar_Enabled = CreateConVar("l4d_tank_hp_sprite_enable", "1", "Enable/Disable the plugin.\n0 = Disable, 1 = Enable", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_ZAxis = CreateConVar("l4d_tank_hp_sprite_z_axis", "92", "Additional Z distance based on the tank position.", CVAR_FLAGS, true, 0.0);
g_hCvar_FadeDistance = CreateConVar("l4d_tank_hp_sprite_fade_distance", "-1", "Minimum distance that a client must be from the tank to see the sprite (both alive and dead sprites).\n-1 = Always visible.", CVAR_FLAGS, true, -1.0, true, 9999.0);
g_hCvar_Sight = CreateConVar("l4d_tank_hp_sprite_sight", "1", "Show the sprite to the survivor only if the Tank is on sight.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_AttackDelay = CreateConVar("l4d_tank_hp_sprite_attack_delay", "0.0", "Show the sprite to the survivor attacker, by this amount of time in seconds, after hitting the Tank.\n0 = OFF.", CVAR_FLAGS, true, 0.0);
g_hCvar_AliveShow = CreateConVar("l4d_tank_hp_sprite_alive_show", "1", "Show the alive sprite while tank is alive.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_AliveModel = CreateConVar("l4d_tank_hp_sprite_alive_model", "materials/vgui/healthbar_white.vmt", "Model of alive tank sprite.");
g_hCvar_AliveAlpha = CreateConVar("l4d_tank_hp_sprite_alive_alpha", "200", "Alpha of alive tank sprite.\n0 = Invisible, 255 = Fully Visible", CVAR_FLAGS, true, 0.0, true, 255.0);
g_hCvar_AliveScale = CreateConVar("l4d_tank_hp_sprite_alive_scale", "0.25", "Scale of alive tank sprite (increases both height and width).\nNote: Some range values maintain the same size. (e.g. from 0.0 to 0.38 the size doesn't change).", CVAR_FLAGS, true, 0.0);
g_hCvar_DeadShow = CreateConVar("l4d_tank_hp_sprite_dead_show", "1", "Show the dead sprite when a tank dies.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_DeadModel = CreateConVar("l4d_tank_hp_sprite_dead_model", "materials/sprites/death_icon.vmt", "Model of dead tank sprite.");
g_hCvar_DeadAlpha = CreateConVar("l4d_tank_hp_sprite_dead_alpha", "200", "Alpha of dead tank sprite.\n0 = Invisible, 255 = Fully Visible", CVAR_FLAGS, true, 0.0, true, 255.0);
g_hCvar_DeadScale = CreateConVar("l4d_tank_hp_sprite_dead_scale", "0.25", "Scale of dead tank sprite (increases both height and width).\nSome range values maintain the size the same.", CVAR_FLAGS, true, 0.0);
g_hCvar_DeadColor = CreateConVar("l4d_tank_hp_sprite_dead_color", "225 0 0", "Color of dead tank sprite.\nUse three values between 0-255 separated by spaces (\"<0-255> <0-255> <0-255>\").", CVAR_FLAGS);
g_hCvar_Team = CreateConVar("l4d_tank_hp_sprite_team", "3", "Which teams should the sprite be visible.\n0 = NONE, 1 = SURVIVOR, 2 = INFECTED, 4 = SPECTATOR, 8 = HOLDOUT.\nAdd numbers greater than 0 for multiple options.\nExample: \"3\", enables for SURVIVOR and INFECTED.", CVAR_FLAGS, true, 0.0, true, 15.0);
g_hCvar_Enabled = CreateConVar("l4d_tank_hp_sprite_enable", "1", "Enable/Disable the plugin.\n0 = Disable, 1 = Enable.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_ZAxis = CreateConVar("l4d_tank_hp_sprite_z_axis", "92", "Additional Z distance based on the tank position.", CVAR_FLAGS, true, 0.0);
g_hCvar_FadeDistance = CreateConVar("l4d_tank_hp_sprite_fade_distance", "-1", "Minimum distance that a client must be from the tank to see the sprite (both alive and dead sprites).\n-1 = Always visible.", CVAR_FLAGS, true, -1.0, true, 9999.0);
g_hCvar_Sight = CreateConVar("l4d_tank_hp_sprite_sight", "1", "Show the sprite to the survivor only if the Tank is on sight.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_AttackDelay = CreateConVar("l4d_tank_hp_sprite_attack_delay", "0.0", "Show the sprite to the survivor attacker, by this amount of time in seconds, after hitting the Tank.\n0 = OFF.", CVAR_FLAGS, true, 0.0);
g_hCvar_AliveShow = CreateConVar("l4d_tank_hp_sprite_alive_show", "1", "Show the alive sprite while tank is alive.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_AliveModel = CreateConVar("l4d_tank_hp_sprite_alive_model", "materials/vgui/healthbar_white.vmt", "Model of alive tank sprite.");
g_hCvar_AliveAlpha = CreateConVar("l4d_tank_hp_sprite_alive_alpha", "200", "Alpha of alive tank sprite.\n0 = Invisible, 255 = Fully Visible", CVAR_FLAGS, true, 0.0, true, 255.0);
g_hCvar_AliveScale = CreateConVar("l4d_tank_hp_sprite_alive_scale", "0.25", "Scale of alive tank sprite (increases both height and width).\nNote: Some range values maintain the same size. (e.g. from 0.0 to 0.38 the size doesn't change).", CVAR_FLAGS, true, 0.0);
g_hCvar_DeadShow = CreateConVar("l4d_tank_hp_sprite_dead_show", "1", "Show the dead sprite when a tank dies.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_DeadModel = CreateConVar("l4d_tank_hp_sprite_dead_model", "materials/sprites/death_icon.vmt", "Model of dead tank sprite.");
g_hCvar_DeadAlpha = CreateConVar("l4d_tank_hp_sprite_dead_alpha", "200", "Alpha of dead tank sprite.\n0 = Invisible, 255 = Fully Visible", CVAR_FLAGS, true, 0.0, true, 255.0);
g_hCvar_DeadScale = CreateConVar("l4d_tank_hp_sprite_dead_scale", "0.25", "Scale of dead tank sprite (increases both height and width).\nSome range values maintain the size the same.", CVAR_FLAGS, true, 0.0);
g_hCvar_DeadColor = CreateConVar("l4d_tank_hp_sprite_dead_color", "225 0 0", "Color of dead tank sprite.\nUse three values between 0-255 separated by spaces (\"<0-255> <0-255> <0-255>\").", CVAR_FLAGS);
g_hCvar_Team = CreateConVar("l4d_tank_hp_sprite_team", "3", "Which teams should the sprite be visible.\n0 = NONE, 1 = SURVIVOR, 2 = INFECTED, 4 = SPECTATOR, 8 = HOLDOUT.\nAdd numbers greater than 0 for multiple options.\nExample: \"3\", enables for SURVIVOR and INFECTED.", CVAR_FLAGS, true, 0.0, true, 15.0);
g_hCvar_CustomModel = CreateConVar("l4d_tank_hp_sprite_custom_model", "0", "Use a custom sprite for the alive model\nNote: This requires the client downloading the custom model (.vmt and .vtf) to work.\nSearch for FastDL for more info.\n0 = OFF, 1 = ON.", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_CustomModelVMT = CreateConVar("l4d_tank_hp_sprite_custom_model_vmt", "materials/mart/mart_custombar.vmt", "Custom sprite VMT path.");
g_hCvar_CustomModelVTF = CreateConVar("l4d_tank_hp_sprite_custom_model_vtf", "materials/mart/mart_custombar.vtf", "Custom sprite VTF path.");
g_hCvar_AllSpecials = CreateConVar("l4d_tank_hp_sprite_all_specials", "1", "Should all specials have healthbar or only tanks\n0 = Tanks Only, 1 = All Specials", CVAR_FLAGS, true, 0.0, true, 1.0);
g_hCvar_Enabled.AddChangeHook(Event_ConVarChanged);
@ -217,6 +241,9 @@ public void OnPluginStart()
g_hCvar_DeadScale.AddChangeHook(Event_ConVarChanged);
g_hCvar_DeadColor.AddChangeHook(Event_ConVarChanged);
g_hCvar_Team.AddChangeHook(Event_ConVarChanged);
g_hCvar_CustomModel.AddChangeHook(Event_ConVarChanged);
g_hCvar_CustomModelVMT.AddChangeHook(Event_ConVarChanged);
g_hCvar_CustomModelVTF.AddChangeHook(Event_ConVarChanged);
// Load plugin configs from .cfg
AutoExecConfig(true, CONFIG_FILENAME);
@ -234,7 +261,7 @@ public void OnPluginStart()
public void OnPluginEnd()
{
int entity;
char targetname[64];
char targetname[19];
entity = INVALID_ENT_REFERENCE;
while ((entity = FindEntityByClassname(entity, CLASSNAME_ENV_SPRITE)) != INVALID_ENT_REFERENCE)
@ -285,7 +312,6 @@ public void GetCvars()
g_bCvar_AliveShow = g_hCvar_AliveShow.BoolValue;
g_hCvar_AliveModel.GetString(g_sCvar_AliveModel, sizeof(g_sCvar_AliveModel));
TrimString(g_sCvar_AliveModel);
PrecacheModel(g_sCvar_AliveModel, true);
g_iCvar_AliveAlpha = g_hCvar_AliveAlpha.IntValue;
FormatEx(g_sCvar_AliveAlpha, sizeof(g_sCvar_AliveAlpha), "%i", g_iCvar_AliveAlpha);
g_fCvar_AliveScale = g_hCvar_AliveScale.FloatValue;
@ -293,7 +319,6 @@ public void GetCvars()
g_bCvar_DeadShow = g_hCvar_DeadShow.BoolValue;
g_hCvar_DeadModel.GetString(g_sCvar_DeadModel, sizeof(g_sCvar_DeadModel));
TrimString(g_sCvar_DeadModel);
PrecacheModel(g_sCvar_DeadModel, true);
g_iCvar_DeadAlpha = g_hCvar_DeadAlpha.IntValue;
FormatEx(g_sCvar_DeadAlpha, sizeof(g_sCvar_DeadAlpha), "%i", g_iCvar_DeadAlpha);
g_fCvar_DeadScale = g_hCvar_DeadScale.FloatValue;
@ -301,6 +326,28 @@ public void GetCvars()
g_hCvar_DeadColor.GetString(g_sCvar_DeadColor, sizeof(g_sCvar_DeadColor));
TrimString(g_sCvar_DeadColor);
g_iCvar_Team = g_hCvar_Team.IntValue;
g_bCvar_CustomModel = g_hCvar_CustomModel.BoolValue;
g_hCvar_CustomModelVMT.GetString(g_sCvar_CustomModelVMT, sizeof(g_sCvar_CustomModelVMT));
TrimString(g_sCvar_CustomModelVMT);
g_hCvar_CustomModelVTF.GetString(g_sCvar_CustomModelVTF, sizeof(g_sCvar_CustomModelVTF));
TrimString(g_sCvar_CustomModelVTF);
if (g_bCvar_AliveShow)
{
if (g_bCvar_CustomModel)
{
AddFileToDownloadsTable(g_sCvar_CustomModelVMT);
AddFileToDownloadsTable(g_sCvar_CustomModelVTF);
PrecacheModel(g_sCvar_CustomModelVMT, true);
}
else
{
PrecacheModel(g_sCvar_AliveModel, true);
}
}
if (g_bCvar_DeadShow)
PrecacheModel(g_sCvar_DeadModel, true);
}
/****************************************************************************************************/
@ -309,8 +356,10 @@ public void LateLoad()
{
for (int client = 1; client <= MaxClients; client++)
{
if (IsPlayerSpecialInfected(client))
TankSprite(client);
if (!IsPlayerTank(client))
continue;
TankSprite(client);
}
}
@ -322,6 +371,7 @@ public void OnClientDisconnect(int client)
return;
gc_iTankSpriteRef[client] = INVALID_ENT_REFERENCE;
gc_iTankSpriteFrameRef[client] = INVALID_ENT_REFERENCE;
for (int target = 1; target <= MaxClients; target++)
{
@ -372,6 +422,7 @@ public void HookEvents(bool hook)
{
g_bEventsHooked = true;
HookEvent("tank_spawn", Event_TankSpawn);
HookEvent("player_hurt", Event_PlayerHurt);
return;
@ -381,6 +432,7 @@ public void HookEvents(bool hook)
{
g_bEventsHooked = false;
UnhookEvent("tank_spawn", Event_TankSpawn);
UnhookEvent("player_hurt", Event_PlayerHurt);
return;
@ -389,27 +441,37 @@ public void HookEvents(bool hook)
/****************************************************************************************************/
public void Event_TankSpawn(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("userid"));
public void OnClientPutInServer(int client) {
if(GetClientTeam(client) == TEAM_INFECTED) {
//If all specials turned off and not tank; ignore.
if(!g_hCvar_AllSpecials.BoolValue && GetZombieClass(client) != g_iTankClass) return;
TankSprite(client);
}
if (!IsValidClient(client))
return;
TankSprite(client);
}
/****************************************************************************************************/
public void Event_PlayerHurt(Event event, const char[] name, bool dontBroadcast) {
int tank = GetClientOfUserId(event.GetInt("userid"));
if (IsPlayerSpecialInfected(tank)) {
TankSprite(tank);
if(g_bCvar_AttackDelay) {
int attacker = GetClientOfUserId(event.GetInt("attacker"));
if (IsValidClient(attacker) && GetClientTeam(attacker) != TEAM_SURVIVOR)
gc_fLastAttack[tank][attacker] = GetGameTime();
}
}
public void Event_PlayerHurt(Event event, const char[] name, bool dontBroadcast)
{
if (!g_bCvar_AttackDelay)
return;
int target = GetClientOfUserId(event.GetInt("userid"));
if (!IsPlayerTank(target))
return;
int attacker = GetClientOfUserId(event.GetInt("attacker"));
if (!IsValidClient(attacker))
return;
if (GetClientTeam(attacker) != TEAM_SURVIVOR)
return;
gc_fLastAttack[target][attacker] = GetGameTime();
}
/****************************************************************************************************/
@ -419,21 +481,26 @@ public Action TimerKill(Handle timer)
if (!g_bConfigLoaded)
return Plugin_Continue;
for (int client = 1; client <= MaxClients; client++)
for (int target = 1; target <= MaxClients; target++)
{
if (gc_iTankSpriteRef[client] != INVALID_ENT_REFERENCE && !IsPlayerSpecialInfected(client)) {
int entity = EntRefToEntIndex(gc_iTankSpriteRef[client]);
if (gc_iTankSpriteRef[target] == INVALID_ENT_REFERENCE)
continue;
if (entity != INVALID_ENT_REFERENCE)
AcceptEntityInput(entity, "Kill");
if (g_bCvar_Enabled && IsPlayerTank(target))
continue;
gc_iTankSpriteRef[client] = INVALID_ENT_REFERENCE;
int entity = EntRefToEntIndex(gc_iTankSpriteRef[target]);
for (int client2 = 1; client2 <= MaxClients; client2++)
{
gc_bVisible[client][client2] = false;
gc_fLastAttack[client][client2] = 0.0;
}
if (entity != INVALID_ENT_REFERENCE)
AcceptEntityInput(entity, "Kill");
gc_iTankSpriteRef[target] = INVALID_ENT_REFERENCE;
gc_iTankSpriteFrameRef[target] = INVALID_ENT_REFERENCE;
for (int client = 1; client <= MaxClients; client++)
{
gc_bVisible[target][client] = false;
gc_fLastAttack[target][client] = 0.0;
}
}
@ -455,38 +522,31 @@ public Action TimerVisible(Handle timer)
if (gc_iTankSpriteRef[target] == INVALID_ENT_REFERENCE)
continue;
if (!IsClientConnected(target))
if (!IsClientInGame(target))
continue;
for (int client = 1; client <= MaxClients; client++)
{
if (!IsClientConnected(client))
gc_bVisible[target][client] = false;
if (!IsClientInGame(client))
continue;
if (IsFakeClient(client))
continue;
if (!(GetClientTeamFlag(client) & g_iCvar_Team))
{
gc_bVisible[target][client] = false;
if (!(GetTeamFlag(GetClientTeam(client)) & g_iCvar_Team))
continue;
}
if (g_bCvar_AttackDelay || g_bCvar_Sight)
{
if (GetClientTeam(client) == TEAM_SURVIVOR || GetClientTeam(client) == TEAM_HOLDOUT)
{
if (g_bCvar_AttackDelay && (GetGameTime() - gc_fLastAttack[target][client] > g_fCvar_AttackDelay))
{
gc_bVisible[target][client] = false;
continue;
}
if (g_bCvar_Sight && !IsVisibleTo(client, target))
{
gc_bVisible[target][client] = false;
continue;
}
}
}
@ -509,7 +569,7 @@ public Action TimerRender(Handle timer)
for (int target = 1; target <= MaxClients; target++)
{
if (!IsPlayerSpecialInfected(target))
if (!IsPlayerTank(target))
continue;
TankSprite(target);
@ -529,14 +589,43 @@ public void TankSprite(int client)
if (entity == INVALID_ENT_REFERENCE)
{
char targetname[22];
FormatEx(targetname, sizeof(targetname), "%s-%i", "l4d_tank_hp_sprite", client);
entity = CreateEntityByName(CLASSNAME_ENV_SPRITE);
DispatchKeyValue(entity, "targetname", "l4d_tank_hp_sprite");
ge_iOwner[entity] = client;
gc_iTankSpriteRef[client] = EntIndexToEntRef(entity);
DispatchKeyValue(entity, "targetname", targetname);
DispatchKeyValue(entity, "spawnflags", "1");
DispatchKeyValue(entity, "fademindist", g_sCvar_FadeDistance);
SetEntProp(entity, Prop_Data, "m_iHammerID", -1);
SDKHook(entity, SDKHook_SetTransmit, OnSetTransmit);
ge_iOwner[entity] = client;
gc_iTankSpriteRef[client] = EntIndexToEntRef(entity);
}
if (g_bCvar_CustomModel)
{
int entityFrame = INVALID_ENT_REFERENCE;
if (gc_iTankSpriteFrameRef[client] != INVALID_ENT_REFERENCE)
entityFrame = EntRefToEntIndex(gc_iTankSpriteFrameRef[client]);
if (entityFrame == INVALID_ENT_REFERENCE)
{
char targetname[22];
FormatEx(targetname, sizeof(targetname), "%s-%i", "l4d_tank_hp_sprite", client);
entityFrame = CreateEntityByName(CLASSNAME_ENV_TEXTURETOGGLE);
gc_iTankSpriteFrameRef[client] = EntIndexToEntRef(entityFrame);
DispatchKeyValue(entityFrame, "targetname", "l4d_tank_hp_sprite");
DispatchKeyValue(entityFrame, "target", targetname);
TeleportEntity(entityFrame, g_fVPos, NULL_VECTOR, NULL_VECTOR);
DispatchSpawn(entityFrame);
ActivateEntity(entityFrame);
SetVariantString("!activator");
AcceptEntityInput(entityFrame, "SetParent", entity);
}
}
if (IsPlayerIncapacitated(client))
@ -547,12 +636,15 @@ public void TankSprite(int client)
DispatchKeyValue(entity, "rendercolor", g_sCvar_DeadColor);
DispatchKeyValue(entity, "renderamt", g_sCvar_DeadAlpha); // If renderamt goes before rendercolor, it doesn't render
DispatchKeyValue(entity, "scale", g_sCvar_DeadScale);
TeleportEntity(entity, g_fVPos, NULL_VECTOR, NULL_VECTOR);
DispatchSpawn(entity);
ActivateEntity(entity);
SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", client);
SetVariantString("!activator");
AcceptEntityInput(entity, "SetParent", client);
AcceptEntityInput(entity, "ShowSprite");
TeleportEntity(entity, g_fVPos, NULL_VECTOR, NULL_VECTOR);
}
return;
@ -568,9 +660,7 @@ public void TankSprite(int client)
int currentHealth = GetClientHealth(client);
float percentageHealth;
if (maxHealth == 0)
percentageHealth = 0.0;
else
if (maxHealth > 0)
percentageHealth = (float(currentHealth) / float(maxHealth));
bool halfHealth = (percentageHealth <= 0.5);
@ -578,16 +668,35 @@ public void TankSprite(int client)
char sRenderColor[12];
Format(sRenderColor, sizeof(sRenderColor), "%i %i 0", halfHealth ? 255 : RoundFloat(255.0 * ((1.0 - percentageHealth) * 2)), halfHealth ? RoundFloat(255.0 * (percentageHealth) * 2) : 255);
DispatchKeyValue(entity, "model", g_sCvar_AliveModel);
DispatchKeyValue(entity, "model", g_bCvar_CustomModel ? g_sCvar_CustomModelVMT : g_sCvar_AliveModel);
DispatchKeyValue(entity, "rendercolor", sRenderColor);
DispatchKeyValue(entity, "renderamt", g_sCvar_AliveAlpha); // If renderamt goes before rendercolor, it doesn't render
DispatchKeyValue(entity, "scale", g_sCvar_AliveScale);
TeleportEntity(entity, g_fVPos, NULL_VECTOR, NULL_VECTOR);
DispatchSpawn(entity);
ActivateEntity(entity);
SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", client);
SetVariantString("!activator");
AcceptEntityInput(entity, "SetParent", client);
AcceptEntityInput(entity, "ShowSprite");
TeleportEntity(entity, g_fVPos, NULL_VECTOR, NULL_VECTOR);
if (!g_bCvar_CustomModel)
return;
int entityFrame = EntRefToEntIndex(gc_iTankSpriteFrameRef[client]);
if (entityFrame == INVALID_ENT_REFERENCE)
return;
int frame = RoundFloat(percentageHealth * 100);
char input[38];
FormatEx(input, sizeof(input), "OnUser1 !self:SetTextureIndex:%i:0:1", frame);
SetVariantString(input);
AcceptEntityInput(entityFrame, "AddOutput");
AcceptEntityInput(entityFrame, "FireUser1");
}
/****************************************************************************************************/
@ -612,14 +721,14 @@ bool IsVisibleTo(int client, int target)
float vClientPos[3];
float vEntityPos[3];
float vLookAt[3];
float vAngles[3];
float vAng[3];
GetClientEyePosition(client, vClientPos);
GetClientEyePosition(target, vEntityPos);
MakeVectorFromPoints(vClientPos, vEntityPos, vLookAt);
GetVectorAngles(vLookAt, vAngles);
GetVectorAngles(vLookAt, vAng);
Handle trace = TR_TraceRayFilterEx(vClientPos, vAngles, MASK_PLAYERSOLID, RayType_Infinite, TraceFilter, target);
Handle trace = TR_TraceRayFilterEx(vClientPos, vAng, MASK_PLAYERSOLID, RayType_Infinite, TraceFilter, target);
bool isVisible;
@ -682,6 +791,9 @@ public Action CmdPrintCvars(int client, int args)
PrintToConsole(client, "l4d_tank_hp_sprite_dead_scale : %.2f", g_fCvar_DeadScale);
PrintToConsole(client, "l4d_tank_hp_sprite_dead_color : \"%s\"", g_sCvar_DeadColor);
PrintToConsole(client, "l4d_tank_hp_sprite_team : %i", g_iCvar_Team);
PrintToConsole(client, "l4d_tank_hp_sprite_custom_model : %b (%s)", g_bCvar_CustomModel, g_bCvar_CustomModel ? "true" : "false");
PrintToConsole(client, "l4d_tank_hp_sprite_custom_model_vmt : \"%s\"", g_sCvar_CustomModelVMT);
PrintToConsole(client, "l4d_tank_hp_sprite_custom_model_vtf : \"%s\"", g_sCvar_CustomModelVTF);
PrintToConsole(client, "");
PrintToConsole(client, "======================================================================");
PrintToConsole(client, "");
@ -777,7 +889,8 @@ bool IsPlayerIncapacitated(int client)
* @param client Client index.
* @return True if client is a tank, false otherwise.
*/
bool IsPlayerSpecialInfected(int client) {
bool IsPlayerTank(int client)
{
bool isValid = IsValidClient(client) && GetClientTeam(client) == TEAM_INFECTED && IsPlayerAlive(client) && !IsPlayerGhost(client);
if(!g_hCvar_AllSpecials.BoolValue && GetZombieClass(client) != g_iTankClass)
return false;
@ -788,14 +901,14 @@ bool IsPlayerSpecialInfected(int client) {
/****************************************************************************************************/
/**
* Returns the team flag from a client.
* Returns the team flag from a team.
*
* @param client Client index.
* @return Client team flag.
* @param team Team index.
* @return Team flag.
*/
int GetClientTeamFlag(int client)
int GetTeamFlag(int team)
{
switch (GetClientTeam(client))
switch (team)
{
case TEAM_SURVIVOR:
return FLAG_TEAM_SURVIVOR;

View file

@ -0,0 +1,149 @@
#include <sourcemod>
#include <sdktools>
#include <left4dhooks>
#define UNRESERVE_VERSION "1.1.1"
#define UNRESERVE_DEBUG 0
#define UNRESERVE_DEBUG_LOG 0
#define L4D_MAXCLIENTS MaxClients
#define L4D_MAXCLIENTS_PLUS1 (L4D_MAXCLIENTS + 1)
#define L4D_MAXHUMANS_LOBBY_VERSUS 8
#define L4D_MAXHUMANS_LOBBY_OTHER 4
new Handle:cvarGameMode = INVALID_HANDLE;
public Plugin:myinfo =
{
name = "L4D1/2 Remove Lobby Reservation",
author = "Downtown1",
description = "Removes lobby reservation when server is full",
version = UNRESERVE_VERSION,
url = "http://forums.alliedmods.net/showthread.php?t=87759"
}
new Handle:cvarUnreserve = INVALID_HANDLE;
public OnPluginStart()
{
LoadTranslations("common.phrases");
RegAdminCmd("sm_unreserve", Command_Unreserve, ADMFLAG_BAN, "sm_unreserve - manually force removes the lobby reservation");
cvarUnreserve = CreateConVar("l4d_unreserve_full", "1", "Automatically unreserve server after a full lobby joins", FCVAR_SPONLY|FCVAR_NOTIFY);
CreateConVar("l4d_unreserve_version", UNRESERVE_VERSION, "Version of the Lobby Unreserve plugin.", FCVAR_SPONLY|FCVAR_NOTIFY);
cvarGameMode = FindConVar("mp_gamemode");
}
bool:IsScavengeMode()
{
decl String:sGameMode[32];
GetConVarString(cvarGameMode, sGameMode, sizeof(sGameMode));
if (StrContains(sGameMode, "scavenge") > -1)
{
return true;
}
else
{
return false;
}
}
bool:IsVersusMode()
{
decl String:sGameMode[32];
GetConVarString(cvarGameMode, sGameMode, sizeof(sGameMode));
if (StrContains(sGameMode, "versus") > -1)
{
return true;
}
else
{
return false;
}
}
IsServerLobbyFull()
{
new humans = GetHumanCount();
DebugPrintToAll("IsServerLobbyFull : humans = %d", humans);
if(IsVersusMode() || IsScavengeMode())
{
return humans >= L4D_MAXHUMANS_LOBBY_VERSUS;
}
return humans >= L4D_MAXHUMANS_LOBBY_OTHER;
}
public OnClientPutInServer(client)
{
DebugPrintToAll("Client put in server %N", client);
if(GetConVarBool(cvarUnreserve) && /*L4D_LobbyIsReserved() &&*/ IsServerLobbyFull())
{
//PrintToChatAll("[SM] A full lobby has connected, automatically unreserving the server.");
L4D_LobbyUnreserve();
}
}
public Action:Command_Unreserve(client, args)
{
/*if(!L4D_LobbyIsReserved())
{
ReplyToCommand(client, "[SM] Server is already unreserved.");
}*/
L4D_LobbyUnreserve();
PrintToChatAll("[SM] Lobby reservation has been removed.");
return Plugin_Handled;
}
//client is in-game and not a bot
stock bool:IsClientInGameHuman(client)
{
return IsClientInGame(client) && !IsFakeClient(client);
}
stock GetHumanCount()
{
new humans = 0;
new i;
for(i = 1; i < L4D_MAXCLIENTS_PLUS1; i++)
{
if(IsClientInGameHuman(i))
{
humans++
}
}
return humans;
}
DebugPrintToAll(const String:format[], any:...)
{
#if UNRESERVE_DEBUG || UNRESERVE_DEBUG_LOG
decl String:buffer[192];
VFormat(buffer, sizeof(buffer), format, 2);
#if UNRESERVE_DEBUG
PrintToChatAll("[UNRESERVE] %s", buffer);
PrintToConsole(0, "[UNRESERVE] %s", buffer);
#endif
LogMessage("%s", buffer);
#else
//suppress "format" never used warning
if(format[0])
return;
else
return;
#endif
}

855
scripting/sceneprocessor.sp Normal file
View file

@ -0,0 +1,855 @@
#define PLUGIN_VERSION "1.33.2"
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <sceneprocessor>
int iSkippedFrames;
char sVocalizeScene[MAXPLAYERS+1][MAX_VOCALIZE_LENGTH];
bool bSceneHasInitiator[MAXPLAYERS+1], bScenesUnprocessed, bUnvocalizedCommands, bJailbreakVocalize, bIsL4D;
float fStartTimeStamp, fVocalizePreDelay[MAXPLAYERS+1], fVocalizePitch[MAXPLAYERS+1];
Handle hSceneStageForward, hVocalizeCommandForward;
ArrayList alVocalize;
ArrayStack asScene;
enum struct SceneData
{
SceneStages ssDataBit;
bool bInFakePostSpawn;
float fTimeStampData;
int iActorData;
int iInitiatorData;
char sFileData[MAX_SCENEFILE_LENGTH];
char sVocalizeData[MAX_VOCALIZE_LENGTH];
float fPreDelayData;
float fPitchData;
}
SceneData nSceneData[2048];
int iScenePlaying[MAXPLAYERS+1], iVocalizeTick[MAXPLAYERS+1], iVocalizeInitiator[MAXPLAYERS+1];
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
EngineVersion evGame = GetEngineVersion();
if (evGame == Engine_Left4Dead)
{
bIsL4D = true;
}
else if (evGame != Engine_Left4Dead2)
{
strcopy(error, err_max, "[SP] Plugin Supports L4D And L4D2 Only!");
return APLRes_Failure;
}
CreateNative("GetSceneStage", SP_GetSceneStage);
CreateNative("GetSceneStartTimeStamp", SP_GetSceneStartTimeStamp);
CreateNative("GetActorFromScene", SP_GetSceneActor);
CreateNative("GetSceneFromActor", SP_GetActorScene);
CreateNative("GetSceneInitiator", SP_GetSceneInitiator);
CreateNative("GetSceneFile", SP_GetSceneFile);
CreateNative("GetSceneVocalize", SP_GetSceneVocalize);
CreateNative("GetScenePreDelay", SP_GetScenePreDelay);
CreateNative("SetScenePreDelay", SP_SetScenePreDelay);
CreateNative("GetScenePitch", SP_GetScenePitch);
CreateNative("SetScenePitch", SP_SetScenePitch);
CreateNative("CancelScene", SP_CancelScene);
CreateNative("PerformScene", SP_PerformScene);
CreateNative("PerformSceneEx", SP_PerformSceneEx);
RegPluginLibrary("sceneprocessor");
return APLRes_Success;
}
public any SP_GetSceneStage(Handle plugin, int numParams)
{
if (numParams == 0)
{
return SceneStage_Unknown;
}
int scene = GetNativeCell(1);
if (scene < 1 || scene > 2048 || !IsValidEntity(scene))
{
return SceneStage_Unknown;
}
return nSceneData[scene].ssDataBit;
}
public any SP_GetSceneStartTimeStamp(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0.0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0.0;
}
return nSceneData[scene].fTimeStampData;
}
public int SP_GetActorScene(Handle plugin, int numParams)
{
if (numParams == 0)
{
return INVALID_ENT_REFERENCE;
}
int iActor = GetNativeCell(1);
if (iActor < 1 || iActor > MaxClients || !IsClientInGame(iActor) || GetClientTeam(iActor) != 2 || !IsPlayerAlive(iActor))
{
return INVALID_ENT_REFERENCE;
}
return iScenePlaying[iActor];
}
public int SP_GetSceneActor(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
return nSceneData[scene].iActorData;
}
public int SP_GetSceneInitiator(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
return nSceneData[scene].iInitiatorData;
}
public int SP_GetSceneFile(Handle plugin, int numParams)
{
if (numParams != 3)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
int len = GetNativeCell(3);
int bytesWritten;
SetNativeString(2, nSceneData[scene].sFileData, len, _, bytesWritten);
return bytesWritten;
}
public int SP_GetSceneVocalize(Handle plugin, int numParams)
{
if (numParams != 3)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
int len = GetNativeCell(3);
int bytesWritten;
SetNativeString(2, nSceneData[scene].sVocalizeData, len, _, bytesWritten);
return bytesWritten;
}
public any SP_GetScenePreDelay(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0.0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0.0;
}
return nSceneData[scene].fPreDelayData;
}
public int SP_SetScenePreDelay(Handle plugin, int numParams)
{
if (numParams != 2)
{
return;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return;
}
float fPreDelay = GetNativeCell(2);
SetEntPropFloat(scene, Prop_Data, "m_flPreDelay", fPreDelay);
nSceneData[scene].fPreDelayData = fPreDelay;
}
public any SP_GetScenePitch(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0.0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0.0;
}
return nSceneData[scene].fPitchData;
}
public int SP_SetScenePitch(Handle plugin, int numParams)
{
if (numParams != 2)
{
return;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return;
}
float fPitch = GetNativeCell(2);
SetEntPropFloat(scene, Prop_Data, "m_fPitch", fPitch);
nSceneData[scene].fPitchData = fPitch;
}
public int SP_CancelScene(Handle plugin, int numParams)
{
if (numParams == 0)
{
return;
}
int scene = GetNativeCell(1);
if (scene < 1 || scene > 2048 || !IsValidEntity(scene))
{
return;
}
SceneStages ssBit = nSceneData[scene].ssDataBit;
if (ssBit == SceneStage_Unknown)
{
return;
}
else if (ssBit == SceneStage_Started || (ssBit == SceneStage_SpawnedPost && nSceneData[scene].bInFakePostSpawn))
{
AcceptEntityInput(scene, "Cancel");
}
else if (ssBit != SceneStage_Cancelled && ssBit != SceneStage_Completion && ssBit != SceneStage_Killed)
{
AcceptEntityInput(scene, "Kill");
}
}
public int SP_PerformScene(Handle plugin, int numParams)
{
if (numParams < 2)
{
return;
}
int client = GetNativeCell(1);
if (client < 1 || client > MaxClients || !IsClientInGame(client) || GetClientTeam(client) != 2 || !IsPlayerAlive(client))
{
return;
}
static char sVocalize[MAX_VOCALIZE_LENGTH], sFile[MAX_SCENEFILE_LENGTH];
float fPreDelay = DEFAULT_SCENE_PREDELAY, fPitch = DEFAULT_SCENE_PITCH;
int iInitiator = SCENE_INITIATOR_PLUGIN;
if (GetNativeString(2, sVocalize, MAX_VOCALIZE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown Vocalize Parameter!");
return;
}
if (numParams >= 3)
{
if (GetNativeString(3, sFile, MAX_SCENEFILE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown File Parameter!");
return;
}
}
if (numParams >= 4)
{
fPreDelay = GetNativeCell(4);
}
if (numParams >= 5)
{
fPitch = GetNativeCell(5);
}
if (numParams >= 6)
{
iInitiator = GetNativeCell(6);
}
Scene_Perform(client, sVocalize, sFile, fPreDelay, fPitch, iInitiator);
}
public int SP_PerformSceneEx(Handle plugin, int numParams)
{
if (numParams < 2)
{
return;
}
int client = GetNativeCell(1);
if (client < 1 || client > MaxClients || !IsClientInGame(client) || GetClientTeam(client) != 2 || !IsPlayerAlive(client))
{
return;
}
static char sVocalize[MAX_VOCALIZE_LENGTH], sFile[MAX_SCENEFILE_LENGTH];
float fPreDelay = DEFAULT_SCENE_PREDELAY, fPitch = DEFAULT_SCENE_PITCH;
int iInitiator = SCENE_INITIATOR_PLUGIN;
if (GetNativeString(2, sVocalize, MAX_VOCALIZE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown Vocalize Parameter!");
return;
}
if (numParams >= 3)
{
if (GetNativeString(3, sFile, MAX_SCENEFILE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown File Parameter!");
return;
}
}
if (numParams >= 4)
{
fPreDelay = GetNativeCell(4);
}
if (numParams >= 5)
{
fPitch = GetNativeCell(5);
}
if (numParams >= 6)
{
iInitiator = GetNativeCell(6);
}
Scene_Perform(client, sVocalize, sFile, fPreDelay, fPitch, iInitiator, true);
}
public Plugin myinfo =
{
name = "Scene Processor",
author = "Buster \"Mr. Zero\" Nielsen (Fork by cravenge & Dragokas)",
description = "Provides Forwards and Natives For Scenes' Manipulation.",
version = PLUGIN_VERSION,
url = "https://forums.alliedmods.net/showthread.php?t=241585"
};
public void OnPluginStart()
{
hSceneStageForward = CreateGlobalForward("OnSceneStageChanged", ET_Ignore, Param_Cell, Param_Cell);
hVocalizeCommandForward = CreateGlobalForward("OnVocalizeCommand", ET_Hook, Param_Cell, Param_String, Param_Cell);
CreateConVar("sceneprocessor_version", PLUGIN_VERSION, "Scene Processor Version", FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD);
if (!bIsL4D)
{
ConVar spJailbreakVocalize = CreateConVar("sceneprocessor_jailbreak_vocalize", "1", "Enable/Disable Jailbreak Vocalizations", FCVAR_SPONLY|FCVAR_NOTIFY);
spJailbreakVocalize.AddChangeHook(OnSPCVarChanged);
bJailbreakVocalize = spJailbreakVocalize.BoolValue;
}
AddCommandListener(OnVocalizeCmd, "vocalize");
asScene = new ArrayStack();
alVocalize = new ArrayList(MAX_VOCALIZE_LENGTH);
for (int i = 1; i < 2049; i++)
{
if (IsValidEntity(i) && IsValidEdict(i))
{
SceneData_SetStage(i, SceneStage_Unknown);
}
}
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i))
{
ResetClientVocalizeData(i);
}
}
}
public void OnSPCVarChanged(ConVar cvar, const char[] sOldValue, const char[] sNewValue)
{
bJailbreakVocalize = cvar.BoolValue;
}
public Action OnVocalizeCmd(int client, const char[] command, int args)
{
if (client == 0 || args == 0)
{
return Plugin_Continue;
}
if (!IsClientInGame(client))
{
return Plugin_Handled;
}
static char sVocalize[128];
GetCmdArg(1, sVocalize, sizeof(sVocalize));
if (!bIsL4D && args != 2)
{
if (bJailbreakVocalize)
{
JailbreakVocalize(client, sVocalize);
}
return Plugin_Handled;
}
int iTick = GetGameTickCount();
if (!bSceneHasInitiator[client] || (iVocalizeTick[client] > 0 && iVocalizeTick[client] != iTick))
{
iVocalizeInitiator[client] = client;
if (!bIsL4D && args > 1 && StrEqual(sVocalize, "smartlook", false))
{
static char sTime[32];
GetCmdArg(2, sTime, sizeof(sTime));
if (StrEqual(sTime, "auto", false))
{
iVocalizeInitiator[client] = SCENE_INITIATOR_WORLD;
}
}
}
strcopy(sVocalizeScene[client], MAX_VOCALIZE_LENGTH, sVocalize);
iVocalizeTick[client] = iTick;
Action aResult = Plugin_Continue;
Call_StartForward(hVocalizeCommandForward);
Call_PushCell(client);
Call_PushString(sVocalize);
Call_PushCell(iVocalizeInitiator[client]);
Call_Finish(aResult);
return (aResult == Plugin_Stop) ? Plugin_Handled : Plugin_Continue;
}
public void OnPluginEnd()
{
RemoveCommandListener(OnVocalizeCmd, "vocalize");
}
public void OnMapStart()
{
iSkippedFrames = 0;
fStartTimeStamp = GetGameTime();
}
public void OnEntityCreated(int entity, const char[] classname)
{
if (entity < 1 || entity > 2048)
{
return;
}
if (StrEqual(classname, "instanced_scripted_scene"))
{
SDKHook(entity, SDKHook_SpawnPost, OnSpawnPost);
SceneData_SetStage(entity, SceneStage_Created);
}
}
public void OnSpawnPost(int entity)
{
int iActor = GetEntPropEnt(entity, Prop_Data, "m_hOwner");
nSceneData[entity].iActorData = iActor;
static char sFile[MAX_SCENEFILE_LENGTH];
GetEntPropString(entity, Prop_Data, "m_iszSceneFile", sFile, MAX_SCENEFILE_LENGTH);
strcopy(nSceneData[entity].sFileData, MAX_SCENEFILE_LENGTH, sFile);
nSceneData[entity].fPitchData = GetEntPropFloat(entity, Prop_Data, "m_fPitch");
if (iActor > 0 && iActor <= MaxClients && IsClientInGame(iActor))
{
if (iVocalizeTick[iActor] == GetGameTickCount())
{
strcopy(nSceneData[entity].sVocalizeData, MAX_VOCALIZE_LENGTH, sVocalizeScene[iActor]);
nSceneData[entity].iInitiatorData = iVocalizeInitiator[iActor];
nSceneData[entity].fPreDelayData = fVocalizePreDelay[iActor];
nSceneData[entity].fPitchData = fVocalizePitch[iActor];
}
ResetClientVocalizeData(iActor);
}
SetEntPropFloat(entity, Prop_Data, "m_fPitch", nSceneData[entity].fPitchData);
SetEntPropFloat(entity, Prop_Data, "m_flPreDelay", nSceneData[entity].fPreDelayData);
asScene.Push(entity);
bScenesUnprocessed = true;
HookSingleEntityOutput(entity, "OnStart", OnSceneStart_EntOutput);
HookSingleEntityOutput(entity, "OnCanceled", OnSceneCanceled_EntOutput);
SceneData_SetStage(entity, SceneStage_Spawned);
}
public void OnSceneStart_EntOutput(const char[] output, int caller, int activator, float delay)
{
if (caller < 1 || caller > 2048 || !IsValidEntity(caller))
{
return;
}
static char sFile[MAX_SCENEFILE_LENGTH];
strcopy(sFile, MAX_SCENEFILE_LENGTH, nSceneData[caller].sFileData);
if (!sFile[0])
{
return;
}
nSceneData[caller].fTimeStampData = GetEngineTime();
if (nSceneData[caller].ssDataBit == SceneStage_Spawned)
{
nSceneData[caller].bInFakePostSpawn = true;
SceneData_SetStage(caller, SceneStage_SpawnedPost);
}
if (nSceneData[caller].ssDataBit == SceneStage_SpawnedPost)
{
int iActor = nSceneData[caller].iActorData;
if (iActor > 0 && iActor <= MaxClients && IsClientInGame(iActor))
{
iScenePlaying[iActor] = caller;
}
SceneData_SetStage(caller, SceneStage_Started);
}
}
public void OnSceneCanceled_EntOutput(const char[] output, int caller, int activator, float delay)
{
if (caller < 1 || caller > 2048 || !IsValidEntity(caller))
{
return;
}
for (int i = 1; i <= MaxClients; i++)
{
if (iScenePlaying[i] == caller)
{
iScenePlaying[i] = INVALID_ENT_REFERENCE;
break;
}
}
SceneData_SetStage(caller, SceneStage_Cancelled);
}
public void OnEntityDestroyed(int entity)
{
if (entity < 1 || entity > 2048 || !IsValidEdict(entity))
{
return;
}
static char sEntityClass[64];
GetEdictClassname(entity, sEntityClass, sizeof(sEntityClass));
if (!StrEqual(sEntityClass, "instanced_scripted_scene"))
{
return;
}
SDKUnhook(entity, SDKHook_SpawnPost, OnSpawnPost);
SceneStages ssBit = nSceneData[entity].ssDataBit;
if (ssBit != SceneStage_Unknown)
{
if (ssBit == SceneStage_Started)
{
SceneData_SetStage(entity, SceneStage_Completion);
}
SceneData_SetStage(entity, SceneStage_Killed);
for (int i = 1; i <= MaxClients; i++)
{
if (!IsClientInGame(i) || iScenePlaying[i] != entity)
{
continue;
}
iScenePlaying[i] = INVALID_ENT_REFERENCE;
break;
}
}
SceneData_SetStage(entity, SceneStage_Unknown);
}
public void OnClientDisconnect(int client)
{
if (client == 0)
{
return;
}
iScenePlaying[client] = INVALID_ENT_REFERENCE;
}
public void OnGameFrame()
{
iSkippedFrames += 1;
if (iSkippedFrames < 3)
{
return;
}
iSkippedFrames = 1;
if (bScenesUnprocessed)
{
bScenesUnprocessed = false;
int dScene;
while (!asScene.Empty)
{
asScene.Pop(dScene);
if (dScene < 1 || dScene > 2048 || !IsValidEntity(dScene))
{
continue;
}
if (nSceneData[dScene].ssDataBit != SceneStage_Spawned)
{
continue;
}
nSceneData[dScene].fPreDelayData = GetEntPropFloat(dScene, Prop_Data, "m_flPreDelay");
nSceneData[dScene].bInFakePostSpawn = false;
SceneData_SetStage(dScene, SceneStage_SpawnedPost);
}
}
if (bUnvocalizedCommands)
{
int iArraySize = alVocalize.Length,
iCurrentTick = GetGameTickCount();
static char sVocalize[MAX_VOCALIZE_LENGTH];
float fPreDelay, fPitch;
int client, dInitiator, dTick;
for (int i = 0; i < iArraySize; i += 6)
{
dTick = alVocalize.Get(i + 5);
if (iCurrentTick != dTick)
{
continue;
}
client = alVocalize.Get(i + 0);
alVocalize.GetString(i + 1, sVocalize, MAX_VOCALIZE_LENGTH);
fPreDelay = view_as<float>(alVocalize.Get(i + 2));
fPitch = view_as<float>(alVocalize.Get(i + 3));
dInitiator = alVocalize.Get(i + 4);
Scene_Perform(client, sVocalize, _, fPreDelay, fPitch, dInitiator, true);
for (int j = 0; j < 6; j++)
{
alVocalize.Erase(i);
iArraySize -= 1;
}
}
if (iArraySize < 1)
{
alVocalize.Clear();
bUnvocalizedCommands = false;
}
}
}
public void OnMapEnd()
{
iSkippedFrames = 0;
bScenesUnprocessed = false;
bUnvocalizedCommands = false;
while (!asScene.Empty)
{
PopStack(asScene);
}
alVocalize.Clear();
for (int i = 1; i < 2049; i++)
{
if (IsValidEntity(i) && IsValidEdict(i))
{
SceneData_SetStage(i, SceneStage_Unknown);
}
}
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i))
{
iScenePlaying[i] = INVALID_ENT_REFERENCE;
}
}
}
void ResetClientVocalizeData(int client)
{
iVocalizeTick[client] = 0;
sVocalizeScene[client] = "\0";
bSceneHasInitiator[client] = false;
iVocalizeInitiator[client] = SCENE_INITIATOR_WORLD;
fVocalizePreDelay[client] = DEFAULT_SCENE_PREDELAY;
fVocalizePitch[client] = DEFAULT_SCENE_PITCH;
}
void SceneData_SetStage(int scene, SceneStages stage)
{
nSceneData[scene].ssDataBit = stage;
if (stage != SceneStage_Unknown)
{
Call_StartForward(hSceneStageForward);
Call_PushCell(scene);
Call_PushCell(stage);
Call_Finish();
}
else
{
nSceneData[scene].bInFakePostSpawn = false;
nSceneData[scene].fTimeStampData = 0.0;
nSceneData[scene].iActorData = 0;
nSceneData[scene].iInitiatorData = 0;
strcopy(nSceneData[scene].sFileData, MAX_SCENEFILE_LENGTH, "\0");
strcopy(nSceneData[scene].sVocalizeData, MAX_VOCALIZE_LENGTH, "\0");
nSceneData[scene].fPreDelayData = DEFAULT_SCENE_PREDELAY;
nSceneData[scene].fPitchData = DEFAULT_SCENE_PITCH;
}
}
void Scene_Perform(int client, const char[] sVocalizeParam, const char[] sFileParam = "", float fScenePreDelay = DEFAULT_SCENE_PREDELAY, float fScenePitch = DEFAULT_SCENE_PITCH, int iSceneInitiator = SCENE_INITIATOR_PLUGIN, bool bVocalizeNow = false)
{
if (sFileParam[0] && FileExists(sFileParam, true))
{
int iScene = CreateEntityByName("instanced_scripted_scene");
DispatchKeyValue(iScene, "SceneFile", sFileParam);
SetEntPropEnt(iScene, Prop_Data, "m_hOwner", client);
nSceneData[iScene].iActorData = client;
SetEntPropFloat(iScene, Prop_Data, "m_flPreDelay", fScenePreDelay);
nSceneData[iScene].fPreDelayData = fScenePreDelay;
SetEntPropFloat(iScene, Prop_Data, "m_fPitch", fScenePitch);
nSceneData[iScene].fPitchData = fScenePitch;
nSceneData[iScene].iInitiatorData = iSceneInitiator;
strcopy(nSceneData[iScene].sVocalizeData, MAX_VOCALIZE_LENGTH, sVocalizeParam);
DispatchSpawn(iScene);
ActivateEntity(iScene);
AcceptEntityInput(iScene, "Start", client, client);
}
else if (sVocalizeParam[0])
{
if (bVocalizeNow)
{
iVocalizeInitiator[client] = iSceneInitiator;
bSceneHasInitiator[client] = true;
fVocalizePreDelay[client] = fScenePreDelay;
fVocalizePitch[client] = fScenePitch;
if (bIsL4D)
{
FakeClientCommandEx(client, "vocalize %s", sVocalizeParam);
}
else
{
JailbreakVocalize(client, sVocalizeParam);
}
}
else
{
alVocalize.Push(client);
alVocalize.PushString(sVocalizeParam);
alVocalize.Push(fScenePreDelay);
alVocalize.Push(fScenePitch);
alVocalize.Push(iSceneInitiator);
alVocalize.Push(GetGameTickCount() + 10 - 1);
bUnvocalizedCommands = true;
}
}
}
void JailbreakVocalize(int client, const char[] sVocalize)
{
char sBuffer[2][32];
FloatToString((GetGameTime() - fStartTimeStamp) + 2.0, sBuffer[0], 32);
ExplodeString(sBuffer[0], ".", sBuffer, 2, 32);
Format(sBuffer[1], 2, "%s\0", sBuffer[1][0]);
FakeClientCommandEx(client, "vocalize %s #%s%s", sVocalize, sBuffer[0], sBuffer[1]);
}