#pragma semicolon 1
#include <amxmodx>
#include <reapi>
#include <json>
new const PLUGIN_VERSION[] = "0.0.3";
new const JSON_CONFIG_FILE[] = "/GrenadesTrail/GrenadesTrail.json";
enum _:COLOR_COMPONENTS {
RED,
GREEN,
BLUE
}
enum _:TRAIL_CONFIG {
bool:CONFIG_USE_TEAM_COLOR,
CONFIG_LIFETIME,
CONFIG_WIDTH,
CONFIG_BRIGHTNESS
}
enum _:GRENADE_TRAIL_COLORS {
COLOR_TEAM_TT,
COLOR_TEAM_CT,
COLOR_HE,
COLOR_FLASH,
COLOR_SMOKE
}
new g_eTrailConfig[TRAIL_CONFIG],
g_eTrailColors[GRENADE_TRAIL_COLORS][COLOR_COMPONENTS],
g_iSpriteTrail;
public plugin_precache() {
g_iSpriteTrail = precache_model("sprites/smoke.spr");
}
public plugin_init() {
register_plugin("[ReAPI] Grenades Trail", PLUGIN_VERSION, "mIDnight");
LoadTrailConfig();
RegisterHookChain(RG_CBasePlayer_ThrowGrenade, "@OnThrowGrenade_Post", .post = true);
}
LoadTrailConfig() {
new configFile[PLATFORM_MAX_PATH];
get_localinfo("amxx_configsdir", configFile, charsmax(configFile));
add(configFile, charsmax(configFile), JSON_CONFIG_FILE);
new JSON:config = json_parse(configFile, true, true);
if (config == Invalid_JSON) {
set_fail_state("JSON syntax error in file (%s).", JSON_CONFIG_FILE);
}
if (!json_is_object(config)) {
set_fail_state("File must contain a JSON-object (%s).", JSON_CONFIG_FILE);
}
new JSON:trailSettings = json_object_get_value(config, "grenade_trail_settings");
g_eTrailConfig[CONFIG_USE_TEAM_COLOR] = json_object_get_bool(trailSettings, "use_team_color");
g_eTrailConfig[CONFIG_LIFETIME] = json_object_get_number(trailSettings, "lifetime");
g_eTrailConfig[CONFIG_WIDTH] = json_object_get_number(trailSettings, "width");
g_eTrailConfig[CONFIG_BRIGHTNESS] = json_object_get_number(trailSettings, "brightness");
LoadColorArray(trailSettings, "team_colors.terrorists", g_eTrailColors[COLOR_TEAM_TT]);
LoadColorArray(trailSettings, "team_colors.counter_terrorists", g_eTrailColors[COLOR_TEAM_CT]);
LoadColorArray(trailSettings, "grenade_colors.he", g_eTrailColors[COLOR_HE]);
LoadColorArray(trailSettings, "grenade_colors.flash", g_eTrailColors[COLOR_FLASH]);
LoadColorArray(trailSettings, "grenade_colors.smoke", g_eTrailColors[COLOR_SMOKE]);
json_free(config);
}
LoadColorArray(JSON:settings, const szKey[], iColorArray[COLOR_COMPONENTS]) {
new JSON:jsonColors = json_object_get_value(settings, szKey, .dot_not = true);
if(jsonColors != Invalid_JSON && json_is_array(jsonColors)) {
for(new i = 0; i < COLOR_COMPONENTS; i++) {
iColorArray[i] = json_array_get_number(jsonColors, i);
}
}
}
@OnThrowGrenade_Post(player, weapon) {
new grenade = GetHookChainReturn(ATYPE_INTEGER);
if (!is_entity(grenade) || !is_user_connected(player)) {
return HC_CONTINUE;
}
if (get_entvar(grenade, var_flags) & FL_KILLME) {
return HC_CONTINUE;
}
new team = get_member(player, m_iTeam);
new trailColorType;
if (g_eTrailConfig[CONFIG_USE_TEAM_COLOR]) {
trailColorType = (TeamName:team == TEAM_TERRORIST) ? COLOR_TEAM_TT : COLOR_TEAM_CT;
}
else {
new WeaponIdType:weaponType = WeaponIdType:get_member(weapon, m_iId);
trailColorType = GetGrenadeColorType(weaponType);
}
if (trailColorType == -1) return HC_CONTINUE;
new players[MAX_PLAYERS], playerCount;
get_players(players, playerCount, "ch");
new teamBits = (1 << team);
for (new i = 0; i < playerCount; i++) {
if ((1 << get_member(players[i], m_iTeam)) & teamBits) {
UTIL_ShowTrailEffect(players[i], grenade, g_eTrailColors[trailColorType]);
}
}
return HC_CONTINUE;
}
UTIL_ShowTrailEffect(player, grenade, const color[COLOR_COMPONENTS]) {
message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, .player = player);
write_byte(TE_BEAMFOLLOW);
write_short(grenade);
write_short(g_iSpriteTrail);
write_byte(g_eTrailConfig[CONFIG_LIFETIME] * 10);
write_byte(g_eTrailConfig[CONFIG_WIDTH]);
write_byte(color[RED]);
write_byte(color[GREEN]);
write_byte(color[BLUE]);
write_byte(g_eTrailConfig[CONFIG_BRIGHTNESS]);
message_end();
}
GetGrenadeColorType(WeaponIdType:weaponType) {
switch (weaponType) {
case WEAPON_HEGRENADE: return COLOR_HE;
case WEAPON_FLASHBANG: return COLOR_FLASH;
case WEAPON_SMOKEGRENADE: return COLOR_SMOKE;
}
return -1;
}