Priority Deliveries (#36968)
This commit is contained in:
19
Content.Shared/ComponentTable/ComponentTableComponent.cs
Normal file
19
Content.Shared/ComponentTable/ComponentTableComponent.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Content.Shared.EntityTable.EntitySelectors;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.ComponentTable;
|
||||
|
||||
/// <summary>
|
||||
/// Applies components from entities selected from the table on init.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(SharedComponentTableSystem))]
|
||||
public sealed partial class ComponentTableComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The table from which to grab entities.
|
||||
/// ALL components of the grabbed entities will be added to the holder of this component.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public EntityTableSelector Table = default!;
|
||||
}
|
||||
33
Content.Shared/ComponentTable/SharedComponentTableSystem.cs
Normal file
33
Content.Shared/ComponentTable/SharedComponentTableSystem.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Content.Shared.EntityTable;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.ComponentTable;
|
||||
|
||||
/// <summary>
|
||||
/// Applies an entity prototype to an entity on map init. Taken from entities inside an EntityTableSelector.
|
||||
/// </summary>
|
||||
public sealed class SharedComponentTableSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly EntityTableSystem _entTable = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ComponentTableComponent, MapInitEvent>(OnTableInit);
|
||||
}
|
||||
|
||||
private void OnTableInit(Entity<ComponentTableComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
var spawns = _entTable.GetSpawns(ent.Comp.Table);
|
||||
|
||||
foreach (var entity in spawns)
|
||||
{
|
||||
if (_proto.TryIndex(entity, out var entProto))
|
||||
{
|
||||
EntityManager.AddComponents(ent, entProto.Components);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.NameModifier.EntitySystems;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Delivery;
|
||||
|
||||
@@ -8,6 +13,9 @@ namespace Content.Shared.Delivery;
|
||||
public sealed partial class DeliveryModifierSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
|
||||
[Dependency] private readonly SharedDeliverySystem _delivery = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -15,8 +23,13 @@ public sealed partial class DeliveryModifierSystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<DeliveryRandomMultiplierComponent, MapInitEvent>(OnRandomMultiplierMapInit);
|
||||
SubscribeLocalEvent<DeliveryRandomMultiplierComponent, GetDeliveryMultiplierEvent>(OnGetRandomMultiplier);
|
||||
|
||||
SubscribeLocalEvent<DeliveryPriorityComponent, MapInitEvent>(OnPriorityMapInit);
|
||||
SubscribeLocalEvent<DeliveryPriorityComponent, ExaminedEvent>(OnPriorityExamine);
|
||||
SubscribeLocalEvent<DeliveryPriorityComponent, GetDeliveryMultiplierEvent>(OnGetPriorityMultiplier);
|
||||
}
|
||||
|
||||
#region Random
|
||||
private void OnRandomMultiplierMapInit(Entity<DeliveryRandomMultiplierComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ent.Comp.CurrentMultiplierOffset = _random.NextFloat(ent.Comp.MinMultiplierOffset, ent.Comp.MaxMultiplierOffset);
|
||||
@@ -27,4 +40,70 @@ public sealed partial class DeliveryModifierSystem : EntitySystem
|
||||
{
|
||||
args.AdditiveMultiplier += ent.Comp.CurrentMultiplierOffset;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Priority
|
||||
private void OnPriorityMapInit(Entity<DeliveryPriorityComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ent.Comp.DeliverUntilTime = _timing.CurTime + ent.Comp.DeliveryTime;
|
||||
_delivery.UpdatePriorityVisuals(ent);
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnPriorityExamine(Entity<DeliveryPriorityComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
var trueName = _nameModifier.GetBaseName(ent.Owner);
|
||||
var timeLeft = ent.Comp.DeliverUntilTime - _timing.CurTime;
|
||||
|
||||
if (_timing.CurTime < ent.Comp.DeliverUntilTime)
|
||||
args.PushMarkup(Loc.GetString("delivery-priority-examine", ("type", trueName), ("time", timeLeft.ToString("mm\\:ss"))));
|
||||
else
|
||||
args.PushMarkup(Loc.GetString("delivery-priority-expired-examine", ("type", trueName)));
|
||||
}
|
||||
|
||||
private void OnGetPriorityMultiplier(Entity<DeliveryPriorityComponent> ent, ref GetDeliveryMultiplierEvent args)
|
||||
{
|
||||
if (_timing.CurTime < ent.Comp.DeliverUntilTime)
|
||||
args.AdditiveMultiplier += ent.Comp.InTimeMultiplierOffset;
|
||||
else
|
||||
args.AdditiveMultiplier += ent.Comp.ExpiredMultiplierOffset;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Loops
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
UpdatePriorty(frameTime);
|
||||
}
|
||||
|
||||
private void UpdatePriorty(float frameTime)
|
||||
{
|
||||
var priorityQuery = EntityQueryEnumerator<DeliveryPriorityComponent>();
|
||||
var curTime = _timing.CurTime;
|
||||
|
||||
while (priorityQuery.MoveNext(out var uid, out var priorityData))
|
||||
{
|
||||
if (priorityData.Expired)
|
||||
continue;
|
||||
|
||||
if (priorityData.DeliverUntilTime < curTime)
|
||||
{
|
||||
priorityData.Expired = true;
|
||||
_delivery.UpdatePriorityVisuals((uid, priorityData));
|
||||
Dirty(uid, priorityData);
|
||||
|
||||
var ev = new DeliveryPriorityExpiredEvent();
|
||||
RaiseLocalEvent(uid, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets raised on a priority delivery when it's timer expires.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public readonly record struct DeliveryPriorityExpiredEvent;
|
||||
|
||||
43
Content.Shared/Delivery/DeliveryPriorityComponent.cs
Normal file
43
Content.Shared/Delivery/DeliveryPriorityComponent.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Delivery;
|
||||
|
||||
/// <summary>
|
||||
/// Component given to deliveries.
|
||||
/// Applies a duration before which the delivery must be delivered.
|
||||
/// If successful, adds a small multiplier, otherwise removes a small multiplier.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(DeliveryModifierSystem))]
|
||||
public sealed partial class DeliveryPriorityComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The highest the random multiplier can go.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float InTimeMultiplierOffset = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// The lowest the random multiplier can go.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float ExpiredMultiplierOffset = -0.1f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this priority delivery has already ran out of time or not.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool Expired;
|
||||
|
||||
/// <summary>
|
||||
/// How much time you get from spawn until the delivery expires.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan DeliveryTime = TimeSpan.FromMinutes(5);
|
||||
|
||||
/// <summary>
|
||||
/// The time by which this has to be delivered.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan DeliverUntilTime;
|
||||
}
|
||||
@@ -9,11 +9,18 @@ public enum DeliveryVisuals : byte
|
||||
IsTrash,
|
||||
IsBroken,
|
||||
IsFragile,
|
||||
IsPriority,
|
||||
IsPriorityInactive,
|
||||
PriorityState,
|
||||
JobIcon,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DeliveryPriorityState : byte
|
||||
{
|
||||
Off,
|
||||
Active,
|
||||
Inactive,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DeliverySpawnerVisuals : byte
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ public abstract class SharedDeliverySystem : EntitySystem
|
||||
var multiplier = GetDeliveryMultiplier(ent);
|
||||
var totalSpesos = Math.Round(ent.Comp.BaseSpesoReward * multiplier);
|
||||
|
||||
args.PushMarkup(Loc.GetString("delivery-earnings-examine", ("spesos", totalSpesos)));
|
||||
args.PushMarkup(Loc.GetString("delivery-earnings-examine", ("spesos", totalSpesos)), -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +238,18 @@ public abstract class SharedDeliverySystem : EntitySystem
|
||||
|
||||
// If we're trying to unlock, always remove the priority tape
|
||||
if (!isLocked)
|
||||
_appearance.SetData(uid, DeliveryVisuals.IsPriority, false);
|
||||
_appearance.SetData(uid, DeliveryVisuals.PriorityState, DeliveryPriorityState.Off);
|
||||
}
|
||||
|
||||
public void UpdatePriorityVisuals(Entity<DeliveryPriorityComponent> ent)
|
||||
{
|
||||
if (!TryComp<DeliveryComponent>(ent, out var delivery))
|
||||
return;
|
||||
|
||||
if (delivery.IsLocked && !delivery.IsOpened)
|
||||
{
|
||||
_appearance.SetData(ent, DeliveryVisuals.PriorityState, ent.Comp.Expired ? DeliveryPriorityState.Inactive : DeliveryPriorityState.Active);
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateDeliverySpawnerVisuals(EntityUid uid, int contents)
|
||||
@@ -257,7 +268,10 @@ public abstract class SharedDeliverySystem : EntitySystem
|
||||
var ev = new GetDeliveryMultiplierEvent();
|
||||
RaiseLocalEvent(ent, ref ev);
|
||||
|
||||
return ev.AdditiveMultiplier * ev.MultiplicativeMultiplier;
|
||||
// Ensure the multiplier can never go below 0.
|
||||
var totalMultiplier = Math.Max(ev.AdditiveMultiplier * ev.MultiplicativeMultiplier, 0);
|
||||
|
||||
return totalMultiplier;
|
||||
}
|
||||
|
||||
protected virtual void GrantSpesoReward(Entity<DeliveryComponent?> ent) { }
|
||||
|
||||
@@ -141,7 +141,8 @@ public abstract class SharedItemSystem : EntitySystem
|
||||
{
|
||||
// show at end of message generally
|
||||
args.PushMarkup(Loc.GetString("item-component-on-examine-size",
|
||||
("size", GetItemSizeLocale(component.Size))), priority: -1);
|
||||
("size", GetItemSizeLocale(component.Size))),
|
||||
priority: -2);
|
||||
}
|
||||
|
||||
public ItemSizePrototype GetSizePrototype(ProtoId<ItemSizePrototype> id)
|
||||
|
||||
@@ -20,3 +20,8 @@ delivery-teleporter-amount-examine =
|
||||
}
|
||||
delivery-teleporter-empty = The {$entity} is empty.
|
||||
delivery-teleporter-empty-verb = Take mail
|
||||
|
||||
|
||||
# modifiers
|
||||
delivery-priority-examine = This is a [color=orange]priority {$type}[/color]. You have [color=orange]{$time}[/color] left to deliver it to get a bonus.
|
||||
delivery-priority-expired-examine = This is a [color=orange]priority {$type}[/color]. It seems you ran out of time.
|
||||
|
||||
@@ -14,14 +14,11 @@
|
||||
enum.DeliveryVisualLayers.Lock:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
enum.DeliveryVisuals.IsPriority:
|
||||
enum.DeliveryVisuals.PriorityState:
|
||||
enum.DeliveryVisualLayers.PriorityTape:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
enum.DeliveryVisuals.IsPriorityInactive:
|
||||
enum.DeliveryVisualLayers.PriorityTape:
|
||||
True: { shader: shaded, state: priority_inactive }
|
||||
False: { shader: unshaded, state: priority }
|
||||
Off: { visible: false }
|
||||
Active: { visible: true, shader: unshaded, state: priority }
|
||||
Inactive: { visible: true, shader: shaded, state: priority_inactive }
|
||||
enum.DeliveryVisuals.IsBroken:
|
||||
enum.DeliveryVisualLayers.Breakage:
|
||||
True: { visible: true }
|
||||
@@ -45,6 +42,9 @@
|
||||
- type: SimpleToolUsage
|
||||
doAfter: 4
|
||||
usageVerb: delivery-slice-verb
|
||||
- type: ComponentTable
|
||||
table: !type:NestedSelector
|
||||
tableId: DeliveryModifierTable
|
||||
|
||||
- type: entity
|
||||
parent: BaseDelivery
|
||||
@@ -128,3 +128,19 @@
|
||||
containers:
|
||||
delivery: !type:NestedSelector
|
||||
tableId: LetterDeliveryRewards
|
||||
|
||||
|
||||
# Modifier Tables
|
||||
- type: entityTable
|
||||
id: DeliveryModifierTable
|
||||
table: !type:AllSelector
|
||||
children:
|
||||
- id: DeliveryModifierPriority
|
||||
prob: 0.25
|
||||
|
||||
- type: entity
|
||||
id: DeliveryModifierPriority
|
||||
description: Components to add when a delivery is rolled as priority.
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: DeliveryPriority
|
||||
|
||||
Reference in New Issue
Block a user