Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,55 @@ public sealed partial class PopupMessageEntityEffectSystem : EntityEffectSystem<
[Dependency] private readonly SharedPopupSystem _popup = default!;

protected override void Effect(Entity<TransformComponent> entity, ref EntityEffectEvent<PopupMessage> args)
{
// DEN start: move this to a public method
PopupMessage(entity,
args.Effect.Messages,
args.Effect.VisualType,
args.Effect.Method,
args.Effect.Type);
// DEN end
}

// DEN start: move this to a public method

/// <summary>
/// Spawns a random popup message on the given entity with the given parameters.
/// </summary>
/// <param name="entity">The entity to spawn a popup message on.</param>
/// <param name="messages">An array of possible random messages.</param>
/// <param name="popupType">The visual type of the popup.</param>
/// <param name="method">The popup API type to use.</param>
/// <param name="recipients">Whether this popup only shows for the entity, or for everyone.</param>
public void PopupMessage(Entity<TransformComponent> entity,
string[] messages,
PopupType popupType,
PopupMethod method,
PopupRecipients recipients)
{
// TODO: When we get proper random prediction remove this check.
if (_net.IsClient)
return;

var msg = Loc.GetString(_random.Pick(args.Effect.Messages), ("entity", entity));
var msg = Loc.GetString(_random.Pick(messages), ("entity", entity));

switch ((args.Effect.Method, args.Effect.Type))
switch ((method, recipients))
{
case (PopupMethod.PopupEntity, PopupRecipients.Local):
_popup.PopupEntity(msg, entity, entity, args.Effect.VisualType);
_popup.PopupEntity(msg, entity, entity, popupType);
break;
case (PopupMethod.PopupEntity, PopupRecipients.Pvs):
_popup.PopupEntity(msg, entity, args.Effect.VisualType);
_popup.PopupEntity(msg, entity, popupType);
break;
case (PopupMethod.PopupCoordinates, PopupRecipients.Local):
_popup.PopupCoordinates(msg, Transform(entity).Coordinates, entity, args.Effect.VisualType);
_popup.PopupCoordinates(msg, Transform(entity).Coordinates, entity, popupType);
break;
case (PopupMethod.PopupCoordinates, PopupRecipients.Pvs):
_popup.PopupCoordinates(msg, Transform(entity).Coordinates, args.Effect.VisualType);
_popup.PopupCoordinates(msg, Transform(entity).Coordinates, popupType);
break;
}
}
// DEN end
}

/// <inheritdoc cref="EntityEffect"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Content.Shared._DEN.StatusEffects.Components;

/// <summary>
/// A status effect that will create a popup message on the entity upon the status effect expiring.
/// </summary>
/// <remarks>
/// This is very similar to the "PopupMessage" entity effect in metabolisms, but rather than
/// being a chance per metabolism tick, this just shows a random message on expiry -
/// making it more consistent.
/// </remarks>
[RegisterComponent]
public sealed partial class ExpiryPopupMessageStatusEffectComponent : PopupMessageStatusEffectComponent
{ }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Content.Shared._DEN.StatusEffects.Components;

/// <summary>
/// A status effect that will regularly create a popup message on the entity on a given interval.
/// </summary>
/// <remarks>
/// This is very similar to the "PopupMessage" entity effect in metabolisms, but rather than
/// being a chance per metabolism tick, this just shows random messages on a given interval -
/// making it more consistent.
/// </remarks>
[RegisterComponent]
public sealed partial class IntervalPopupMessageStatusEffectComponent : PopupMessageStatusEffectComponent
{
/// <summary>
/// The minimum and maximum time interval that popup messages will be displayed.
/// </summary>
[DataField]
public (TimeSpan Min, TimeSpan Max) Interval = (TimeSpan.FromSeconds(30.0f), TimeSpan.FromSeconds(60.0f));

/// <summary>
/// The next time we should display a popup message.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan NextPopupTime = TimeSpan.Zero;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared.EntityEffects.Effects.Transform;
using Content.Shared.Popups;

namespace Content.Shared._DEN.StatusEffects.Components;

/// <summary>
/// Abstract class for status effects that show popup messages.
/// </summary>
/// <remarks>
/// This is very similar to the "PopupMessage" entity effect in metabolisms.
/// </remarks>
public abstract partial class PopupMessageStatusEffectComponent : Component
{
/// <summary>
/// Array of messages that can popup.
/// Only one is chosen when the effect is applied.
/// </summary>
[DataField(required: true)]
public string[] Messages = default!;

/// <summary>
/// Whether to just the entity we're affecting, or everyone around them.
/// </summary>
[DataField]
public PopupRecipients Recipients = PopupRecipients.Local;

/// <summary>
/// Which popup API method to use.
/// Use PopupCoordinates in case the entity will be deleted while the popup is shown.
/// </summary>
[DataField]
public PopupMethod Method = PopupMethod.PopupEntity;

/// <summary>
/// Size of the popup.
/// </summary>
[DataField]
public PopupType VisualType = PopupType.Small;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Content.Shared._DEN.StatusEffects.Components;
using Content.Shared.EntityEffects.Effects.Transform;
using Content.Shared.StatusEffectNew;
using Content.Shared.StatusEffectNew.Components;
using Robust.Shared.Random;
using Robust.Shared.Timing;

namespace Content.Shared._DEN.StatusEffects.EntitySystems;

/// <summary>
/// This system handles displaying popup messages for various popup message status effects.
/// </summary>
public sealed partial class PopupMessageStatusEffectSystem : EntitySystem
{
[Dependency] private readonly PopupMessageEntityEffectSystem _popupEffect = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IGameTiming _timing = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<IntervalPopupMessageStatusEffectComponent, StatusEffectAppliedEvent>(OnIntervalPopupApplied);
SubscribeLocalEvent<ExpiryPopupMessageStatusEffectComponent, StatusEffectRemovedEvent>(OnExpiredPopupRemoved);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

var query = EntityQueryEnumerator<IntervalPopupMessageStatusEffectComponent, StatusEffectComponent>();
while (query.MoveNext(out var uid, out var interval, out var statusEffect))
{
if (_timing.CurTime < interval.NextPopupTime)
continue;

UpdatePopupIntervalTime((uid, interval));
SpawnPopup((uid, statusEffect), interval);
}
}

private void OnIntervalPopupApplied(Entity<IntervalPopupMessageStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
{
UpdatePopupIntervalTime(ent);
}

private void OnExpiredPopupRemoved(Entity<ExpiryPopupMessageStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
{
SpawnPopup((ent.Owner, null), ent.Comp);
}

/// <summary>
/// Spawns a popup message related to a popup message status effect.
/// </summary>
/// <param name="ent">The status effect entity.</param>
/// <param name="popupComp">The popup message component associated with this effect.</param>
private void SpawnPopup(Entity<StatusEffectComponent?> ent, PopupMessageStatusEffectComponent popupComp)
{
if (!Resolve(ent.Owner, ref ent.Comp))
return;

var statusEffect = ent.Comp;
if (statusEffect.AppliedTo == null)
return;

var xform = Transform(statusEffect.AppliedTo.Value);
_popupEffect.PopupMessage((statusEffect.AppliedTo.Value, xform),
popupComp.Messages,
popupComp.VisualType,
popupComp.Method,
popupComp.Recipients);
}

/// <summary>
/// Sets the next popup message spawn time for an interval popup effect.
/// </summary>
/// <param name="ent">The interval popup status effect.</param>
private void UpdatePopupIntervalTime(Entity<IntervalPopupMessageStatusEffectComponent> ent)
{
var comp = ent.Comp;
var (min, max) = comp.Interval;
var newInterval = _random.NextDouble(min.TotalSeconds, max.TotalSeconds);

comp.NextPopupTime = _timing.CurTime + TimeSpan.FromSeconds(newInterval);
}
}
7 changes: 7 additions & 0 deletions Resources/Locale/en-US/_DEN/flavors/flavor-profiles.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# base flavors

flavor-base-tart = tart

# complex flavors

flavor-complex-pomegranate = like pomegranates
1 change: 1 addition & 0 deletions Resources/Locale/en-US/_DEN/guidebook/guides.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
guide-entry-lewd = ⑱ Lewd
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# general

food-sequence-content-pomegranate = pomegranate

# burgers

food-sequence-burger-content-pomegranate = pom

# cotton burgers
food-sequence-cotton-burger-content-plushie-alien-germ = germ
food-sequence-cotton-burger-content-plushie-azalea = aza
Expand Down
9 changes: 9 additions & 0 deletions Resources/Locale/en-US/_DEN/reagents/lewd.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
reagent-effect-aphrodisiac-mild1 = Your entire body feels warm.
reagent-effect-aphrodisiac-mild2 = Your breathing feels heavier.
reagent-effect-aphrodisiac-mild3 = Your thoughts feel more vivid.
reagent-effect-aphrodisiac-mild4 = The flush in your face is hard to ignore.
reagent-effect-aphrodisiac-mild5 = You feel more sensitive to the touch.
reagent-effect-aphrodisiac-mild6 = Every sensation feels more intense.
reagent-effect-aphrodisiac-mildoverdose1 = You feel nauseous.
reagent-effect-aphrodisiac-mildoverdose2 = You feel lightheaded.
reagent-effect-aphrodisiac-mildexpired1 = You feel your inhibitions normalize.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
reagent-name-juice-pomegranate = pomegranate juice
reagent-desc-juice-pomegranate = The sweet and tart juice of pomegranates. Bold and intense.
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_DEN/reagents/meta/lewd.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
reagent-name-pomelustine = pomelustine
reagent-desc-pomelustine = A mild aphrodisiac synthesized from pomegranates. Often ingested to provoke desire and arousal.
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_DEN/seeds/seeds.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
seeds-pomegranate-name = pomegranate
seeds-pomegranate-display-name = pomegranate tree
3 changes: 2 additions & 1 deletion Resources/Prototypes/Catalog/Fills/Crates/botany.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
parent: CrateHydroponics
id: CrateHydroponicsSeeds
name: seeds crate
description: Big things have small beginnings. Contains twenty-four different seeds.
description: Big things have small beginnings. Contains twenty-five different seeds. # DEN: 24 -> 25
components:
- type: EntityTableContainerFill
containers:
Expand Down Expand Up @@ -101,6 +101,7 @@
- id: PeaSeeds
- id: CherrySeeds
- id: CottonSeeds
- id: PomegranateSeeds # DEN

- type: entity
parent: CrateHydroponics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
OnionRedSeeds: 5
OrangeSeeds: 5
PeaSeeds: 5
PomegranateSeeds: 5 # DEN
PoppySeeds: 3
PotatoSeeds: 5
PumpkinSeeds: 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@
- id: DrinkShakeWhite
- id: DrinkTheMartinez
- id: DrinkMoonshineGlass
# Start DEN: Additions
# Note: Do NOT add NSFW-oriented glasses here, like aphrodisiacs.
- id: DrinkPomegranateJuiceGlass
# End DEN
- !type:GroupSelector #rare
weight: 0.05
children:
Expand Down
1 change: 1 addition & 0 deletions Resources/Prototypes/Guidebook/chemicals.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Foods
- Botanical
- Biological
- Lewd # DEN
- Special
- Others
filterEnabled: True
Expand Down
8 changes: 8 additions & 0 deletions Resources/Prototypes/Reagents/elements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
color: "#848789"
boilingPoint: 2327.0
meltingPoint: 660.0
metabolisms: # DEN: Aluminium removes aphrodisiacs
Metabolites:
effects:
# Five units will remove 50u of pomelustine.
- !type:AdjustReagent
reagent: Pomelustine
amount: -5
conditions:

- type: reagent
id: Carbon
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Aphrodisiacs

- type: entity
parent: DrinkGlass
id: DrinkPomelustineGlass
suffix: pomelustine
components:
- type: SolutionContainerManager
solutions:
drink:
maxVol: 30
reagents:
- ReagentId: Pomelustine
Quantity: 30

# Others.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Juice

- type: entity
parent: DrinkGlass
id: DrinkPomegranateJuiceGlass
suffix: pomegranate juice
components:
- type: SolutionContainerManager
solutions:
drink:
maxVol: 30
reagents:
- ReagentId: JuicePomegranate
Quantity: 30

# Cocktails
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
- type: entity
parent: FoodProduceBase
id: FoodPomegranate
name: pomegranate
description: A sticky, sweet symbol of fertility and abundance.
components:
- type: FlavorProfile
flavors:
- pomegranate
- type: SolutionContainerManager
solutions:
food:
maxVol: 14
reagents:
- ReagentId: Nutriment
Quantity: 10
- ReagentId: Vitamin
Quantity: 4
- type: Sprite
sprite: _DEN/Objects/Specific/Hydroponics/pomegranate.rsi
- type: Item
heldPrefix: produce
- type: Produce
seedId: pomegranate
- type: Extractable
juiceSolution:
reagents:
- ReagentId: JuicePomegranate
Quantity: 10
- type: Tag
tags:
- Fruit
- type: FoodSequenceElement
entries:
Burger: PomegranateBurger
Taco: Pomegranate
Loading
Loading