#pragma semicolon 1
#include <amxmodx>
#include <fakemeta>
#include <reapi>
#include <xs>
#define IsPlayer(%1) (%1 && %1 <= MaxClients)
#define SCREENFADE_TIME 5.0
public plugin_init() {
RegisterHookChain(RG_RadiusFlash_TraceLine, "RadiusFlash_TraceLine_Pre", false);
}
public RadiusFlash_TraceLine_Pre(const id, inflictor, attacker, Float:start[3], Float:end[3], tracehandle) {
if(IsPlayer(inflictor)) {
return HC_CONTINUE;
}
if(IsGlassWall(inflictor, start, end, tracehandle)) {
new Float: view_ofs[3]; get_entvar(id, var_view_ofs, view_ofs);
new Float: v_angle[3]; get_entvar(id, var_v_angle, v_angle);
xs_vec_add(start, view_ofs, start);
new visible = is_angle_visible(start, v_angle, end, 46.0, 50.0);
UTIL_ScreenFade(
.Index = id,
.flUntilTime = SCREENFADE_TIME,
.Alpha = visible ? 255 : 127
);
}
return HC_CONTINUE;
}
// *********** Stocks ***********
stock bool: IsGlassWall(inflictor, Float: start[3], Float: end[3], tracehandle) {
engfunc(EngFunc_TraceLine, start, end, DONT_IGNORE_MONSTERS | IGNORE_GLASS, inflictor, tracehandle);
new Float: flFraction; get_tr2(tracehandle, TR_flFraction, flFraction);
if(flFraction == 1.0) {
return false;
}
new pHit = get_tr2(tracehandle, TR_pHit);
return (FClassnameIs(pHit, "func_wall") && Float: get_entvar(pHit, var_renderamt) < 200.0);
}
stock bool: is_angle_visible(Float:origin[3], Float:angles[3], Float:point[3], Float:x, Float:y) { // https://amx-x.ru/viewtopic.php?f=8&p=298972#p298972
static i; i = -1; // Если углы не игрока, т.е. от 0 до 360.
while(++i < sizeof(angles)) {
if(angles[i] > 180.0) angles[i] -= 360.0;
}
static Float:vec[3];
vec[0] = point[0] - origin[0];
vec[1] = point[1] - origin[1];
vec[2] = point[2] - origin[2];
vector_to_angle(vec, vec);
vec[0] = floatabs(vec[0] - angles[0]);
vec[1] = floatabs(vec[1] - angles[1]);
if(vec[0] > 180.0) vec[0] = floatabs(360.0 - vec[0]);
if(vec[1] > 180.0) vec[1] = floatabs(360.0 - vec[1]);
return (vec[0] > y || vec[1] > x);
}
stock UTIL_ScreenFade(const Index, Float: flUntilTime = 3.0, Color[3] = { 255, 255, 255 }, Alpha = 255) {
if(IsBlind(Index)) {
return 0;
}
const FFADE_IN = 0x0000;
static msgidScreenFade;
if(msgidScreenFade || (msgidScreenFade = get_user_msgid("ScreenFade"))) {
new Float: flGameTime = get_gametime();
flUntilTime += flGameTime;
set_member(Index, m_blindUntilTime, flUntilTime);
set_member(Index, m_blindStartTime, flGameTime);
new Float: flEffectTime = (flUntilTime - flGameTime)/2;
set_member(Index, m_blindHoldTime, flEffectTime);
set_member(Index, m_blindFadeTime, flEffectTime);
enum { red, green, blue };
message_begin(MSG_ONE, msgidScreenFade, .player = Index);
{
write_short(FixedUnsigned16(get_member(Index, m_blindFadeTime)));
write_short(FixedUnsigned16(get_member(Index, m_blindHoldTime)));
write_short(FFADE_IN); // Flags
write_byte(Color[red]); // Color Red
write_byte(Color[green]); // Color Green
write_byte(Color[blue]); // Color Blue
write_byte(Alpha); // Alpha
}
message_end();
}
return 1;
}
stock bool: IsBlind(const Index) {
return (get_member(Index, m_blindUntilTime) > get_gametime());
}
stock FixedUnsigned16(Float: flValue, iScale = (1 << 12)) {
return clamp(floatround(flValue * iScale), 0, 0xFFFF);
}