Added option to vischeck/multipoint all hitboxes instead of one (#1697)
Added option to vischeck all hitboxes
This commit is contained in:
parent
4e09888306
commit
6530e72b2b
@ -26,8 +26,8 @@
|
||||
<List width="150">
|
||||
<AutoVariable width="fill" target="aimbot.projectile.enable" label="Enable projectile aimbot"/>
|
||||
<AutoVariable width="fill" target="aimbot.debug.engine-pp" label="Engine prediction"/>
|
||||
<AutoVariable width="fill" target="misc.auto-flip-viewmodel" label="Flip viewmodel" tooltip="Automatically flip the viewmodel for projectile weapons."/>
|
||||
<AutoVariable width="fill" target="debug.pp-steps" label="Prediction steps" min="1" max="300"/>
|
||||
<AutoVariable width="fill" target="misc.auto-flip-viewmodel" label="Flip viewmodel" tooltip="Automatically flip the viewmodel for projectile weapons."/>
|
||||
<AutoVariable width="fill" target="aimbot.projectile.gravity" label="Gravity override"/>
|
||||
<AutoVariable width="fill" target="aimbot.projectile.initial-velocity" label="Initial velocity"/>
|
||||
<AutoVariable width="fill" target="aimbot.projectile.speed" label="Velocity override"/>
|
||||
@ -86,6 +86,13 @@
|
||||
</LabeledObject>
|
||||
<AutoVariable width="fill" target="aimbot.target.max-range" label="Max range" tooltip="Entities further than this distance will not be targeted. Measured in Hammer units."/>
|
||||
<AutoVariable width="fill" target="aimbot.multipoint" label="Multipoint"/>
|
||||
<LabeledObject width="fill" label="All Hiitboxes" tooltip="This will vischeck as many hitboxes as it can on the target to see if it can shoot. This will reduce your FPS.">
|
||||
<Select target="aimbot.vischeck-hitboxes">
|
||||
<Option name="Disable" value="0"/>
|
||||
<Option name="Rage Only" value="1"/>
|
||||
<Option name="All" value="2"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<AutoVariable width="fill" target="aimbot.assistance.only" label="Assistance only" tooltip="Aimbot will only activate if your mouse has moved in the last half second."/>
|
||||
<AutoVariable width="fill" target="aimbot.lock-target" label="Lock target" tooltip="Lock onto a target until they die or leave your FOV."/>
|
||||
<AutoVariable width="fill" target="aimbot.target.ignore-non-rage" label="Rage only" tooltip="Only target players set to RAGE."/>
|
||||
|
@ -43,9 +43,11 @@ bool IsTargetStateGood(CachedEntity *entity);
|
||||
bool Aim(CachedEntity *entity);
|
||||
void DoAutoshoot(CachedEntity *target = nullptr);
|
||||
int notVisibleHitbox(CachedEntity *target, int preferred);
|
||||
int autoHitbox(CachedEntity* target);
|
||||
bool hitscanSpecialCases(CachedEntity* target_entity, int weapon_case);
|
||||
bool projectileSpecialCases(CachedEntity* target_entity, int weapon_case);
|
||||
std::vector<Vector> getHitpointsVischeck(CachedEntity *ent, int hitbox);
|
||||
float projectileHitboxSize(int projectile_size);
|
||||
int autoHitbox(CachedEntity *target);
|
||||
bool hitscanSpecialCases(CachedEntity *target_entity, int weapon_case);
|
||||
bool projectileSpecialCases(CachedEntity *target_entity, int weapon_case);
|
||||
int BestHitbox(CachedEntity *target);
|
||||
bool isHitboxMedium(int hitbox);
|
||||
int ClosestHitbox(CachedEntity *target);
|
||||
|
@ -118,6 +118,7 @@ bool GetProjectileData(CachedEntity *weapon, float &speed, float &gravity, float
|
||||
bool IsVectorVisible(Vector a, Vector b, bool enviroment_only = false, CachedEntity *self = LOCAL_E, unsigned int mask = MASK_SHOT_HULL);
|
||||
// A Special function for navparser to check if a Vector is visible.
|
||||
bool IsVectorVisibleNavigation(Vector a, Vector b, unsigned int mask = MASK_SHOT_HULL);
|
||||
bool didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity, int projectile_size);
|
||||
Vector getShootPos(Vector angle);
|
||||
Vector GetForwardVector(Vector origin, Vector viewangles, float distance, CachedEntity *punch_entity = nullptr);
|
||||
Vector GetForwardVector(float distance, CachedEntity *punch_entity = nullptr);
|
||||
|
@ -24,10 +24,9 @@ Vector SimpleLatencyPrediction(CachedEntity *ent, int hb);
|
||||
|
||||
// The first entry ignores initial velocity, the second one does not.
|
||||
// Used for vischeck things.
|
||||
std::pair<Vector, Vector> BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity = 0.0f);
|
||||
std::pair<Vector, Vector> ProjectilePrediction(CachedEntity *ent, int hb, float speed, float gravitymod, float entgmod, float proj_startvelocity = 0.0f);
|
||||
std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb, float speed, float gravitymod, float entgmod, float proj_startvelocity = 0.0f);
|
||||
|
||||
std::pair<Vector, Vector> BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity);
|
||||
std::vector<Vector> Predict(CachedEntity *player, Vector pos, float offset, Vector vel, Vector acceleration, std::pair<Vector, Vector> minmax, int count, bool vischeck = true);
|
||||
Vector PredictStep(Vector pos, Vector &vel, const Vector &acceleration, std::pair<Vector, Vector> *minmax, float steplength = g_GlobalVars->interval_per_tick, StrafePredictionData *strafepred = nullptr, bool vischeck = true, std::optional<float> grounddistance = std::nullopt);
|
||||
float PlayerGravityMod(CachedEntity *player);
|
||||
|
@ -29,6 +29,7 @@ static settings::Boolean autoshoot{ "aimbot.autoshoot", "1" };
|
||||
static settings::Boolean autoreload{ "aimbot.autoshoot.activate-heatmaker", "false" };
|
||||
static settings::Boolean autoshoot_disguised{ "aimbot.autoshoot-disguised", "1" };
|
||||
static settings::Boolean multipoint{ "aimbot.multipoint", "0" };
|
||||
static settings::Int vischeck_hitboxes{ "aimbot.vischeck-hitboxes", "0" };
|
||||
static settings::Int hitbox_mode{ "aimbot.hitbox-mode", "0" };
|
||||
static settings::Float normal_fov{ "aimbot.fov", "0" };
|
||||
static settings::Int priority_mode{ "aimbot.priority-mode", "0" };
|
||||
@ -147,7 +148,7 @@ std::vector<Vector> getValidHitpoints(CachedEntity *ent, int hitbox)
|
||||
hitpoints.push_back(hb->center);
|
||||
}
|
||||
|
||||
if (!multipoint)
|
||||
if (!*multipoint)
|
||||
return hitpoints;
|
||||
|
||||
// Multipoint
|
||||
@ -186,6 +187,77 @@ std::vector<Vector> getValidHitpoints(CachedEntity *ent, int hitbox)
|
||||
positions.insert(positions.end(), corners, &corners[8]);
|
||||
positions.insert(positions.end(), line_positions, &line_positions[12]);
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
trace_t trace;
|
||||
if (IsEntityVectorVisible(ent, positions[i], true, MASK_SHOT_HULL, &trace))
|
||||
{
|
||||
if (trace.hitbox == hitbox)
|
||||
hitpoints.push_back(positions[i]);
|
||||
}
|
||||
}
|
||||
if (*vischeck_hitboxes)
|
||||
{
|
||||
if (*vischeck_hitboxes == 1 && playerlist::AccessData(ent).state != playerlist::k_EState::RAGE)
|
||||
{
|
||||
return hitpoints;
|
||||
}
|
||||
int i = 0;
|
||||
while (hitpoints.empty() && i <= 17) // Prevents returning empty at all costs. Loops through every hitbox
|
||||
{
|
||||
if (hitbox == i)
|
||||
i++;
|
||||
hitpoints = getHitpointsVischeck(ent, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return hitpoints;
|
||||
}
|
||||
std::vector<Vector> getHitpointsVischeck(CachedEntity *ent, int hitbox)
|
||||
{
|
||||
std::vector<Vector> hitpoints;
|
||||
auto hb = ent->hitboxes.GetHitbox(hitbox);
|
||||
if (!*multipoint)
|
||||
{
|
||||
hitpoints.push_back(hb->center);
|
||||
return hitpoints;
|
||||
}
|
||||
auto bboxmin = hb->bbox->bbmin;
|
||||
auto bboxmax = hb->bbox->bbmax;
|
||||
|
||||
auto transform = ent->hitboxes.GetBones()[hb->bbox->bone];
|
||||
QAngle rotation;
|
||||
Vector origin;
|
||||
|
||||
MatrixAngles(transform, rotation, origin);
|
||||
|
||||
Vector corners[8];
|
||||
GenerateBoxVertices(origin, rotation, bboxmin, bboxmax, corners);
|
||||
|
||||
float shrink_size = 1;
|
||||
|
||||
if (!isHitboxMedium(hitbox)) // hitbox should be chosen based on size.
|
||||
shrink_size = 3;
|
||||
else
|
||||
shrink_size = 6;
|
||||
|
||||
// Shrink positions by moving towards opposing corner
|
||||
for (int i = 0; i < 8; i++)
|
||||
corners[i] += (corners[7 - i] - corners[i]) / shrink_size;
|
||||
|
||||
// Generate middle points on line segments
|
||||
// Define cleans up code
|
||||
|
||||
const Vector line_positions[12] = { GET_MIDDLE(0, 1), GET_MIDDLE(0, 2), GET_MIDDLE(1, 3), GET_MIDDLE(2, 3), GET_MIDDLE(7, 6), GET_MIDDLE(7, 5), GET_MIDDLE(6, 4), GET_MIDDLE(5, 4), GET_MIDDLE(0, 4), GET_MIDDLE(1, 5), GET_MIDDLE(2, 6), GET_MIDDLE(3, 7) };
|
||||
|
||||
// Create combined vector
|
||||
std::vector<Vector> positions;
|
||||
|
||||
positions.reserve(sizeof(Vector) * 20);
|
||||
positions.insert(positions.end(), corners, &corners[8]);
|
||||
positions.insert(positions.end(), line_positions, &line_positions[12]);
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
trace_t trace;
|
||||
@ -845,6 +917,36 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
|
||||
AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX];
|
||||
cd.hitbox = BestHitbox(entity);
|
||||
if (*vischeck_hitboxes && !*multipoint)
|
||||
{
|
||||
if (*vischeck_hitboxes == 1 && playerlist::AccessData(entity).state != playerlist::k_EState::RAGE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
trace_t first_tracer;
|
||||
if (IsEntityVectorVisible(entity, entity->hitboxes.GetHitbox(cd.hitbox)->center, true, MASK_SHOT_HULL, &first_tracer))
|
||||
return true;
|
||||
while (i <= 17) // Prevents returning empty at all costs. Loops through every hitbox
|
||||
{
|
||||
if (i == cd.hitbox)
|
||||
i++;
|
||||
trace_t test_trace;
|
||||
std::vector<Vector> centered_hitbox = getHitpointsVischeck(entity, i);
|
||||
|
||||
if (IsEntityVectorVisible(entity, centered_hitbox[0], true, MASK_SHOT_HULL, &test_trace))
|
||||
{
|
||||
cd.hitbox = i;
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false; // It looped through every hitbox and found nothing. It isn't visible.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
@ -960,7 +1062,34 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
|
||||
return false;
|
||||
}
|
||||
float projectileHitboxSize(int projectile_size)
|
||||
{
|
||||
float projectile_hitbox_size = 6.3f;
|
||||
switch (projectile_size)
|
||||
{
|
||||
case CL_CLASS(CTFRocketLauncher):
|
||||
case CL_CLASS(CTFRocketLauncher_Mortar):
|
||||
case CL_CLASS(CTFRocketLauncher_AirStrike):
|
||||
case CL_CLASS(CTFRocketLauncher_DirectHit):
|
||||
case CL_CLASS(CTFPipebombLauncher):
|
||||
case CL_CLASS(CTFGrenadeLauncher):
|
||||
case CL_CLASS(CTFCannon):
|
||||
break;
|
||||
case CL_CLASS(CTFFlareGun):
|
||||
case CL_CLASS(CTFFlareGun_Revenge):
|
||||
case CL_CLASS(CTFDRGPomson):
|
||||
projectile_hitbox_size = 3;
|
||||
break;
|
||||
case CL_CLASS(CTFSyringeGun):
|
||||
case CL_CLASS(CTFCompoundBow):
|
||||
projectile_hitbox_size = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return projectile_hitbox_size;
|
||||
}
|
||||
// A function to aim at a specific entitiy
|
||||
bool Aim(CachedEntity *entity)
|
||||
{
|
||||
@ -969,22 +1098,24 @@ bool Aim(CachedEntity *entity)
|
||||
|
||||
// Get angles from eye to target
|
||||
Vector is_it_good = PredictEntity(entity);
|
||||
bool should_aim;
|
||||
if (extrapolate || projectileAimbotRequired || entity->m_Type() != ENTITY_PLAYER)
|
||||
if (!projectileAimbotRequired)
|
||||
{
|
||||
should_aim = IsEntityVectorVisible(entity, is_it_good, true);
|
||||
if (!IsEntityVectorVisible(entity, is_it_good, false))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, is_it_good, LOCAL_E);
|
||||
|
||||
if (projectileAimbotRequired) // unfortunately you have to check this twice, otherwise you'd have to run GetAimAtAngles far too early
|
||||
{
|
||||
should_aim = IsEntityVectorVisible(entity, is_it_good, false);
|
||||
|
||||
if (!didProjectileHit(getShootPos(angles), is_it_good, entity, projectileHitboxSize(LOCAL_W->m_iClassID())))
|
||||
return false;
|
||||
}
|
||||
if (!should_aim)
|
||||
return false;
|
||||
|
||||
AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX];
|
||||
if (fov > 0 && cd.fov > fov)
|
||||
return false;
|
||||
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, is_it_good, LOCAL_E);
|
||||
// Slow aim
|
||||
if (slow_aim)
|
||||
DoSlowAim(angles);
|
||||
@ -1156,16 +1287,13 @@ Vector PredictEntity(CachedEntity *entity)
|
||||
// Buildings
|
||||
case ENTITY_BUILDING:
|
||||
{
|
||||
if (projectileAimbotRequired)
|
||||
if (cur_proj_grav != 0)
|
||||
{
|
||||
std::pair<Vector, Vector> tmp_result;
|
||||
tmp_result = BuildingPrediction(entity, GetBuildingPosition(entity), cur_proj_speed, cur_proj_grav, cur_proj_start_vel);
|
||||
result = tmp_result.second; // Buildings don't have velocity but I'll keep it in nonetheless
|
||||
std::pair<Vector, Vector> temp_result = BuildingPrediction(entity, GetBuildingPosition(entity), cur_proj_speed, cur_proj_grav, cur_proj_start_vel);
|
||||
result = temp_result.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GetBuildingPosition(entity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// NPCs (Skeletons, merasmus, etc)
|
||||
@ -1308,6 +1436,7 @@ int BestHitbox(CachedEntity *target)
|
||||
// Hitbox machine :b:roke
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Function to find the closesnt hitbox to the crosshair for a given ent
|
||||
int ClosestHitbox(CachedEntity *target)
|
||||
{
|
||||
|
@ -651,6 +651,18 @@ powerup_type GetPowerupOnPlayer(CachedEntity *player)
|
||||
return powerup_type::supernova;
|
||||
return powerup_type::not_powerup;
|
||||
}
|
||||
bool didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity, int projectile_size)
|
||||
{
|
||||
|
||||
trace::filter_default.SetSelf(RAW_ENT(g_pLocalPlayer->entity));
|
||||
Ray_t ray;
|
||||
trace_t trace_obj;
|
||||
trace_t *tracer = &trace_obj;
|
||||
ray.Init(start_point, end_point, Vector(0, -projectile_size, -projectile_size), Vector(0, projectile_size, projectile_size));
|
||||
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, tracer);
|
||||
return (((IClientEntity *) tracer->m_pEnt) == RAW_ENT(entity) || !tracer->DidHit());
|
||||
}
|
||||
|
||||
// A function to find a weapon by WeaponID
|
||||
int getWeaponByID(CachedEntity *player, int weaponid)
|
||||
{
|
||||
@ -1017,7 +1029,7 @@ std::mutex trace_lock;
|
||||
bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos, bool use_weapon_offset, unsigned int mask, trace_t *trace)
|
||||
{
|
||||
trace_t trace_object;
|
||||
|
||||
|
||||
if (!trace)
|
||||
trace = &trace_object;
|
||||
Ray_t ray;
|
||||
@ -1035,6 +1047,7 @@ bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos, bool use_weapon_
|
||||
if (!tcm || g_Settings.is_create_move)
|
||||
g_ITrace->TraceRay(ray, mask, &trace::filter_default, trace);
|
||||
}
|
||||
|
||||
return (((IClientEntity *) trace->m_pEnt) == RAW_ENT(entity) || !trace->DidHit());
|
||||
}
|
||||
|
||||
|
@ -501,7 +501,6 @@ Vector EnginePrediction(CachedEntity *entity, float time, Vector *vecVelocity)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb, float speed, float gravity, float entgmod, float proj_startvelocity)
|
||||
{
|
||||
Vector origin = ent->m_vecOrigin();
|
||||
@ -514,24 +513,22 @@ std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb,
|
||||
if (!sv_gravity)
|
||||
sv_gravity = g_ICvar->FindVar("sv_gravity");
|
||||
|
||||
if (speed == 0.0f || !sv_gravity)
|
||||
if (speed == 0.0f || !sv_gravity)
|
||||
return { Vector(), Vector() };
|
||||
|
||||
|
||||
float currenttime = g_pLocalPlayer->v_Eye.DistTo(hitbox) / speed - 1.5f;
|
||||
if (currenttime <= 0.0f)
|
||||
if (currenttime <= 0.0f)
|
||||
currenttime = 0.01f;
|
||||
|
||||
|
||||
float besttime = currenttime;
|
||||
float mindelta = 65536.0f;
|
||||
float no_regression = 66534.0f;
|
||||
Vector bestpos = origin;
|
||||
Vector current = origin;
|
||||
Vector current_velocity = velocity;
|
||||
int maxsteps = (int) debug_pp_steps;
|
||||
float steplength = g_GlobalVars->interval_per_tick;
|
||||
|
||||
Vector ent_mins = RAW_ENT(ent)->GetCollideable()->OBBMins();
|
||||
Vector ent_maxs = RAW_ENT(ent)->GetCollideable()->OBBMaxs();
|
||||
|
||||
bool has_run_before = false;
|
||||
for (int steps = 0; steps < maxsteps; steps++, currenttime += steplength)
|
||||
{
|
||||
ent->m_vecOrigin() = current;
|
||||
@ -553,6 +550,10 @@ std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb,
|
||||
bestpos = current;
|
||||
mindelta = timedelta;
|
||||
}
|
||||
else if (mindelta < no_regression)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// logging::Info("besttime: %f, currenttime: %f, old currenttime: %f", besttime, currenttime, currenttime - steplength * maxsteps);
|
||||
const_cast<Vector &>(RAW_ENT(ent)->GetAbsOrigin()) = origin;
|
||||
@ -568,32 +569,6 @@ std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb,
|
||||
result.y - origin.y, result.z - origin.z);*/
|
||||
return { result, result_initialvel };
|
||||
}
|
||||
std::pair<Vector, Vector> BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity)
|
||||
{
|
||||
if (!vec.z || CE_BAD(building))
|
||||
return { Vector(), Vector() };
|
||||
Vector result = vec;
|
||||
|
||||
if (!sv_gravity)
|
||||
sv_gravity = g_ICvar->FindVar("sv_gravity");
|
||||
|
||||
if (speed == 0.0f || !sv_gravity)
|
||||
return { Vector(), Vector() };
|
||||
|
||||
trace::filter_no_player.SetSelf(RAW_ENT(building));
|
||||
|
||||
// Buildings do not move. We don't need to do any steps here
|
||||
float time = g_pLocalPlayer->v_Eye.DistTo(result) / speed;
|
||||
// Compensate for ping
|
||||
time += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING) + cl_interp->GetFloat();
|
||||
|
||||
result.z += (sv_gravity->GetFloat() / 2.0f * time * time * gravity);
|
||||
Vector result_initialvel = result;
|
||||
result_initialvel.z -= proj_startvelocity * time;
|
||||
// S = at^2/2 ; t = sqrt(2S/a)*/
|
||||
return { result, result_initialvel };
|
||||
}
|
||||
|
||||
std::pair<Vector, Vector> ProjectilePrediction(CachedEntity *ent, int hb, float speed, float gravitymod, float entgmod, float proj_startvelocity)
|
||||
{
|
||||
Vector origin = ent->m_vecOrigin();
|
||||
@ -677,6 +652,32 @@ float DistanceToGround(CachedEntity *ent)
|
||||
return DistanceToGround(origin, mins, maxs);
|
||||
}
|
||||
|
||||
std::pair<Vector, Vector> BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity)
|
||||
{
|
||||
if (!vec.z || CE_BAD(building))
|
||||
return { Vector(), Vector() };
|
||||
Vector result = vec;
|
||||
|
||||
if (!sv_gravity)
|
||||
sv_gravity = g_ICvar->FindVar("sv_gravity");
|
||||
|
||||
if (speed == 0.0f || !sv_gravity)
|
||||
return { Vector(), Vector() };
|
||||
|
||||
trace::filter_no_player.SetSelf(RAW_ENT(building));
|
||||
|
||||
// Buildings do not move. We don't need to do any steps here
|
||||
float time = g_pLocalPlayer->v_Eye.DistTo(result) / speed;
|
||||
// Compensate for ping
|
||||
time += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING) + cl_interp->GetFloat();
|
||||
|
||||
result.z += (sv_gravity->GetFloat() / 2.0f * time * time * gravity);
|
||||
Vector result_initialvel = result;
|
||||
result_initialvel.z -= proj_startvelocity * time;
|
||||
// S = at^2/2 ; t = sqrt(2S/a)*/
|
||||
return { result, result_initialvel };
|
||||
}
|
||||
|
||||
float DistanceToGround(Vector origin, Vector mins, Vector maxs)
|
||||
{
|
||||
// First, ensure we're not slightly below the floor, up to 18 HU will snap up
|
||||
|
Reference in New Issue
Block a user