diff --git a/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs index f2c68d4959..b896ecc49e 100644 --- a/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Numerics; using Content.Client.Station; // Frontier +using Content.Client.Weapons.Ranged.Systems; using Content.Shared.Projectiles; using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Components; @@ -29,6 +30,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl private readonly SharedShuttleSystem _shuttles; private readonly SharedTransformSystem _transform; private readonly EntityLookupSystem _lookup; // WD EDIT + private readonly GunSystem _gun; // WD EDIT /// /// Used to transform all of the radar objects. Typically is a shuttle console parented to a grid. @@ -57,6 +59,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl _transform = EntManager.System(); _station = EntManager.System(); // Frontier _lookup = EntManager.System(); // WWDP EDIT + _gun = EntManager.System(); // WWDP EDIT } public void SetMatrix(EntityCoordinates? coordinates, Angle? angle) @@ -141,7 +144,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl var fixturesQuery = EntManager.GetEntityQuery(); var bodyQuery = EntManager.GetEntityQuery(); - EntManager.TryGetComponent(_coordinates.Value.EntityId, out var ourGunComp); // WD EDIT + _gun.TryGetGun(_coordinates.Value.EntityId, out _, out var ourGunComp); // WWDP EDIT if (!xformQuery.TryGetComponent(_coordinates.Value.EntityId, out var xform) || xform.MapID == MapId.Nullspace) diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index 58eb70e0a8..e67c144d98 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -157,15 +157,8 @@ public sealed partial class GunSystem : SharedGunSystem if (a.Sprite is not SpriteSpecifier.Rsi rsi) continue; - var coords = GetCoordinates(a.coordinates); - - if (Deleted(coords.EntityId)) - continue; - - var ent = Spawn(HitscanProto, coords); + var ent = Spawn(HitscanProto, a.coordinates, rotation: a.angle); // WWDP EDIT var sprite = Comp(ent); - var xform = Transform(ent); - xform.LocalRotation = a.angle; sprite[EffectLayers.Unshaded].AutoAnimated = false; sprite.LayerSetSprite(EffectLayers.Unshaded, rsi); sprite.LayerSetState(EffectLayers.Unshaded, rsi.RsiState); diff --git a/Content.Client/_White/DollyMixture/DollyMixtureComponent.cs b/Content.Client/_White/DollyMixture/DollyMixtureComponent.cs deleted file mode 100644 index 1e6501778b..0000000000 --- a/Content.Client/_White/DollyMixture/DollyMixtureComponent.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Robust.Client.Graphics; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Text; -using System.Threading.Tasks; - -namespace Content.Client._White.DollyMixture; - -[RegisterComponent] -public sealed partial class DollyMixtureComponent : Component -{ - [DataField("sprite")] - public string RSIPath = ""; - - [DataField(required: true)] - public List States = default!; - - public RSI? RSI; - - [DataField] - public Vector2 LayerOffset = new(0, 1); - - [DataField] - public Vector2 Offset; - - public Angle LastAngle; - public List LayerIndices = new(); - - [DataField] - public int RepeatLayers = 1; - - [DataField] - public Vector2 LayerScale = Vector2.One; - - [DataField] - public string? DefaultShader; -} diff --git a/Content.Client/_White/DollyMixture/DollyMixtureSystem.cs b/Content.Client/_White/DollyMixture/DollyMixtureSystem.cs index d0e563bfae..3c4771682a 100644 --- a/Content.Client/_White/DollyMixture/DollyMixtureSystem.cs +++ b/Content.Client/_White/DollyMixture/DollyMixtureSystem.cs @@ -1,19 +1,25 @@ +using Content.Shared._White.DollyMixture; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.ResourceManagement; +using Robust.Shared.Timing; using System.Numerics; namespace Content.Client._White.DollyMixture; -public sealed class DollyMixtureSystem : EntitySystem +public sealed class DollyMixtureSystem : SharedDollyMixtureSystem { [Dependency] private readonly IResourceCache _res = default!; [Dependency] private readonly IEyeManager _eye = default!; [Dependency] private readonly SharedTransformSystem _xform = default!; + [Dependency] private readonly IGameTiming _timing = default!; public override void Initialize() { + base.Initialize(); SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnAutoState); } public override void FrameUpdate(float frameTime) @@ -22,85 +28,153 @@ public sealed class DollyMixtureSystem : EntitySystem while (query.MoveNext(out var uid, out var dollymix, out var sprite, out var xform)) { Angle angle = _xform.GetWorldRotation(xform) + _eye.CurrentEye.Rotation; + if (dollymix.DirectionCount > 0) + angle = Math.Round(angle / Math.Tau * dollymix.DirectionCount) * Math.Tau / dollymix.DirectionCount; + const float MinAngleDelta = MathF.PI / 180 * 0.01f; if (MathHelper.CloseTo(dollymix.LastAngle, angle, MinAngleDelta)) continue; dollymix.LastAngle = angle; - for (int i = 0; i < dollymix.LayerIndices.Count; i++) - { - sprite.LayerSetRotation(dollymix.LayerIndices[i], angle); - } + for (int i = 0; i < dollymix.LayerMappings.Count; i++) + sprite.LayerSetRotation(dollymix.LayerMappings[i], angle); } } + private void OnAutoState(EntityUid uid, DollyMixtureComponent comp, AfterAutoHandleStateEvent args) + { + UpdateDollyMixture(uid, comp); + } + + private void UpdateDollyMixture(EntityUid uid, DollyMixtureComponent comp) + { + if (comp.CurrentRSIPath == comp.RSIPath) + return; + + if (comp.RSIPath is null) + { + RemoveLayers(uid, comp); + return; + } + + if (comp.CurrentRSIPath is not null) + RemoveLayers(uid, comp); + + BuildLayers(uid, comp); + } + + private void OnRemove(EntityUid uid, DollyMixtureComponent comp, ComponentRemove args) + { + if (!_timing.IsFirstTimePredicted) + return; + + RemoveLayers(uid, comp); + } + // more than half of this method is handling missing shit. gg. private void OnInit(EntityUid uid, DollyMixtureComponent comp, ComponentInit args) { - if (!TryComp(uid, out var sprite)) - { + if (!_timing.IsFirstTimePredicted) + return; + + if (!TryComp(uid, out var sprite)) // unlike OnRemove() and RemoveLayers(), this doesn't get executed when placing a prototype + { // i cry Log.Error($"Failed to get SpriteComponent for {ToPrettyString(uid)}. Removing DollyMixtureComponent."); RemComp(uid); return; } - if (!TryComp(uid, out var xform)) + var xform = Transform(uid); + sprite.NoRotation = true; + + if (comp.RSIPath is not null) + BuildLayers(uid, comp, sprite); + } + + public override void Apply3D(EntityUid uid, string RsiPath, string? statePrefix = null, Vector2? layerOffset = null, DollyMixtureComponent? comp = null) + { + comp ??= EnsureComp(uid); + + base.Apply3D(uid, RsiPath, statePrefix, layerOffset, comp); + UpdateDollyMixture(uid, comp); + } + + public override void Remove3D(EntityUid uid, DollyMixtureComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + base.Remove3D(uid, comp); + UpdateDollyMixture(uid, comp); + } + + private void RemoveLayers(EntityUid uid, DollyMixtureComponent comp) + { + SpriteComponent? sprite = null; + if (!Resolve(uid, ref sprite, false)) // this gets executed after simply placing a prototype with this comp + return; // i assume it is some prediction-related bullshit + foreach (var layerMapping in comp.LayerMappings) + sprite.RemoveLayer(layerMapping); + comp.CurrentRSIPath = null; + comp.LayerMappings.Clear(); + } + + private void BuildLayers(EntityUid uid, DollyMixtureComponent comp, SpriteComponent? sprite = null) + { + if (string.IsNullOrEmpty(comp.RSIPath)) { - Log.Error($"Failed to get SpriteComponent for {ToPrettyString(uid)}. Removing DollyMixtureComponent."); - RemComp(uid); + Log.Error($"An empty rsi path was passed to BuildLayers()."); return; } - RSIResource? RSIres = null; - if (!string.IsNullOrEmpty(comp.RSIPath) && !_res.TryGetResource($"/Textures/{comp.RSIPath}", out RSIres)) + if (!Resolve(uid, ref sprite, false)) + return; + + var xform = Transform(uid); + if (!_res.TryGetResource($"/Textures/{comp.RSIPath}", out RSIResource? RSIres)) { - Log.Error($"Failed to get RSI {$"/Textures/{comp.RSIPath}"} for a dolly mixture component. Removing component. ({ToPrettyString(uid)})"); - RemComp(uid); + Log.Error($"Failed to get RSI {$"/Textures/{comp.RSIPath}"} for a dolly mixture component."); return; } - var RSI = RSIres?.RSI ?? sprite.BaseRSI; - if(RSI is null) - { - Log.Error($"No RSI specified for both DollyMixtureComponent and SpriteComponent. Removing DollyMixtureComponent. ({ToPrettyString(uid)})"); - RemComp(uid); - return; - } + var RSI = RSIres.RSI; - comp.RSI = RSI; - comp.LayerIndices = new(comp.States.Count); - - for (int i = 0; i < comp.States.Count; i++) + int i = 1; + while (RSI.TryGetState($"{comp.StatePrefix}{i}", out var state)) { - string stateId = comp.States[i]; - for (int repeat = 0; repeat < comp.RepeatLayers; repeat++) + for (int repeat = 0; repeat <= comp.RepeatLayers; repeat++) { - Vector2 layerOffset = comp.Offset / EyeManager.PixelsPerMeter + comp.LayerOffset / EyeManager.PixelsPerMeter * i; - layerOffset += comp.LayerOffset * ((float)repeat / comp.RepeatLayers); + float fraction = comp.RepeatLayers > 0 ? (float) repeat / comp.RepeatLayers : 0f; + + Vector2 layerOffset = comp.Offset / EyeManager.PixelsPerMeter + comp.LayerOffset / EyeManager.PixelsPerMeter * (i - 1 + fraction); int layerIndex = sprite.AddBlankLayer(); sprite.LayerSetRSI(layerIndex, RSI); - sprite.LayerSetState(layerIndex, stateId); + sprite.LayerSetState(layerIndex, state.StateId); sprite.LayerSetOffset(layerIndex, layerOffset); - sprite.LayerSetScale(layerIndex, comp.LayerScale); sprite.LayerSetRotation(layerIndex, xform.LocalRotation + _eye.CurrentEye.Rotation); - if (comp.DefaultShader is not null) - sprite.LayerSetShader(layerIndex, comp.DefaultShader); // crutch, need to assign a proper datadef for each dollymix layer instead of this. - comp.LayerIndices.Add(layerIndex); + if (comp.DefaultShader is string defaultshader) + sprite.LayerSetShader(layerIndex, defaultshader); // crutch for customghosts + string layerMap = $"dmm-{comp.StatePrefix}{i}({repeat}/{comp.RepeatLayers})"; + sprite.LayerMapSet(layerMap, layerIndex); + comp.LayerMappings.Add(layerMap); - if (sprite.BaseRSI?.TryGetState($"{stateId}-unshaded", out var unshadedState) ?? false) // todo: assign a proper datadef for each dollymix layer instead of this. + if (RSI.TryGetState($"{comp.StatePrefix}{i}-unshaded", out var unshadedState)) { layerIndex = sprite.AddBlankLayer(); sprite.LayerSetRSI(layerIndex, RSI); - sprite.LayerSetState(layerIndex, $"{stateId}-unshaded"); - sprite.LayerSetShader(layerIndex, "unshaded"); + sprite.LayerSetState(layerIndex, unshadedState.StateId); sprite.LayerSetOffset(layerIndex, layerOffset); - sprite.LayerSetScale(layerIndex, comp.LayerScale); sprite.LayerSetRotation(layerIndex, xform.LocalRotation + _eye.CurrentEye.Rotation); - comp.LayerIndices.Add(layerIndex); + sprite.LayerSetShader(layerIndex, "unshaded"); + layerMap = $"{layerMap}u"; + sprite.LayerMapSet(layerMap, layerIndex); + comp.LayerMappings.Add(layerMap); } } + i++; } - //sprite.GranularLayersRendering = true; + comp.CurrentRSIPath = comp.RSIPath; } } + diff --git a/Content.Client/_White/Guns/ModularTurretSystem.cs b/Content.Client/_White/Guns/ModularTurretSystem.cs new file mode 100644 index 0000000000..9db7a3b8f4 --- /dev/null +++ b/Content.Client/_White/Guns/ModularTurretSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._White.Guns.ModularTurret; + +namespace Content.Client._White.Guns; + +public sealed class ModularTurretSystem : SharedModularTurretSystem; diff --git a/Content.Server/Entry/IgnoredComponents.cs b/Content.Server/Entry/IgnoredComponents.cs index 13d7f6a600..3affeaa89c 100644 --- a/Content.Server/Entry/IgnoredComponents.cs +++ b/Content.Server/Entry/IgnoredComponents.cs @@ -21,7 +21,6 @@ namespace Content.Server.Entry "HolidayRsiSwap", "OptionsVisualizer", "ToggleableLightWieldable", // Goobstation - "DollyMixture", // WWDP EDIT "ItemSlotRenderer", // WWDP EDIT }; } diff --git a/Content.Server/Explosion/Components/SpawnOnTriggerComponent.cs b/Content.Server/Explosion/Components/SpawnOnTriggerComponent.cs index a8b36fbd84..0aa00c0abd 100644 --- a/Content.Server/Explosion/Components/SpawnOnTriggerComponent.cs +++ b/Content.Server/Explosion/Components/SpawnOnTriggerComponent.cs @@ -1,6 +1,7 @@ using Content.Server.Explosion.EntitySystems; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using System.Numerics; namespace Content.Server.Explosion.Components; @@ -9,4 +10,9 @@ public sealed partial class SpawnOnTriggerComponent : Component { [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] public string Proto = string.Empty; + + // WWDP EDIT START + [DataField] + public List Offsets = new() { Vector2.Zero }; + // WWDP EDIT END } diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index a18f3ef725..d02fe9aed6 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -141,8 +141,15 @@ namespace Content.Server.Explosion.EntitySystems if (!coords.IsValid(EntityManager)) return; - - Spawn(component.Proto, coords); + // WWDP EDIT START + if(component.Offsets.Count == 0) + { + Log.Warning($"SpawnOnTriggerComponent on {ToPrettyString(uid)} has empty offsets."); + return; + } + foreach(var offset in component.Offsets) + Spawn(component.Proto, new Robust.Shared.Map.EntityCoordinates(uid, offset)); + // WWDP EDIT END } private void HandleExplodeTrigger(EntityUid uid, ExplodeOnTriggerComponent component, TriggerEvent args) diff --git a/Content.Server/Language/LanguageSystem.cs b/Content.Server/Language/LanguageSystem.cs index 7b40d895d2..932bf27f7d 100644 --- a/Content.Server/Language/LanguageSystem.cs +++ b/Content.Server/Language/LanguageSystem.cs @@ -76,7 +76,7 @@ public sealed partial class LanguageSystem : SharedLanguageSystem // WWDP EDIT START // quick fix // todo: reimplement as an event handler on RemoteControllableComponent. - if(TryComp(ent.Owner, out var remoteControlTarget) && remoteControlTarget.User is { } controller) + if(TryComp(ent.Owner, out var remoteControlTarget) && remoteControlTarget.User is { } controller) return CanUnderstand(controller, language); // WWDP EDIT END return Resolve(ent, ref ent.Comp, logMissing: false) && ent.Comp.UnderstoodLanguages.Contains(language); @@ -89,7 +89,7 @@ public sealed partial class LanguageSystem : SharedLanguageSystem // WWDP EDIT START // quick fix // todo: reimplement as an event handler on RemoteControllableComponent. - if (TryComp(ent.Owner, out var remoteControlTarget) && remoteControlTarget.User is { } controller) + if (TryComp(ent.Owner, out var remoteControlTarget) && remoteControlTarget.User is { } controller) return CanSpeak(controller, language); // WWDP EDIT END return ent.Comp.SpokenLanguages.Contains(language); diff --git a/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs b/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs index 734cf9d89c..efe60462a5 100644 --- a/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs +++ b/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs @@ -23,7 +23,7 @@ namespace Content.Server.Power.EntitySystems if (TryComp(uid, out var batteryComp)) { - _batterySystem.SetMaxCharge(uid, MathF.Pow(component.MaxChargeMultiplier, powerCellRating - 1) * component.BaseMaxCharge, batteryComp); + _batterySystem.SetMaxCharge(uid, MathF.Pow(component.MaxChargeMultiplier, powerCellRating) * component.BaseMaxCharge, batteryComp); } } diff --git a/Content.Server/Salvage/SalvageSystem.Magnet.cs b/Content.Server/Salvage/SalvageSystem.Magnet.cs index 7d7845bf68..0ca3282e2a 100644 --- a/Content.Server/Salvage/SalvageSystem.Magnet.cs +++ b/Content.Server/Salvage/SalvageSystem.Magnet.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Numerics; using System.Threading.Tasks; +using Content.Server.Popups; using Content.Server.Salvage.Magnet; using Content.Shared._White.CCVar; using Content.Shared.Humanoid; diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs index cc9af0e490..72990110f3 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs @@ -1,12 +1,16 @@ using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; using Content.Server.Temperature.Components; using Content.Server.Temperature.Systems; +using Content.Shared._White.Guns; using Content.Shared.Damage; using Content.Shared.Damage.Events; using Content.Shared.FixedPoint; +using Content.Shared.PowerCell.Components; using Content.Shared.Projectiles; using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged.Components; +using Robust.Shared.Containers; using Robust.Shared.Prototypes; namespace Content.Server.Weapons.Ranged.Systems; @@ -28,6 +32,18 @@ public sealed partial class GunSystem SubscribeLocalEvent(OnBatteryStartup); SubscribeLocalEvent(OnBatteryChargeChange); SubscribeLocalEvent(OnBatteryDamageExamine); + //// WWDP EDIT START + SubscribeLocalEvent(OnBatteryStartup); + SubscribeLocalEvent(OnContainerBatteryInserted); + SubscribeLocalEvent(OnContainerBatteryRemoved); + SubscribeLocalEvent(OnBatteryDamageExamine); + SubscribeLocalEvent(OnBatteryChargeChangeTracker); + + SubscribeLocalEvent(OnBatteryStartup); + SubscribeLocalEvent(OnContainerBatteryInserted); + SubscribeLocalEvent(OnContainerBatteryRemoved); + SubscribeLocalEvent(OnBatteryDamageExamine); + //// WWDP EDIT END } private void OnBatteryStartup(EntityUid uid, BatteryAmmoProviderComponent component, ComponentStartup args) @@ -42,7 +58,8 @@ public sealed partial class GunSystem public void UpdateShots(EntityUid uid, BatteryAmmoProviderComponent component) // WWDP EDIT - private -> public { - if (!TryComp(uid, out var battery)) + var batteryUid = component is ContainerBatteryAmmoProviderComponent ? Transform(uid).ParentUid : uid; // WWDP EDIT + if (!TryComp(batteryUid, out var battery)) // WWDP EDIT return; UpdateShots(uid, component, battery.CurrentCharge, battery.MaxCharge); @@ -108,7 +125,44 @@ public sealed partial class GunSystem protected override void TakeCharge(EntityUid uid, BatteryAmmoProviderComponent component) { + if(component is ContainerBatteryAmmoProviderComponent comp) + { + uid = comp.Linked!.Value; // the validity of this should be enforced by EntGotInserted/Removed event handlers below. + } // Will raise ChargeChangedEvent _battery.UseCharge(uid, component.FireCost); } + + // WWDP EDIT START + private void OnContainerBatteryInserted(EntityUid uid, ContainerBatteryAmmoProviderComponent comp, EntGotInsertedIntoContainerMessage args) + { + var contUid = args.Container.Owner; + var tracker = EnsureComp(contUid); + tracker.Linked.Add(uid); + comp.Linked = contUid; + UpdateShots(uid, comp); + } + + private void OnContainerBatteryRemoved(EntityUid uid, ContainerBatteryAmmoProviderComponent comp, EntGotRemovedFromContainerMessage args) + { + var contUid = args.Container.Owner; + var tracker = Comp(contUid); // intended to throw on failure, should not happen + tracker.Linked.Remove(uid); + comp.Linked = null; + if (tracker.Linked.Count == 0) + RemComp(contUid, tracker); + UpdateShots(uid, comp, 0, 0); + } + + private void OnBatteryChargeChangeTracker(EntityUid uid, ContainerBatteryAmmoTrackerComponent comp, ref ChargeChangedEvent args) + { + foreach (var gunUid in comp.Linked) + { + if(TryComp(gunUid, out var projectileAmmoProvider)) + UpdateShots(gunUid, projectileAmmoProvider, args.Charge, args.MaxCharge); + else if(TryComp(gunUid, out var hitscanAmmoProvider)) + UpdateShots(gunUid, hitscanAmmoProvider, args.Charge, args.MaxCharge); + } + } + // WWDP EDIT END } diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index 8ab8fcc9df..c2b4d92643 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -25,8 +25,8 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; using Robust.Shared.Containers; -using Content.Shared._Lavaland.Weapons.Ranged.Events; -using ProjectileShotEvent = Content.Shared._Lavaland.Weapons.Ranged.Events.ProjectileShotEvent; // Lavaland Change +using ProjectileShotEvent = Content.Shared._Lavaland.Weapons.Ranged.Events.ProjectileShotEvent; +using Content.Shared.Mech.Components; namespace Content.Server.Weapons.Ranged.Systems; @@ -71,6 +71,13 @@ public sealed partial class GunSystem : SharedGunSystem EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, out bool userImpulse, EntityUid? user = null, bool throwItems = false) { userImpulse = true; + // WWDP EDIT START // All code related to mechs is fucking vile. + var trueUser = user; + if(TryComp(user, out var mechComp)) + { + trueUser = mechComp.PilotSlot.ContainedEntity; + } + // WWDP EDIT END if (user != null) { @@ -157,66 +164,64 @@ public sealed partial class GunSystem : SharedGunSystem EntityUid? lastHit = null; var from = fromMap; - // can't use map coords above because funny FireEffects - var fromEffect = fromCoordinates; + // can't use map coords above because funny FireEffects // my brother in christ, you wrote that method var dir = mapDirection.Normalized(); - //in the situation when user == null, means that the cannon fires on its own (via signals). And we need the gun to not fire by itself in this case var lastUser = user ?? gunUid; - - if (hitscan.Reflective != ReflectType.None) + RayCastResults? lastResult = null; // WWDP EDIT + for (var reflectAttempt = 0; reflectAttempt < 3; reflectAttempt++) { - for (var reflectAttempt = 0; reflectAttempt < 3; reflectAttempt++) + var ray = new CollisionRay(from.Position, dir, hitscan.CollisionMask); + var rayCastResults = + Physics.IntersectRay(from.MapId, ray, hitscan.MaxLength, lastUser, false).ToList(); + if (!rayCastResults.Any()) + break; + + var raycastEvent = new HitScanAfterRayCastEvent(rayCastResults); + RaiseLocalEvent(lastUser, ref raycastEvent); + + if (raycastEvent.RayCastResults == null) + break; + + var result = raycastEvent.RayCastResults[0]; + lastResult = result; // WWDP EDIT + // Check if laser is shot from in a container + if (!_container.IsEntityOrParentInContainer(lastUser)) { - var ray = new CollisionRay(from.Position, dir, hitscan.CollisionMask); - var rayCastResults = - Physics.IntersectRay(from.MapId, ray, hitscan.MaxLength, lastUser, false).ToList(); - if (!rayCastResults.Any()) - break; - - var raycastEvent = new HitScanAfterRayCastEvent(rayCastResults); - RaiseLocalEvent(lastUser, ref raycastEvent); - - if (raycastEvent.RayCastResults == null) - break; - - var result = raycastEvent.RayCastResults[0]; - - // Check if laser is shot from in a container - if (!_container.IsEntityOrParentInContainer(lastUser)) + // Checks if the laser should pass over unless targeted by its user + foreach (var collide in rayCastResults) { - // Checks if the laser should pass over unless targeted by its user - foreach (var collide in rayCastResults) + if (collide.HitEntity != gun.Target && + CompOrNull(collide.HitEntity)?.Active == true) { - if (collide.HitEntity != gun.Target && - CompOrNull(collide.HitEntity)?.Active == true) - { - continue; - } - - result = collide; - break; + continue; } - } - var hit = result.HitEntity; - lastHit = hit; - - FireEffects(fromEffect, result.Distance, dir.Normalized().ToAngle(), hitscan, hit); - - var ev = new HitScanReflectAttemptEvent(user, gunUid, hitscan.Reflective, dir, false, hitscan.Damage); // WD EDIT - RaiseLocalEvent(hit, ref ev); - - if (!ev.Reflected) + result = collide; break; - - fromEffect = Transform(hit).Coordinates; - from = fromEffect.ToMap(EntityManager, _transform); - dir = ev.Direction; - lastUser = hit; + } } + + var hit = result.HitEntity; + lastHit = hit; + + FireEffects(from, result.Distance, dir.Normalized().ToAngle(), hitscan, hit); + + if (hitscan.Reflective == ReflectType.None) // WWDP EDIT + break; // WWDP EDIT + + var ev = new HitScanReflectAttemptEvent(user, gunUid, hitscan.Reflective, dir, false, hitscan.Damage); // WD EDIT + RaiseLocalEvent(hit, ref ev); + + if (!ev.Reflected) + break; + + from = _transform.GetMapCoordinates(hit); // WWDP EDIT + dir = ev.Direction; + lastUser = hit; } + if (lastHit != null) { var hitEntity = lastHit.Value; @@ -246,21 +251,33 @@ public sealed partial class GunSystem : SharedGunSystem if (user != null) { Logs.Add(LogType.HitScanHit, - $"{ToPrettyString(user.Value):user} hit {hitName:target} using hitscan and dealt {dmg.GetTotal():damage} damage"); + $"{ToPrettyString(user.Value):user} hit {hitName:target} using hitscan ({hitscan.ID}) and dealt {dmg.GetTotal():damage} damage"); } else { Logs.Add(LogType.HitScanHit, - $"{hitName:target} hit by hitscan dealing {dmg.GetTotal():damage} damage"); + $"{hitName:target} hit by hitscan ({hitscan.ID}) dealing {dmg.GetTotal():damage} damage"); } } + // WWDP EDIT START + if (hitscan.SpawnAtImpact is EntProtoId impactEntity) + { + Angle ang = hitscan.ImpactSpawnRandomAngle ? Random.NextAngle() : dir.ToAngle() - Math.PI/2; + Spawn(impactEntity, new MapCoordinates(lastResult!.Value.HitPos, from.MapId), rotation: ang); + } + // WWDP EDIT END } else { - FireEffects(fromEffect, hitscan.MaxLength, dir.ToAngle(), hitscan); + FireEffects(from, hitscan.MaxLength, dir.ToAngle(), hitscan); + // WWDP EDIT START + Angle ang = hitscan.ImpactSpawnRandomAngle ? Random.NextAngle() : dir.ToAngle() - Math.PI/2; + if (hitscan.SpawnAtMaxLength is EntProtoId impactEntity) + Spawn(impactEntity, from.Offset(dir * hitscan.MaxLength), rotation: ang); + // WWDP EDIT END } - Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user); + Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, trueUser); // WWDP EDIT break; default: throw new ArgumentOutOfRangeException(); @@ -330,8 +347,8 @@ public sealed partial class GunSystem : SharedGunSystem } SpreadBreak: - MuzzleFlash(gunUid, ammoComp, mapDirection.ToAngle(), user); - Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user); + MuzzleFlash(gunUid, ammoComp, mapDirection.ToAngle(), trueUser); // WWDP EDIT + Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, trueUser); // WWDP EDIT } } @@ -444,55 +461,37 @@ public sealed partial class GunSystem : SharedGunSystem // TODO: Pseudo RNG so the client can predict these. #region Hitscan effects - private void FireEffects(EntityCoordinates fromCoordinates, float distance, Angle mapDirection, HitscanPrototype hitscan, EntityUid? hitEntity = null) + private void FireEffects(MapCoordinates fromCoordinates, float distance, Angle mapDirection, HitscanPrototype hitscan, EntityUid? hitEntity = null) { // Lord - // Forgive me for the shitcode I am about to do + // Forgive me for the shitcode I am about to do // https://www.youtube.com/watch?v=sCAdVQNaDTE go fuck yourself // Effects tempt me not - var sprites = new List<(NetCoordinates coordinates, Angle angle, SpriteSpecifier sprite, float scale)>(); - var gridUid = fromCoordinates.GetGridUid(EntityManager); + var sprites = new List<(MapCoordinates coordinates, Angle angle, SpriteSpecifier sprite, float scale)>(); + var angle = mapDirection; - // We'll get the effects relative to the grid / map of the firer - // Look you could probably optimise this a bit with redundant transforms at this point. - var xformQuery = GetEntityQuery(); - - if (xformQuery.TryGetComponent(gridUid, out var gridXform)) - { - var (_, gridRot, gridInvMatrix) = TransformSystem.GetWorldPositionRotationInvMatrix(gridXform, xformQuery); - - fromCoordinates = new EntityCoordinates(gridUid.Value, - Vector2.Transform(fromCoordinates.ToMapPos(EntityManager, TransformSystem), gridInvMatrix)); - - // Use the fallback angle I guess? - angle -= gridRot; - } - if (distance >= 1f) { if (hitscan.MuzzleFlash != null) { var coords = fromCoordinates.Offset(angle.ToVec().Normalized() / 2); - var netCoords = GetNetCoordinates(coords); - sprites.Add((netCoords, angle, hitscan.MuzzleFlash, 1f)); + sprites.Add((coords, angle, hitscan.MuzzleFlash, 1f)); } if (hitscan.TravelFlash != null) { var coords = fromCoordinates.Offset(angle.ToVec() * (distance + 0.5f) / 2); - var netCoords = GetNetCoordinates(coords); - sprites.Add((netCoords, angle, hitscan.TravelFlash, distance - 1.5f)); + sprites.Add((coords, angle, hitscan.TravelFlash, distance - 1.5f)); } } if (hitscan.ImpactFlash != null) { var coords = fromCoordinates.Offset(angle.ToVec() * distance); - var netCoords = GetNetCoordinates(coords); - sprites.Add((netCoords, angle.FlipPositive(), hitscan.ImpactFlash, 1f)); + sprites.Add((coords, angle.FlipPositive(), hitscan.ImpactFlash, 1f)); } if (sprites.Count > 0) @@ -500,7 +499,7 @@ public sealed partial class GunSystem : SharedGunSystem RaiseNetworkEvent(new HitscanEvent { Sprites = sprites, - }, Filter.Pvs(fromCoordinates, entityMan: EntityManager)); + }, Filter.Pvs(fromCoordinates)); } } diff --git a/Content.Server/_White/DollyMixture/DollyMixtureSystem.cs b/Content.Server/_White/DollyMixture/DollyMixtureSystem.cs new file mode 100644 index 0000000000..4c3dd524e1 --- /dev/null +++ b/Content.Server/_White/DollyMixture/DollyMixtureSystem.cs @@ -0,0 +1,8 @@ +using Content.Shared._White.DollyMixture; + +namespace Content.Server._White.DollyMixture; + +public sealed class DollyMixtureSystem : SharedDollyMixtureSystem +{ + +} diff --git a/Content.Server/_White/Guns/ModularTurret/ModularTurretSystem.cs b/Content.Server/_White/Guns/ModularTurret/ModularTurretSystem.cs new file mode 100644 index 0000000000..7bfb27af20 --- /dev/null +++ b/Content.Server/_White/Guns/ModularTurret/ModularTurretSystem.cs @@ -0,0 +1,53 @@ +using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; +using Content.Shared._White.Guns.ModularTurret; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; + +namespace Content.Server._White.Guns.ModularTurret; + +public sealed class ModularTurretSystem : SharedModularTurretSystem +{ + [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly ItemSlotsSystem _slot = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnModularTurretShotAttempt); + SubscribeLocalEvent(OnModularTurretWeaponShot); + } + + + private void OnModularTurretShotAttempt(EntityUid turretUid, ModularTurretComponent comp, ref ShotAttemptedEvent args) + { + RechargeWeapon(turretUid, args.Used); + } + + private void OnModularTurretWeaponShot(EntityUid gunUid, ModularTurretWeaponComponent comp, ref GunShotEvent args) + { + if(comp.CurrentTurretHolder is EntityUid turretUid) + RechargeWeapon(turretUid, gunUid); + } + + + private void RechargeWeapon(EntityUid turretUid, EntityUid gunUid) + { + if (!HasComp(gunUid)) + return; + + //var turretComp = Comp(turretUid); + if (!TryComp(gunUid, out var gunBattery) || // || !turretComp.CanChargeWeapon + !TryComp(turretUid, out var turretBattery)) + return; + + float missing = gunBattery.MaxCharge - gunBattery.CurrentCharge; + + float recharged = -_battery.UseCharge(turretUid, missing, turretBattery); + + _battery.SetCharge(gunUid, gunBattery.CurrentCharge + recharged, gunBattery); + } +} + diff --git a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Console.cs b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Console.cs index 5ba44fc874..bc1fbd5b50 100644 --- a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Console.cs +++ b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Console.cs @@ -13,12 +13,14 @@ public partial class RemoteControlSystem { private void InitializeConsole() { + SubscribeLocalEvent(OnConsoleInit); SubscribeLocalEvent(OnConsoleMapInit); SubscribeLocalEvent(OnConsoleShutdown); SubscribeLocalEvent(OnActivateInWorld); SubscribeLocalEvent(OnUseInHand); + SubscribeLocalEvent(OnNewLinkAttempt); SubscribeLocalEvent(OnNewLink); SubscribeLocalEvent(OnPortDisconnected); @@ -27,13 +29,14 @@ public partial class RemoteControlSystem SubscribeLocalEvent(OnPowerChanged); } + private void OnConsoleInit(EntityUid uid, RemoteControlConsoleComponent comp, ComponentInit args) + { + _link.EnsureSourcePorts(uid, SourcePortId); + } + private void OnConsoleMapInit(EntityUid uid, RemoteControlConsoleComponent component, MapInitEvent args) { - EntityUid? actionUid = null; - _action.AddAction(uid, ref actionUid, component.SwitchToNextAction); - - if (actionUid.HasValue) - component.SwitchToNextActionUid = actionUid.Value; + _action.AddAction(uid, ref component.SwitchToNextActionUid, component.SwitchToNextAction); } private void OnConsoleShutdown(EntityUid uid, RemoteControlConsoleComponent component, ComponentShutdown args) @@ -50,16 +53,22 @@ public partial class RemoteControlSystem private void OnActivateInWorld(EntityUid uid, RemoteControlConsoleComponent component, ActivateInWorldEvent args) => TryActivate(uid, component, args.User); - private void OnNewLink(EntityUid uid, RemoteControlConsoleComponent component, NewLinkEvent args) + private void OnNewLinkAttempt(EntityUid uid, RemoteControlConsoleComponent component, LinkAttemptEvent args) { - if (!_whitelist.CheckBoth(args.Sink, component.Blacklist, component.Whitelist) - || args.Source != uid - || args.SourcePort != SourcePortId - || args.SinkPort != SinkPortId - || !HasComp(args.Sink)) + if (args.Source != uid || args.SourcePort != SourcePortId) return; - component.LinkedEntities.Add(args.Sink); + if (!HasComp(args.Sink) || + !_whitelist.CheckBoth(args.Sink, component.Blacklist, component.Whitelist) || + args.Source != uid || + args.SourcePort != SourcePortId || + args.SinkPort != SinkPortId) + args.Cancel(); + } + private void OnNewLink(EntityUid uid, RemoteControlConsoleComponent component, NewLinkEvent args) + { + if (args.Source == uid && args.SourcePort == SourcePortId) + component.LinkedEntities.Add(args.Sink); } private void OnPortDisconnected(EntityUid uid, RemoteControlConsoleComponent component, PortDisconnectedEvent args) @@ -71,7 +80,7 @@ public partial class RemoteControlSystem // the device link got severed while the turret was in use; either relink to another turret or kick the user out of the console. if (component.User is { } user - && TryComp(user, out var controlling) + && TryComp(user, out var controlling) && controlling.Target == args.RemovedPortUid) EndRemoteControl(user, (uid, component), true); } @@ -90,7 +99,7 @@ public partial class RemoteControlSystem private void TryActivate(EntityUid uid, RemoteControlConsoleComponent component, EntityUid user) { if (!this.IsPowered(uid, EntityManager) - || HasComp(user) + || HasComp(user) || component.User is not null || component.LinkedEntities.Count == 0 || GetFirstValid(component) is not { } target) @@ -101,7 +110,7 @@ public partial class RemoteControlSystem private bool TrySwitchToNextAvailable(EntityUid console, RemoteControlConsoleComponent component) { - if (component.User is not { } user || GetFirstValid(component, component.Target) is not {} target) + if (component.User is not { } user || GetFirstValid(component, component.Target) is not { } target) return false; component.LastIndex = component.LinkedEntities.IndexOf(target); @@ -123,7 +132,7 @@ public partial class RemoteControlSystem var ent = list[index]; if ((!exclude.HasValue || ent != exclude) - && HasComp(ent) + && HasComp(ent) || TryComp(ent, out var mindContainer) && mindContainer.HasMind) return ent; diff --git a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Target.cs b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Target.cs index b3ff840e4d..f0bfab34c3 100644 --- a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Target.cs +++ b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.Target.cs @@ -11,19 +11,19 @@ public partial class RemoteControlSystem { private void InitializeTarget() { - SubscribeLocalEvent(OnTargetMapInit); - SubscribeLocalEvent(OnTargetShutdown); + SubscribeLocalEvent(OnTargetMapInit); + SubscribeLocalEvent(OnTargetShutdown); - SubscribeLocalEvent(OnTargetSpeechSourceOverride); + SubscribeLocalEvent(OnTargetSpeechSourceOverride); - SubscribeLocalEvent>(GetAltVerb); + SubscribeLocalEvent>(GetAltVerb); - SubscribeLocalEvent(OnTargetMobStateChanged); + SubscribeLocalEvent(OnTargetMobStateChanged); - SubscribeLocalEvent(OnExitAction); + SubscribeLocalEvent(OnExitAction); } - private void OnTargetMapInit(EntityUid uid, RemoteControlTargetComponent comp, MapInitEvent args) + private void OnTargetMapInit(EntityUid uid, RemoteControllableComponent comp, MapInitEvent args) { EntityUid? actionUid = null; _action.AddAction(uid, ref actionUid, comp.EndRemoteControlAction); @@ -32,11 +32,11 @@ public partial class RemoteControlSystem comp.EndRemoteControlActionUid = actionUid.Value; } - private void OnTargetShutdown(EntityUid uid, RemoteControlTargetComponent comp, ComponentShutdown args) + private void OnTargetShutdown(EntityUid uid, RemoteControllableComponent comp, ComponentShutdown args) { _action.RemoveAction(uid, comp.EndRemoteControlActionUid); - if (!TryComp(comp.User, out var userComponent)) + if (!TryComp(comp.User, out var userComponent)) return; if (TryComp(userComponent.Console, out var consoleComponent)) @@ -45,15 +45,15 @@ public partial class RemoteControlSystem EndRemoteControl((comp.User.Value, userComponent), (uid, comp), true); } - private void OnTargetSpeechSourceOverride(EntityUid uid, RemoteControlTargetComponent comp, SpeechSourceOverrideEvent args) + private void OnTargetSpeechSourceOverride(EntityUid uid, RemoteControllableComponent comp, SpeechSourceOverrideEvent args) { if (comp.User is { } user) args.Override = user; } - private void GetAltVerb(EntityUid uid, RemoteControlTargetComponent component, GetVerbsEvent args) + private void GetAltVerb(EntityUid uid, RemoteControllableComponent component, GetVerbsEvent args) { - if (!component.CanManually || !args.CanAccess || !args.CanInteract || !args.CanComplexInteract) + if (!component.ManualControl || !args.CanAccess || !args.CanInteract || !args.CanComplexInteract) return; args.Verbs.Add( @@ -82,13 +82,13 @@ public partial class RemoteControlSystem } - private void OnExitAction(EntityUid uid, RemoteControlTargetComponent component, RemoteControlExitActionEvent args) + private void OnExitAction(EntityUid uid, RemoteControllableComponent component, RemoteControlExitActionEvent args) { if(component.User is not null) EndRemoteControl(component.User.Value, (uid, component)); } - private void OnTargetMobStateChanged(EntityUid uid, RemoteControlTargetComponent component, MobStateChangedEvent args) + private void OnTargetMobStateChanged(EntityUid uid, RemoteControllableComponent component, MobStateChangedEvent args) { if (args.NewMobState != MobState.Alive && component.User.HasValue) EndRemoteControl(component.User.Value, (uid, component), true); diff --git a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.User.cs b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.User.cs index ff8c2f0361..f09677e27b 100644 --- a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.User.cs +++ b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.User.cs @@ -7,18 +7,18 @@ public partial class RemoteControlSystem { private void InitializeUser() { - SubscribeLocalEvent(OnUserShutdown); + SubscribeLocalEvent(OnUserShutdown); - SubscribeLocalEvent(OnUserMobStateChanged); + SubscribeLocalEvent(OnUserMobStateChanged); } - private void OnUserShutdown(EntityUid uid, RemoteControlUserComponent comp, ComponentShutdown args) + private void OnUserShutdown(EntityUid uid, RemoteControllingComponent comp, ComponentShutdown args) { - if (TryComp(comp.Target, out var targetComp) && targetComp.User == uid) + if (TryComp(comp.Target, out var targetComp) && targetComp.User == uid) EndRemoteControl((uid, comp), (comp.Target, targetComp)); } - private void OnUserMobStateChanged(EntityUid uid, RemoteControlUserComponent comp, MobStateChangedEvent args) + private void OnUserMobStateChanged(EntityUid uid, RemoteControllingComponent comp, MobStateChangedEvent args) { if (args.NewMobState != MobState.Alive) EndRemoteControl((uid, comp)); diff --git a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.cs b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.cs index 7a286972a5..d63e2c0d4a 100644 --- a/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.cs +++ b/Content.Server/_White/RemoteControl/Systems/RemoteControlSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Actions; using Content.Server.Chat.Systems; +using Content.Server.DeviceLinking.Systems; using Content.Server.Interaction; using Content.Server.Mind; using Content.Server.Popups; @@ -13,11 +14,13 @@ using Content.Shared.Whitelist; using Robust.Server.GameObjects; using Robust.Shared.Player; using Robust.Shared.Prototypes; +using Robust.Shared.Utility; namespace Content.Server._White.RemoteControl.Systems; public sealed partial class RemoteControlSystem : EntitySystem { + [Dependency] private readonly DeviceLinkSystem _link = default!; [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; [Dependency] private readonly ActionsSystem _action = default!; [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; @@ -27,8 +30,8 @@ public sealed partial class RemoteControlSystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly TransformSystem _transform = default!; - public static ProtoId SinkPortId = "RemoteControlOutputPort"; - public static ProtoId SourcePortId = "RemoteControlInputPort"; + public static ProtoId SinkPortId = "RemoteControlSinkPort"; + public static ProtoId SourcePortId = "RemoteControlSourcePort"; public override void Initialize() { @@ -44,7 +47,7 @@ public sealed partial class RemoteControlSystem : EntitySystem { var sourceXform = Transform(args.Source); - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); while (query.MoveNext(out _, out var comp, out var xform)) { var range = xform.MapID != sourceXform.MapID @@ -61,7 +64,7 @@ public sealed partial class RemoteControlSystem : EntitySystem public override void Update(float frameTime) { - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp)) { if(!_actionBlocker.CanInteract(uid, comp.Console) @@ -70,17 +73,17 @@ public sealed partial class RemoteControlSystem : EntitySystem } } - private bool RemoteControl(Entity user, Entity target, Entity console, bool overlay = false) + private bool RemoteControl(EntityUid user, Entity target, Entity console, bool overlay = false) { if (!Resolve(target, ref target.Comp) - || HasComp(user) + || HasComp(user) || HasComp(target) || _mind.GetMind(user) is not { } userMind) return false; - user.Comp = EnsureComp(user); - user.Comp.Target = target; - user.Comp.Console = console; + var userComp = EnsureComp(user); + userComp.Target = target; + userComp.Console = console; target.Comp.User = user; @@ -89,8 +92,8 @@ public sealed partial class RemoteControlSystem : EntitySystem console.Comp.User = user; console.Comp.Target = target; console.Comp.LastIndex = console.Comp.LinkedEntities.IndexOf(target); - - _action.AddAction(target, console.Comp.SwitchToNextActionUid, console); + DebugTools.Assert(console.Comp.SwitchToNextActionUid.HasValue); + _action.AddAction(target, console.Comp.SwitchToNextActionUid.Value, console); } _mind.Visit(userMind, target); @@ -103,7 +106,7 @@ public sealed partial class RemoteControlSystem : EntitySystem return true; } - private bool EndRemoteControl(Entity user, bool shouldAutoSwitch = false) + private bool EndRemoteControl(Entity user, bool shouldAutoSwitch = false) { if (!Resolve(user, ref user.Comp)) return false; @@ -111,11 +114,7 @@ public sealed partial class RemoteControlSystem : EntitySystem return EndRemoteControl(user, user.Comp.Target, user.Comp.Console, shouldAutoSwitch); } - private bool EndRemoteControl( - Entity user, - Entity target, - bool shouldAutoSwitch = false - ) + private bool EndRemoteControl(Entity user, Entity target, bool shouldAutoSwitch = false) { if (!Resolve(user, ref user.Comp) || !Resolve(target, ref target.Comp)) return false; @@ -123,11 +122,7 @@ public sealed partial class RemoteControlSystem : EntitySystem return EndRemoteControl(user, target, user.Comp.Console, shouldAutoSwitch); } - private bool EndRemoteControl( - Entity user, - Entity console, - bool shouldAutoSwitch = false - ) + private bool EndRemoteControl(Entity user, Entity console, bool shouldAutoSwitch = false ) { if (!Resolve(user, ref user.Comp) || !Resolve(console, ref console.Comp)) return false; @@ -135,12 +130,7 @@ public sealed partial class RemoteControlSystem : EntitySystem return EndRemoteControl(user, user.Comp.Target, console, shouldAutoSwitch); } - private bool EndRemoteControl( - Entity user, - Entity target, - Entity console, - bool shouldAutoSwitch = false - ) + private bool EndRemoteControl(Entity user, Entity target, Entity console, bool shouldAutoSwitch = false ) { if (!Resolve(user, ref user.Comp) || !Resolve(target, ref target.Comp) diff --git a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs index f977a2eeb4..f16ac85777 100644 --- a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs +++ b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs @@ -31,6 +31,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Inventory.VirtualItem; using Robust.Shared.Configuration; using Content.Shared.Implants.Components; +using Content.Shared.Weapons.Ranged.Systems; namespace Content.Shared.Mech.EntitySystems; @@ -75,6 +76,7 @@ public abstract class SharedMechSystem : EntitySystem SubscribeLocalEvent(OnAttackAttempt); SubscribeLocalEvent(OnEntGotRemovedFromContainer); SubscribeLocalEvent(OnShotAttempted); // Goobstation + SubscribeLocalEvent(OnGunShot); // WWDP EDIT Subs.CVar(_config, GoobCVars.MechGunOutsideMech, value => _canUseMechGunOutside = value, true); // Goobstation } @@ -509,6 +511,14 @@ public abstract class SharedMechSystem : EntitySystem RaiseLocalEvent(uid, ev); } + // WWDP EDIT START + private void OnGunShot(EntityUid uid, MechEquipmentComponent component, ref GunShotEvent args) + { + var ev = new HandleMechEquipmentBatteryEvent(); + RaiseLocalEvent(uid, ev); + } + // WWDP EDIT END + private void UpdateAppearance(EntityUid uid, MechComponent? component = null, AppearanceComponent? appearance = null) { diff --git a/Content.Shared/Movement/Components/InputMoverComponent.cs b/Content.Shared/Movement/Components/InputMoverComponent.cs index 40cb532e60..16c712f3f8 100644 --- a/Content.Shared/Movement/Components/InputMoverComponent.cs +++ b/Content.Shared/Movement/Components/InputMoverComponent.cs @@ -32,7 +32,7 @@ namespace Content.Shared.Movement.Components // We change which vector we write into based on whether we were sprinting after the previous input. // (well maybe we do but the code is designed such that MoverSystem applies movement speed) // (and I'm not changing that) - + /// /// Should our velocity be applied to our parent? /// diff --git a/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs b/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs index e5e52a3e47..4209c47b82 100644 --- a/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs +++ b/Content.Shared/Radio/Components/SharedRadioJammerComponent.cs @@ -30,20 +30,20 @@ public sealed partial class RadioJammerComponent : Component /// to this setting. /// [DataField(required: true)] - public LocId Message = string.Empty; + public LocId Message; /// /// Name of the setting. /// [DataField(required: true)] - public LocId Name = string.Empty; + public LocId Name; } /// /// List of all the settings for the radio jammer. /// [DataField(required: true), ViewVariables(VVAccess.ReadOnly)] - public RadioJamSetting[] Settings; + public RadioJamSetting[] Settings = default!; /// /// Index of the currently selected setting. diff --git a/Content.Shared/Shuttles/Systems/SharedShuttleSystem.IFF.cs b/Content.Shared/Shuttles/Systems/SharedShuttleSystem.IFF.cs index e435bc1c4c..ba0a546c77 100644 --- a/Content.Shared/Shuttles/Systems/SharedShuttleSystem.IFF.cs +++ b/Content.Shared/Shuttles/Systems/SharedShuttleSystem.IFF.cs @@ -87,6 +87,7 @@ public abstract partial class SharedShuttleSystem UpdateIFFInterfaces(gridUid, component); } + [PublicAPI] public void RemoveIFFFlag(EntityUid gridUid, IFFFlags flags, IFFComponent? component = null) { diff --git a/Content.Shared/Weapons/Ranged/HitscanPrototype.cs b/Content.Shared/Weapons/Ranged/HitscanPrototype.cs index a5063e3ab5..6f2163857c 100644 --- a/Content.Shared/Weapons/Ranged/HitscanPrototype.cs +++ b/Content.Shared/Weapons/Ranged/HitscanPrototype.cs @@ -43,6 +43,15 @@ public sealed partial class HitscanPrototype : IPrototype, IShootable [DataField("sound")] public SoundSpecifier? Sound; + [DataField] + public EntProtoId? SpawnAtImpact = null; + + [DataField] + public EntProtoId? SpawnAtMaxLength = null; + + [DataField] + public bool ImpactSpawnRandomAngle = false; + /// /// Force the hitscan sound to play rather than potentially playing the entity's sound. /// diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Battery.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Battery.cs index f44273257d..c0e496e663 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Battery.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Battery.cs @@ -1,3 +1,4 @@ +using Content.Shared._White.Guns; using Content.Shared.Examine; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; @@ -25,6 +26,21 @@ public abstract partial class SharedGunSystem SubscribeLocalEvent(OnBatteryTakeAmmo); SubscribeLocalEvent(OnBatteryAmmoCount); SubscribeLocalEvent(OnBatteryExamine); + + // WWDP EDIT START + // Container, Projectile + SubscribeLocalEvent(OnBatteryGetState); + SubscribeLocalEvent(OnBatteryHandleState); + SubscribeLocalEvent(OnBatteryTakeAmmo); + SubscribeLocalEvent(OnBatteryAmmoCount); + //SubscribeLocalEvent(OnBatteryExamine); // you'll have trouble examining something inside a container + + // Container, Hitscan + SubscribeLocalEvent(OnBatteryGetState); + SubscribeLocalEvent(OnBatteryHandleState); + SubscribeLocalEvent(OnBatteryTakeAmmo); + SubscribeLocalEvent(OnBatteryAmmoCount); + // WWDP EDIT END } private void OnBatteryHandleState(EntityUid uid, BatteryAmmoProviderComponent component, ref ComponentHandleState args) @@ -109,6 +125,11 @@ public abstract partial class SharedGunSystem return (ent, EnsureShootable(ent)); case HitscanBatteryAmmoProviderComponent hitscan: return (null, ProtoManager.Index(hitscan.Prototype)); + case ProjectileContainerBatteryAmmoProviderComponent proj: + var entc = Spawn(proj.Prototype, coordinates); + return (entc, EnsureShootable(entc)); + case HitscanContainerBatteryAmmoProviderComponent hitscan: + return (null, ProtoManager.Index(hitscan.Prototype)); default: throw new ArgumentOutOfRangeException(); } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 7021f0d817..13fd2985dc 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -707,7 +707,7 @@ public abstract partial class SharedGunSystem : EntitySystem [Serializable, NetSerializable] public sealed class HitscanEvent : EntityEventArgs { - public List<(NetCoordinates coordinates, Angle angle, SpriteSpecifier Sprite, float Distance)> Sprites = new(); + public List<(MapCoordinates coordinates, Angle angle, SpriteSpecifier Sprite, float Distance)> Sprites = new(); // WWDP EDIT } } diff --git a/Content.Shared/_White/DollyMixture/DollyMixtureComponent.cs b/Content.Shared/_White/DollyMixture/DollyMixtureComponent.cs new file mode 100644 index 0000000000..1e26f20ec3 --- /dev/null +++ b/Content.Shared/_White/DollyMixture/DollyMixtureComponent.cs @@ -0,0 +1,40 @@ +using Robust.Shared.GameStates; +using System.Numerics; + +namespace Content.Shared._White.DollyMixture; + + +// this now lives in shared because it allows to add this component server-side and +// have it appear for all clients without additional syncing boilerplate +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] +public sealed partial class DollyMixtureComponent : Component +{ + [DataField("sprite"), AutoNetworkedField] + public string? RSIPath = null; + public string? CurrentRSIPath = null; + + [DataField] + public string StatePrefix = "dollymix"; + + // Crutch for customghosts, since i can't modify an existing spritecomponent through a ComponentRegistry. Or, at best, i don't know how. + [DataField] + public string? DefaultShader = null; + + // 0 to disable + [DataField] + public int DirectionCount = 0; + + [DataField] + public Vector2 LayerOffset = new(0, 1); + + [DataField] + public Vector2 Offset; + + [DataField] + public int RepeatLayers = 0; + + public Angle LastAngle; + + [ViewVariables(VVAccess.ReadOnly)] + public List LayerMappings = new(); +} diff --git a/Content.Shared/_White/DollyMixture/SharedDollyMixtureSystem.cs b/Content.Shared/_White/DollyMixture/SharedDollyMixtureSystem.cs new file mode 100644 index 0000000000..3efdc0d42c --- /dev/null +++ b/Content.Shared/_White/DollyMixture/SharedDollyMixtureSystem.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace Content.Shared._White.DollyMixture; + +public abstract class SharedDollyMixtureSystem : EntitySystem +{ + public virtual void Apply3D(EntityUid uid, string RsiPath, string? statePrefix = null, Vector2? layerOffset = null, DollyMixtureComponent? comp = null) + { + comp ??= EnsureComp(uid); + + comp.RSIPath = RsiPath; + Dirty(uid, comp); + } + + public virtual void Remove3D(EntityUid uid, DollyMixtureComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + comp.RSIPath = null; + Dirty(uid, comp); + } +} + diff --git a/Content.Shared/_White/Guns/AmmoProviderRedirect/AmmoProviderRedirectComponents.cs b/Content.Shared/_White/Guns/AmmoProviderRedirect/AmmoProviderRedirectComponents.cs new file mode 100644 index 0000000000..58d1747ae7 --- /dev/null +++ b/Content.Shared/_White/Guns/AmmoProviderRedirect/AmmoProviderRedirectComponents.cs @@ -0,0 +1,6 @@ +namespace Content.Shared._White.Guns.AmmoProviderRedirect; + +[RegisterComponent] +public sealed partial class ParentAmmoProviderComponent : Component +{ +} diff --git a/Content.Shared/_White/Guns/AmmoProviderRedirect/AmmoProviderRedirectSystem.cs b/Content.Shared/_White/Guns/AmmoProviderRedirect/AmmoProviderRedirectSystem.cs new file mode 100644 index 0000000000..02bbe1cc51 --- /dev/null +++ b/Content.Shared/_White/Guns/AmmoProviderRedirect/AmmoProviderRedirectSystem.cs @@ -0,0 +1,21 @@ +using Content.Shared.Weapons.Ranged.Events; + +namespace Content.Shared._White.Guns.AmmoProviderRedirect; + +public sealed class AmmoProviderRedirectSystem : EntitySystem +{ + [Dependency] private readonly SharedTransformSystem _transform = default!; + + public override void Initialize() + { + SubscribeLocalEvent(RedirectParent); + } + + // todo figure out a way to check bullets' caliber before firing + // don't let people feed .50 cal rounds into methaphorical pea shooters + private void RedirectParent(EntityUid uid, ParentAmmoProviderComponent comp, TakeAmmoEvent args) + { + if (_transform.GetParentUid(uid) is { Valid: true } parent) + RaiseLocalEvent(parent, args); + } +} diff --git a/Content.Shared/_White/Guns/ModularTurret/ModularTurretComponents.cs b/Content.Shared/_White/Guns/ModularTurret/ModularTurretComponents.cs new file mode 100644 index 0000000000..311800caf3 --- /dev/null +++ b/Content.Shared/_White/Guns/ModularTurret/ModularTurretComponents.cs @@ -0,0 +1,28 @@ +namespace Content.Shared._White.Guns.ModularTurret; + + +[RegisterComponent] +public sealed partial class ModularTurretWeaponComponent : Component +{ + [DataField(required: true)] + public List WeaponClass = new(); + + [DataField] + public bool OnlyUsableByTurret = true; + + [DataField] + public EntityUid? CurrentTurretHolder; + + [DataField("dollyMixSprite")] + public string? DollyMixRSIPath = null; +} + +[RegisterComponent] +public sealed partial class ModularTurretComponent : Component +{ + [DataField] + public string? MountClass; + + [DataField(required: true)] + public string Slot = ""; +} diff --git a/Content.Shared/_White/Guns/ModularTurret/SharedModularTurretSystem.cs b/Content.Shared/_White/Guns/ModularTurret/SharedModularTurretSystem.cs new file mode 100644 index 0000000000..d82cc1ed58 --- /dev/null +++ b/Content.Shared/_White/Guns/ModularTurret/SharedModularTurretSystem.cs @@ -0,0 +1,61 @@ +using Content.Shared._White.DollyMixture; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Containers; + +namespace Content.Shared._White.Guns.ModularTurret; + +public abstract class SharedModularTurretSystem : EntitySystem +{ + [Dependency] private readonly SharedDollyMixtureSystem _dolly = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnInsertAttempt); + SubscribeLocalEvent(OnInserted); + SubscribeLocalEvent(OnRemoved); + SubscribeLocalEvent(OnModularTurretWeaponShotAttempt); + } + + private void OnModularTurretWeaponShotAttempt(EntityUid turretUid, ModularTurretWeaponComponent comp, ref ShotAttemptedEvent args) + { + if (comp.OnlyUsableByTurret && !HasComp(args.User)) + args.Cancel(); + } + + private void OnInsertAttempt(EntityUid uid, ModularTurretComponent comp, ContainerIsInsertingAttemptEvent args) + { + if (args.Container.ID != comp.Slot) + return; + + if (!TryComp(args.EntityUid, out var modweapon)) + { + args.Cancel(); + return; + } + + if (comp.MountClass is string turretClass && + !modweapon.WeaponClass.Contains(turretClass)) + args.Cancel(); + } + + protected virtual void OnInserted(EntityUid uid, ModularTurretComponent comp, EntInsertedIntoContainerMessage args) + { + if (args.Container.ID == comp.Slot && TryComp(args.Entity, out var weapon)) + { + weapon.CurrentTurretHolder = uid; + if (weapon.DollyMixRSIPath is string path) + _dolly.Apply3D(uid, path); + } + } + + protected virtual void OnRemoved(EntityUid uid, ModularTurretComponent comp, EntRemovedFromContainerMessage args) + { + if (args.Container.ID == comp.Slot && TryComp(args.Entity, out var weapon)) + { + weapon.CurrentTurretHolder = null; + if (weapon.DollyMixRSIPath is not null) + _dolly.Remove3D(uid); + } + } + +} diff --git a/Content.Shared/_White/Guns/ProjectileContainerBatteryAmmoProviderComponent.cs b/Content.Shared/_White/Guns/ProjectileContainerBatteryAmmoProviderComponent.cs new file mode 100644 index 0000000000..c232f93b5a --- /dev/null +++ b/Content.Shared/_White/Guns/ProjectileContainerBatteryAmmoProviderComponent.cs @@ -0,0 +1,36 @@ +using Content.Shared.Weapons.Ranged; +using Content.Shared.Weapons.Ranged.Components; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared._White.Guns; + + +public abstract partial class ContainerBatteryAmmoProviderComponent : BatteryAmmoProviderComponent +{ + public EntityUid? Linked = null; +} + +/// +/// Uses the battery of the container it's currently in. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class ProjectileContainerBatteryAmmoProviderComponent : ContainerBatteryAmmoProviderComponent +{ + [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Prototype = default!; +} + +[RegisterComponent, NetworkedComponent] +public sealed partial class HitscanContainerBatteryAmmoProviderComponent : ContainerBatteryAmmoProviderComponent +{ + [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Prototype = default!; +} + +[RegisterComponent] +public sealed partial class ContainerBatteryAmmoTrackerComponent : Component +{ + public List Linked = new(); +} diff --git a/Content.Shared/_White/Guns/ProjectileDamageModifier.cs b/Content.Shared/_White/Guns/ProjectileDamageModifier.cs new file mode 100644 index 0000000000..f462bb4ab5 --- /dev/null +++ b/Content.Shared/_White/Guns/ProjectileDamageModifier.cs @@ -0,0 +1,53 @@ +using Content.Shared.Projectiles; +using Content.Shared.Whitelist; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Content.Shared._White.Guns; + +[RegisterComponent] +public sealed partial class ProjectileDamageModifierComponent : Component +{ + [DataField(required: true)] + public List Multipliers = new(); + + [DataField] + public float DefaultMultiplier = 1f; + +} + +[DataDefinition] +public sealed partial class WhitelistMultiplierPair +{ + [DataField(required: true)] + public EntityWhitelist Whitelist = new(); + + [DataField(required: true)] + public float Multiplier; +} + +public sealed class ProjectileDamageMultiplierSystem : EntitySystem +{ + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnHit); + } + + private void OnHit(EntityUid uid, ProjectileDamageModifierComponent comp, ref ProjectileHitEvent args) + { + foreach(var pair in comp.Multipliers) + { + if (_whitelist.IsWhitelistPass(pair.Whitelist, args.Target)) + { + args.Damage *= pair.Multiplier; + return; + } + } + args.Damage *= comp.DefaultMultiplier; + } +} diff --git a/Content.Shared/_White/Lock/LockDeviceLinksComponent.cs b/Content.Shared/_White/Lock/LockDeviceLinksComponent.cs new file mode 100644 index 0000000000..5f74e497e2 --- /dev/null +++ b/Content.Shared/_White/Lock/LockDeviceLinksComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.DeviceLinking.Events; +using Content.Shared.Lock; + +namespace Content.Shared._White.Lock; + +[RegisterComponent] +public sealed partial class LockDeviceLinksComponent : Component; + +public sealed class LockDeviceLinksSystem : EntitySystem +{ + [Dependency] private readonly LockSystem _lock = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnLinkAttempt); + } + + private void OnLinkAttempt(EntityUid uid, LockDeviceLinksComponent comp, LinkAttemptEvent args) + { + if (_lock.IsLocked(uid)) + args.Cancel(); + } +} diff --git a/Content.Shared/_White/RemoteControl/Components/RemoteControlConsoleComponent.cs b/Content.Shared/_White/RemoteControl/Components/RemoteControlConsoleComponent.cs index 43a9ae0253..7cf4a353d2 100644 --- a/Content.Shared/_White/RemoteControl/Components/RemoteControlConsoleComponent.cs +++ b/Content.Shared/_White/RemoteControl/Components/RemoteControlConsoleComponent.cs @@ -23,7 +23,7 @@ public sealed partial class RemoteControlConsoleComponent : Component public EntProtoId SwitchToNextAction = "RemoteControlConsoleSwitchToNextAction"; [ViewVariables] - public EntityUid SwitchToNextActionUid; + public EntityUid? SwitchToNextActionUid; [ViewVariables] public EntityUid? User; diff --git a/Content.Shared/_White/RemoteControl/Components/RemoteControlTargetComponent.cs b/Content.Shared/_White/RemoteControl/Components/RemoteControlTargetComponent.cs index d644cf2a29..c351db325d 100644 --- a/Content.Shared/_White/RemoteControl/Components/RemoteControlTargetComponent.cs +++ b/Content.Shared/_White/RemoteControl/Components/RemoteControlTargetComponent.cs @@ -4,13 +4,13 @@ using Robust.Shared.Prototypes; namespace Content.Shared._White.RemoteControl.Components; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class RemoteControlTargetComponent : Component +public sealed partial class RemoteControllableComponent : Component { [DataField] public EntProtoId EndRemoteControlAction = "ActionEndRemoteControl"; [DataField] - public bool CanManually; + public bool ManualControl; [ViewVariables, AutoNetworkedField] public EntityUid? User; diff --git a/Content.Shared/_White/RemoteControl/Components/RemoteControlUserComponent.cs b/Content.Shared/_White/RemoteControl/Components/RemoteControlUserComponent.cs index 9185e3045e..1da5ee7c6b 100644 --- a/Content.Shared/_White/RemoteControl/Components/RemoteControlUserComponent.cs +++ b/Content.Shared/_White/RemoteControl/Components/RemoteControlUserComponent.cs @@ -3,7 +3,7 @@ using Robust.Shared.GameStates; namespace Content.Shared._White.RemoteControl.Components; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class RemoteControlUserComponent : Component +public sealed partial class RemoteControllingComponent : Component { [ViewVariables, AutoNetworkedField] public EntityUid Target; diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 46b9b3d75b..d2092eef3d 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -35,7 +35,7 @@ Slash: 10 Piercing: 10 Heat: 10 - # Structural: 10 # WWDP its for structures bruh + Structural: 5 - type: damageModifierSet id: Rock @@ -51,17 +51,17 @@ - type: damageModifierSet id: RockStrong coefficients: - Structural: 1 # WWDP + Structural: 2 # WWDP Blunt: 0.25 Slash: 0.1 Piercing: 0.25 Heat: 0.5 flatReductions: - Blunt: 10 - Slash: 10 - Piercing: 10 - Heat: 10 - # Structural: 10 # WWDP + Blunt: 15 + Slash: 15 + Piercing: 15 + Heat: 15 + # Structural: 5 # WWDP # no - type: damageModifierSet id: PerforatedMetallic diff --git a/Resources/Prototypes/Entities/Effects/admin_triggers.yml b/Resources/Prototypes/Entities/Effects/admin_triggers.yml index e1f366678d..c9baefd00d 100644 --- a/Resources/Prototypes/Entities/Effects/admin_triggers.yml +++ b/Resources/Prototypes/Entities/Effects/admin_triggers.yml @@ -109,4 +109,33 @@ - type: SingularityDistortion intensity: 10 falloffPower: 1.5 - + +# WWDP # + +# This kills the SpawnAndDirtyAllEntities test. +# The test tries to get this entity's netuid to send the projectileComp's "Shooter" field to clients, +# but does this not fast enough, so this entity is long since deleted by that point. +# todo: kill that test +#- type: entity +# id: AdminInstantEffectShrapnel +# suffix: Shrapnel +# parent: AdminInstantEffectBase +# components: +# - type: ClusterGrenade +# fillPrototype: PelletClusterLethal +# maxGrenadesCount: 30 +# grenadeType: enum.GrenadeType.Shoot +# - type: ContainerContainer +# containers: +# cluster-payload: !type:Container + +- type: entity + id: AdminInstantEffectExplosionSmall + suffix: Small Explosion + parent: AdminInstantEffectBase + components: + - type: ExplodeOnTrigger + - type: Explosive + totalIntensity: 30 + explosionType: Default + tileBreakScale: 5 diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Mech/Weapons/Gun/base.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Mech/Weapons/Gun/base.yml index f4b8f23f12..874ba6c56e 100644 --- a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Mech/Weapons/Gun/base.yml +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Mech/Weapons/Gun/base.yml @@ -15,4 +15,4 @@ - type: ClothingSpeedModifier walkModifier: 0.5 sprintModifier: 0.5 - - type: HeldSpeedModifier \ No newline at end of file + - type: HeldSpeedModifier diff --git a/Resources/Prototypes/_White/Catalog/Cargo/ship_weapons.yml b/Resources/Prototypes/_White/Catalog/Cargo/ship_weapons.yml new file mode 100644 index 0000000000..685919210b --- /dev/null +++ b/Resources/Prototypes/_White/Catalog/Cargo/ship_weapons.yml @@ -0,0 +1,119 @@ +- type: cargoProduct + id: WeaponShipLightIR + description: A single IR laser. Low damage and even lower power draw. + icon: + sprite: _White/Objects/Weapons/Guns/Turrets/IR_laser.rsi + state: icon + product: CrateWeaponSecureWeaponShipLightIR + cost: 7500 + category: cargoproduct-category-name-shuttle + group: market + +- type: entity + parent: CrateWeaponSecure + id: CrateWeaponSecureWeaponShipLightIR + name: IR laser crate + components: + - type: StorageFill + contents: + - id: WeaponShipLightIR + +- type: cargoProduct + id: WeaponShipLightAnnihilator + description: A single annihilator MLRS. Fires a burst of low-damage rockets in a wide arc for suppression and area denial. + icon: + sprite: _White/Objects/Weapons/Guns/Turrets/annihilator.rsi + state: icon + product: CrateWeaponSecureWeaponShipLightAnnihilator + cost: 27500 + category: cargoproduct-category-name-shuttle + group: market + +- type: entity + parent: CrateWeaponSecure + id: CrateWeaponSecureWeaponShipLightAnnihilator + name: annihilator crate + components: + - type: StorageFill + contents: + - id: WeaponShipLightAnnihilator + +- type: cargoProduct + id: WeaponShipLightHotspot + description: A single Hotspot CIWS. Inaccurate dual-minigun, capable of firing in short bursts, intended for point-defense against soft targets. + icon: + sprite: _White/Objects/Weapons/Guns/Turrets/hotspot.rsi + state: icon + product: CrateWeaponSecureWeaponShipLightHotspot + cost: 16500 + category: cargoproduct-category-name-shuttle + group: market + +- type: entity + parent: CrateWeaponSecure + id: CrateWeaponSecureWeaponShipLightHotspot + name: hotspot crate + components: + - type: StorageFill + contents: + - id: WeaponShipLightHotspot + +- type: cargoProduct + id: WeaponShipLightHMG + description: A single heavy machine gun. Well suited for any task. + icon: + sprite: _White/Objects/Weapons/Guns/Turrets/hmg.rsi + state: icon + product: CrateWeaponSecureWeaponShipLightHMG + cost: 23000 + category: cargoproduct-category-name-shuttle + group: market + +- type: entity + parent: CrateWeaponSecure + id: CrateWeaponSecureWeaponShipLightHMG + name: ship HMG crate + components: + - type: StorageFill + contents: + - id: WeaponShipLightHMG + +- type: cargoProduct + id: WeaponShipLightBlaster + description: A single mining blaster. Tears apart hull and rock alike, but near useless in actual combat due to slow projectiles. + icon: + sprite: _White/Objects/Weapons/Guns/Turrets/blaster.rsi + state: icon + product: CrateWeaponSecureWeaponShipLightBlaster + cost: 18000 + category: cargoproduct-category-name-shuttle + group: market + +- type: entity + parent: CrateWeaponSecure + id: CrateWeaponSecureWeaponShipLightBlaster + name: mining blaster crate + components: + - type: StorageFill + contents: + - id: WeaponShipLightBlaster + +- type: cargoProduct + id: WeaponShipLightMiningLaser + description: A single mining laser. Effective at presicely cutting pieces of rock and hull, it is slower than a mining blaster. + icon: + sprite: _White/Objects/Weapons/Guns/Turrets/mining_laser.rsi + state: icon + product: CrateWeaponSecureWeaponShipLightMiningLaser + cost: 20500 + category: cargoproduct-category-name-shuttle + group: market + +- type: entity + parent: CrateWeaponSecure + id: CrateWeaponSecureWeaponShipLightMiningLaser + name: mining laser crate + components: + - type: StorageFill + contents: + - id: WeaponShipLightMiningLaser diff --git a/Resources/Prototypes/_White/DeviceLinking/sink_ports.yml b/Resources/Prototypes/_White/DeviceLinking/sink_ports.yml index b845b47a6f..2f6d1ef9de 100644 --- a/Resources/Prototypes/_White/DeviceLinking/sink_ports.yml +++ b/Resources/Prototypes/_White/DeviceLinking/sink_ports.yml @@ -1,4 +1,10 @@ +- type: sourcePort + id: RemoteControlSourcePort + name: signal-port-name-remote-control-source + description: signal-port-description-remote-control-source + defaultLinks: [ RemoteControlSinkPort ] + - type: sinkPort - id: RemoteControlOutputPort - name: signal-port-name-remote-control-output - description: signal-port-description-remote-control-output + id: RemoteControlSinkPort + name: signal-port-name-remote-control-sink + description: signal-port-description-remote-control-sink diff --git a/Resources/Prototypes/_White/DeviceLinking/source_ports.yml b/Resources/Prototypes/_White/DeviceLinking/source_ports.yml deleted file mode 100644 index 99fa14c837..0000000000 --- a/Resources/Prototypes/_White/DeviceLinking/source_ports.yml +++ /dev/null @@ -1,5 +0,0 @@ -- type: sourcePort - id: RemoteControlInputPort - name: signal-port-name-remote-control-input - description: signal-port-description-remote-control-input - defaultLinks: [ RemoteControlOutputPort ] diff --git a/Resources/Prototypes/_White/Entities/Objects/Devices/Circuitboards/misc.yml b/Resources/Prototypes/_White/Entities/Objects/Devices/Circuitboards/misc.yml index e85b54a32f..2d1a31ebef 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Devices/Circuitboards/misc.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Devices/Circuitboards/misc.yml @@ -14,7 +14,7 @@ - AiCoreBoard - type: entity - id: WeaponTurretModularCircuitBoard + id: WeaponTurretUniversalCircuitboard parent: BaseMachineCircuitboard name: modular turret machine board description: Circuitboard for a modular turret, which is a fancy way of saying "a servomotor tied to a gun's trigger with a string". @@ -22,10 +22,9 @@ - type: Sprite state: engineering - type: MachineBoard - prototype: WeaponTurretModular + prototype: WeaponTurretUniversal requirements: - MatterBin: 1 - Manipulator: 3 + Manipulator: 1 Capacitor: 1 materialRequirements: Cable: 5 diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Ship/weapons.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Ship/weapons.yml new file mode 100644 index 0000000000..fe133f1478 --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Ship/weapons.yml @@ -0,0 +1,369 @@ +- type: entity + parent: BaseItem + id: BaseWeaponShip + abstract: True + components: + - type: Appearance + - type: StaticPrice + price: 1 + - type: Item + size: Ginormous + - type: MultiHandedItem + - type: ClothingSpeedModifier + walkModifier: 0.5 + sprintModifier: 0.5 + - type: HeldSpeedModifier + - type: ModularTurretWeapon + onlyUsableByTurret: true + - type: Gun + fireOnDropChance: 0 + shipWeapon: true + +- type: entity + id: BaseWeaponShipLightEnergy + parent: BaseWeaponShip + abstract: True + components: + - type: ModularTurretWeapon + weaponClass: + - LightEnergy + +- type: entity + id: BaseWeaponShipLightBallistic + parent: BaseWeaponShip + abstract: True + components: + - type: ModularTurretWeapon + weaponClass: + - LightBallistic + + + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightIR + name: IR Pulse Laser + description: A power-efficient, albeit weak infrared pulse laser. Being essentially a scaled-up version of a regular laser carbine, this cannon trades damage for extreme power efficiency. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/IR_laser.rsi + state: icon + - type: Gun + fireRate: 3.5 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/laser.ogg + params: + volume: -5 + - type: ProjectileContainerBatteryAmmoProvider + proto: BulletLaser + fireCost: 75 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/IR_laser.rsi + + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightAnnihilator + name: Annihilator Rocket Launcher + description: Fires a spread of unguided flash-printed microrockets that cover a wide arc. Despite the low damage output, it can still deal a devastating blow in hands of a skilled fighter pilot. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/annihilator.rsi + state: icon + - type: Gun + selectedMode: Burst + availableModes: + - Burst + burstFireRate: 10 + burstCooldown: 3 + shotsPerBurst: 10 + minAngle: 15 + maxAngle: 15 + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/rpgfire.ogg + params: + volume: -5 + - type: ProjectileContainerBatteryAmmoProvider + proto: BulletWeakRocket + fireCost: 1000 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/annihilator.rsi + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightMiningLaser + name: Mining Laser + description: A cheap utility laser, excels at melting loose rock and cutting various salvage into pieces, but performs poorly against softer targets. Has a rather short focus range, making it ill-suited for combat use. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/mining_laser.rsi + state: icon + - type: Gun + fireRate: 5 + angleDecay: -12 + angleIncrease: -6 + maxAngle: 40 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/laser.ogg + params: + volume: -10 + - type: HitscanContainerBatteryAmmoProvider + proto: RedMiningLaser + fireCost: 500 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/mining_laser.rsi + +# I'll put the mining beam prototype right after the mining laser itself to +# make it obvious what it does. +- type: hitscan + id: RedMiningLaser + maxLength: 30 + damage: + types: + Heat: 3 + Structural: 15 + muzzleFlash: + sprite: _White/Objects/Weapons/Guns/Projectiles/projectiles.rsi + state: muzzle_mining_laser + travelFlash: + sprite: _White/Objects/Weapons/Guns/Projectiles/projectiles.rsi + state: mining_laser + impactFlash: + sprite: _White/Objects/Weapons/Guns/Projectiles/projectiles.rsi + state: impact_mining_laser + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightRiftLance + name: Rift lance + description: We commit this body to the holy vaccuum, dust to dust, stars to stars, that the Creator may renew our us in the cycle of eternal life. - Luddic funereal prayer, traditional. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/rift_lance.rsi + state: icon + - type: Gun + fireRate: 0.1 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/mateba.ogg + - type: HitscanContainerBatteryAmmoProvider + proto: RiftLanceBeam + fireCost: 8000 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/rift_lance.rsi + +# I'll put the rift lance beam prototype right after the rift lance itself to +# make it obvious why it should *not* be given to players. +- type: hitscan + id: RiftLanceBeam + maxLength: 800 # fuck it we ballin' + damage: + types: + Blunt: 2000 # oh yeah + spawnAtImpact: OmegaBlastPierce # extra funny + muzzleFlash: + sprite: _White/Objects/Weapons/Guns/Projectiles/projectiles.rsi + state: muzzle_fast + travelFlash: + sprite: _White/Objects/Weapons/Guns/Projectiles/projectiles.rsi + state: fast + impactFlash: + sprite: _White/Objects/Weapons/Guns/Projectiles/projectiles.rsi + state: impact_fast + +- type: entity + id: OmegaBlastPierce + categories: [ HideSpawnMenu ] + components: + - type: TriggerOnSpawn + - type: SpawnOnTrigger + proto: AdminInstantEffectExplosionSmall + offsets: + - 0,0 + - 0,2 + - 0,4 + - 0,6 + - 0,8 + - 0,10 + - type: TimedDespawn + lifetime: 1 + + +#- type: entity +# parent: BaseWeaponShipLightEnergy +# id: WeaponShipLightAutopulse +# name: Autopulse Laser Cannon +# description: Numerous built-in capacitors are at the core of this extremely inefficient, yet potent energy weapon. +# components: +# - type: Sprite +# sprite: Objects/Specific/Mech/mecha_equipment.rsi +# layers: +# - map: [ "icon" ] +# state: mecha_pulse +# - type: Gun +# fireRate: 5 +# selectedMode: FullAuto +# availableModes: +# - FullAuto +# soundGunshot: +# path: /Audio/Weapons/Guns/Gunshots/laser3.ogg +# - type: ProjectileContainerBatteryAmmoProvider +# proto: BulletPulse +# fireCost: 150 + + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightHotspot + name: Hotspot PD + description: A rapid fire ballistic weapon effective against soft targets. A respectable close-in weapon system, it's effectiveness is severely limited by poor accuracy and low damage against any substantial armor. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/hotspot.rsi + state: icon + - type: Gun + fireRate: 20 + angleDecay: 12 + angleIncrease: 3 + maxAngle: 20 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/minigun.ogg + params: + volume: -4 + - type: ProjectileContainerBatteryAmmoProvider + proto: BulletHotspot + fireCost: 250 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/hotspot.rsi + +- type: entity + id: BulletHotspot + name: bullet (.13 point-defense) + parent: BaseBullet + categories: [ HideSpawnMenu ] + components: + - type: Projectile + damage: + types: + Piercing: 4 + Blunt: 2 + Slash: 2 + + +- type: entity + id: BulletHotspotSpread + categories: [ HideSpawnMenu ] + parent: BulletHotspot + components: + - type: ProjectileSpread + proto: BulletHotspot + count: 3 + spread: 4 + + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightHMG + name: Ship HMG + description: A jack of all trades, this weapon is a well-rounded option for any type of job. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/hmg.rsi + state: icon + - type: Gun + fireRate: 5 + angleDecay: 10 + angleIncrease: 5 + maxAngle: 25 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/lmg.ogg + params: + volume: 0 + - type: ProjectileContainerBatteryAmmoProvider + proto: BulletHighCaliberWeak + fireCost: 1000 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/hmg.rsi + + + +- type: entity + categories: [ HideSpawnMenu ] + parent: BaseBullet + id: BulletHighCaliberWeak + name: bullet (.50 flash-printed) + components: + - type: Projectile + damage: + types: + Piercing: 25 + Structural: 25 # weaker compared to other .50 cal bullets + + + + +- type: entity + parent: BaseWeaponShipLightEnergy + id: WeaponShipLightBlaster + name: Mining Blaster + description: Able to carve out chunks of stone and hull alike, this weapon's performance is severely hampered by it's low firerate and projectile speed. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/blaster.rsi + state: icon + - type: Gun + projectileSpeed: 10 + fireRate: 0.333 + angleDecay: 2.5 + angleIncrease: 10 + maxAngle: 25 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/laser.ogg + params: + volume: 0 + - type: ProjectileContainerBatteryAmmoProvider + proto: BulletMiningBlast + fireCost: 4000 + - type: ModularTurretWeapon + dollyMixSprite: _White/Objects/Weapons/Guns/Turrets/blaster.rsi + + +- type: entity + id: BulletMiningBlast + name: unstable energy orb + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi + color: "#FF00FFFF" #E7C60F? + layers: + - state: impact_laser_greyscale + - type: ExplodeOnTrigger + - type: Explosive + explosionType: DemolitionCharge + maxIntensity: 1 + intensitySlope: 1 + totalIntensity: 21 + maxTileBreak: 0 + - type: PointLight + radius: 1.5 + color: red + energy: 0.25 diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml new file mode 100644 index 0000000000..c41f91efd9 --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml @@ -0,0 +1,176 @@ +- type: entity + parent: [BaseStructure, ConstructibleMachine] + id: BaseWeaponTurretShip + suffix: Naval, Remote Controlled + abstract: true + name: ship turret + description: A remotely-operated turret designed to accept anti-ship weapons. + components: + - type: Clickable + - type: InteractionOutline + - type: Actions + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.45,0.45,0.45" + density: 60 + mask: + - MachineMask + layer: + - MachineLayer + - type: Sprite + sprite: Objects/Weapons/Guns/Turrets/turrets.rsi + drawdepth: Mobs + noRot: true + state: syndie_base + - type: DollyMixture + directionCount: 64 + repeatLayers: 3 + - type: CombatMode + isInCombatMode: true + toggleMouseRotator: false + - type: Damageable + damageContainer: Inorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 450 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + WeaponTurretSyndicateBroken: + min: 1 + max: 1 + - trigger: + !type:DamageTrigger + damage: 300 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: MetalGlassBreak + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: MetalGlassBreak + - type: GunFireAngleRestriction + - type: MouseRotator + angleTolerance: 0.05 + rotationSpeed: 90 + simple4DirMode: false + - type: NoRotateOnInteract + - type: NoRotateOnMove + - type: Input + context: "human" + - type: ContainerContainer + containers: + weapon_slot: !type:ContainerSlot + machine_board: !type:Container + machine_parts: !type:Container + - type: GunSlot + slot: weapon_slot + - type: ModularTurret + slot: weapon_slot + - type: ItemSlots + slots: + weapon_slot: + ejectOnInteract: false + ejectOnBreak: true + swap: false + name: Weapon slot + priority: 1 + whitelist: + components: + - Gun + - ModularTurretWeapon + - type: RemoteControllable + - type: RemoteControlOverlay + - type: Lock + locked: false + lockTime: 5 + unlockTime: 20 + - type: ItemSlotsLock + slots: + - weapon_slot + - type: GunSignalControl + - type: DeviceNetwork + deviceNetId: Wireless + receiveFrequencyId: BasicDevice + - type: WiredNetworkConnection + - type: DeviceLinkSink + ports: + - RemoteControlSinkPort + - type: Battery + maxCharge: 2000 + startingCharge: 0 + - type: ApcPowerReceiverBattery + idleLoad: 5 + batteryRechargeRate: 200 + batteryRechargeEfficiency: 1.225 + - type: ApcPowerReceiver + powerLoad: 5 + - type: ExtensionCableReceiver + - type: Alerts + - type: Telescope + lerpAmount: 0.25 + - type: Silicon + entityType: enum.SiliconType.Player + batteryPowered: true + drainPerSecond: 2 + speedModifierThresholds: + 4: 1 + 3: 1 + 2: 1 + 1: 1 + 0: 1 + + +- type: entity + parent: [ BaseWeaponTurretShip, InnateMassScanner150 ] + id: WeaponTurretShipLight + suffix: Naval, Remote Controlled + name: small weapon mount + description: A remotely-operated weapon mount designed to accept light anti-ship and anti-infantry weaponry. + components: + - type: Sprite + sprite: _White/Objects/Weapons/Guns/Turrets/mounts.rsi + state: light + - type: Battery + maxCharge: 10000 + startingCharge: 0 + - type: ApcPowerReceiverBattery + idleLoad: 50 + batteryRechargeRate: 1000 + batteryRechargeEfficiency: 2.45 + - type: ApcPowerReceiver + powerLoad: 50 + - type: Machine + board: WeaponTurretShipLightCircuitBoard + - type: UpgradeBattery + maxChargeMultiplier: 3 + baseMaxCharge: 10000 + +- type: entity + id: WeaponTurretShipLightCircuitBoard + parent: BaseMachineCircuitboard + name: modular turret machine board + description: Circuitboard for a light ship weapon mount. + components: + - type: Sprite + state: security + - type: MachineBoard + prototype: WeaponTurretShipLight + requirements: + MatterBin: 1 + Manipulator: 2 + Capacitor: 3 + materialRequirements: + Cable: 5 + Steel: 10 diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turret_base.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turret_base.yml index 4021de8f63..f4d3b4d7e5 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turret_base.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turret_base.yml @@ -76,6 +76,7 @@ forceShootForward: true - type: GunFireAngleRestriction +# this is dumb - type: entity id: BaseTurret3D abstract: true @@ -87,10 +88,7 @@ layers: - state: syndie_base - type: DollyMixture - states: - - dm1 - - dm2 - - dm3 - - dm4 - - dm5 + sprite: Objects/Weapons/Guns/Turrets/turrets.rsi + statePrefix: dm + repeatLayers: 3 layerOffset: 0,0.75 diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_energy.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_energy.yml index e7af01dae7..e69de29bb2 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_energy.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_energy.yml @@ -1,36 +0,0 @@ -- type: entity - parent: BaseWeaponEnergyTurret - id: WeaponEnergyTurretShip - name: ship laser turret - description: A burst fire heavy laser weapon mounted to a simple actuator rig with a camera. Its weapon will recharge while connected to an active power grid. - suffix: Remote Controlled - components: - - type: DeviceLinkSink - ports: - - RemoteControlOutputPort - - type: Gun - shipWeapon: true - burstCooldown: 0.4 - projectileSpeed: 50 - angleIncrease: 1.25 - maxAngle: 5 - selectedMode: Burst - availableModes: - - Burst - - type: HTN # since there is no functionality to discard inherited components, we just disable HTN instead - enabled: false - - type: IntrinsicUI - uis: - enum.RadarConsoleUiKey.Key: - toggleAction: ActionAGhostShowRadar - - type: MouseRotator - angleTolerance: 0.5 - - type: RadarConsole - followEntity: true - fieldOfVision: 90 - - type: RemoteControlTarget - - type: RemoteControlOverlay - - type: UserInterface - interfaces: - enum.RadarConsoleUiKey.Key: - type: RadarConsoleBoundUserInterface diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_ballistic.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/universal_mount.yml similarity index 57% rename from Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_ballistic.yml rename to Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/universal_mount.yml index 28590ed083..16c1532861 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/turrets_ballistic.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/universal_mount.yml @@ -1,16 +1,18 @@ - type: entity parent: [BaseWeaponTurretNoHTR, ConstructibleMachine] - id: WeaponTurretModular - name: modular turret - description: A remotely-operated turret designed to accept standard hand-held weapons. Being a simple gimbal mount, it is unable to recharge energy weapons. - suffix: Remote controlled + id: WeaponTurretUniversal + suffix: Remote Controlled + name: universal weapon mount + description: A remotely-operated turret designed to accept standard hand-held weapons. Being a simple gimbal mount, it is unable to do much besides aiming a gun and firing it. components: - type: Sprite granularLayersRendering: true + sprite: Objects/Weapons/Guns/Turrets/turrets.rsi + drawdepth: Mobs layers: - state: syndie_base renderingStrategy: NoRotation - - map: [ "weapon" ] + - map: [ "weapon_layer" ] renderingStrategy: Default rotation: -90 - type: ContainerContainer @@ -26,19 +28,19 @@ ejectOnInteract: false ejectOnBreak: true swap: false - name: weapon-slot + name: Weapon slot priority: 1 whitelist: components: - Gun - type: ItemSlotRenderer mapping: - weapon_slot: weapon - - type: RemoteControlTarget - canManually: true + weapon_slot: weapon_layer + - type: RemoteControllable + manualControl: true - type: RemoteControlOverlay - type: Machine - board: WeaponTurretModularCircuitBoard + board: WeaponTurretUniversalCircuitboard - type: Lock locked: false lockTime: 3 @@ -50,7 +52,25 @@ - type: DeviceNetwork deviceNetId: Wireless receiveFrequencyId: BasicDevice - - type: DeviceLinkSink - ports: - - RemoteControlOutputPort - type: WiredNetworkConnection + - type: Battery + maxCharge: 2000 + startingCharge: 0 + - type: ApcPowerReceiverBattery + idleLoad: 5 + batteryRechargeRate: 200 + batteryRechargeEfficiency: 1.225 + - type: ApcPowerReceiver + powerLoad: 5 + - type: ExtensionCableReceiver + - type: Alerts + - type: Silicon + entityType: enum.SiliconType.Player + batteryPowered: true + drainPerSecond: 2 + speedModifierThresholds: + 4: 1 + 3: 1 + 2: 1 + 1: 1 + 0: 0 diff --git a/Resources/Prototypes/_White/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/_White/Entities/Structures/Machines/Computers/remote_control.yml similarity index 96% rename from Resources/Prototypes/_White/Entities/Structures/Machines/Computers/computers.yml rename to Resources/Prototypes/_White/Entities/Structures/Machines/Computers/remote_control.yml index e7c44f32cc..9c2bbc9442 100644 --- a/Resources/Prototypes/_White/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/_White/Entities/Structures/Machines/Computers/remote_control.yml @@ -25,4 +25,4 @@ - type: RemoteControlConsole - type: DeviceLinkSource ports: - - RemoteControlInputPort + - RemoteControlSourcePort diff --git a/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml b/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml index 43bbd0e1d5..70fef228ab 100644 --- a/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml +++ b/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml @@ -188,7 +188,7 @@ #just look at the ckey field you dumbass - type: customGhost id: redfoxiv-ghost - ckey: RedFoxIV + ckey: RedFoxIV@localhost sprite: _White/Ghosts/empty.rsi alpha: 1 ghostName: яицевозка @@ -200,108 +200,10 @@ simple4DirMode: false - type: DollyMixture sprite: _White/Ghosts/redfoxiv-3Dghost.rsi + statePrefix: hqyaitca offset: 0,-16 layerOffset: 0,0.675 - repeatLayers: 1 defaultShader: unshaded - states: - - hqyaitca97 - - hqyaitca96 - - hqyaitca95 - - hqyaitca94 - - hqyaitca93 - - hqyaitca92 - - hqyaitca91 - - hqyaitca90 - - hqyaitca89 - - hqyaitca88 - - hqyaitca87 - - hqyaitca86 - - hqyaitca85 - - hqyaitca84 - - hqyaitca83 - - hqyaitca82 - - hqyaitca81 - - hqyaitca80 - - hqyaitca79 - - hqyaitca78 - - hqyaitca77 - - hqyaitca76 - - hqyaitca75 - - hqyaitca74 - - hqyaitca73 - - hqyaitca72 - - hqyaitca71 - - hqyaitca70 - - hqyaitca69 - - hqyaitca68 - - hqyaitca67 - - hqyaitca66 - - hqyaitca65 - - hqyaitca64 - - hqyaitca63 - - hqyaitca62 - - hqyaitca61 - - hqyaitca60 - - hqyaitca59 - - hqyaitca58 - - hqyaitca57 - - hqyaitca56 - - hqyaitca55 - - hqyaitca54 - - hqyaitca53 - - hqyaitca52 - - hqyaitca51 - - hqyaitca50 - - hqyaitca49 - - hqyaitca48 - - hqyaitca47 - - hqyaitca46 - - hqyaitca45 - - hqyaitca44 - - hqyaitca43 - - hqyaitca42 - - hqyaitca41 - - hqyaitca40 - - hqyaitca39 - - hqyaitca38 - - hqyaitca37 - - hqyaitca36 - - hqyaitca35 - - hqyaitca34 - - hqyaitca33 - - hqyaitca32 - - hqyaitca31 - - hqyaitca30 - - hqyaitca29 - - hqyaitca28 - - hqyaitca27 - - hqyaitca26 - - hqyaitca25 - - hqyaitca24 - - hqyaitca23 - - hqyaitca22 - - hqyaitca21 - - hqyaitca20 - - hqyaitca19 - - hqyaitca18 - - hqyaitca17 - - hqyaitca16 - - hqyaitca15 - - hqyaitca14 - - hqyaitca13 - - hqyaitca12 - - hqyaitca11 - - hqyaitca10 - - hqyaitca9 - - hqyaitca8 - - hqyaitca7 - - hqyaitca6 - - hqyaitca5 - - hqyaitca4 - - hqyaitca3 - - hqyaitca2 - - hqyaitca1 ##xivi diff --git a/Resources/Prototypes/_White/Innate/InnateMassScanner.yml b/Resources/Prototypes/_White/Innate/InnateMassScanner.yml new file mode 100644 index 0000000000..f723d92733 --- /dev/null +++ b/Resources/Prototypes/_White/Innate/InnateMassScanner.yml @@ -0,0 +1,62 @@ +- type: entity + id: InnateMassScanner360 + abstract: true + components: + - type: IntrinsicUI + uis: + enum.RadarConsoleUiKey.Key: + toggleAction: ActionAGhostShowRadar + - type: UserInterface + interfaces: + enum.RadarConsoleUiKey.Key: + type: RadarConsoleBoundUserInterface + - type: RadarConsole + followEntity: true + +- type: entity + parent: InnateMassScanner360 + id: InnateMassScanner30 + abstract: true + components: + - type: RadarConsole + fieldOfVision: 30 + +- type: entity + parent: InnateMassScanner360 + id: InnateMassScanner60 + abstract: true + components: + - type: RadarConsole + fieldOfVision: 60 + +- type: entity + parent: InnateMassScanner360 + id: InnateMassScanner90 + abstract: true + components: + - type: RadarConsole + fieldOfVision: 90 + +- type: entity + parent: InnateMassScanner360 + id: InnateMassScanner120 + abstract: true + components: + - type: RadarConsole + fieldOfVision: 120 + +- type: entity + parent: InnateMassScanner360 + id: InnateMassScanner150 + abstract: true + components: + - type: RadarConsole + fieldOfVision: 150 + +- type: entity + parent: InnateMassScanner360 + id: InnateMassScanner180 + abstract: true + components: + - type: RadarConsole + fieldOfVision: 180 diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/fast.png b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/fast.png new file mode 100644 index 0000000000..c53795c635 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/fast.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/impact_fast.png b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/impact_fast.png new file mode 100644 index 0000000000..1ac335913e Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/impact_fast.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/impact_mining_laser.png b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/impact_mining_laser.png new file mode 100644 index 0000000000..653466cbce Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/impact_mining_laser.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json new file mode 100644 index 0000000000..f33e7dba7c --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json @@ -0,0 +1,101 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken and modified from cev-eris at https://github.com/discordia-space/CEV-Eris/tree/7ff8f28ea4de734f3cc3cb70f2d4e4b4263a988d", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "muzzle_mining_laser", + "delays": [ + [ + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002 + ] + ] + }, + { + "name": "mining_laser", + "delays": [ + [ + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002 + ] + ] + }, + { + "name": "impact_mining_laser", + "delays": [ + [ + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002 + ] + ] + }, + { + "name": "muzzle_fast", + "delays": [ + [ + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002 + ] + ] + }, + { + "name": "fast", + "delays": [ + [ + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002 + ] + ] + }, + { + "name": "impact_fast", + "delays": [ + [ + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002, + 0.060000002 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/mining_laser.png b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/mining_laser.png new file mode 100644 index 0000000000..e1231014db Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/mining_laser.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_fast.png b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_fast.png new file mode 100644 index 0000000000..02756543c5 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_fast.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_mining_laser.png b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_mining_laser.png new file mode 100644 index 0000000000..b1aced7708 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_mining_laser.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix1.png new file mode 100644 index 0000000000..b2cb37625c Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix2.png new file mode 100644 index 0000000000..bc35ee0747 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix3.png new file mode 100644 index 0000000000..723356c9c5 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix4-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix4-unshaded.png new file mode 100644 index 0000000000..6c6609442d Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix4-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix4.png new file mode 100644 index 0000000000..e445ed1636 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix5.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix5.png new file mode 100644 index 0000000000..a72458fdeb Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/dollymix5.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/icon.png new file mode 100644 index 0000000000..e95c366bae Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/meta.json new file mode 100644 index 0000000000..4595ca25d9 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/IR_laser.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1"}, + { "name": "dollymix2"}, + { "name": "dollymix3"}, + { "name": "dollymix4-unshaded", "delays":[[1, 1, 1, 1]] }, + { "name": "dollymix4"}, + { "name": "dollymix5"}, + { "name": "icon"} + ] +} diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix1.png new file mode 100644 index 0000000000..ddac8f5a5b Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix2.png new file mode 100644 index 0000000000..2f00f868db Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix3.png new file mode 100644 index 0000000000..a4c9c3416e Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix4.png new file mode 100644 index 0000000000..5441cf8e59 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix5.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix5.png new file mode 100644 index 0000000000..8b621e4639 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix5.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix6.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix6.png new file mode 100644 index 0000000000..b9e0775b96 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix6.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix7.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix7.png new file mode 100644 index 0000000000..6fc7dd1c80 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix7.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix8.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix8.png new file mode 100644 index 0000000000..abeb7c49c3 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/dollymix8.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/icon.png new file mode 100644 index 0000000000..11a0f33df8 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/meta.json new file mode 100644 index 0000000000..8c8a797a7a --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/annihilator.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1"}, + { "name": "dollymix2"}, + { "name": "dollymix3"}, + { "name": "dollymix4"}, + { "name": "dollymix5"}, + { "name": "dollymix6"}, + { "name": "dollymix7"}, + { "name": "dollymix8"}, + { "name": "icon"} + ] +} diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix1.png new file mode 100644 index 0000000000..b898d00812 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix2.png new file mode 100644 index 0000000000..988e90030c Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix3.png new file mode 100644 index 0000000000..283daf6f62 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix4.png new file mode 100644 index 0000000000..76c64b4bfe Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix5.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix5.png new file mode 100644 index 0000000000..d249549b5f Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/dollymix5.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/icon.png new file mode 100644 index 0000000000..d274c6cfda Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/meta.json new file mode 100644 index 0000000000..d75991f1a1 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/blaster.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP autogenerated", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1" }, + { "name": "dollymix2" }, + { "name": "dollymix3" }, + { "name": "dollymix4" }, + { "name": "dollymix5" }, + { "name": "icon" } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix1.png new file mode 100644 index 0000000000..9fbb64fb0e Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix2.png new file mode 100644 index 0000000000..9edcc5aee6 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix3.png new file mode 100644 index 0000000000..d9a7c527b1 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix4.png new file mode 100644 index 0000000000..b72d55f4b7 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/icon.png new file mode 100644 index 0000000000..c20651fcf4 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/meta.json new file mode 100644 index 0000000000..73e0eb5872 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hmg.rsi/meta.json @@ -0,0 +1,16 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP autogenerated", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1" }, + { "name": "dollymix2" }, + { "name": "dollymix3" }, + { "name": "dollymix4" }, + { "name": "icon" } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix1.png new file mode 100644 index 0000000000..d440dc7d8e Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix2.png new file mode 100644 index 0000000000..bd6f3ace8b Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix3.png new file mode 100644 index 0000000000..0f3af05b37 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix4.png new file mode 100644 index 0000000000..477f8cfcf4 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix5.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix5.png new file mode 100644 index 0000000000..8ece2b9fa2 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/dollymix5.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/icon.png new file mode 100644 index 0000000000..ce46002a8d Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/meta.json new file mode 100644 index 0000000000..d75991f1a1 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/hotspot.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP autogenerated", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1" }, + { "name": "dollymix2" }, + { "name": "dollymix3" }, + { "name": "dollymix4" }, + { "name": "dollymix5" }, + { "name": "icon" } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix1.png new file mode 100644 index 0000000000..f3d3b77ff3 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix2.png new file mode 100644 index 0000000000..02934a6382 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix3-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix3-unshaded.png new file mode 100644 index 0000000000..be35105a0b Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix3-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix3.png new file mode 100644 index 0000000000..6736113c6e Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix4.png new file mode 100644 index 0000000000..ec6c027da8 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix5-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix5-unshaded.png new file mode 100644 index 0000000000..21b16235f1 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix5-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix5.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix5.png new file mode 100644 index 0000000000..9060a6fdb4 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix5.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix6.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix6.png new file mode 100644 index 0000000000..8c467d971c Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix6.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix7-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix7-unshaded.png new file mode 100644 index 0000000000..853d3fe805 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix7-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix7.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix7.png new file mode 100644 index 0000000000..9e189fde05 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix7.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix8.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix8.png new file mode 100644 index 0000000000..91303a24a7 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix8.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix9-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix9-unshaded.png new file mode 100644 index 0000000000..ea3b033069 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix9-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix9.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix9.png new file mode 100644 index 0000000000..9c099943e1 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/dollymix9.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/icon.png new file mode 100644 index 0000000000..093d9f201b Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/meta.json new file mode 100644 index 0000000000..1285c3e6e0 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mining_laser.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1"}, + { "name": "dollymix2"}, + { "name": "dollymix3"}, + { "name": "dollymix3-unshaded", "delays": [[0.2, 0.2, 0.2, 0.2]]}, + { "name": "dollymix4"}, + { "name": "dollymix5"}, + { "name": "dollymix5-unshaded", "delays": [[0.2, 0.2, 0.2, 0.2]]}, + { "name": "dollymix6"}, + { "name": "dollymix7"}, + { "name": "dollymix7-unshaded", "delays": [[0.2, 0.2, 0.2, 0.2]]}, + { "name": "dollymix8"}, + { "name": "dollymix9"}, + { "name": "dollymix9-unshaded", "delays": [[0.2, 0.2, 0.2, 0.2]]}, + { "name": "icon"} + ] +} diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/light.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/light.png new file mode 100644 index 0000000000..55f6724a1c Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/light.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/light_broken.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/light_broken.png new file mode 100644 index 0000000000..6c3eb9a654 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/light_broken.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/meta.json new file mode 100644 index 0000000000..b44648e414 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/mounts.rsi/meta.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation/commit/42e0275d860551197687c571c689c270ff423288; edited by WWDP", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "light" }, + { "name": "light_broken" } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix1-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix1-unshaded.png new file mode 100644 index 0000000000..9113c476ed Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix1-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix1.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix1.png new file mode 100644 index 0000000000..b6eb4b66a3 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix1.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix2-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix2-unshaded.png new file mode 100644 index 0000000000..bb0f858eae Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix2-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix2.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix2.png new file mode 100644 index 0000000000..3d537ed3bc Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix2.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix3-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix3-unshaded.png new file mode 100644 index 0000000000..bb0f858eae Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix3-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix3.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix3.png new file mode 100644 index 0000000000..7b6f4989b9 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix3.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix4-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix4-unshaded.png new file mode 100644 index 0000000000..2034eebe92 Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix4-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix4.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix4.png new file mode 100644 index 0000000000..916c70614f Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix4.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix5-unshaded.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix5-unshaded.png new file mode 100644 index 0000000000..621c8881ac Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix5-unshaded.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix5.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix5.png new file mode 100644 index 0000000000..621c8881ac Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/dollymix5.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/icon.png b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/icon.png new file mode 100644 index 0000000000..c162fa84ef Binary files /dev/null and b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/icon.png differ diff --git a/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/meta.json b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/meta.json new file mode 100644 index 0000000000..7ac543be08 --- /dev/null +++ b/Resources/Textures/_White/Objects/Weapons/Guns/Turrets/rift_lance.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { "name": "dollymix1"}, + { "name": "dollymix2"}, + { "name": "dollymix3"}, + { "name": "dollymix4"}, + { "name": "dollymix5"}, + { "name": "dollymix1-unshaded"}, + { "name": "dollymix2-unshaded"}, + { "name": "dollymix3-unshaded"}, + { "name": "dollymix4-unshaded"}, + { "name": "dollymix5-unshaded"}, + { "name": "icon"} + ] +} diff --git a/Tools/dollymix/readme.txt b/Tools/dollymix/readme.txt new file mode 100644 index 0000000000..d1c21baa4d --- /dev/null +++ b/Tools/dollymix/readme.txt @@ -0,0 +1,19 @@ +Copy these into the .rsi folder you're working on. + +These require the pillow module ("pip install pillow") + +zslice - splits a vertical slice strip produced by MagicaVoxel into separate files. + Expects the source file to be named "dollymix.png". + Asks for vertical size and then will split the image into that many rows. + If "dollymix-unshaded.png" is present, splits that aswell. + Does not automatically remove empty images. + +zicon - uses the same "dollymix.png" file to produce a default sprite for the model. + +ztest - does the same thing as zicon at a higher resolution and different angles. + For checking how the "model" looks without starting the game. + +All file names start with a "z" so that they appear last in the folder when sorted by name. +Also for the purposes of goida. + +Recommended toolchain - MagicaVoxel for initial modeling -> Aseprite for layer edits and very basic animation -> the shit in this folder. \ No newline at end of file diff --git a/Tools/dollymix/zicon.py b/Tools/dollymix/zicon.py new file mode 100644 index 0000000000..1969e63d81 --- /dev/null +++ b/Tools/dollymix/zicon.py @@ -0,0 +1,25 @@ +from PIL import Image +import os, sys + +path = os.getcwd() +basefile = "dollymix" +ext = ".png" +size = int(input("size: ")) +offset = int(input("downward offset (in pixels): ")) + +base = Image.open(os.path.join(path,basefile+ext)) + +reverse = size > 0 +size = abs(size) + +amount = base.height // size + +out = Image.new("RGBA", (size, size), (0,0,0,0)) + +for i in range(amount): + if(reverse): + out.alpha_composite(base.crop((0,size*(amount-1-i),base.width,size*(amount-i))).rotate(90), (0,-i-offset)) + else: + out.alpha_composite(base.crop((0,size*i,base.width,size*(i+1))).rotate(90), (0,-i-offset)) + +out.save(os.path.join(path,"icon.png")) diff --git a/Tools/dollymix/zslice.py b/Tools/dollymix/zslice.py new file mode 100644 index 0000000000..2a7748d2f5 --- /dev/null +++ b/Tools/dollymix/zslice.py @@ -0,0 +1,64 @@ +from PIL import Image +import os, sys + +path = os.getcwd() +basefile = "dollymix" +ext = ".png" +size = int(input("size: ")) +reverse = size > 0 +size = abs(size) + + +base = Image.open(os.path.join(path,basefile+ext)) +amount = base.height // size + +states = [] + +for i in range(amount): + name = basefile+str(i+1) + filename = name+ext + states.append(name) + print(filename) + if(reverse): + base.crop((0,size*(amount-1-i),base.width,size*(amount-i))).save(os.path.join(path,filename)) + else: + base.crop((0,size*i,base.width,size*(i+1))).save(os.path.join(path,filename)) + +unshadedfile = os.path.join(path,basefile+"-unshaded"+ext) +if os.path.exists(unshadedfile): + base = Image.open(unshadedfile) + amount = base.height // size + + for i in range(amount): + name = basefile+str(i+1)+"-unshaded" + filename = name+ext + states.append(name) + print(filename) + if(reverse): + base.crop((0,size*(amount-1-i),base.width,size*(amount-i))).save(os.path.join(path,filename)) + else: + base.crop((0,size*i,base.width,size*(i+1))).save(os.path.join(path,filename)) + +if(len(states) == 0): + exit(1) + +metaheader = """{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "WWDP autogenerated", + "size": { + "x": 32, + "y": 32 + }, + "states": [ +""" +metaentry = """ {{ "name": "{0}" }}""" +metaterm = """ + ] +}""" + +states.append("icon") +with open(os.path.join(path,"meta.json"), 'w') as metajson: + metajson.write(metaheader) + metajson.write(",\n".join([metaentry.format(state) for state in states])) + metajson.write(metaterm) \ No newline at end of file diff --git a/Tools/dollymix/ztest.py b/Tools/dollymix/ztest.py new file mode 100644 index 0000000000..bbbefb9206 --- /dev/null +++ b/Tools/dollymix/ztest.py @@ -0,0 +1,36 @@ +from PIL import Image +import os, sys + +path = os.getcwd() +basefile = "dollymix" +ext = ".png" +size = int(input("size: ")) +offset = float(input("offset: ")) +repeat = int(input("repeat: ")) + +base = Image.open(os.path.join(path,basefile+ext)) + +reverse = size > 0 +size = abs(size) + +amount = base.height // size + +testfolder = os.path.join(path, "test") +if not os.path.exists(testfolder): + os.makedirs(testfolder) + +copies = 24 +scaleFactor = 5 +for rot in range(copies): + angle = rot*(360/copies) + print(f"{angle:03}.png") + out = Image.new("RGBA", (size*scaleFactor, size*scaleFactor), (0,0,0,0)) + for i in range(amount): + for r in range(repeat): + vertOffset = round(-(i-1+r/repeat)*scaleFactor*offset) + if(reverse): + out.alpha_composite(base.crop((0,size*(amount-1-i),base.width,size*(amount-i))).resize((size*scaleFactor, size*scaleFactor), 0).rotate(angle), (0,vertOffset)) + else: + out.alpha_composite(base.crop((0,size*i,base.width,size*(i+1))).resize((size*scaleFactor, size*scaleFactor), 0).rotate(angle), (0,vertOffset)) + + out.save(os.path.join(path, "test", f"{angle:03}.png"))