Skip to content

Commit

Permalink
ballistics rework pt1 (#10)
Browse files Browse the repository at this point in the history
* renaming

* examine

* kill

* tracer bullets wooo

* smallest milon pr

* buff damage

* PRAY

* wield sprites

* more weapon renaming
  • Loading branch information
MilonPL authored Jan 3, 2025
1 parent 9044a75 commit b9dda67
Show file tree
Hide file tree
Showing 136 changed files with 2,663 additions and 77 deletions.
23 changes: 23 additions & 0 deletions Content.Client/_Emberfall/Weapons/Ranged/Overlays/TracerOverlay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Content.Client._Emberfall.Weapons.Ranged.Systems;
using Robust.Client.Graphics;
using Robust.Shared.Enums;

namespace Content.Client._Emberfall.Weapons.Ranged.Overlays;

public sealed class TracerOverlay : Overlay
{
private readonly TracerSystem _tracer;

public override OverlaySpace Space => OverlaySpace.WorldSpace;

public TracerOverlay(TracerSystem tracer)
{
_tracer = tracer;
IoCManager.InjectDependencies(this);
}

protected override void Draw(in OverlayDrawArgs args)
{
_tracer.Draw(args.WorldHandle, args.MapId);
}
}
87 changes: 87 additions & 0 deletions Content.Client/_Emberfall/Weapons/Ranged/Systems/TracerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System.Numerics;
using Content.Client._Emberfall.Weapons.Ranged.Overlays;
using Content.Shared._Emberfall.Weapons.Ranged;
using Robust.Client.Graphics;
using Robust.Shared.Map;
using Robust.Shared.Timing;

namespace Content.Client._Emberfall.Weapons.Ranged.Systems;

public sealed class TracerSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;

public override void Initialize()
{
base.Initialize();
_overlay.AddOverlay(new TracerOverlay(this));

SubscribeLocalEvent<TracerComponent, ComponentStartup>(OnTracerStart);
}

private void OnTracerStart(Entity<TracerComponent> ent, ref ComponentStartup args)
{
var xform = Transform(ent);
var pos = _transform.GetWorldPosition(xform);

ent.Comp.Data = new TracerData(
new List<Vector2> { pos },
_timing.CurTime + TimeSpan.FromSeconds(ent.Comp.Lifetime)
);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

var curTime = _timing.CurTime;
var query = EntityQueryEnumerator<TracerComponent, TransformComponent>();

while (query.MoveNext(out var uid, out var tracer, out var xform))
{
if (curTime > tracer.Data.EndTime)
{
RemCompDeferred<TracerComponent>(uid);
continue;
}

var currentPos = _transform.GetWorldPosition(xform);
tracer.Data.PositionHistory.Add(currentPos);

while (tracer.Data.PositionHistory.Count > 2 &&
GetTrailLength(tracer.Data.PositionHistory) > tracer.Length)
{
tracer.Data.PositionHistory.RemoveAt(0);
}
}
}

private static float GetTrailLength(List<Vector2> positions)
{
var length = 0f;
for (var i = 1; i < positions.Count; i++)
{
length += Vector2.Distance(positions[i - 1], positions[i]);
}
return length;
}

public void Draw(DrawingHandleWorld handle, MapId currentMap)
{
var query = EntityQueryEnumerator<TracerComponent, TransformComponent>();

while (query.MoveNext(out _, out var tracer, out var xform))
{
if (xform.MapID != currentMap)
continue;

var positions = tracer.Data.PositionHistory;
for (var i = 1; i < positions.Count; i++)
{
handle.DrawLine(positions[i - 1], positions[i], tracer.Color);
}
}
}
}
128 changes: 128 additions & 0 deletions Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Examine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Utility;

namespace Content.Shared.Weapons.Ranged.Systems;

public abstract partial class SharedGunSystem
{
private void OnGunVerbExamine(Entity<GunComponent> ent, ref GetVerbsEvent<ExamineVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;

var examineMarkup = GetGunExamine(ent);

var ev = new GunExamineEvent(examineMarkup);
RaiseLocalEvent(ent, ref ev);

Examine.AddDetailedExamineVerb(args,
ent.Comp,
examineMarkup,
Loc.GetString("gun-examinable-verb-text"),
"/Textures/Interface/VerbIcons/dot.svg.192dpi.png",
Loc.GetString("gun-examinable-verb-message"));
}

private FormattedMessage GetGunExamine(Entity<GunComponent> ent)
{
var msg = new FormattedMessage();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine"));

// Recoil (AngleIncrease)
msg.PushNewline();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine-recoil",
("color", FireRateExamineColor),
("value", MathF.Round((float)ent.Comp.AngleIncreaseModified.Degrees, 2))
));

// Stability (AngleDecay)
msg.PushNewline();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine-stability",
("color", FireRateExamineColor),
("value", MathF.Round((float)ent.Comp.AngleDecayModified.Degrees, 2))
));

// Max Angle
msg.PushNewline();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine-max-angle",
("color", FireRateExamineColor),
("value", MathF.Round((float)ent.Comp.MaxAngleModified.Degrees, 2))
));

// Min Angle
msg.PushNewline();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine-min-angle",
("color", FireRateExamineColor),
("value", MathF.Round((float)ent.Comp.MinAngleModified.Degrees, 2))
));

// Fire Rate (converted from RPS to RPM)
msg.PushNewline();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine-fire-rate",
("color", FireRateExamineColor),
("value", MathF.Round(ent.Comp.FireRateModified, 1))
));

// Muzzle Velocity (ProjectileSpeed * 10)
msg.PushNewline();
msg.AddMarkupOrThrow(Loc.GetString("gun-examine-muzzle-velocity",
("color", FireRateExamineColor),
("value", MathF.Round(ent.Comp.ProjectileSpeedModified * 10f, 0))
));

return msg;
}

private bool TryGetGunCaliber(EntityUid uid, [NotNullWhen(true)] out string? caliber)
{
caliber = null;

// Try standard gun with ItemSlots first
if (HasComp<ItemSlotsComponent>(uid) &&
_slots.TryGetSlot(uid, "gun_chamber", out var chamberSlot) &&
chamberSlot.Whitelist?.Tags is { Count: > 0 })
{
caliber = GetCaliberFromTag(chamberSlot.Whitelist.Tags.First());
return true;
}

// Try revolver
if (TryComp<RevolverAmmoProviderComponent>(uid, out var revolver) &&
revolver.Whitelist?.Tags is { Count: > 0 })
{
caliber = GetCaliberFromTag(revolver.Whitelist.Tags.First());
return true;
}

return false;
}

private static string GetCaliberFromTag(string tag)
{
return tag switch
{
"CartridgeMagnum" => ".44 Magnum",
"CartridgePistol" => "9x19mm",
"CartridgeHeavyPistol" => "10mm auto",
"CartridgeRifle" => "7.62x51mm",
"CartridgeLightRifle" => "5.56x45mm",
"CartridgeCaselessRifle" => "4.73x33mm caseless",
_ => tag,
};
}

private void InitializeGunExamine()
{
SubscribeLocalEvent<GunComponent, GetVerbsEvent<ExamineVerb>>(OnGunVerbExamine);
}
}

/// <summary>
/// Event raised on a gun entity to get additional examine text relating to its specifications.
/// </summary>
[ByRefEvent]
public readonly record struct GunExamineEvent(FormattedMessage Msg);
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,19 @@ private void OnExamine(EntityUid uid, GunComponent component, ExaminedEvent args

using (args.PushGroup(nameof(GunComponent)))
{
// Emberfall - Add caliber info
if (TryGetGunCaliber(uid, out var caliber))
{
args.PushMarkup(Loc.GetString("gun-examine-caliber",
("color", FireRateExamineColor),
("caliber", caliber)));
}
// End Emberfall

args.PushMarkup(Loc.GetString("gun-selected-mode-examine", ("color", ModeExamineColor),
("mode", GetLocSelector(component.SelectedMode))));
args.PushMarkup(Loc.GetString("gun-fire-rate-examine", ("color", FireRateExamineColor),
("fireRate", $"{component.FireRateModified:0.0}")));
// args.PushMarkup(Loc.GetString("gun-fire-rate-examine", ("color", FireRateExamineColor),
// ("fireRate", $"{component.FireRateModified:0.0}")));
}
}

Expand Down
1 change: 1 addition & 0 deletions Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public override void Initialize()
InitializeClothing();
InitializeContainer();
InitializeSolution();
InitializeGunExamine(); // Emberfall

// Interactions
SubscribeLocalEvent<GunComponent, GetVerbsEvent<AlternativeVerb>>(OnAltVerb);
Expand Down
47 changes: 47 additions & 0 deletions Content.Shared/_Emberfall/Weapons/Ranged/TracerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Numerics;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;

namespace Content.Shared._Emberfall.Weapons.Ranged;

/// <summary>
/// Added to projectiles to give them tracer effects
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class TracerComponent : Component
{
/// <summary>
/// How long the tracer effect should remain visible for after firing
/// </summary>
[DataField]
public float Lifetime = 10f;

/// <summary>
/// The maximum length of the tracer trail
/// </summary>
[DataField]
public float Length = 2f;

/// <summary>
/// Color of the tracer line effect
/// </summary>
[DataField]
public Color Color = Color.Red;

[ViewVariables]
public TracerData Data = default!;
}

[Serializable, NetSerializable, DataRecord]
public struct TracerData(List<Vector2> positionHistory, TimeSpan endTime)
{
/// <summary>
/// The history of positions this tracer has moved through
/// </summary>
public List<Vector2> PositionHistory = positionHistory;

/// <summary>
/// When this tracer effect should end
/// </summary>
public TimeSpan EndTime = endTime;
}
Binary file not shown.
1 change: 1 addition & 0 deletions Resources/Audio/_Emberfall/license.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nightshade.ogg is modified from free sound effects from https://www.fesliyanstudios.com which are licensed under the CC0 1.0 License.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
research-technology-tracer-ammunition = Tracer Ammunition
11 changes: 11 additions & 0 deletions Resources/Locale/en-US/_emberfall/store/uplink-catalog.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
uplink-smg-atreides-name = Atreides
uplink-smg-atreides-desc = An older SMG model that refuses to die. Uses SMG magazines (9x19mm)
uplink-pistol-pollock-name = Pollock
uplink-pistol-pollock-desc = Mass-produced mercenary sidearm. No serial numbers, no questions asked. Uses 10mm auto.
uplink-pistol-magazine-high-capacity-name = SMG Magazine (9x19mm)
uplink-pistol-magazine-high-capacity-desc = SMG magazine with 20 catridges. Compatible with the Atreides.
uplink-pistol-magazine-heavy-name = Pistol Magazine (10mm auto)
uplink-pistol-magazine-heavy-desc = Pistol magazine with 12 catridges. Compatible with the Pollock.
10 changes: 10 additions & 0 deletions Resources/Locale/en-US/_emberfall/weapons/gun-examine.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
gun-examinable-verb-text = Examine statistics
gun-examinable-verb-message = Detailed statistics
gun-examine = Gun specifications:
gun-examine-recoil = - [color={$color}]Recoil[/color]: [color=lightblue]{$value}°[/color] per shot
gun-examine-stability = - [color={$color}]Stability[/color]: [color=lightblue]{$value}°[/color] per second
gun-examine-max-angle = - [color={$color}]Maximum spread[/color]: [color=lightblue]{$value}°[/color]
gun-examine-min-angle = - [color={$color}]Minimum spread[/color]: [color=lightblue]{$value}°[/color]
gun-examine-fire-rate = - [color={$color}]Fire rate[/color]: [color=lightblue]{$value} RPS[/color]
gun-examine-muzzle-velocity = - [color={$color}]Muzzle velocity[/color]: [color=lightblue]{$value} m/s[/color]
gun-examine-caliber = It's chambered in [color={$color}]{$caliber}[/color].
Loading

0 comments on commit b9dda67

Please sign in to comment.