182 lines
6.2 KiB
C++
182 lines
6.2 KiB
C++
|
|
/*
|
|
*
|
|
* Auto-Airblast
|
|
*
|
|
*/
|
|
|
|
namespace modules::source::features::airblast {
|
|
|
|
// Yes its ripped from cathook, but i made it, i deserve the paste
|
|
// Vars for user settings
|
|
/*CatVar enabled(CV_SWITCH, "reflect_enabled", "0", "Auto Reflect", "Master
|
|
AutoReflect switch"); CatVar idle_only(CV_SWITCH, "reflect_only_idle", "0",
|
|
"Only when not shooting", "Don't AutoReflect if you're holding M1"); CatVar
|
|
legit(CV_SWITCH, "reflect_legit", "0", "Legit Reflect", "Only Auto-airblasts
|
|
projectiles that you can see, doesnt move your crosshair"); CatVar
|
|
dodgeball(CV_SWITCH, "reflect_dodgeball", "0", "Dodgeball Mode","Allows
|
|
auto-reflect to work in dodgeball servers"); CatVar blastkey(CV_KEY,
|
|
"reflect_key", "0", "Reflect Key", "Hold this key to activate auto-airblast");
|
|
CatVar stickies(CV_SWITCH, "reflect_stickybombs", "0", "Reflect stickies",
|
|
"Reflect Stickybombs");
|
|
// TODO setup proj sorting
|
|
// TODO CatVar big_proj(CV_SWITCH, "reflect_big_projectile", "0", "Reflect big
|
|
// projectiles", "Reflect Rockets");
|
|
// TODO CatVar small_proj(CV_SWITCH, "reflect_small_projectile", "0", "Reflect
|
|
// small projectiles", "Reflect Huntsman arrows, Crusaders bolts");
|
|
// TODO CatVar misc_proj(CV_SWITCH, "reflect_misc_projectile", "0", "Reflect
|
|
// other", "Reflect jarate, milk");
|
|
|
|
// Function called by game for movement
|
|
void CreateMove() {
|
|
// Check if user settings allow Auto Reflect
|
|
if (!enabled) return;
|
|
if (blastkey && !blastkey.KeyDown()) return;
|
|
|
|
// Check if player is using a flame thrower
|
|
if (g_pLocalPlayer->weapon()->m_iClassID != CL_CLASS(CTFFlameThrower))
|
|
return;
|
|
|
|
// Check for phlogistinator, which is item 594
|
|
if (HasWeapon(LOCAL_E, 594))
|
|
return;
|
|
|
|
// If user settings allow, return if local player is in attack
|
|
if (idle_only && (g_pUserCmd->buttons & IN_ATTACK))
|
|
return;
|
|
|
|
// Create some book-keeping vars
|
|
float closest_dist = 0.0f;
|
|
Vector closest_vec;
|
|
// Loop to find the closest entity
|
|
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
|
{
|
|
|
|
// Find an ent from the for loops current tick
|
|
CachedEntity *ent = ENTITY(i);
|
|
|
|
// Check if null or dormant
|
|
if (CE_BAD(ent))
|
|
continue;
|
|
|
|
// Check if ent should be reflected
|
|
if (!ShouldReflect(ent))
|
|
continue;
|
|
|
|
// Some extrapolating due to reflect timing being latency based
|
|
// Grab latency
|
|
float latency =
|
|
g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_INCOMING) +
|
|
g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING);
|
|
// Create a vector variable to store our velocity
|
|
Vector velocity;
|
|
// Grab Velocity of projectile
|
|
velocity::EstimateAbsVelocity(RAW_ENT(ent), velocity);
|
|
// Predict a vector for where the projectile will be
|
|
Vector predicted_proj = ent->m_vecOrigin + (velocity * latency);
|
|
;
|
|
|
|
// Dont vischeck if ent is stickybomb or if dodgeball mode is enabled
|
|
if (!IsEntStickyBomb(ent) && !dodgeball)
|
|
{
|
|
// Vis check the predicted vector
|
|
if (!IsVectorVisible(g_pLocalPlayer->v_Origin, predicted_proj))
|
|
continue;
|
|
} //else {
|
|
// Stickys are weird, we use a different way to vis check them
|
|
// Vis checking stickys are wonky, I quit, just ignore the check
|
|
>_>
|
|
//if (!VisCheckEntFromEnt(ent, LOCAL_E)) continue;
|
|
//}
|
|
|
|
// Calculate distance
|
|
float dist = predicted_proj.DistToSqr(g_pLocalPlayer->v_Origin);
|
|
|
|
// If legit mode is on, we check to see if reflecting will work if we
|
|
// dont aim at the projectile
|
|
if (legit)
|
|
{
|
|
if (GetFov(g_pLocalPlayer->v_OrigViewangles,
|
|
g_pLocalPlayer->v_Eye, predicted_proj) > 85.0f) continue;
|
|
}
|
|
|
|
// Compare our info to the others and determine if its the best, if we
|
|
// dont have a projectile already, then we save it here
|
|
if (dist < closest_dist || closest_dist == 0.0f)
|
|
{
|
|
closest_dist = dist;
|
|
closest_vec = predicted_proj;
|
|
}
|
|
}
|
|
|
|
// Determine whether the closest projectile is whithin our parameters,
|
|
// preferably 185 units should be our limit, sqr is around the number
|
|
below if (closest_dist == 0 || closest_dist > 34400) return;
|
|
|
|
// We dont want to aim if legit is true
|
|
if (!legit)
|
|
{
|
|
// Aim at predicted projectile
|
|
AimAt(g_pLocalPlayer->v_Eye, closest_vec, g_pUserCmd);
|
|
// Use silent angles
|
|
g_pLocalPlayer->bUseSilentAngles = true;
|
|
}
|
|
|
|
// Airblast
|
|
g_pUserCmd->buttons |= IN_ATTACK2;
|
|
|
|
// Function is finished, return
|
|
return;
|
|
}
|
|
|
|
// Function to determine whether an ent is good to reflect
|
|
bool ShouldReflect(CachedEntity *ent)
|
|
{
|
|
// Check if the entity is a projectile
|
|
if (ent->m_Type != ENTITY_PROJECTILE)
|
|
return false;
|
|
|
|
// We dont want to do these checks in dodgeball, it breakes if we do
|
|
if (!dodgeball)
|
|
{
|
|
// Check if the projectile is your own teams
|
|
if (!ent->m_bEnemy)
|
|
return false;
|
|
|
|
// If projectile is already deflected, don't deflect it again.
|
|
if (CE_INT(ent, (ent->m_bGrenadeProjectile
|
|
?
|
|
// NetVar for grenades netvar.Grenade_iDeflected
|
|
:
|
|
// For rockets netvar.Rocket_iDeflected)))
|
|
return false;
|
|
}
|
|
|
|
// Check if the projectile is a sticky bomb and if the user settings allow
|
|
// it to be reflected
|
|
if (IsEntStickyBomb(ent) && !stickies)
|
|
return false;
|
|
|
|
// Target passed the test, return true
|
|
return true;
|
|
}
|
|
|
|
bool IsEntStickyBomb(CachedEntity *ent)
|
|
{
|
|
// Check if the projectile is a sticky bomb
|
|
if (ent->m_iClassID == CL_CLASS(CTFGrenadePipebombProjectile))
|
|
{
|
|
if (CE_INT(ent, netvar.iPipeType) == 1)
|
|
{
|
|
// Ent passed and should be reflected
|
|
return true;
|
|
}
|
|
}
|
|
// Ent didnt pass the test so return false
|
|
return false;
|
|
}
|
|
}
|
|
void Init()
|
|
*/
|
|
} // namespace modules::source::features::airblast
|