View Single Post
Author Message
finishlast
Senior Member
Join Date: Nov 2018
Location: In Reno with the vitamin D.
Old 07-09-2019 , 09:31   L4d / Prevent Smokers from smoking last survivor
Reply With Quote #1

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);
	}
}

Last edited by finishlast; 07-17-2019 at 13:42.
finishlast is offline