Hi,
I'm pretty sure I saw that one on a russian server a while ago but I wasn't able to find the plugin.
Anyway what I would like to see is a plugin that checks if all survivors -1 are at least dead, pounced, hanging on ledge or incapped and then prevent the smoker from smoking last.
Preferable make it possible to set a value for chat or hud in cfg to show a message like "You are not allowed to smoke last!" and the option to slay that smoker instantly (or disable the tongue).
*******
As it is now it should support +8 Player servers with multiple smoker.
*******
Slapping the player by SlapPlayer command didn't work 100% to break tongue but thanks to xZk I just alter the smoker position and that seems to break the tongue now.
Code:
/********************************************************************************************
* Plugin : L4DNoSmoking
* Version : 1.0.0
* Game : Left 4 Dead
* Author : Finishlast
* Parts taken from:
* [L4D, L4D2] No Death Check Until Dead
* https://forums.alliedmods.net/showthread.php?t=142432
* [L4D & L4D2] Survivor Bot Takeover v0.8
* https://forums.alliedmods.net/showthread.php?p=1192594
* And TeleportEntity suggestion by xZk
* Testers : Myself
* Website : www.l4d.com
* Purpose : Prevents smoker from smoking last survivor.
********************************************************************************************/
#include <sourcemod>
#include <sdktools>
#define CVAR_FLAGS FCVAR_NOTIFY
#define CVAR_FLAGS_PLUGIN_VERSION FCVAR_NOTIFY|FCVAR_DONTRECORD|FCVAR_SPONLY
#define PLUGIN_NAME "L4DNoSmoking"
#define PLUGIN_VERSION "1.0.0"
#define IS_VALID_CLIENT(%1) (%1 > 0 && %1 <= MaxClients)
#define IS_CONNECTED_INGAME(%1) (IsClientConnected(%1) && IsClientInGame(%1))
#define IS_SURVIVOR(%1) (GetClientTeam(%1) == 2)
#define IS_INFECTED(%1) (GetClientTeam(%1) == 3)
#define IS_VALID_INGAME(%1) (IS_VALID_CLIENT(%1) && IS_CONNECTED_INGAME(%1))
#define IS_VALID_SURVIVOR(%1) (IS_VALID_INGAME(%1) && IS_SURVIVOR(%1))
#define IS_VALID_INFECTED(%1) (IS_VALID_INGAME(%1) && IS_INFECTED(%1))
#define IS_SURVIVOR_ALIVE(%1) (IS_VALID_SURVIVOR(%1) && IsPlayerAlive(%1))
#define IS_INFECTED_ALIVE(%1) (IS_VALID_INFECTED(%1) && IsPlayerAlive(%1))
new Handle:cvar_killorslap;
new Handle:cvar_displaykillmessage;
new survivorslotscount = 0;
new l4dver;
public Plugin myinfo =
{
name = PLUGIN_NAME,
author = "Finishlast",
description = "Prevents smoker from smoking last survivor.",
version = PLUGIN_VERSION,
url = "www.l4d.com"
}
public OnPluginStart()
{
CreateConVar("L4DNoSmoking_version", PLUGIN_VERSION, "L4DNoSmoking_version", CVAR_FLAGS_PLUGIN_VERSION);
cvar_killorslap = CreateConVar("killorslap", "1", "1 kill smoker or 2 slap smoker", CVAR_FLAGS);
cvar_displaykillmessage = CreateConVar("displaykillmessage", "3", " 0 - Disabled; 1 - small HUD Hint; 2 - big HUD Hint; 3 - Chat Notification ", CVAR_FLAGS);
AutoExecConfig(true, "L4DNoSmoking");
HookEvent("tongue_grab", tongue_grab);
HookEvent("player_spawn", PlayerSpawn);
char GameName[12];
GetGameFolderName(GameName, sizeof(GameName));
if (StrEqual(GameName, "left4dead2", false))
{
l4dver = 2;
}
else
{
l4dver = 1;
}
}
public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
survivorslotscount = 0
for (new i = 1; i <= MaxClients; i++)
{
if (IS_VALID_SURVIVOR(i))
{
survivorslotscount++;
}
}
return Plugin_Continue;
}
public Action:tongue_grab(Handle:event, const String:name[], bool:dontBroadcast)
{
new displaykillmessage = GetConVarInt(cvar_displaykillmessage);
new killorslap = GetConVarInt(cvar_killorslap);
new id = GetClientOfUserId(GetEventInt(event, "userid"));
if (IS_INFECTED_ALIVE(id))
{
new survivors = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IS_SURVIVOR_ALIVE(i) && GetClientHealth(i) > 0 )
{
survivors++;
}
}
new incappedsurvivors = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IS_VALID_SURVIVOR(i))
{
if (l4dver == 1)
{
if (IsClientIncapacitatedl4d1(i) == true)
{
incappedsurvivors++;
}
}
else
{
if (IsClientIncapacitatedl4d2(i) == true)
{
incappedsurvivors++;
}
}
}
}
new dead = survivorslotscount - survivors;
new lastmanstanding = survivorslotscount - incappedsurvivors - dead;
if(lastmanstanding == 0)
{
new String:PlayerName[200];
GetClientName(id, PlayerName, sizeof(PlayerName));
switch (killorslap)
{
case 1:
PerformKill(id, displaykillmessage,PlayerName);
case 2:
PerformSlap(id, displaykillmessage,PlayerName);
}
}
}
return Plugin_Continue;
}
stock bool:IsClientIncapacitatedl4d1(client)
{
return GetEntProp(client, Prop_Send, "m_isIncapacitated") != 0 || // incap
GetEntProp(client, Prop_Send, "m_isHangingFromLedge") != 0 || // incap ledge
GetEntProp(client, Prop_Send, "m_isFallingFromLedge") != 0 || // incap fall
GetEntProp(client, Prop_Send, "m_isHangingFromTongue") != 0 || // smoker ledge
GetEntProp(client, Prop_Send, "m_tongueOwner") > 0 || // smoker
GetEntProp(client, Prop_Send, "m_pounceAttacker") > 0 ; // hunter
}
stock bool:IsClientIncapacitatedl4d2(client)
{
return GetEntProp(client, Prop_Send, "m_isIncapacitated") != 0 || // incap
GetEntProp(client, Prop_Send, "m_isHangingFromLedge") != 0 || // incap ledge
GetEntProp(client, Prop_Send, "m_isFallingFromLedge") != 0 || // incap fall
GetEntProp(client, Prop_Send, "m_isHangingFromTongue") != 0 || // smoker ledge
GetEntProp(client, Prop_Send, "m_carryAttacker") > 0 || // charger
GetEntProp(client, Prop_Send, "m_pummelAttacker") > 0 || // charger
GetEntProp(client, Prop_Send, "m_jockeyAttacker") > 0 || // jockey
GetEntProp(client, Prop_Send, "m_tongueOwner") > 0 || // smoker
GetEntProp(client, Prop_Send, "m_pounceAttacker") > 0 ; // hunter
}
void PerformKill(int id, int displaykillmessage, const char[] PlayerName)
{
ForcePlayerSuicide(id);
switch (displaykillmessage)
{
case 1:
PrintCenterTextAll("[SM] %s was socked for smoking last.", PlayerName);
case 2:
PrintHintTextToAll("[SM] %s was socked for smoking last.", PlayerName);
case 3:
PrintToChatAll("\x01\x04[SM] \x03%s \x01was socked for smoking last.", PlayerName);
}
}
void PerformSlap(int id, int displaykillmessage, const char[] PlayerName)
{
new Float:vpos[3];
new Float:vec[3];
GetEntPropVector(id, Prop_Data, "m_vecOrigin", vpos);
vec[0] = vpos[0]+0.0;
vec[1] = vpos[1]+0.0;
vec[2] = vpos[2]+30.0;
TeleportEntity(id, vec, NULL_VECTOR, NULL_VECTOR);
switch (displaykillmessage)
{
case 1:
PrintCenterTextAll("[SM] %s was slapped for smoking last.", PlayerName);
case 2:
PrintHintTextToAll("[SM] %s was slapped for smoking last.", PlayerName);
case 3:
PrintToChatAll("\x01\x04[SM] \x03%s \x01was slapped for smoking last.", PlayerName);
}
}