Have the following code for testing. Idea is to generate random origin within a player's AbsBox and then trace towards the player origin horizontally until a hitbox is detected then send a sprite message there.
The problem is you I can't find a proper message to use with a transparent(additive) sprite and that would also have velocity parameters.
Currently tried TE_SMOKE and TE_PROJECTILE but both of them use IndexAlpha sprites which have only greyscale color support.
Also tried TE_EXPLOSION but 8 units per second vertical velocity is just too low to look anywhere close to realistic.
PHP Code:
#include <amxmodx>
#include <engine>
#include <fakemeta>
//#include <cs_ham_bots_api>
#include <amxmisc>
#include <D7Debug>
new const g_szSprites[][] =
{/*
"sprites/aexplo.spr",
"sprites/bexplo.spr",
"sprites/richo2.spr",
"sprites/xfire.spr",
// "sprites/xfire2.spr",
"sprites/xfireball3.spr",
// "sprites/xflare2.spr"*/
"sprites/black_smoke1.spr",
"sprites/black_smoke2.spr",
"sprites/black_smoke3.spr",
"sprites/black_smoke4.spr"
//"sprites/3dmflaora.spr"
//"sprites/D7FireHighFadeInOutAdditive1.spr"
//"sprites/D7FireHighFadeInOutIndexAlpha1.spr"
}
new g_iIDSpriteDot, g_iIDsSprites[sizeof g_szSprites], g_iCountSpritesFrames[sizeof g_szSprites];
new g_iMaxPlayers, g_bBurn[33];
public plugin_precache()
{
for (new iID; iID < sizeof g_szSprites; iID++)
{
g_iIDsSprites[iID] = precache_model(g_szSprites[iID]);
g_iCountSpritesFrames[iID] = engfunc(EngFunc_ModelFrames, g_iIDsSprites[iID]);
}
g_iIDSpriteDot = precache_model("sprites/dot.spr");
}
public plugin_init()
{
register_plugin("D7 Test sprite trace to model", "0.1.2", "D7")
register_clcmd("say", "fwClCmdSayPre")
g_iMaxPlayers = get_maxplayers();
}
public fwClCmdSayPre(const iID)
{
static szArg[192], szArg1[15], szArg2[31];
read_args(szArg, charsmax(szArg))
trim(szArg)
remove_quotes(szArg)
szArg1 = "";
szArg2 = "";
parse(szArg, szArg1, charsmax(szArg1), szArg2, charsmax(szArg2))
if (!equali(szArg1, "/fm"))
return;
new iID2;
if (szArg2[0])
{
if (equali(szArg2, "*"))
iID2 = -1;
else
iID2 = cmd_target(iID2, szArg2, CMDTARGET_ALLOW_SELF);
}
if (iID2 >= 0)
{
if (!iID2)
iID2 = iID;
if (!g_bBurn[iID2])
{
g_bBurn[iID2] = 1;
}
else
{
g_bBurn[iID2] = 0;
}
}
else
{
for (iID2 = 1; iID2 <= g_iMaxPlayers; iID2++)
{
if (!g_bBurn[iID2])
{
g_bBurn[iID2] = 1;
}
else
{
g_bBurn[iID2] = 0;
}
}
}
}
public client_PreThink(iID)
{
//static const Float:fVecSizeHullStandMins[3] = { -16.0, -16.0, -36.0 };
//static const Float:fVecSizeHullStandMaxs[3] = { 16.0, 16.0, 36.0 };
//static const Float:fVecViewOffsetStand[3] = { 0.0, 0.0, 17.0 };
//static const Float:fVecSizeHullDuckMins[3] = { -16.0, -16.0, -18.0 };
//static const Float:fVecSizeHullDuckMaxs[3] = { 16.0, 16.0, 32.0 };
//static const Float:fVecViewOffsetDuck[3] = { 0.0, 0.0, 12.0 };
if (!is_user_alive(iID) || !g_bBurn[iID])
return;
new Float:fTimeGame = get_gametime();
static Float:fTimeLastBurn[33];
if (fTimeGame - fTimeLastBurn[iID] < random_float(0.03, 0.05))
return;
fTimeLastBurn[iID] = fTimeGame;
new Float:fVecOrigin[3], Float:fVecTemp[3], Float:fVecOriginSprite[3];
pev(iID, pev_origin, fVecOrigin)
new bDucking = (pev(iID, pev_flags) & FL_DUCKING);
new iIDTrace// = create_tr2();
LabelTraceStart:
fVecTemp = fVecOrigin;
if (!bDucking)
{
fVecTemp[0] += random_float(-16.0, 16.0);//(random_num(0, 1) ? -16.0 : 16.0)
fVecTemp[1] += random_float(-16.0, 16.0);//(random_num(0, 1) ? -16.0 : 16.0)
fVecTemp[2] += random_float(-36.0, 18.0);
}
else
{
fVecTemp[0] += random_float(-16.0, 16.0);//(random_num(0, 1) ? -16.0 : 16.0)
fVecTemp[1] += random_float(-16.0, 16.0);//(random_num(0, 1) ? -16.0 : 16.0)
fVecTemp[2] += random_float(-18.0, 20.0);
}
fVecOriginSprite = fVecOrigin;
fVecOriginSprite[2] = fVecTemp[2];
iIDTrace = trace_line(g_iMaxPlayers + 1, fVecTemp, fVecOriginSprite, fVecOriginSprite);
if (pev_valid(iIDTrace))
{
new szClassName[32];
pev(iIDTrace, pev_classname, szClassName, charsmax(szClassName))
set_hudmessage(255, 128, 0, 0.05, -1.0, 0, 0.0, 1.5, 0.0, 0.5, 4);
ftD7Log("f", iID, "[client_PreThink] HitID: %d. Owner: %d. ClassName: ^"%s^".", iIDTrace, pev(iIDTrace, pev_owner), szClassName)
}
else
{
set_hudmessage(255, 128, 0, 0.05, -1.0, 0, 0.0, 1.5, 0.0, 0.5, 4);
ftD7Log("f", iID, "[client_PreThink] HitID: %d.", iIDTrace)
//goto LabelTraceStart;
}
//engfunc(EngFunc_TraceLine, fVecTemp, fVecOriginSprite, DONT_IGNORE_MONSTERS, g_iMaxPlayers + 1, iIDTrace)// | IGNORE_MISSILE | IGNORE_GLASS
//get_tr2(iIDTrace, TR_vecEndPos, fVecOriginSprite)
if (get_distance_f(fVecTemp, fVecOriginSprite) >= 72)
{
ftD7Log(_, _, "[client_PreThink] iID: %d. Trace distance is bigger than 72(missed the player).", iID)
goto LabelTraceStart;
}
if (fVecTemp[0] == fVecOriginSprite[0] && fVecTemp[1] == fVecOriginSprite[1] && fVecTemp[2] == fVecOriginSprite[2])
{
ftD7Log(_, _, "[client_PreThink] iID: %d. Trace start and end origins are the same(inside the player model).", iID)
goto LabelTraceStart;
}
//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, fVecTemp[0]) // x
engfunc(EngFunc_WriteCoord, fVecTemp[1]) // y
engfunc(EngFunc_WriteCoord, fVecTemp[2]) // z
engfunc(EngFunc_WriteCoord, fVecOriginSprite[0]) // x
engfunc(EngFunc_WriteCoord, fVecOriginSprite[1]) // y
engfunc(EngFunc_WriteCoord, fVecOriginSprite[2]) // z
write_short(g_iIDSpriteDot);
write_byte(1); // framestart
write_byte(1); // framerate
write_byte(1); // life in 0.1's
write_byte(2); // 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();
iIDTrace = random_num(0, sizeof g_szSprites - 1);
// if Z origin is lower than X, subsctract some more.
// Smoke sprite
engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, fVecOrigin, 0)
write_byte(TE_SMOKE) // TE id
engfunc(EngFunc_WriteCoord, fVecOriginSprite[0]) // x
engfunc(EngFunc_WriteCoord, fVecOriginSprite[1]) // y
engfunc(EngFunc_WriteCoord, fVecOriginSprite[2]) // z
write_short(g_iIDsSprites[iIDTrace]) // sprite
write_byte(random_num(1, 3)) // scale
write_byte(random_num(g_iCountSpritesFrames[iIDTrace] * 2, floatround(g_iCountSpritesFrames[iIDTrace] * 1.5, floatround_floor))) // framerate
message_end()
/*
engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, fVecOrigin, 0)
write_byte(TE_PROJECTILE)
engfunc(EngFunc_WriteCoord, fVecOriginSprite[0]) // x
engfunc(EngFunc_WriteCoord, fVecOriginSprite[1]) // y
engfunc(EngFunc_WriteCoord, fVecOriginSprite[2]) // z
engfunc(EngFunc_WriteCoord, 0.0) // x
engfunc(EngFunc_WriteCoord, 0.0) // y
engfunc(EngFunc_WriteCoord, 30.0) // z
write_short(g_iIDsSprites[iIDTrace])
write_byte(g_iCountSpritesFrames[iIDTrace] / 10)
write_byte(iID) //projectile won't collide with owner (if owner == 0, projectile will hit any client).
message_end()*/
//set_task(random_float(0.1, 0.1), "client_PreThink", iID)
}
/*
#define TE_SMOKE 5 // Alphablend sprite, move vertically 30 pps
// write_byte(TE_SMOKE)
// write_coord(position.x)
// write_coord(position.y)
// write_coord(position.z)
// write_short(sprite index)
// write_byte(scale in 0.1's)
// write_byte(framerate)
#define TE_EXPLOSION 3 // Additive sprite, 2 dynamic lights, flickering particles, explosion sound, move vertically 8 pps
// write_byte(TE_EXPLOSION)
// write_coord(position.x)
// write_coord(position.y)
// write_coord(position.z)
// write_short(sprite index)
// write_byte(scale in 0.1's)
// write_byte(framerate)
// write_byte(flags)
//
// The Explosion effect has some flags to control performance/aesthetic features:
#define TE_EXPLFLAG_NONE 0 // All flags clear makes default Half-Life explosion
#define TE_EXPLFLAG_NOADDITIVE 1 // Sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite)
#define TE_EXPLFLAG_NODLIGHTS 2 // Do not render dynamic lights
#define TE_EXPLFLAG_NOSOUND 4 // Do not play client explosion sound
#define TE_EXPLFLAG_NOPARTICLES 8 // Do not draw particles
#define TE_PROJECTILE 119 // Makes a projectile (like a nail) (this is a high-priority tent)
// write_byte(TE_PROJECTILE)
// write_coord(position.x)
// write_coord(position.y)
// write_coord(position.z)
// write_coord(velocity.x)
// write_coord(velocity.y)
// write_coord(velocity.z)
// write_short(modelindex)
// write_byte(life)
// write_byte(owner) projectile won't collide with owner (if owner == 0, projectile will hit any client).
*/