Serialization v3 content PR (#3491)
* serv3 in shared pt 1 * beginning of deepclone api * progress in implementing ideepclone & serv3 in content * adds target * its cant hurt you it cant hurt you * more changes to content.server * adds dataclasses * almost there * renamed & edited entry * finishes refactoring content to use serv3 * gasmixture runtimes, next: reagentunit * fucin hell that was an annoying one * adds flags * fixes some yaml errors * removes comment * fixes generic components for now * removes todo actually clones values my god paul fixes bug involving resolving custom data classes from other proj renames dataclass fixes spritecomp adds WithFormat.Constants support * adds deepclone to ResistanceSet * adds a bunch of deepclone implementations adds a deepclone analyzer (TODO) adds a deep clone fallback for classes & structs * fixes a bunch of runtimes * adds deepclone to entityuid * adds generator to sln * gets rid of warnings * fixes * argh * componentdata refactors * more deepclone impl * heck me i reworked all of content deepclone * renames custom dataclasstarget * misc * reworks prototypes * deepclone nuke * renamed customdataclass attribute * fixes everything * misc fixed * the killcommit * getting there * changed yamlfieldattribute namespace * adds back iselfserialize * renames everything to data(field/definition) * ouch * Fix most errors on content * Fix more errors in content * Fix some components * work on tests * fixes some customdataclasses * fuggin shit * yes * yeas * Remove data classes * Data field naming fixes * arg * Git resetti RobustToolbox * Merge fixes * General fixes * Fix startup serialization errors * Fix DamageContainerPrototype when supported classes or types are null * Implement construction graph step type serializer * Fix up construction serialization * Fix up construction serialization part 2 * Fix null list in technology database component * Fix body serialization * Fix entity storage serialization * Fix actions serialization * Fix AI serialization * Fix reaction serialization * Fix body serialization * Fix grid atmosphere serialization * Rename IServ3Manager to ISerializationManager * Convert every non generic serializer to the new format, general fixes * Serialization and body system fix * pushinheritance fix * Update all prototypes to have a parent and have consistent id/parent properties * Merge fixes * smh my head * cuddling slaps * Content commit for engine PR * stuff * more fixes * argh * yes even you are fixed * changelog fixes * fixes seeds * argh * Test fixes * Add writing for alert order prototype * Fix alert order writing * FIX * its been alot ok * Fix the rest of the visualizers * Fix server alerts component tests * Fix alert prototype tests not using the read value * Fix alert prototype tests initializing serialization multiple times * THIS IS AN AMERICAN CODEBASE GOD BLESS THE USA * Add ImplicitDataDefinitionForInheritors to IMechanismBehavior Fixes the behaviors not being found * Fix NRE in strap component Good night to the 1 buckle optimization * Fix clothing component slot flags serialization tag * Fix body component in all components test * Merge fixes * ffs * Make construction graph prototype use serialization hooks * human yaml linted * a * Do the thing for construction * stuff * a * monke see yaml linter * LINT HARDER * Remove redundant todo * yes * Add skip hook argument to readers and copiers * we gamin * test/datafield fixes * adds more verbose validation * moves linter to action * Improve construction graph step type serializer error message * Fix ammo box component NRE * gamin * some updates to the linter * yes * removes that test * misc fixes * array fix priority fix misc fixes * adds proper info the validation * adds alwaysrelevant usa * Make yaml linter take half as long to run (~50% less) * Make yaml linter 5 times faster (~80% less execution time) * based vera being based * fixes mapsaving * warning cleanup & moves surpressor * removes old msbuild targets * Revert "Make yaml linter 5 times faster (~80% less execution time)" This reverts commit 3e6091359a26252c3e98828199553de668031c63. * Add -nowarn to yaml linter run configuration * Improve yaml linter message feedback * Make dependencies an argument instead of a property on the serialization manager * yamllinting slaps * Clean up type serializers * Move yaml linter code to its own method * Fix yaml errors * Change yaml linter action name and remove -nowarn * yaml linter please shut * Git resetti robust toolbox Co-authored-by: Paul <ritter.paul1+git@googlemail.com> Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
@@ -14,7 +14,7 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
@@ -24,27 +24,30 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
{
|
||||
public override string Name => "AmmoBox";
|
||||
|
||||
private BallisticCaliber _caliber;
|
||||
public int Capacity => _capacity;
|
||||
private int _capacity;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
|
||||
[DataField("capacity")]
|
||||
public int Capacity
|
||||
{
|
||||
get => _capacity;
|
||||
set
|
||||
{
|
||||
_capacity = value;
|
||||
_spawnedAmmo = new Stack<IEntity>(value);
|
||||
}
|
||||
}
|
||||
|
||||
private int _capacity = 30;
|
||||
|
||||
public int AmmoLeft => _spawnedAmmo.Count + _unspawnedCount;
|
||||
private Stack<IEntity> _spawnedAmmo;
|
||||
private Stack<IEntity> _spawnedAmmo = new();
|
||||
private Container _ammoContainer;
|
||||
private int _unspawnedCount;
|
||||
|
||||
[DataField("fillPrototype")]
|
||||
private string _fillPrototype;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _capacity, "capacity", 30);
|
||||
serializer.DataField(ref _fillPrototype, "fillPrototype", null);
|
||||
|
||||
_spawnedAmmo = new Stack<IEntity>(_capacity);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
@@ -9,6 +9,7 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -19,13 +20,15 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
/// Generally used for bullets but can be used for other things like bananas
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class AmmoComponent : Component, IExamine
|
||||
public class AmmoComponent : Component, IExamine, ISerializationHooks
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
public override string Name => "Ammo";
|
||||
public BallisticCaliber Caliber => _caliber;
|
||||
private BallisticCaliber _caliber;
|
||||
|
||||
[field: DataField("caliber")]
|
||||
public BallisticCaliber Caliber { get; } = BallisticCaliber.Unspecified;
|
||||
|
||||
public bool Spent
|
||||
{
|
||||
get
|
||||
@@ -38,64 +41,60 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
return _spent;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _spent;
|
||||
|
||||
/// <summary>
|
||||
/// Used for anything without a case that fires itself
|
||||
/// </summary>
|
||||
[DataField("isProjectile")]
|
||||
private bool _ammoIsProjectile;
|
||||
|
||||
/// <summary>
|
||||
/// Used for something that is deleted when the projectile is retrieved
|
||||
/// </summary>
|
||||
public bool Caseless => _caseless;
|
||||
private bool _caseless;
|
||||
[field: DataField("caseless")]
|
||||
public bool Caseless { get; }
|
||||
|
||||
// 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;
|
||||
[field: DataField("projectilesFired")]
|
||||
public int ProjectilesFired { get; } = 1;
|
||||
|
||||
[DataField("projectile")]
|
||||
private string _projectileId;
|
||||
|
||||
// How far apart each entity is if multiple are shot
|
||||
public float EvenSpreadAngle => _evenSpreadAngle;
|
||||
private float _evenSpreadAngle;
|
||||
[field: DataField("ammoSpread")]
|
||||
public float EvenSpreadAngle { get; } = default;
|
||||
|
||||
/// <summary>
|
||||
/// How fast the shot entities travel
|
||||
/// </summary>
|
||||
public float Velocity => _velocity;
|
||||
private float _velocity;
|
||||
[field: DataField("ammoVelocity")]
|
||||
public float Velocity { get; } = 20f;
|
||||
|
||||
private string _muzzleFlashSprite;
|
||||
[DataField("muzzleFlash")]
|
||||
private string _muzzleFlashSprite = "Objects/Weapons/Guns/Projectiles/bullet_muzzle.png";
|
||||
|
||||
public string SoundCollectionEject => _soundCollectionEject;
|
||||
private string _soundCollectionEject;
|
||||
[field: DataField("soundCollectionEject")]
|
||||
public string SoundCollectionEject { get; } = "CasingEject";
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
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/Weapons/Guns/Projectiles/bullet_muzzle.png");
|
||||
serializer.DataField(ref _soundCollectionEject, "soundCollectionEject", "CasingEject");
|
||||
DebugTools.Assert(!(_ammoIsProjectile == true && Caseless == true));
|
||||
|
||||
if (_projectilesFired < 1)
|
||||
if (ProjectilesFired < 1)
|
||||
{
|
||||
Logger.Error("Ammo can't have less than 1 projectile");
|
||||
}
|
||||
|
||||
if (_evenSpreadAngle > 0 && _projectilesFired == 1)
|
||||
if (EvenSpreadAngle > 0 && ProjectilesFired == 1)
|
||||
{
|
||||
Logger.Error("Can't have an even spread if only 1 projectile is fired");
|
||||
throw new InvalidOperationException();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
{
|
||||
public partial class AmmoComponentData : ISerializationHooks
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
{
|
||||
@@ -12,13 +14,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
{
|
||||
public override string Name => "ChemicalAmmo";
|
||||
|
||||
private float _fractionTransfered;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _fractionTransfered, "fractionTransfered", 1);
|
||||
}
|
||||
[DataField("fractionTransfered")]
|
||||
private float _fractionTransfered = 1;
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent component)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,9 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
@@ -27,30 +29,25 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
|
||||
public int ShotsLeft => _spawnedAmmo.Count + _unspawnedCount;
|
||||
public int Capacity => _capacity;
|
||||
private int _capacity;
|
||||
[DataField("capacity")]
|
||||
private int _capacity = 20;
|
||||
|
||||
public MagazineType MagazineType => _magazineType;
|
||||
private MagazineType _magazineType;
|
||||
[DataField("magazineType")]
|
||||
private MagazineType _magazineType = MagazineType.Unspecified;
|
||||
public BallisticCaliber Caliber => _caliber;
|
||||
private BallisticCaliber _caliber;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
|
||||
// If there's anything already in the magazine
|
||||
[DataField("fillPrototype")]
|
||||
private string _fillPrototype;
|
||||
// By default the magazine won't spawn the entity until needed so we need to keep track of how many left we can spawn
|
||||
// Generally you probablt don't want to use this
|
||||
private int _unspawnedCount;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _magazineType, "magazineType", MagazineType.Unspecified);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _fillPrototype, "fillPrototype", null);
|
||||
serializer.DataField(ref _capacity, "capacity", 20);
|
||||
}
|
||||
|
||||
void IMapInit.MapInit()
|
||||
{
|
||||
if (_fillPrototype != null)
|
||||
|
||||
@@ -10,7 +10,9 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
{
|
||||
@@ -22,26 +24,19 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition
|
||||
{
|
||||
public override string Name => "SpeedLoader";
|
||||
|
||||
private BallisticCaliber _caliber;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
public int Capacity => _capacity;
|
||||
private int _capacity;
|
||||
[DataField("capacity")]
|
||||
private int _capacity = 6;
|
||||
private Container _ammoContainer;
|
||||
private Stack<IEntity> _spawnedAmmo;
|
||||
private Stack<IEntity> _spawnedAmmo = new();
|
||||
private int _unspawnedCount;
|
||||
|
||||
public int AmmoLeft => _spawnedAmmo.Count + _unspawnedCount;
|
||||
|
||||
private string _fillPrototype;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _capacity, "capacity", 6);
|
||||
serializer.DataField(ref _fillPrototype, "fillPrototype", null);
|
||||
|
||||
_spawnedAmmo = new Stack<IEntity>(_capacity);
|
||||
}
|
||||
[DataField("fillPrototype")]
|
||||
private string _fillPrototype = default;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -42,16 +42,19 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
}
|
||||
}
|
||||
public override int Capacity => _capacity;
|
||||
private int _capacity;
|
||||
[DataField("capacity")]
|
||||
private int _capacity = 6;
|
||||
|
||||
private ContainerSlot _chamberContainer;
|
||||
private Stack<IEntity> _spawnedAmmo;
|
||||
private Container _ammoContainer;
|
||||
|
||||
[ViewVariables]
|
||||
private BallisticCaliber _caliber;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("fillPrototype")]
|
||||
private string _fillPrototype;
|
||||
[ViewVariables]
|
||||
private int _unspawnedCount;
|
||||
@@ -91,28 +94,19 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
}
|
||||
}
|
||||
private bool _boltOpen;
|
||||
[DataField("autoCycle")]
|
||||
private bool _autoCycle;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
// Sounds
|
||||
private string _soundCycle;
|
||||
private string _soundBoltOpen;
|
||||
private string _soundBoltClosed;
|
||||
private string _soundInsert;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _capacity, "capacity", 6);
|
||||
serializer.DataField(ref _fillPrototype, "fillPrototype", null);
|
||||
serializer.DataField(ref _autoCycle, "autoCycle", false);
|
||||
|
||||
serializer.DataField(ref _soundCycle, "soundCycle", "/Audio/Weapons/Guns/Cock/sf_rifle_cock.ogg");
|
||||
serializer.DataField(ref _soundBoltOpen, "soundBoltOpen", "/Audio/Weapons/Guns/Bolt/rifle_bolt_open.ogg");
|
||||
serializer.DataField(ref _soundBoltClosed, "soundBoltClosed", "/Audio/Weapons/Guns/Bolt/rifle_bolt_closed.ogg");
|
||||
serializer.DataField(ref _soundInsert, "soundInsert", "/Audio/Weapons/Guns/MagIn/bullet_insert.ogg");
|
||||
}
|
||||
[DataField("soundCycle")]
|
||||
private string _soundCycle = "/Audio/Weapons/Guns/Cock/sf_rifle_cock.ogg";
|
||||
[DataField("soundBoltOpen")]
|
||||
private string _soundBoltOpen = "/Audio/Weapons/Guns/Bolt/rifle_bolt_open.ogg";
|
||||
[DataField("soundBoltClosed")]
|
||||
private string _soundBoltClosed = "/Audio/Weapons/Guns/Bolt/rifle_bolt_closed.ogg";
|
||||
[DataField("soundInsert")]
|
||||
private string _soundInsert = "/Audio/Weapons/Guns/MagIn/bullet_insert.ogg";
|
||||
|
||||
void IMapInit.MapInit()
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -14,6 +13,7 @@ using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
/// Bolt-action rifles
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class PumpBarrelComponent : ServerRangedBarrelComponent, IMapInit, IExamine
|
||||
public sealed class PumpBarrelComponent : ServerRangedBarrelComponent, IMapInit, ISerializationHooks
|
||||
{
|
||||
public override string Name => "PumpBarrel";
|
||||
public override uint? NetID => ContentNetIDs.PUMP_BARREL;
|
||||
@@ -37,43 +37,36 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
}
|
||||
}
|
||||
|
||||
public override int Capacity => _capacity;
|
||||
private int _capacity;
|
||||
private const int DefaultCapacity = 6;
|
||||
[field: DataField("capacity")]
|
||||
public override int Capacity { get; } = DefaultCapacity;
|
||||
|
||||
// Even a point having a chamber? I guess it makes some of the below code cleaner
|
||||
private ContainerSlot _chamberContainer;
|
||||
private Stack<IEntity> _spawnedAmmo;
|
||||
private Stack<IEntity> _spawnedAmmo = new (DefaultCapacity-1);
|
||||
private Container _ammoContainer;
|
||||
|
||||
[ViewVariables]
|
||||
private BallisticCaliber _caliber;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("fillPrototype")]
|
||||
private string _fillPrototype;
|
||||
[ViewVariables]
|
||||
private int _unspawnedCount;
|
||||
|
||||
private bool _manualCycle;
|
||||
[DataField("manualCycle")]
|
||||
private bool _manualCycle = true;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
|
||||
// Sounds
|
||||
private string _soundCycle;
|
||||
private string _soundInsert;
|
||||
[DataField("soundCycle")]
|
||||
private string _soundCycle = "/Audio/Weapons/Guns/Cock/sf_rifle_cock.ogg";
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _capacity, "capacity", 6);
|
||||
serializer.DataField(ref _fillPrototype, "fillPrototype", null);
|
||||
serializer.DataField(ref _manualCycle, "manualCycle", true);
|
||||
|
||||
serializer.DataField(ref _soundCycle, "soundCycle", "/Audio/Weapons/Guns/Cock/sf_rifle_cock.ogg");
|
||||
serializer.DataField(ref _soundInsert, "soundInsert", "/Audio/Weapons/Guns/MagIn/bullet_insert.ogg");
|
||||
|
||||
_spawnedAmmo = new Stack<IEntity>(_capacity - 1);
|
||||
}
|
||||
[DataField("soundInsert")]
|
||||
private string _soundInsert = "/Audio/Weapons/Guns/MagIn/bullet_insert.ogg";
|
||||
|
||||
void IMapInit.MapInit()
|
||||
{
|
||||
@@ -101,6 +94,11 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
SoundGunshot);
|
||||
}
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
_spawnedAmmo = new Stack<IEntity>(Capacity - 1);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
@@ -17,12 +17,13 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class RevolverBarrelComponent : ServerRangedBarrelComponent
|
||||
public sealed class RevolverBarrelComponent : ServerRangedBarrelComponent, ISerializationHooks
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
@@ -30,42 +31,49 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
public override uint? NetID => ContentNetIDs.REVOLVER_BARREL;
|
||||
|
||||
[ViewVariables]
|
||||
private BallisticCaliber _caliber;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
|
||||
private Container _ammoContainer;
|
||||
|
||||
[ViewVariables]
|
||||
private int _currentSlot = 0;
|
||||
private int _currentSlot;
|
||||
|
||||
public override int Capacity => _ammoSlots.Length;
|
||||
private IEntity[] _ammoSlots;
|
||||
|
||||
[DataField("capacity")]
|
||||
private int _serializedCapacity = 6;
|
||||
|
||||
[DataField("ammoSlots", readOnly: true)]
|
||||
private IEntity[] _ammoSlots = Array.Empty<IEntity>();
|
||||
|
||||
public override int ShotsLeft => _ammoContainer.ContainedEntities.Count;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
[ViewVariables]
|
||||
[DataField("fillPrototype")]
|
||||
private string _fillPrototype;
|
||||
|
||||
[ViewVariables]
|
||||
private int _unspawnedCount;
|
||||
|
||||
// Sounds
|
||||
private string _soundEject;
|
||||
private string _soundInsert;
|
||||
private string _soundSpin;
|
||||
[DataField("soundEject")]
|
||||
private string _soundEject = "/Audio/Weapons/Guns/MagOut/revolver_magout.ogg";
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
[DataField("soundInsert")]
|
||||
private string _soundInsert = "/Audio/Weapons/Guns/MagIn/revolver_magin.ogg";
|
||||
|
||||
[DataField("soundSpin")]
|
||||
private string _soundSpin = "/Audio/Weapons/Guns/Misc/revolver_spin.ogg";
|
||||
|
||||
void ISerializationHooks.BeforeSerialization()
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
_serializedCapacity = _ammoSlots.Length;
|
||||
}
|
||||
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataReadWriteFunction(
|
||||
"capacity",
|
||||
6,
|
||||
cap => _ammoSlots = new IEntity[cap],
|
||||
() => _ammoSlots.Length);
|
||||
serializer.DataField(ref _fillPrototype, "fillPrototype", null);
|
||||
|
||||
// Sounds
|
||||
serializer.DataField(ref _soundEject, "soundEject", "/Audio/Weapons/Guns/MagOut/revolver_magout.ogg");
|
||||
serializer.DataField(ref _soundInsert, "soundInsert", "/Audio/Weapons/Guns/MagIn/revolver_magin.ogg");
|
||||
serializer.DataField(ref _soundSpin, "soundSpin", "/Audio/Weapons/Guns/Misc/revolver_spin.ogg");
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
_ammoSlots = new IEntity[_serializedCapacity];
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState(ICommonSession player)
|
||||
@@ -112,21 +120,21 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent appearanceComponent))
|
||||
{
|
||||
_appearanceComponent = appearanceComponent;
|
||||
}
|
||||
|
||||
UpdateAppearance();
|
||||
Dirty();
|
||||
}
|
||||
|
||||
private void UpdateAppearance()
|
||||
{
|
||||
if (!Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Placeholder, at this stage it's just here for the RPG
|
||||
_appearanceComponent?.SetData(MagazineBarrelVisuals.MagLoaded, ShotsLeft > 0);
|
||||
_appearanceComponent?.SetData(AmmoVisuals.AmmoCount, ShotsLeft);
|
||||
_appearanceComponent?.SetData(AmmoVisuals.AmmoMax, Capacity);
|
||||
appearance.SetData(MagazineBarrelVisuals.MagLoaded, ShotsLeft > 0);
|
||||
appearance.SetData(AmmoVisuals.AmmoCount, ShotsLeft);
|
||||
appearance.SetData(AmmoVisuals.AmmoMax, Capacity);
|
||||
}
|
||||
|
||||
public bool TryInsertBullet(IEntity user, IEntity entity)
|
||||
|
||||
@@ -18,7 +18,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
@@ -30,17 +30,22 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
public override uint? NetID => ContentNetIDs.BATTERY_BARREL;
|
||||
|
||||
// The minimum change we need before we can fire
|
||||
[ViewVariables] private float _lowerChargeLimit;
|
||||
[ViewVariables] private int _baseFireCost;
|
||||
[DataField("lowerChargeLimit")]
|
||||
[ViewVariables] private float _lowerChargeLimit = 10;
|
||||
[DataField("fireCost")]
|
||||
[ViewVariables] private int _baseFireCost = 300;
|
||||
// What gets fired
|
||||
[DataField("ammoPrototype")]
|
||||
[ViewVariables] private string _ammoPrototype;
|
||||
|
||||
[ViewVariables] public IEntity PowerCellEntity => _powerCellContainer.ContainedEntity;
|
||||
public BatteryComponent PowerCell => _powerCellContainer.ContainedEntity?.GetComponent<BatteryComponent>();
|
||||
private ContainerSlot _powerCellContainer;
|
||||
private ContainerSlot _ammoContainer;
|
||||
private string _powerCellPrototype;
|
||||
[ViewVariables] private bool _powerCellRemovable;
|
||||
[DataField("powerCellPrototype")]
|
||||
private string _powerCellPrototype = default;
|
||||
[DataField("powerCellRemovable")]
|
||||
[ViewVariables] private bool _powerCellRemovable = default;
|
||||
|
||||
public override int ShotsLeft
|
||||
{
|
||||
@@ -75,21 +80,10 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
|
||||
// Sounds
|
||||
private string _soundPowerCellInsert;
|
||||
private string _soundPowerCellEject;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _powerCellPrototype, "powerCellPrototype", null);
|
||||
serializer.DataField(ref _powerCellRemovable, "powerCellRemovable", false);
|
||||
serializer.DataField(ref _baseFireCost, "fireCost", 300);
|
||||
serializer.DataField(ref _ammoPrototype, "ammoPrototype", null);
|
||||
serializer.DataField(ref _lowerChargeLimit, "lowerChargeLimit", 10);
|
||||
serializer.DataField(ref _soundPowerCellInsert, "soundPowerCellInsert", null);
|
||||
serializer.DataField(ref _soundPowerCellEject, "soundPowerCellEject", null);
|
||||
}
|
||||
[DataField("soundPowerCellInsert")]
|
||||
private string _soundPowerCellInsert = default;
|
||||
[DataField("soundPowerCellEject")]
|
||||
private string _soundPowerCellEject = default;
|
||||
|
||||
public override ComponentState GetComponentState(ICommonSession player)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -37,9 +37,11 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
private ContainerSlot _magazineContainer;
|
||||
|
||||
[ViewVariables] public MagazineType MagazineTypes => _magazineTypes;
|
||||
private MagazineType _magazineTypes;
|
||||
[DataField("magazineTypes")]
|
||||
private MagazineType _magazineTypes = default;
|
||||
[ViewVariables] public BallisticCaliber Caliber => _caliber;
|
||||
private BallisticCaliber _caliber;
|
||||
[DataField("caliber")]
|
||||
private BallisticCaliber _caliber = BallisticCaliber.Unspecified;
|
||||
|
||||
public override int ShotsLeft
|
||||
{
|
||||
@@ -77,6 +79,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
}
|
||||
}
|
||||
|
||||
[DataField("magFillPrototype")]
|
||||
private string _magFillPrototype;
|
||||
|
||||
public bool BoltOpen
|
||||
@@ -115,40 +118,28 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
}
|
||||
private bool _boltOpen = true;
|
||||
|
||||
[DataField("autoEjectMag")]
|
||||
private bool _autoEjectMag;
|
||||
// If the bolt needs to be open before we can insert / remove the mag (i.e. for LMGs)
|
||||
public bool MagNeedsOpenBolt => _magNeedsOpenBolt;
|
||||
private bool _magNeedsOpenBolt;
|
||||
[DataField("magNeedsOpenBolt")]
|
||||
private bool _magNeedsOpenBolt = default;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
|
||||
// Sounds
|
||||
private string _soundBoltOpen;
|
||||
private string _soundBoltClosed;
|
||||
private string _soundRack;
|
||||
private string _soundMagInsert;
|
||||
private string _soundMagEject;
|
||||
private string _soundAutoEject;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataReadWriteFunction(
|
||||
"magazineTypes",
|
||||
new List<MagazineType>(),
|
||||
types => types.ForEach(mag => _magazineTypes |= mag), GetMagazineTypes);
|
||||
serializer.DataField(ref _caliber, "caliber", BallisticCaliber.Unspecified);
|
||||
serializer.DataField(ref _magFillPrototype, "magFillPrototype", null);
|
||||
serializer.DataField(ref _autoEjectMag, "autoEjectMag", false);
|
||||
serializer.DataField(ref _magNeedsOpenBolt, "magNeedsOpenBolt", false);
|
||||
serializer.DataField(ref _soundBoltOpen, "soundBoltOpen", null);
|
||||
serializer.DataField(ref _soundBoltClosed, "soundBoltClosed", null);
|
||||
serializer.DataField(ref _soundRack, "soundRack", null);
|
||||
serializer.DataField(ref _soundMagInsert, "soundMagInsert", null);
|
||||
serializer.DataField(ref _soundMagEject, "soundMagEject", null);
|
||||
serializer.DataField(ref _soundAutoEject, "soundAutoEject", "/Audio/Weapons/Guns/EmptyAlarm/smg_empty_alarm.ogg");
|
||||
}
|
||||
[DataField("soundBoltOpen")]
|
||||
private string _soundBoltOpen = default;
|
||||
[DataField("soundBoltClosed")]
|
||||
private string _soundBoltClosed = default;
|
||||
[DataField("soundRack")]
|
||||
private string _soundRack = default;
|
||||
[DataField("soundMagInsert")]
|
||||
private string _soundMagInsert = default;
|
||||
[DataField("soundMagEject")]
|
||||
private string _soundMagEject = default;
|
||||
[DataField("soundAutoEject")]
|
||||
private string _soundAutoEject = "/Audio/Weapons/Guns/EmptyAlarm/smg_empty_alarm.ogg";
|
||||
|
||||
private List<MagazineType> GetMagazineTypes()
|
||||
{
|
||||
@@ -535,7 +526,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
[Flags]
|
||||
public enum MagazineType
|
||||
{
|
||||
|
||||
Unspecified = 0,
|
||||
LPistol = 1 << 0, // Placeholder?
|
||||
Pistol = 1 << 1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -24,6 +24,7 @@ using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -33,7 +34,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
/// All of the ranged weapon components inherit from this to share mechanics like shooting etc.
|
||||
/// Only difference between them is how they retrieve a projectile to shoot (battery, magazine, etc.)
|
||||
/// </summary>
|
||||
public abstract class ServerRangedBarrelComponent : SharedRangedBarrelComponent, IUse, IInteractUsing, IExamine
|
||||
public abstract class ServerRangedBarrelComponent : SharedRangedBarrelComponent, IUse, IInteractUsing, IExamine, ISerializationHooks
|
||||
{
|
||||
// There's still some of py01 and PJB's work left over, especially in underlying shooting logic,
|
||||
// it's just when I re-organised it changed me as the contributor
|
||||
@@ -41,11 +42,17 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
|
||||
public override FireRateSelector FireRateSelector => _fireRateSelector;
|
||||
private FireRateSelector _fireRateSelector;
|
||||
|
||||
[DataField("currentSelector")]
|
||||
private FireRateSelector _fireRateSelector = FireRateSelector.Safety;
|
||||
|
||||
public override FireRateSelector AllRateSelectors => _fireRateSelector;
|
||||
|
||||
[DataField("allSelectors")]
|
||||
private FireRateSelector _allRateSelectors;
|
||||
public override float FireRate => _fireRate;
|
||||
private float _fireRate;
|
||||
|
||||
[field: DataField("fireRate")]
|
||||
public override float FireRate { get; } = 2f;
|
||||
|
||||
// _lastFire is when we actually fired (so if we hold the button then recoil doesn't build up if we're not firing)
|
||||
private TimeSpan _lastFire;
|
||||
@@ -54,100 +61,76 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
public abstract IEntity TakeProjectile(EntityCoordinates spawnAt);
|
||||
|
||||
// Recoil / spray control
|
||||
private Angle _minAngle;
|
||||
private Angle _maxAngle;
|
||||
[DataField("minAngle")]
|
||||
private float _minAngleDegrees;
|
||||
|
||||
public Angle MinAngle { get; private set; }
|
||||
|
||||
[DataField("maxAngle")]
|
||||
private float _maxAngleDegrees = 45;
|
||||
|
||||
public Angle MaxAngle { get; private set; }
|
||||
|
||||
private Angle _currentAngle = Angle.Zero;
|
||||
|
||||
[DataField("angleDecay")]
|
||||
private float _angleDecayDegrees = 20;
|
||||
|
||||
/// <summary>
|
||||
/// How slowly the angle's theta decays per second in radians
|
||||
/// </summary>
|
||||
private float _angleDecay;
|
||||
public float AngleDecay { get; private set; }
|
||||
|
||||
[DataField("angleIncrease")]
|
||||
private float? _angleIncreaseDegrees;
|
||||
|
||||
/// <summary>
|
||||
/// How quickly the angle's theta builds for every shot fired in radians
|
||||
/// </summary>
|
||||
private float _angleIncrease;
|
||||
// Multiplies the ammo spread to get the final spread of each pellet
|
||||
private float _spreadRatio;
|
||||
public float AngleIncrease { get; private set; }
|
||||
|
||||
public bool CanMuzzleFlash => _canMuzzleFlash;
|
||||
private bool _canMuzzleFlash = true;
|
||||
// Multiplies the ammo spread to get the final spread of each pellet
|
||||
[DataField("ammoSpreadRatio")]
|
||||
public float SpreadRatio { get; private set; }
|
||||
|
||||
[field: DataField("canMuzzleFlash")]
|
||||
public bool CanMuzzleFlash { get; } = true;
|
||||
|
||||
// Sounds
|
||||
public string SoundGunshot
|
||||
[field: DataField("soundGunshot")]
|
||||
public string SoundGunshot { get; set; }
|
||||
|
||||
[field: DataField("soundEmpty")]
|
||||
public string SoundEmpty { get; } = "/Audio/Weapons/Guns/Empty/empty.ogg";
|
||||
|
||||
void ISerializationHooks.BeforeSerialization()
|
||||
{
|
||||
get => _soundGunshot;
|
||||
set => _soundGunshot = value;
|
||||
_minAngleDegrees = (float) (MinAngle.Degrees * 2);
|
||||
_maxAngleDegrees = (float) (MaxAngle.Degrees * 2);
|
||||
_angleIncreaseDegrees = MathF.Round(AngleIncrease / ((float) Math.PI / 180f), 2);
|
||||
AngleDecay = MathF.Round(AngleDecay / ((float) Math.PI / 180f), 2);
|
||||
}
|
||||
private string _soundGunshot;
|
||||
public string SoundEmpty => _soundEmpty;
|
||||
private string _soundEmpty;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _fireRateSelector, "currentSelector", FireRateSelector.Safety);
|
||||
serializer.DataField(ref _fireRate, "fireRate", 2.0f);
|
||||
|
||||
// This hard-to-read area's dealing with recoil
|
||||
// Use degrees in yaml as it's easier to read compared to "0.0125f"
|
||||
serializer.DataReadWriteFunction(
|
||||
"minAngle",
|
||||
0,
|
||||
angle => _minAngle = Angle.FromDegrees(angle / 2f),
|
||||
() => _minAngle.Degrees * 2);
|
||||
MinAngle = Angle.FromDegrees(_minAngleDegrees / 2f);
|
||||
|
||||
// Random doubles it as it's +/- so uhh we'll just half it here for readability
|
||||
serializer.DataReadWriteFunction(
|
||||
"maxAngle",
|
||||
45,
|
||||
angle => _maxAngle = Angle.FromDegrees(angle / 2f),
|
||||
() => _maxAngle.Degrees * 2);
|
||||
MaxAngle = Angle.FromDegrees(_maxAngleDegrees / 2f);
|
||||
|
||||
serializer.DataReadWriteFunction(
|
||||
"angleIncrease",
|
||||
40 / _fireRate,
|
||||
angle => _angleIncrease = angle * (float) Math.PI / 180f,
|
||||
() => MathF.Round(_angleIncrease / ((float) Math.PI / 180f), 2));
|
||||
_angleIncreaseDegrees ??= 40 / FireRate;
|
||||
AngleIncrease = _angleIncreaseDegrees.Value * (float) Math.PI / 180f;
|
||||
|
||||
serializer.DataReadWriteFunction(
|
||||
"angleDecay",
|
||||
20f,
|
||||
angle => _angleDecay = angle * (float) Math.PI / 180f,
|
||||
() => MathF.Round(_angleDecay / ((float) Math.PI / 180f), 2));
|
||||
|
||||
serializer.DataField(ref _spreadRatio, "ammoSpreadRatio", 1.0f);
|
||||
|
||||
serializer.DataReadWriteFunction(
|
||||
"allSelectors",
|
||||
new List<FireRateSelector>(),
|
||||
selectors => selectors.ForEach(selector => _allRateSelectors |= selector),
|
||||
() =>
|
||||
{
|
||||
var types = new List<FireRateSelector>();
|
||||
|
||||
foreach (FireRateSelector selector in Enum.GetValues(typeof(FireRateSelector)))
|
||||
{
|
||||
if ((_allRateSelectors & selector) != 0)
|
||||
{
|
||||
types.Add(selector);
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
});
|
||||
AngleDecay = _angleDecayDegrees * (float) Math.PI / 180f;
|
||||
|
||||
// For simplicity we'll enforce it this way; ammo determines max spread
|
||||
if (_spreadRatio > 1.0f)
|
||||
if (SpreadRatio > 1.0f)
|
||||
{
|
||||
Logger.Error("SpreadRatio must be <= 1.0f for guns");
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
serializer.DataField(ref _canMuzzleFlash, "canMuzzleFlash", true);
|
||||
|
||||
// Sounds
|
||||
serializer.DataField(ref _soundGunshot, "soundGunshot", null);
|
||||
serializer.DataField(ref _soundEmpty, "soundEmpty", "/Audio/Weapons/Guns/Empty/empty.ogg");
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
@@ -176,7 +159,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
{
|
||||
var currentTime = _gameTiming.CurTime;
|
||||
var timeSinceLastFire = (currentTime - _lastFire).TotalSeconds;
|
||||
var newTheta = MathHelper.Clamp(_currentAngle.Theta + _angleIncrease - _angleDecay * timeSinceLastFire, _minAngle.Theta, _maxAngle.Theta);
|
||||
var newTheta = MathHelper.Clamp(_currentAngle.Theta + AngleIncrease - AngleDecay * timeSinceLastFire, MinAngle.Theta, MaxAngle.Theta);
|
||||
_currentAngle = new Angle(newTheta);
|
||||
|
||||
var random = (_robustRandom.NextDouble() - 0.5) * 2;
|
||||
@@ -214,9 +197,9 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
{
|
||||
if (ShotsLeft == 0)
|
||||
{
|
||||
if (_soundEmpty != null)
|
||||
if (SoundEmpty != null)
|
||||
{
|
||||
SoundSystem.Play(Filter.Broadcast(), _soundEmpty, Owner.Transform.Coordinates);
|
||||
SoundSystem.Play(Filter.Broadcast(), SoundEmpty, Owner.Transform.Coordinates);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -225,7 +208,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
var projectile = TakeProjectile(shooter.Transform.Coordinates);
|
||||
if (projectile == null)
|
||||
{
|
||||
SoundSystem.Play(Filter.Broadcast(), _soundEmpty, Owner.Transform.Coordinates);
|
||||
SoundSystem.Play(Filter.Broadcast(), SoundEmpty, Owner.Transform.Coordinates);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -266,7 +249,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
SoundSystem.Play(Filter.Broadcast(), _soundGunshot, Owner.Transform.Coordinates);
|
||||
SoundSystem.Play(Filter.Broadcast(), SoundGunshot, Owner.Transform.Coordinates);
|
||||
_lastFire = _gameTiming.CurTime;
|
||||
|
||||
return;
|
||||
@@ -352,7 +335,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
List<Angle> sprayAngleChange = null;
|
||||
if (count > 1)
|
||||
{
|
||||
evenSpreadAngle *= _spreadRatio;
|
||||
evenSpreadAngle *= SpreadRatio;
|
||||
sprayAngleChange = Linspace(-evenSpreadAngle / 2, evenSpreadAngle / 2, count);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
||||
@@ -33,9 +33,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
||||
private TimeSpan _lastFireTime;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool ClumsyCheck { get; set; }
|
||||
[DataField("clumsyCheck")]
|
||||
public bool ClumsyCheck { get; set; } = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float ClumsyExplodeChance { get; set; }
|
||||
[DataField("clumsyExplodeChance")]
|
||||
public float ClumsyExplodeChance { get; set; } = 0.5f;
|
||||
|
||||
public Func<bool> WeaponCanFireHandler;
|
||||
public Func<IEntity, bool> UserCanFireHandler;
|
||||
@@ -70,14 +73,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
||||
return (UserCanFireHandler == null || UserCanFireHandler(user)) && ActionBlockerSystem.CanAttack(user);
|
||||
}
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(this, p => p.ClumsyCheck, "clumsyCheck", true);
|
||||
serializer.DataField(this, p => p.ClumsyExplodeChance, "clumsyExplodeChance", 0.5f);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user