I made this plugin some time ago which forces CS bots to shoot breakables when they're aiming at them because sometimes they would fail. Would probably be useful for your case. Uncomment and enable the sprite message to visualize the start and end position of the trace.
PHP Code:
#include <amxmodx>
//#include <engine>
#include <fakemeta>
#include <hamsandwich>
#include <cs_ham_bots_api>
#include <bitsums>
//#include <D7Debug>
new g_iBsShoot;//g_iIDSpriteDot,
/*
public plugin_precache()
g_iIDSpriteDot = precache_model("sprites/dot.spr");*/
public plugin_init()
{
register_plugin("D7 Bot shoot breakables", "0.0.2", "D7")
register_forward(FM_CmdStart, "fwFmCmdStartPre")
//RegisterHam(Ham_Spawn, "player", "fwHamSpawnPlayer", 1)
//RegisterHam(Ham_Killed, "player", "fwHamKilledPlayer", 1)
#if defined _cs_ham_bots_api_included
RegisterHamBots(Ham_Spawn, "fwHamSpawnPlayer", 1)
RegisterHamBots(Ham_Killed, "fwHamKilledPlayer", 1)
#endif
}
public client_putinserver(iID)
bitsum_del(g_iBsShoot, iID)
public client_disconnect(iID)
{
if (!is_user_bot(iID))
return;
bitsum_del(g_iBsShoot, iID)
remove_task(iID)
}
public fwHamSpawnPlayer(const iID)
{
bitsum_del(g_iBsShoot, iID)
if (!is_user_alive(iID) || !is_user_bot(iID))
return;
remove_task(iID)
set_task(0.1, "fwTaskBreakable", iID, _, _, "b")
}
public fwHamKilledPlayer(const iID)//, iIDAttacker, iShouldGib
{
bitsum_del(g_iBsShoot, iID)
remove_task(iID)
}
ftFmVelocityByAim(const iID, const Float:fAmount, Float:fVecTemp[3])
{
pev(iID, pev_v_angle, fVecTemp)
angle_vector(fVecTemp, ANGLEVECTOR_FORWARD, fVecTemp)
fVecTemp[0] *= fAmount;
fVecTemp[1] *= fAmount;
fVecTemp[2] *= fAmount;
}
public fwTaskBreakable(const iID)
{
bitsum_del(g_iBsShoot, iID)
new Float:fVecOrigin[3], Float:fVecTemp[3];
pev(iID, pev_origin, fVecOrigin)
pev(iID, pev_view_ofs, fVecTemp)
fVecOrigin[0] += fVecTemp[0];
fVecOrigin[1] += fVecTemp[1];
fVecOrigin[2] += fVecTemp[2];
ftFmVelocityByAim(iID, 150.0, fVecTemp)
//velocity_by_aim(iID, 150, fVecTemp)
//VelocityByAim(iID, 150, fVecTemp)
fVecTemp[0] += fVecOrigin[0];
fVecTemp[1] += fVecOrigin[1];
fVecTemp[2] += fVecOrigin[2];
new iIDTrace = create_tr2();
engfunc(EngFunc_TraceLine, fVecOrigin, fVecTemp, IGNORE_MONSTERS | IGNORE_MISSILE, iID, iIDTrace);
new iIDEnt = get_tr2(iIDTrace, TR_pHit);
free_tr2(iIDTrace)
/*
//engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, fVecOrigin, 0)
engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, fVecOrigin, 0)
write_byte(TE_BEAMPOINTS);
engfunc(EngFunc_WriteCoord, fVecOrigin[0]) // x
engfunc(EngFunc_WriteCoord, fVecOrigin[1]) // y
engfunc(EngFunc_WriteCoord, fVecOrigin[2]) // z
engfunc(EngFunc_WriteCoord, fVecTemp[0]) // x
engfunc(EngFunc_WriteCoord, fVecTemp[1]) // y
engfunc(EngFunc_WriteCoord, fVecTemp[2]) // z
write_short(g_iIDSpriteDot);
write_byte(1); // framestart
write_byte(1); // framerate
write_byte(2); // life in 0.1's
write_byte(5); // width
write_byte(0); // noise
write_byte(255); // r, g, b
write_byte(128); // r, g, b
write_byte(0); // r, g, b
write_byte(200); // brightness
write_byte(0); // speed
message_end();*/
//ftD7Log("e", _, "iID: %d. iIDEnt: %d.", iID, iIDEnt)
if (iIDEnt < 33 || !pev_valid(iIDEnt))
return;
else if (pev(iIDEnt, pev_takedamage) < 1)
{
//ftD7Log("e", _, "pev_takedamage: %d.", pev(iIDEnt, pev_takedamage))
return;
}
new szClassName[32];
pev(iIDEnt, pev_classname, szClassName, charsmax(szClassName))
if (containi(szClassName, "hostage") != -1)
{
//ftD7Log("e", _, "pev_takedamage: %d.", pev(iIDEnt, pev_takedamage))
return;
}
//ftD7Log("e", _, "pev_takedamage: %d. Forcing attack.", pev(iIDEnt, pev_takedamage))
bitsum_add(g_iBsShoot, iID)
//set_pev(iID, pev_oldbuttons, pev(iID, pev_oldbuttons) & ~IN_ATTACK)
//set_pev(iID, pev_button, pev(iID, pev_button) | IN_ATTACK)
}
public fwFmCmdStartPre(const iID, const iIDUCHandle)
{
if (!(1 <= iID <= 32) || !bitsum_get(g_iBsShoot, iID))
return;
set_uc(iIDUCHandle, UC_Buttons, get_uc(iIDUCHandle, UC_Buttons) | IN_ATTACK)
}