Files
tbd-station-14/Content.Server/GameObjects/Components/Weapon/Ranged/Ammunition/AmmoComponent.cs
metalgearsloth 95995b6232 Add a LOT more dakka (#1033)
* Start adding flashy flash

* Change slop

Might give a smoother decline

* flashy flash

* Add flashbang and flash projectiles

Bang bang bang pull my flash trigger

* Add collision check to area flash

* Flash cleanupo

* flash.ogg mixed to mono
* Adjusted flash curve again

* Enhancing flashes with unshaded and lights and shit

Still a WIP

* Add the other ballistic gun types

Re-organised some of the gun stuff so the powercell guns share the shooting code with the ballistic guns.

* Re-merging branch with master

Also fixed some visualizer bugs

* Last cleanup

Fixed some crashes
Fixed Deckard sprite
Fixed Hitscan effects
Re-applied master changes
Re-factor to using soundsystem
Add some more audio effects

* Cleanup flashes for merge

Can put flashbangs in lockers so you don't get blinded

Fix some bugs

* Fix shotties

Also removed some redundant code

* Bulldoze some legacycode

brrrrrrrrt

* Fix clientignore warnings

* Add the other Stunnable types to StunnableProjectile

* Some gun refactoring

* Removed extra visualizers
* All casing ejections use the same code
* Speed loaders can have their ammo pulled out
* Bolt sound less loud

* Stop ThrowController from throwing

* Fix speed loader visuals

* Update hitscan collision mask and fix typo

* Cleanup

* Fit hitscan and flashbang collisions
* Use the new flags support

* Update taser placeholder description

* Update protonames per style guide

* Add yaml flag support for gun firerates

* Cleanup crew

* Fix Audio up (components, audio file, + remove global sounds)
* Add server-side recoil back-in (forgot that I was testing this client-side)
* Add Flag support for fire-rate selectors

* Wrong int you dolt

* Fix AI conflicts

Haha ranged bulldozer go BRR
(I'll rewrite it after the other AI systems are done).

* Mix bang.ogg from stereo to mono

* Make sure serializer's reading for guns

Fixes integration test

* Change EntitySystem calls to use the static function

Also removed the Pumpbarrel commented-out code

* Change StunnableProjectile defaults to 0

* Fix taser paralyse

Apparently removing defaults means you have to specify the values, whodathunkit

* Add slowdown to stunnableprojectiles and fix tasers

* Remove FlagsFor from gun components

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
2020-06-21 21:47:15 +02:00

177 lines
6.1 KiB
C#

using System;
using System.Timers;
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Logger = Robust.Shared.Log.Logger;
using Timer = Robust.Shared.Timers.Timer;
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
{
/// <summary>
/// Allows this entity to be loaded into a ranged weapon (if the caliber matches)
/// Generally used for bullets but can be used for other things like bananas
/// </summary>
[RegisterComponent]
public class AmmoComponent : Component
{
public override string Name => "Ammo";
public BallisticCaliber Caliber => _caliber;
private BallisticCaliber _caliber;
public bool Spent
{
get
{
if (_ammoIsProjectile)
{
return false;
}
return _spent;
}
}
private bool _spent;
/// <summary>
/// Used for anything without a case that fires itself
/// </summary>
private bool _ammoIsProjectile;
/// <summary>
/// Used for something that is deleted when the projectile is retrieved
/// </summary>
public bool Caseless => _caseless;
private bool _caseless;
// Rather than managing bullet / case state seemed easier to just have 2 toggles
// ammoIsProjectile being for a beanbag for example and caseless being for ClRifle rounds
/// <summary>
/// For shotguns where they might shoot multiple entities
/// </summary>
public int ProjectilesFired => _projectilesFired;
private int _projectilesFired;
private string _projectileId;
// How far apart each entity is if multiple are shot
public float EvenSpreadAngle => _evenSpreadAngle;
private float _evenSpreadAngle;
/// <summary>
/// How fast the shot entities travel
/// </summary>
public float Velocity => _velocity;
private float _velocity;
private string _muzzleFlashSprite;
public string SoundCollectionEject => _soundCollectionEject;
private string _soundCollectionEject;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
// For shotty of whatever as well
serializer.DataField(ref _projectileId, "projectile", null);
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
serializer.DataField(ref _projectilesFired, "projectilesFired", 1);
// Used for shotty to determine overall pellet spread
serializer.DataField(ref _evenSpreadAngle, "ammoSpread", 0);
serializer.DataField(ref _velocity, "ammoVelocity", 20.0f);
serializer.DataField(ref _ammoIsProjectile, "isProjectile", false);
serializer.DataField(ref _caseless, "caseless", false);
// Being both caseless and shooting yourself doesn't make sense
DebugTools.Assert(!(_ammoIsProjectile && _caseless));
serializer.DataField(ref _muzzleFlashSprite, "muzzleFlash", "Objects/Guns/Projectiles/bullet_muzzle.png");
serializer.DataField(ref _soundCollectionEject, "soundCollectionEject", "CasingEject");
if (_projectilesFired < 1)
{
Logger.Error("Ammo can't have less than 1 projectile");
}
if (_evenSpreadAngle > 0 && _projectilesFired == 1)
{
Logger.Error("Can't have an even spread if only 1 projectile is fired");
throw new InvalidOperationException();
}
}
public IEntity TakeBullet()
{
if (_ammoIsProjectile)
{
return Owner;
}
if (_spent)
{
return null;
}
_spent = true;
if (Owner.TryGetComponent(out AppearanceComponent appearanceComponent))
{
appearanceComponent.SetData(AmmoVisuals.Spent, true);
}
var entity = Owner.EntityManager.SpawnEntity(_projectileId, Owner.Transform.GridPosition);
DebugTools.AssertNotNull(entity);
return entity;
}
public void MuzzleFlash(GridCoordinates grid, Angle angle)
{
if (_muzzleFlashSprite == null)
{
return;
}
var time = IoCManager.Resolve<IGameTiming>().CurTime;
var deathTime = time + TimeSpan.FromMilliseconds(200);
// Offset the sprite so it actually looks like it's coming from the gun
var offset = angle.ToVec().Normalized / 2;
var message = new EffectSystemMessage
{
EffectSprite = _muzzleFlashSprite,
Born = time,
DeathTime = deathTime,
Coordinates = grid.Translated(offset),
//Rotated from east facing
Rotation = (float) angle.Theta,
Color = Vector4.Multiply(new Vector4(255, 255, 255, 255), 1.0f),
ColorDelta = new Vector4(0, 0, 0, -1500f),
Shaded = false
};
EntitySystem.Get<EffectSystem>().CreateParticle(message);
}
}
public enum BallisticCaliber
{
Unspecified = 0,
A357, // Placeholder?
ClRifle,
SRifle,
Pistol,
A35, // Placeholder?
LRifle,
Magnum,
AntiMaterial,
Shotgun,
Cap, // Placeholder
Rocket,
Dart, // Placeholder
Grenade,
Energy,
}
}