Code:
#pragma semicolon 1
#include <sourcemod>
#include <clientprefs>
#include <sdktools>
#include <sdkhooks>
#include <morecolors>
#define SND_SHOOT "weapons/grenade_launcher_shoot.wav"
#define SND_WARN "misc/doomsday_lift_warning.wav"
#define MDL_BOMBLET "models/weapons/w_models/w_stickybomb.mdl"
#define PARTICLE_EXPLOSION "merasmus_bomb_explosion"
new Handle:g_hCvarEnabled, bool:g_bCvarEnabled;
new Handle:g_hCvarSpawnDelay, Float:g_flCvarSpawnDelay;
new Handle:g_hCvarBombDamage, Float:g_flCvarBombDamage;
/* added by fluxX */
new Handle:g_hCookieMiniBombs = INVALID_HANDLE;
new bool:g_bSpawnMiniBombs[MAXPLAYERS+1] = {true,...};
new bool:g_bIsDonor[MAXPLAYERS+1] = {false, ...};
new g_iMiniBombOwner[MAXPLAYERS+1] = {-1,...};
public Plugin:myinfo =
{
name = "[TF2] Minibombs",
author = "Pelipoika, fluxX",
description = "Makes stickies spit out lil bomblets",
version = "1.0",
url = "http://www.sourcemod.net/"
}
public OnPluginStart()
{
g_hCvarEnabled = CreateConVar("sm_minibombs_enabled", "1.0", "Enable Minibombs \n0 = Disabled\n1 = Enabled", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bCvarEnabled = GetConVarBool(g_hCvarEnabled);
HookConVarChange(g_hCvarEnabled, OnConVarChange);
g_hCvarSpawnDelay = CreateConVar("sm_minibombs_spawndelay", "5.0", "How often should a sticky spawn a minibomb? (Seconds)", FCVAR_PLUGIN, true, 0.0);
g_flCvarSpawnDelay = GetConVarFloat(g_hCvarSpawnDelay);
HookConVarChange(g_hCvarSpawnDelay, OnConVarChange);
g_hCvarBombDamage = CreateConVar("sm_minibombs_damage", "20.0", "How much damage should a minibomb do?", FCVAR_PLUGIN, true, 0.0);
g_flCvarBombDamage = GetConVarFloat(g_hCvarBombDamage);
HookConVarChange(g_hCvarBombDamage, OnConVarChange);
RegConsoleCmd("sm_minibombs", Cmd_MiniBombs);
g_hCookieMiniBombs = RegClientCookie("sm_minibombs_spawn", "Spawn minibombs", CookieAccess_Protected);
LoadTranslations("core.phrases");
}
public OnConVarChange(Handle:hConvar, const String:strOldValue[], const String:strNewValue[])
{
g_bCvarEnabled = GetConVarBool(g_hCvarEnabled);
g_flCvarSpawnDelay = GetConVarFloat(g_hCvarSpawnDelay);
g_flCvarBombDamage = GetConVarFloat(g_hCvarBombDamage);
}
public OnMapStart()
{
PrecacheSound(SND_SHOOT);
PrecacheSound(SND_WARN);
PrecacheModel(PARTICLE_EXPLOSION);
PrecacheModel(MDL_BOMBLET);
}
public OnClientPutInServer(client)
{
SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}
public OnClientPostAdminCheck(client)
{
if(CheckCommandAccess(client, "", ADMFLAG_RESERVATION, true))
g_bIsDonor[client] = true;
else
g_bIsDonor[client] = false;
}
public OnClientCookiesCached(client)
{
decl String:sBuffer[16];
GetClientCookie(client, g_hCookieMiniBombs, sBuffer, sizeof(sBuffer));
if(strlen(sBuffer) == 1 || StrEqual(sBuffer, "Yes"))
g_bSpawnMiniBombs[client] = true;
else
g_bSpawnMiniBombs[client] = false;
// Set default value
if(strlen(sBuffer) == 1)
SetClientCookie(client, g_hCookieMiniBombs, "Yes");
}
public Action:Cmd_MiniBombs(client, args)
{
if(!g_bIsDonor[client])
{
PrintToChat(client, "%t", "No Access");
return Plugin_Handled;
}
else if(!g_bSpawnMiniBombs[client])
{
SetClientCookie(client, g_hCookieMiniBombs, "Yes");
g_bSpawnMiniBombs[client] = true;
CPrintToChat(client, "Minibombs on");
return Plugin_Handled;
}
else
{
SetClientCookie(client, g_hCookieMiniBombs, "No");
g_bSpawnMiniBombs[client] = false;
CPrintToChat(client, "Minibombs off");
return Plugin_Handled;
}
}
public OnEntityCreated(entity, const String:classname[])
{
if(g_bCvarEnabled && StrEqual(classname,"tf_projectile_pipe_remote"))
{
CreateTimer(2.0, Timer_SetProps, EntIndexToEntRef(entity));
}
}
public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype)
{
if(IsValidClient(attacker))
{
decl String:sWeapon[32];
GetEdictClassname(inflictor, sWeapon, sizeof(sWeapon));
if(StrEqual(sWeapon, "tf_projectile_pipe"))
{
if(victim == g_iMiniBombOwner[attacker])
return Plugin_Handled;
}
}
return Plugin_Continue;
}
public Action:Timer_SetProps(Handle:timer, any:entity)
{
new ent = EntRefToEntIndex(entity);
if (ent > 0 && ent > MaxClients && IsValidEntity(ent) && GetEntProp(ent, Prop_Send, "m_bTouched") && GetEntProp(ent, Prop_Send, "m_iType") != 2)
{
new client = GetEntPropEnt(ent, Prop_Send, "m_hThrower");
new clientteam = GetClientTeam(client); //Throwers team
if(!g_bIsDonor[client] || !g_bSpawnMiniBombs[client])
return Plugin_Handled;
g_iMiniBombOwner[client] = client;
new Float:pos[3];
GetEntPropVector(ent, Prop_Send, "m_vecOrigin", pos);
decl Float:g_angles[3], Float:g_angles2[3]; //Rotate sticky a bit when it shoots a bomblet
GetEntPropVector(ent, Prop_Send, "m_angRotation", g_angles);
g_angles2[0] = (g_angles[0] += GetRandomFloat(5.0,45.0));
g_angles2[1] = (g_angles[1] += GetRandomFloat(5.0,45.0));
g_angles2[2] = (g_angles[2] += GetRandomFloat(5.0,45.0));
decl Float:ang[3];
ang[0] = GetRandomFloat(-90.0, 90.0); //Left, Right
ang[1] = GetRandomFloat(-90.0, 90.0); //Forward, Back
ang[2] = GetRandomFloat(240.0, 340.0); //UP, Down
new pitch = 150;
EmitAmbientSound(SND_SHOOT, pos, ent, _, _, _, pitch);
new ent2 = CreateEntityByName("tf_projectile_pipe");
if(ent2 != -1)
{
SetEntPropEnt(ent2, Prop_Data, "m_hThrower", client);
SetEntProp(ent2, Prop_Send, "m_iTeamNum", clientteam);
SetEntProp(ent2, Prop_Send, "m_bCritical", true);
SetEntPropFloat(ent2, Prop_Send, "m_flModelScale", 0.8);
SetEntPropFloat(ent2, Prop_Send, "m_flDamage", g_flCvarBombDamage);
DispatchSpawn(ent2);
SetEntityModel(ent2, MDL_BOMBLET);
TeleportEntity(ent2, pos, NULL_VECTOR, ang); //Teleport bomblet to momma stickybomb
TeleportEntity(ent, NULL_VECTOR, g_angles2, NULL_VECTOR); //Rotate
CreateTimer(g_flCvarSpawnDelay, Timer_SetProps, EntRefToEntIndex(ent)); //The cycle continues..
}
}
return Plugin_Handled;
}
stock bool:IsValidClient(client)
{
if(client < 1 || client > MaxClients)
return false;
if(!IsClientConnected(client))
return false;
return IsClientInGame(client);
}