mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-05 16:13:20 +00:00
Update updated part of README.md
This commit is contained in:
parent
73fa3ea30f
commit
f1ad9f3865
21 changed files with 4934 additions and 89 deletions
|
@ -166,7 +166,7 @@ This really only affects wandering zombies, mobs and panic events, but it may wo
|
|||
### l4d2_feedthetrolls
|
||||
This plugin allows you to enact certain troll modes on any player, some are subtle some are less so. Either way, it works great to deal with a rusher, an asshole or even your friends.
|
||||
|
||||
Troll Modes: (updated 1/2/2021)
|
||||
Troll Modes: (updated 4/20/2021)
|
||||
|
||||
1. **SlowSpeed** (0.8 < 1.0 base) - Slows down a user
|
||||
2. **HigherGravity** (1.3 > 1.0) - Adds more gravity to a user
|
||||
|
|
BIN
plugins/BumpMineGiver.smx
Normal file
BIN
plugins/BumpMineGiver.smx
Normal file
Binary file not shown.
BIN
plugins/L4D2PreventBotMovement.smx
Normal file
BIN
plugins/L4D2PreventBotMovement.smx
Normal file
Binary file not shown.
BIN
plugins/l4d2_drop_secondary.smx
Normal file
BIN
plugins/l4d2_drop_secondary.smx
Normal file
Binary file not shown.
BIN
plugins/l4d2_skill_detect.smx
Normal file
BIN
plugins/l4d2_skill_detect.smx
Normal file
Binary file not shown.
BIN
plugins/l4d2_target_test.smx
Normal file
BIN
plugins/l4d2_target_test.smx
Normal file
Binary file not shown.
Binary file not shown.
BIN
plugins/l4d_target_override.smx
Normal file
BIN
plugins/l4d_target_override.smx
Normal file
Binary file not shown.
BIN
plugins/l4dunreservelobby.smx
Normal file
BIN
plugins/l4dunreservelobby.smx
Normal file
Binary file not shown.
BIN
plugins/left4dhooks.smx
Normal file
BIN
plugins/left4dhooks.smx
Normal file
Binary file not shown.
BIN
plugins/sceneprocessor.smx
Normal file
BIN
plugins/sceneprocessor.smx
Normal file
Binary file not shown.
|
@ -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
114
scripting/BumpMineGiver.sp
Normal 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;
|
||||
}
|
57
scripting/L4D2PreventBotMovement.sp
Normal file
57
scripting/L4D2PreventBotMovement.sp
Normal 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
60
scripting/csgo-misc.sp
Normal 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);
|
||||
}
|
233
scripting/l4d2_drop_secondary.sp
Normal file
233
scripting/l4d2_drop_secondary.sp
Normal 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);
|
||||
}
|
||||
}
|
3125
scripting/l4d2_skill_detect.sp
Normal file
3125
scripting/l4d2_skill_detect.sp
Normal file
File diff suppressed because it is too large
Load diff
136
scripting/l4d2_target_test.sp
Normal file
136
scripting/l4d2_target_test.sp
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
|
|
149
scripting/l4dunreservelobby.sp
Normal file
149
scripting/l4dunreservelobby.sp
Normal 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
855
scripting/sceneprocessor.sp
Normal 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]);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue