/* AMX Mod X script. Blinding Flashlight plugin (c) Copyright 2006, VEN (c) Copyright 2007, Simon Logic 'slspam@land.ru' This file is provided AS IS (no warranties). Info: Use your flashlight to blind your enemies! Requirements: * any mod * AMX/X 1.7x or higher New cvars: * bf_mindistance (default=500) min. distance with constant flashlight impact level defined by 'bf_maxflashtime' & 'bf_maxblend' cvars * bf_maxdistance (default=1500) max. distance when flashlight impact level exhausts (actually it's smaller a bit due to math calculations; dependence is linear) * bf_maxblindtime (default=1.5) blind time (actually it's holdtime param of ScreenFade event which does not include fade in/out effect time) at minimal distance to victim * bf_maxblend (default=255) max. blend level (transparency) at 'bf_mindistance' distance & closer * bf_minblend (default=128) min. blend level (transparency) at 'bf_maxdistance' distance * bf_hitplace (default=b) set hitplace to trigger blind effect: a - generic (actually nothing) b - head c - chest d - stomach e - leftarm f - rightarm g - leftleg h - rightleg * bf_fxfactor (defaul=4.0) multiplier to calculate duration of blind fx (fade in/out) Notes: * all cvars are read/applied on map start & each time flashlight is triggered by any player * i recommend you to set 'bf_mindistance' cvar to 200 for better gameplay; right now this value is based on real in-game experiments with flashlight power * i recommend you to use CustomFlashlight plugin by XxAvalanchexX to adjust (speed-up) flashlight battery consumption because default gamplay rules aren't balanced with this plugin Credits: * VEN for plugin base Changelog: v0.2.3SL [2007-06-28] + added cvars 'bf_hitplace', 'bf_fxfactor' * adjusted default cvar values v0.2.2SL [2007-06-27] * changed light impact formula to make it more user-friendly * changed default light impact level; previous one was too high + added bunch of cvars: 'bf_maxdistance', 'bf_maxflashtime', 'bf_maxblindtime','bf_maxblend', 'bf_minblend' + show a notification text on successful blind event at victim & attacker HUD center v0.2.1SL [2007-06-26] + potential support of any mod ! reset g_flash_until array on round restart; this could lead to no-blind issue ! fixed holdtime to seconds formula; previous formula results in too long periods of flashing; this could lead to no-blind issue ! now you can't blind a victim when he doesn't look at attacker v0.2.0 * original version by VEN (http://forums.alliedmods.net/showpost.php?p=362999&postcount=32) */ #include #include #include #include #define MY_PLUGIN_NAME "Blinding Flashlight" #define MY_PLUGIN_VERSION "0.2.3SL" #define MY_PLUGIN_AUTHORS "VEN & SL" #define MAX_CLIENTS 32 // gametime <-> flashtime coefficient #define C_FLASHTIME (1<<12) // flash flags, RGB, alpha #define FLASH_FLAGS 0 #define FLASH_RED 255 #define FLASH_GREEN 255 #define FLASH_BLUE 255 //#define FLASH_ALPHA 255 new bool:g_flashlight[MAX_CLIENTS + 1] new Float:g_flash_until[MAX_CLIENTS + 1] new g_msgid_screen_fade new bool:g_bFF, bool:g_bUnderCS new g_iHitPlaceFlags, g_iMaxDist, g_iMinDist, g_iDeltaDist, g_iMaxBlend, g_iMinBlend, g_iDeltaBlend new Float:g_fMaxImpcatTime, Float:g_fFxFactor new g_pcvar_ff, g_cvarMaxDist, g_cvarMinDist, g_cvarMaxImpactTime, g_cvarMaxBlend, g_cvarMinBlend, g_cvarHitPlace, g_cvarFxFactor //----------------------------------------------------------------------------- public plugin_init() { g_bUnderCS = bool:cstrike_running() g_msgid_screen_fade = get_user_msgid("ScreenFade") register_plugin(MY_PLUGIN_NAME, MY_PLUGIN_VERSION, MY_PLUGIN_AUTHORS) register_cvar("version_blinding_flashlight", MY_PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY) // NOTE: actual distance is further but it's already long enough g_cvarMaxDist = register_cvar("bf_maxdistance", "1500") // NOTE: this is exact length when strength of light stays constant // (used Zoom Info plugin & AWP weapon) g_cvarMinDist = register_cvar("bf_mindistance", "500") g_cvarMaxImpactTime = register_cvar("bf_maxblindtime", "1.5") g_cvarMaxBlend = register_cvar("bf_maxblend", "255") g_cvarMinBlend = register_cvar("bf_minblend", "128") g_cvarHitPlace = register_cvar("bf_hitplace", "b") g_cvarFxFactor = register_cvar("bf_fxfactor", "4.0") //g_cvarNotify = register_cvar("bc_notify", "vc") register_event("Flashlight", "event_flashlight", "be") // alive register_event("Health", "event_notalive", "bd", "1=0") // dead if(g_bUnderCS) register_event("HLTV", "event_new_round", "a", "1=0", "2=0") register_forward(FM_PlayerPreThink, "forward_player_prethink") } //----------------------------------------------------------------------------- public plugin_cfg() { g_pcvar_ff = get_cvar_pointer("mp_friendlyfire") storeCVars() } //----------------------------------------------------------------------------- public event_flashlight(id) { g_flashlight[id] = bool:read_data(1) storeCVars() } //----------------------------------------------------------------------------- public event_notalive(id) { g_flashlight[id] = false g_flash_until[id] = 0.0 } //----------------------------------------------------------------------------- public client_disconnect(id) { g_flashlight[id] = false g_flash_until[id] = 0.0 } //----------------------------------------------------------------------------- public event_new_round() { arrayset(_:g_flashlight, 0, sizeof(g_flashlight)) arrayset(_:g_flash_until, 0, sizeof(g_flash_until)) } //----------------------------------------------------------------------------- public forward_player_prethink(id) { if(!g_flashlight[id]) return FMRES_IGNORED static phit, hitgroup, Float:dist dist = get_user_aiming(id, phit, hitgroup) if (!phit || !((1<= g_iMaxDist) // holdtime will be <= 0 return false if(attacker == victim) return false static Float:gametime; gametime= get_gametime() if(g_flash_until[victim] > gametime) // flash is still active return false static iAlpha static Float:holdtime, Float:duration getScreenFadeParams(distance, holdtime, duration, iAlpha) if(holdtime < 0.1) { // light is too tiny g_flash_until[victim] = gametime + 0.1 return false } static Float:fOrigin[3] pev(attacker, pev_origin, fOrigin) if(!fm_is_in_viewcone(victim, fOrigin)) // victim can't see the light return false static Float:holdtime_sec; holdtime_sec = holdtime / C_FLASHTIME g_flash_until[victim] = gametime + holdtime_sec //g_flash_until[victim] = gametime + holdtime_sec + EMP_IMPACTTIME_TO_SEC(duration)/2.0 message_begin(MSG_ONE, g_msgid_screen_fade, _, victim) write_short(floatround(duration)) write_short(floatround(holdtime)) write_short(FLASH_FLAGS) write_byte(FLASH_RED) write_byte(FLASH_GREEN) write_byte(FLASH_BLUE) write_byte(iAlpha) message_end() // TODO: implement via cvar? static name[32] get_user_name(victim, name, sizeof(name)-1) client_print(victim, print_center, "You're blinded for %.1f sec!", holdtime_sec) client_print(attacker, print_center, "%s is blinded!", name) return true } //----------------------------------------------------------------------------- stock bool:fm_is_in_viewcone(index, const Float:point[3]) { static Float:angles[3] //pev(index, pev_angles, angles) pev(index, pev_v_angle, angles) engfunc(EngFunc_MakeVectors, angles) global_get(glb_v_forward, angles) angles[2] = 0.0 static Float:origin[3], Float:diff[3], Float:norm[3] pev(index, pev_origin, origin) xs_vec_sub(point, origin, diff) diff[2] = 0.0 xs_vec_normalize(diff, norm) static Float:dot, Float:fov dot = xs_vec_dot(norm, angles) pev(index, pev_fov, fov) if (dot >= floatcos(fov * M_PI / 360.0)) return true return false } //----------------------------------------------------------------------------- stock getScreenFadeParams(const Float:distance, &Float:holdtime, &Float:duration, &alpha) { if(distance <= g_iMinDist) { holdtime = g_fMaxImpcatTime alpha = g_iMaxBlend } else { static Float:fPercent; fPercent = (g_iMaxDist - distance) / g_iDeltaDist holdtime = fPercent * g_fMaxImpcatTime normFlashtimeVal(holdtime) if(holdtime) { alpha = floatround(g_iMinBlend + g_iDeltaBlend * fPercent) normBlendVal(alpha) } else alpha = 0 } if(holdtime) { duration = g_fFxFactor * holdtime normFlashtimeVal(duration) } else duration = 0.0 } //----------------------------------------------------------------------------- stock storeCVars() { if(g_pcvar_ff) g_bFF = bool:get_pcvar_num(g_pcvar_ff) g_iHitPlaceFlags = getPCvarAsFlags(g_cvarHitPlace) g_iMinDist = get_pcvar_num(g_cvarMinDist) g_iMaxDist = get_pcvar_num(g_cvarMaxDist) if(g_iMaxDist < 0) g_iMaxDist = 0 if(g_iMinDist > g_iMaxDist) g_iMinDist = g_iMaxDist g_iDeltaDist = g_iMaxDist - g_iMinDist g_fMaxImpcatTime = get_pcvar_float(g_cvarMaxImpactTime) * C_FLASHTIME normFlashtimeVal(g_fMaxImpcatTime) g_iMaxBlend = get_pcvar_num(g_cvarMaxBlend) normBlendVal(g_iMaxBlend) g_iMinBlend = get_pcvar_num(g_cvarMinBlend) if(g_iMinBlend > g_iMaxBlend) g_iMinBlend = g_iMaxBlend else normBlendVal(g_iMinBlend) g_iDeltaBlend = g_iMaxBlend - g_iMinBlend g_fFxFactor = get_pcvar_float(g_cvarFxFactor) if(g_fFxFactor < 0.0) g_fFxFactor = 0.0 } //----------------------------------------------------------------------------- stock normBlendVal(&val) { if(val < 0) val = 0 else if(val > 255) val = 255 } //----------------------------------------------------------------------------- stock normFlashtimeVal(&Float:val) { if(val < 0.1) val = 0.0 else if(val > 65535.0) val = 65535.0 } //----------------------------------------------------------------------------- stock getPCvarAsFlags(pcvar) { static sValue[27] get_pcvar_string(pcvar, sValue, sizeof(sValue) - 1) return read_flags(sValue) } //-----------------------------------------------------------------------------