Stable merge (#37050)

This commit is contained in:
Myra
2025-04-29 21:54:43 +01:00
committed by GitHub
16 changed files with 159 additions and 53 deletions

View File

@@ -1,3 +1,4 @@
using System.Linq;
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Robust.Client.AutoGenerated;
@@ -29,48 +30,47 @@ namespace Content.Client.PDA.Ringer
{
var input = RingerNoteInputs[i];
var index = i;
var foo = () => // Prevents unauthorized characters from being entered into the LineEdit
{
input.Text = input.Text.ToUpper();
if (!IsNote(input.Text))
{
input.Text = PreviousNoteInputs[index];
}
else
PreviousNoteInputs[index] = input.Text;
input.RemoveStyleClass("Caution");
};
input.OnFocusExit += _ => foo();
input.OnTextEntered += _ =>
{
foo();
input.CursorPosition = input.Text.Length; // Resets caret position to the end of the typed input
};
input.OnTextChanged += args =>
{
// Convert to uppercase
var upperText = args.Text.ToUpper();
if (input.Text.Length <= 0)
return;
// Filter to only valid notes
var newText = upperText;
if (!IsNote(newText))
input.Text = args.Text.ToUpper();
var isValid = IsNote(input.Text);
if (!isValid)
{
newText = PreviousNoteInputs[index];
input.Text = PreviousNoteInputs[index];
input.AddStyleClass("Caution");
}
else
{
PreviousNoteInputs[index] = newText;
PreviousNoteInputs[index] = input.Text;
input.RemoveStyleClass("Caution");
}
// Only update if there's a change
if (newText != input.Text)
input.Text = newText;
input.CursorPosition = input.Text.Length;
};
input.OnFocusExit += _ =>
{
if (!IsNote(input.Text))
{
input.Text = PreviousNoteInputs[index];
input.RemoveStyleClass("Caution");
}
};
input.OnTextEntered += _ =>
{
if (!IsNote(input.Text))
{
input.Text = PreviousNoteInputs[index];
input.RemoveStyleClass("Caution");
}
input.CursorPosition = input.Text.Length;
};
}
}
@@ -86,6 +86,9 @@ namespace Content.Client.PDA.Ringer
/// </summary>
public static bool IsNote(string input)
{
if (input.Any(char.IsDigit))
return false;
input = input.Replace("#", "sharp");
return Enum.TryParse(input, true, out Note _);

View File

@@ -1,6 +1,5 @@
using Content.Shared.Interaction;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Server.Actions;
@@ -20,8 +19,10 @@ namespace Content.Server.Actions;
[RegisterComponent]
public sealed partial class ActionOnInteractComponent : Component
{
[DataField(required:true)]
[DataField(required: true)]
public List<EntProtoId>? Actions;
[DataField] public List<EntityUid>? ActionEntities;
[DataField] public bool RequiresCharge;
}

View File

@@ -1,5 +1,7 @@
using System.Linq;
using Content.Shared.Actions;
using Content.Shared.Charges.Components;
using Content.Shared.Charges.Systems;
using Content.Shared.Interaction;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -15,6 +17,7 @@ public sealed class ActionOnInteractSystem : EntitySystem
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly ActionContainerSystem _actionContainer = default!;
[Dependency] private readonly SharedChargesSystem _charges = default!;
public override void Initialize()
{
@@ -54,6 +57,9 @@ public sealed class ActionOnInteractSystem : EntitySystem
if (options.Count == 0)
return;
if (!TryUseCharge((uid, component)))
return;
var (actId, act) = _random.Pick(options);
_actions.PerformAction(args.User, null, actId, act, act.Event, _timing.CurTime, false);
args.Handled = true;
@@ -85,6 +91,9 @@ public sealed class ActionOnInteractSystem : EntitySystem
if (entOptions.Count > 0)
{
if (!TryUseCharge((uid, component)))
return;
var (entActId, entAct) = _random.Pick(entOptions);
if (entAct.Event != null)
{
@@ -108,6 +117,9 @@ public sealed class ActionOnInteractSystem : EntitySystem
if (entWorldOptions.Count > 0)
{
if (!TryUseCharge((uid, component)))
return;
var (entActId, entAct) = _random.Pick(entWorldOptions);
if (entAct.Event != null)
{
@@ -132,6 +144,9 @@ public sealed class ActionOnInteractSystem : EntitySystem
if (options.Count == 0)
return;
if (!TryUseCharge((uid, component)))
return;
var (actId, act) = _random.Pick(options);
if (act.Event != null)
{
@@ -163,4 +178,17 @@ public sealed class ActionOnInteractSystem : EntitySystem
return valid;
}
private bool TryUseCharge(Entity<ActionOnInteractComponent> ent)
{
if (!ent.Comp.RequiresCharge)
return true;
Entity<LimitedChargesComponent?> charges = ent.Owner;
if (_charges.IsEmpty(charges))
return false;
_charges.TryUseCharge(charges);
return true;
}
}

View File

@@ -0,0 +1,30 @@
using Content.Server.Fluids.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Shared.Map;
namespace Content.Server.Chemistry.TileReactions
{
[UsedImplicitly]
[DataDefinition]
public sealed partial class SpillIfPuddlePresentTileReaction : ITileReaction
{
public FixedPoint2 TileReact(TileRef tile,
ReagentPrototype reagent,
FixedPoint2 reactVolume,
IEntityManager entityManager,
List<ReagentData>? data)
{
var spillSystem = entityManager.System<PuddleSystem>();
if (!spillSystem.TryGetPuddle(tile, out _))
return FixedPoint2.Zero;
return spillSystem.TrySpillAt(tile, new Solution(reagent.ID, reactVolume, data), out _, sound: false, tileReact: false)
? reactVolume
: FixedPoint2.Zero;
}
}
}

View File

@@ -0,0 +1,28 @@
using Content.Server.Fluids.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Shared.Map;
namespace Content.Server.Chemistry.TileReactions
{
[UsedImplicitly]
[DataDefinition]
public sealed partial class SpillTileReaction : ITileReaction
{
public FixedPoint2 TileReact(TileRef tile,
ReagentPrototype reagent,
FixedPoint2 reactVolume,
IEntityManager entityManager,
List<ReagentData>? data)
{
var spillSystem = entityManager.System<PuddleSystem>();
return spillSystem.TrySpillAt(tile, new Solution(reagent.ID, reactVolume, data), out _, sound: false, tileReact: false)
? reactVolume
: FixedPoint2.Zero;
}
}
}

View File

@@ -232,6 +232,9 @@ public sealed class NPCUtilitySystem : EntitySystem
{
if (_container.TryGetContainingContainer(targetUid, out var container))
{
if (container.Owner == owner)
return 0f;
if (TryComp<EntityStorageComponent>(container.Owner, out var storageComponent))
{
if (storageComponent is { Open: false } && _weldable.IsWelded(container.Owner))

View File

@@ -55,7 +55,6 @@ public sealed class RingerSystem : SharedRingerSystem
/// </summary>
private void OnGenerateUplinkCode(Entity<RingerUplinkComponent> ent, ref GenerateUplinkCodeEvent ev)
{
// Generate a new uplink code
var code = GenerateRingtone();
// Set the code on the component
@@ -74,6 +73,10 @@ public sealed class RingerSystem : SharedRingerSystem
if (!HasComp<StoreComponent>(uid))
return false;
// Wasn't generated yet
if (uplink.Code is null)
return false;
// On the server, we always check if the code matches
if (!uplink.Code.SequenceEqual(ringtone))
return false;

View File

@@ -40,7 +40,7 @@ public sealed class AnimateSpellSystem : EntitySystem
_container.AttachParentToContainerOrGrid((ent, xform)); // Items animated inside inventory now exit, they can't be picked up and so can't escape otherwise
var ev = new AnimateSpellEvent();
RaiseLocalEvent(ref ev);
RaiseLocalEvent(ent, ref ev);
}
}

View File

@@ -14,7 +14,7 @@ public sealed partial class RingerUplinkComponent : Component
/// Set via GenerateUplinkCodeEvent.
/// </summary>
[DataField]
public Note[] Code = new Note[SharedRingerSystem.RingtoneLength];
public Note[]? Code;
/// <summary>
/// Whether to show the toggle uplink button in PDA settings.

View File

@@ -45,8 +45,8 @@ public abstract class SharedRingerSystem : EntitySystem
/// <inheritdoc/>
public override void Update(float frameTime)
{
var ringerQuery = EntityQueryEnumerator<RingerComponent>();
while (ringerQuery.MoveNext(out var uid, out var ringer))
var ringerQuery = EntityQueryEnumerator<RingerComponent, TransformComponent>();
while (ringerQuery.MoveNext(out var uid, out var ringer, out var xform))
{
if (!ringer.Active || !ringer.NextNoteTime.HasValue)
continue;
@@ -63,10 +63,9 @@ public abstract class SharedRingerSystem : EntitySystem
// and play it separately with PlayLocal, so that it's actually predicted
if (_net.IsServer)
{
var ringerXform = Transform(uid);
_audio.PlayEntity(
GetSound(ringer.Ringtone[ringer.NoteCount]),
Filter.Empty().AddInRange(_xform.GetMapCoordinates(uid, ringerXform), ringer.Range),
Filter.Empty().AddInRange(_xform.GetMapCoordinates(uid, xform), ringer.Range),
uid,
true,
AudioParams.Default.WithMaxDistance(ringer.Range).WithVolume(ringer.Volume)
@@ -257,14 +256,6 @@ public abstract class SharedRingerSystem : EntitySystem
return true;
}
/// <summary>
/// Helper method to determine if the mind is an antagonist.
/// </summary>
protected bool IsAntagonist(EntityUid? user)
{
return user != null && _mind.TryGetMind(user.Value, out var mindId, out _) && _role.MindIsAntagonist(mindId);
}
/// <summary>
/// Gets the sound path for a specific note.
/// </summary>

View File

@@ -3,14 +3,12 @@
name: Animate
description: Bring an inanimate object to life!
components:
- type: LimitedCharges
maxCharges: 5
- type: EntityTargetAction
useDelay: 0
itemIconStyle: BigAction
whitelist:
components:
- Animateable # Currently on: SeatBase, TableBase, ClosetBase, BaseMachine, ConstructibleMachine, BaseComputer, BaseItem, CrateGeneric, StorageTank, GasCanister, BaseTarget
- Animateable # Currently on: SeatBase, TableBase, ClosetBase, BaseMachine, ConstructibleMachine, BaseComputer, BaseItem, CrateGeneric, StorageTank, GasCanister
blacklist:
components:
- MindContainer
@@ -19,7 +17,7 @@
- AnomalyGenerator
- TegGenerator
- TegCirculator
- Artifact
- XenoArtifact
canTargetSelf: false
interactOnMiss: false
sound: !type:SoundPathSpecifier
@@ -70,9 +68,11 @@
collection: MetalBreak
- type: Hands
- type: CanEscapeInventory
- type: MobCollision
toRemove:
- RequireProjectileTarget
- BlockMovement
- Item
- MeleeRequiresWield
speech: action-speech-spell-animate
doSpeech: false

View File

@@ -7,6 +7,10 @@
name: RGB staff
description: Helps fix the underabundance of RGB gear on the station.
components:
- type: LimitedCharges
maxCharges: 25
- type: AutoRecharge
rechargeDuration: 30
- type: Sprite
sprite: Objects/Weapons/Guns/Basic/staves.rsi
layers:
@@ -14,6 +18,7 @@
- state: nothing-unshaded
shader: unshaded
- type: ActionOnInteract
requiresCharge: true
actions:
- ActionRgbLight
- type: Item
@@ -38,11 +43,16 @@
name: staff of animation
description: Brings inanimate objects to life!
components:
- type: LimitedCharges
maxCharges: 5
- type: AutoRecharge
rechargeDuration: 30
- type: Sprite
sprite: Objects/Weapons/Guns/Basic/staves.rsi
layers:
- state: animation
- type: ActionOnInteract
requiresCharge: true
actions:
- ActionAnimateSpell
- type: Item
@@ -59,8 +69,6 @@
- type: entity
id: ActionRgbLight
components:
- type: LimitedCharges
maxCharges: 25
- type: EntityTargetAction
whitelist: { components: [ PointLight ] }
sound: /Audio/Magic/blink.ogg

View File

@@ -19,6 +19,7 @@
amount: 1
tileReactions:
- !type:ExtinguishTileReaction { }
- !type:SpillIfPuddlePresentTileReaction { }
- type: reagent
id: BaseSoda

View File

@@ -175,6 +175,8 @@
recognizable: true
physicalDesc: reagent-physical-desc-sticky
viscosity: 0.55 #Start using syrup to attach your remote recievers to your microwaves!
tileReactions:
- !type:SpillTileReaction
metabolisms:
Food:
# 12 diona blood for 1 unit of syrup, this stuff better be worthwhile.

View File

@@ -66,6 +66,8 @@
recognizable: true
physicalDesc: reagent-physical-desc-viscous
viscosity: 0.25
tileReactions:
- !type:SpillTileReaction
metabolisms:
Food:
# Delicious!
@@ -87,6 +89,8 @@
recognizable: true
physicalDesc: reagent-physical-desc-sticky
viscosity: 0.10
tileReactions:
- !type:SpillTileReaction
metabolisms:
Food:
# Sweet!

View File

@@ -77,6 +77,8 @@
recognizable: true
boilingPoint: 290.0 # Glycerin
meltingPoint: 18.2
tileReactions:
- !type:SpillTileReaction
friction: 0.0
- type: reagent
@@ -88,6 +90,8 @@
color: "#ffffff"
boilingPoint: 250.0
meltingPoint: 380.0
tileReactions:
- !type:SpillTileReaction
viscosity: 0.5
reactiveEffects:
Acidic: