#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <hamsandwich>
#define VERSION "0.2.7"
#define MAX_PLAYERS 32
enum _:BombSites_Datas {
iBsIndex,
szBsModel[5]
}
enum _:BombSites_States {
AllSites,
MainSite,
NoSite
}
#define StatusIconDontShow 0
#define StatusIconShow 1
new const func_bomb_target[] = "func_bomb_target"
new const info_bomb_target[] = "info_bomb_target"
new const classname[] = "classname"
#define FIND_ENT_BY_CLASSNAME(%1,%2) engfunc(EngFunc_FindEntityByString, %1, classname, %2)
#define XTRA_OFS_PLAYER 5
#define m_iTeam 114
#define cs_get_user_team_index(%1) get_pdata_int(%1, m_iTeam, XTRA_OFS_PLAYER)
#define CS_TEAM_CT 2
new g_iMaxPlayers
new g_pCvarMinCts, g_pCvarMidCts
new g_pCvarStartRoundText, g_pCvarPlanterText
new bool:g_bMainSiteSet
new szConfigFile[64], g_szMapName[32]
new g_mMainBombSite[BombSites_Datas]
new g_szBombSiteName[16]
new Array:g_aBombSites
new Float:g_flCountUntilGameTime
new bool:g_bCountNewSpawns
new g_iSyncHud
new mp_buytime
new gmsgStatusIcon
new g_iBombSites_State
new g_iC4Carrier
public plugin_init()
{
new iEnt, mDatas[BombSites_Datas]
while( (iEnt = FIND_ENT_BY_CLASSNAME(iEnt, func_bomb_target)) )
{
if( g_aBombSites == Invalid_Array )
{
g_aBombSites = ArrayCreate(BombSites_Datas)
}
mDatas[iBsIndex] = iEnt
pev(iEnt, pev_model, mDatas[szBsModel], charsmax(mDatas[szBsModel]))
ArrayPushString(g_aBombSites, mDatas)
}
while( (iEnt = FIND_ENT_BY_CLASSNAME(iEnt, info_bomb_target)) )
{
if( g_aBombSites == Invalid_Array )
{
g_aBombSites = ArrayCreate(BombSites_Datas)
}
mDatas[iBsIndex] = iEnt
pev(iEnt, pev_model, mDatas[szBsModel], charsmax(mDatas[szBsModel]))
ArrayPushString(g_aBombSites, mDatas)
}
if( g_aBombSites == Invalid_Array )
{
register_plugin("c4 management", "NotBombMap", "ConnorMcLeod")
pause("ad")
return
}
register_plugin("c4 management", VERSION, "ConnorMcLeod")
register_dictionary("c4management.txt")
g_pCvarMinCts = register_cvar("bm_minct", "0")
g_pCvarMidCts = register_cvar("bm_midct", "5")
g_pCvarStartRoundText = register_cvar("bm_roundstart_text", "2")
g_pCvarPlanterText = register_cvar("bm_planter_text", "1")
get_mapname(g_szMapName, charsmax(g_szMapName))
get_localinfo("amxx_configsdir", szConfigFile, charsmax(szConfigFile))
format(szConfigFile, charsmax(szConfigFile), "%s/bombsites.ini", szConfigFile)
if( !file_exists(szConfigFile) )
{
new iFile = fopen(szConfigFile, "at")
fprintf(iFile, "; c4 management configuration file^n")
fclose(iFile)
}
g_iMaxPlayers = get_maxplayers()
GetMainBombSiteByFile()
register_event("HLTV", "Event_HLTV_New_Round", "a", "1=0", "2=0")
register_logevent("LogEvent_RoundStart", 2, "1=Round_Start")
register_logevent("Logevent_Round_End", 2, "1=Round_End")
RegisterHam(Ham_Spawn, "player", "Player_Spawn_Post", 1)
register_event("WeapPickup", "Event_WeapPickup_c4", "be", "1=6")
register_message(get_user_msgid("StatusIcon"), "Message_StatusIcon")
register_event("BombDrop", "Event_BombDrop", "bc")
register_event("TextMsg", "Event_TextMsg_C4PlantAtBombSpot", "be", "1=4", "2=#C4_Plant_At_Bomb_Spot")
register_clcmd("bm_mark_bs", "AdminCommand_MarkBombSite", ADMIN_CFG, " <BombSite Name>")
g_iSyncHud = CreateHudSyncObj()
mp_buytime = get_cvar_pointer("mp_buytime")
gmsgStatusIcon = get_user_msgid("StatusIcon")
}
GetMainBombSiteByFile()
{
new iFile = fopen(szConfigFile, "rt")
if( iFile )
{
new szData[64], szMapname[32], szModel[5], szBombSiteName[16]
while( fgets(iFile, szData, charsmax(szData)) )
{
if( !szData[0] || szData[0] == '/' || szData[0] == ';' || szData[0] == '#' )
{
continue
}
trim(szData)
parse(szData, szMapname, charsmax(szMapname),
szModel, charsmax(szModel),
szBombSiteName, charsmax(szBombSiteName))
if( equali(szMapname, g_szMapName) )
{
new iEnt
// less efficient than engine but used only at map start
iEnt = FIND_ENT_BY_MODELNAME(g_iMaxPlayers, func_bomb_target, szModel)
if( !iEnt )
{
iEnt = FIND_ENT_BY_MODELNAME(g_iMaxPlayers, info_bomb_target, szModel)
}
if( iEnt )
{
g_mMainBombSite[iBsIndex] = iEnt
g_mMainBombSite[szBsModel] = szModel
remove_quotes(szBombSiteName)
g_szBombSiteName = szBombSiteName
g_bMainSiteSet = true
}
break
}
}
fclose(iFile)
}
}
public plugin_pause()
{
new iBombSiteNum = ArraySize(g_aBombSites)
new mBombSiteDatas[BombSites_Datas]
for(new i; i<iBombSiteNum; i++)
{
ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
SetBombSite(mBombSiteDatas[iBsIndex], true)
}
}
public plugin_end()
{
if( g_aBombSites != Invalid_Array )
{
ArrayDestroy(g_aBombSites)
}
}
public Event_HLTV_New_Round()
{
g_iC4Carrier = 0
g_bCountNewSpawns = false
g_iBombSites_State = AllSites
}
public Event_BombDrop()
{
g_iC4Carrier = 0
if( read_data(4) ) // Bomb Planted
{
g_bCountNewSpawns = false
}
}
public Logevent_Round_End()
{
g_bCountNewSpawns = false
}
public LogEvent_RoundStart()
{
g_bCountNewSpawns = true
g_flCountUntilGameTime = get_gametime() + get_pcvar_float(mp_buytime) * 60.0
if(!g_bMainSiteSet)
{
return
}
CountCounterTerrorists()
}
public AdminCommand_MarkBombSite(id, level, cid)
{
if( !cmd_access(id, level, cid, 2) )
{
return PLUGIN_HANDLED
}
if(g_bMainSiteSet)
{
client_print(id, print_console, "%L", id, "BM_ALREADY")
client_cmd(id, "spk buttons/latchlocked1")
return PLUGIN_HANDLED
}
new iBombSiteNum = ArraySize(g_aBombSites)
new mBombSiteDatas[BombSites_Datas], iEnt
new Float:fVecOrigin[3], Float:fVecAbsMin[3], Float:fVecAbsMax[3]
for(new i=0; i<iBombSiteNum; i++)
{
ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
iEnt = mBombSiteDatas[iBsIndex]
pev(id, pev_origin, fVecOrigin)
pev(iEnt, pev_absmin, fVecAbsMin)
pev(iEnt, pev_absmax, fVecAbsMax)
if( (fVecAbsMin[0] <= fVecOrigin[0] <= fVecAbsMax[0])
&& (fVecAbsMin[1] <= fVecOrigin[1] <= fVecAbsMax[1])
&& (-72.0 <= (((fVecAbsMax[2] + fVecAbsMin[2]) / 2.0) - fVecOrigin[2]) <= 72.0) )
{
read_argv(1, g_szBombSiteName, charsmax(g_szBombSiteName))
new iFile = fopen(szConfigFile, "at")
fprintf(iFile, "^n%s %s ^"%s^"", g_szMapName, mBombSiteDatas[szBsModel], g_szBombSiteName)
fclose(iFile)
g_mMainBombSite = mBombSiteDatas
g_bMainSiteSet = true
client_print(id, print_console, "%L", id, "BM_DEFINED")
client_cmd(id, "spk events/task_complete")
return PLUGIN_HANDLED
}
}
client_print(id, print_console, "%L", id, "BM_NOTBOMBSITE")
client_cmd(id, "spk events/friend_died")
return PLUGIN_HANDLED
}
public Event_WeapPickup_c4( id )
{
g_iC4Carrier = id
}
public Message_StatusIcon(/*iMsgId, iMsgDest, id*/)
{
if( g_iBombSites_State != AllSites && get_msg_arg_int(1) == StatusIconShow )
{
new szIcon[4]
get_msg_arg_string(2, szIcon, charsmax(szIcon))
if( get_msg_arg_string(2, szIcon, charsmax(szIcon)) == 2 // check "c4" length first
&& equal(szIcon, "c4") )
{
switch( g_iBombSites_State )
{
case NoSite:
{
set_msg_arg_int(1, ARG_BYTE, 0)
}
case MainSite:
{
set_msg_arg_int(3, ARG_BYTE, 200)
set_msg_arg_int(4, ARG_BYTE, 100)
}
}
}
}
}
public Event_TextMsg_C4PlantAtBombSpot(id)
{
if( !get_pcvar_num(g_pCvarPlanterText) )
{
return
}
new iBombSiteNum = ArraySize(g_aBombSites)
new mBombSiteDatas[BombSites_Datas], iEnt
new Float:fVecOrigin[3], Float:fVecAbsMin[3], Float:fVecAbsMax[3]
for(new i=0; i<iBombSiteNum; i++)
{
ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
iEnt = mBombSiteDatas[iBsIndex]
pev(id, pev_origin, fVecOrigin)
pev(iEnt, pev_absmin, fVecAbsMin)
pev(iEnt, pev_absmax, fVecAbsMax)
if( (fVecAbsMin[0] <= fVecOrigin[0] <= fVecAbsMax[0])
&& (fVecAbsMin[1] <= fVecOrigin[1] <= fVecAbsMax[1])
&& (-72.0 <= (((fVecAbsMax[2] + fVecAbsMin[2]) / 2.0) - fVecOrigin[2]) <= 72.0) )
{
switch( g_iBombSites_State )
{
case NoSite:
{
client_print(id, print_center, "%L", id, "BM_AD_NOPLANT", get_pcvar_num(g_pCvarMinCts))
}
case MainSite:
{
client_print(id, print_center, "%L", id, "BM_AD_ONLYMAIN",
get_pcvar_num(g_pCvarMidCts), g_szBombSiteName)
}
}
break
}
}
}
public Player_Spawn_Post(id)
{
if( g_bMainSiteSet
&& g_bCountNewSpawns
&& is_user_alive(id)
&& cs_get_user_team_index(id) == CS_TEAM_CT )
{
if( g_flCountUntilGameTime < get_gametime() )
{
g_bCountNewSpawns = false
return
}
CountCounterTerrorists()
}
}
CountCounterTerrorists()
{
new iPlayers[MAX_PLAYERS], iNum, iCtNum
get_players(iPlayers, iNum, "h")
for(new i; i<iNum; i++)
{
if( cs_get_user_team_index(iPlayers[i]) == CS_TEAM_CT )
{
iCtNum++
}
}
new iMinCts = get_pcvar_num(g_pCvarMinCts)
new iMidCts = get_pcvar_num(g_pCvarMidCts)
new const szTag[] = "C4 Management"
new iBombSiteNum = ArraySize(g_aBombSites)
new mBombSiteDatas[BombSites_Datas]
if( iCtNum < iMinCts)
{
switch( get_pcvar_num(g_pCvarStartRoundText) )
{
case 1:
{
client_print(0, print_chat, "* [%s] %L", szTag, LANG_PLAYER, "BM_AD_NOPLANT", iMinCts)
}
case 2:
{
set_hudmessage(200, 50, 50, -1.0, 0.15, .holdtime=8.0, .channel=-1)
ShowSyncHudMsg(0, g_iSyncHud, "%s : %L", szTag, LANG_PLAYER, "BM_AD_NOPLANT", iMinCts)
}
}
for(new i; i<iBombSiteNum; i++)
{
ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
SetBombSite(mBombSiteDatas[iBsIndex], false)
}
g_iBombSites_State = NoSite
if( g_iC4Carrier )
{
Send_StatusIcon_c4(g_iC4Carrier)
}
}
else if( iCtNum < iMidCts)
{
switch( get_pcvar_num(g_pCvarStartRoundText) )
{
case 1:
{
client_print(0, print_chat, "* [%s] %L", szTag, LANG_PLAYER, "BM_AD_ONLYMAIN", iMidCts, g_szBombSiteName)
}
case 2:
{
set_hudmessage(0, 255, 0, -1.0, 0.15, .holdtime=8.0, .channel=-1)
ShowSyncHudMsg(0, g_iSyncHud, "%s : %L", szTag, LANG_PLAYER, "BM_AD_ONLYMAIN", iMidCts, g_szBombSiteName)
}
}
new iEnt
for(new i; i<iBombSiteNum; i++)
{
ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
iEnt = mBombSiteDatas[iBsIndex]
SetBombSite(iEnt, iEnt == g_mMainBombSite[iBsIndex] ? true : false)
}
g_iBombSites_State = MainSite
if( g_iC4Carrier )
{
Send_StatusIcon_c4(g_iC4Carrier, StatusIconShow, 200, 100, 0)
}
}
else
{
switch( get_pcvar_num(g_pCvarStartRoundText) )
{
case 1:
{
client_print(0, print_chat, "* [%s] %L", szTag, LANG_PLAYER, "BM_AD_ALLSITES")
}
case 2:
{
set_hudmessage(50, 200, 50, -1.0, 0.15, .holdtime=8.0, .channel=-1)
ShowSyncHudMsg(0, g_iSyncHud, "%s : %L", szTag, LANG_PLAYER, "BM_AD_ALLSITES")
}
}
for(new i; i<iBombSiteNum; i++)
{
ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
SetBombSite(mBombSiteDatas[iBsIndex], true)
}
g_iBombSites_State = AllSites
if( g_iC4Carrier )
{
Send_StatusIcon_c4(g_iC4Carrier, StatusIconShow, 0, 160, 0)
}
}
}
SetBombSite(iEnt, bool:bActive)
{
set_pev(iEnt, pev_solid, bActive ? SOLID_TRIGGER : SOLID_NOT)
}
Send_StatusIcon_c4(id, Mode=StatusIconDontShow, r=0, g=0, b=0)
{
message_begin(MSG_ONE_UNRELIABLE, gmsgStatusIcon, .player=id)
write_byte(Mode)
write_string("c4")
if( Mode )
{
write_byte(r)
write_byte(g)
write_byte(b)
}
message_end()
}
FIND_ENT_BY_MODELNAME(const iStartEnt, const szClassName[], const szModel[])
{
new iEnt = iStartEnt
new szMdl[72]
while( (iEnt = FIND_ENT_BY_CLASSNAME(iEnt, szClassName)) )
{
pev(iEnt, pev_model, szMdl, charsmax(szMdl))
if( equal(szMdl, szModel) )
{
return iEnt
}
}
return 0
}