Auto-Reflect Improvements

This commit is contained in:
julianacat 2017-06-29 11:38:48 -05:00
parent b022a74519
commit 19b6ff3cfd
6 changed files with 128 additions and 118 deletions

View File

@ -840,6 +840,9 @@ float EffectiveTargetingRange() {
// Melees use a close range, TODO add dynamic range for demoknight swords
if (GetWeaponMode() == weapon_melee) {
return 100.0f;
// Pyros only have so much untill their flames hit
} else if ( g_pLocalPlayer->weapon()->m_iClassID == CL_CLASS(CTFFlameThrower) ) {
return 185.0f;
}
// Else return user settings
return (float)max_range;

View File

@ -12,56 +12,132 @@
namespace hacks { namespace tf { namespace autoreflect {
CatVar enabled(CV_SWITCH, "reflect_enabled", "0", "AutoReflect", "Master AutoReflect switch");
// 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 stickies(CV_SWITCH, "reflect_stickybombs", "0", "Reflect stickies", "Reflect Stickybombs");
CatVar max_distance(CV_INT, "reflect_distance", "200", "Distance", "Maximum distance to reflect at", true, 300.0f);
// TODO setup proj sorting
// TODO CatVar bigProj(CV_SWITCH, "reflect_big_projectile", "0", "Reflect big projectiles", "Reflect Rockets");
// TODO CatVar smallProj(CV_SWITCH, "reflect_small_projectile", "0", "Reflect small projectiles", "Reflect Huntsman arrows, Crusaders bolts");
// TODO CatVar miscProj(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;
// Check if player is using a flame thrower
if (g_pLocalPlayer->weapon()->m_iClassID != CL_CLASS(CTFFlameThrower)) return;
// If user settings allow, return if local player is in attack
if (idle_only && (g_pUserCmd->buttons & IN_ATTACK)) return;
CachedEntity* closest = 0;
// 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;
//if (ent->Var<Vector>(eoffsets.vVelocity).IsZero(1.0f)) continue;
float dist = ent->m_vecOrigin.DistToSqr(g_pLocalPlayer->v_Origin);
if (dist < closest_dist || !closest) {
closest = ent;
// 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 predictedProj = 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, predictedProj)) 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 = predictedProj.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, predictedProj) > 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 = predictedProj;
}
}
if (CE_BAD(closest)) return;
if (closest_dist == 0 || closest_dist > SQR((int)max_distance)) return;
Vector tr = (closest->m_vecOrigin - g_pLocalPlayer->v_Eye);
Vector angles;
VectorAngles(tr, angles);
fClampAngle(angles);
g_pUserCmd->viewangles = angles;
g_pLocalPlayer->bUseSilentAngles = true;
// 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 > 34650) 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) {
if (CE_BAD(ent)) return false;
// Check if the entity is a projectile
if (ent->m_Type != ENTITY_PROJECTILE) return false;
if (CE_INT(ent, netvar.iTeamNum) == g_pLocalPlayer->team) 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;
logging::Info("Is projectile");
// 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;
logging::Info("isnt team");
// 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;
logging::Info("pass already reflect");
}
// 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) {
if (!stickies) return false;
// Ent passed and should be reflected
return true;
}
}
return true;
// Ent didnt pass the test so return false
return false;
}
}}}

View File

@ -19,6 +19,7 @@ extern CatVar max_distance;
void CreateMove();
bool ShouldReflect(CachedEntity* ent);
bool IsEntStickyBomb(CachedEntity* ent);
}}}

View File

@ -316,6 +316,7 @@ bool IsEntityVectorVisible(CachedEntity* entity, Vector endpos) {
return (trace_object.fraction >= 0.99f || (((IClientEntity*)trace_object.m_pEnt)) == RAW_ENT(entity));
}
// For when you need to vis check something that isnt the local player
bool VisCheckEntFromEnt(CachedEntity* startEnt, CachedEntity* endEnt) {
// We setSelf as the starting ent as we dont want to hit it, we want the other ent
trace_t trace;
@ -336,6 +337,27 @@ bool VisCheckEntFromEnt(CachedEntity* startEnt, CachedEntity* endEnt) {
return false;
}
// Use when you need to vis check something but its not the ent origin that you use, so we check from the vector to the ent, ignoring the first just in case
bool VisCheckEntFromEntVector(Vector startVector, CachedEntity* startEnt, CachedEntity* endEnt) {
// We setSelf as the starting ent as we dont want to hit it, we want the other ent
trace_t trace;
trace::filter_default.SetSelf(RAW_ENT(startEnt));
// Setup the trace starting with the origin of the starting ent attemting to hit the origin of the end ent
Ray_t ray;
ray.Init(startVector, endEnt->m_vecOrigin);
{
PROF_SECTION(IEVV_TraceRay);
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, &trace);
}
// Is the entity that we hit our target ent? if so, the vis check passes
if (trace.m_pEnt) {
if ((((IClientEntity*)trace.m_pEnt)) == RAW_ENT(endEnt)) return true;
}
// Since we didnt hit our target ent, the vis check failed so return false
return false;
}
Vector GetBuildingPosition(CachedEntity* ent) {
Vector res;
res = ent->m_vecOrigin;
@ -688,98 +710,6 @@ bool IsEntityVisiblePenetration(CachedEntity* entity, int hb) {
return false;
}
class CMoveData;
/*void RunEnginePrediction(IClientEntity* ent, CUserCmd *ucmd) {
// we are going to require some helper functions for this to work
// notably SetupMove, FinishMove and ProcessMovement
// setup the types of the functions
typedef void(*SetupMoveFn)(IClientEntity *, CUserCmd *, class IMoveHelper *, CMoveData *);
typedef void(*FinishMoveFn)(IClientEntity *, CUserCmd*, CMoveData*);
typedef void(*ProcessMovementFn)(IClientEntity *, CMoveData *);
typedef void(*StartTrackPredictionErrorsFn)(IClientEntity *);
typedef void(*FinishTrackPredictionErrorsFn)(IClientEntity *);
// get the vtable
void **predictionVtable = *(void ***)prediction;
logging::Info("predictionVtable 0x%08x", predictionVtable);
// get the functions
SetupMoveFn oSetupMove = (SetupMoveFn) predictionVtable[19];
FinishMoveFn oFinishMove = (FinishMoveFn) predictionVtable[20];
// get the vtable
void **gameMovementVtable = *(void ***)gamemovement;
logging::Info("gameMovementVtable 0x%08x", gameMovementVtable);
// get the functions
ProcessMovementFn oProcessMovement = (ProcessMovementFn) gameMovementVtable[2];
StartTrackPredictionErrorsFn oStartTrackPredictionErrors = (StartTrackPredictionErrorsFn) gameMovementVtable[3];
FinishTrackPredictionErrorsFn oFinishTrackPredictionErrors = (FinishTrackPredictionErrorsFn) gameMovementVtable[4];
// use this as movedata (should be big enough - otherwise the stack will die!)
unsigned char moveData[2048];
CMoveData *pMoveData = (CMoveData *)&(moveData[0]);
logging::Info("pMoveData 0x%08x", pMoveData);
// back up globals
float frameTime = gvars->frametime;
float curTime = gvars->curtime;
CUserCmd defaultCmd;
if(ucmd == NULL)
{
ucmd = &defaultCmd;
}
// set the current command
NET_VAR(ent, 0x105C, void*) = ucmd;
// set up the globals
gvars->curtime = gvars->interval_per_tick * NET_INT(ent, netvar.nTickBase);
gvars->frametime = gvars->interval_per_tick;
oStartTrackPredictionErrors(ent);
logging::Info("StartTrackPredictionErrors(ent)");
oSetupMove(ent, ucmd, NULL, pMoveData);
logging::Info("oSetupMove");
oProcessMovement(ent, pMoveData);
logging::Info("oProcessMovement");
oFinishMove(ent, ucmd, pMoveData);
logging::Info("oFinishMove");
oFinishTrackPredictionErrors(ent);
logging::Info("oFinishTrackPredictionErrors");
// reset the current command
NET_VAR(ent, 0x105C, void *) = 0;
// restore globals
gvars->frametime = frameTime;
gvars->curtime = curTime;
return;
}
float oldCurtime;
float oldFrametime;
void StartPrediction(CUserCmd* cmd) {
oldCurtime = gvars->curtime;
oldFrametime = gvars->frametime;
gvars->curtime = NET_INT(g_pLocalPlayer->entity, netvar.nTickBase) * gvars->interval_per_tick;
gvars->frametime = gvars->interval_per_tick;
//gamemovement->
}
void EndPrediction() {
gvars->curtime = oldCurtime;
gvars->frametime = oldFrametime;
}*/
void PrintChat(const char* fmt, ...) {
CHudBaseChat* chat = (CHudBaseChat*)g_CHUD->FindElement("CHudChat");
if (chat) {

View File

@ -74,7 +74,8 @@ void VectorAngles(Vector &forward, Vector &angles);
bool IsEntityVisible(CachedEntity* entity, int hb);
bool IsEntityVectorVisible(CachedEntity* entity, Vector endpos);
bool VisCheckEntFromEnt(CachedEntity* startEnt, CachedEntity* endEnt);
bool VisCheckEntFromEntVector(Vector startVector, CachedEntity* startEnt, CachedEntity* endEnt);
bool LineIntersectsBox(Vector& bmin, Vector& bmax, Vector& lmin, Vector& lmax);
float DistToSqr(CachedEntity* entity);

View File

@ -100,9 +100,8 @@
"name": "Auto Sticky",
"list": [
"sticky_enabled",
"sticky_distance",
"sticky_buildings",
"sticky_visable"
"sticky_legit"
]
},
{