Skip to content

Commit

Permalink
cs1.4 (#4)
Browse files Browse the repository at this point in the history
* initial sidestream port
* blyatison
  • Loading branch information
RedFoxIV authored Feb 16, 2025
1 parent 4ca353f commit 9bc57d0
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 70 deletions.
54 changes: 52 additions & 2 deletions Content.Client/Weapons/Ranged/Commands/ShowSpreadCommand.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,68 @@
using Content.Client.Weapons.Ranged.Systems;
using Robust.Shared.Console;
using Robust.Shared.Reflection;
using System.Linq;
using static Content.Client.Weapons.Ranged.Systems.GunSystem;

namespace Content.Client.Weapons.Ranged;

public sealed class ShowSpreadCommand : IConsoleCommand
{
public string Command => "showgunspread";
public string Description => $"Shows gun spread overlay for debugging";
// WWDP EDIT START
// I REGRET DOING ENUMS HERE
public string Help => $"{Command} off/partial/full";

readonly Dictionary<string, GunSpreadOverlayEnum> dick = new() {
{"off", GunSpreadOverlayEnum.Off},
{"partial", GunSpreadOverlayEnum.Partial },
{"full", GunSpreadOverlayEnum.Full}
};

public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
if (args.Length <= 1)
return CompletionResult.FromOptions(dick.Keys);
return CompletionResult.Empty;
}

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var system = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GunSystem>();

if (args.Length != 1 ||
!dick.TryGetValue(args[0].ToLower(), out var option))
{
shell.WriteLine(Help);
return;
}

if (system.SpreadOverlay == option)
{
shell.WriteLine($"Spread overlay already set to \"{system.SpreadOverlay}\".");
}
else {
system.SpreadOverlay = option;
shell.WriteLine($"Set spread overlay to \"{system.SpreadOverlay}\".");
}
}
}

public sealed class ShowFullSpreadCommand : IConsoleCommand
{
public string Command => "showgunspreadfull";
public string Description => $"Shows gun spread overlay for debugging";
public string Help => $"{Command}";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var system = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GunSystem>();
system.SpreadOverlay ^= true;
if (system.SpreadOverlay == GunSystem.GunSpreadOverlayEnum.Full)
system.SpreadOverlay = GunSystem.GunSpreadOverlayEnum.Off;
else
system.SpreadOverlay = GunSystem.GunSpreadOverlayEnum.Full;

shell.WriteLine($"Set spread overlay to {system.SpreadOverlay}");
shell.WriteLine($"Set spread overlay to \"{system.SpreadOverlay}\".");
}
}
// WWDP EDIT END
187 changes: 165 additions & 22 deletions Content.Client/Weapons/Ranged/GunSpreadOverlay.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,43 @@
using System.Numerics;
using Content.Client.Resources;
using Content.Client.Viewport;
using Content.Client.Weapons.Ranged.Systems;
using Content.Shared.Contests;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.ResourceManagement;
using Robust.Client.Utility;
using Robust.Shared.ContentPack;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using Robust.Shared.Utility;


namespace Content.Client.Weapons.Ranged;

public sealed class GunSpreadOverlay : Overlay
// WWDP EDIT START
// so much shit was tossed around and changed, it's easier to assume
// the entire file is changed.
[Virtual]
public class GunSpreadOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.WorldSpace;

private IEntityManager _entManager;
private readonly IEyeManager _eye;
private readonly IGameTiming _timing;
private readonly IInputManager _input;
private readonly IPlayerManager _player;
private readonly GunSystem _guns;
private readonly SharedTransformSystem _transform;
protected IEntityManager _entManager;
protected readonly IEyeManager _eye;
protected readonly IGameTiming _timing;
protected readonly IInputManager _input;
protected readonly IPlayerManager _player;
protected readonly GunSystem _guns;
protected readonly SharedTransformSystem _transform;
protected readonly ContestsSystem _contest;

public GunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGameTiming timing, IInputManager input, IPlayerManager player, GunSystem system, SharedTransformSystem transform)
public GunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGameTiming timing, IInputManager input, IPlayerManager player, GunSystem system, SharedTransformSystem transform, ContestsSystem contest)
{
_entManager = entManager;
_eye = eyeManager;
Expand All @@ -29,6 +46,7 @@ public GunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGame
_player = player;
_guns = system;
_transform = transform;
_contest = contest;
}

protected override void Draw(in OverlayDrawArgs args)
Expand All @@ -40,43 +58,168 @@ protected override void Draw(in OverlayDrawArgs args)
if (player == null ||
!_entManager.TryGetComponent<TransformComponent>(player, out var xform))
{
Reset();
return;
}

var mapPos = _transform.GetMapCoordinates(player.Value, xform: xform);

if (mapPos.MapId == MapId.Nullspace)
{
Reset();
return;

}
if (!_guns.TryGetGun(player.Value, out var gunUid, out var gun))
{
Reset();
return;
}

var contest = 1 / _contest.MassContest(player);

var mouseScreenPos = _input.MouseScreenPosition;
var mousePos = _eye.PixelToMap(mouseScreenPos);

if (mapPos.MapId != mousePos.MapId)
{
Reset();
return;
}

// (☞゚ヮ゚)☞
var maxSpread = gun.MaxAngleModified;
var minSpread = gun.MinAngleModified;
var timeSinceLastFire = (_timing.CurTime - gun.NextFire).TotalSeconds;
var currentAngle = new Angle(MathHelper.Clamp(gun.CurrentAngle.Theta - gun.AngleDecayModified.Theta * timeSinceLastFire,
gun.MinAngleModified.Theta, gun.MaxAngleModified.Theta));
double timeSinceLastFire = (_timing.CurTime - gun.CurrentAngleLastUpdate).TotalSeconds;
double timeSinceLastBonusUpdate = (_timing.CurTime - gun.BonusAngleLastUpdate).TotalSeconds;
double maxBonusSpread = gun.MaxBonusAngleModified * contest / 2;
double minSpread = Math.Max(gun.MinAngleModified, 0) * contest / 2;
double maxSpread = gun.MaxAngleModified * contest / 2;

double bonusSpread = new Angle(MathHelper.Clamp((gun.BonusAngle - gun.BonusAngleDecayModified * timeSinceLastBonusUpdate) / 2,
0, maxBonusSpread)) * contest;
double currentAngle = new Angle(MathHelper.Clamp((gun.CurrentAngle.Theta - gun.AngleDecayModified.Theta * timeSinceLastFire) / 2,
minSpread, maxSpread)) * contest;
var direction = (mousePos.Position - mapPos.Position);

worldHandle.DrawLine(mapPos.Position, mousePos.Position + direction, Color.Orange);
Vector2 from = mapPos.Position;
Vector2 to = mousePos.Position + direction;

DrawSpread(worldHandle, gun, from, direction, timeSinceLastFire, maxBonusSpread, bonusSpread, maxSpread, minSpread, currentAngle);
}

protected virtual void DrawCone(DrawingHandleWorld handle, Vector2 from, Vector2 direction, Angle angle, Color color, float lerp = 1f)
{
var dir1 = angle.RotateVec(direction);
var dir2 = (-angle).RotateVec(direction);
handle.DrawLine(from + dir1 * (1 - lerp), from + dir1 * (1 + lerp), color);
handle.DrawLine(from + dir2 * (1 - lerp), from + dir2 * (1 + lerp), color);
}

protected virtual void DrawSpread(DrawingHandleWorld worldHandle, GunComponent gun, Vector2 from, Vector2 direction, double timeSinceLastFire, Angle maxBonusSpread, Angle bonusSpread, Angle maxSpread, Angle minSpread, Angle currentAngle)
{
worldHandle.DrawLine(from, direction*2, Color.Orange);

// Show max spread either side
worldHandle.DrawLine(mapPos.Position, mousePos.Position + maxSpread.RotateVec(direction), Color.Red);
worldHandle.DrawLine(mapPos.Position, mousePos.Position + (-maxSpread).RotateVec(direction), Color.Red);
DrawCone(worldHandle, from, direction, maxSpread + bonusSpread, Color.Red);

// Show min spread either side
worldHandle.DrawLine(mapPos.Position, mousePos.Position + minSpread.RotateVec(direction), Color.Green);
worldHandle.DrawLine(mapPos.Position, mousePos.Position + (-minSpread).RotateVec(direction), Color.Green);
DrawCone(worldHandle, from, direction, minSpread + bonusSpread, Color.Green);

// Show current angle
worldHandle.DrawLine(mapPos.Position, mousePos.Position + currentAngle.RotateVec(direction), Color.Yellow);
worldHandle.DrawLine(mapPos.Position, mousePos.Position + (-currentAngle).RotateVec(direction), Color.Yellow);
DrawCone(worldHandle, from, direction, currentAngle + bonusSpread, Color.Yellow);

DrawCone(worldHandle, from, direction, maxBonusSpread, Color.BetterViolet);

DrawCone(worldHandle, from, direction, bonusSpread, Color.Violet);

var oldTheta = MathHelper.Clamp(gun.CurrentAngle - gun.AngleDecayModified * timeSinceLastFire, gun.MinAngleModified, gun.MaxAngleModified);
var newTheta = MathHelper.Clamp(oldTheta + gun.AngleIncreaseModified.Theta, gun.MinAngleModified.Theta, gun.MaxAngleModified.Theta);
var shit = new Angle(newTheta + bonusSpread);
DrawCone(worldHandle, from, direction, shit, Color.Gray);
}

protected virtual void Reset() { }

}


public sealed class PartialGunSpreadOverlay : GunSpreadOverlay
{
private SpriteSystem _sprite;
private GunComponent? _lastGun;

private double SmoothedCurrentAngle;
private double SmoothedBonusSpread;

private Texture _textureS;
private Texture _textureL;

public PartialGunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGameTiming timing, IInputManager input, IPlayerManager player, GunSystem system, SharedTransformSystem transform, ContestsSystem contest, SpriteSystem sprite) : base(entManager, eyeManager, timing, input, player, system, transform, contest)
{
_sprite = sprite;
_textureS = _sprite.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/_White/Interface/gun-spread-marker-s.png")));
_textureL = _sprite.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/_White/Interface/gun-spread-marker-l.png")));
}

protected override void Reset() { _lastGun = null; }

protected override void DrawSpread(DrawingHandleWorld worldHandle, GunComponent gun, Vector2 from, Vector2 direction, double timeSinceLastFire, Angle maxBonusSpread, Angle bonusSpread, Angle maxSpread, Angle minSpread, Angle currentAngle)
{
if (_lastGun != gun)
{
_lastGun = gun;
SmoothedCurrentAngle = currentAngle;
SmoothedBonusSpread = bonusSpread;
}
else
{
SmoothedCurrentAngle = Double.Lerp(SmoothedCurrentAngle, currentAngle, 0.7);
SmoothedBonusSpread = Double.Lerp(SmoothedBonusSpread, bonusSpread, 0.35);
}
const float third = 1f / 3f;
float L = (float) ((currentAngle - minSpread) / (maxSpread - minSpread)); // not smoothed
float hue = Math.Clamp(third - third * L, 0, third);
Color color = Color.FromHsv(new Robust.Shared.Maths.Vector4(hue, 1, 1, 1));
DrawCone(worldHandle, from, direction, SmoothedCurrentAngle + SmoothedBonusSpread, color, 0.15f);
DrawCone(worldHandle, from, direction, SmoothedCurrentAngle, color.WithAlpha(0.33f), 0.15f);
}

protected override void DrawCone(DrawingHandleWorld handle, Vector2 from, Vector2 direction, Angle angle, Color color, float lineLerp = 1f)
{
var mpp = 1f / EyeManager.PixelsPerMeter;

var dir1 = angle.RotateVec(direction);
var dir2 = (-angle).RotateVec(direction);

Angle negRot = -_eye.CurrentEye.Rotation;

handle.SetTransform(from, 0);

Angle ang1 = dir1.ToAngle();
Angle ang2 = dir2.ToAngle();
handle.DrawTextureCentered(_textureL, dir1 * 0.76f, ang1, color);
handle.DrawTextureCentered(_textureL, dir2 * 0.76f, ang2, color);
handle.DrawTextureCentered(_textureS, dir1 * 0.88f, ang1, color);
handle.DrawTextureCentered(_textureS, dir2 * 0.88f, ang2, color);
handle.DrawTextureCentered(_textureL, dir1 * 1f, ang1, color);
handle.DrawTextureCentered(_textureL, dir2 * 1f, ang2, color);
handle.DrawTextureCentered(_textureS, dir1 * 1.12f, ang1, color);
handle.DrawTextureCentered(_textureS, dir2 * 1.12f, ang2, color);
handle.DrawTextureCentered(_textureL, dir1 * 1.24f, ang1, color);
handle.DrawTextureCentered(_textureL, dir2 * 1.24f, ang2, color);

}
}

public static class DrawingHandleWorldExt
{
public static void DrawTextureCentered(this DrawingHandleWorld handle, Texture tex, Vector2 position, Color? color = null) =>
handle.DrawTextureRect(tex, Box2.CenteredAround(position, tex.Size / (float) EyeManager.PixelsPerMeter), color);

public static void DrawTextureCentered(this DrawingHandleWorld handle, Texture tex, Vector2 position, Angle angle, Color? color = null) =>
handle.DrawTextureRect(tex, new Box2Rotated(Box2.CenteredAround(position, tex.Size / (float) EyeManager.PixelsPerMeter), angle, position), color);

public static void DrawRectCentered(this DrawingHandleWorld handle, Vector2 position, Vector2 size, Color color, bool filled = false) =>
handle.DrawRect(Box2.CenteredAround(position, size), color, filled);

public static void DrawRectCentered(this DrawingHandleWorld handle, Vector2 position, Vector2 size, Angle rot, Color color, bool filled = false) =>
handle.DrawRect(new Box2Rotated(Box2.CenteredAround(position, size), rot, position), color, filled);
}
Loading

0 comments on commit 9bc57d0

Please sign in to comment.