Трахов
-
Автор темы
- #1
хз кому надо но вот.
TraceToExit перепастил с какого-то сурса, не помню откуда.
От говна по типу TraceLine и ClipTraceToPlayer чистите сами так как делал на скорую руку и перепривязывать не хотел.
Автоволл хороший но фпса с ним как у курицы (скорее всего из-за гипер скана) да и есть некоторые баги по неизвестным причинам.
TraceToExit перепастил с какого-то сурса, не помню откуда.
От говна по типу TraceLine и ClipTraceToPlayer чистите сами так как делал на скорую руку и перепривязывать не хотел.
Автоволл хороший но фпса с ним как у курицы (скорее всего из-за гипер скана) да и есть некоторые баги по неизвестным причинам.
cpp:
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
#include "autowall.h"
bool autowall::is_breakable_entity(IClientEntity* e)
{
if (!e || !e->EntIndex())
return false;
static auto is_breakable = util::FindSignature(crypt_str("client.dll"), crypt_str("55 8B EC 51 56 8B F1 85 F6 74 68"));
auto take_damage = *(uintptr_t*)((uintptr_t)is_breakable + 0x26);
auto backup = *(uint8_t*)((uintptr_t)e + take_damage);
auto client_class = e->GetClientClass();
auto network_name = client_class->m_pNetworkName;
if (!strcmp(network_name, "CBreakableSurface"))
*(uint8_t*)((uintptr_t)e + take_damage) = DAMAGE_YES;
else if (!strcmp(network_name, "CBaseDoor") || !strcmp(network_name, "CDynamicProp"))
*(uint8_t*)((uintptr_t)e + take_damage) = DAMAGE_NO;
using Fn = bool(__thiscall*)(IClientEntity*);
auto result = ((Fn)is_breakable)(e);
*(uint8_t*)((uintptr_t)e + take_damage) = backup;
return result;
}
void autowall::TraceLine(Vector& absStart, const Vector& absEnd, unsigned int mask, player_t* ignore, CGameTrace* ptr)
{
Ray_t ray;
ray.Init(absStart, absEnd);
CTraceFilter filter;
filter.pSkip = ignore;
m_trace()->TraceRay(ray, mask, &filter, ptr);
}
void autowall::ScaleDamage(CGameTrace& enterTrace, weapon_info_t* weaponData, float& currentDamage)
{
if (!enterTrace.hit_entity || !enterTrace.hit_entity->GetClientClass() || !g_ctx.local()->m_hActiveWeapon() || enterTrace.hit_entity->GetClientClass()->m_ClassID != CCSPlayer)
return;
player_t* target = (player_t*)enterTrace.hit_entity;
auto new_damage = currentDamage;
const int hitgroup = enterTrace.hitgroup;
const auto is_zeus = g_ctx.local()->m_hActiveWeapon()->m_iItemDefinitionIndex() == WEAPON_TASER;
static auto is_armored = [](player_t* player, int armor, int hitgroup) {
if (player && player->m_ArmorValue() > 0)
{
if (player->m_bHasHelmet() && hitgroup == HITGROUP_HEAD || (hitgroup >= HITGROUP_CHEST && hitgroup <= HITGROUP_RIGHTARM))
return true;
}
return false;
};
if (!is_zeus) {
switch (hitgroup)
{
case HITGROUP_HEAD:
new_damage *= 4.f;
break;
case HITGROUP_STOMACH:
new_damage *= 1.25f;
break;
case HITGROUP_LEFTLEG:
case HITGROUP_RIGHTLEG:
new_damage *= .75f;
break;
default:
break;
/*4.0; 1
1.0; 2
1.25; 3
1.0; 4
1.0; 5
0.75; 6
0.75; 7
1.0; 8*/
}
}
else
new_damage *= 0.92f;
if (is_armored(target, target->m_ArmorValue(), hitgroup))
{
float flHeavyRatio = 1.0f;
float flBonusRatio = 0.5f;
float flRatio = weaponData->flArmorRatio * 0.5f;
float flNewDamage;
if (!target->m_bHasHeavyArmor())
{
flNewDamage = new_damage * flRatio;
}
else
{
flBonusRatio = 0.33f;
flRatio = weaponData->flArmorRatio * 0.5f;
flHeavyRatio = 0.33f;
flNewDamage = (new_damage * (flRatio * 0.5)) * 0.85f;
}
int iArmor = target->m_ArmorValue();
if (((new_damage - flNewDamage) * (flBonusRatio * flHeavyRatio)) > iArmor)
flNewDamage = new_damage - (iArmor / flBonusRatio);
new_damage = flNewDamage;
}
currentDamage = new_damage;
}
bool DidHitWorld(IClientEntity* m_pEnt)
{
return m_pEnt == m_entitylist()->GetClientEntity(0);
}
bool DidHitNonWorldEntity(IClientEntity* m_pEnt)
{
return m_pEnt != NULL && DidHitWorld(m_pEnt);
}
bool autowall::TraceToExit(Vector& start, Vector dir, Vector& end, CGameTrace& enter_trace, CGameTrace& exit_trace)
{
float flDistance = 0;
int nStartContents = 0;
while (flDistance <= 90.f)
{
flDistance += 4.0f;
end = start + (flDistance * dir);
Vector vecTrEnd = end - (4.0f * dir);
if (nStartContents == 0)
nStartContents = m_trace()->GetPointContents_WorldOnly(end, MASK_SHOT_HULL | CONTENTS_HITBOX);
int nCurrentContents = m_trace()->GetPointContents_WorldOnly(end, MASK_SHOT_HULL | CONTENTS_HITBOX);
if ((nCurrentContents & MASK_SHOT_HULL) == 0 || ((nCurrentContents & CONTENTS_HITBOX) && nStartContents != nCurrentContents))
{
// this gets a bit more complicated and expensive when we have to deal with displacements
util::trace_line(end, vecTrEnd, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr, &exit_trace);
// we exited the wall into a player's hitbox
if (exit_trace.startsolid == true && (exit_trace.surface.flags & SURF_HITBOX)/*( nStartContents & CONTENTS_HITBOX ) == 0 && (nCurrentContents & CONTENTS_HITBOX)*/)
{
CTraceFilter filter;
filter.pSkip = exit_trace.hit_entity;
// do another trace, but skip the player to get the actual exit surface
util::trace_line(end, start, MASK_SHOT_HULL, &filter, &exit_trace);
if (exit_trace.DidHit() && exit_trace.startsolid == false)
{
end = exit_trace.endpos;
return true;
}
}
else if (exit_trace.DidHit() && exit_trace.startsolid == false)
{
bool bStartIsNodraw = !!(enter_trace.surface.flags & (SURF_NODRAW));
bool bExitIsNodraw = !!(exit_trace.surface.flags & (SURF_NODRAW));
if (bExitIsNodraw && is_breakable_entity(exit_trace.hit_entity) && is_breakable_entity(enter_trace.hit_entity))
{
// we have a case where we have a breakable object, but the mapper put a nodraw on the backside
end = exit_trace.endpos;
return true;
}
else if (bExitIsNodraw == false || (bStartIsNodraw && bExitIsNodraw)) // exit nodraw is only valid if our entrace is also nodraw
{
Vector vecNormal = exit_trace.plane.normal;
float flDot = dir.Dot(vecNormal);
if (flDot <= 1.0f)
{
// get the real end pos
end = end - ((4.f * exit_trace.fraction) * dir);
return true;
}
}
}
else if (DidHitNonWorldEntity(enter_trace.hit_entity) && is_breakable_entity(enter_trace.hit_entity))
{
// if we hit a breakable, make the assumption that we broke it if we can't find an exit (hopefully..)
// fake the end pos
exit_trace = enter_trace;
exit_trace.endpos = start + (1.0f * dir);
return true;
}
}
}
return false;
}
bool autowall::HandleBulletPenetration(player_t* ignore, weapon_info_t* weaponData, CGameTrace& enterTrace, Vector& eyePosition, Vector direction, int& possibleHitsRemaining, float& currentDamage, float penetrationPower, float ff_damage_bullet_penetration, bool pskip)
{
static ConVar* ff_damage_reduction_bullets = m_cvar()->FindVar(crypt_str("ff_damage_reduction_bullets"));
if (possibleHitsRemaining <= 0 || weaponData->flPenetration <= 0 || currentDamage < 1) {
return false;
}
CGameTrace exitTrace;
auto* pEnemy = (player_t*)enterTrace.hit_entity;
auto* const enterSurfaceData = m_physsurface()->GetSurfaceData(enterTrace.surface.surfaceProps);
const int enter_material = enterSurfaceData->game.material;
if (!enterSurfaceData || enterSurfaceData->game.flPenetrationModifier <= 0)
return false;
const auto enter_penetration_modifier = enterSurfaceData->game.flPenetrationModifier;
//float enterDamageModifier = enterSurfaceData->game.damagemodifier;// , modifier, finalDamageModifier, combinedPenetrationModifier;
const bool isSolidSurf = (enterTrace.contents & CONTENTS_GRATE);
const bool isLightSurf = (enterTrace.surface.flags & SURF_NODRAW);
if ((possibleHitsRemaining <= 0 && !isLightSurf && !isSolidSurf && enter_material != CHAR_TEX_GRATE && enter_material != CHAR_TEX_GLASS)
|| penetrationPower <= 0)
return false;
Vector end;
if (!TraceToExit(enterTrace.endpos, direction, end, enterTrace, exitTrace))
{
if (!(m_trace()->GetPointContents(end, 0x600400B) & 0x600400B))
return false;
}
auto* const exitSurfaceData = m_physsurface()->GetSurfaceData(exitTrace.surface.surfaceProps);
const int exitMaterial = exitSurfaceData->game.material;
const float exitSurfPenetrationModifier = exitSurfaceData->game.flPenetrationModifier;
//float exitDamageModifier = exitSurfaceData->game.damagemodifier;
float combined_damage_modifier = 0.16f;
float combined_penetration_modifier;
//Are we using the newer penetration system?
if (enter_material == CHAR_TEX_GLASS || enter_material == CHAR_TEX_GRATE) {
combined_damage_modifier = 0.05f;
combined_penetration_modifier = 3;
}
else if (isSolidSurf || isLightSurf) {
combined_damage_modifier = 0.16f;
combined_penetration_modifier = 1;
}
else if (enter_material == CHAR_TEX_FLESH && ff_damage_reduction_bullets->GetFloat() == 0 && pEnemy != nullptr && pEnemy->is_player() && pEnemy->m_iTeamNum() == g_ctx.local()->m_iTeamNum())
{
if (ff_damage_bullet_penetration == 0)
{
// don't allow penetrating players when FF is off
combined_penetration_modifier = 0;
return false;
}
combined_penetration_modifier = ff_damage_bullet_penetration;
}
else {
combined_penetration_modifier = (enter_penetration_modifier + exitSurfPenetrationModifier) / 2;
}
if (enter_material == exitMaterial) {
if (exitMaterial == CHAR_TEX_WOOD || exitMaterial == CHAR_TEX_CARDBOARD)
combined_penetration_modifier = 3;
else if (exitMaterial == CHAR_TEX_PLASTIC)
combined_penetration_modifier = 2;
}
auto penetration_mod = fmaxf(0.f, (3.f / penetrationPower) * 1.25f);
float modifier = fmaxf(0, 1.0f / combined_penetration_modifier);
auto thickness = (exitTrace.endpos - enterTrace.endpos).Length();
const auto lost_damage = ((modifier * 3.f) * penetration_mod + (currentDamage * combined_damage_modifier)) + (((thickness * thickness) * modifier) / 24.f);
currentDamage -= std::fmaxf(0.f, lost_damage);
if (currentDamage < 1.f)
return false;
eyePosition = exitTrace.endpos;
--possibleHitsRemaining;
return true;
}
void autowall::FixTraceRay(Vector end, Vector start, CGameTrace* oldtrace, player_t* ent)
{
if (!ent)
return;
const auto mins = ent->m_vecMins();
const auto maxs = ent->m_vecMaxs();
auto dir(end - start);
auto len = dir.Normalize();
const auto center = (mins + maxs) / 2;
const auto pos(ent->m_vecOrigin() + center);
auto to = pos - start;
const float range_along = dir.Dot(to);
float range;
if (range_along < 0.f) {
range = -(to).Length();
}
else if (range_along > len) {
range = -(pos - end).Length();
}
else {
auto ray(pos - (start + (dir * range_along)));
range = ray.Length();
}
if (range <= 60.f) {
Ray_t ray;
ray.Init(start, end);
trace_t trace;
m_trace()->ClipRayToEntity(ray, 0x4600400B, ent, &trace);
if (oldtrace->fraction > trace.fraction)
*oldtrace = trace;
}
}
void autowall::ClipTraceToPlayers(const Vector& start, const Vector& end, uint32_t mask, ITraceFilter* filter, CGameTrace* tr) {
Vector pos, to, dir, on_ray;
float len, range_along, range;
//CGameTrace new_trace;
float smallestFraction = tr->fraction;
constexpr float maxRange = 60.0f;
//Vector delta(vecAbsEnd - vecAbsStart);
//const float delta_length = delta.Normalize();
dir = start - end;
len = dir.Normalize();
Ray_t ray;
ray.Init(start, end);
for (int i = 1; i <= 64; ++i) {
player_t* ent = (player_t*)m_entitylist()->GetClientEntity(i);
if (!ent || ent->IsDormant() || ent->is_alive())
continue;
if (filter && !filter->ShouldHitEntity(ent, mask))
continue;
// set some local vars.
pos = ent->m_vecOrigin() + ((ent->m_vecMins() + ent->m_vecMaxs()) * 0.5f);
to = pos - start;
range_along = dir.Dot(to);
// off start point.
if (range_along < 0.f)
range = -(to).Length();
// off end point.
else if (range_along > len)
range = -(pos - end).Length();
// within ray bounds.
else {
on_ray = start + (dir * range_along);
range = (pos - on_ray).Length();
}
if (/*range > 0.0f && */range <= maxRange) {
trace_t playerTrace;
//ray.Init(start, end);
m_trace()->ClipRayToEntity(ray, 0x4600400B, ent, &playerTrace);
if (playerTrace.fraction < smallestFraction) {
// we shortened the ray - save off the trace
*tr = playerTrace;
smallestFraction = playerTrace.fraction;
}
}
}
}
bool autowall::FireBullet(Vector eyepos, weapon_t* pWeapon, Vector& direction, float& currentDamage, player_t* ignore, player_t* to_who, int hitbox, bool* was_viable, std::vector<float>* power)
{
if (!pWeapon || !ignore)
return false;
// Current bullet travel Power to penetrate Distance to penetrate Range Player bullet reduction convars Amount to extend ray by
float currentDistance = 0;
static ConVar* damageBulletPenetration = m_cvar()->FindVar(crypt_str("ff_damage_bullet_penetration"));
const float ff_damage_bullet_penetration = damageBulletPenetration->GetFloat();
weapon_info_t* weaponData = g_ctx.globals.weapon->get_csweapon_info();
CGameTrace enterTrace;
CTraceFilter filter;
filter.pSkip = ignore;
if (!weaponData)
return false;
//Set our current damage to what our gun's initial damage reports it will do
currentDamage = float(weaponData->iDamage);
auto maxRange = weaponData->flRange;
auto penetrationDistance = weaponData->flRange;
auto penetrationPower = weaponData->flPenetration;
auto RangeModifier = weaponData->flRangeModifier;
auto possibleHitsRemaining = 4;
//This gets set in FX_Firebullets to 4 as a pass-through value.
//CS:GO has a maximum of 4 surfaces a bullet can pass-through before it 100% stops.
//Excerpt from Valve: https://steamcommunity.com/sharedfiles/filedetails/?id=275573090
//"The total number of surfaces any bullet can penetrate in a single flight is capped at 4." -CS:GO Official
if (power)
{
maxRange = power->at(0);
penetrationDistance = power->at(1);
penetrationPower = power->at(2);
currentDamage = power->at(3);
RangeModifier = power->at(4);
}
int penetrated = 0;
//If our damage is greater than (or equal to) 1, and we can shoot, let's shoot.
while (/*ctx.last_penetrated_count >= 0 &&*/currentDamage > 0)
{
//Calculate max bullet range
//Create endpoint of bullet
Vector end = eyepos + direction * (maxRange - currentDistance);
util::trace_line(eyepos, end, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &enterTrace);
//utilTraceLine(eyepos, end, 0x4600400B/*_HULL | CONTENTS_HITBOX*/, ignore, &enterTrace);
if (to_who || enterTrace.contents & CONTENTS_HITBOX && enterTrace.hit_entity) {
FixTraceRay(eyepos + (direction * 40.f), eyepos, &enterTrace, (to_who != nullptr ? to_who : (player_t*)enterTrace.hit_entity));
}
else
ClipTraceToPlayers(eyepos, eyepos + (direction * 40.f), 0x4600400B, &filter, &enterTrace);
if (enterTrace.fraction == 1.0f)
return false;
//We have to do this *after* tracing to the player.
//int enterMaterial = enterSurfaceData->game.material;
//calculate the damage based on the distance the bullet traveled.
currentDistance += enterTrace.fraction * (maxRange - currentDistance);
//Let's make our damage drops off the further away the bullet is.
currentDamage *= powf(RangeModifier, (currentDistance / 500));
if (!(enterTrace.contents & CONTENTS_HITBOX))
enterTrace.hitgroup = 1;
//This looks gay as fuck if we put it into 1 long line of code.
const bool canDoDamage = enterTrace.hitgroup > 0 && enterTrace.hitgroup <= 8 || enterTrace.hitgroup == HITGROUP_GEAR;
const bool isPlayer = enterTrace.hit_entity != nullptr
&& enterTrace.hit_entity->GetClientClass()
&& enterTrace.hit_entity->GetClientClass()->m_ClassID == CCSPlayer
&& (!g_ctx.local() || g_ctx.local()->is_alive() || ((player_t*)enterTrace.hit_entity)->m_iTeamNum() != g_ctx.local()->m_iTeamNum());
if (to_who)
{
if (enterTrace.hit_entity && to_who == enterTrace.hit_entity && canDoDamage && isPlayer) {
ScaleDamage(enterTrace, weaponData, currentDamage);
if (was_viable != nullptr)
*was_viable = (penetrated == 0);
return true;
}
}
else
{
if (enterTrace.hit_entity && canDoDamage && isPlayer) {
ScaleDamage(enterTrace, weaponData, currentDamage);
if (was_viable != nullptr)
*was_viable = (penetrated == 0);
return true;
}
}
//Sanity checking / Can we actually shoot through?
if (currentDistance > maxRange && penetrationPower
|| m_physsurface()->GetSurfaceData(enterTrace.surface.surfaceProps)->game.flPenetrationModifier < 0.1f) {
return false;//ctx.last_penetrated_count = 0;
}
const auto prev = possibleHitsRemaining;
//Calling HandleBulletPenetration here reduces our penetrationCounter, and if it returns true, we can't shoot through it.
if (!HandleBulletPenetration(ignore, weaponData, enterTrace, eyepos, direction, possibleHitsRemaining, currentDamage, penetrationPower, ff_damage_bullet_penetration)) {
break;
}
if (prev != possibleHitsRemaining)
penetrated++;
}
return false;
}
////////////////////////////////////// Usage Calls //////////////////////////////////////
float autowall::CanHit(Vector& vecEyePos, Vector& point)
{
g_ctx.globals.autowalling = true;
Vector angles, direction;
Vector tmp = point - vecEyePos;
float currentDamage = 0;
math::vector_angles(tmp, angles);
math::angle_vectors(angles, direction);
direction.Normalize();
auto weapon = g_ctx.local()->m_hActiveWeapon().Get();
if (weapon != nullptr && !weapon->is_non_aim() && FireBullet(vecEyePos, weapon, direction, currentDamage, g_ctx.local()))
{
g_ctx.globals.autowalling = false;
return currentDamage;
}
return -1; //That wall is just a bit too thick buddy
}
float autowall::CanHit(const Vector& vecEyePos, Vector& point, player_t* ignore_ent, player_t* to_who, int hitbox, bool* was_viable)
{
if (ignore_ent == nullptr || to_who == nullptr)
return 0;
g_ctx.globals.autowalling = true;
Vector direction;
Vector tmp = point - vecEyePos;
float currentDamage = 0;
direction = tmp.Normalized();
auto weapon = g_ctx.local()->m_hActiveWeapon().Get();
if (weapon != nullptr)
{
if (!weapon->is_non_aim() && FireBullet(vecEyePos, weapon, direction, currentDamage, ignore_ent, to_who, hitbox, was_viable))
{
g_ctx.globals.autowalling = false;
return currentDamage;
}
else
{
g_ctx.globals.autowalling = false;
return -1;
}
}
return -1;
}
float autowall::SimulateShot(Vector& vecEyePos, Vector& point, player_t* ignore_ent, player_t* to_who, bool* was_viable)
{
if (ignore_ent == nullptr || to_who == nullptr)
return 0;
g_ctx.globals.autowalling = true;
Vector angles, direction;
const Vector tmp(point - vecEyePos);
float currentDamage = 0.f;
math::vector_angles(tmp, angles);
math::angle_vectors(angles, direction);
direction.Normalize();
auto weapon = g_ctx.local()->m_hActiveWeapon().Get();
static std::vector<float> power = { 4000.f, 4000.f, 2.50f, 80.f, 1.f };
if (weapon != nullptr)
{
if (FireBullet(vecEyePos, weapon, direction, currentDamage, ignore_ent, to_who, -1, was_viable, &power))
{
g_ctx.globals.autowalling = false;
return currentDamage;
}
else
{
g_ctx.globals.autowalling = false;
return -1;
}
}
return -1;
}
hpp:
#pragma once
#include "..\..\includes.hpp"
class weapon_info_t;
class weapon_t;
class autowall : public singleton <autowall>
{
public:
bool is_breakable_entity(IClientEntity* e);
void TraceLine(Vector& absStart, const Vector& absEnd, unsigned int mask, player_t* ignore, CGameTrace* ptr);
void ScaleDamage(CGameTrace& enterTrace, weapon_info_t* weaponData, float& currentDamage);
bool TraceToExit(Vector& start, Vector dir, Vector& end, CGameTrace& enter_trace, CGameTrace& exit_trace);
bool HandleBulletPenetration(player_t* ignore, weapon_info_t* weaponData, CGameTrace& enterTrace, Vector& eyePosition, Vector direction, int& possibleHitsRemaining, float& currentDamage, float penetrationPower, float ff_damage_bullet_penetration, bool pskip = false);
void FixTraceRay(Vector end, Vector start, CGameTrace* oldtrace, player_t* ent);
void ClipTraceToPlayers(const Vector& vecAbsStart, const Vector& vecAbsEnd, uint32_t mask, ITraceFilter* filter, CGameTrace* tr);
bool FireBullet(Vector eyepos, weapon_t* pWeapon, Vector& direction, float& currentDamage, player_t* ignore, player_t* to_who = nullptr, int hitbox = -1, bool* was_viable = nullptr, std::vector<float>* = nullptr);
float CanHit(Vector& vecEyePos, Vector& point);
float CanHit(const Vector& vecEyePos, Vector& point, player_t* ignore_ent, player_t* start_ent, int hitbox, bool* was_viable = nullptr);
float SimulateShot(Vector& vecEyePos, Vector& point, player_t* ignore_ent, player_t* to_who, bool* was_viable = nullptr);
};
if (auto fire_data = autowall::get().CanHit(shoot_position, point.point, g_ctx.local(), record->player, point.hitbox, &was_viable); fire_data > 0)
bool was_viable вместо fire_data.visible
bool was_viable вместо fire_data.visible
Последнее редактирование: