Add Spaceshrooms (#17092)
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Random;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
@@ -18,14 +17,8 @@ public sealed class RandomFillSolutionComponent : Component
|
||||
public string Solution { get; set; } = "default";
|
||||
|
||||
/// <summary>
|
||||
/// Weighted random prototype Id. Used to pick reagent.
|
||||
/// Weighted random fill prototype Id. Used to pick reagent and quantity.
|
||||
/// </summary>
|
||||
[DataField("weightedRandomId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomPrototype>))]
|
||||
[DataField("weightedRandomId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomFillSolutionPrototype>))]
|
||||
public string WeightedRandomId { get; set; } = "default";
|
||||
|
||||
/// <summary>
|
||||
/// Amount of reagent to add.
|
||||
/// </summary>
|
||||
[DataField("quantity")]
|
||||
public FixedPoint2 Quantity { get; set; } = 0;
|
||||
}
|
||||
|
||||
@@ -20,18 +20,20 @@ public sealed class SolutionRandomFillSystem : EntitySystem
|
||||
SubscribeLocalEvent<RandomFillSolutionComponent, MapInitEvent>(OnRandomSolutionFillMapInit);
|
||||
}
|
||||
|
||||
public void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args)
|
||||
private void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args)
|
||||
{
|
||||
var target = _solutionsSystem.EnsureSolution(uid, component.Solution);
|
||||
var reagent = _proto.Index<WeightedRandomPrototype>(component.WeightedRandomId).Pick(_random);
|
||||
var pick = _proto.Index<WeightedRandomFillSolutionPrototype>(component.WeightedRandomId).Pick(_random);
|
||||
|
||||
if (!_proto.TryIndex<ReagentPrototype>(reagent, out ReagentPrototype? reagentProto))
|
||||
var reagent = pick.reagent;
|
||||
var quantity = pick.quantity;
|
||||
|
||||
if (!_proto.HasIndex<ReagentPrototype>(reagent))
|
||||
{
|
||||
Logger.Error(
|
||||
$"Tried to add invalid reagent Id {reagent} using SolutionRandomFill.");
|
||||
Log.Error($"Tried to add invalid reagent Id {reagent} using SolutionRandomFill.");
|
||||
return;
|
||||
}
|
||||
|
||||
target.AddReagent(reagent, component.Quantity);
|
||||
target.AddReagent(reagent, quantity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,25 +25,29 @@ public sealed partial class GatherableSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GatherableComponent, ActivateInWorldEvent>(OnActivate);
|
||||
SubscribeLocalEvent<GatherableComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<GatherableComponent, GatherableDoAfterEvent>(OnDoAfter);
|
||||
InitializeProjectile();
|
||||
}
|
||||
|
||||
private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args)
|
||||
private void Gather(EntityUid gatheredUid, EntityUid user, EntityUid used, GatheringToolComponent? tool = null, GatherableComponent? component = null)
|
||||
{
|
||||
if (!Resolve(used, ref tool, false) || !Resolve(gatheredUid, ref component, false) ||
|
||||
component.ToolWhitelist?.IsValid(used) == false)
|
||||
{
|
||||
if (!TryComp<GatheringToolComponent>(args.Used, out var tool) || component.ToolWhitelist?.IsValid(args.Used) == false)
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't gather too many entities at once.
|
||||
if (tool.MaxGatheringEntities < tool.GatheringEntities.Count + 1)
|
||||
return;
|
||||
|
||||
var damageRequired = _destructible.DestroyedAt(uid);
|
||||
var damageRequired = _destructible.DestroyedAt(gatheredUid);
|
||||
var damageTime = (damageRequired / tool.Damage.Total).Float();
|
||||
damageTime = Math.Max(1f, damageTime);
|
||||
|
||||
var doAfter = new DoAfterArgs(args.User, damageTime, new GatherableDoAfterEvent(), uid, target: uid, used: args.Used)
|
||||
var doAfter = new DoAfterArgs(user, damageTime, new GatherableDoAfterEvent(), gatheredUid, target: gatheredUid, used: used)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnTargetMove = true,
|
||||
@@ -54,6 +58,16 @@ public sealed partial class GatherableSystem : EntitySystem
|
||||
_doAfterSystem.TryStartDoAfter(doAfter);
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, GatherableComponent component, ActivateInWorldEvent args)
|
||||
{
|
||||
Gather(uid, args.User, args.User);
|
||||
}
|
||||
|
||||
private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args)
|
||||
{
|
||||
Gather(uid, args.User, args.Used, component: component);
|
||||
}
|
||||
|
||||
private void OnDoAfter(EntityUid uid, GatherableComponent component, GatherableDoAfterEvent args)
|
||||
{
|
||||
if(!TryComp<GatheringToolComponent>(args.Args.Used, out var tool))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Dataset;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.Random.Helpers
|
||||
@@ -75,5 +76,61 @@ namespace Content.Shared.Random.Helpers
|
||||
|
||||
throw new InvalidOperationException($"Invalid weighted pick");
|
||||
}
|
||||
|
||||
public static (string reagent, FixedPoint2 quantity) Pick(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null)
|
||||
{
|
||||
var randomFill = prototype.PickRandomFill(random);
|
||||
|
||||
IoCManager.Resolve(ref random);
|
||||
|
||||
var sum = randomFill.Reagents.Count;
|
||||
var accumulated = 0f;
|
||||
|
||||
var rand = random.NextFloat() * sum;
|
||||
|
||||
foreach (var reagent in randomFill.Reagents)
|
||||
{
|
||||
accumulated += 1f;
|
||||
|
||||
if (accumulated >= rand)
|
||||
{
|
||||
return (reagent, randomFill.Quantity);
|
||||
}
|
||||
}
|
||||
|
||||
// Shouldn't happen
|
||||
throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!");
|
||||
}
|
||||
|
||||
public static RandomFillSolution PickRandomFill(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null)
|
||||
{
|
||||
IoCManager.Resolve(ref random);
|
||||
|
||||
var fills = prototype.Fills;
|
||||
Dictionary<RandomFillSolution, float> picks = new();
|
||||
|
||||
foreach (var fill in fills)
|
||||
{
|
||||
picks[fill] = fill.Weight;
|
||||
}
|
||||
|
||||
var sum = picks.Values.Sum();
|
||||
var accumulated = 0f;
|
||||
|
||||
var rand = random.NextFloat() * sum;
|
||||
|
||||
foreach (var (randSolution, weight) in picks)
|
||||
{
|
||||
accumulated += weight;
|
||||
|
||||
if (accumulated >= rand)
|
||||
{
|
||||
return randSolution;
|
||||
}
|
||||
}
|
||||
|
||||
// Shouldn't happen
|
||||
throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
33
Content.Shared/Random/RandomFillSolution.cs
Normal file
33
Content.Shared/Random/RandomFillSolution.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Random;
|
||||
|
||||
/// <summary>
|
||||
/// Data that specifies reagents that share the same weight and quantity for use with WeightedRandomSolution.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
[DataDefinition]
|
||||
public sealed class RandomFillSolution
|
||||
{
|
||||
/// <summary>
|
||||
/// Quantity of listed reagents.
|
||||
/// </summary>
|
||||
[DataField("quantity")]
|
||||
public FixedPoint2 Quantity = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Random weight of listed reagents.
|
||||
/// </summary>
|
||||
[DataField("weight")]
|
||||
public float Weight = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Listed reagents that the weight and quantity apply to.
|
||||
/// </summary>
|
||||
[DataField("reagents", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<ReagentPrototype>))]
|
||||
public List<string> Reagents = new();
|
||||
}
|
||||
18
Content.Shared/Random/WeightedRandomFillSolutionPrototype.cs
Normal file
18
Content.Shared/Random/WeightedRandomFillSolutionPrototype.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Random;
|
||||
|
||||
/// <summary>
|
||||
/// Random weighting dataset for solutions, able to specify reagents quantity.
|
||||
/// </summary>
|
||||
[Prototype("weightedRandomFillSolution")]
|
||||
public sealed class WeightedRandomFillSolutionPrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// List of RandomFills that can be picked from.
|
||||
/// </summary>
|
||||
[DataField("fills", required: true)]
|
||||
public List<RandomFillSolution> Fills = new();
|
||||
}
|
||||
@@ -42,6 +42,7 @@ flavor-base-cheap = cheap
|
||||
flavor-base-piquant = piquant
|
||||
flavor-base-sharp = sharp
|
||||
flavor-base-syrupy = syrupy
|
||||
flavor-base-spaceshroom = mysterious
|
||||
|
||||
# lmao
|
||||
flavor-base-terrible = terrible
|
||||
@@ -145,6 +146,7 @@ flavor-complex-electrons = like electrons
|
||||
flavor-complex-parents = like someone's parents
|
||||
flavor-complex-plastic = like plastic
|
||||
flavor-complex-glue = like glue
|
||||
flavor-complex-spaceshroom-cooked = like space umami
|
||||
|
||||
# Drink-specific flavors.
|
||||
|
||||
|
||||
@@ -131,3 +131,20 @@
|
||||
- ClothingEyesBlindfold
|
||||
chance: 0.6
|
||||
offset: 0.0
|
||||
|
||||
- type: entity
|
||||
name: Maint Loot Spawner
|
||||
suffix: Plants
|
||||
id: MaintenancePlantSpawner
|
||||
parent: MarkerBase
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: red
|
||||
- sprite: Objects/Misc/spaceshroom.rsi
|
||||
state: spaceshroom
|
||||
- type: RandomSpawner
|
||||
prototypes:
|
||||
- FoodSpaceshroom
|
||||
chance: 0.6
|
||||
offset: 0.0
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
- type: Polymorphable
|
||||
- type: Identity
|
||||
- type: Hands
|
||||
- type: GatheringTool
|
||||
damage:
|
||||
types:
|
||||
Structural: 50
|
||||
- type: MovementSpeedModifier
|
||||
- type: MovedByPressure
|
||||
- type: Barotrauma
|
||||
|
||||
123
Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml
Normal file
123
Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
- type: entity
|
||||
name: spaceshroom
|
||||
parent: BaseStructure
|
||||
id: Spaceshroom
|
||||
suffix: Structure
|
||||
description: A cluster of wild mushrooms that likes to grow in dark, moist environments.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/spaceshroom.rsi
|
||||
state: structure
|
||||
- type: Transform
|
||||
anchored: true
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.2
|
||||
- type: InteractionOutline
|
||||
# TODO: Nuke this shit
|
||||
- type: OreVein
|
||||
oreChance: 1.0
|
||||
currentOre: SpaceShrooms
|
||||
- type: Gatherable
|
||||
whitelist:
|
||||
components:
|
||||
- Hands
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Wood
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 150
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
|
||||
- type: entity
|
||||
name: spaceshroom
|
||||
parent: FoodProduceBase
|
||||
id: FoodSpaceshroom
|
||||
description: A wild mushroom. There's no telling what effect it could have...
|
||||
components:
|
||||
- type: Produce
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/spaceshroom.rsi
|
||||
state: object
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- spaceshroom
|
||||
- type: Extractable
|
||||
juiceSolution:
|
||||
reagents:
|
||||
- ReagentId: SpaceDrugs
|
||||
Quantity: 10
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
maxVol: 20
|
||||
reagents:
|
||||
- ReagentId: Nutriment
|
||||
Quantity: 3
|
||||
- ReagentId: Vitamin
|
||||
Quantity: 2
|
||||
- type: RandomFillSolution
|
||||
solution: food
|
||||
weightedRandomId: RandomFillSpaceshroom
|
||||
- type: StaticPrice
|
||||
price: 20
|
||||
|
||||
- type: weightedRandomFillSolution
|
||||
id: RandomFillSpaceshroom
|
||||
fills:
|
||||
- quantity: 10
|
||||
weight: 10
|
||||
reagents:
|
||||
- SpaceDrugs
|
||||
- quantity: 0
|
||||
weight: 5
|
||||
reagents:
|
||||
- Water
|
||||
- quantity: 10
|
||||
weight: 3
|
||||
reagents:
|
||||
- Ephedrine
|
||||
- quantity: 10
|
||||
weight: 1
|
||||
reagents:
|
||||
- Lexorin
|
||||
- quantity: 15
|
||||
weight: 1
|
||||
reagents:
|
||||
- Amatoxin
|
||||
|
||||
# Cooked Object
|
||||
- type: entity
|
||||
name: cooked spaceshroom
|
||||
parent: FoodProduceBase
|
||||
id: FoodSpaceshroomCooked
|
||||
description: A wild mushroom that has been cooked through. It seems the heat has removed its chemical effects.
|
||||
components:
|
||||
- type: FlavorProfile
|
||||
flavors:
|
||||
- spaceshroomcooked
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
maxVol: 15
|
||||
reagents:
|
||||
- ReagentId: Nutriment
|
||||
Quantity: 10
|
||||
- ReagentId: Vitamin
|
||||
Quantity: 5
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/spaceshroom.rsi
|
||||
state: spaceshroom_cooked
|
||||
- type: Produce
|
||||
- type: StaticPrice
|
||||
price: 40
|
||||
@@ -1,38 +1,46 @@
|
||||
- type: weightedRandom
|
||||
- type: weightedRandomFillSolution
|
||||
id: RandomFillStrangePill
|
||||
weights:
|
||||
# Elements
|
||||
Aluminium: 1
|
||||
Carbon: 1
|
||||
Chlorine: 1
|
||||
Copper: 1
|
||||
Fluorine: 1
|
||||
Hydrogen: 1
|
||||
Iodine: 1
|
||||
Lithium: 1
|
||||
Mercury: 1
|
||||
Potassium: 1
|
||||
Phosphorus: 1
|
||||
Radium: 1
|
||||
Silicon: 1
|
||||
Sulfur: 1
|
||||
Sodium: 1
|
||||
# Medicines
|
||||
Ipecac: 3
|
||||
Omnizine: 2
|
||||
Tricordrazine: 3
|
||||
# Narcotics
|
||||
Desoxyephedrine: 3
|
||||
Ephedrine: 3
|
||||
SpaceDrugs: 5
|
||||
Nocturine: 3
|
||||
MuteToxin: 3
|
||||
NorepinephricAcid: 3
|
||||
# Toxins
|
||||
ChloralHydrate: 3
|
||||
Mold: 3
|
||||
Pax: 3
|
||||
Toxin: 5
|
||||
fills:
|
||||
- quantity: 20
|
||||
weight: 1
|
||||
reagents:
|
||||
- Aluminium
|
||||
- Carbon
|
||||
- Chlorine
|
||||
- Copper
|
||||
- Fluorine
|
||||
- Hydrogen
|
||||
- Iodine
|
||||
- Lithium
|
||||
- Mercury
|
||||
- Potassium
|
||||
- Phosphorus
|
||||
- Radium
|
||||
- Silicon
|
||||
- Sulfur
|
||||
- Sodium
|
||||
- quantity: 20
|
||||
weight: 2
|
||||
reagents:
|
||||
- Omnizine
|
||||
- quantity: 20
|
||||
weight: 3
|
||||
reagents:
|
||||
- ChloralHydrate
|
||||
- Desoxyephedrine
|
||||
- Ephedrine
|
||||
- Ipecac
|
||||
- Mold
|
||||
- MuteToxin
|
||||
- Nocturine
|
||||
- NorepinephricAcid
|
||||
- Pax
|
||||
- Tricordrazine
|
||||
- quantity: 20
|
||||
weight: 5
|
||||
reagents:
|
||||
- SpaceDrugs
|
||||
- Toxin
|
||||
|
||||
- type: entity
|
||||
name: strange pill
|
||||
@@ -47,7 +55,6 @@
|
||||
- type: RandomFillSolution
|
||||
solution: food
|
||||
weightedRandomId: RandomFillStrangePill
|
||||
quantity: 20
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Chemistry/pills.rsi
|
||||
layers:
|
||||
|
||||
@@ -823,3 +823,13 @@
|
||||
id: rocksandstones
|
||||
flavorType: Complex
|
||||
description: flavor-complex-rocksandstones
|
||||
|
||||
- type: flavor
|
||||
id: spaceshroom
|
||||
flavorType: Base
|
||||
description: flavor-base-spaceshroom
|
||||
|
||||
- type: flavor
|
||||
id: spaceshroomcooked
|
||||
flavorType: Complex
|
||||
description: flavor-complex-spaceshroom-cooked
|
||||
@@ -1632,3 +1632,11 @@
|
||||
solids:
|
||||
FoodChevreSlice: 1
|
||||
FoodBreadBaguetteSlice: 1
|
||||
|
||||
- type: microwaveMealRecipe
|
||||
id: RecipeCookedSpaceshroom
|
||||
name: cooked spaceshroom recipe
|
||||
result: FoodSpaceshroomCooked
|
||||
time: 5
|
||||
solids:
|
||||
FoodSpaceshroom: 1
|
||||
@@ -1,3 +1,10 @@
|
||||
# TODO: Kill ore veins
|
||||
# Split it into 2 components, 1 for "spawn XYZ on destruction" and 1 for "randomly select one of these for spawn on destruction"
|
||||
# You could even just use an entityspawncollection instead.
|
||||
- type: ore
|
||||
id: SpaceShrooms
|
||||
oreEntity: FoodSpaceshroom
|
||||
|
||||
# High yields
|
||||
- type: ore
|
||||
id: OreSteel
|
||||
|
||||
20
Resources/Textures/Objects/Misc/spaceshroom.rsi/meta.json
Normal file
20
Resources/Textures/Objects/Misc/spaceshroom.rsi/meta.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC0-1.0",
|
||||
"copyright": "Created by @UbaserB (GitHub)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "object"
|
||||
},
|
||||
{
|
||||
"name": "spaceshroom_cooked"
|
||||
},
|
||||
{
|
||||
"name": "structure"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Resources/Textures/Objects/Misc/spaceshroom.rsi/object.png
Normal file
BIN
Resources/Textures/Objects/Misc/spaceshroom.rsi/object.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
Resources/Textures/Objects/Misc/spaceshroom.rsi/structure.png
Normal file
BIN
Resources/Textures/Objects/Misc/spaceshroom.rsi/structure.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Reference in New Issue
Block a user