Stable merge (#37050)
This commit is contained in:
@@ -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 _);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -24,4 +23,6 @@ public sealed partial class ActionOnInteractComponent : Component
|
||||
public List<EntProtoId>? Actions;
|
||||
|
||||
[DataField] public List<EntityUid>? ActionEntities;
|
||||
|
||||
[DataField] public bool RequiresCharge;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Content.Server/Chemistry/TileReactions/SpillTileReaction.cs
Normal file
28
Content.Server/Chemistry/TileReactions/SpillTileReaction.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
amount: 1
|
||||
tileReactions:
|
||||
- !type:ExtinguishTileReaction { }
|
||||
- !type:SpillIfPuddlePresentTileReaction { }
|
||||
|
||||
- type: reagent
|
||||
id: BaseSoda
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user