mirror of
https://github.com/MathiasLui/CSGO-Projects.git
synced 2025-05-06 13:51:18 +00:00
Fix bomb damage radius
* Change version to 1.3.0.3 * Fix bomb radius not accurate by using a box * When creating a point somewhere we now store its in-game coordinates for the bomb intersection test * SpatialPartitioningHelper.cs is not yet used, except for the BoxIntersects-Method *
This commit is contained in:
parent
4fe796769e
commit
3e94f4c622
4 changed files with 231 additions and 6 deletions
|
@ -11,8 +11,8 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>27.ico</ApplicationIcon>
|
||||
<FileVersion>1.3.0.1</FileVersion>
|
||||
<AssemblyVersion>1.3.0.1</AssemblyVersion>
|
||||
<FileVersion>1.3.0.3</FileVersion>
|
||||
<AssemblyVersion>1.3.0.3</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -32,6 +32,12 @@ namespace Damage_Calculator
|
|||
|
||||
private readonly string placeholderText = "None";
|
||||
|
||||
private static readonly double eyeLevelStanding = 64.093811;
|
||||
private static readonly double eyeLevelCrouching = 46.076218;
|
||||
private static readonly int heightStanding = 72;
|
||||
private static readonly int heightCrouching = 54;
|
||||
private static readonly int playerWidth = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Holds current in-game mouse coordinates when hovering over the map
|
||||
/// </summary>
|
||||
|
@ -1026,6 +1032,7 @@ namespace Damage_Calculator
|
|||
// left and right point for the X and Y coordinates (in pixels) so we gotta convert those
|
||||
Point[] points = this.connectingLine.Tag as Point[];
|
||||
|
||||
// These are not in-game coordinates yet, but the offset from the top left -- but in units instead of pixels
|
||||
double leftX = this.getUnitsFromPixels(points[0].X);
|
||||
double leftY = this.getUnitsFromPixels(points[0].Y);
|
||||
double leftZ;
|
||||
|
@ -1034,10 +1041,29 @@ namespace Damage_Calculator
|
|||
double rightY = this.getUnitsFromPixels(points[1].Y);
|
||||
double rightZ;
|
||||
|
||||
// Make the left and right point in-game coordinates accessible to everyone outside this function
|
||||
Point playerCoords = this.getGameCoordsFromPoint(points[1].X, points[1].Y);
|
||||
this.playerPoint.X = playerCoords.X;
|
||||
this.playerPoint.Y = playerCoords.Y;
|
||||
|
||||
Point targetOrBombCoords = this.getGameCoordsFromPoint(points[0].X, points[0].Y);
|
||||
if (this.bombPoint != null)
|
||||
{
|
||||
this.bombPoint.X = targetOrBombCoords.X;
|
||||
this.bombPoint.Y = targetOrBombCoords.Y;
|
||||
}
|
||||
if(this.targetPoint != null)
|
||||
{
|
||||
this.targetPoint.X = targetOrBombCoords.X;
|
||||
this.targetPoint.Y = targetOrBombCoords.Y;
|
||||
}
|
||||
|
||||
// Manage height
|
||||
if (this.playerPoint.AssociatedAreaID < 0 ||
|
||||
((this.DrawMode == eDrawMode.Shooting && this.targetPoint.AssociatedAreaID < 0)
|
||||
|| (this.DrawMode == eDrawMode.Bomb && this.bombPoint.AssociatedAreaID < 0)))
|
||||
{
|
||||
// One of the points has no area ID, and thus no Z coordinate
|
||||
leftZ = 0;
|
||||
rightZ = 0;
|
||||
}
|
||||
|
@ -1051,13 +1077,14 @@ namespace Damage_Calculator
|
|||
double diffPixels2D = Math.Sqrt(Math.Pow(leftX - rightX, 2) + Math.Pow(leftY - rightY, 2));
|
||||
double unitsDifference2D = this.getUnitsFromPixels(diffPixels2D);
|
||||
|
||||
|
||||
if (this.DrawMode == eDrawMode.Bomb)
|
||||
{
|
||||
// Add the appropriate eye level
|
||||
if (radioPlayerStanding.IsChecked == true)
|
||||
rightZ += 64.093811;
|
||||
rightZ += eyeLevelStanding;
|
||||
else if(radioPlayerCrouched.IsChecked == true)
|
||||
rightZ += 46.076218;
|
||||
rightZ += eyeLevelCrouching;
|
||||
}
|
||||
|
||||
// Add Z height to calculation, unless a point has no area ID associated, then it stays 2D
|
||||
|
@ -1172,11 +1199,46 @@ namespace Damage_Calculator
|
|||
|
||||
private void calculateAndUpdateBombDamage()
|
||||
{
|
||||
// This is the maximum damage, and the height of the bell curve
|
||||
double flDamage = this.loadedMap.BombDamage; // 500 is hard-coded as the default, and also the default in the hammer editor, can be overridden as a map creator
|
||||
double flBombRadius = flDamage * 3.5d;
|
||||
|
||||
// First we need to check if the player is within the bomb radius, this isn't done with a circle, but with a box that has a side length of 2r
|
||||
// So basically it's the bounding box, so if you're not directly above, below, left or right of the bomb, the radius increases a bit
|
||||
// Also its calculated via the bounding box of the player which is 32x32 units in the horizontal axes
|
||||
|
||||
// Get mins and maxs of player hitbox
|
||||
|
||||
// Mins is X - 16, Y - 16, Z
|
||||
Vector3 playerMins = new Vector3 { X = (float)(this.playerPoint.X - (playerWidth / 2d)), Y = (float)(this.playerPoint.Y - (playerWidth / 2d)), Z = (float)this.playerPoint.Z };
|
||||
|
||||
// Head height is not eye level, crouching is smaller, otherwise use standing height
|
||||
float headHeight = (float)(this.radioPlayerCrouched.IsChecked == true ? heightCrouching : heightStanding);
|
||||
|
||||
// Maxs is X + 16, Y + 16, Z + head height
|
||||
Vector3 playerMaxs = new Vector3 { X = (float)(this.playerPoint.X + (playerWidth / 2d)), Y = (float)(this.playerPoint.Y + (playerWidth / 2d)), Z = (float)this.playerPoint.Z + headHeight };
|
||||
|
||||
// Get mins and maxs of bomb radius
|
||||
Vector3 bombMins = new Vector3 { X = (float)(this.bombPoint.X - flBombRadius), Y = (float)(this.bombPoint.Y - flBombRadius), Z = (float)(this.bombPoint.Z - flBombRadius) };
|
||||
|
||||
Vector3 bombMaxs = new Vector3 { X = (float)(this.bombPoint.X + flBombRadius), Y = (float)(this.bombPoint.Y + flBombRadius), Z = (float)(this.bombPoint.Z + flBombRadius) };
|
||||
|
||||
// Check if the two boxes intersect
|
||||
bool playerIsInRange = SpatialPartitioningHelper.BoxIntersects(bombMins, bombMaxs, playerMins, playerMaxs);
|
||||
|
||||
if (!playerIsInRange)
|
||||
{
|
||||
txtResult.Text = txtResultArmor.Text = "0";
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we can calculate the damage...
|
||||
|
||||
const double damagePercentage = 1.0d;
|
||||
|
||||
double flDamage = this.loadedMap.BombDamage; // 500 - default, if radius is not written on the map https://i.imgur.com/mUSaTHj.png
|
||||
double flBombRadius = flDamage * 3.5d;
|
||||
// From player origin + eye level, to the bomb
|
||||
double flDistanceToLocalPlayer = (double)this.unitsDistance;// ((c4bomb origin + viewoffset) - (localplayer origin + viewoffset))
|
||||
// This defines the width of the curve, a smaller value gives a steeper curve and a faster falloff
|
||||
double fSigma = flBombRadius / 3.0d;
|
||||
double fGaussianFalloff = Math.Exp(-flDistanceToLocalPlayer * flDistanceToLocalPlayer / (2.0d * fSigma * fSigma));
|
||||
double flAdjustedDamage = flDamage * fGaussianFalloff * damagePercentage;
|
||||
|
|
150
DamageCalculator/DamageCalculator/SpatialPartitioningHelper.cs
Normal file
150
DamageCalculator/DamageCalculator/SpatialPartitioningHelper.cs
Normal file
|
@ -0,0 +1,150 @@
|
|||
using SteamShared.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.RightsManagement;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Damage_Calculator
|
||||
{
|
||||
internal class Voxel
|
||||
{
|
||||
private uint x;
|
||||
private uint y;
|
||||
private uint z;
|
||||
private uint voxelId;
|
||||
|
||||
public uint X
|
||||
{
|
||||
get => this.x;
|
||||
set
|
||||
{
|
||||
this.x = value & 0x7FF; // Maximum value is 11 bits, make double sure
|
||||
this.updateVoxelId();
|
||||
}
|
||||
}
|
||||
|
||||
public uint Y
|
||||
{
|
||||
get => this.y;
|
||||
set
|
||||
{
|
||||
this.y = value & 0x7FF; // Maximum value is 11 bits, make double sure
|
||||
this.updateVoxelId();
|
||||
}
|
||||
}
|
||||
|
||||
public uint Z
|
||||
{
|
||||
get => this.z;
|
||||
set
|
||||
{
|
||||
this.z = value & 0x3FF; // Maximum value is 10 bits, make double sure
|
||||
this.updateVoxelId();
|
||||
}
|
||||
}
|
||||
|
||||
public uint VoxelId
|
||||
{
|
||||
get => this.voxelId;
|
||||
set
|
||||
{
|
||||
this.voxelId = value;
|
||||
|
||||
// VoxelID consists of X=11, Y=11 and Z=10 bits in little endian like this ZZZZZZZZZZYYYYYYYYYYYXXXXXXXXXXX
|
||||
// so extract them
|
||||
|
||||
// No need to bitshift since it's already on the lowest bit, but & it so that Y and Z are 0
|
||||
this.x = value & 0x7FF;
|
||||
|
||||
// & it to only get the Y value in the middle and then shift it to the rightmost spot
|
||||
this.y = (value & 0x3FF800) >> 11;
|
||||
|
||||
// This has no values higher than it so no & is needed, but shift it to the rightmost spot, the lower values will be discarded anyways
|
||||
this.z = value >> 22;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVoxelId()
|
||||
{
|
||||
this.voxelId = 0;
|
||||
|
||||
this.voxelId |= this.x;
|
||||
|
||||
this.voxelId |= this.y << 11;
|
||||
|
||||
this.voxelId |= this.z << 22;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SpatialPartitioningHelper
|
||||
{
|
||||
const int MAX_COORD_INTEGER = 16384;
|
||||
const int MIN_COORD_INTEGER = -MAX_COORD_INTEGER;
|
||||
const float MAX_COORD_FLOAT = MAX_COORD_INTEGER;
|
||||
const float MIN_COORD_FLOAT = -MAX_COORD_FLOAT;
|
||||
const int COORD_EXTENT = 2 * MAX_COORD_INTEGER;
|
||||
|
||||
const int SPHASH_LEVEL_SKIP = 2;
|
||||
|
||||
const int SPHASH_VOXEL_SIZE = 256; // Must be power of 2
|
||||
const int SPHASH_VOXEL_SHIFT = 8;
|
||||
|
||||
const float SPHASH_EPS = 0.03125f;
|
||||
|
||||
static readonly Vector3 voxelOrigin = new Vector3 { X = MIN_COORD_FLOAT, Y = MIN_COORD_FLOAT, Z = MIN_COORD_FLOAT };
|
||||
|
||||
static int levelShift;
|
||||
static int levelCount;
|
||||
|
||||
static int GetVoxelSize(int level)
|
||||
{
|
||||
return SPHASH_VOXEL_SIZE << (SPHASH_LEVEL_SKIP * level);
|
||||
}
|
||||
|
||||
static void UpdateLevelShift(int level)
|
||||
{
|
||||
levelShift = SPHASH_VOXEL_SHIFT + (SPHASH_LEVEL_SKIP * level);
|
||||
}
|
||||
|
||||
static void UpdateLevelCount()
|
||||
{
|
||||
levelCount = 0;
|
||||
while (ComputeVoxelCountAtLevel(levelCount) > 2)
|
||||
{
|
||||
// From level 0 to 3 it will be 128, 32, 8, 2
|
||||
++levelCount;
|
||||
}
|
||||
|
||||
// And then add one to have the count instead of the maximum level index
|
||||
++levelCount;
|
||||
}
|
||||
|
||||
static int ComputeVoxelCountAtLevel(int level)
|
||||
{
|
||||
int nVoxelCount = COORD_EXTENT >> SPHASH_VOXEL_SHIFT;
|
||||
nVoxelCount >>= (SPHASH_LEVEL_SKIP * level);
|
||||
|
||||
return (nVoxelCount > 0) ? nVoxelCount : 1;
|
||||
}
|
||||
|
||||
static Vector3 VoxelIndexFromPoint(Vector3 worldPoint)
|
||||
{
|
||||
Vector3 voxel = new Vector3();
|
||||
|
||||
voxel.X = (int)(worldPoint.X - voxelOrigin.X) >> levelShift;
|
||||
voxel.Y = (int)(worldPoint.Y - voxelOrigin.Y) >> levelShift;
|
||||
voxel.Z = (int)(worldPoint.Z - voxelOrigin.Z) >> levelShift;
|
||||
|
||||
return voxel;
|
||||
}
|
||||
|
||||
public static bool BoxIntersects(Vector3 boxMins, Vector3 boxMaxs, Vector3 otherMins, Vector3 otherMaxs)
|
||||
{
|
||||
return (otherMins.X <= boxMaxs.X) && (otherMaxs.X >= boxMins.X) &&
|
||||
(otherMins.Y <= boxMaxs.Y) && (otherMaxs.Y >= boxMins.Y) &&
|
||||
(otherMins.Z <= boxMaxs.Z) && (otherMaxs.Z >= boxMins.Z);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,19 @@ namespace SteamShared.Models
|
|||
|
||||
public double PercentageY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The in-game X-coordinate.
|
||||
/// </summary>
|
||||
public double X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The in-game Y-coordinate.
|
||||
/// </summary>
|
||||
public double Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The in-game Z-coordinate.
|
||||
/// </summary>
|
||||
public double Z { get; set; }
|
||||
|
||||
public int AssociatedAreaID { get; set; } = -1;
|
||||
|
|
Loading…
Add table
Reference in a new issue