//#define CSDM
//Uncomment the above line if you have CSDM installed
/*
Changelog
---------
v1.2:
- Fixed plugin not working when csdm is not installed.
v1.1:
- Better approach to wall planting.
- Fixed c4_wait not getting disabled.
*/
#include <amxmodx>
#include <cstrike>
#include <csx>
#include <fakemeta>
#if defined CSDM
#include <csdm>
#endif
#define OFFSET_TEAM 114
#define OFFSET_CSDEATHS 444
#define NO_CSDM_TASK_ID 199
#define STACK_SIZE 16
// PCvars
new g_pcvarAnywhere
new g_pcvarBuy
new g_pcvarCTBuy
new g_pcvarKills
new g_pcvarWall
new g_pcvarCost
new g_pcvarWait
new g_pcvarCsdm
// Cache
new g_msgDeath
new g_msgShowTimer
new g_msgScoreInfo
new g_RoundEndDisabled
new g_PlanterID
new g_Planters[STACK_SIZE]
public plugin_precache()
{
g_pcvarAnywhere = register_cvar("c4_anywhere", "1");
// Create PlantAnywhere Bombsite
if(get_pcvar_num(g_pcvarAnywhere))
CreateBombTarget();
}
public plugin_init()
{
register_plugin("Plant Anywhere 2", "1.2", "Av3ngeR");
register_concmd("c4", "cmdBuyC4");
register_srvcmd("c4_disable_roundend", "cmdNoRoundEnd");
register_event("HLTV", "eventNewRound", "a", "1=0", "2=0");
register_event("23", "eventBombExplode", "a", "1=17", "6=-105", "7=17");
register_logevent("eventRoundStart", 2, "1=Round_Start");
register_logevent("eventJoinTerrorist", 3, "1=joined team", "2=TERRORIST");
register_logevent("eventBombPlanted", 3, "2=Planted_The_Bomb");
register_logevent("eventBombDefused", 3, "2=Defused_The_Bomb")
register_forward(FM_Touch, "forwardTouch");
register_forward(FM_CmdStart, "forwardCmdStart");
g_pcvarBuy = register_cvar("c4_buy", "1");
g_pcvarCTBuy = register_cvar("c4_buy_ct", "0");
g_pcvarKills = register_cvar("c4_kill", "1");
g_pcvarWall = register_cvar("c4_wall", "1");
g_pcvarCost = register_cvar("c4_cost", "3000");
g_pcvarWait = register_cvar("c4_wait", "20");
g_pcvarCsdm = register_cvar("csdm_active", "0");
g_msgDeath = get_user_msgid("DeathMsg");
g_msgShowTimer = get_user_msgid("ShowTimer");
g_msgScoreInfo = get_user_msgid("ScoreInfo");
}
public forwardCmdStart(id, ucHandle, Seed)
{
if(is_user_alive(id) && (get_user_weapon(id) == CSW_C4))
{
// Disable planting till amx_c4Wait seconds
if(task_exists(id) || task_exists(NO_CSDM_TASK_ID))
{
// DevconeS's Code
new buttons = get_uc(ucHandle,UC_Buttons)
if(buttons & IN_ATTACK)
{
buttons &= ~IN_ATTACK
set_uc(ucHandle,UC_Buttons,buttons)
}
}
}
}
public forwardTouch(touchedID,toucherID)
{
static touchedClass[32], toucherClass[32];
if(!pev_valid(touchedID))
return FMRES_IGNORED;
// Get Classnames of the entity
pev(touchedID, pev_classname, touchedClass, 31);
pev(toucherID, pev_classname, toucherClass, 31);
if(equal(touchedClass, "weaponbox") && equal(toucherClass, "player"))
{
// Get Modelname of the weapon entity
static touchedModel[32];
pev(touchedID, pev_model, touchedModel, 31);
// Do not allow player to pickup bomb if he already has it
if(equal(touchedModel, "models/w_backpack.mdl"))
{
if(user_has_weapon(toucherID, CSW_C4))
return FMRES_SUPERCEDE
}
}
return FMRES_IGNORED
}
public cmdNoRoundEnd()
{
fm_remove_entity_name("func_bomb_target");
fm_remove_entity_name("info_bomb_target");
CreateBombTarget();
g_RoundEndDisabled = 1;
}
public cmdBuyC4(id)
{
if(!is_user_alive(id))
return;
if(!get_pcvar_num(g_pcvarBuy))
{
client_print(id, print_center, "#Cstrike_Not_Available")
return;
}
if(!cs_get_user_buyzone(id))
{
if(!get_pcvar_num(g_pcvarCsdm))
{
client_print(id, print_center, "You must be in the buy zone in order to purchase")
return;
}
}
if(cs_get_user_team(id) == CS_TEAM_CT)
{
if(!get_pcvar_num(g_pcvarCTBuy))
{
client_print(id, print_center, "#Cstrike_TitlesTXT_Cannot_Buy_This")
return;
}
}
if(user_has_weapon(id, CSW_C4))
{
client_print(id, print_center, "#Cstrike_Already_Own_Weapon");
return;
}
new BombCost = get_pcvar_num(g_pcvarCost);
new PlayerMoney = cs_get_user_money(id);
if(PlayerMoney < BombCost)
{
client_print(id, print_center, "#Cstrike_TitlesTXT_Not_Enough_Money");
return;
}
fm_give_item(id, "weapon_c4");
cs_set_user_money(id, PlayerMoney - BombCost);
cs_set_user_plant(id, 1);
if(get_pcvar_num(g_pcvarAnywhere))
{
if(get_pcvar_num(g_pcvarWait) <= 1)
return;
if(get_pcvar_num(g_pcvarCsdm))
{
// Avoid multiple tasks due to multiple buys
if(task_exists(id))
remove_task(id);
set_task(get_pcvar_float(g_pcvarWait), "AllowPlanting", id);
client_print(id, print_chat, "You are allowed to plant after %d seconds", get_pcvar_num(g_pcvarWait));
}
}
}
public eventJoinTerrorist()
{
if(!get_pcvar_num(g_pcvarBuy))
return;
new id;
id = get_loguser_index();
client_print(id, print_chat, "Terrorists can buy C4 ($%d) by entering ^"c4^" in console", get_pcvar_num(g_pcvarCost));
}
public eventNewRound()
{
// Remove Bomb Objectives so dat there is no round-end
// Server has to restart to revert back
if(!g_RoundEndDisabled)
{
if(get_pcvar_num(g_pcvarCsdm))
{
cmdNoRoundEnd();
}
}
// Clear all plants
for(new i=0; i < STACK_SIZE; i++)
{
g_Planters[i] = 0;
}
}
public eventRoundStart()
{
if(!get_pcvar_num(g_pcvarAnywhere))
return;
new id, Max;
static Players[32];
get_players(Players, Max, "ae", "TERRORIST");
for(new i=0; i<Max; i++)
{
// Cache
id = Players[i];
if(user_has_weapon(id, CSW_C4))
{
if(get_pcvar_num(g_pcvarWait) < 1)
break;
// Needs to be displayed regardless of g_pcvarCsdm
client_print(id, print_chat, "You are allowed to plant after %d seconds", get_pcvar_num(g_pcvarWait));
if(get_pcvar_num(g_pcvarCsdm))
{
// Avoid multiple tasks due to multiple restarts in g_pcvarWait seconds
if(task_exists(id))
remove_task(id);
set_task(get_pcvar_float(g_pcvarWait), "AllowPlanting", id);
}
}
}
// Should not be inside loop since it won't get executed if no one has the C4
if(!get_pcvar_num(g_pcvarCsdm))
{
// Avoid multiple tasks due to multiple restarts in g_pcvarWait seconds
if(task_exists(NO_CSDM_TASK_ID))
{
remove_task(NO_CSDM_TASK_ID);
}
set_task(get_pcvar_float(g_pcvarWait), "AllowPlanting", NO_CSDM_TASK_ID);
}
}
public eventBombPlanted()
{
new id = get_loguser_index();
if(get_pcvar_num(g_pcvarKills))
{
for(new i=0; i < STACK_SIZE; i++)
{
if(g_Planters[i] > 0)
continue;
g_Planters[i] = id;
break;
}
}
// Based on Cheap_Suit's Code
if(!get_pcvar_num(g_pcvarWall))
return;
new Float:Origin[3], Float:Normal[3];
if(!fm_get_aim_origin_normal(id, Origin, Normal))
return;
new c4;
while((c4 = fm_find_ent_by_model(c4, "grenade", "models/w_c4.mdl")))
{
if(pev(c4, pev_movetype) == MOVETYPE_FLY || (pev(c4, pev_flags) & FL_ONGROUND))
continue;
set_pev(c4, pev_movetype, MOVETYPE_FLY);
Origin[1] -= 0.7;
engfunc(EngFunc_SetOrigin, c4, Origin);
new Float:Angles[3];
vector_to_angle(Normal, Angles);
Angles[1] -= 90.0;
Angles[2] -= 90.0;
set_pev(c4, pev_angles, Angles);
}
}
public eventBombExplode()
{
for(new i=0; i < STACK_SIZE; i++)
{
if(g_Planters[i] > 0)
{
g_PlanterID = g_Planters[i];
g_Planters[i] = g_Planters[++i];
g_Planters[++i] = 0;
break;
}
}
// Timer doesn't show up when objectives are removed
if(g_RoundEndDisabled)
{
message_begin(MSG_ALL, g_msgShowTimer, _, 0);
message_end();
}
if(get_pcvar_num(g_pcvarKills))
{
// No Target Bombed bonus
new Float:frags;
pev(g_PlanterID, pev_frags, frags);
fm_set_user_frags(g_PlanterID, frags - 3.0);
}
}
public eventBombDefused(id)
{
new Float:frags;
pev(id, pev_frags, frags);
fm_set_user_frags(id, frags + 3.0);
// Timer doesn't show up when objectives are removed
if(g_RoundEndDisabled)
{
message_begin(MSG_ALL, g_msgShowTimer, _, 0);
message_end();
}
}
public client_death(KillerID , VictimID , WeaponID, HitboxID, isTK)
{
// CT killed by C4
if(get_pcvar_num(g_pcvarKills) && (WeaponID == CSW_C4) && (cs_get_user_team(VictimID) != cs_get_user_team(g_PlanterID)))
{
// Increase Planter's Frags by 1
new Float:frags;
pev(g_PlanterID, pev_frags, frags);
fm_set_user_frags(g_PlanterID, ++frags);
// Increase Victims's Deaths by 1
cs_set_user_deaths(VictimID, cs_get_user_deaths(VictimID) + 1);
// Displayed Death Message
message_begin(MSG_BROADCAST, g_msgDeath);
write_byte(g_PlanterID);
write_byte(VictimID);
write_byte(0);
write_string("c4");
message_end();
}
#if defined CSDM
// Player doesnt respawn when objectives are removed
if(get_pcvar_num(g_pcvarCsdm) && !is_user_alive(VictimID))
{
csdm_respawn(VictimID);
}
#endif
}
public AllowPlanting() {}
public CreateBombTarget()
{
new NewBombTarget = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "func_bomb_target"))
if(NewBombTarget > 0)
{
dllfunc(DLLFunc_Spawn, NewBombTarget)
engfunc(EngFunc_SetSize, NewBombTarget, Float:{-100000.0,-100000.0,-100000.0}, Float:{100000.0,100000.0,100000.0})
}
}
stock get_loguser_index()
{
new Log[80], Name[32];
read_logargv(0, Log, 79);
parse_loguser(Log, Name, 31);
return get_user_index(Name);
}
stock fm_set_user_frags(id, Float:Frags)
{
set_pev(g_PlanterID, pev_frags, Frags);
message_begin(MSG_ALL, g_msgScoreInfo);
write_byte(id);
write_short(floatround(Frags));
write_short(get_pdata_int(id, OFFSET_CSDEATHS));
write_short(0);
write_short(get_pdata_int(id, OFFSET_TEAM));
message_end();
}
// From fakemeta_util
stock fm_find_ent_by_model(index, const classname[], const model[])
{
new ent = index, mdl[72];
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)))
{
pev(ent, pev_model, mdl, sizeof mdl - 1);
if (equal(mdl, model))
return ent;
}
return 0;
}
// From fakemeta_util
stock fm_give_item(index, const item[])
{
if (!equal(item, "weapon_", 7) && !equal(item, "ammo_", 5) && !equal(item, "item_", 5) && !equal(item, "tf_weapon_", 10))
return 0;
new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item));
if (!pev_valid(ent))
return 0;
new Float:origin[3];
pev(index, pev_origin, origin);
set_pev(ent, pev_origin, origin);
set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN);
dllfunc(DLLFunc_Spawn, ent);
new save = pev(ent, pev_solid);
dllfunc(DLLFunc_Touch, ent, index);
if (pev(ent, pev_solid) != save)
return ent;
engfunc(EngFunc_RemoveEntity, ent);
return -1;
}
// From fakemeta_util
stock fm_remove_entity_name(const classname[]) {
new ent = -1, num = 0;
while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)))
num += engfunc(EngFunc_RemoveEntity, ent);
return num;
}
// From fakemeta_util (Combined 2 functions)
stock fm_get_aim_origin_normal(index, Float:origin[3], Float:normal[3]) {
new Float:start[3], Float:view_ofs[3];
pev(index, pev_origin, start);
pev(index, pev_view_ofs, view_ofs);
start[0] += view_ofs[0];
start[1] += view_ofs[1];
start[2] += view_ofs[2];
new Float:dest[3];
pev(index, pev_v_angle, dest);
engfunc(EngFunc_MakeVectors, dest);
global_get(glb_v_forward, dest);
dest[0] *= 54.0;
dest[1] *= 54.0;
dest[2] *= 54.0;
dest[0] += start[0];
dest[1] += start[1];
dest[2] += start[2];
engfunc(EngFunc_TraceLine, start, dest, 0, index, 0);
get_tr2(0, TR_vecEndPos, origin);
get_tr2(0, TR_vecPlaneNormal, normal);
new Float:fraction;
get_tr2(0, TR_flFraction, fraction);
if (fraction >= 1.0)
return 0;
return 1;
}