Skip to content

Commit

Permalink
Merge branch 'master' into 2024-05-Dungeon-Spawner-UPD
Browse files Browse the repository at this point in the history
  • Loading branch information
ErhardSteinhauer authored Jun 2, 2024
2 parents 9149156 + 76aaeed commit 3572453
Show file tree
Hide file tree
Showing 354 changed files with 4,745 additions and 1,596 deletions.
7 changes: 7 additions & 0 deletions Content.Server/Explosion/Components/ExplosiveComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ public sealed partial class ExplosiveComponent : Component
[DataField("deleteAfterExplosion")]
public bool? DeleteAfterExplosion;

/// <summary>
/// Whether to not set <see cref="Exploded"/> to true, allowing it to explode multiple times.
/// This should never be used if it is damageable.
/// </summary>
[DataField]
public bool Repeatable;

/// <summary>
/// Avoid somehow double-triggering this explosion (e.g. by damaging this entity from its own explosion.
/// </summary>
Expand Down
25 changes: 25 additions & 0 deletions Content.Server/Explosion/Components/RepeatingTriggerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Content.Server.Explosion.EntitySystems;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Server.Explosion.Components;

/// <summary>
/// Constantly triggers after being added to an entity.
/// </summary>
[RegisterComponent, Access(typeof(TriggerSystem))]
[AutoGenerateComponentPause]
public sealed partial class RepeatingTriggerComponent : Component
{
/// <summary>
/// How long to wait between triggers.
/// The first trigger starts this long after the component is added.
/// </summary>
[DataField]
public TimeSpan Delay = TimeSpan.FromSeconds(1);

/// <summary>
/// When the next trigger will be.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan NextTrigger;
}
2 changes: 1 addition & 1 deletion Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public void TriggerExplosive(EntityUid uid, ExplosiveComponent? explosive = null
if (explosive.Exploded)
return;

explosive.Exploded = true;
explosive.Exploded = !explosive.Repeatable;

// Override the explosion intensity if optional arguments were provided.
if (radius != null)
Expand Down
21 changes: 21 additions & 0 deletions Content.Server/Explosion/EntitySystems/TriggerSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public override void Initialize()
SubscribeLocalEvent<TriggerOnStepTriggerComponent, StepTriggeredOffEvent>(OnStepTriggered);
SubscribeLocalEvent<TriggerOnSlipComponent, SlipEvent>(OnSlipTriggered);
SubscribeLocalEvent<TriggerWhenEmptyComponent, OnEmptyGunShotEvent>(OnEmptyTriggered);
SubscribeLocalEvent<RepeatingTriggerComponent, MapInitEvent>(OnRepeatInit);

SubscribeLocalEvent<SpawnOnTriggerComponent, TriggerEvent>(OnSpawnTrigger);
SubscribeLocalEvent<DeleteOnTriggerComponent, TriggerEvent>(HandleDeleteTrigger);
Expand Down Expand Up @@ -278,6 +279,11 @@ private void OnEmptyTriggered(EntityUid uid, TriggerWhenEmptyComponent component
Trigger(uid, args.EmptyGun);
}

private void OnRepeatInit(Entity<RepeatingTriggerComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextTrigger = _timing.CurTime + ent.Comp.Delay;
}

public bool Trigger(EntityUid trigger, EntityUid? user = null)
{
var triggerEvent = new TriggerEvent(trigger, user);
Expand Down Expand Up @@ -360,6 +366,7 @@ public override void Update(float frameTime)
UpdateProximity();
UpdateTimer(frameTime);
UpdateTimedCollide(frameTime);
UpdateRepeat();
}

private void UpdateTimer(float frameTime)
Expand Down Expand Up @@ -394,5 +401,19 @@ private void UpdateTimer(float frameTime)
_appearance.SetData(uid, TriggerVisuals.VisualState, TriggerVisualState.Unprimed, appearance);
}
}

private void UpdateRepeat()
{
var now = _timing.CurTime;
var query = EntityQueryEnumerator<RepeatingTriggerComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (comp.NextTrigger > now)
continue;

comp.NextTrigger = now + comp.Delay;
Trigger(uid);
}
}
}
}
1 change: 0 additions & 1 deletion Content.Shared/Access/Components/IdCardConsoleComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public WriteToTargetIdMessage(string fullName, string jobTitle, List<ProtoId<Acc
"Maintenance",
"Medical",
"Mercenary", // Frontier
"Pilot", // Frontier
//"Quartermaster",
//"Research",
//"ResearchDirector",
Expand Down
2 changes: 1 addition & 1 deletion Content.Shared/Access/Systems/AccessReaderSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public bool IsAllowed(
return IsAllowedInternal(access, stationKeys, reader);

if (!_containerSystem.TryGetContainer(target, reader.ContainerAccessProvider, out var container))
return false;
return Paused(target); // when mapping, containers with electronics arent spawned

foreach (var entity in container.ContainedEntities)
{
Expand Down
4 changes: 2 additions & 2 deletions Content.Shared/Blocking/BlockingSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Content.Shared.Actions;
using Content.Shared.Damage;
using Content.Shared.Examine;
Expand Down Expand Up @@ -209,7 +209,7 @@ public bool StartBlocking(EntityUid item, BlockingComponent component, EntityUid
_fixtureSystem.TryCreateFixture(user,
component.Shape,
BlockingComponent.BlockFixtureID,
hard: true,
hard: false, // Frontier - True to false, mobs AI abuse.
collisionLayer: (int) CollisionGroup.WallLayer,
body: physicsComponent);
}
Expand Down
10 changes: 10 additions & 0 deletions Content.Shared/Hands/Components/HandHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using Content.Shared.Hands.EntitySystems;

namespace Content.Shared.Hands.Components;

Expand All @@ -20,6 +21,15 @@ public static class HandHelpers
/// </summary>
public static int CountFreeHands(this HandsComponent component) => component.Hands.Values.Count(hand => hand.IsEmpty);

/// <summary>
/// Get the number of hands that are not currently holding anything. This is a LinQ method, not a property, so
/// cache it instead of accessing this multiple times.
/// </summary>
public static int CountFreeableHands(this Entity<HandsComponent> component, SharedHandsSystem system)
{
return system.CountFreeableHands(component);
}

/// <summary>
/// Get a list of hands that are currently holding nothing. This is a LinQ method, not a property, so cache
/// it instead of accessing this multiple times.
Expand Down
13 changes: 12 additions & 1 deletion Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Item;
using Content.Shared.Storage.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Input.Binding;
Expand Down Expand Up @@ -299,4 +298,16 @@ public bool TryGetHand(EntityUid handsUid, string handId, [NotNullWhen(true)] ou

return hands.Hands.TryGetValue(handId, out hand);
}

public int CountFreeableHands(Entity<HandsComponent> hands)
{
var freeable = 0;
foreach (var hand in hands.Comp.Hands.Values)
{
if (hand.IsEmpty || CanDropHeld(hands, hand))
freeable++;
}

return freeable;
}
}
48 changes: 42 additions & 6 deletions Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
using Content.Shared.Popups;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
Expand All @@ -29,6 +30,7 @@ public abstract class SharedVirtualItemSystem : EntitySystem
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;

[ValidatePrototypeId<EntityPrototype>]
private const string VirtualItem = "VirtualItem";
Expand Down Expand Up @@ -71,23 +73,53 @@ private void OnBeforeRangedInteract(Entity<VirtualItemComponent> ent, ref Before
}

#region Hands

/// <summary>
/// Spawns a virtual item in a empty hand
/// </summary>
/// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
/// <param name="user">The entity that we want to insert the virtual entity</param>
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user)
/// <param name="dropOthers">Whether or not to try and drop other items to make space</param>
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, bool dropOthers = false)
{
return TrySpawnVirtualItemInHand(blockingEnt, user, out _);
return TrySpawnVirtualItemInHand(blockingEnt, user, out _, dropOthers);
}

/// <inheritdoc cref="TrySpawnVirtualItemInHand(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid)"/>
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
/// <inheritdoc cref="TrySpawnVirtualItemInHand(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid,bool)"/>
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem, bool dropOthers = false)
{
if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem) || !_handsSystem.TryGetEmptyHand(user, out var hand))
virtualItem = null;
if (!_handsSystem.TryGetEmptyHand(user, out var empty))
{
if (!dropOthers)
return false;

foreach (var hand in _handsSystem.EnumerateHands(user))
{
if (hand.HeldEntity is not { } held)
continue;

if (held == blockingEnt || HasComp<VirtualItemComponent>(held))
continue;

if (!_handsSystem.TryDrop(user, hand))
continue;

if (!TerminatingOrDeleted(held))
_popup.PopupClient(Loc.GetString("virtual-item-dropped-other", ("dropped", held)), user, user);

empty = hand;
break;
}
}

if (empty == null)
return false;

if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem))
return false;

_handsSystem.DoPickup(user, hand, virtualItem.Value);
_handsSystem.DoPickup(user, empty, virtualItem.Value);
return true;
}

Expand Down Expand Up @@ -120,6 +152,7 @@ public void DeleteInHandsMatching(EntityUid user, EntityUid matching)
/// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
/// <param name="user">The entity that we want to insert the virtual entity</param>
/// <param name="slot">The slot to which we will insert the virtual entity (could be the "shoes" slot, for example)</param>
/// <param name="force">Whether or not to force an equip</param>
public bool TrySpawnVirtualItemInInventory(EntityUid blockingEnt, EntityUid user, string slot, bool force = false)
{
return TrySpawnVirtualItemInInventory(blockingEnt, user, slot, force, out _);
Expand All @@ -140,6 +173,8 @@ public bool TrySpawnVirtualItemInInventory(EntityUid blockingEnt, EntityUid user
/// that's done check if the found virtual entity is a copy of our matching entity,
/// if it is, delete it
/// </summary>
/// <param name="user">The entity that we want to delete the virtual entity from</param>
/// <param name="matching">The entity that made the virtual entity</param>
/// <param name="slotName">Set this param if you have the name of the slot, it avoids unnecessary queries</param>
public void DeleteInSlotMatching(EntityUid user, EntityUid matching, string? slotName = null)
{
Expand Down Expand Up @@ -178,6 +213,7 @@ public void DeleteInSlotMatching(EntityUid user, EntityUid matching, string? slo
/// </summary>
/// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
/// <param name="user">The entity that we want to insert the virtual entity</param>
/// <param name="virtualItem">The virtual item, if spawned</param>
public bool TrySpawnVirtualItem(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
{
if (_netManager.IsClient)
Expand Down
8 changes: 8 additions & 0 deletions Content.Shared/Preferences/Loadouts/RoleLoadout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,20 @@ public void EnsureValid(ICommonSession session, IDependencyCollection collection
{
var loadout = loadouts[i];

// Old prototype or otherwise invalid.
if (!protoManager.TryIndex(loadout.Prototype, out var loadoutProto))
{
loadouts.RemoveAt(i);
continue;
}

// Malicious client maybe, check the group even has it.
if (!groupProto.Loadouts.Contains(loadout.Prototype))
{
loadouts.RemoveAt(i);
continue;
}

// Validate the loadout can be applied (e.g. points).
if (!IsValid(session, loadout.Prototype, collection, out _))
{
Expand Down
37 changes: 37 additions & 0 deletions Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Content.Shared.Actions;
using Content.Shared.Weapons.Ranged.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared.Weapons.Ranged.Components;

/// <summary>
/// Lets you shoot a gun using an action.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(ActionGunSystem))]
public sealed partial class ActionGunComponent : Component
{
/// <summary>
/// Action to create, must use <see cref="ActionGunShootEvent"/>.
/// </summary>
[DataField(required: true)]
public EntProtoId Action = string.Empty;

[DataField]
public EntityUid? ActionEntity;

/// <summary>
/// Prototype of gun entity to spawn.
/// Deleted when this component is removed.
/// </summary>
[DataField(required: true)]
public EntProtoId GunProto = string.Empty;

[DataField]
public EntityUid? Gun;
}

/// <summary>
/// Action event for <see cref="ActionGunComponent"/> to shoot at a position.
/// </summary>
public sealed partial class ActionGunShootEvent : WorldTargetActionEvent;
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ namespace Content.Shared.Weapons.Ranged.Components;
/// <summary>
/// Indicates that this gun requires wielding to be useable.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem))]
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(WieldableSystem))]
public sealed partial class GunRequiresWieldComponent : Component
{
[DataField, AutoNetworkedField]
public TimeSpan LastPopup;

[DataField, AutoNetworkedField]
public TimeSpan PopupCooldown = TimeSpan.FromSeconds(1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ public sealed partial class GunWieldBonusComponent : Component
/// </summary>
[DataField, AutoNetworkedField]
public Angle AngleIncrease = Angle.FromDegrees(0);

[DataField]
public LocId? WieldBonusExamineMessage = "gunwieldbonus-component-examine";
}
4 changes: 3 additions & 1 deletion Content.Shared/Weapons/Ranged/Events/ShotAttemptedEvent.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Content.Shared.Weapons.Ranged.Components;

namespace Content.Shared.Weapons.Ranged.Events;

/// <summary>
Expand All @@ -15,7 +17,7 @@ public record struct ShotAttemptedEvent
/// <summary>
/// The gun being shot.
/// </summary>
public EntityUid Used;
public Entity<GunComponent> Used;

public bool Cancelled { get; private set; }

Expand Down
Loading

0 comments on commit 3572453

Please sign in to comment.