Randomized lollipop and gumball flavors (#1074)
* Give lollipops and gumballs random flavors * RandomizedCandy: Fix borg lollipop action * RandomizedCandy: Play sound when candy is fabricated * RandomizedCandy: Lollipop can now be put in mouth * RandomizedCandy: Quieten fab sound * RandomizedCandy: merge icons and reexport without pHYs chunk should speed up downloading these textures on 9600 baud modems * RandomizedCandy: loads more flavors and update description * RandomizedCandy: Fix duplicate candyFlavor IDs * RandomizedCandy: Fix attrib and preserve flavor order * RandomizedCandy: init on MapInit instead of ComponentInit * RandomizedCandy: Fix minor code style issues, file placement * RandomizedCandy: put new code into DeltaV namespace * RandomizedCandy: Removed redundant datafield tags Signed-off-by: no <165581243+pissdemon@users.noreply.github.com> --------- Signed-off-by: no <165581243+pissdemon@users.noreply.github.com>
|
|
@ -0,0 +1,26 @@
|
|||
using Content.Shared.DeltaV.Abilities.Borgs;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.DeltaV.Abilities.Borgs;
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for coloring randomized candy.
|
||||
/// </summary>
|
||||
public sealed class RandomizedCandyVisualizer : VisualizerSystem<RandomizedCandyComponent>
|
||||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, RandomizedCandyComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite)
|
||||
|| !AppearanceSystem.TryGetData<Color>(uid, RandomizedCandyVisuals.Color, out var color, args.Component))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sprite.LayerSetColor(CandyVisualLayers.Ball, color);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CandyVisualLayers : byte
|
||||
{
|
||||
Ball
|
||||
}
|
||||
|
|
@ -118,6 +118,7 @@ namespace Content.Client.Entry
|
|||
_prototypeManager.RegisterIgnore("wireLayout");
|
||||
_prototypeManager.RegisterIgnore("alertLevels");
|
||||
_prototypeManager.RegisterIgnore("nukeopsRole");
|
||||
_prototypeManager.RegisterIgnore("candyFlavor"); // Delta-V
|
||||
|
||||
_componentFactory.GenerateNetIds();
|
||||
_adminManager.Initialize();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
using Content.Shared.Nutrition;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.DeltaV.Abilities.Borgs;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the color and flavor profile of lollipops and gumballs. Yummy!
|
||||
/// </summary>
|
||||
[Prototype("candyFlavor")]
|
||||
public sealed partial class CandyFlavorPrototype : IPrototype
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The display name for this candy. Not localized.
|
||||
/// </summary>
|
||||
[DataField] public string Name { get; private set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// The color of the candy.
|
||||
/// </summary>
|
||||
[DataField] public Color Color { get; private set; } = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// How the candy tastes like.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public HashSet<ProtoId<FlavorPrototype>> Flavors { get; private set; } = [];
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Shared.DeltaV.Abilities.Borgs;
|
||||
using Content.Shared.Nutrition;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.DeltaV.Abilities.Borgs;
|
||||
|
||||
/// <summary>
|
||||
/// Gives things with a <see cref="RandomizedCandyComponent"/> a random flavor, with corresponding appearance and
|
||||
/// examine text.
|
||||
/// </summary>
|
||||
public sealed partial class RandomizedCandySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Flavors that are masked by the candy.
|
||||
/// </summary>
|
||||
private static readonly string[] MaskedReagents = { "Sugar", "Iron" }; // sugar is obvious and iron is "metallic" :(
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<RandomizedCandyComponent, MapInitEvent>(OnInit);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, RandomizedCandyComponent candyComp, MapInitEvent args)
|
||||
{
|
||||
// pick a random flavor
|
||||
var flavors = _prototypeManager.EnumeratePrototypes<CandyFlavorPrototype>();
|
||||
var candyFlavor = _random.Pick(flavors.ToList());
|
||||
|
||||
// color the candy :3
|
||||
_appearance.SetData(uid, RandomizedCandyVisuals.Color, candyFlavor.Color);
|
||||
|
||||
// flavor the candy! yummy
|
||||
var flavorProfile = EnsureComp<FlavorProfileComponent>(uid);
|
||||
flavorProfile.Flavors.Clear(); // it shouldn't be flavored but clear it anyway
|
||||
foreach (var flavorId in candyFlavor.Flavors)
|
||||
{
|
||||
flavorProfile.Flavors.Add(flavorId);
|
||||
}
|
||||
flavorProfile.IgnoreReagents.UnionWith(MaskedReagents); // otherwise the nom text gets too long
|
||||
|
||||
// update the candy's metadata with fluff
|
||||
var meta = MetaData(uid);
|
||||
if (!string.IsNullOrEmpty(candyFlavor.Name))
|
||||
_metaData.SetEntityName(uid, $"{candyFlavor.Name} {meta.EntityName}", meta);
|
||||
_metaData.SetEntityDescription(uid, $"{meta.EntityDescription} {GetExamineFluff(candyFlavor.Flavors)}");
|
||||
Dirty(uid, meta);
|
||||
}
|
||||
|
||||
// this technically duplicates code from FlavorProfileSystem but what we would need to call
|
||||
// is upstream code in a private method with fixed loc strings and unnecessary sorting, so i don't want to touch it
|
||||
private string GetExamineFluff(HashSet<ProtoId<FlavorPrototype>> flavorIds)
|
||||
{
|
||||
var flavors = new List<string>();
|
||||
foreach (var flavorId in flavorIds)
|
||||
{
|
||||
if (_prototypeManager.TryIndex(flavorId, out var flavor) &&
|
||||
Loc.TryGetString(flavor.FlavorDescription, out var flavorText))
|
||||
{
|
||||
flavors.Add(flavorText);
|
||||
}
|
||||
}
|
||||
|
||||
return flavors.Count switch
|
||||
{
|
||||
> 1 => Loc.GetString("candy-flavor-profile-multiple",
|
||||
("lastFlavor", flavors.Pop()),
|
||||
("flavors", string.Join(", ", flavors))
|
||||
),
|
||||
1 => Loc.GetString("candy-flavor-profile", ("flavor", flavors.Single())),
|
||||
_ => Loc.GetString("candy-flavor-profile-unknown")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,25 @@
|
|||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Abilities.Borgs;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class FabricateCandyComponent : Component
|
||||
{
|
||||
[DataField("lollipopAction")]
|
||||
[DataField]
|
||||
public EntityUid? LollipopAction;
|
||||
|
||||
[DataField("gumballAction")]
|
||||
[DataField]
|
||||
public EntityUid? GumballAction;
|
||||
|
||||
/// <summary>
|
||||
/// The sound played when fabricating candy.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier FabricationSound = new SoundPathSpecifier("/Audio/Machines/machine_vend.ogg")
|
||||
{
|
||||
Params = new AudioParams
|
||||
{
|
||||
Volume = -2f
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using Robust.Server.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Actions.Events;
|
||||
|
||||
|
|
@ -6,6 +8,8 @@ namespace Content.Server.Abilities.Borgs;
|
|||
public sealed partial class FabricateCandySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
|
@ -25,13 +29,19 @@ public sealed partial class FabricateCandySystem : EntitySystem
|
|||
|
||||
private void OnLollipop(FabricateLollipopActionEvent args)
|
||||
{
|
||||
Spawn("FoodLollipop", Transform(args.Performer).Coordinates);
|
||||
args.Handled = true;
|
||||
OnCandy("FoodLollipop", args);
|
||||
}
|
||||
|
||||
private void OnGumball(FabricateGumballActionEvent args)
|
||||
{
|
||||
Spawn("FoodGumball", Transform(args.Performer).Coordinates);
|
||||
args.Handled = true;
|
||||
OnCandy("FoodGumball", args);
|
||||
}
|
||||
|
||||
private void OnCandy(EntProtoId proto, BaseActionEvent evt)
|
||||
{
|
||||
Spawn(proto, Transform(evt.Performer).Coordinates);
|
||||
if (TryComp(evt.Performer, out FabricateCandyComponent? comp))
|
||||
_audioSystem.PlayPvs(comp.FabricationSound, evt.Performer);
|
||||
evt.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.DeltaV.Abilities.Borgs;
|
||||
|
||||
/// <summary>
|
||||
/// Marks this entity as being candy with a random flavor and color.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class RandomizedCandyComponent : Component
|
||||
{
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum RandomizedCandyVisuals : byte
|
||||
{
|
||||
Color
|
||||
}
|
||||
|
|
@ -27,3 +27,10 @@ flavor-complex-daiquiri = fashionable
|
|||
flavor-complex-arsonistsbrew = like ash and flame
|
||||
flavor-complex-healthcodeviolation = ominous
|
||||
flavor-complex-pumpkin = like pumpkin
|
||||
flavor-complex-blellow = like an impossible color
|
||||
flavor-complex-candy-strawberry = like strawberries
|
||||
flavor-complex-candy-bubblegum = like bubble gum
|
||||
|
||||
candy-flavor-profile = This one is supposed to taste {$flavor}.
|
||||
candy-flavor-profile-multiple = This one is supposed to taste {$flavors} and {$lastFlavor}.
|
||||
candy-flavor-profile-unknown = You have no idea what this one is supposed to taste like.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,236 @@
|
|||
# Flavors for lollipops and gumballs
|
||||
|
||||
- type: candyFlavor
|
||||
id: berry
|
||||
name: berry
|
||||
color: '#800080'
|
||||
flavors:
|
||||
- berry
|
||||
|
||||
- type: candyFlavor
|
||||
id: ginger
|
||||
name: ginger
|
||||
color: '#fbdba0'
|
||||
flavors:
|
||||
- gingersoda
|
||||
|
||||
- type: candyFlavor
|
||||
id: bananashake
|
||||
name: banana shake
|
||||
color: '#ffe135'
|
||||
flavors:
|
||||
- bananahonk
|
||||
|
||||
- type: candyFlavor
|
||||
id: vanilla
|
||||
name: vanilla
|
||||
color: '#f9e5bc'
|
||||
flavors:
|
||||
- creamy
|
||||
- vanilla
|
||||
|
||||
- type: candyFlavor
|
||||
id: orange
|
||||
name: orange
|
||||
color: '#fa7000'
|
||||
flavors:
|
||||
- orange
|
||||
|
||||
- type: candyFlavor
|
||||
id: watermelon
|
||||
name: watermelon
|
||||
color: '#009345'
|
||||
flavors:
|
||||
- watermelon
|
||||
|
||||
- type: candyFlavor
|
||||
id: pineapple
|
||||
name: pineapple
|
||||
color: '#e6ae25'
|
||||
flavors:
|
||||
- pineapple
|
||||
|
||||
- type: candyFlavor
|
||||
id: rootbeer
|
||||
name: root beer
|
||||
color: '#290e05'
|
||||
flavors:
|
||||
- rootbeersoda
|
||||
|
||||
- type: candyFlavor
|
||||
id: lemon
|
||||
name: lemon
|
||||
color: '#fef250'
|
||||
flavors:
|
||||
- lemondrop
|
||||
|
||||
- type: candyFlavor
|
||||
id: cola
|
||||
name: cola
|
||||
color: '#3c3024'
|
||||
flavors:
|
||||
- cola
|
||||
|
||||
- type: candyFlavor
|
||||
id: icedtea
|
||||
name: iced tea
|
||||
color: '#e0a779'
|
||||
flavors:
|
||||
- icedtea
|
||||
|
||||
- type: candyFlavor
|
||||
id: peppermint
|
||||
name: peppermint
|
||||
color: '#47e7ad'
|
||||
flavors:
|
||||
- minty
|
||||
|
||||
- type: candyFlavor
|
||||
id: spearmint
|
||||
name: spearmint
|
||||
color: '#47e75b'
|
||||
flavors:
|
||||
- minty
|
||||
|
||||
- type: candyFlavor
|
||||
id: apple
|
||||
name: apple
|
||||
color: '#dd1533'
|
||||
flavors:
|
||||
- apple
|
||||
|
||||
- type: candyFlavor
|
||||
id: honey
|
||||
name: honey
|
||||
color: '#e79a3f'
|
||||
flavors:
|
||||
- honey
|
||||
|
||||
- type: candyFlavor
|
||||
id: bungo
|
||||
name: bungo
|
||||
color: '#ffe017'
|
||||
flavors:
|
||||
- bungo
|
||||
|
||||
- type: candyFlavor
|
||||
id: grape
|
||||
name: grape
|
||||
color: '#6c3461'
|
||||
flavors:
|
||||
- grape
|
||||
|
||||
- type: candyFlavor
|
||||
id: bubbletea
|
||||
name: bubble tea
|
||||
color: '#d2b18c'
|
||||
flavors:
|
||||
- bubbletea
|
||||
|
||||
- type: candyFlavor
|
||||
id: mystery
|
||||
name: mystery flavor
|
||||
color: '#202020'
|
||||
flavors:
|
||||
- spaceshroom # it's a "mysterious" flavor
|
||||
|
||||
- type: candyFlavor
|
||||
id: creamystrawberry
|
||||
name: creamy strawberry
|
||||
color: '#f8d9df'
|
||||
flavors:
|
||||
- creamy
|
||||
- candystrawberry
|
||||
|
||||
- type: candyFlavor
|
||||
id: strawberryyogurt
|
||||
name: strawberry yogurt
|
||||
color: '#f8d9df'
|
||||
flavors:
|
||||
- sour
|
||||
- candystrawberry
|
||||
- milk
|
||||
|
||||
- type: candyFlavor
|
||||
id: sourapple
|
||||
name: sour apple # mouth-puckering!
|
||||
color: '#68aa2e'
|
||||
flavors:
|
||||
- sour
|
||||
- apple
|
||||
|
||||
- type: candyFlavor
|
||||
id: bubblegum
|
||||
name: bubble gum
|
||||
color: '#f988d9'
|
||||
flavors:
|
||||
- candybubblegum
|
||||
|
||||
- type: candyFlavor
|
||||
id: chilibungo
|
||||
name: chili bungo # don't ask, i found chili mango lollipops on google, and bungos supposedly taste similar to mango
|
||||
color: '#813c23'
|
||||
flavors:
|
||||
- spicy
|
||||
- bungo
|
||||
|
||||
- type: candyFlavor
|
||||
id: tequilasunrise
|
||||
name: tequila sunrise
|
||||
color: '#ffe48c'
|
||||
flavors:
|
||||
- tequilasunrise
|
||||
|
||||
- type: candyFlavor
|
||||
id: mime
|
||||
name: mime
|
||||
color: '#eeeeee'
|
||||
flavors:
|
||||
- nothing
|
||||
|
||||
- type: candyFlavor
|
||||
id: honeylemonginger
|
||||
name: honey lemon ginger
|
||||
color: '#e6d781'
|
||||
flavors:
|
||||
- sour
|
||||
- honey
|
||||
- gingersoda
|
||||
|
||||
# weird flavors below!
|
||||
|
||||
- type: candyFlavor
|
||||
id: foof
|
||||
name: foof
|
||||
color: '#ff00ff'
|
||||
flavors:
|
||||
- pinkdrink
|
||||
|
||||
- type: candyFlavor
|
||||
id: feline
|
||||
name: cat-flavored
|
||||
color: '#7c4511'
|
||||
flavors:
|
||||
- cat
|
||||
|
||||
- type: candyFlavor
|
||||
id: blellow
|
||||
name: blellow
|
||||
color: '#737373'
|
||||
flavors:
|
||||
- blellow
|
||||
|
||||
- type: candyFlavor
|
||||
id: stale
|
||||
name: stale
|
||||
color: '#96818e'
|
||||
flavors:
|
||||
- terrible
|
||||
- sadness
|
||||
|
||||
- type: candyFlavor
|
||||
id: weh
|
||||
name: weh # sorry, doesn't actually make you weh!
|
||||
color: '#59b23a'
|
||||
flavors:
|
||||
- weh
|
||||
|
|
@ -115,3 +115,19 @@
|
|||
id: arsonistsbrew
|
||||
flavorType: Complex
|
||||
description: flavor-complex-arsonistsbrew
|
||||
|
||||
- type: flavor
|
||||
id: blellow
|
||||
flavorType: Complex
|
||||
description: flavor-complex-blellow
|
||||
|
||||
# this is prefixed with "candy" to avoid clashes with potential future strawberries upstream
|
||||
- type: flavor
|
||||
id: candystrawberry
|
||||
flavorType: Complex
|
||||
description: flavor-complex-candy-strawberry
|
||||
|
||||
- type: flavor
|
||||
id: candybubblegum
|
||||
flavorType: Complex
|
||||
description: flavor-complex-candy-bubblegum
|
||||
|
|
|
|||
|
|
@ -175,5 +175,6 @@
|
|||
components:
|
||||
- type: InstantAction
|
||||
icon: { sprite: Nyanotrasen/Objects/Consumable/Food/candy.rsi, state: gumball }
|
||||
iconColor: '#FFAED7'
|
||||
useDelay: 40
|
||||
event: !type:FabricateGumballActionEvent
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
parent: FoodBase
|
||||
id: FoodLollipop
|
||||
name: lollipop
|
||||
description: For being such a good sport.
|
||||
description: For being such a good sport! It's enriched with potent yet mostly safe-to-eat medicine.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
|
|
@ -21,13 +21,23 @@
|
|||
Quantity: 3
|
||||
- type: Sprite
|
||||
sprite: Nyanotrasen/Objects/Consumable/Food/candy.rsi
|
||||
state: lollipop
|
||||
layers:
|
||||
- state: lollipop-ball
|
||||
map: [ "enum.CandyVisualLayers.Ball" ]
|
||||
- state: lollipop-stickandshine
|
||||
- type: Clothing
|
||||
sprite: Nyanotrasen/Objects/Consumable/Food/candy.rsi
|
||||
slots: [ mask ]
|
||||
equippedPrefix: lollipop
|
||||
quickEquip: false # would block eating otherwise
|
||||
- type: Appearance
|
||||
- type: RandomizedCandy
|
||||
|
||||
- type: entity
|
||||
parent: FoodBase
|
||||
id: FoodGumball
|
||||
name: gumball
|
||||
description: For being such a good sport.
|
||||
description: Try as you might, you can't blow bubbles with it... it's enriched with medicine for minor ailments.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
|
|
@ -44,4 +54,9 @@
|
|||
Quantity: 3
|
||||
- type: Sprite
|
||||
sprite: Nyanotrasen/Objects/Consumable/Food/candy.rsi
|
||||
state: gumball
|
||||
layers:
|
||||
- state: gumball
|
||||
map: [ "enum.CandyVisualLayers.Ball" ]
|
||||
- state: gumball-shine
|
||||
- type: Appearance
|
||||
- type: RandomizedCandy
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 135 B |
|
After Width: | Height: | Size: 109 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 118 B |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24",
|
||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24, made colorable by pissdemon, equip sprites made by pissdemon based on cigarette.rsi taken from tgstation and paradise (see attributions in Resources/Textures/Objects/Consumable/Smokeables/Cigarettes/cigarette.rsi)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
|
|
@ -10,8 +10,25 @@
|
|||
{
|
||||
"name": "gumball"
|
||||
},
|
||||
{
|
||||
"name": "gumball-shine"
|
||||
},
|
||||
{
|
||||
"name": "lollipop"
|
||||
},
|
||||
{
|
||||
"name": "lollipop-ball"
|
||||
},
|
||||
{
|
||||
"name": "lollipop-stickandshine"
|
||||
},
|
||||
{
|
||||
"name": "lollipop-equipped-MASK",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "lollipop-equipped-MASK-vulpkanin",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||