Compare commits

..
2 Commits
Author SHA1 Message Date
Vanessa 45a0ccec2a Limited arti scaling 2026-07-09 11:00:23 -05:00
Vanessa d9bb403264 more glim glim 2026-07-08 23:15:07 -05:00
590 changed files with 2861 additions and 21230 deletions
@@ -2,7 +2,6 @@ using Content.Client.Cargo.UI;
using Content.Shared.Cargo.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
using Content.Shared._DV.Cargo.Components; // DeltaV: Bounty claim messages
namespace Content.Client.Cargo.BUI;
@@ -31,18 +30,6 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
{
SendMessage(new BountySkipMessage(id));
};
// DeltaV: bounty claim stuff begins
_menu.OnClaimButtonPressed += id =>
{
SendMessage(new BountyClaimedMessage(id));
};
_menu.OnStatusOptionSelected += (id, status) =>
{
SendMessage(new BountySetStatusMessage(id, status));
};
// DeltaV: bounty claim stuff ends
}
protected override void UpdateState(BoundUserInterfaceState message)
+4 -14
View File
@@ -10,8 +10,6 @@
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<RichTextLabel Name="RewardLabel"/>
<RichTextLabel Name="ManifestLabel"/>
<RichTextLabel Name="ClaimedBylabel"/> <!-- DeltaV bounty claim -->
<RichTextLabel Name="StatusLabel"/> <!-- DeltaV bounty claim -->
</BoxContainer>
<Control MinWidth="10"/>
<BoxContainer Orientation="Vertical" MinWidth="120">
@@ -19,22 +17,14 @@
<Button Name="PrintButton"
Text="{Loc 'bounty-console-label-button-text'}"
HorizontalExpand="False"
StyleClasses="OpenBoth"/>
HorizontalAlignment="Right"
StyleClasses="OpenRight"/>
<Button Name="SkipButton"
Text="{Loc 'bounty-console-skip-button-text'}"
HorizontalExpand="True"
HorizontalExpand="False"
HorizontalAlignment="Right"
StyleClasses="OpenLeft"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" MinWidth="120"> <!-- Begin DeltaV bounty claim content -->
<Button Name="ClaimButton"
Text= "{Loc 'bounty-console-claim-button-text'}"
HorizontalExpand="False"
StyleClasses="OpenRight"/>
<OptionButton Name="BountyStatusSelector"
Access="Public"
StyleClasses="OpenBoth"
HorizontalExpand="True"/>
</BoxContainer> <!-- End DeltaV content-->
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
</BoxContainer>
</BoxContainer>
@@ -17,8 +17,6 @@ public sealed partial class BountyEntry : BoxContainer
public Action? OnLabelButtonPressed;
public Action? OnSkipButtonPressed;
public Action? OnClaimButtonPressed; // DeltaV
public Action? OnStatusOptionSelected; // DeltaV
public TimeSpan EndTime;
public TimeSpan UntilNextSkip;
@@ -47,20 +45,6 @@ public sealed partial class BountyEntry : BoxContainer
PrintButton.OnPressed += _ => OnLabelButtonPressed?.Invoke();
SkipButton.OnPressed += _ => OnSkipButtonPressed?.Invoke();
// Begin DeltaV bounty claiming
ClaimButton.OnPressed += _ => OnClaimButtonPressed?.Invoke();
BountyStatusSelector.AddItem(Loc.GetString($"bounty-console-status-{nameof(CargoBountyStatus.Undelivered)}"), 0);
BountyStatusSelector.AddItem(Loc.GetString($"bounty-console-status-{nameof(CargoBountyStatus.Waiting)}"), 1);
BountyStatusSelector.AddItem(Loc.GetString($"bounty-console-status-{nameof(CargoBountyStatus.OnShuttle)}"), 2);
BountyStatusSelector.Select((int) bounty.Status);
BountyStatusSelector.ToolTip = Loc.GetString($"bounty-console-status-tooltip-{bounty.Status.ToString()}");
var claimedByText = string.IsNullOrEmpty(bounty.ClaimedBy) ? Loc.GetString("bounty-console-claimed-by-none") : bounty.ClaimedBy;
ClaimedBylabel.SetMarkup(Loc.GetString("bounty-console-claimed-by", ("claimant", claimedByText)));
StatusLabel.SetMarkup(Loc.GetString($"bounty-console-formatted-status-{bounty.Status.ToString()}"));
// End DeltaV bounty claiming
}
private void UpdateSkipButton(float deltaSeconds)
+2 -3
View File
@@ -1,9 +1,8 @@
<!--DeltaV - SetSize was 550, now 750 to accomodate bounty claim UI -->
<controls:FancyWindow xmlns="https://spacestation14.io"
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'bounty-console-menu-title'}"
SetSize="750 420"
SetSize="550 420"
MinSize="400 350">
<BoxContainer Orientation="Vertical"
VerticalExpand="True"
@@ -11,8 +11,6 @@ public sealed partial class CargoBountyMenu : FancyWindow
{
public Action<string>? OnLabelButtonPressed;
public Action<string>? OnSkipButtonPressed;
public Action<string>? OnClaimButtonPressed; // DeltaV
public Action<string, int>? OnStatusOptionSelected; // DeltaV
public CargoBountyMenu()
{
@@ -33,8 +31,6 @@ public sealed partial class CargoBountyMenu : FancyWindow
var entry = new BountyEntry(b, untilNextSkip);
entry.OnLabelButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
entry.OnSkipButtonPressed += () => OnSkipButtonPressed?.Invoke(b.Id);
entry.OnClaimButtonPressed += () => OnClaimButtonPressed?.Invoke(b.Id); // DeltaV
entry.BountyStatusSelector.OnItemSelected += args => OnStatusOptionSelected?.Invoke(b.Id, args.Id); // DeltaV
BountyEntriesContainer.AddChild(entry);
}
-3
View File
@@ -34,9 +34,6 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.RotateStoredItem);
common.AddFunction(ContentKeyFunctions.SaveItemLocation);
common.AddFunction(ContentKeyFunctions.Point);
// Floofstation section
common.AddFunction(ContentKeyFunctions.OfferItem);
// Floofstation section end
common.AddFunction(ContentKeyFunctions.ZoomOut);
common.AddFunction(ContentKeyFunctions.ZoomIn);
common.AddFunction(ContentKeyFunctions.ResetZoom);
@@ -75,11 +75,9 @@ public sealed partial class CrewMonitoringNavMapControl : NavMapControl
if (!LocalizedNames.TryGetValue(netEntity, out var name))
name = Loc.GetString("navmap-unknown-entity");
var pos = _xform.ToMapCoordinates(blip.Coordinates); // DeltaV - map-coordinates
var message = name + "\n" + Loc.GetString("navmap-location",
("x", MathF.Round(pos.X)), // DeltaV - map-coordinates
("y", MathF.Round(pos.Y))); // DeltaV - map-coordinates
("x", MathF.Round(blip.Coordinates.X)),
("y", MathF.Round(blip.Coordinates.Y)));
_trackedEntityLabel.Text = message;
_trackedEntityPanel.Visible = true;
@@ -208,7 +208,6 @@ namespace Content.Client.Options.UI.Tabs
AddButton(ContentKeyFunctions.MovePulledObject);
AddButton(ContentKeyFunctions.ReleasePulledObject);
AddButton(ContentKeyFunctions.Point);
AddButton(ContentKeyFunctions.OfferItem); // Floofstation
AddButton(ContentKeyFunctions.RotateObjectClockwise);
AddButton(ContentKeyFunctions.RotateObjectCounterclockwise);
AddButton(ContentKeyFunctions.FlipObject);
@@ -11,7 +11,6 @@ using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player; // DeltaV
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using static Robust.Shared.Maths.Color;
@@ -23,7 +22,6 @@ namespace Content.Client.Overlays;
/// </summary>
public sealed class EntityHealthBarOverlay : Overlay
{
[Dependency] private readonly IPlayerManager _player = default!; // DeltaV
private readonly IEntityManager _entManager;
private readonly IPrototypeManager _prototype;
@@ -42,8 +40,6 @@ public sealed class EntityHealthBarOverlay : Overlay
public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager prototype)
{
IoCManager.InjectDependencies(this); // DeltaV
_entManager = entManager;
_prototype = prototype;
_transform = _entManager.System<SharedTransformSystem>();
@@ -73,11 +69,6 @@ public sealed class EntityHealthBarOverlay : Overlay
out var damageableComponent,
out var spriteComponent))
{
// BEGIN DeltaV - You can't see your own bar :godo:
if (_player.LocalEntity is { } player && player.Id == uid.Id)
continue;
// END DeltaV
if (statusIcon != null && !_statusIconSystem.IsVisible((uid, _entManager.GetComponent<MetaDataComponent>(uid)), statusIcon))
continue;
@@ -1,73 +0,0 @@
using System.Linq;
using Content.Shared._DV.Forensics;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Shared.Containers;
using Robust.Shared.Utility;
namespace Content.Client._DV.Forensics;
public sealed class DVItemSlotVisualsSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
private static readonly ResPath TextureRoot = new("/Textures");
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DVItemSlotVisualsComponent, EntInsertedIntoContainerMessage>(OnInsertedIntoContainer);
SubscribeLocalEvent<DVItemSlotVisualsComponent, EntRemovedFromContainerMessage>(OnRemovedFromContainer);
}
private void RefreshVisuals(Entity<DVItemSlotVisualsComponent> ent)
{
var slot = _container.EnsureContainer<ContainerSlot>(ent, ent.Comp.ItemSlot);
if (slot.ContainedEntity is { } contained)
{
_sprite.CopySprite(contained, ent.Owner);
_sprite.AddLayer(ent.Owner, ent.Comp.FilledSprite);
}
else
{
var sprite = Comp<SpriteComponent>(ent);
var count = sprite.AllLayers.Count();
for (var i = count - 1; i >= 0; i--)
{
_sprite.RemoveLayer((ent, sprite), i);
}
if (ent.Comp.UnfilledSprite is not SpriteSpecifier.Rsi rsi)
{
throw new InvalidOperationException($"{ToPrettyString(ent)} has an unfilled sprite that's not an RSI");
}
if (!_resourceCache.TryGetResource<RSIResource>(TextureRoot / rsi.RsiPath, out var res))
{
throw new InvalidOperationException($"{ToPrettyString(ent)} has invalid RSI: {TextureRoot / rsi.RsiPath}");
}
_sprite.SetBaseRsi(ent.Owner, res.RSI);
_sprite.AddLayer(ent.Owner, ent.Comp.UnfilledSprite);
}
}
private void OnInsertedIntoContainer(Entity<DVItemSlotVisualsComponent> ent, ref EntInsertedIntoContainerMessage args)
{
if (args.Container.ID != ent.Comp.ItemSlot)
return;
RefreshVisuals(ent);
}
private void OnRemovedFromContainer(Entity<DVItemSlotVisualsComponent> ent, ref EntRemovedFromContainerMessage args)
{
if (args.Container.ID != ent.Comp.ItemSlot)
return;
RefreshVisuals(ent);
}
}
@@ -0,0 +1,5 @@
using Content.Shared._DV.Silicons;
namespace Content.Client._DV.Silicons;
public sealed class SiliconEmpSystem : SharedSiliconEmpSystem;
@@ -1,71 +0,0 @@
using System.Numerics;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Shared.Enums;
using Robust.Shared.Utility;
namespace Content.Client._Floof.OfferItem;
public sealed class OfferItemIndicatorsOverlay : Overlay
{
private readonly IInputManager _inputManager;
private readonly IEntityManager _entMan;
private readonly IEyeManager _eye;
private readonly OfferItemSystem _offer;
private readonly Texture _sight;
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
private readonly Color _mainColor = Color.White.WithAlpha(0.3f);
private readonly Color _strokeColor = Color.Black.WithAlpha(0.5f);
private readonly float _scale = 0.6f; // 1 is a little big
public OfferItemIndicatorsOverlay(IInputManager input, IEntityManager entMan,
IEyeManager eye, OfferItemSystem offerSys)
{
_inputManager = input;
_entMan = entMan;
_eye = eye;
_offer = offerSys;
var spriteSys = _entMan.EntitySysManager.GetEntitySystem<SpriteSystem>();
_sight = spriteSys.Frame0(new SpriteSpecifier.Rsi(new("/Textures/_Floof/Interface/Misc/give_item.rsi"), "give_item"));
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (!_offer.IsInOfferMode())
return false;
return base.BeforeDraw(in args);
}
protected override void Draw(in OverlayDrawArgs args)
{
var mouseScreenPosition = _inputManager.MouseScreenPosition;
var mousePosMap = _eye.PixelToMap(mouseScreenPosition);
if (mousePosMap.MapId != args.MapId)
return;
var mousePos = mouseScreenPosition.Position;
var uiScale = (args.ViewportControl as Control)?.UIScale ?? 1f;
var limitedScale = uiScale > 1.25f ? 1.25f : uiScale;
DrawSight(_sight, args.ScreenHandle, mousePos, limitedScale * _scale);
}
private void DrawSight(Texture sight, DrawingHandleScreen screen, Vector2 centerPos, float scale)
{
var sightSize = sight.Size * scale;
var expandedSize = sightSize + new Vector2(7f, 7f);
screen.DrawTextureRect(sight,
UIBox2.FromDimensions(centerPos - sightSize * 0.5f, sightSize), _strokeColor);
screen.DrawTextureRect(sight,
UIBox2.FromDimensions(centerPos - expandedSize * 0.5f, expandedSize), _mainColor);
}
}
@@ -1,39 +0,0 @@
using Content.Shared._Floof.OfferItem;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
namespace Content.Client._Floof.OfferItem;
public sealed class OfferItemSystem : SharedOfferItemSystem
{
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IEyeManager _eye = default!;
public override void Initialize()
{
base.Initialize();
_overlayManager.AddOverlay(new OfferItemIndicatorsOverlay(
_inputManager,
EntityManager,
_eye,
this));
}
public override void Shutdown()
{
_overlayManager.RemoveOverlay<OfferItemIndicatorsOverlay>();
base.Shutdown();
}
public bool IsInOfferMode()
{
var entity = _playerManager.LocalEntity;
if (entity == null)
return false;
return IsInOfferMode(entity.Value);
}
}
@@ -1,6 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Access.Systems; // DeltaV
using Content.Server.Cargo.Components;
using Content.Server.NameIdentifier;
using Content.Shared.Access.Components;
@@ -21,7 +20,6 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Shared._DV.Cargo.Components; // DeltaV: Bounty claim messages
namespace Content.Server.Cargo.Systems;
@@ -30,7 +28,6 @@ public sealed partial class CargoSystem
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly NameIdentifierSystem _nameIdentifier = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSys = default!;
[Dependency] private readonly IdCardSystem _idCard = default!; // DeltaV
private static readonly ProtoId<NameIdentifierGroupPrototype> BountyNameIdentifierGroup = "Bounty";
@@ -43,8 +40,6 @@ public sealed partial class CargoSystem
SubscribeLocalEvent<CargoBountyConsoleComponent, BoundUIOpenedEvent>(OnBountyConsoleOpened);
SubscribeLocalEvent<CargoBountyConsoleComponent, BountyPrintLabelMessage>(OnPrintLabelMessage);
SubscribeLocalEvent<CargoBountyConsoleComponent, BountySkipMessage>(OnSkipBountyMessage);
SubscribeLocalEvent<CargoBountyConsoleComponent, BountyClaimedMessage>(OnBountyClaimedMessage); // DeltaV
SubscribeLocalEvent<CargoBountyConsoleComponent, BountySetStatusMessage>(OnSetBountyStatusMessage); // DeltaV
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
@@ -116,72 +111,6 @@ public sealed partial class CargoSystem
_audio.PlayPvs(component.SkipSound, uid);
}
// Begin DeltaV bounty claim system
private void OnSetBountyStatusMessage(Entity<CargoBountyConsoleComponent> ent, ref BountySetStatusMessage args)
{
if (_station.GetOwningStation(ent.Owner) is not { } station || !TryComp<StationCargoBountyDatabaseComponent>(station, out var bountyDbComp))
return;
for (var i = 0; i < bountyDbComp.Bounties.Count; i++)
{
var bounty = bountyDbComp.Bounties[i];
if (bounty.Id != args.BountyId)
continue;
var newData = new CargoBountyData
{
Id = bounty.Id,
Bounty = bounty.Bounty,
ClaimedBy = bounty.ClaimedBy,
Status = (CargoBountyStatus)args.Status,
};
bountyDbComp.Bounties[i] = newData;
}
var untilNextSkip = bountyDbComp.NextSkipTime - Timing.CurTime;
_uiSystem.SetUiState(ent.Owner, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(bountyDbComp.Bounties, bountyDbComp.History, untilNextSkip));
}
private void OnBountyClaimedMessage(Entity<CargoBountyConsoleComponent> ent, ref BountyClaimedMessage args)
{
if (_station.GetOwningStation(ent.Owner) is not { } station || !TryComp<StationCargoBountyDatabaseComponent>(station, out var bountyDbComp))
return;
for (var i = 0; i < bountyDbComp.Bounties.Count; i++)
{
var bounty = bountyDbComp.Bounties[i];
if (bounty.Id != args.BountyId)
continue;
string name;
if (_idCard.TryFindIdCard(args.Actor, out var idCard) && idCard.Comp.FullName != null)
{
name = idCard.Comp.FullName;
}
else
{
name = Loc.GetString("bounty-console-claimed-by-unknown");
}
var newData = new CargoBountyData
{
Id = bounty.Id,
Bounty = bounty.Bounty,
ClaimedBy = name.Equals(bounty.ClaimedBy) ? string.Empty : name,
Status = bounty.Status,
};
bountyDbComp.Bounties[i] = newData;
}
var untilNextSkip = bountyDbComp.NextSkipTime - Timing.CurTime;
_uiSystem.SetUiState(ent.Owner, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(bountyDbComp.Bounties, bountyDbComp.History, untilNextSkip));
}
// End DeltaV bounty claim system
public void SetupBountyLabel(EntityUid uid, EntityUid stationId, CargoBountyData bounty, PaperComponent? paper = null, CargoBountyLabelComponent? label = null)
{
if (!Resolve(uid, ref paper, ref label) || !_protoMan.Resolve<CargoBountyPrototype>(bounty.Bounty, out var prototype))
+1
View File
@@ -1,4 +1,5 @@
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Damage; // DeltaV - EMP damage
using Content.Server.Power.EntitySystems;
using Content.Server.Radio;
using Content.Server.SurveillanceCamera;
@@ -23,7 +23,6 @@ using Robust.Shared.Timing;
using System.Linq;
using Content.Shared.EntityEffects.Effects.Solution;
using TimedDespawnComponent = Robust.Shared.Spawners.TimedDespawnComponent;
using Content.Server.Body.Components; // Delta V
namespace Content.Server.Fluids.EntitySystems;
@@ -268,8 +267,7 @@ public sealed class SmokeSystem : EntitySystem
if (!_solutionContainerSystem.ResolveSolution(entity, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution) || bloodSolution.AvailableVolume <= 0)
return;
var blockIngestion = _internals.AreInternalsWorking(entity)
|| !HasComp<RespiratorComponent>(entity); // Starlight - Shadekin does not breathe and "AreInternalsWorking" does not check for that
var blockIngestion = _internals.AreInternalsWorking(entity);
var cloneSolution = solution.Clone();
var availableTransfer = FixedPoint2.Min(cloneSolution.Volume, component.TransferRate);
@@ -18,7 +18,6 @@ using Content.Shared.Zombies;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using System.Globalization;
using System.Linq; // DeltaV
namespace Content.Server.GameTicking.Rules;
@@ -127,21 +126,15 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
// BEGIN DeltaV - Change mode to survival if zombies die
var anyInitialInfectedAlive = EntityQuery<InitialInfectedComponent, MobStateComponent>(false)
.Any(x => x.Item2.CurrentState != MobState.Dead);
var anyLivingZombies = EntityQuery<ZombieComponent, MobStateComponent>(false)
.Any(x => x.Item2.CurrentState != MobState.Dead);
var anyPendingZombies = EntityQuery<PendingZombieComponent>(false).Any();
// All II turned/dead, all entities that have turned are dead, and there are no more pending zombies
if (!anyInitialInfectedAlive && !anyLivingZombies && !anyPendingZombies)
var infectedPercent = GetInfectedFraction(false);
if (Math.Round(infectedPercent, 0) == 0) // All zombies defeated
{
_roundEnd.DoRoundEndBehavior(zombieRuleComponent.ZombieRoundEndBehavior, zombieRuleComponent.ZombieShuttleDelay);
zombieRuleComponent.ZombieRoundEndBehavior = RoundEndBehavior.Nothing; // stop this check in the future
}
// END DeltaV
if (GetInfectedFraction(false) > zombieRuleComponent.ZombieShuttleCallPercentage && !_roundEnd.IsRoundEndRequested())
if (infectedPercent > zombieRuleComponent.ZombieShuttleCallPercentage && !_roundEnd.IsRoundEndRequested()) // DeltaV - Move GetInfectedFraction to var
{
foreach (var station in _station.GetStations())
{
+1 -10
View File
@@ -41,7 +41,6 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Content.Server.Mobs; // Starlight
namespace Content.Server.Ghost
{
@@ -620,15 +619,7 @@ namespace Content.Server.Ghost
_damageable.GetTotalDamage((playerEntity.Value, damageable));
}
// Starlight - Start
//DamageSpecifier damage = new(_prototypeManager.Index(AsphyxiationDamageType), dealtDamage);
var damageType = _prototypeManager.Index(AsphyxiationDamageType);
if (TryComp<DeathgaspComponent>(playerEntity, out var deathgasp))
damageType = _prototypeManager.Index(deathgasp.DamageType);
DamageSpecifier damage = new(damageType, dealtDamage);
// Starlight - End
DamageSpecifier damage = new(_prototypeManager.Index(AsphyxiationDamageType), dealtDamage);
_damageable.ChangeDamage(playerEntity.Value, damage, true);
}
+1 -9
View File
@@ -1,6 +1,4 @@
using Content.Shared.Chat.Prototypes; // Starlight
using Content.Shared.Damage.Prototypes; // Starlight
using Robust.Shared.Prototypes;
using Content.Shared.Chat.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Mobs;
@@ -23,10 +21,4 @@ public sealed partial class DeathgaspComponent : Component
/// </summary>
[DataField]
public bool NeedsCritical = true;
/// <summary>
/// Starlight - The damage that is taken when succumbing
/// </summary>
[DataField]
public ProtoId<DamageTypePrototype> DamageType = "Asphyxiation";
}
@@ -55,13 +55,9 @@ public sealed class PseudoItemSystem : SharedPseudoItemSystem
protected override void OnGettingPickedUpAttempt(EntityUid uid, PseudoItemComponent component, GettingPickedUpAttemptEvent args)
{
// Floof - changed this a bit to actually start a do-after
// Try to pick the entity up instead first
if (args.User != args.Item
&& TryComp<CarriableComponent>(uid, out var carriable)
&& _carrying.CanCarry(args.User, (uid, carriable)))
if (args.User != args.Item && _carrying.TryCarry(args.User, uid))
{
_carrying.StartCarryDoAfter(args.User, (uid, carriable));
args.Cancel();
return;
}
@@ -209,24 +209,20 @@ namespace Content.Server.Psionics.Glimmer
private void OnDestroyed(EntityUid uid, SharedGlimmerReactiveComponent component, DestructionEventArgs args)
{
var proberCoords = Transform(uid).Coordinates;
Spawn("MaterialBluespace1", Transform(uid).Coordinates);
var tier = _glimmerSystem.GetGlimmerTier();
if (tier < GlimmerTier.High)
return;
var explosionMultiplier = 2;
if (_glimmerSystem.GetGlimmerTier() == GlimmerTier.Critical) // YOU DONE FUCKED UP
explosionMultiplier = 3;
var totalIntensity = (float) (_glimmerSystem.Glimmer * 2);
var slope = (float) (11 - _glimmerSystem.Glimmer / 100);
var maxIntensity = 20;
var totalIntensity = (float)(_glimmerSystem.Glimmer * explosionMultiplier);
var slope = (float)(11 - _glimmerSystem.Glimmer / 100);
var maxIntensity = 75; // Same as syndicate bomb
var removed = _glimmerSystem.Glimmer * _random.NextFloat(0.06f, 0.08f);
_glimmerSystem.Glimmer -= (int)removed;
var removed = (float) _glimmerSystem.Glimmer * _random.NextFloat(0.06f, 0.08f);
_glimmerSystem.Glimmer -= (int) removed;
BeamRandomNearProber(uid, _glimmerSystem.Glimmer / 350, _glimmerSystem.Glimmer / 50);
_explosionSystem.QueueExplosion(uid, "Default", totalIntensity, slope, maxIntensity, addLog: true);
Spawn("MaterialBluespace1", proberCoords); // Congrats on your bluespace!
_explosionSystem.QueueExplosion(uid, "Default", totalIntensity, slope, maxIntensity);
}
private void OnUnanchorAttempt(EntityUid uid, SharedGlimmerReactiveComponent component, UnanchorAttemptEvent args)
@@ -234,7 +230,7 @@ namespace Content.Server.Psionics.Glimmer
if (component.Locked)
{
_sharedAudioSystem.PlayPvs(component.ShockNoises, args.User);
_electrocutionSystem.TryDoElectrocution(args.User, uid, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false);
_electrocutionSystem.TryDoElectrocution(args.User, null, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false);
args.Cancel();
}
}
@@ -184,8 +184,7 @@ public sealed class OracleSystem : EntitySystem
while (i != 0)
{
var entityToSpawn = _random.Next(0, 2) == 0 ? "MaterialBluespace1" : "CrystalNormality";
Spawn(entityToSpawn, Transform(user).Coordinates);
Spawn("MaterialBluespace1", Transform(user).Coordinates);
i--;
}
@@ -75,7 +75,8 @@ public sealed partial class CosmicFinaleComponent : Component
{ "Blunt", 2.25},
{ "Cold", 2.25},
{ "Radiation", 2.25},
{ "Asphyxiation", 2.25}
{ "Asphyxiation", 2.25},
{ "Ion", 2.25}
}
};
}
@@ -174,7 +174,7 @@ public sealed partial class CosmicCultSystem : SharedCosmicCultSystem
if (!EntityIsCultist(args.Equipee))
{
_statusEffects.TryAddStatusEffect<CosmicEntropyDebuffComponent>(args.Equipee, EntropicDegen, TimeSpan.FromDays(1), true); // TimeSpan.MaxValue causes a crash here, so we use FromDays(1) instead.
if (TryComp<CosmicEntropyDebuffComponent>(args.Equipee, out var comp)) comp.Degen = new(){DamageDict = new(){{"Cold", 0.5}, {"Asphyxiation", 1.5}}};
if (TryComp<CosmicEntropyDebuffComponent>(args.Equipee, out var comp)) comp.Degen = new(){DamageDict = new(){{"Cold", 0.5}, {"Asphyxiation", 1.5}, {"Ion", 1.5}}};
}
}
@@ -188,7 +188,7 @@ public sealed partial class CosmicCultSystem : SharedCosmicCultSystem
if (!EntityIsCultist(args.User))
{
_statusEffects.TryAddStatusEffect<CosmicEntropyDebuffComponent>(args.User, EntropicDegen, TimeSpan.FromDays(1), true);
if (TryComp<CosmicEntropyDebuffComponent>(args.User, out var comp)) comp.Degen = new(){DamageDict = new(){{"Cold", 0.5}, {"Asphyxiation", 1.5}}};
if (TryComp<CosmicEntropyDebuffComponent>(args.User, out var comp)) comp.Degen = new(){DamageDict = new(){{"Cold", 0.5}, {"Asphyxiation", 1.5}, {"Ion", 1.5}}};
_popup.PopupEntity(Loc.GetString("cosmiccult-gear-pickup", ("ITEM", args.Equipped)), args.User, args.User, PopupType.MediumCaution);
}
}
@@ -75,7 +75,8 @@ public sealed class CosmicRiftSystem : EntitySystem
if (TryComp<CosmicEntropyDebuffComponent>(mob, out var debuff)) debuff.Degen =
new(){DamageDict = new(){
{"Cold", 0.05 * damageMultiplier},
{"Asphyxiation", 0.15 * damageMultiplier}
{"Asphyxiation", 0.15 * damageMultiplier},
{"Ion", 0.15 * damageMultiplier}
}};
}
}
@@ -0,0 +1,5 @@
using Content.Shared._DV.Silicons;
namespace Content.Server._DV.Silicons;
public sealed class SiliconEmpSystem : SharedSiliconEmpSystem;
@@ -109,10 +109,8 @@ public sealed class FugitiveRule : StationEventSystem<FugitiveRuleComponent>
var report = new FormattedMessage();
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-title"));
report.PushNewline();
report.PushNewline();
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-first-line"));
report.PushNewline();
report.PushNewline();
if (!TryComp<HumanoidProfileComponent>(uid, out var humanoid))
{
@@ -123,28 +121,22 @@ public sealed class FugitiveRule : StationEventSystem<FugitiveRuleComponent>
var species = PrototypeManager.Index(humanoid.Species);
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-morphotype", ("species", Loc.GetString(species.Name))));
report.PushNewline();
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-age", ("age", humanoid.Age)));
report.PushNewline();
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-sex", ("sex", humanoid.Sex)));
report.PushNewline();
if (TryComp<PhysicsComponent>(uid, out var physics))
{
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-weight", ("weight", Math.Round(physics.FixturesMass))));
report.PushNewline();
}
// add a random identifying quality that officers can use to track them down
report.AddMarkupOrThrow(RobustRandom.Next(0, 2) switch
{
0 => Loc.GetString("fugitive-report-detail-dna", ("dna", GetDNA(uid))),
_ => Loc.GetString("fugitive-report-detail-prints", ("prints", GetPrints(uid)))
});
report.PushNewline();
report.PushNewline();
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-crimes-header"));
report.PushNewline();
// generate some random crimes to avoid this situation
// "officer what are my charges?"
// "uh i dunno a piece of paper said to arrest you thats it"
@@ -180,7 +172,6 @@ public sealed class FugitiveRule : StationEventSystem<FugitiveRuleComponent>
{
var count = RobustRandom.Next(rule.MinCounts, rule.MaxCounts + 1);
report.AddMarkupOrThrow(Loc.GetString("fugitive-report-crime", ("crime", Loc.GetString(crime)), ("count", count)));
report.PushNewline();
}
}
}
@@ -1,44 +0,0 @@
using Content.Shared.Store;
using Content.Shared.Store.Components;
using Robust.Shared.Prototypes;
namespace Content.Server._DV.Store.Conditions;
/// <summary>
/// XOR (eXclusive-OR) Buy Condition
/// A condition where that blocks buying a listing if another listing
/// specified is bought before it. Used to enforce that a traitor
/// can only buy 1 of X options.
///
/// Primarily used for choose-your-own-adventure DAGD Implants.
/// </summary>
public sealed partial class XORBuyCondition : ListingCondition
{
/// <summary>
/// Listing(s) that if bought, block this purchase, if any.
/// </summary>
[DataField(required: true)]
public HashSet<ProtoId<ListingPrototype>>? Listings;
public override bool Condition(ListingConditionArgs args)
{
if (!args.EntityManager.TryGetComponent<StoreComponent>(args.StoreEntity, out var storeComp))
return false;
var allListings = storeComp.FullListingsCatalog;
if (Listings != null)
{
foreach (var blacklistListing in Listings)
{
foreach (var listing in allListings)
{
if (listing.ID == blacklistListing.Id && listing.PurchaseAmount > 0)
return false; // it was purchased, so return false to fail the condition
}
}
}
return true; // If no purchases were found, return true
}
}
-163
View File
@@ -1,163 +0,0 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Numerics;
using System.Text.RegularExpressions;
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Shared.Maths;
using Robust.Shared.Toolshed;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Utility;
namespace Content.Server._DV.Toolshed;
/// <summary>
/// An extended version of the engine's <c>do</c> command. Runs a console command once per piped value,
/// substituting <c>$NAME</c> tokens in the command string first.
/// </summary>
/// <remarks>
/// On top of the built-in tokens that <c>do</c> supports (<c>$ID</c>, <c>$PID</c>, <c>$WX</c>, <c>$WY</c>,
/// <c>$LX</c>, <c>$LY</c>, <c>$SELF</c>), any other <c>$name</c> is resolved as a toolshed variable and
/// converted to a string. Tokens that don't resolve to anything are left untouched.
///
/// Where the command actually runs is explicit:
/// <list type="bullet">
/// <item><c>doext:client</c> sends it back down to the calling user's own client to run locally. This is what
/// you want for client-side commands like <c>exec</c>, which resolve paths against the client's user data.</item>
/// <item><c>doext:server</c> runs it server-side as the calling session, like <c>do</c> does.</item>
/// </list>
/// </remarks>
/// <example><code>
/// self doext:client "exec /Script_$var.txt"
/// i 5 => $count; self doext:server "somecommand $count"
/// </code></example>
[ToolshedCommand(Name = "doext"), AdminCommand(AdminFlags.Debug)]
public sealed class DoExtCommand : ToolshedCommand
{
/// <summary>
/// Matches a <c>$name</c> token. Names use the same character set as toolshed variable names, so this
/// matches whole identifiers - <c>$IDLE</c> resolves as "IDLE" rather than being mangled into <c>$ID</c>.
/// </summary>
private static readonly Regex TokenRegex = new(@"\$(\w+)", RegexOptions.Compiled);
[Dependency] private readonly IConsoleHost _console = default!;
private SharedTransformSystem? _xform;
/// <summary>
/// Sends the command back down to the calling user's client, which runs it locally.
/// </summary>
[CommandImplementation("client"), TakesPipedTypeAsGeneric]
public IEnumerable<T> Client<T>(IInvocationContext ctx, [PipedArgument] IEnumerable<T> input, string command)
{
// No session means there's no client to hand this back to - e.g. the server console.
if (ctx.Session is not { } session)
{
ctx.ReportError(new NoClientSessionError());
yield break;
}
foreach (var value in input)
{
_console.RemoteExecuteCommand(session, Substitute(command, value, ctx));
yield return value;
}
}
/// <summary>
/// Runs the command on the server as the calling session.
/// </summary>
[CommandImplementation("server"), TakesPipedTypeAsGeneric]
public IEnumerable<T> Server<T>(IInvocationContext ctx, [PipedArgument] IEnumerable<T> input, string command)
{
foreach (var value in input)
{
_console.ExecuteCommand(ctx.Session, Substitute(command, value, ctx));
yield return value;
}
}
private string Substitute<T>(string command, T value, IInvocationContext ctx)
{
return TokenRegex.Replace(command, match =>
{
var name = match.Groups[1].Value;
if (TryGetBuiltin(name, value, ctx, out var builtin))
return builtin;
// Anything else is looked up as a toolshed variable and implicitly stringified.
if (ctx.ReadVar(name) is { } variable)
return Stringify(variable);
// Unresolved, so leave the token alone rather than silently blanking it.
return match.Value;
});
}
private bool TryGetBuiltin<T>(string name, T value, IInvocationContext ctx, [NotNullWhen(true)] out string? result)
{
switch (name)
{
case "SELF":
result = Stringify(value);
return true;
case "PID":
result = (ctx.Session?.AttachedEntity ?? EntityUid.Invalid).ToString();
return true;
}
// The remaining tokens are all positional, so they only apply when piping entities.
if (value is not EntityUid uid)
{
result = null;
return false;
}
switch (name)
{
case "ID":
result = uid.ToString();
return true;
case "WX":
result = Number(WorldPosition(uid).X);
return true;
case "WY":
result = Number(WorldPosition(uid).Y);
return true;
case "LX":
result = Number(Transform(uid).Coordinates.X);
return true;
case "LY":
result = Number(Transform(uid).Coordinates.Y);
return true;
}
result = null;
return false;
}
private Vector2 WorldPosition(EntityUid uid)
{
_xform ??= GetSys<SharedTransformSystem>();
return _xform.GetWorldPosition(uid);
}
private static string Number(float value) => value.ToString(CultureInfo.InvariantCulture);
private static string Stringify(object? value) => value?.ToString() ?? string.Empty;
}
public sealed class NoClientSessionError : IConError
{
public FormattedMessage DescribeInner()
{
return FormattedMessage.FromUnformatted("There is no client to run this on. doext:client must be run by a player, not the server console.");
}
public string? Expression { get; set; }
public Vector2i? IssueSpan { get; set; }
public StackTrace? Trace { get; set; }
}
-136
View File
@@ -1,136 +0,0 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Shared.Maths;
using Robust.Shared.Toolshed;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Toolshed.Syntax;
using Robust.Shared.Toolshed.TypeParsers;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Server._DV.Toolshed;
/// <summary>
/// Reads the value of a single field or property off of the piped input, by name.
/// Member names are resolved the same way <c>vvread</c> does: the member must be exposed
/// via <c>[ViewVariables]</c>, <c>[DataField]</c>, or <c>[IncludeDataField]</c>.
/// </summary>
/// <example><code>ent 12345 . Name</code></example>
[ToolshedCommand(Name = "."), AdminCommand(AdminFlags.Debug)]
public sealed class FieldCommand : ToolshedCommand
{
[CommandImplementation]
public object? Field([PipedArgument] object? value, [CommandArgument(typeof(FieldNameParser))] string field, IInvocationContext ctx)
{
if (value == null)
{
ctx.ReportError(new NullInputFieldError());
return null;
}
var type = value.GetType();
var member = GetSingleMember(type, field);
// Restrict to members that vvread would let you read, so this can't be used to peek at arbitrary internals.
if (member == null || !ViewVariablesUtility.TryGetViewVariablesAccess(member, out _))
{
ctx.ReportError(new NoSuchFieldError(type, field));
return null;
}
return member switch
{
FieldInfo f => f.GetValue(value),
PropertyInfo p => p.GetValue(value),
_ => null,
};
}
/// <summary>
/// Finds the field or property with the given name, mirroring the resolution used by <c>vvread</c>.
/// </summary>
private static MemberInfo? GetSingleMember(Type type, string member)
{
var members = type
.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(m => m.Name == member && m is FieldInfo or PropertyInfo)
.ToArray();
if (members.Length == 0)
return null;
// In case there's member hiding going on, grab the one declared by the type of the object by default.
return members.Length > 1
? members.FirstOrDefault(m => m.DeclaringType == type) ?? members[0]
: members[0];
}
}
/// <summary>
/// Parses a field name as a bare identifier (letters, digits, underscore) so that the <c>.</c> command doesn't
/// require the name to be wrapped in quotes like the default <see cref="string"/> parser does.
/// </summary>
public sealed class FieldNameParser : CustomTypeParser<string>
{
public override bool TryParse(ParserContext ctx, [NotNullWhen(true)] out string? result)
{
ctx.ConsumeWhitespace();
result = ctx.GetWord(ParserContext.IsToken);
if (result != null)
return true;
if (ctx.PeekRune() is null)
ctx.Error = new OutOfInputError();
else
ctx.Error = new InvalidFieldNameError();
ctx.Error.Contextualize(ctx.Input, (ctx.Index, ctx.Index + 1));
return false;
}
public override CompletionResult? TryAutocomplete(ParserContext ctx, CommandArgument? arg)
{
return CompletionResult.FromHint(GetArgHint(arg));
}
}
public sealed class InvalidFieldNameError : IConError
{
public FormattedMessage DescribeInner()
{
return FormattedMessage.FromUnformatted("Expected a field name (letters, digits, or underscores).");
}
public string? Expression { get; set; }
public Vector2i? IssueSpan { get; set; }
public StackTrace? Trace { get; set; }
}
public sealed class NullInputFieldError : IConError
{
public FormattedMessage DescribeInner()
{
return FormattedMessage.FromUnformatted("Cannot read a field off of a null input.");
}
public string? Expression { get; set; }
public Vector2i? IssueSpan { get; set; }
public StackTrace? Trace { get; set; }
}
public sealed class NoSuchFieldError(Type type, string field) : IConError
{
public FormattedMessage DescribeInner()
{
return FormattedMessage.FromUnformatted($"Type {type.Name} has no readable field or property named '{field}'. It must be exposed via [ViewVariables], [DataField], or [IncludeDataField].");
}
public string? Expression { get; set; }
public Vector2i? IssueSpan { get; set; }
public StackTrace? Trace { get; set; }
}
@@ -1,5 +0,0 @@
using Content.Shared._Floof.OfferItem;
namespace Content.Server._Floof.OfferItem;
public sealed partial class OfferItemSystem : SharedOfferItemSystem;
@@ -13,7 +13,7 @@ public sealed partial class RevenantStasisComponent : Component
public Entity<RevenantComponent> Revenant;
[ViewVariables(VVAccess.ReadOnly)]
public TimeSpan StasisDuration = TimeSpan.FromSeconds(100); // DeltaV - change from 60 to 100s
public TimeSpan StasisDuration = TimeSpan.FromSeconds(60);
public RevenantStasisComponent(TimeSpan stasisDuration, Entity<RevenantComponent> revenant)
{
@@ -27,7 +27,6 @@ using Content.Shared.Mobs;
using Robust.Shared.Timing;
using Content.Shared.Construction.Components;
using Content.Shared.Trigger.Components;
using Content.Shared.Zombies; // DeltaV
namespace Content.Server._Impstation.Revenant.EntitySystems;
@@ -197,7 +196,6 @@ public sealed partial class RevenantAnimatedSystem : EntitySystem
animate.EndTime = _gameTiming.CurTime + duration.Value;
else if (revenant != null)
animate.EndTime = _gameTiming.CurTime + revenant.Value.Comp.AnimateTime;
EnsureComp<ZombieImmuneComponent>(target); // DeltaV - ensure immune from zombies so we don't break clients
return true;
}
-290
View File
@@ -1,290 +0,0 @@
using Content.Shared.Humanoid;
using Content.Shared.Alert;
using Robust.Server.GameObjects;
using Content.Shared.Examine;
using Robust.Server.Containers;
using Content.Shared._Starlight;
using Content.Shared.Damage.Components;
using Content.Shared.Mobs;
using Content.Shared.Movement.Systems;
using Content.Shared.Movement.Components;
using Content.Shared.Damage;
using Content.Server.Chat.Managers;
using Content.Shared.Damage.Systems;
using Content.Shared._Goobstation.Overlays;
using Robust.Shared.Timing;
using Content.Server.Body.Components;
using System.Linq;
using Content.Shared._Goobstation.Flashbang;
using Content.Shared._Starlight.Flash.Components;
using Content.Shared.Body.Components;
using Content.Shared.Flash; // Delta V - Flash Work
namespace Content.Server._Starlight;
public sealed class ShadekinSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly MovementSpeedModifierSystem _speed = default!;
[Dependency] private readonly SharedFlashSystem _flashSystem = default!;
private sealed class LightCone
{
public float Direction { get; set; }
public float InnerWidth { get; set; }
public float OuterWidth { get; set; }
}
private readonly Dictionary<string, List<LightCone>> lightMasks = new()
{
["/Textures/Effects/LightMasks/cone.png"] = new List<LightCone>
{
new LightCone { Direction = 0, InnerWidth = 30, OuterWidth = 60 }
},
["/Textures/Effects/LightMasks/double_cone.png"] = new List<LightCone>
{
new LightCone { Direction = 0, InnerWidth = 30, OuterWidth = 60 },
new LightCone { Direction = 180, InnerWidth = 30, OuterWidth = 60 }
}
};
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ShadekinComponent, ComponentStartup>(OnInit);
SubscribeLocalEvent<ShadekinComponent, EyeColorInitEvent>(OnEyeColorChange);
SubscribeLocalEvent<ShadekinComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
SubscribeLocalEvent<ShadekinComponent, AfterFlashedEvent>(OnShadekinFlashed); // Delta V - Prevent Chain Flashing
SubscribeLocalEvent<ShadekinComponent, FlashDurationMultiplierEvent>(GetFlashModifier); // Delta V - Flash Modifier to Shadekin
}
private void OnInit(EntityUid uid, ShadekinComponent component, ComponentStartup args)
{
UpdateAlert(uid, component, (short)component.CurrentState);
RemComp<InternalsComponent>(uid);
}
private void OnEyeColorChange(EntityUid uid, ShadekinComponent component, EyeColorInitEvent args)
{
if (!TryComp<HumanoidProfileComponent>(uid, out var humanoid))
return;
// humanoid.EyeColor = Color.Black;
Dirty(uid, humanoid);
}
public void UpdateAlert(EntityUid uid, ShadekinComponent component, short state)
{
_alerts.ShowAlert(uid, component.ShadekinAlert, state);
}
private Angle GetAngle(EntityUid lightUid, SharedPointLightComponent lightComp, EntityUid targetUid)
{
var (lightPos, lightRot) = _transform.GetWorldPositionRotation(lightUid);
lightPos += lightRot.RotateVec(lightComp.Offset);
var (targetPos, targetRot) = _transform.GetWorldPositionRotation(targetUid);
var mapDiff = targetPos - lightPos;
var oppositeMapDiff = (-lightRot).RotateVec(mapDiff);
var angle = oppositeMapDiff.ToWorldAngle();
if (angle == double.NaN && _transform.ContainsEntity(targetUid, lightUid) || _transform.ContainsEntity(lightUid, targetUid))
{
angle = 0f;
}
return angle;
}
/// <summary>
/// Return an illumination float value with is how many "energy" of light is hitting our ent.
/// WARNING: This function might be expensive, Avoid calling it too much and CACHE THE RESULT!
/// </summary>
/// <param name="uid"></param>
/// <returns></returns>
public float GetLightExposure(EntityUid uid)
{
var illumination = 0f;
var lightQuery = _lookup.GetEntitiesInRange<PointLightComponent>(Transform(uid).Coordinates, 20, LookupFlags.Uncontained);
foreach (var light in lightQuery)
{
if (!light.Comp.Enabled
|| light.Comp.Radius < 1
|| light.Comp.Energy <= 0)
continue;
var (lightPos, lightRot) = _transform.GetWorldPositionRotation(light);
lightPos += lightRot.RotateVec(light.Comp.Offset);
if (!_examine.InRangeUnOccluded(light, uid, light.Comp.Radius, null))
continue;
Transform(uid).Coordinates.TryDistance(EntityManager, Transform(light).Coordinates, out var dist);
var denom = dist / light.Comp.Radius;
var attenuation = 1 - (denom * denom);
var calculatedLight = 0f;
if (light.Comp.MaskPath is not null)
{
var angleToTarget = GetAngle(light, light.Comp, uid);
foreach (var cone in lightMasks[light.Comp.MaskPath])
{
var coneLight = 0f;
var angleAttenuation = (float)Math.Min((float)Math.Max(cone.OuterWidth - angleToTarget, 0f), cone.InnerWidth) / cone.OuterWidth;
if (angleToTarget.Degrees - cone.Direction > cone.OuterWidth)
continue;
else if (angleToTarget.Degrees - cone.Direction > cone.InnerWidth
&& angleToTarget.Degrees - cone.Direction < cone.OuterWidth)
coneLight = light.Comp.Energy * attenuation * attenuation * angleAttenuation;
else
coneLight = light.Comp.Energy * attenuation * attenuation;
calculatedLight = Math.Max(calculatedLight, coneLight);
}
}
else
calculatedLight = light.Comp.Energy * attenuation * attenuation;
illumination += calculatedLight; //Math.Max(illumination, calculatedLight);
}
return illumination;
}
private void SetPassiveBuff(EntityUid uid, ShadekinState state)
{
if (!TryComp<PassiveDamageComponent>(uid, out var passive))
return;
if (state == ShadekinState.Extreme || state == ShadekinState.Annoying || state == ShadekinState.High)
{
// passive.DamageCap = 1;
}
else if (state == ShadekinState.Low)
{
// passive.DamageCap = 20;
passive.AllowedStates.Clear();
passive.AllowedStates.Add(MobState.Alive);
passive.Interval = 1f;
}
else if (state != ShadekinState.Dark)
{
// passive.DamageCap = 0;
passive.AllowedStates.Clear();
passive.AllowedStates.Add(MobState.Alive);
passive.AllowedStates.Add(MobState.Critical);
passive.AllowedStates.Add(MobState.Dead);
passive.Interval = 0.5f;
}
}
private void ToggleNightVision(EntityUid uid, ShadekinState state)
{
if (state == ShadekinState.Dark)
{
var nightVisionComponent = EnsureComp<NightVisionComponent>(uid);
nightVisionComponent.Color = Color.FromHex("#808080"); // Delta V - Change Night Vision Color
}
else
{
if (TryComp<NightVisionComponent>(uid, out var nightVision) && nightVision.IsActive)
_flashSystem.Flash(uid, uid, uid, TimeSpan.FromSeconds(0.5 * (int)state), 0.5f);
RemComp<NightVisionComponent>(uid);
}
}
private void ApplyLightDamage(EntityUid uid, float dmg)
{
var damage = new DamageSpecifier();
damage.DamageDict.Add("Heat", dmg);
_damageable.TryChangeDamage(uid, damage, true, false);
}
private void OnRefreshMovementSpeedModifiers(EntityUid uid, ShadekinComponent component, RefreshMovementSpeedModifiersEvent args)
{
if (component.CurrentState == ShadekinState.Low || component.CurrentState == ShadekinState.Annoying ||
component.CurrentState == ShadekinState.Dark || component.CurrentState == ShadekinState.Invalid)
return;
if (!TryComp<MovementSpeedModifierComponent>(uid, out var movement))
return;
var sprintDif = movement.BaseWalkSpeed / movement.BaseSprintSpeed;
args.ModifySpeed(1f, sprintDif);
}
private ShadekinState GetStateByThreshold(ShadekinComponent component, float lightExposure)
{
var returnState = ShadekinState.Dark;
foreach (var (threshold, shadekinState) in component.Thresholds.Reverse())
{
if (threshold <= lightExposure)
{
returnState = shadekinState;
break;
}
}
return returnState;
}
// Delta V - Begin Shadekin Flash Changes
private void GetFlashModifier(EntityUid uid, ShadekinComponent comp, FlashDurationMultiplierEvent args)
{
if (!TryComp<FlashModifierComponent>(uid, out var flashModifier))
return;
args.Multiplier = flashModifier.Modifier;
}
private void OnShadekinFlashed(EntityUid uid, ShadekinComponent comp, AfterFlashedEvent ev)
{
RemComp<NightVisionComponent>(uid);
}
// Delta V - End
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<ShadekinComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (_timing.CurTime < component.NextUpdate)
continue;
component.NextUpdate = _timing.CurTime + component.UpdateCooldown;
var lightExposure = 0f;
if (!_container.IsEntityInContainer(uid))
lightExposure = GetLightExposure(uid);
component.CurrentState = GetStateByThreshold(component, lightExposure);
UpdateAlert(uid, component, (short)component.CurrentState);
SetPassiveBuff(uid, component.CurrentState);
ToggleNightVision(uid, component.CurrentState);
_speed.RefreshMovementSpeedModifiers(uid);
if (component.CurrentState == ShadekinState.Extreme)
ApplyLightDamage(uid, 5);
}
}
}
@@ -23,8 +23,6 @@ using Robust.Shared.Timing;
using Content.Shared._DV.Access.Systems;
using Content.Shared._DV.Access.Components;
using Content.Shared.Mind; // DeltaV - Subdermal ID Cards
using Content.Shared.Ninja.Components; // DeltaV
using Content.Shared.Revenant.Components; // DeltaV
namespace Content.Shared.Access.Systems;
@@ -33,6 +31,7 @@ public sealed class AccessReaderSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly SharedGameTicker _gameTicker = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
@@ -152,7 +151,7 @@ public sealed class AccessReaderSystem : EntitySystem
private void OnEmagged(EntityUid uid, AccessReaderComponent reader, ref GotEmaggedEvent args)
{
if (HasComp<SpaceNinjaComponent>(args.UserUid) || HasComp<RevenantComponent>(args.UserUid)) // DeltaV - Don't break access if its a ninja doing it
if (!_emag.CompareFlag(args.Type, EmagType.Interaction)) // DeltaV - emag for lockers etc instead of doorjack
return;
if (!reader.BreakOnAccessBreaker)
+2 -13
View File
@@ -100,12 +100,6 @@ public abstract partial class SharedVisualBodySystem : EntitySystem
if (!other.Layer.Equals(ent.Comp.Layer))
return;
// Delta V - Begin Fix Height for Cloning
var height = other.Profile.Height;
if (TryComp<HumanoidProfileComponent>(args.Body.Owner, out var component))
ScaleBody((args.Body.Owner, component), height, height);
// Delta V - End
SetOrganAppearance(ent, other.Data);
}
@@ -118,14 +112,9 @@ public abstract partial class SharedVisualBodySystem : EntitySystem
var height = Math.Clamp(MathF.Round(args.Base.Value.Height, 2), speciesPrototype.MinHeight, speciesPrototype.MaxHeight);
ScaleBody(entity, speciesPrototype.ScaleHeight ? height : 1f, height);
}
private void ScaleBody(Entity<HumanoidProfileComponent> entity, float heightX, float heightY)
{
_scaleVisualsSystem.SetSpriteScale(
entity.Owner,
new Vector2(heightX, heightY)
new Vector2(speciesPrototype.ScaleHeight ? height : 1f, height)
);
}
// Delta V - END
@@ -159,7 +148,7 @@ public abstract partial class SharedVisualBodySystem : EntitySystem
if (ent.Comp.Layer.Equals(HumanoidVisualLayers.Eyes))
{
// Delta V - Begin Add AppearanceLoaded Event
var appearanceLoaded = new AppearanceLoadedEvent(ent.Comp.Profile.EyeColor, ent.Comp.Profile.SkinColor);
var appearanceLoaded = new AppearanceLoadedEvent(ent.Comp.Profile.EyeColor);
RaiseLocalEvent(args.Body.Owner, ref appearanceLoaded);
// Delta V - End
SetOrganColor(ent, ent.Comp.Profile.EyeColor);
+1 -15
View File
@@ -28,18 +28,4 @@ public readonly partial record struct CargoBountyData
Bounty = bounty.ID;
Id = $"{bounty.IdPrefix}{uniqueIdentifier:D3}";
}
// Begin DeltaV bounty claiming
[DataField]
public string ClaimedBy { get; init; } = string.Empty;
[DataField]
public CargoBountyStatus Status { get; init; } = CargoBountyStatus.Undelivered;
}
public enum CargoBountyStatus
{
Undelivered,
Waiting,
OnShuttle,
} // End DeltaV bounty claiming
}
@@ -94,4 +94,3 @@ public sealed class BountySkipMessage : BoundUserInterfaceMessage
BountyId = bountyId;
}
}
+24 -9
View File
@@ -25,6 +25,12 @@ public abstract class SharedEmpSystem : EntitySystem
[Dependency] private readonly SharedPvsOverrideSystem _pvs = default!; // Frontier
[Dependency] private readonly IConfigurationManager _cfg = default!; // Frontier: EMP Blast PVS
/// <summary>
/// DeltaV. Default damage of EMPs, as dertermined by direction. There's no good component to put
/// this on so its defined here.
/// </summary>
private static readonly DamageSpecifier? DefaultEmpDamage = new() { DamageDict = new() { { "Ion", 130 } } };
private HashSet<EntityUid> _entSet = new();
private EntityQuery<EmpResistanceComponent> _resistanceQuery;
@@ -53,11 +59,12 @@ public abstract class SharedEmpSystem : EntitySystem
/// <param name="energyConsumption">The amount of energy consumed by the EMP pulse. In Joule.</param>
/// <param name="duration">The duration of the EMP effects.</param>
/// <param name="user">The player that caused the effect. Used for predicted audio.</param>
public void EmpPulse(MapCoordinates mapCoordinates, float range, float energyConsumption, TimeSpan duration, EntityUid? user = null)
/// <param name="damage">DeltaV - The damage that that EMP will do. If not specified or null, will do 130 Ion damage. To do no damage, pass in a DamageSpecifier with no damage types.</param>
public void EmpPulse(MapCoordinates mapCoordinates, float range, float energyConsumption, TimeSpan duration, EntityUid? user = null, DamageSpecifier? damage = null) // DeltaV - Add Ion Damage
{
foreach (var uid in _lookup.GetEntitiesInRange(mapCoordinates, range))
{
TryEmpEffects(uid, energyConsumption, duration, user);
TryEmpEffects(uid, energyConsumption, duration, user, damage ?? DefaultEmpDamage); // DeltaV - Add Ion Damage
}
// TODO: replace with PredictedSpawn once it works with animated sprites
@@ -85,13 +92,15 @@ public abstract class SharedEmpSystem : EntitySystem
/// <param name="energyConsumption">The amount of energy consumed by the EMP pulse.</param>
/// <param name="duration">The duration of the EMP effects.</param>
/// <param name="user">The player that caused the effect. Used for predicted audio.</param>'
public void EmpPulse(EntityCoordinates coordinates, float range, float energyConsumption, TimeSpan duration, EntityUid? user = null, bool predicted = true)
/// <param name="damage">DeltaV - The damage that that EMP will do. If not specified or null, will do 130 Ion damage. To do no damage, pass in a DamageSpecifier with no damage types.</param>
/// <param name="predicted">Whether this pulse is being replicated on the client.</param>
public void EmpPulse(EntityCoordinates coordinates, float range, float energyConsumption, TimeSpan duration, EntityUid? user = null, DamageSpecifier? damage = null, bool predicted = true) // Delta V - Add ion damage
{
_entSet.Clear();
_lookup.GetEntitiesInRange(coordinates, range, _entSet);
foreach (var uid in _entSet)
{
TryEmpEffects(uid, energyConsumption, duration, user);
TryEmpEffects(uid, energyConsumption, duration, user, damage ?? DefaultEmpDamage); // DeltaV - Add Ion Damage
}
// TODO: replace with PredictedSpawn once it works with animated sprites
if (_net.IsServer)
@@ -114,31 +123,37 @@ public abstract class SharedEmpSystem : EntitySystem
/// <summary>
/// Attempts to apply the effects of an EMP pulse onto an entity by first raising an <see cref="EmpAttemptEvent"/>, followed by raising a <see cref="EmpPulseEvent"/> on it.
/// <br/>
/// <br/>DeltaV - In most cases, you will want to use <see cref="EmpPulse"/> instead.
/// </summary>
/// <param name="uid">The entity to apply the EMP effects on.</param>
/// <param name="energyConsumption">The amount of energy consumed by the EMP.</param>
/// <param name="duration">The duration of the EMP effects.</param>
/// <param name="user">The player that caused the EMP. For prediction purposes.</param>
/// <param name="damage">DeltaV - The damage that that EMP will do. If null, no damage is done.</param>
/// <returns>If the entity was affected by the EMP.</returns>
public bool TryEmpEffects(EntityUid uid, float energyConsumption, TimeSpan duration, EntityUid? user = null)
public bool TryEmpEffects(EntityUid uid, float energyConsumption, TimeSpan duration, EntityUid? user = null, DamageSpecifier? damage = null) // DeltaV - Add Ion Damage
{
var attemptEv = new EmpAttemptEvent();
RaiseLocalEvent(uid, ref attemptEv);
if (attemptEv.Cancelled)
return false;
return DoEmpEffects(uid, energyConsumption, duration, user);
return DoEmpEffects(uid, energyConsumption, duration, user, damage); // DeltaV - Add Ion Damage
}
/// <summary>
/// Applies the effects of an EMP pulse onto an entity by raising a <see cref="EmpPulseEvent"/> on it.
/// <br/>
/// <br/>DeltaV - In most cases, you will want to use <see cref="EmpPulse"/> instead.
/// </summary>
/// <param name="uid">The entity to apply the EMP effects on.</param>
/// <param name="energyConsumption">The amount of energy consumed by the EMP.</param>
/// <param name="duration">The duration of the EMP effects.</param>
/// <param name="user">The player that caused the EMP. For prediction purposes.</param>
/// <param name="damage">DeltaV - The damage that that EMP will do. If null, no damage is done.</param>
/// <returns>If the entity was affected by the EMP.</returns>
public bool DoEmpEffects(EntityUid uid, float energyConsumption, TimeSpan duration, EntityUid? user = null)
public bool DoEmpEffects(EntityUid uid, float energyConsumption, TimeSpan duration, EntityUid? user = null, DamageSpecifier? damage = null) // DeltaV - Add Ion Damage
{
var strMultiplier = 1f;
var durMultiplier = 1f;
@@ -147,7 +162,7 @@ public abstract class SharedEmpSystem : EntitySystem
strMultiplier = resistance.StrengthMultiplier;
durMultiplier = resistance.DurationMultiplier;
}
var ev = new EmpPulseEvent(energyConsumption * strMultiplier, false, false, duration * durMultiplier, user);
var ev = new EmpPulseEvent(energyConsumption * strMultiplier, false, false, duration * durMultiplier, user, damage); // DeltaV - Add Ion Damage
RaiseLocalEvent(uid, ref ev);
// TODO: replace with PredictedSpawn once it works with animated sprites
@@ -220,7 +235,7 @@ public record struct EmpAttemptEvent(bool Cancelled);
/// <param name="User">The player that caused the EMP. For prediction purposes.</param>
[ByRefEvent]
public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled, TimeSpan Duration, EntityUid? User);
public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled, TimeSpan Duration, EntityUid? User, DamageSpecifier? Damage = null); // DeltaV - Added Damage
/// <summary>
/// Raised on an entity after <see cref="EmpDisabledComponent"/> is removed.
+1 -2
View File
@@ -26,7 +26,6 @@ using System.Linq;
using Content.Shared.Movement.Systems;
using Content.Shared.Random.Helpers;
using Content.Shared.Clothing.Components;
using Content.Shared._Starlight.Flash.Components; // Delta V - For Flash Duration
namespace Content.Shared.Flash;
@@ -174,7 +173,7 @@ public abstract class SharedFlashSystem : EntitySystem
// Goobstation end
// don't paralyze, slowdown or convert to rev if the target is immune to flashes
if (!_statusEffectsSystem.TryAddStatusEffect<FlashedComponent>(target, FlashedKey, flashDuration * multiplier, true) && !ignoreProtection) //DeltaV: allow flashing to ignore flash protection. Added Flashduration Multiplier
if (!_statusEffectsSystem.TryAddStatusEffect<FlashedComponent>(target, FlashedKey, flashDuration, true) && !ignoreProtection) //DeltaV: allow flashing to ignore flash protection
return;
if (stunDuration != null)
@@ -68,7 +68,6 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction TakeScreenshotNoUI = "TakeScreenshotNoUI";
public static readonly BoundKeyFunction ToggleFullscreen = "ToggleFullscreen";
public static readonly BoundKeyFunction Point = "Point";
public static readonly BoundKeyFunction OfferItem = "OfferItem"; // Floofstation
public static readonly BoundKeyFunction ZoomOut = "ZoomOut";
public static readonly BoundKeyFunction ZoomIn = "ZoomIn";
public static readonly BoundKeyFunction ResetZoom = "ResetZoom";
-16
View File
@@ -103,22 +103,6 @@ public abstract class SharedItemSystem : EntitySystem
VisualsChanged(uid);
}
/// <summary>
/// DeltaV - clear item visuals
/// </summary>
public void ClearVisuals(Entity<ItemComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
ent.Comp.RsiPath = null;
ent.Comp.InhandVisuals = new();
ent.Comp.HeldPrefix = null;
Dirty(ent, ent.Comp);
VisualsChanged(ent.Owner);
}
#endregion
private void OnHandInteract(EntityUid uid, ItemComponent component, InteractHandEvent args)
@@ -1,5 +1,4 @@
using Content.Shared._ST.Interaction; // Stellar - interaction particles
using Content.Shared._Floof.OfferItem; // Floof
using Content.Shared.ActionBlocker;
using Content.Shared.Administration.Logs;
using Content.Shared.Alert;
@@ -118,11 +117,10 @@ public sealed class PullingSystem : EntitySystem
if (TryComp(args.PullerUid, out PullerComponent? pullerComp) && !pullerComp.NeedsHands)
return;
if (!_virtual.TrySpawnVirtualItemInHand(args.PulledUid, uid, out var virt)) // Floofstation - store item
if (!_virtual.TrySpawnVirtualItemInHand(args.PulledUid, uid))
{
DebugTools.Assert("Unable to find available hand when starting pulling??");
}
EnsureComp<OfferableVirtualItemComponent>(virt.Value); // Floofstation - add a special component to allow offering it
}
private void HandlePullStopped(EntityUid uid, HandsComponent component, PullStoppedMessage args)
@@ -1,7 +1,8 @@
using Content.Shared.Actions;
using Content.Shared.Bed.Sleep;
using Content.Shared.DoAfter;
using Content.Shared.Hands;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Events;
using Content.Shared.Item;
using Content.Shared.Item.PseudoItem;
@@ -23,8 +24,7 @@ public abstract partial class SharedPseudoItemSystem : EntitySystem
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedContainerSystem _container = default!; // Floofstation
[Dependency] private readonly SharedHandsSystem _hands = default!; // Floofstation
[Dependency] private readonly SharedTransformSystem _transform = default!;
private readonly ProtoId<TagPrototype> PreventTag = "PreventLabel";
private readonly EntProtoId SleepActionId = "ActionSleep"; // The action used for sleeping inside bags. Currently uses the default sleep action (same as beds)
@@ -116,35 +116,17 @@ public abstract partial class SharedPseudoItemSystem : EntitySystem
protected virtual void OnGettingPickedUpAttempt(EntityUid uid, PseudoItemComponent component,
GettingPickedUpAttemptEvent args)
{
args.Cancel(); // Floof - this is a terrible idea. This triggers every time ANY system checks if a pseudo-item can be picked up.
// WHY DID YOU DO THAT, NYANOTRASEN???
if (args.User == args.Item)
return;
// if (args.User == args.Item)
// return;
//
// _transform.AttachToGridOrMap(uid);
// args.Cancel();
_transform.AttachToGridOrMap(uid);
args.Cancel();
}
private void OnDropAttempt(EntityUid uid, PseudoItemComponent component, DropAttemptEvent args)
{
if (!component.Active)
return;
// Floof - we try to get the containing container and try to drop it into it
// If possible, we do it, since a bagged cat probably can put things back into the bag just like they can pick them up.
string? failReason = null;
if (_hands.GetActiveItem(uid) is { Valid: true, } droppedItem
&& _container.TryGetContainingContainer(Transform(uid).ParentUid, uid, out var pseudoItemContainer)
&& TryComp<StorageComponent>(pseudoItemContainer.Owner, out var targetStorage)
&& _storage.CanInsert(pseudoItemContainer.Owner, droppedItem, out failReason, targetStorage, ignoreStacks: true)
)
_storage.Insert(pseudoItemContainer.Owner, droppedItem, out _, uid, targetStorage, stackAutomatically: false);
if (failReason != null)
_popupSystem.PopupEntity(Loc.GetString(failReason), uid, uid);
args.Cancel();
if (component.Active)
args.Cancel();
}
private void OnInsertAttempt(EntityUid uid, PseudoItemComponent component,
@@ -159,9 +141,8 @@ public abstract partial class SharedPseudoItemSystem : EntitySystem
// Prevents moving within the bag :)
private void OnInteractAttempt(EntityUid uid, PseudoItemComponent component, InteractionAttemptEvent args)
{
// Floof - why the fuck.
// if (args.Uid == args.Target && component.Active)
// args.Cancelled = true;
if (args.Uid == args.Target && component.Active)
args.Cancelled = true;
}
private void OnDoAfter(EntityUid uid, PseudoItemComponent component, DoAfterEvent args)
@@ -17,7 +17,7 @@ namespace Content.Shared.Psionics.Glimmer
get { return _glimmer; }
set
{
var newGlimmer = _enabled ? Math.Clamp(value, 0, 1000) : 0;
var newGlimmer = _enabled ? Math.Clamp(value, 0, 2000) : 0;
if (_glimmer == newGlimmer)
return;
@@ -32,7 +32,7 @@ public sealed partial class RevenantComponent : Component
public string SpawnOnDeathPrototype = "EctoplasmRevenant"; // DeltaV
[DataField("stasisTime"), ViewVariables(VVAccess.ReadWrite)] // Begin Imp Changes
public TimeSpan StasisTime = TimeSpan.FromSeconds(100); // DeltaV - change from 60 to 100s
public TimeSpan StasisTime = TimeSpan.FromSeconds(60);
/// <summary>
/// If true, only bible users can exorcise this revenant
@@ -50,7 +50,7 @@ public sealed partial class RevenantComponent : Component
/// grinder will explode.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public bool GrindingRequiresSalt = false; // End Imp Changes - DeltaV - true to false
public bool GrindingRequiresSalt = true; // End Imp Changes
/// <summary>
/// The entity's current max amount of essence. Can be increased
@@ -188,20 +188,12 @@ public abstract class SharedStorageSystem : EntitySystem
return;
}
// Begin DeltaV - the grid check excludes the item being resized because it's already in the storage which defeats the purpose so yoink it out to remove that
storage.StoredItems.Remove(itemEnt.Owner);
UpdateOccupied((container.Owner, storage));
if (ItemFitsInGridLocation((itemEnt.Owner, itemEnt.Comp), (container.Owner, storage), loc))
{
storage.StoredItems.Add(itemEnt.Owner, loc);
UpdateOccupied((container.Owner, storage));
}
else
if (!ItemFitsInGridLocation((itemEnt.Owner, itemEnt.Comp), (container.Owner, storage), loc))
{
ContainerSystem.Remove(itemEnt.Owner, container, force: true);
}
// End DeltaV - the grid check excludes the item being resized because it's already in the storage which defeats the purpose so yoink it out to remove that
}
private void OnNestedStorageCvar(bool obj)
@@ -28,4 +28,10 @@ public sealed partial class EmpOnTriggerComponent : BaseXOnTriggerComponent
/// </summary>
[DataField, AutoNetworkedField]
public TimeSpan DisableDuration = TimeSpan.FromSeconds(60);
/// <summary>
/// DeltaV - The damage dealt to silicons instead of draining their power cells
/// </summary>
[DataField, AutoNetworkedField]
public DamageSpecifier? Damage;
}
@@ -9,7 +9,7 @@ public sealed class EmpOnTriggerSystem : XOnTriggerSystem<EmpOnTriggerComponent>
protected override void OnTrigger(Entity<EmpOnTriggerComponent> ent, EntityUid target, ref TriggerEvent args)
{
_emp.EmpPulse(Transform(target).Coordinates, ent.Comp.Range, ent.Comp.EnergyConsumption, ent.Comp.DisableDuration, args.User, predicted: args.Predicted);
_emp.EmpPulse(Transform(target).Coordinates, ent.Comp.Range, ent.Comp.EnergyConsumption, ent.Comp.DisableDuration, args.User, ent.Comp.Damage, predicted: args.Predicted); // Delta V - Silicon Damage
args.Handled = true;
}
}
@@ -75,7 +75,4 @@ public sealed partial class PreenableComponent : Component
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
public TimeSpan? ReplenishTime;
[DataField, AutoNetworkedField]
public Color? Color;
}
@@ -1,6 +1,5 @@
using Content.Shared._DV.Body.Components;
using Content.Shared._DV.Body.Events;
using Content.Shared._DV.Humanoid;
using Content.Shared.Body.Components;
using Content.Shared.Chat;
using Content.Shared.Damage;
@@ -46,7 +45,6 @@ public sealed class PreenableSystem : EntitySystem
SubscribeLocalEvent<PreenableComponent, DamageChangedEvent>(OnDamaged);
SubscribeLocalEvent<PreenableComponent, DamageModifyEvent>(OnDamageModify);
SubscribeLocalEvent<PreenableComponent, ComponentInit>(OnCompInit);
SubscribeLocalEvent<PreenableComponent, AppearanceLoadedEvent>(OnProfileLoadFinished);
}
private void OnCompInit(Entity<PreenableComponent> ent, ref ComponentInit args)
@@ -187,7 +185,7 @@ public sealed class PreenableSystem : EntitySystem
if (TryComp<HumanoidProfileComponent>(ent, out var appearance))
{
_appearance.SetData(feather, FeatherVisuals.FeatherColor, ent.Comp.Color ?? Color.White);
_appearance.SetData(feather, FeatherVisuals.FeatherColor, Color.White); // TODO: Nubody Colors
}
// best be careful, no cleaning this
@@ -206,11 +204,6 @@ public sealed class PreenableSystem : EntitySystem
return feather;
}
private void OnProfileLoadFinished(Entity<PreenableComponent> ent, ref AppearanceLoadedEvent args)
{
ent.Comp.Color = args.SkinColor;
}
public override void Update(float deltaTime)
{
base.Update(deltaTime);
@@ -1,31 +0,0 @@
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared._DV.Cargo.Components;
[Serializable, NetSerializable]
public sealed class BountyClaimedMessage : BoundUserInterfaceMessage
{
public readonly string BountyId;
public BountyClaimedMessage(string bountyId)
{
BountyId = bountyId;
}
}
[Serializable, NetSerializable]
public sealed class BountySetStatusMessage : BoundUserInterfaceMessage
{
public readonly string BountyId;
public readonly int Status;
public BountySetStatusMessage(string bountyId, int status)
{
BountyId = bountyId;
Status = status;
}
}
+12 -17
View File
@@ -28,7 +28,6 @@ using Robust.Shared.Network;
using Robust.Shared.Physics.Components;
using System.Numerics;
using Content.Shared._DV.Polymorph;
using Content.Shared._Floof.OfferItem;
using Content.Shared.Hands.EntitySystems;
namespace Content.Shared._DV.Carrying;
@@ -182,15 +181,14 @@ public sealed class CarryingSystem : EntitySystem
/// </summary>
private void OnInteractionAttempt(Entity<BeingCarriedComponent> ent, ref InteractionAttemptEvent args)
{
// Floofstation - no - this prevents the person from escaping and more.
// if (args.Target is not {} target)
// return;
//
// var targetParent = Transform(target).ParentUid;
//
// var carrier = ent.Comp.Carrier;
// if (target != carrier && targetParent != carrier && targetParent != ent.Owner)
// args.Cancelled = true;
if (args.Target is not {} target)
return;
var targetParent = Transform(target).ParentUid;
var carrier = ent.Comp.Carrier;
if (target != carrier && targetParent != carrier && targetParent != ent.Owner)
args.Cancelled = true;
}
private void OnMoveAttempt(Entity<BeingCarriedComponent> ent, ref UpdateCanMoveEvent args)
@@ -205,9 +203,8 @@ public sealed class CarryingSystem : EntitySystem
private void OnInteractedWith(Entity<BeingCarriedComponent> ent, ref GettingInteractedWithAttemptEvent args)
{
// Floofstation - why?
// if (args.Uid != ent.Comp.Carrier)
// args.Cancelled = true;
if (args.Uid != ent.Comp.Carrier)
args.Cancelled = true;
}
private void OnPullAttempt(Entity<BeingCarriedComponent> ent, ref PullAttemptEvent args)
@@ -245,8 +242,7 @@ public sealed class CarryingSystem : EntitySystem
args.Handled = true;
}
// Floofstation - made public
public void StartCarryDoAfter(EntityUid carrier, Entity<CarriableComponent> carried)
private void StartCarryDoAfter(EntityUid carrier, Entity<CarriableComponent> carried)
{
TimeSpan length = GetPickupDuration(carrier, carried);
@@ -303,8 +299,7 @@ public sealed class CarryingSystem : EntitySystem
for (var x = 0; x < Comp<CarriableComponent>(carried).FreeHandsRequired; x++)
{
if (_virtualItem.TrySpawnVirtualItemInHand(carried, carrier, out var virtualItem))
EnsureComp<OfferableVirtualItemComponent>(virtualItem.Value);
_virtualItem.TrySpawnVirtualItemInHand(carried, carrier);
}
}
@@ -1,15 +0,0 @@
using Content.Shared.Item;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._DV.Forensics;
[RegisterComponent, NetworkedComponent]
public sealed partial class DVExpandToInsertedItemSizeComponent : Component
{
[DataField(required: true)]
public string ItemSlot;
[DataField(required: true)]
public ProtoId<ItemSizePrototype> EmptySize;
}
@@ -1,50 +0,0 @@
using Content.Shared.Item;
using Robust.Shared.Containers;
namespace Content.Shared._DV.Forensics;
public sealed class DVExpandToInsertedItemSizeSystem : EntitySystem
{
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DVExpandToInsertedItemSizeComponent, EntInsertedIntoContainerMessage>(OnItemInserted);
SubscribeLocalEvent<DVExpandToInsertedItemSizeComponent, EntRemovedFromContainerMessage>(OnItemRemoved);
}
private void Refresh(Entity<DVExpandToInsertedItemSizeComponent> ent)
{
var slot = _container.EnsureContainer<ContainerSlot>(ent, ent.Comp.ItemSlot);
if (slot.ContainedEntity is { } contained)
{
var item = Comp<ItemComponent>(contained);
_item.SetSize(ent, item.Size);
_item.SetShape(ent, item.Shape);
}
else
{
_item.SetSize(ent, ent.Comp.EmptySize);
_item.SetShape(ent, null);
}
}
private void OnItemInserted(Entity<DVExpandToInsertedItemSizeComponent> ent, ref EntInsertedIntoContainerMessage args)
{
if (ent.Comp.ItemSlot != args.Container.ID)
return;
Refresh(ent);
}
private void OnItemRemoved(Entity<DVExpandToInsertedItemSizeComponent> ent, ref EntRemovedFromContainerMessage args)
{
if (ent.Comp.ItemSlot != args.Container.ID)
return;
Refresh(ent);
}
}
@@ -1,17 +0,0 @@
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Shared._DV.Forensics;
[RegisterComponent, NetworkedComponent]
public sealed partial class DVItemSlotVisualsComponent : Component
{
[DataField(required: true)]
public string ItemSlot;
[DataField(required: true)]
public SpriteSpecifier FilledSprite;
[DataField(required: true)]
public SpriteSpecifier UnfilledSprite;
}
@@ -1,10 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared._DV.Forensics;
[RegisterComponent, NetworkedComponent]
public sealed partial class DVSeenInsertedItemComponent : Component
{
[DataField(required: true)]
public string ItemSlot;
}
@@ -1,80 +0,0 @@
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Item;
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
namespace Content.Shared._DV.Forensics;
public sealed class DVSeenInsertedItemSystem : EntitySystem
{
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DVSeenInsertedItemComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<DVSeenInsertedItemComponent, RefreshNameModifiersEvent>(OnRefreshModifiers);
SubscribeLocalEvent<DVSeenInsertedItemComponent, EntInsertedIntoContainerMessage>(OnItemInserted);
SubscribeLocalEvent<DVSeenInsertedItemComponent, EntRemovedFromContainerMessage>(OnItemRemoved);
}
private void OnExamined(Entity<DVSeenInsertedItemComponent> ent, ref ExaminedEvent args)
{
var slot = _container.EnsureContainer<ContainerSlot>(ent, ent.Comp.ItemSlot);
if (slot.ContainedEntity is { } contained)
{
args.PushMarkup(Loc.GetString("dv-seen-inserted-item-examined.full", ("container", Identity.Entity(ent, EntityManager, args.Examiner)), ("contained", contained)));
}
else
{
args.PushMarkup(Loc.GetString("dv-seen-inserted-item-examined.empty", ("container", Identity.Entity(ent, EntityManager, args.Examiner))));
}
}
private void OnRefreshModifiers(Entity<DVSeenInsertedItemComponent> ent, ref RefreshNameModifiersEvent args)
{
var slot = _container.EnsureContainer<ContainerSlot>(ent, ent.Comp.ItemSlot);
if (slot.ContainedEntity is not { } contained)
return;
args.AddModifier("dv-seen-inserted-item-name-modifier", extraArgs: ("contained", contained));
}
private void Refresh(Entity<DVSeenInsertedItemComponent> ent)
{
_nameModifier.RefreshNameModifiers(ent.Owner);
var slot = _container.EnsureContainer<ContainerSlot>(ent, ent.Comp.ItemSlot);
if (slot.ContainedEntity is { } contained)
{
var item = Comp<ItemComponent>(contained);
_item.CopyVisuals(ent.Owner, item);
}
else
{
_item.ClearVisuals(ent.Owner);
}
}
private void OnItemInserted(Entity<DVSeenInsertedItemComponent> ent, ref EntInsertedIntoContainerMessage args)
{
if (args.Container.ID != ent.Comp.ItemSlot || _timing.ApplyingState)
return;
Refresh(ent);
}
private void OnItemRemoved(Entity<DVSeenInsertedItemComponent> ent, ref EntRemovedFromContainerMessage args)
{
if (args.Container.ID != ent.Comp.ItemSlot || _timing.ApplyingState)
return;
Refresh(ent);
}
}
@@ -4,4 +4,4 @@ namespace Content.Shared._DV.Humanoid;
/// Raised on an entity when their appearance is changed.
/// </summary>
[ByRefEvent]
public record struct AppearanceLoadedEvent(Color EyeColor, Color SkinColor);
public record struct AppearanceLoadedEvent(Color EyeColor);
@@ -0,0 +1,7 @@
namespace Content.Shared._DV.Silicons.Components;
///<summary>
///This components prevents the normal EMP effects on an entity, and makes it take ion damage instead
///</summary>
[RegisterComponent]
public sealed partial class SiliconEmpComponent : Component;
@@ -0,0 +1,40 @@
using Content.Shared.Emp;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Damage.Components;
using Content.Shared._DV.Silicons.Components;
namespace Content.Shared._DV.Silicons;
public abstract class SharedSiliconEmpSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
/// <summary>
/// If the entity has the <see cref="SiliconEmpComponent"/>, then it should take damage instead of draining its battery.
/// </summary>
/// <param name="entity">The entity to check</param>
/// <returns>true if the entity has <see cref="SiliconEmpComponent"/></returns>
public bool ShouldTakeDamageInsteadOfPowerDrain(Entity<SiliconEmpComponent?> entity)
{
if (!Resolve(entity, ref entity.Comp, false))
return false;
return true;
}
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SiliconEmpComponent, EmpPulseEvent>(OnEmpPulse);
}
private void OnEmpPulse(Entity<SiliconEmpComponent> ent, ref EmpPulseEvent args)
{
if (args.Damage is not { } damage)
return;
_damageable.TryChangeDamage(ent.Owner, damage, false);
}
}
@@ -18,7 +18,7 @@ public sealed class XAEModifyGlimmerSystem : EntitySystem
private void OnActivated(Entity<XAEModifyGlimmerComponent> arti, ref XenoArtifactNodeActivatedEvent args)
{
var range = arti.Comp.Range;
var current = _glimmer.Glimmer;
var current = Math.Min(_glimmer.Glimmer, 1000); // Only scale up to 1000 glimmer
if (range.Min > current || current > range.Max)
return;
@@ -1,5 +0,0 @@
using Content.Shared.Alert;
namespace Content.Shared._Floof.OfferItem;
public sealed partial class AcceptOfferAlertEvent : BaseAlertEvent;
@@ -1,52 +0,0 @@
using Content.Shared.Alert;
using Content.Shared.Inventory.VirtualItem;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._Floof.OfferItem;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
[Access(typeof(SharedOfferItemSystem))]
public sealed partial class OfferItemComponent : Component
{
/// <summary>
/// Apparently this indicates whether the entity is currently choosing an entity to offer (right after pressing F).
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public bool IsInOfferMode;
/// <summary>
/// If this is true, then someone is currently offering an item to this entity, and <see cref="ReceivingFrom"/>
/// stores the ID of that entity.
/// </summary>
[DataField, AutoNetworkedField]
public bool IsInReceiveMode;
[DataField, AutoNetworkedField]
public string? Hand;
[DataField, AutoNetworkedField]
public EntityUid? Item;
/// <summary>
/// Floofstation note. So, this is EE shitcode, so prepare for an emotional rollercoaster.
/// This field can mean TWO things. It's either the target entity this entity is offering an item to,
/// or an entity that is offering an item to this entity.
/// Whether it's one or the other is distinguished by <see cref="IsInReceiveMode"/>.<br/><br/>
///
/// In rare cases it can be both. According to my research, if entity A offers an item to entity B, and entity B offers to entity A,
/// then both entities will end up in receive mode, and they will have each other as targets. There's a check preventing offer loops
/// of length more than 2.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid? ReceivingFrom;
[DataField]
public float MaxOfferDistance = 2f;
[DataField]
public ProtoId<AlertPrototype> OfferAlert = "Offer";
public EntityUid GetRealEntity(EntityManager entityManager) =>
entityManager.GetComponentOrNull<VirtualItemComponent>(Item)?.BlockingEntity ?? Item ?? EntityUid.Invalid;
}
@@ -1,11 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Floof.OfferItem;
/// <summary>
/// A marker component that, when applied to a virtual item, allows it to be offered using item offering.
/// Implementors have to listen on ItemTransferredEvent.
/// </summary>
[RegisterComponent]
[NetworkedComponent]
public sealed partial class OfferableVirtualItemComponent : Component;
@@ -1,93 +0,0 @@
using Content.Shared.ActionBlocker;
using Content.Shared.Alert;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Input;
using Content.Shared.Popups;
using Robust.Shared.Input.Binding;
using Robust.Shared.Player;
namespace Content.Shared._Floof.OfferItem;
public abstract partial class SharedOfferItemSystem
{
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
private void InitializeInteractions()
{
base.Initialize();
CommandBinds.Builder
.Bind(ContentKeyFunctions.OfferItem, InputCmdHandler.FromDelegate(SetInOfferMode, handle: false, outsidePrediction: false))
.Register<SharedOfferItemSystem>();
}
public override void Shutdown()
{
base.Shutdown();
CommandBinds.Unregister<SharedOfferItemSystem>();
}
/// <summary>
/// This sets IsInOfferMode to true, allowing the player to select whom to offer an item to with interaction.
/// </summary>
private void SetInOfferMode(ICommonSession? offerer)
{
if (offerer is not { } playerSession)
return;
if (playerSession.AttachedEntity is not { Valid: true } uid)
return;
if (!Exists(uid))
return;
if (!_actionBlocker.CanInteract(uid, null))
return;
if (!TryComp<OfferItemComponent>(uid, out var offerItem))
return;
if (!TryComp<HandsComponent>(uid, out var hands))
return;
if (_hands.GetActiveHand((uid, hands)) is not { } activeHandName)
return;
if (!_hands.TryGetHeldItem((uid, hands), activeHandName, out var heldItem))
return;
offerItem.Item = heldItem;
if (!offerItem.IsInOfferMode)
{
if (offerItem.Item == null)
{
_popup.PopupEntity(Loc.GetString("offer-item-empty-hand"), uid, uid);
return;
}
if (offerItem.Hand == null || offerItem.ReceivingFrom == null)
{
offerItem.IsInOfferMode = true;
offerItem.Hand = activeHandName;
Dirty(uid, offerItem);
return;
}
}
// If we're already offering an item to someone, cancel that offer
if (offerItem.ReceivingFrom != null)
{
UnReceive(offerItem.ReceivingFrom.Value, offererComp: offerItem);
offerItem.IsInOfferMode = false;
Dirty(uid, offerItem);
return;
}
UnOffer(uid, offerItem);
}
}
@@ -1,414 +0,0 @@
using Content.Shared._DV.Carrying;
using Content.Shared.Alert;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Nutrition.EntitySystems;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Timing;
// Dear contributor.
// This system is fucking unmaintainable.
// If you ever happen to touch this again, please do your best to document your changes and try to resolve mysteries surrounding this code.
// I did what I could to document the parts I managed to understand, but there is still more truth to be unveiled.
//
// HOURS_WASTED_HERE_FLOOFSTATION = 10
// HOURS_WASTED_HERE_DELTAV = 1
namespace Content.Shared._Floof.OfferItem;
public abstract partial class SharedOfferItemSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly CarryingSystem _carrying = default!;
[Dependency] private readonly PullingSystem _pulling = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<OfferItemComponent, AcceptOfferAlertEvent>(OnAcceptOffer);
SubscribeLocalEvent<OfferItemComponent, InteractUsingEvent>(OnInteractWithReceiver, before: [typeof(IngestionSystem)]);
SubscribeLocalEvent<OfferableVirtualItemComponent, BeforeRangedInteractEvent>(OnRangedInteractWithReceiver);
SubscribeLocalEvent<OfferItemComponent, MoveEvent>(OnMove);
SubscribeLocalEvent<BeingCarriedComponent, ItemTransferredEvent>(OnCarryTransfer);
SubscribeLocalEvent<PullableComponent, ItemTransferredEvent>(OnPulledTransfer);
InitializeInteractions();
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<OfferItemComponent, HandsComponent>();
while (query.MoveNext(out var uid, out var offerItem, out var hands))
{
// If the mob no longer holds an item in the original offering hand, clear offering mode
if (offerItem.Hand != null && !_hands.TryGetHeldItem((uid, hands), offerItem.Hand, out _))
{
if (offerItem.ReceivingFrom != null)
{
UnReceive(offerItem.ReceivingFrom.Value, offererComp: offerItem);
offerItem.IsInOfferMode = false;
Dirty(uid, offerItem);
}
else
UnOffer(uid, offerItem);
}
if (!offerItem.IsInReceiveMode)
{
_alertsSystem.ClearAlert(uid, offerItem.OfferAlert);
continue;
}
_alertsSystem.ShowAlert(uid, offerItem.OfferAlert);
}
}
#region Events
private void OnAcceptOffer(Entity<OfferItemComponent> ent, ref AcceptOfferAlertEvent args)
{
Receive((ent, ent.Comp));
}
private void OnInteractWithReceiver(Entity<OfferItemComponent> receiver, ref InteractUsingEvent args)
{
if (!_timing.IsFirstTimePredicted || _timing.ApplyingState || args.Handled)
return;
if (!TryComp<OfferItemComponent>(args.User, out var offererComponent))
return;
args.Handled = CreateOffer(receiver, (args.User, offererComponent));
}
private void OnRangedInteractWithReceiver(Entity<OfferableVirtualItemComponent> virtItem, ref BeforeRangedInteractEvent args)
{
// If the entity being offered is a virtual item, InteractUsing will not be raised
// because virtual items exclude themselves from being marked as used
// If this is the case, InteractHand will be raised instead, which we can use anyway because OfferItem.Item stores the offered item
//
// We also can't check Handled here because VirtualItemSystem handles it, ffs
// This won't lead you to accidentally offering someone your gun
//
// This is shitcode, this time my shitcode. My changes to the offering system allow you to transfer carrying and pulling,
// but in order to handle these, we need to be able to intercept interactions with virtual items.
//
// Ideally this code should be rewritten to:
// a) Have each different virtual item have a distinct component (e.g. CarryingVirtualItem) which would allow to distinguish them from the rest
// b) Not rely on the InteractionSystem.
// However, I'm not in the mood to do either. And I'm too deep into the rabbit hole of getting this shit to work.
if (!_timing.IsFirstTimePredicted || _timing.ApplyingState)
return;
var receiver = args.Target;
if (!TryComp<OfferItemComponent>(receiver, out var receiverComponent))
return;
var offerer = args.User;
if (!TryComp<OfferItemComponent>(offerer, out var offererComponent) || offererComponent.Item == null)
return;
// Since this is ranged, we must also check distance, because the interaction system wont check it for us in this case
if (!Transform(offerer).Coordinates.TryDistance(EntityManager, _transform, Transform(receiver.Value).Coordinates, out var dst)
|| dst > offererComponent.MaxOfferDistance)
return;
args.Handled = CreateOffer((receiver.Value, receiverComponent), (offerer, offererComponent));
}
private void OnMove(EntityUid uid, OfferItemComponent component, MoveEvent args)
{
if (_net.IsClient) // Client often mispredicts movement, we cant trust it here
return;
if (component.ReceivingFrom == null)
return;
if (_transform.InRange(args.NewPosition, Transform(component.ReceivingFrom.Value).Coordinates, component.MaxOfferDistance))
return;
UnOffer(uid, component);
}
private void OnCarryTransfer(Entity<BeingCarriedComponent> ent, ref ItemTransferredEvent args)
{
if (args.Handled
|| args.PassedItem == args.RealItem // Means the entity is transferred NOT via carrying
|| args.RealItem is not { Valid: true } carried
|| ent.Comp.Carrier is not { Valid: true } oldCarrier)
return;
_carrying.DropCarried(oldCarrier, ent);
args.Handled = _carrying.TryCarry(args.Target, carried);
}
private void OnPulledTransfer(Entity<PullableComponent> ent, ref ItemTransferredEvent args)
{
if (args.Handled
|| args.PassedItem == args.RealItem // Means the entity is transferred NOT via pulling
|| args.RealItem is not { Valid: true } pulled)
return;
_pulling.TryStopPull(pulled, ent);
args.Handled = _pulling.TryStartPull(args.Target, ent, null, ent.Comp);
}
#endregion
#region Offering / Recieving
/// <summary>
/// Attempts to create an offer. Expects offerer.Item to already be set to the offered item, offererComponent.InReceiveMode == true.
/// Will fail if offerer == receiver or if receiver already has a set TargetOrOfferer, and that person is not the current offerer
/// </summary>
private bool CreateOffer(Entity<OfferItemComponent> receiver, Entity<OfferItemComponent> offerer)
{
var offererComponent = offerer.Comp;
var receiverComponent = receiver.Comp;
if (offerer == receiver || receiverComponent.IsInReceiveMode || !offererComponent.IsInOfferMode)
return false;
if (offererComponent.IsInReceiveMode && offererComponent.ReceivingFrom != receiver)
return false;
receiverComponent.IsInReceiveMode = true;
receiverComponent.ReceivingFrom = offerer;
Dirty(receiver, receiverComponent);
offererComponent.ReceivingFrom = receiver; // TODO this is ee shitcode, may not be necessary?
offererComponent.IsInOfferMode = false;
Dirty(offerer, offererComponent);
if (offererComponent.Item == null)
return false;
// Sender popup (client-side only)
_popup.PopupClient(
Loc.GetString("offer-item-try-give",
("item", Identity.Entity(offererComponent.GetRealEntity(EntityManager), EntityManager)),
("target", Identity.Entity(receiver, EntityManager))),
offerer,
offerer);
// Receiver popup (server side only, not predicted because recipient != local player)
_popup.PopupEntity(
Loc.GetString("offer-item-try-give-target",
("user", Identity.Entity(receiverComponent.ReceivingFrom.Value, EntityManager)),
("item", Identity.Entity(offererComponent.GetRealEntity(EntityManager), EntityManager))),
offerer,
receiver,
Popups.PopupType.Medium);
return true;
}
/// <summary>
/// Resets the <see cref="OfferItemComponent"/> of the user and the target
/// </summary>
protected void UnOffer(EntityUid thisEntity, OfferItemComponent offererComp)
{
if (!TryComp<HandsComponent>(thisEntity, out var hands) || _hands.GetActiveHand((thisEntity, hands)) is null)
return;
if (offererComp.ReceivingFrom is { } otherEntity && TryComp<OfferItemComponent>(otherEntity, out var otherOfferer))
{
// So this tries to figure out which of these entities do what...
// if A.OfferItemComponent.Item != null, then A is currently offering an item to A.OfferItemComponent.TargetOrOfferer
// If it is null, then it is ONLY being offered an item TO.
if (offererComp.Item != null && _net.IsServer)
{
_popup.PopupEntity(
Loc.GetString("offer-item-no-give",
("item", Identity.Entity(offererComp.GetRealEntity(EntityManager), EntityManager)), // Floof - resolve virtual items
("target", Identity.Entity(otherEntity, EntityManager))),
thisEntity,
thisEntity);
_popup.PopupEntity(
Loc.GetString("offer-item-no-give-target",
("user", Identity.Entity(thisEntity, EntityManager)),
("item", Identity.Entity(offererComp.GetRealEntity(EntityManager), EntityManager))),
thisEntity,
otherEntity);
}
else if (otherOfferer.Item != null && _net.IsServer)
{
_popup.PopupEntity(
Loc.GetString("offer-item-no-give",
("item", Identity.Entity(otherOfferer.GetRealEntity(EntityManager), EntityManager)), // Floof - resolve virtual items
("target", Identity.Entity(thisEntity, EntityManager))),
otherEntity,
otherEntity);
_popup.PopupEntity(
Loc.GetString("offer-item-no-give-target",
("user", Identity.Entity(otherEntity, EntityManager)),
("item", Identity.Entity(otherOfferer.GetRealEntity(EntityManager), EntityManager))),
otherEntity,
thisEntity);
}
otherOfferer.IsInOfferMode = false;
otherOfferer.IsInReceiveMode = false;
otherOfferer.Hand = null;
otherOfferer.ReceivingFrom = null;
otherOfferer.Item = null;
Dirty(otherEntity, otherOfferer);
}
offererComp.IsInOfferMode = false;
offererComp.IsInReceiveMode = false;
offererComp.Hand = null;
offererComp.ReceivingFrom = null;
offererComp.Item = null;
Dirty(thisEntity, offererComp);
}
/// <summary>
/// Cancels the transfer of the item
/// </summary>
protected void UnReceive(EntityUid receiver, OfferItemComponent? receiverComp = null, OfferItemComponent? offererComp = null)
{
if (!Resolve(receiver, ref receiverComp)
|| receiverComp.ReceivingFrom is not {} offerer
|| !Resolve(offerer, ref offererComp))
return;
// Idk why this check is here
if (!TryComp<HandsComponent>(receiver, out var hands) || _hands.GetActiveHand((receiver, hands)) == null || receiverComp.ReceivingFrom == null)
return;
// If offererComp.Item != null, then they are actively offering to TargetOrOfferer
// Normally this method is called right after a transfer is done, but this part can be called from SetInOfferMode when the player presses F again to cancel an ongoing offer
if (offererComp.Item != null)
{
_popup.PopupClient(
Loc.GetString("offer-item-no-give",
("item", Identity.Entity(offererComp.GetRealEntity(EntityManager), EntityManager)), // Floof - resolve virtual items
("target", Identity.Entity(receiver, EntityManager))),
offerer,
offerer);
_popup.PopupEntity(
Loc.GetString("offer-item-no-give-target",
("user", Identity.Entity(receiverComp.ReceivingFrom.Value, EntityManager)), // Floof - resolve virtual items
("item", Identity.Entity(offererComp.GetRealEntity(EntityManager), EntityManager))),
offerer,
receiver);
}
if (!offererComp.IsInReceiveMode)
{
offererComp.ReceivingFrom = null;
receiverComp.ReceivingFrom = null;
}
offererComp.Item = null;
offererComp.Hand = null;
receiverComp.IsInReceiveMode = false;
Dirty(receiver, receiverComp);
}
/// <summary>
/// Accepting the offer and receive item
/// </summary>
public void Receive(Entity<OfferItemComponent?> receiver)
{
if (!_timing.IsFirstTimePredicted)
return;
if (!Resolve(receiver, ref receiver.Comp))
return;
if (!TryComp<OfferItemComponent>(receiver.Comp.ReceivingFrom, out var offererComponent) ||
offererComponent.Hand == null ||
receiver.Comp.ReceivingFrom is not {} sender ||
!TryComp<HandsComponent>(receiver, out var hands))
return;
if (offererComponent.Item != null)
{
// Floof - check if there's something else handling it first
var realItem = offererComponent.GetRealEntity(EntityManager);
if (!TryHandleExtendedTransfer(sender, receiver, offererComponent.Item.Value, realItem)
&& !_hands.TryPickup(receiver, offererComponent.Item.Value, handsComp: hands))
{
_popup.PopupEntity(Loc.GetString("offer-item-full-hand"), receiver, receiver);
return;
}
_popup.PopupEntity(
Loc.GetString("offer-item-give",
("item", Identity.Entity(realItem, EntityManager)), // FLoof - resolve virtual items
("target", Identity.Entity(receiver, EntityManager))),
sender,
sender);
_popup.PopupEntity(
Loc.GetString("offer-item-give-other",
("user", Identity.Entity(receiver.Comp.ReceivingFrom.Value, EntityManager)),
("item", Identity.Entity(realItem, EntityManager)), // FLoof - resolve virtual items
("target", Identity.Entity(receiver, EntityManager))),
sender,
Filter.PvsExcept(sender, entityManager: EntityManager),
true);
}
offererComponent.Item = null;
UnReceive(receiver, receiver.Comp, offererComponent);
}
#endregion
/// <summary>
/// Returns true if <see cref="OfferItemComponent.IsInOfferMode"/> = true
/// </summary>
protected bool IsInOfferMode(Entity<OfferItemComponent?> ent)
{
return Resolve(ent, ref ent.Comp, false) && ent.Comp.IsInOfferMode;
}
private bool TryHandleExtendedTransfer(EntityUid user, EntityUid target, EntityUid offeredItem, EntityUid realItem)
{
var ev = new ItemTransferredEvent
{
User = user,
Target = target,
PassedItem = offeredItem,
RealItem = realItem,
};
RaiseLocalEvent(realItem, ref ev);
return ev.Handled;
}
}
/// <summary>
/// Raised on the entity that was transferred via item offering.
/// </summary>
[ByRefEvent]
public sealed class ItemTransferredEvent : HandledEntityEventArgs
{
public EntityUid User;
public EntityUid Target;
/// <summary>
/// The actual item being passed around. Can be a virtual item.
/// </summary>
public EntityUid PassedItem;
/// <summary>
/// If <see cref="PassedItem"/> is a virtual item, this field contains the real item that was transferred.
/// </summary>
public EntityUid? RealItem;
}
@@ -1,66 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Impstation.Clothing;
/// <summary>
/// Adds examine text to the entity that wears item, for making things obvious.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(WearerGetsExamineTextSystem))]
public sealed partial class WearerGetsExamineTextComponent : Component
{
/// <summary>
/// The LocId that specifies what category of object this is.
/// i.e. "pin" or "scarf"
/// Should be redefined on a per-category basis, naturally.
/// </summary>
[DataField("thing")]
public LocId Category = "obvious-thing-default";
/// <summary>
/// The LocId that specifies what member of the category this is.
/// i.e. "lesbian pride"
/// Can be used to define text colors that are copied to all things
/// which share this specifier (i.e. the other items of the same pride).
/// (And summarily, makes accessibility-based changes for these colors a cinch.)
/// Should be defined by each thing that has this component.
/// </summary>
[DataField("thingType")]
public LocId Specifier = "obvious-type-default";
/// <summary>
/// The LocId that will be added to any wearing entity's examination.
/// Typically only needs redefining on a per-category basis,
/// but items that should have totally-unique obvious text can simply specify them here.
/// </summary>
[DataField("examineText", required: true)]
public LocId ExamineOnWearer = "obvious-desc-default";
/// <summary>
/// Reference to the entity wearing this clothing.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid? Wearer;
/// <summary>
/// The string that is attached to this item's ExamineOnWearer.
/// Typically doesn't need to be redefined.
/// </summary>
[DataField]
public LocId PrefixExamineOnWearer = "obvious-prefix-wearing";
/// <summary>
/// If true, an entity with this item in any slot (i.e. in pockets) will gain the examine text,
/// instead of when just equipped as clothing.
/// Should be used sparingly only when truly appropriate; this is effectively a half-measure for lack of a special pin slot.
/// </summary>
[DataField]
public bool PocketEvident;
/// <summary>
/// If true, the entity's description will inform examiners what others will see on the wearer (before they equip it).
/// If the item is contraband, the item will also warn that displaying it may cause undue attention.
/// Keep this false for good-natured jokes (i.e. the pride cloaks having funny, non-pride names)
/// </summary>
[DataField]
public bool WarnExamine = true;
}
@@ -1,111 +0,0 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Inventory.Events;
using Content.Shared.Contraband;
using Content.Shared._Impstation.Examine;
using System.Text;
namespace Content.Shared._Impstation.Clothing;
/// <summary>
/// Adds examine text to the entity that wears item, for making things obvious.
/// </summary>
public sealed class WearerGetsExamineTextSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<WearerGetsExamineTextComponent, GotEquippedEvent>(OnEquipped);
SubscribeLocalEvent<WearerGetsExamineTextComponent, GotUnequippedEvent>(OnUnequipped);
SubscribeLocalEvent<WearerGetsExamineTextComponent, ExaminedEvent>(OnExamine);
}
private void OnEquipped(Entity<WearerGetsExamineTextComponent> entity, ref GotEquippedEvent args)
{
if (!TryComp(entity, out ClothingComponent? clothing))
return;
var isCorrectSlot = (clothing.Slots & args.SlotFlags) != Inventory.SlotFlags.NONE;
if (!entity.Comp.PocketEvident) //if it can't be evident in our pockets
{
// Make sure the clothing item was equipped to the right slot, and not just held in a hand.
if (!isCorrectSlot)
return;
}
entity.Comp.Wearer = args.Equipee;
Dirty(entity);
//GIVE THEM INSPECT TEXT
var obviousExamine = EnsureComp<ExtraExamineTextComponent>(args.Equipee);
obviousExamine.Lines.TryAdd(entity.Owner, //using try so that we don't cause an error if we move something from slot to slot
ConstructExamineText(entity, !isCorrectSlot, args.Equipee));
}
private string ConstructExamineText(Entity<WearerGetsExamineTextComponent> entity, bool prefixFallback, EntityUid affecting)
{
//parameters (these are the same between both constructions)
var user = Identity.Entity(affecting, EntityManager);
var nomen = Identity.Name(affecting, EntityManager);
var thing = Loc.GetString(entity.Comp.Category);
var type = Loc.GetString(entity.Comp.Specifier);
var stringSpec = entity.Comp.Specifier.ToString();
var shortType = stringSpec.Substring(stringSpec.LastIndexOf('-')); // necessary for working with colored text...
var prefix = Loc.GetString(prefixFallback ? "obvious-prefix-default" : entity.Comp.PrefixExamineOnWearer, // uses a different prefix if worn / displayed
("user", user),
("name", nomen),
("thing", thing),
("type", type));
var suffix = Loc.GetString(entity.Comp.ExamineOnWearer,
("user", user),
("name", nomen),
("thing", thing),
("type", type),
("short-type", shortType));
return prefix + " " + suffix;
}
private void OnUnequipped(Entity<WearerGetsExamineTextComponent> entity, ref GotUnequippedEvent args)
{
if (entity.Comp.Wearer is not { } wearer)
return;
if (TryComp(wearer, out ExtraExamineTextComponent? obviousExamine))
{
obviousExamine.Lines.Remove(entity.Owner);
}
entity.Comp.Wearer = null;
Dirty(entity);
}
private void OnExamine(Entity<WearerGetsExamineTextComponent> entity, ref ExaminedEvent args)
{
var currentlyWorn = entity.Comp.Wearer != null;
var outString = new StringBuilder(Loc.GetString(currentlyWorn ? "obvious-on-item-currently" : "obvious-on-item",
("used", Loc.GetString(entity.Comp.PocketEvident ? "obvious-reveal-pockets" : "obvious-reveal-default")),
("thing", entity.Comp.Category),
("me", Identity.Entity(entity, EntityManager))));
if (entity.Comp.WarnExamine)
{
if (!currentlyWorn && TryComp(entity, out ContrabandComponent? contra)) // if the item's contra and we're not wearing it yet
{
var contraLocId = "obvious-on-item-contra-" + contra.Severity; // apply additional text if the item is contraband to note that displaying it might be really bad
if (Loc.HasString(contraLocId)) // saves us the trouble of making a switch block for this
outString.Append(" " + Loc.GetString(contraLocId));
}
var affecting = currentlyWorn ? entity.Comp.Wearer.GetValueOrDefault() : args.Examiner;
var testOut = ConstructExamineText(entity, false, affecting);
outString.Append("\n" + Loc.GetString("obvious-on-item-for-others",
("will", currentlyWorn ? "can" : "will"), // i love hardcoding strings it's my favorite thing ever
("output", testOut)));
}
args.PushMarkup(outString.ToString());
}
}
@@ -1,40 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Impstation.Examine;
[RegisterComponent, NetworkedComponent]
public sealed partial class DetailedInspectComponent : Component
{
[DataField]
public LocId VerbText = "verbs-detailed-inspect";
[DataField]
public LocId VerbMessage = "verbs-detailed-inspect-message";
[DataField(required: true)]
public List<LocId> ExamineText;
/// <summary>
/// Whether or not the entries in ExamineText are separated by linebreaks.
/// </summary>
[DataField]
public bool LineBreak = true;
/// <summary>
/// Whether or not the entries in ExamineText are preceded by ticks.
/// </summary>
[DataField]
public bool TickEntries = false;
/// <summary>
/// Whether or not entries in the list are numbered.
/// </summary>
[DataField]
public bool NumberedEntries = false;
/// <summary>
/// Rooted directory of the icon for the verb.
/// </summary>
[DataField]
public string Icon = "/Textures/Interface/VerbIcons/dot.svg.192dpi.png";
}
@@ -1,50 +0,0 @@
using Content.Shared.Examine;
using Content.Shared.Verbs;
using Robust.Shared.Network;
using Robust.Shared.Utility;
namespace Content.Shared._Impstation.Examine;
public sealed partial class DetailedInspectSystem : EntitySystem
{
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DetailedInspectComponent, GetVerbsEvent<ExamineVerb>>(OnGetVerb);
}
public void OnGetVerb(Entity<DetailedInspectComponent> ent, ref GetVerbsEvent<ExamineVerb> args)
{
if (!args.CanInteract || !args.CanAccess || !_net.IsServer)
return;
var msg = new FormattedMessage();
var numberedIndex = 1;
foreach (var locId in ent.Comp.ExamineText)
{
if (ent.Comp.TickEntries)
msg.AddMarkupOrThrow("- ");
if (ent.Comp.NumberedEntries)
{
msg.AddMarkupOrThrow($"{numberedIndex}. ");
numberedIndex++;
}
msg.AddMarkupOrThrow(Loc.GetString(locId));
if (ent.Comp.LineBreak)
msg.PushNewline();
else
msg.AddMarkupOrThrow(" ");
}
_examine.AddDetailedExamineVerb(args, ent.Comp, msg, Loc.GetString(ent.Comp.VerbText), ent.Comp.Icon, Loc.GetString(ent.Comp.VerbMessage));
}
}
@@ -1,24 +0,0 @@
using Robust.Shared.GameStates;
using Content.Shared._Impstation.Clothing;
namespace Content.Shared._Impstation.Examine;
/// <summary>
/// Adds examine text to the entity, intentionally "obvious details".
/// Like, that's it. It's basic -- all it does is add the lines to the attached entity.
/// This is particularly used for assigning players unique examine text.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(ExtraExamineTextSystem), typeof(WearerGetsExamineTextSystem))]
public sealed partial class ExtraExamineTextComponent : Component
{
/// <summary>
/// The LocIds that will be added to the attached entity's examination.
///
/// The key is the source of the line, and the value is the text
/// (built by the component that creates this one).
/// </summary>
[DataField, AutoNetworkedField]
public Dictionary<EntityUid, LocId> Lines { get; set; } = new();
}
@@ -1,33 +0,0 @@
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
namespace Content.Shared._Impstation.Examine;
/// <summary>
/// Adds examine text to the entity, intentionally "obvious details".
/// Like, that's it. It's basic -- all it does is add the line to the attached entity.
/// This is particularly used for assigning players unique examine text.
/// </summary>
public sealed class ExtraExamineTextSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ExtraExamineTextComponent, ExaminedEvent>(OnExamine);
}
private void OnExamine(Entity<ExtraExamineTextComponent> entity, ref ExaminedEvent args)
{
if (entity.Comp.Lines.Count == 0)
{
RemCompDeferred<ExtraExamineTextComponent>(entity); // no more need for me!
return;
}
foreach (var l in entity.Comp.Lines)
{
args.PushMarkup(l.Value);
}
}
}
@@ -1,8 +0,0 @@
namespace Content.Shared._Starlight.Flash.Components;
[RegisterComponent]
public sealed partial class FlashModifierComponent : Component
{
[DataField]
public float Modifier = 1f;
}
@@ -1,51 +0,0 @@
namespace Content.Shared.Humanoid;
public static class EyeColor
{
public const float ShadekinBrightness = 0.251f;
public static bool VerifyShadekin(Color color)
{
var colorHsv = Color.ToHsv(color);
if (colorHsv.Z > ShadekinBrightness)
return false;
return true;
}
public static Color MakeShadekinValid(Color color)
{
var hsv = Color.ToHsv(color);
hsv.Z = Math.Clamp(hsv.Z, 0, ShadekinBrightness);
return Color.FromHsv(hsv);
}
public static bool VerifyEyeColor(HumanoidEyeColor type, Color color)
{
return type switch
{
HumanoidEyeColor.Shadekin => VerifyShadekin(color),
_ => false,
};
}
public static Color ValidEyeColor(HumanoidEyeColor type, Color color)
{
return type switch
{
HumanoidEyeColor.Shadekin => MakeShadekinValid(color),
_ => color
};
}
}
public enum HumanoidEyeColor : byte
{
Shadekin,
}
[ByRefEvent]
public record struct EyeColorInitEvent();
@@ -1,45 +0,0 @@
using Content.Shared.Alert;
using Content.Shared.FixedPoint;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared._Starlight;
#region Shadekin
[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause, AutoGenerateComponentState]
public sealed partial class ShadekinComponent : Component
{
[DataField]
public ProtoId<AlertPrototype> ShadekinAlert = "Shadekin";
[ViewVariables(VVAccess.ReadOnly), AutoPausedField]
public TimeSpan NextUpdate = TimeSpan.Zero;
[DataField]
public TimeSpan UpdateCooldown = TimeSpan.FromSeconds(1f);
[AutoNetworkedField, ViewVariables]
public ShadekinState CurrentState { get; set; } = ShadekinState.Dark;
[DataField("thresholds", required: true)]
public SortedDictionary<FixedPoint2, ShadekinState> Thresholds = new();
/// <summary>
/// whether to flicker lights or not. default on
/// </summary>
[DataField] public bool DoLightFlicker = true;
}
[Serializable, NetSerializable]
public enum ShadekinState : byte
{
Invalid = 0,
Dark = 1,
Low = 2,
Annoying = 3,
High = 4,
Extreme = 5
}
#endregion
@@ -1,9 +0,0 @@
- files: ["beep_500.ogg"]
license: "CC0-1.0"
copyright: "Synthesized in Audacity by BasedUser."
source: "https://github.com/ekrixi-14/ekrixi"
- files: ["whirr1.ogg", "whirr2.ogg", "whirr3.ogg"]
license: "CC0-1.0"
copyright: "Taken from source, spectrally modified and clipped"
source: "https://freesound.org/people/sad3d/sounds/500168/"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,29 +0,0 @@
- files: ["wurble.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from CHOMPStation"
source: "https://github.com/CHOMPStation2/CHOMPStation2/blob/e846f4f73d14875a390ede039a11e4b9b699f420/sound/voice/wurble.ogg"
- files: ["mar.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from CHOMPStation"
source: "https://github.com/CHOMPStation2/CHOMPStation2/blob/e846f4f73d14875a390ede039a11e4b9b699f420/sound/voice/mar.ogg"
- files: ["scream_f1.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken and remixed from CHOMPStation"
source: "https://github.com/CHOMPStation2/CHOMPStation2/blob/e846f4f73d14875a390ede039a11e4b9b699f420/sound/voice/scream_f1.ogg"
- files: ["scream_f2.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken and remixed from CHOMPStation"
source: "https://github.com/CHOMPStation2/CHOMPStation2/blob/e846f4f73d14875a390ede039a11e4b9b699f420/sound/voice/scream_f2.ogg"
- files: ["scream_m1.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken and remixed from CHOMPStation"
source: "https://github.com/CHOMPStation2/CHOMPStation2/blob/e846f4f73d14875a390ede039a11e4b9b699f420/sound/voice/scream_m1.ogg"
- files: ["scream_m2.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken and remixed from CHOMPStation"
source: "https://github.com/CHOMPStation2/CHOMPStation2/blob/e846f4f73d14875a390ede039a11e4b9b699f420/sound/voice/scream_f2.ogg"
Binary file not shown.
Binary file not shown.
-16
View File
@@ -332,21 +332,5 @@ Entries:
id: 36
time: '2026-06-16T20:02:18.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6006
- author: einknusprigestoast
changes:
- message: Changed SRT loadouts
type: Tweak
- message: Added the eviscerator, a ERT-/SRT-issued heavy plasma rifle.
type: Add
id: 37
time: '2026-07-13T13:44:06.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6233
- author: einknusprigestoast
changes:
- message: The white dragon has been spotted in the sector.
type: Add
id: 38
time: '2026-07-19T16:18:47.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6317
Name: DeltaVAdmin
Order: 5
+433 -458
View File
@@ -1,4 +1,437 @@
Entries:
- author: PureBreadBagel
changes:
- message: You are now able to craft the makeshift and forged varient of the omnitool!
type: Fix
- message: The makeshift/forged varient of the omnitool should no longer display
"verb-categories-switch" in its right click menu.
type: Fix
id: 2036
time: '2026-01-09T16:34:26.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5165
- author: MilonPL
changes:
- message: Picking senior PDAs in the loadout will now change your job name accordingly
once again.
type: Fix
id: 2037
time: '2026-01-10T16:48:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5176
- author: Eternally-Confused
changes:
- message: The announcement for the Spare Captain's ID no longer references crimes
that don't exist
type: Fix
id: 2038
time: '2026-01-10T21:42:58.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5177
- author: Eternally-Confused
changes:
- message: Feroxi nukies now recieve actual syndicate survival boxes.
type: Fix
id: 2039
time: '2026-01-10T21:43:51.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5179
- author: FaintSpeaker
changes:
- message: Fix for one error possibly causing replays to fail to load. Continue
to report any broken replays after this fix!
type: Fix
id: 2040
time: '2026-01-10T21:44:55.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5173
- author: snowywinters
changes:
- message: The station AI is now better integrated into the station allowing use
of fabs and substations/SMES
type: Add
id: 2041
time: '2026-01-10T21:58:12.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5132
- author: FaintSpeaker
changes:
- message: Adv. Cleaning Cyborg Module now regenerates Space Cleaner.
type: Add
id: 2042
time: '2026-01-10T22:07:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5155
- author: ShepardToTheStars, Toby222
changes:
- message: Fixed feroxi paramedic and goliath hardsuit helmet sprites displaying
the incorrect sprite.
type: Fix
id: 2043
time: '2026-01-10T22:07:30.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5161
- author: keekee38
changes:
- message: Increased minimum player count for nukies to 20 ready and 40 total players.
type: Tweak
id: 2044
time: '2026-01-10T23:06:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5159
- author: MilonPL
changes:
- message: Fixed emergency jaws of life not draining their battery when prying doors.
type: Fix
id: 2045
time: '2026-01-11T15:34:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5189
- author: ShepardToTheStars
changes:
- message: Crawling or being knocked down no longer nerfs your melee damage by 75%.
You will do the normal amount of melee damage now.
type: Tweak
id: 2046
time: '2026-01-11T15:38:24.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5182
- author: ShepardToTheStars
changes:
- message: The spare ID will always unlock 15 seconds after nukies declare war,
even if there is a captain.
type: Tweak
id: 2047
time: '2026-01-11T15:40:02.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5104
- author: Pharaz4
changes:
- message: Added Skia to guidebook.
type: Add
- message: Fixed some typos and a page on guidebook.
type: Fix
id: 2048
time: '2026-01-11T16:27:06.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5178
- author: Minerva
changes:
- message: Crash carts can now be ordered from Logistics under the Medical category.
type: Add
id: 2049
time: '2026-01-11T16:43:30.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5190
- author: DisposableCrewmember42
changes:
- message: The revenant can use its Haunt ability again
type: Fix
id: 2050
time: '2026-01-11T19:48:58.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5124
- author: DisposableCrewmember42
changes:
- message: The Revenant can no longer be killed by spiking your own water bottle.
type: Fix
id: 2051
time: '2026-01-11T19:57:38.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5125
- author: Apachito
changes:
- message: Moved the craftable armor to the clothing tab in the crafting menu
type: Tweak
- message: Reduced firerate on the forged smg from 5 to 4.5
type: Tweak
- message: Made improvised ammo do 75% damage compared to their normal counterparts
type: Tweak
id: 2052
time: '2026-01-11T22:08:13.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5129
- author: Unkn0wnGh0st333
changes:
- message: Gulp Emote from Goob has been added... gulp...
type: Add
id: 2053
time: '2026-01-12T04:42:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5033
- author: Velcroboy
changes:
- message: Tanks of ammonia are now purchasable from logi for mixing more space
cleaner or making the station stinky
type: Add
id: 2054
time: '2026-01-13T05:00:57.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5167
- author: Pharaz4
changes:
- message: Syndicate Assault, Medical, and Saboteur borgs now get names.
type: Add
- message: Fixed SRN Saboteur borg not being able to fit Engineering module
type: Fix
id: 2055
time: '2026-01-14T13:23:22.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5197
- author: MilonPL
changes:
- message: Added a dynamic tip system that shows contextual tips to players based
on their job, playtime, and more.
type: Add
- message: Tips can be disabled or reset in the Options menu under DeltaV.
type: Add
id: 2056
time: '2026-01-14T20:23:40.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5199
- author: Velcroboy
changes:
- message: Fixed bomb and effigy targets being on grids off the station sometimes.
type: Fix
id: 2057
time: '2026-01-15T07:29:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5213
- author: Pharaz4
changes:
- message: Hard hats are now protective!
type: Tweak
id: 2058
time: '2026-01-15T15:44:57.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5175
- author: Halo3moth
changes:
- message: The hos locker will now spawn with a briefcase that allows them to pick
between sidearms.
type: Add
- message: The energy magnum now also works for the hos steal objective.
type: Tweak
- message: Energy magnum standard bolt from 20 heat to 24 and magnum bolt from 30
heat to 24 heat and 11 pierce.
type: Tweak
id: 2059
time: '2026-01-16T17:46:17.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5203
- author: mnva0
changes:
- message: Ovinia now start with a emergency survival box.
type: Fix
id: 2060
time: '2026-01-16T17:55:22.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5207
- author: Halo3moth
changes:
- message: Re-added the graytide stamp to maints lockers.
type: Add
- message: Tweak some of the spawn rates for meme items in maints lockers.
type: Tweak
id: 2061
time: '2026-01-16T17:58:01.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5221
- author: Pharaz4
changes:
- message: Fixed extra hardsuit that spawned in Suit storage lockers.
type: Fix
- message: Fixed free Epistemics access for HoP in pTech.
type: Fix
id: 2062
time: '2026-01-16T17:59:12.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5201
- author: BarryNorfolk
changes:
- message: Added new mapping command 'togglenetworklinks'
type: Add
id: 2063
time: '2026-01-16T18:09:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5188
- author: Halo3moth
changes:
- message: Devils will now role 2.5 times more often.
type: Tweak
id: 2064
time: '2026-01-16T18:13:00.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5225
- author: EmberAstra
changes:
- message: Added the microwave emitter! Epistemics has a radiation gun to shoot
artifacts with now!
type: Add
id: 2065
time: '2026-01-16T18:19:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5205
- author: DisposableCrewmember42
changes:
- message: Lord Singuloth rises.
type: Tweak
id: 2066
time: '2026-01-16T18:26:06.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5209
- author: BunglesnortBoss
changes:
- message: Made AI Nanites a good option. Heals 50 HP with a shorter cooldown
type: Tweak
id: 2067
time: '2026-01-16T18:27:22.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5210
- author: pootslap
changes:
- message: Carpy has acquired a fancy new pen and stamp and is ready to dispense
legal advice.
type: Tweak
- message: Removed the duplicate chaplain stamp from the listening post
type: Fix
id: 2068
time: '2026-01-16T18:29:14.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5169
- author: cmorley191
changes:
- message: Harpies are now reliably more sensitive to pollutant gases than other
species. For example, 0.4% of CO2 will make harpies start gasping, while humans
are okay up to 1.1% CO2
type: Add
id: 2069
time: '2026-01-16T18:32:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5158
- author: ShepardToTheStars
changes:
- message: Added CentComm Shipyard to order free ships with CentComm access.
type: Add
id: 2070
time: '2026-01-16T18:37:33.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5172
- author: EmberAstra
changes:
- message: Made the Engineering Void Suit printable!
type: Tweak
id: 2071
time: '2026-01-16T18:41:11.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5222
- author: cmorley191
changes:
- message: The Oracle will no longer request items that are "very" far away from
being researched.
type: Tweak
id: 2072
time: '2026-01-16T18:58:51.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4430
- author: Proxysseia
changes:
- message: Prison Knives no longer spawn in Prison Lockers
type: Remove
id: 2073
time: '2026-01-16T18:59:31.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4934
- author: Toby222
changes:
- message: Removed footprint prediction (for now)
type: Remove
id: 2074
time: '2026-01-16T19:07:45.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5224
- author: Velcroboy
changes:
- message: Prisoners can find dull bread knives in the ChefVend.
type: Tweak
id: 2075
time: '2026-01-17T21:13:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5234
- author: Halo3moth
changes:
- message: The T1 armored vest (slim) can now once again be picked in security loadouts.
type: Add
id: 2076
time: '2026-01-17T21:36:45.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5220
- author: biddygelson
changes:
- message: 'Academy: added anti-meteor zones and anti-anomaly zone, AI restoration
console in Mystagogue, Robotics Console in robo, fishing hole added to park,
materials is cargo at roundstart.'
type: Add
- message: 'Academy: station starts with distro and waste enabled, spare atmos chambers
start as vacuums, split artifacts'' APCs for power management, botany has more
trays and is slightly larger, department-front holopads in the department.'
type: Tweak
id: 2077
time: '2026-01-18T01:54:56.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5130
- author: DisposableCrewmember42
changes:
- message: You can no longer drink the deep fryer.
type: Fix
id: 2078
time: '2026-01-18T04:40:48.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5238
- author: snowywinters
changes:
- message: Reinforced cameras can now be built! They have additional HP and are
more resistant to explosions and meteors.
type: Add
- message: The AI has its own section in the security cameras console.
type: Add
id: 2079
time: '2026-01-18T17:18:45.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5027
- author: Dorragon
changes:
- message: Ready Manifest added to the lobby
type: Add
id: 2080
time: '2026-01-18T18:47:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5187
- author: MilonPL
changes:
- message: Added a new traits system, supporting conditions and new effects. Make
sure to check out the Traits tab in the character editor!
type: Add
- message: All character traits have been reset.
type: Remove
id: 2081
time: '2026-01-20T11:49:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5208
- author: pootslap
changes:
- message: You can now examine character descriptions from much further away.
type: Tweak
id: 2082
time: '2026-01-20T11:49:48.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5219
- author: Eternally-Confused
changes:
- message: (TEST MERGE) Space pens now contain a chemical called Stabilizine instead
of Leporazine, which is better at stabilizing body temperature.
type: Tweak
- message: Avali no longer die from space pens.
type: Tweak
id: 2083
time: '2026-01-20T21:15:21.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5181
- author: turtlemutt
changes:
- message: Added more names for ghost role spawns.
type: Add
id: 2084
time: '2026-01-21T05:17:05.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5254
- author: Cepelinas1
changes:
- message: Logistics Officers can now use the shipyard to buy shuttles. No need
to beg Captain to buy it anymore!
type: Add
id: 2085
time: '2026-01-21T05:52:10.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5251
- author: Colin-Tel
changes:
- message: Eked the Anglish tung tie. In other words, added a trait that lets you
talk like an Anglo Saxon with over 1,100 word replacements.
type: Add
id: 2086
time: '2026-01-21T09:37:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4092
- author: ShepardToTheStars
changes:
- message: The ninja is now revealed with hit with attacks, projectiles, explosions,
and grenades that do damage.
type: Tweak
- message: The ninja is now revealed with hit with attacks, projectiles, explosions,
and grenades that do damage.
type: Fix
id: 2087
time: '2026-01-21T14:18:56.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5217
- author: Toby222
changes:
- message: FTL times have been adjusted. Startup is shorter, travel is longer.
type: Tweak
- message: The FTL startup sound now lines up with the duration of startup again!!!
type: Fix
id: 2088
time: '2026-01-21T14:50:49.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5257
- author: ShepardToTheStars, foxcumberland
changes:
- message: Added fashionable longcoats for command, security, and crew. Find them
@@ -3907,462 +4340,4 @@
id: 2536
time: '2026-07-09T03:53:55.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6080
- author: keekee38
changes:
- message: after years of testing, NT managed to make more bullets fit into the
magnum cartridge boxes
type: Tweak
id: 2537
time: '2026-07-09T04:42:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6226
- author: rebe83
changes:
- message: Revenant can be grinded... ground...grounded up in a grinder without
salt to be killed WITHOUT exploding!
type: Tweak
- message: Revenant stasis time increased from 60 seconds to 100 seconds.
type: Tweak
- message: Skia takes a bit less damage from light sources.
type: Tweak
id: 2538
time: '2026-07-09T11:38:49.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5981
- author: Eternally-Confused
changes:
- message: The "Sentencing" and "Crime Modifiers" sections of Space Law have been
added to the in-game guidebook.
type: Fix
id: 2539
time: '2026-07-09T13:29:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6223
- author: Halo3moth
changes:
- message: Antagonist Guidelines have been updated please re-review them!
type: Tweak
id: 2540
time: '2026-07-09T18:03:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5929
- author: CarolCuchara
changes:
- message: Secure cabinets now need to be unlocked to be able to insert items!
type: Tweak
id: 2541
time: '2026-07-10T13:59:29.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6269
- author: Radezolid
changes:
- message: Seismic charges cost increased from 1250 mining points to 6250 mining
points.
type: Tweak
id: 2542
time: '2026-07-10T14:05:18.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6245
- author: ShepardToTheStars
changes:
- message: Advanced cleaning is now a T3 civilian services research.
type: Tweak
id: 2543
time: '2026-07-10T15:03:13.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6271
- author: ShepardToTheStars
changes:
- message: You can no longer see your own health bar with the medical hud (or similar
eyewear).
type: Tweak
id: 2544
time: '2026-07-10T17:22:38.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6241
- author: ShepardToTheStars
changes:
- message: New death implanters have been added to the syndicate uplink for those
to get the objective to die a glorious death - the true death implanter (free),
death acidifier implanter (free), and microbomb implanter (2TC). Choose wisely
because you only get one.
type: Add
id: 2545
time: '2026-07-10T19:58:17.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6221
- author: CheddaCheez
changes:
- message: Rodentia can now have whiskers and ears at the same time. Cheek fluff
too.
type: Tweak
id: 2546
time: '2026-07-10T20:08:32.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6273
- author: stormyatt
changes:
- message: Added welding mask and multitool to utility belt for MG and salvagers.
type: Add
- message: Removed network configurator from utility belt for MG and salvagers.
type: Remove
id: 2547
time: '2026-07-10T20:20:09.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6217
- author: ArionGekkota
changes:
- message: Allulalo can now fit inside bags!
type: Add
id: 2548
time: '2026-07-10T20:21:42.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6248
- author: Radezolid
changes:
- message: The LO's knuckledusters are back in, get them at your closest Logistics
Officer's locker.
type: Tweak
id: 2549
time: '2026-07-11T08:29:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6243
- author: Radezolid
changes:
- message: Engineering tool belts now come with a nanite applicator.
type: Tweak
id: 2550
time: '2026-07-11T16:09:23.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6261
- author: ollyoaner
changes:
- message: "Slime people can now add elf ear customization markings! \U0001F9DD"
type: Add
id: 2551
time: '2026-07-11T16:30:08.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6265
- author: rebe83
changes:
- message: Ion damage has been removed.
type: Remove
id: 2552
time: '2026-07-11T16:34:56.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5960
- author: rebe83, mousesweater
changes:
- message: Command members now have learner PAIs in their locker ready to absorb
knowledge!
type: Add
id: 2553
time: '2026-07-11T17:25:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5924
- author: Coryler
changes:
- message: Avali Preened Feather Color are now correct again
type: Fix
id: 2554
time: '2026-07-13T13:32:05.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6285
- author: pootslap
changes:
- message: Starlight forged weapons/armour/ammo are no longer craftable.
type: Remove
id: 2555
time: '2026-07-13T13:46:25.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6250
- author: ArionGekkota
changes:
- message: Added the small arms mining kit to the mining voucher. It contains a
crusher dagger and mining drill!
type: Add
id: 2556
time: '2026-07-13T13:51:12.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6260
- author: jessiscah23
changes:
- message: Due to the growing influence of the Cargo Pilots' Employee Advocacy Group,
cargo telepads are no longer available to be researched.
type: Remove
id: 2557
time: '2026-07-13T14:24:25.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6266
- author: Velitation
changes:
- message: Added 2 new outfits and a mantle to the mime's loadout. The outfits can
also be printed out at a uniform printer.
type: Add
id: 2558
time: '2026-07-13T16:16:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6264
- author: ShepardToTheStars
changes:
- message: Derelict borgs no longer have access to heads' rooms.
type: Fix
id: 2559
time: '2026-07-13T17:38:08.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6284
- author: Coryler
changes:
- message: Character height should be correctly applied for clones and paradox clones.
type: Fix
id: 2560
time: '2026-07-13T19:58:26.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6205
- author: ShepardToTheStars
changes:
- message: Objects animated by glimmer, revenants, or magic cannot be turned into
zombies anymore.
type: Fix
id: 2561
time: '2026-07-13T20:36:52.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6291
- author: ShepardToTheStars
changes:
- message: Xenoborg ID chip slots are no longer compatible with crew ID chips or
IDs.
type: Tweak
- message: Only the Xenoborg Mothership Core can talk over binary. All xenoborgs
can still listen.
type: Tweak
- message: Xenoborgs now have EMP resistant batteries and will only take drain around
40% of battery.
type: Tweak
- message: Xenoborgs will only be disabled for 6 seconds when hit by an EMP, instead
of 60 seconds.
type: Tweak
- message: The Xenoborg mothership core now has a magnet for materials.
type: Tweak
- message: The Xenoborg silicon storage square now has a toggleable magnet.
type: Fix
id: 2562
time: '2026-07-13T21:26:01.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6278
- author: Cepelinas1
changes:
- message: Certain fauna, like space dragons or mice can now see in the dark!
type: Add
- message: Dragons can now smell blood.
type: Add
id: 2563
time: '2026-07-14T01:38:28.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5902
- author: Velitation
changes:
- message: Mime PDAs once again start with the NanoTask, NoteKeeper, and NanoChat
apps.
type: Tweak
id: 2564
time: '2026-07-15T00:43:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6252
- author: ShepardToTheStars
changes:
- message: The airlock access override now breaks accesses on the door. You can
see if accesses on doors have been broken with the Diagnostic HUD.
type: Tweak
- message: Added access configurators to engineer lockers, engineering techfab,
and the EngiVend. Engineers are now allowed to repair access around the station!
type: Add
- message: The AI and engineering borgs can now see if a door's accesses have been
modified.
type: Add
id: 2565
time: '2026-07-15T01:58:05.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6263
- author: MantasDab360
changes:
- message: Wanted Fugitive paper is no longer clustered.
type: Fix
id: 2566
time: '2026-07-15T18:42:52.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6308
- author: AppleSmithWorks
changes:
- message: New nuclear scientist PDA in the Engineer loadout.
type: Add
id: 2567
time: '2026-07-16T20:24:27.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6283
- author: ollyoaner
changes:
- message: Slime people upgrades! (Incl. ports from Impstation). Some slimeperson
characters might need their eye marking(s) fix due to them being eyeless by
default!
type: Add
id: 2568
time: '2026-07-17T03:50:51.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6288
- author: Velitation
changes:
- message: Added 2 new hats, 3 new neck items, 1 new coat and, 1 pair of shoes to
the mime loadout.
type: Add
- message: Mimes can now select which shoes they start with.
type: Tweak
id: 2569
time: '2026-07-17T04:31:23.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6307
- author: ArionGekkota
changes:
- message: 'Hitman: Added the ninja kit, for those who want a melee-oriented fight,
as well as its brand new medium-frequency blade!'
type: Add
- message: 'Hitman: Gave some extra goodies to the sharpshooter and poisoner kit.'
type: Tweak
- message: 'Hitman: Revamped the tracker kit to include way more tools to spy on
the crew.'
type: Tweak
- message: 'Hitman: Reworked the loud kit into the bounty hunter kit, now equipped
with a repeater and more cowboy attire'
type: Tweak
- message: 'Hitman: Merged the disguise and assassin kit into one kit, combining
stealth and the ability to blend in anywhere'
type: Tweak
- message: 'Hitman: Reworked the infiltrator kit into the saboteur kit, a kit more
focused on sabotage and setting up traps'
type: Tweak
- message: 'Hitman: Removed the escapist kit. The new ninja kit was given a scram
implant to compensate.'
type: Remove
id: 2570
time: '2026-07-17T04:40:05.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6270
- author: SumofThreeParts
changes:
- message: Traitors are now less likely to have the escape to Midpoint objective.
type: Tweak
id: 2571
time: '2026-07-19T16:19:30.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6323
- author: GooeyPancake
changes:
- message: Pills now have taste again! Sorry Lexorin-pilled people.
type: Add
id: 2572
time: '2026-07-19T16:38:26.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6299
- author: BriBrooo
changes:
- message: Added new kimono and sandals loadout options for the chef.
type: Add
id: 2573
time: '2026-07-20T00:12:52.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6341
- author: Eternally-Confused
changes:
- message: Cyborgs are once again able to "boop" and "whirr"
type: Add
id: 2574
time: '2026-07-20T00:24:43.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6310
- author: kotobdev
changes:
- message: The Ardent Censer no longer requires fuel for deconversions.
type: Tweak
id: 2575
time: '2026-07-20T17:38:51.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5016
- author: Halo3rat, kotobdev
changes:
- message: The Freighter Crew's Jumpsuit is now available in the AutoDrobe, for
those who value their dental hygiene.
type: Add
id: 2576
time: '2026-07-20T20:06:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6331
- author: Mnemotechnician, kotobdev, ShepardToTheStars
changes:
- message: You can now offer items to other players by pressing F, and then clicking
on them! They can accept by clicking on the alert on the side of their screen.
type: Add
id: 2577
time: '2026-07-20T20:13:58.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5597
- author: ShepardToTheStars
changes:
- message: Glimmer probers can once again turn on and lock into place when glimmer
is over 750.
type: Add
- message: Glimmer prober explosions are 1.5x bigger if glimmer is over 900. You
better build drainers! :)
type: Tweak
- message: The oracle can now give normality crystals when completing her requests.
type: Tweak
id: 2578
time: '2026-07-20T20:29:02.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6292
- author: keekee38
changes:
- message: Added the novice mark, to help show that you're new! It is on intern
roles by default, and optional for everyone
type: Add
- message: Some clothes now have examine text, in particular pride clothes.
type: Tweak
id: 2579
time: '2026-07-20T22:08:57.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6118
- author: Coryler
changes:
- message: Shadekin has arrived in the DeltaV sector.
type: Add
id: 2580
time: '2026-07-20T22:10:50.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5481
- author: sowelipililimute
changes:
- message: The crew monitor now reports global coordinate positions.
type: Tweak
id: 2581
time: '2026-07-20T22:20:12.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6326
- author: keekee38
changes:
- message: Vulpkanins can yip now.
type: Tweak
id: 2582
time: '2026-07-20T22:21:24.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6301
- author: pootslap
changes:
- message: Improvised shotgun shells use the old upstream crafting recipe.
type: Tweak
- message: The improvised shotgun is craftable once again.
type: Fix
id: 2583
time: '2026-07-20T22:22:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6327
- author: kotobdev
changes:
- message: Security cold weather ponchos are gone from loadouts and the SecDrobe.
type: Remove
id: 2584
time: '2026-07-20T22:44:01.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6332
- author: sowelipililimute
changes:
- message: Security now has access to evidence bags, for storing all the illegal
things that can be stored.
type: Add
id: 2585
time: '2026-07-20T23:17:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6280
- author: jessiscah23
changes:
- message: Added organizational capabilities to the cargo bounty computer.
type: Add
id: 2586
time: '2026-07-20T23:23:28.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6306
- author: Proxysseia
changes:
- message: (TEST MERGE) Increased traitor starting telecrystal balance from 20 to
30.
type: Tweak
id: 2587
time: '2026-07-20T23:37:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6275
- author: ArionGekkota
changes:
- message: reintroduced researchable PKA modkits
type: Add
- message: Changed the PKA to its current upstream state
type: Tweak
- message: Reduced the health of some salvage mobs
type: Tweak
id: 2588
time: '2026-07-20T23:46:11.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6258
- author: nlaky
changes:
- message: Fixed incorrect Vulpkanin mask sprites.
type: Fix
id: 2589
time: '2026-07-21T00:05:09.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6201
Order: 1
-16
View File
@@ -1071,20 +1071,4 @@
id: 123
time: '2026-06-12T17:16:00.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5940
- author: FieldCommand
changes:
- message: 'Mothership: Turrets have been constructed on the Xenoborg mothership!'
type: Add
id: 124
time: '2026-07-13T13:16:26.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6244
- author: FieldCommand
changes:
- message: 'Midpoint: Added a pool area to Midpoint.'
type: Add
- message: 'Midpoint: Securety on Midpoint is now blue!'
type: Tweak
id: 125
time: '2026-07-14T00:30:06.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6242
Order: 3
@@ -1,9 +0,0 @@
[game]
hostname = "[EN][MRP] Delta-v (Ψ) | Meridian [EU West]"
soft_max_players = 40
[hub]
tags = "lang:en-US,region:eu_w,rp:med,no_tag_infer"
[debug]
pow3r_disable_parallel = false
File diff suppressed because one or more lines are too long
@@ -16,5 +16,3 @@ delta-chat-emote-name-harpysquish = Squish
delta-chat-emote-name-quack = Quack
delta-chat-emote-name-squawk = Squawk
delta-chat-emote-name-horn = Horn
delta-chat-emote-name-yip = Yip
delta-chat-emote-msg-yip = yips.
@@ -0,0 +1 @@
damage-group-electronic = Electronic
@@ -1,4 +0,0 @@
dv-seen-inserted-item-name-modifier = {$baseName} with { INDEFINITE($contained) } { $contained }
dv-seen-inserted-item-examined =
.full = { CAPITALIZE(SUBJECT($container)) } has [color=paleturquoise]{ INDEFINITE($contained) } { $contained }[/color] in { SUBJECT($container) }.
.empty = { CAPITALIZE(SUBJECT($container)) } has nothing in { SUBJECT($container) }.
@@ -1,5 +1 @@
deltav-ghost-role-information-space-dragon-description = Call in 3 carp rifts and take over this quadrant! You must place a rift every 10 minutes or suffer the consequences!
ghost-role-information-space-dragon-matriarch-description = You are the space dragon matriarch. The crew is food, consume them all.
ghost-role-information-space-dragon-matriarch-name = Space Dragon Matriarch
ghost-role-information-space-dragon-matriarch-rules = Kill people, listen to the curator that spawned you in, kill people, dont die and kill people.
@@ -1,44 +1,45 @@
hitman-sharpshooter-kit-name = Sharpshooter kit
hitman-sharpshooter-kit-description =
A kit for those who prefer killing from afar.
Provides a Hristov with ammo, thermal goggles and binoculars to spot
your target, and a stealth box and cigarettes to ease the nerves.
Provides a Hristov with ammo along with an outfit in a briefcase.
it also provides thermal goggles to find your targets.
hitman-bounty-hunter-kit-name = Bounty Hunter kit
hitman-bounty-hunter-kit-description =
hitman-loud-kit-name = Loud kit
hitman-loud-kit-description =
A kit for those who like a direct method.
Provides a SKL93 and a python loaded with armor-piercing rounds, as well
as an extra speedloader and a cowboy outfit, armor vest included.
Provides a Python with Armor-Piercing rounds and two speedloaders.
Alongside an extra of an armor vest and no-slip shoes.
hitman-assassin-kit-name = Assassin kit
hitman-assassin-kit-description =
A kit for those who want to blend in.
Provides a Cobra with toxin and tranquilizer magazines, plus a set of
chameleon clothing, agent ID, fake mindshield and an identity mask implant.
hitman-ninja-kit-name = Ninja kit
hitman-ninja-kit-description =
A kit for those who want to fight up close.
Provides a medium frequency blade, throwing knives and a scram implant.
Plus no-slip shoes, smoke bombs and a combat medkit.
A kit for the quiet killers.
Provides a Cobra with an extra magazine and armor piercing throwing knives.
alongside night vision goggles and a radio jammer.
hitman-poisoner-kit-name = Poisoner kit
hitman-poisoner-kit-description =
A kit for those who enjoy chemicals.
Provides an advanced jet injector along with bottles of of Pax, Toxin,
Mute Toxin, and Nocturine. A chemical synthesis kit is also provided.
Provides a syringe to use with a bottle of pax, toxin, mute toxin, and Nocturine.
A chemical synthesis kit is also provided.
hitman-saboteur-kit-name = Saboteur kit
hitman-saboteur-kit-description =
hitman-infiltration-kit-name = Infiltration kit
hitman-infiltration-kit-description =
A kit for those who want to get anywhere.
Provides a cryptographic sequencer, airlock access override and a
rapid construction device with extra compressed matter.
Plus a set of tools and a dead man's signaller perfect for laying down traps.
Provides a cryptographic sequencer, syndicate jaws of life and stealth box.
hitman-disguise-kit-name = Disguise kit
hitman-disguise-kit-description =
A kit for those who want to be anyone.
Provides an Agent ID, chameleon clothing.
Plus a fake MindShield and voice mask implanter.
hitman-escapist-kit-name = Escapist kit
hitman-escapist-kit-description =
A kit for those who want to get out of anything.
Provides a DNA, freedom and scram implanter.
hitman-tracker-kit-name = Tracker kit
hitman-tracker-kit-description =
A kit for those who wish to know everything.
Provides a station master encryption key and binary encryption key,
a spy monitor, a camera bug, an AI detector disguised as a multitool,
and a security hud disguised as sunglasses.
Plus a modified station map that can access crew records and universal pinpointer.
Provides a station master encryption key and universal pinpointer.
Plus a spy monitor.
@@ -44,7 +44,6 @@ job-alt-title-plasma-scientist = Plasma Scientist
job-alt-title-senior-engineer = Engineering Mentor
job-alt-title-electrician = Electrician
job-alt-title-mechanic = Mechanic
job-alt-title-nuclear-scientist = Nuclear Scientist
job-alt-title-deck-worker = Deck Worker
job-alt-title-inventory-associate = Inventory Associate
@@ -1,154 +0,0 @@
# Ears
marking-EarsShadekinMotley = Motley Ears
marking-EarsShadekinMotley-shadowkin = Ears
marking-EarsShadekinMotley-motley_secondary = Pattern
marking-EarsShadekinShady = Dark Ears
marking-EarsShadekinShady-shady = Ears
marking-EarsShadekinStriped = Striped Ears
marking-EarsShadowkinStriped-shadowkin = Ears
marking-EarsShadowkinStriped-shadowkin_stripes = Stripes
marking-EarsShadekinPiercingAll = Ears with Piercings
marking-EarsShadekinPiercingAll-shadowkin = Ears
marking-EarsShadekinPiercingAll-piercing_all = Piercings
marking-EarsShadekinPiercingLeft = Ears with Piercing (L)
marking-EarsShadekinPiercingLeft-shadowkin = Ears
marking-EarsShadekinPiercingLeft-piercing_left = Piercing
marking-EarsShadekinPiercingRight = Ears with Piercing (R)
marking-EarsShadekinPiercingRight-shadowkin = Ears
marking-EarsShadekinPiercingRight-piercing_right = Piercing
marking-EarsShadekinRingedAll = Ears with Rings
marking-EarsShadekinRingedAll-shadowkin = Ears
marking-EarsShadekinRingedAll-ringed_all_secondary = Rings
marking-EarsShadekinRingedLeft = Ears with Ring (L)
marking-EarsShadekinRingedLeft-shadowkin = Ears
marking-EarsShadekinRingedLeft-ringed_left_secondary = Ring
marking-EarsShadekinRingedRight = Ears with Ring (R)
marking-EarsShadekinRingedRight-shadowkin = Ears
marking-EarsShadekinRingedRight-ringed_right_secondary = Ring
marking-EarsShadekinGauzedAll = Gauzed Ears
marking-EarsShadekinGauzedAll-shadowkin = Ears
marking-EarsShadekinGauzedAll-gauze_ear_all_default = Gauze
marking-EarsShadekinGauzedLeft = Ear Bandage (L)
marking-EarsShadekinGauzedLeft-shadowkin = Ears
marking-EarsShadekinGauzedLeft-gauze_ear_l_default = Bandage
marking-EarsShadekinGauzedRight = Ear Bandage (R)
marking-EarsShadekinGauzedRight-shadowkin = Ears
marking-EarsShadekinGauzedRight-gauze_ear_r_default = Bandage
marking-EarsShadekinFluffy = Fluffy Ears
marking-EarsShadekinFluffy-fluffy_default = Ears
marking-EarsShadekinFluffyButterfly = Fluffy Ears, Butterfly
marking-EarsShadekinFluffyButterfly-fluffy_default = Ears
marking-EarsShadekinFluffyButterfly-fluffy_butterfly = Pattern
marking-EarsShadekinFluffyCowling = Fluffy Ears, Spotted
marking-EarsShadekinFluffyCowling-fluffy_default = Ears
marking-EarsShadekinFluffyCowling-fluffy_cowling = Pattern
marking-EarsShadekinFluffyCrow = Fluffy Ears, Crow
marking-EarsShadekinFluffyCrow-fluffy_default = Ears
marking-EarsShadekinFluffyCrow-fluffy_crow = Pattern
marking-EarsShadekinFluffyMotley = Fluffy Ears, Bright
marking-EarsShadekinFluffyMotley-fluffy_default = Ears
marking-EarsShadekinFluffyMotley-fluffy_motley = Pattern
marking-EarsShadekinFluffySpidy = Fluffy Ears, Spidy
marking-EarsShadekinFluffySpidy-fluffy_default = Ears
marking-EarsShadekinFluffySpidy-fluffy_spidy = Pattern
marking-EarsShadekinFluffyRingedAll = Fluffy Ears, with Rings
marking-EarsShadekinFluffyRingedAll-fluffy_default = Ears
marking-EarsShadekinFluffyRingedAll-fluffy_ringed_all = Rings
marking-EarsShadekinFluffyRingedLeft = Fluffy Ears, with Ring (L)
marking-EarsShadekinFluffyRingedLeft-fluffy_default = Ears
marking-EarsShadekinFluffyRingedLeft-fluffy_ringed_left = Ring
marking-EarsShadekinFluffyRingedRight = Fluffy Ears, with Ring (R)
marking-EarsShadekinFluffyRingedRight-fluffy_default = Ears
marking-EarsShadekinFluffyRingedRight-fluffy_ringed_right = Ring
marking-EarsShadekinSaggy = Drooping Ears
marking-EarsShadekinSaggy-saggy_default = Ears
marking-EarsShadekinSaggyBrawly = Drooping Ears, Patterned
marking-EarsShadekinSaggyBrawly-saggy_default = Ears
marking-EarsShadekinSaggyBrawly-saggy_brawly = Pattern
marking-EarsShadekinSaggyZebra = Drooping Ears, Striped
marking-EarsShadekinSaggyZebra-saggy_default = Ears
marking-EarsShadekinSaggyZebra-saggy_zebra = Stripes
marking-EarsShadekinSaggyGradient = Drooping Ears, Gradient
marking-EarsShadekinSaggyGradient-saggy_default = Ears
marking-EarsShadekinSaggyGradient-saggy_gradient = Gradient
marking-EarsShadekinSaggyGauzedAll = Drooping Ears, Gauzed
marking-EarsShadekinSaggyGauzedAll-saggy_default = Ears
marking-EarsShadekinSaggyGauzedAll-saggy_gauze_all = Gauze
marking-EarsShadekinSaggyGauzedLeft = Drooping Ears, Ear Bandage (L)
marking-EarsShadekinSaggyGauzedLeft-saggy_default = Ears
marking-EarsShadekinSaggyGauzedLeft-saggy_gauze_l = Bandage
marking-EarsShadekinSaggyGauzedRight = Drooping Ears, Ear Bandage (R)
marking-EarsShadekinSaggyGauzedRight-saggy_default = Ears
marking-EarsShadekinSaggyGauzedRight-saggy_gauze_r = Bandage
marking-EarsShadekinShort = Short Ears
marking-EarsShadekinShort-short_default = Ears
marking-EarsShadekinShortButterfly = Short Ears, Decorated
marking-EarsShadekinShortButterfly-short_default = Ears
marking-EarsShadekinShortButterfly-short_butterfly = Pattern
marking-EarsShadekinShortRingedAll = Short Ears, with Rings
marking-EarsShadekinShortRingedAll-short_default = Ears
marking-EarsShadekinShortRingedAll-short_ringed_all = Rings
marking-EarsShadekinShortRingedLeft = Short Ears, with Ring (L)
marking-EarsShadekinShortRingedLeft-short_default = Ears
marking-EarsShadekinShortRingedLeft-short_ringed_left = Ring
marking-EarsShadekinShortRingedRight = Short Ears, with Ring (R)
marking-EarsShadekinShortRingedRight-short_default = Ears
marking-EarsShadekinShortRingedRight-short_ringed_right = Ring
marking-EarsShadekinBull = Straight Ears
marking-EarsShadekinBull-bull_default = Ears
marking-EarsShadekinBullSmooth = Straight Ears, Outlined
marking-EarsShadekinBullSmooth-bull_default = Ears
marking-EarsShadekinBullSmooth-bull_smooth = Inner ears
marking-EarsShadekinAqua = Aqua Ears
marking-EarsShadekinAqua-aqua_default = Ears
marking-EarsShadekinAquaIncolor = Aqua Ears, Colored
marking-EarsShadekinAquaIncolor-aqua_default = Ears
marking-EarsShadekinAquaIncolor-aqua_incolor = Inner ears
# Tails
marking-TailShadekin = Long Tail
marking-TailShadekinBig = Big Tail
marking-TailShadekinShorter = Short Tail
marking-TailShadekinShorter-shadekin_shorter_over = Tail
marking-TailShadekinShorterBrush = Short Tail, Furry
marking-TailShadekinShorterBrush-shadekin_shorter_over = Tail
marking-TailShadekinShorterBrush-shorter_brush_over = Tail tip
marking-TailShadekinMedium = Medium Tail
marking-TailShadekinMedium-shadekin_medium_front = Tail
marking-TailShadekinMediumTwoColored = Medium Tail, Two-Toned
marking-TailShadekinMediumTwoColored-shadekin_medium_front = Tail
marking-TailShadekinMediumTwoColored-medium_twocolored_over = Tail underside
# Overlays
marking-BodyShadekinArrow = Arrow Marking
marking-BodyShadekinArrow-body_arrow = Marking
marking-BodyShadekinBlackHole = Black Hole Marking
marking-BodyShadekinBlackHole-body_blackhole = Marking
marking-BodyShadekinBrace = Bracelet Marking
marking-BodyShadekinBrace-body_brace = Marking
marking-BodyShadekinBrawly = Combat Marking
marking-BodyShadekinBrawly-body_brawly = Marking
marking-BodyShadekinHeart = Heart Marking
marking-BodyShadekinHeart-body_heart = Marking
marking-BodyShadekinInk = Ink Marking
marking-BodyShadekinInk-body_ink = Marking
marking-BodyShadekinInk2 = Ink Marking 2
marking-BodyShadekinInk2-body_ink2 = Marking
marking-BodyShadekinInk3 = Ink Marking 3
marking-BodyShadekinInk3-body_ink3 = Marking
marking-BodyShadekinInk4 = Ink Marking 4
marking-BodyShadekinInk4-body_ink4 = Marking
marking-BodyShadekinInk5 = Ink Marking 5
marking-BodyShadekinInk5-body_ink5 = Marking
marking-BodyShadekinInk6 = Spiritual Ink Marking
marking-BodyShadekinInk6-body_ink6 = Marking
marking-BodyShadekinInkAnim = Spiral Ink Marking
marking-BodyShadekinInkAnim-body_ink_anim = Marking
marking-BodyShadekinLines = Lines Marking
marking-BodyShadekinLines-body_lines = Marking
marking-BodyShadekinNeck = Neck Marking
marking-BodyShadekinNeck-body_neck = Marking
marking-BodyShadekinShield = Protective Marking
marking-BodyShadekinShield-body_shield = Marking
marking-BodyShadekinVacuum = Open Marking
marking-BodyShadekinVacuum-body_vacuum = Marking

Some files were not shown because too many files have changed in this diff Show More