Add Spaceshrooms (#17092)

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
forthbridge
2023-08-01 22:10:48 +08:00
committed by GitHub
parent 474b29cc16
commit 5fc7f21853
18 changed files with 369 additions and 54 deletions

View File

@@ -1,5 +1,4 @@
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using Content.Shared.Random; using Content.Shared.Random;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
@@ -18,14 +17,8 @@ public sealed class RandomFillSolutionComponent : Component
public string Solution { get; set; } = "default"; public string Solution { get; set; } = "default";
/// <summary> /// <summary>
/// Weighted random prototype Id. Used to pick reagent. /// Weighted random fill prototype Id. Used to pick reagent and quantity.
/// </summary> /// </summary>
[DataField("weightedRandomId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomPrototype>))] [DataField("weightedRandomId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomFillSolutionPrototype>))]
public string WeightedRandomId { get; set; } = "default"; public string WeightedRandomId { get; set; } = "default";
/// <summary>
/// Amount of reagent to add.
/// </summary>
[DataField("quantity")]
public FixedPoint2 Quantity { get; set; } = 0;
} }

View File

@@ -20,18 +20,20 @@ public sealed class SolutionRandomFillSystem : EntitySystem
SubscribeLocalEvent<RandomFillSolutionComponent, MapInitEvent>(OnRandomSolutionFillMapInit); 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 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( Log.Error($"Tried to add invalid reagent Id {reagent} using SolutionRandomFill.");
$"Tried to add invalid reagent Id {reagent} using SolutionRandomFill.");
return; return;
} }
target.AddReagent(reagent, component.Quantity); target.AddReagent(reagent, quantity);
} }
} }

View File

@@ -25,25 +25,29 @@ public sealed partial class GatherableSystem : EntitySystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<GatherableComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<GatherableComponent, InteractUsingEvent>(OnInteractUsing); SubscribeLocalEvent<GatherableComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<GatherableComponent, GatherableDoAfterEvent>(OnDoAfter); SubscribeLocalEvent<GatherableComponent, GatherableDoAfterEvent>(OnDoAfter);
InitializeProjectile(); 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 (!TryComp<GatheringToolComponent>(args.Used, out var tool) || component.ToolWhitelist?.IsValid(args.Used) == false) if (!Resolve(used, ref tool, false) || !Resolve(gatheredUid, ref component, false) ||
component.ToolWhitelist?.IsValid(used) == false)
{
return; return;
}
// Can't gather too many entities at once. // Can't gather too many entities at once.
if (tool.MaxGatheringEntities < tool.GatheringEntities.Count + 1) if (tool.MaxGatheringEntities < tool.GatheringEntities.Count + 1)
return; return;
var damageRequired = _destructible.DestroyedAt(uid); var damageRequired = _destructible.DestroyedAt(gatheredUid);
var damageTime = (damageRequired / tool.Damage.Total).Float(); var damageTime = (damageRequired / tool.Damage.Total).Float();
damageTime = Math.Max(1f, damageTime); 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, BreakOnDamage = true,
BreakOnTargetMove = true, BreakOnTargetMove = true,
@@ -54,6 +58,16 @@ public sealed partial class GatherableSystem : EntitySystem
_doAfterSystem.TryStartDoAfter(doAfter); _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) private void OnDoAfter(EntityUid uid, GatherableComponent component, GatherableDoAfterEvent args)
{ {
if(!TryComp<GatheringToolComponent>(args.Args.Used, out var tool)) if(!TryComp<GatheringToolComponent>(args.Args.Used, out var tool))

View File

@@ -1,5 +1,6 @@
using System.Linq; using System.Linq;
using Content.Shared.Dataset; using Content.Shared.Dataset;
using Content.Shared.FixedPoint;
using Robust.Shared.Random; using Robust.Shared.Random;
namespace Content.Shared.Random.Helpers namespace Content.Shared.Random.Helpers
@@ -75,5 +76,61 @@ namespace Content.Shared.Random.Helpers
throw new InvalidOperationException($"Invalid weighted pick"); 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}!");
}
} }
} }

View 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();
}

View 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();
}

View File

@@ -42,6 +42,7 @@ flavor-base-cheap = cheap
flavor-base-piquant = piquant flavor-base-piquant = piquant
flavor-base-sharp = sharp flavor-base-sharp = sharp
flavor-base-syrupy = syrupy flavor-base-syrupy = syrupy
flavor-base-spaceshroom = mysterious
# lmao # lmao
flavor-base-terrible = terrible flavor-base-terrible = terrible
@@ -145,6 +146,7 @@ flavor-complex-electrons = like electrons
flavor-complex-parents = like someone's parents flavor-complex-parents = like someone's parents
flavor-complex-plastic = like plastic flavor-complex-plastic = like plastic
flavor-complex-glue = like glue flavor-complex-glue = like glue
flavor-complex-spaceshroom-cooked = like space umami
# Drink-specific flavors. # Drink-specific flavors.

View File

@@ -131,3 +131,20 @@
- ClothingEyesBlindfold - ClothingEyesBlindfold
chance: 0.6 chance: 0.6
offset: 0.0 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

View File

@@ -34,6 +34,10 @@
- type: Polymorphable - type: Polymorphable
- type: Identity - type: Identity
- type: Hands - type: Hands
- type: GatheringTool
damage:
types:
Structural: 50
- type: MovementSpeedModifier - type: MovementSpeedModifier
- type: MovedByPressure - type: MovedByPressure
- type: Barotrauma - type: Barotrauma

View 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

View File

@@ -1,38 +1,46 @@
- type: weightedRandom - type: weightedRandomFillSolution
id: RandomFillStrangePill id: RandomFillStrangePill
weights: fills:
# Elements - quantity: 20
Aluminium: 1 weight: 1
Carbon: 1 reagents:
Chlorine: 1 - Aluminium
Copper: 1 - Carbon
Fluorine: 1 - Chlorine
Hydrogen: 1 - Copper
Iodine: 1 - Fluorine
Lithium: 1 - Hydrogen
Mercury: 1 - Iodine
Potassium: 1 - Lithium
Phosphorus: 1 - Mercury
Radium: 1 - Potassium
Silicon: 1 - Phosphorus
Sulfur: 1 - Radium
Sodium: 1 - Silicon
# Medicines - Sulfur
Ipecac: 3 - Sodium
Omnizine: 2 - quantity: 20
Tricordrazine: 3 weight: 2
# Narcotics reagents:
Desoxyephedrine: 3 - Omnizine
Ephedrine: 3 - quantity: 20
SpaceDrugs: 5 weight: 3
Nocturine: 3 reagents:
MuteToxin: 3 - ChloralHydrate
NorepinephricAcid: 3 - Desoxyephedrine
# Toxins - Ephedrine
ChloralHydrate: 3 - Ipecac
Mold: 3 - Mold
Pax: 3 - MuteToxin
Toxin: 5 - Nocturine
- NorepinephricAcid
- Pax
- Tricordrazine
- quantity: 20
weight: 5
reagents:
- SpaceDrugs
- Toxin
- type: entity - type: entity
name: strange pill name: strange pill
@@ -47,7 +55,6 @@
- type: RandomFillSolution - type: RandomFillSolution
solution: food solution: food
weightedRandomId: RandomFillStrangePill weightedRandomId: RandomFillStrangePill
quantity: 20
- type: Sprite - type: Sprite
sprite: Objects/Specific/Chemistry/pills.rsi sprite: Objects/Specific/Chemistry/pills.rsi
layers: layers:

View File

@@ -823,3 +823,13 @@
id: rocksandstones id: rocksandstones
flavorType: Complex flavorType: Complex
description: flavor-complex-rocksandstones 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

View File

@@ -1632,3 +1632,11 @@
solids: solids:
FoodChevreSlice: 1 FoodChevreSlice: 1
FoodBreadBaguetteSlice: 1 FoodBreadBaguetteSlice: 1
- type: microwaveMealRecipe
id: RecipeCookedSpaceshroom
name: cooked spaceshroom recipe
result: FoodSpaceshroomCooked
time: 5
solids:
FoodSpaceshroom: 1

View File

@@ -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 # High yields
- type: ore - type: ore
id: OreSteel id: OreSteel

View 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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB