#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#define PLUGIN_VERSION "1.0"
#define GRENADE_USERID 0
#define GRENADE_TEAM 1
#define GRENADE_PROJECTILE 2
#define GRENADE_PARTICLE 3
#define GRENADE_REMOVETIMER 4
#define GRENADE_DAMAGETIMER 5
new Handle:g_hSmokeGrenades;
new Handle:g_hCVDamage;
new Handle:g_hCVSeconds;
new Handle:g_hCVFriendlyFire;
public Plugin:myinfo =
{
name = "Poison Smoke",
author = "Jannik \"Peace-Maker\" Hartung",
description = "Damages anyone who walks into a smokegrenade",
version = PLUGIN_VERSION,
url = "http://www.wcfan.de/"
}
public OnPluginStart()
{
new Handle:hVersion = CreateConVar("sm_posionsmoke_version", PLUGIN_VERSION, "Poison Smoke version", FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_DONTRECORD);
if(hVersion != INVALID_HANDLE)
SetConVarString(hVersion, PLUGIN_VERSION);
g_hCVDamage = CreateConVar("sm_poisonsmoke_damage", "5", "How much damage should we deal to the players in the smoke?", FCVAR_PLUGIN, true, 1.0);
g_hCVSeconds = CreateConVar("sm_poisonsmoke_seconds", "1", "Deal damage every x seconds.", FCVAR_PLUGIN, true, 1.0);
g_hCVFriendlyFire = FindConVar("mp_friendlyfire");
g_hSmokeGrenades = CreateArray();
HookEvent("round_start", Event_OnResetSmokes);
HookEvent("round_end", Event_OnResetSmokes);
}
public OnMapEnd()
{
new iSize = GetArraySize(g_hSmokeGrenades);
new Handle:hGrenade, Handle:hTimer;
for(new i=0; i<iSize; i++)
{
hGrenade = GetArrayCell(g_hSmokeGrenades, i);
if(GetArraySize(hGrenade) > 3)
{
hTimer = GetArrayCell(hGrenade, GRENADE_REMOVETIMER);
KillTimer(hTimer);
hTimer = GetArrayCell(hGrenade, GRENADE_DAMAGETIMER);
KillTimer(hTimer);
}
CloseHandle(hGrenade);
}
ClearArray(g_hSmokeGrenades);
}
public Event_OnResetSmokes(Handle:event, const String:name[], bool:dontBroadcast)
{
new iSize = GetArraySize(g_hSmokeGrenades);
new Handle:hGrenade, Handle:hTimer;
for(new i=0; i<iSize; i++)
{
hGrenade = GetArrayCell(g_hSmokeGrenades, i);
if(GetArraySize(hGrenade) > 3)
{
hTimer = GetArrayCell(hGrenade, GRENADE_REMOVETIMER);
KillTimer(hTimer);
hTimer = GetArrayCell(hGrenade, GRENADE_DAMAGETIMER);
KillTimer(hTimer);
}
CloseHandle(hGrenade);
}
ClearArray(g_hSmokeGrenades);
}
public OnEntityCreated(entity, const String:classname[])
{
if(StrEqual(classname, "smokegrenade_projectile", false))
{
SDKHook(entity, SDKHook_Spawn, Hook_OnSpawnProjectile);
}
if(StrEqual(classname, "env_particlesmokegrenade", false))
{
SDKHook(entity, SDKHook_Spawn, Hook_OnSpawnParticles);
}
}
public Hook_OnSpawnProjectile(entity)
{
new client = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
// Save that smoke in our array
new Handle:hGrenade = CreateArray();
PushArrayCell(hGrenade, GetClientUserId(client));
PushArrayCell(hGrenade, GetClientTeam(client));
PushArrayCell(hGrenade, entity);
PushArrayCell(g_hSmokeGrenades, hGrenade);
}
public Hook_OnSpawnParticles(entity)
{
new Float:fOrigin[3], Float:fOriginSmoke[3];
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", fOrigin);
new iSize = GetArraySize(g_hSmokeGrenades);
new Handle:hGrenade, iGrenade;
for(new i=0; i<iSize; i++)
{
hGrenade = GetArrayCell(g_hSmokeGrenades, i);
iGrenade = GetArrayCell(hGrenade, GRENADE_PROJECTILE);
GetEntPropVector(iGrenade, Prop_Send, "m_vecOrigin", fOriginSmoke);
if(fOrigin[0] == fOriginSmoke[0] && fOrigin[1] == fOriginSmoke[1] && fOrigin[2] == fOriginSmoke[2])
{
PushArrayCell(hGrenade, entity);
// Try to set the color.. Doesn't really work though
SetVariantString("124 252 0");
AcceptEntityInput(entity, "Color");
DispatchKeyValue(entity, "Color1", "124 252 0"); //red green blue
DispatchKeyValue(entity, "Color2", "124 252 0"); //red green blue
new Handle:hTimer = CreateTimer(GetEntPropFloat(entity, Prop_Send, "m_FadeStartTime")+3.0, Timer_RemoveSmoke, entity, TIMER_FLAG_NO_MAPCHANGE);
PushArrayCell(hGrenade, hTimer);
new Handle:hTimer2 = CreateTimer(GetConVarFloat(g_hCVSeconds), Timer_CheckDamage, entity, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
PushArrayCell(hGrenade, hTimer2);
break;
}
}
}
// Remove the poison effect, 2 seconds before the smoke is completely vanished
public Action:Timer_RemoveSmoke(Handle:timer, any:entity)
{
// Get the grenade array with this entity index
new iSize = GetArraySize(g_hSmokeGrenades);
new Handle:hGrenade, iGrenade = -1;
for(new i=0; i<iSize; i++)
{
hGrenade = GetArrayCell(g_hSmokeGrenades, i);
if(GetArraySize(hGrenade) > 3)
{
iGrenade = GetArrayCell(hGrenade, GRENADE_PARTICLE);
// This is the right grenade
// Remove it
if(iGrenade == entity)
{
new Handle:hTimer = GetArrayCell(hGrenade, GRENADE_DAMAGETIMER);
KillTimer(hTimer);
RemoveFromArray(g_hSmokeGrenades, i);
break;
}
}
}
return Plugin_Stop;
}
// Do damage every seconds to players in the smoke
public Action:Timer_CheckDamage(Handle:timer, any:entity)
{
// Get the grenade array with this entity index
new iSize = GetArraySize(g_hSmokeGrenades);
new Handle:hGrenade, iGrenade = -1;
for(new i=0; i<iSize; i++)
{
hGrenade = GetArrayCell(g_hSmokeGrenades, i);
if(GetArraySize(hGrenade) > 3)
{
iGrenade = GetArrayCell(hGrenade, GRENADE_PARTICLE);
if(iGrenade == entity)
break;
}
}
if(iGrenade == -1)
return Plugin_Continue;
new userid = GetArrayCell(hGrenade, GRENADE_USERID);
// Don't do anything, if the client who's thrown the grenade left.
new client = GetClientOfUserId(userid);
if(!client)
return Plugin_Continue;
new Float:fSmokeOrigin[3], Float:fOrigin[3];
GetEntPropVector(iGrenade, Prop_Send, "m_vecOrigin", fSmokeOrigin);
new iGrenadeTeam = GetArrayCell(hGrenade, GRENADE_TEAM);
new bool:bFriendlyFire = GetConVarBool(g_hCVFriendlyFire);
for(new i=1;i<=MaxClients;i++)
{
if(IsClientInGame(i) && IsPlayerAlive(i) && (bFriendlyFire || GetClientTeam(i) != iGrenadeTeam))
{
GetClientAbsOrigin(i, fOrigin);
if(GetVectorDistance(fSmokeOrigin, fOrigin) <= 220)
SDKHooks_TakeDamage(i, iGrenade, client, GetConVarFloat(g_hCVDamage), DMG_POISON, -1, NULL_VECTOR, fSmokeOrigin);
}
}
return Plugin_Continue;
}