Give some love to farming (#1124)

* give some love to farming

* Queryptimization

* Fuck soil!!!

* fuck soil in prototypes!

* seeds improve

* partial merge wild and farm

* some strange fix

* plant kills refactor, add compost

* fix compost

* Update migration.yml

* rain can watering plants

* sage update

* Update seeds.yml

* sage smoking update

* Update seeds.yml
This commit is contained in:
Ed
2025-04-03 15:29:08 +03:00
committed by GitHub
parent 16c4f8be53
commit 48831380b4
98 changed files with 1143 additions and 1322 deletions

View File

@@ -1,4 +1,5 @@
using Content.Shared._CP14.Farming;
using Content.Shared._CP14.Farming.Components;
using Content.Shared.Rounding;
using Robust.Client.GameObjects;
@@ -32,7 +33,7 @@ public sealed class ClientCP14FarmingSystem : CP14SharedFarmingSystem
if (!TryComp<SpriteComponent>(visuals, out var sprite))
return;
if (!TryComp<CP14PlantComponent>(visuals, out var plant))
if (!PlantQuery.TryComp(visuals, out var plant))
return;
var growthState = ContentHelpers.RoundToNearestLevels(plant.GrowthLevel, 1, visuals.Comp.GrowthSteps);

View File

@@ -89,13 +89,6 @@ public sealed class InjectorSystem : SharedInjectorSystem
if (args.Target is not { Valid: true } target || !HasComp<SolutionContainerManagerComponent>(entity))
return;
//CP14 - Shitcode retarget plant -> soil
//TODO: fix it
if (TryComp<CP14PlantComponent>(args.Target, out var plant) && plant.SoilUid is not null)
target = plant.SoilUid.Value;
//CP14 - end shitcode
// Is the target a mob? If yes, use a do-after to give them time to respond.
if (HasComp<MobStateComponent>(target) || HasComp<BloodstreamComponent>(target))
{

View File

@@ -1,5 +1,6 @@
using System.Text;
using Content.Shared._CP14.Farming;
using Content.Shared._CP14.Farming.Components;
using Content.Shared.EntityEffects;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;

View File

@@ -1,156 +0,0 @@
using Content.Server._CP14.Farming.Components;
using Content.Server.Gatherable.Components;
using Content.Shared._CP14.Farming;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Weapons.Melee.Events;
namespace Content.Server._CP14.Farming;
public sealed partial class CP14FarmingSystem
{
private void InitializeInteractions()
{
SubscribeLocalEvent<CP14SeedComponent, AfterInteractEvent>(OnSeedInteract);
SubscribeLocalEvent<CP14PlantGatherableComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<CP14PlantGatherableComponent, AttackedEvent>(OnAttacked);
SubscribeLocalEvent<CP14SoilComponent, PlantSeedDoAfterEvent>(OnSeedPlantedDoAfter);
}
private void OnAttacked(Entity<CP14PlantGatherableComponent> gatherable, ref AttackedEvent args)
{
if (_whitelist.IsWhitelistFailOrNull(gatherable.Comp.ToolWhitelist, args.Used))
return;
TryHarvestPlant(gatherable, out _);
}
private void OnActivate(Entity<CP14PlantGatherableComponent> gatherable, ref ActivateInWorldEvent args)
{
if (args.Handled || !args.Complex)
return;
if (_whitelist.IsWhitelistFailOrNull(gatherable.Comp.ToolWhitelist, args.User))
return;
TryHarvestPlant(gatherable, out _);
args.Handled = true;
}
public bool TryHarvestPlant(Entity<CP14PlantGatherableComponent> gatheredPlant, out HashSet<EntityUid> result, EntityUid? gatherer = null)
{
result = new();
if (!TryComp<CP14PlantComponent>(gatheredPlant, out var plant))
return false;
if (plant.GrowthLevel < gatheredPlant.Comp.GrowthLevelToHarvest)
return false;
if (TryComp<SoundOnGatherComponent>(gatheredPlant, out var soundComp))
{
_audio.PlayPvs(soundComp.Sound, Transform(gatheredPlant).Coordinates);
}
if (gatheredPlant.Comp.Loot == null)
return false;
var pos = _transform.GetMapCoordinates(gatheredPlant);
foreach (var (tag, table) in gatheredPlant.Comp.Loot)
{
if (tag != "All")
{
if (gatherer != null && !_tag.HasTag(gatherer.Value, tag))
continue;
}
if (!_proto.TryIndex(table, out var getLoot))
continue;
var spawnLoot = getLoot.GetSpawns(_random);
foreach (var loot in spawnLoot)
{
var spawnPos = pos.Offset(_random.NextVector2(gatheredPlant.Comp.GatherOffset));
result.Add(Spawn(loot, spawnPos));
}
}
if (gatheredPlant.Comp.DeleteAfterHarvest)
_destructible.DestroyEntity(gatheredPlant);
else
AffectGrowth((gatheredPlant, plant), -gatheredPlant.Comp.GrowthCostHarvest);
return true;
}
private void OnSeedInteract(Entity<CP14SeedComponent> seed, ref AfterInteractEvent args)
{
if (args.Handled)
return;
if (!TryComp<CP14SoilComponent>(args.Target, out var soil))
return;
if (EntityManager.EntityExists(soil.PlantUid))
{
_popup.PopupEntity(Loc.GetString("cp14-farming-soil-interact-plant-exist"), args.Target.Value, args.User);
return;
}
var doAfterArgs =
new DoAfterArgs(EntityManager, args.User, seed.Comp.PlantingTime, new PlantSeedDoAfterEvent(), args.Target, args.Used, args.Target)
{
BreakOnDamage = true,
BlockDuplicate = true,
BreakOnMove = true,
BreakOnHandChange = true,
};
_doAfter.TryStartDoAfter(doAfterArgs);
args.Handled = true;
}
public bool TryPlantSeed(EntityUid seed, EntityUid soil, EntityUid? user)
{
if (!TryComp<CP14SoilComponent>(soil, out var soilComp))
return false;
if (!TryComp<CP14SeedComponent>(seed, out var seedComp))
return false;
if (Exists(soilComp.PlantUid))
{
if (user is not null)
_popup.PopupEntity(Loc.GetString("cp14-farming-soil-interact-plant-exist"), soil, user.Value);
return false;
}
var plant = SpawnAttachedTo(seedComp.PlantProto, Transform(soil).Coordinates);
if (!TryComp<CP14PlantComponent>(plant, out var plantComp))
return false;
_transform.SetParent(plant, soil);
soilComp.PlantUid = plant;
plantComp.SoilUid = soil;
return true;
}
private void OnSeedPlantedDoAfter(Entity<CP14SoilComponent> soil, ref PlantSeedDoAfterEvent args)
{
if (args.Cancelled || args.Handled || args.Args.Used == null || args.Target == null)
return;
if (!TryPlantSeed(args.Target.Value, soil, args.User))
return;
//Audio
QueueDel(args.Target); //delete seed
args.Handled = true;
}
}

View File

@@ -1,5 +1,4 @@
using Content.Server._CP14.Farming.Components;
using Content.Shared._CP14.Farming;
using Content.Shared._CP14.Farming.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
namespace Content.Server._CP14.Farming;
@@ -11,13 +10,20 @@ public sealed partial class CP14FarmingSystem
SubscribeLocalEvent<CP14PlantEnergyFromLightComponent, CP14PlantUpdateEvent>(OnTakeEnergyFromLight);
SubscribeLocalEvent<CP14PlantMetabolizerComponent, CP14PlantUpdateEvent>(OnPlantMetabolizing);
SubscribeLocalEvent<CP14PlantFadingComponent, CP14PlantUpdateEvent>(OnPlantFade);
SubscribeLocalEvent<CP14PlantFadingComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<CP14PlantGrowingComponent, CP14AfterPlantUpdateEvent>(OnPlantGrowing);
}
private void OnMapInit(Entity<CP14PlantFadingComponent> ent, ref MapInitEvent args)
{
ent.Comp.BirthTime = _timing.CurTime;
}
private void OnPlantFade(Entity<CP14PlantFadingComponent> ent, ref CP14PlantUpdateEvent args)
{
var realFade = ent.Comp.ResourcePerMinute * (float)args.Plant.Comp.Age.TotalMinutes;
var age = _timing.CurTime - ent.Comp.BirthTime;
var realFade = ent.Comp.ResourcePerMinute * (float)age.TotalMinutes;
if (args.Plant.Comp.Resource < realFade)
{
_damageable.TryChangeDamage(ent, ent.Comp.FadeDamage, true);
@@ -59,14 +65,12 @@ public sealed partial class CP14FarmingSystem
private void OnPlantMetabolizing(Entity<CP14PlantMetabolizerComponent> ent, ref CP14PlantUpdateEvent args)
{
if (args.Plant.Comp.SoilUid == null ||
!TryComp<CP14SoilComponent>(args.Plant.Comp.SoilUid, out var soil) ||
!TryComp<CP14PlantComponent>(ent, out var plant) ||
!TryComp<SolutionContainerManagerComponent>(args.Plant.Comp.SoilUid, out var solmanager))
if (!PlantQuery.TryComp(ent, out var plant) ||
!SolutionQuery.TryComp(args.Plant, out var solmanager))
return;
var solEntity = new Entity<SolutionContainerManagerComponent?>(args.Plant.Comp.SoilUid.Value, solmanager);
if (!_solutionContainer.TryGetSolution(solEntity, soil.Solution, out var soln, out var solution))
var solEntity = new Entity<SolutionContainerManagerComponent?>(args.Plant, solmanager);
if (!_solutionContainer.TryGetSolution(solEntity, plant.Solution, out var soln, out _))
return;
if (!_proto.TryIndex(ent.Comp.MetabolizerId, out var metabolizer))

View File

@@ -1,17 +1,7 @@
using Content.Server._CP14.Farming.Components;
using Content.Server.Destructible;
using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Shared._CP14.Farming;
using Content.Shared._CP14.Farming.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Tag;
using Content.Shared.Examine;
using Content.Shared.Whitelist;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -20,31 +10,19 @@ namespace Content.Server._CP14.Farming;
public sealed partial class CP14FarmingSystem : CP14SharedFarmingSystem
{
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly DestructibleSystem _destructible = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
public override void Initialize()
{
base.Initialize();
InitializeInteractions();
InitializeResources();
SubscribeLocalEvent<CP14PlantComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<CP14PlantComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<CP14PlantAutoRootComponent, MapInitEvent>(OnAutoRootMapInit);
SubscribeLocalEvent<CP14PlantComponent, ExaminedEvent>(OnExamine);
}
public override void Update(float frameTime)
@@ -59,7 +37,6 @@ public sealed partial class CP14FarmingSystem : CP14SharedFarmingSystem
var newTime = _random.NextFloat(plant.UpdateFrequency);
plant.NextUpdateTime = _timing.CurTime + TimeSpan.FromSeconds(newTime);
plant.Age += TimeSpan.FromSeconds(plant.UpdateFrequency);
var ev = new CP14PlantUpdateEvent((uid, plant));
RaiseLocalEvent(uid, ev);
@@ -74,51 +51,9 @@ public sealed partial class CP14FarmingSystem : CP14SharedFarmingSystem
}
}
private void OnUnpaused(Entity<CP14PlantComponent> ent, ref EntityUnpausedEvent args)
{
ent.Comp.NextUpdateTime += args.PausedTime;
}
private void OnMapInit(Entity<CP14PlantComponent> plant, ref MapInitEvent args)
{
var newTime = _random.NextFloat(plant.Comp.UpdateFrequency);
plant.Comp.NextUpdateTime = _timing.CurTime + TimeSpan.FromSeconds(newTime);
}
private void OnExamine(EntityUid uid, CP14PlantComponent component, ExaminedEvent args)
{
if (component.Energy <= 0)
args.PushMarkup(Loc.GetString("cp14-farming-low-energy"));
if (component.Resource <= 0)
args.PushMarkup(Loc.GetString("cp14-farming-low-resources"));
}
private void OnAutoRootMapInit(Entity<CP14PlantAutoRootComponent> autoRoot, ref MapInitEvent args)
{
var grid = Transform(autoRoot).GridUid;
if (grid == null || !TryComp<MapGridComponent>(grid, out var gridComp))
return;
var targetPos = new EntityCoordinates(grid.Value,Transform(autoRoot).LocalPosition);
var anchored = _map.GetAnchoredEntities(grid.Value, gridComp, targetPos);
foreach (var entt in anchored)
{
if (!TryComp<CP14SoilComponent>(entt, out var soil))
continue;
//Generally, this SHOULD change the parent, but it made the entity unanchored, which caused a bugs: hammer hits could push plants around
//_transform.SetParent(autoRoot, entt);
soil.PlantUid = autoRoot;
if (TryComp<CP14PlantComponent>(autoRoot, out var plantComp))
{
plantComp.SoilUid = entt;
}
break;
}
}
}

View File

@@ -1,9 +0,0 @@
namespace Content.Server._CP14.Farming.Components;
/// <summary>
/// when it init, it automatically attaches itself by its roots to the soil beneath it.
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
public sealed partial class CP14PlantAutoRootComponent : Component
{
}

View File

@@ -1,16 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.Farming.Components;
/// <summary>
/// a component that allows for the creation of the plant entity on the soil
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
public sealed partial class CP14SeedComponent : Component
{
[DataField]
public TimeSpan PlantingTime = TimeSpan.FromSeconds(2f);
[DataField(required: true)]
public EntProtoId PlantProto;
}

View File

@@ -1,13 +0,0 @@
namespace Content.Server._CP14.Farming.Components;
/// <summary>
/// a component that provides a link to a liquid storage that can be used by the plant
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
public sealed partial class CP14SoilComponent : Component
{
[DataField(required: true)]
public string Solution = string.Empty;
public EntityUid? PlantUid;
}

View File

@@ -1,75 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared._CP14.Farming;
/// <summary>
/// The backbone of any plant. Provides common variables for the plant to other components, and a link to the soil
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14PlantComponent : Component
{
/// <summary>
/// Soil link. May be null, as not all plants in the world grow on entity soil (e.g. wild shrubs)
/// </summary>
public EntityUid? SoilUid;
/// <summary>
/// The ability to consume a resource for growing
/// </summary>
[DataField]
public float Energy = 0f;
[DataField]
public float EnergyMax = 100f;
/// <summary>
/// resource consumed for growth
/// </summary>
[DataField]
public float Resource = 0f;
[DataField]
public float ResourceMax = 100f;
/// <summary>
/// Plant growth status, 0 to 1
/// </summary>
[DataField, AutoNetworkedField]
public float GrowthLevel = 0f;
[DataField(serverOnly: true)]
public float UpdateFrequency = 60f;
[DataField(serverOnly: true)]
public TimeSpan NextUpdateTime = TimeSpan.Zero;
[DataField(serverOnly: true)]
public TimeSpan Age = TimeSpan.Zero;
}
/// <summary>
/// Is called periodically at random intervals on the plant.
/// </summary>
public sealed class CP14PlantUpdateEvent : EntityEventArgs
{
public readonly Entity<CP14PlantComponent> Plant;
public float EnergyDelta = 0f;
public float ResourceDelta = 0f;
public CP14PlantUpdateEvent(Entity<CP14PlantComponent> comp)
{
Plant = comp;
}
}
/// <summary>
/// is called after CP14PlantUpdateEvent when all value changes have already been calculated.
/// </summary>
public sealed class CP14AfterPlantUpdateEvent : EntityEventArgs
{
public readonly Entity<CP14PlantComponent> Plant;
public CP14AfterPlantUpdateEvent(Entity<CP14PlantComponent> comp)
{
Plant = comp;
}
}

View File

@@ -0,0 +1,216 @@
using System.Linq;
using Content.Shared._CP14.Farming.Components;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Maps;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
namespace Content.Shared._CP14.Farming;
public abstract partial class CP14SharedFarmingSystem
{
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
private void InitializeInteractions()
{
SubscribeLocalEvent<CP14SeedComponent, AfterInteractEvent>(OnSeedInteract);
SubscribeLocalEvent<CP14PlantGatherableComponent, InteractUsingEvent>(OnActivate);
SubscribeLocalEvent<CP14PlantGatherableComponent, CP14PlantGatherDoAfterEvent>(OnGatherDoAfter);
SubscribeLocalEvent<CP14SeedComponent, CP14PlantSeedDoAfterEvent>(OnSeedPlantedDoAfter);
}
private void OnActivate(Entity<CP14PlantGatherableComponent> gatherable, ref InteractUsingEvent args)
{
if (args.Handled)
return;
if (_whitelist.IsWhitelistFailOrNull(gatherable.Comp.ToolWhitelist, args.Used))
return;
TryHarvestPlant(gatherable, args.Used, args.User);
args.Handled = true;
}
private bool CanHarvestPlant(Entity<CP14PlantGatherableComponent> gatherable)
{
if (PlantQuery.TryComp(gatherable, out var plant))
{
if (plant.GrowthLevel < gatherable.Comp.GrowthLevelToHarvest)
return false;
}
if (gatherable.Comp.Loot == null)
return false;
return true;
}
private bool TryHarvestPlant(Entity<CP14PlantGatherableComponent> gatherable,
EntityUid used,
EntityUid user)
{
if (!CanHarvestPlant(gatherable))
return false;
_audio.PlayPvs(gatherable.Comp.GatherSound, Transform(gatherable).Coordinates);
var doAfterArgs =
new DoAfterArgs(EntityManager,
user,
gatherable.Comp.GatherDelay,
new CP14PlantGatherDoAfterEvent(),
gatherable,
used: used)
{
BreakOnDamage = true,
BlockDuplicate = false,
BreakOnMove = true,
BreakOnHandChange = true,
};
_doAfter.TryStartDoAfter(doAfterArgs);
return true;
}
private void OnGatherDoAfter(Entity<CP14PlantGatherableComponent> gatherable, ref CP14PlantGatherDoAfterEvent args)
{
if (args.Cancelled || args.Handled)
return;
if (!CanHarvestPlant(gatherable))
return;
args.Handled = true;
HarvestPlant(gatherable, out _, args.Used);
}
public void HarvestPlant(Entity<CP14PlantGatherableComponent> gatherable,
out HashSet<EntityUid> result,
EntityUid? used)
{
result = new();
if (_net.IsClient)
return;
if (gatherable.Comp.Loot == null)
return;
var pos = _transform.GetMapCoordinates(gatherable);
foreach (var (tag, table) in gatherable.Comp.Loot)
{
if (tag != "All")
{
if (used != null && !_tag.HasTag(used.Value, tag))
continue;
}
if (!_proto.TryIndex(table, out var getLoot))
continue;
var spawnLoot = getLoot.GetSpawns(_random);
foreach (var loot in spawnLoot)
{
var spawnPos = pos.Offset(_random.NextVector2(gatherable.Comp.GatherOffset));
result.Add(Spawn(loot, spawnPos));
}
}
_audio.PlayPvs(gatherable.Comp.GatherSound, Transform(gatherable).Coordinates);
if (gatherable.Comp.DeleteAfterHarvest)
_destructible.DestroyEntity(gatherable);
else
{
if (PlantQuery.TryComp(gatherable, out var plant))
{
AffectGrowth((gatherable, plant), -gatherable.Comp.GrowthCostHarvest);
}
}
}
private void OnSeedInteract(Entity<CP14SeedComponent> seed, ref AfterInteractEvent args)
{
if (args.Handled)
return;
if (!CanPlantSeed(seed, args.ClickLocation, args.User))
return;
var doAfterArgs =
new DoAfterArgs(EntityManager,
args.User,
seed.Comp.PlantingTime,
new CP14PlantSeedDoAfterEvent(GetNetCoordinates(args.ClickLocation)),
seed)
{
BreakOnDamage = true,
BlockDuplicate = false,
BreakOnMove = true,
BreakOnHandChange = true,
};
_doAfter.TryStartDoAfter(doAfterArgs);
args.Handled = true;
}
private void OnSeedPlantedDoAfter(Entity<CP14SeedComponent> ent, ref CP14PlantSeedDoAfterEvent args)
{
if (_net.IsClient || args.Handled || args.Cancelled)
return;
var position = GetCoordinates(args.Coordinates);
if (!CanPlantSeed(ent, position, args.User))
return;
args.Handled = true;
Spawn(ent.Comp.PlantProto, position);
QueueDel(ent);
}
public bool CanPlantSeed(Entity<CP14SeedComponent> seed, EntityCoordinates position, EntityUid? user)
{
var map = _transform.GetMap(position);
if (!TryComp<MapGridComponent>(map, out var gridComp))
return false;
var tileRef = position.GetTileRef();
if (tileRef is null)
return false;
var tile = tileRef.Value.Tile.GetContentTileDefinition();
if (!seed.Comp.SoilTile.Contains(tile))
{
if (user is not null && _timing.IsFirstTimePredicted && _net.IsClient)
{
_popup.PopupEntity(Loc.GetString("cp14-farming-soil-wrong", ("seed", MetaData(seed).EntityName)),
user.Value,
user.Value);
}
return false;
}
if (_map.GetAnchoredEntities((map.Value, gridComp), position).ToList().Count > 0)
{
if (user is not null)
_popup.PopupEntity(Loc.GetString("cp14-farming-soil-occupied"), user.Value, user.Value);
return false;
}
return true;
}
}

View File

@@ -1,16 +1,63 @@
using Content.Shared._CP14.Farming.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Destructible;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Content.Shared.Whitelist;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
namespace Content.Shared._CP14.Farming;
public abstract partial class CP14SharedFarmingSystem : EntitySystem
{
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedDestructibleSystem _destructible = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly IRobustRandom _random = default!;
protected EntityQuery<CP14PlantComponent> PlantQuery;
protected EntityQuery<CP14SeedComponent> SeedQuery;
protected EntityQuery<SolutionContainerManagerComponent> SolutionQuery;
public override void Initialize()
{
base.Initialize();
InitializeInteractions();
PlantQuery = GetEntityQuery<CP14PlantComponent>();
SeedQuery = GetEntityQuery<CP14SeedComponent>();
SolutionQuery = GetEntityQuery<SolutionContainerManagerComponent>();
SubscribeLocalEvent<CP14PlantComponent, ExaminedEvent>(OnExamine);
}
private void OnExamine(EntityUid uid, CP14PlantComponent component, ExaminedEvent args)
{
if (component.Energy <= 0)
args.PushMarkup(Loc.GetString("cp14-farming-low-energy"));
if (component.Resource <= 0)
args.PushMarkup(Loc.GetString("cp14-farming-low-resources"));
}
public void AffectEnergy(Entity<CP14PlantComponent> ent, float energyDelta)
{
if (energyDelta == 0)
return;
ent.Comp.Energy = MathHelper.Clamp(ent.Comp.Energy + energyDelta, 0, ent.Comp.EnergyMax);
Dirty(ent);
}
public void AffectResource(Entity<CP14PlantComponent> ent, float resourceDelta)
{
@@ -18,6 +65,7 @@ public abstract partial class CP14SharedFarmingSystem : EntitySystem
return;
ent.Comp.Resource = MathHelper.Clamp(ent.Comp.Resource + resourceDelta, 0, ent.Comp.ResourceMax);
Dirty(ent);
}
public void AffectGrowth(Entity<CP14PlantComponent> ent, float growthDelta)
@@ -29,9 +77,20 @@ public abstract partial class CP14SharedFarmingSystem : EntitySystem
Dirty(ent);
}
[Serializable, NetSerializable]
public sealed partial class CP14PlantSeedDoAfterEvent : DoAfterEvent
{
[DataField(required:true)]
public NetCoordinates Coordinates;
public CP14PlantSeedDoAfterEvent(NetCoordinates coordinates)
{
Coordinates = coordinates;
}
public override DoAfterEvent Clone() => this;
}
[Serializable, NetSerializable]
public sealed partial class PlantSeedDoAfterEvent : SimpleDoAfterEvent
{
}
public sealed partial class CP14PlantGatherDoAfterEvent : SimpleDoAfterEvent;
}

View File

@@ -0,0 +1,61 @@
using Robust.Shared.GameStates;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// The backbone of any plant. Provides common variables for the plant to other components
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause, AutoGenerateComponentState(true), Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14PlantComponent : Component
{
/// <summary>
/// The ability to consume a resource for growing
/// </summary>
[DataField, AutoNetworkedField]
public float Energy = 30f;
[DataField, AutoNetworkedField]
public float EnergyMax = 100f;
/// <summary>
/// resource consumed for growth
/// </summary>
[DataField, AutoNetworkedField]
public float Resource = 30f;
[DataField, AutoNetworkedField]
public float ResourceMax = 100f;
/// <summary>
/// Plant growth status, from 0 to 1
/// </summary>
[DataField, AutoNetworkedField]
public float GrowthLevel = 0f;
[DataField]
public float UpdateFrequency = 60f;
[DataField, AutoPausedField]
public TimeSpan NextUpdateTime = TimeSpan.Zero;
[DataField(required: true)]
public string Solution = string.Empty;
}
/// <summary>
/// Is called periodically at random intervals on the plant.
/// </summary>
public sealed class CP14PlantUpdateEvent(Entity<CP14PlantComponent> comp) : EntityEventArgs
{
public readonly Entity<CP14PlantComponent> Plant = comp;
public float EnergyDelta = 0f;
public float ResourceDelta = 0f;
}
/// <summary>
/// is called after CP14PlantUpdateEvent when all value changes have already been calculated.
/// </summary>
public sealed class CP14AfterPlantUpdateEvent(Entity<CP14PlantComponent> comp) : EntityEventArgs
{
public readonly Entity<CP14PlantComponent> Plant = comp;
}

View File

@@ -1,9 +1,9 @@
namespace Content.Server._CP14.Farming.Components;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// allows the plant to receive energy passively, depending on daylight
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
[RegisterComponent, Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14PlantEnergyFromLightComponent : Component
{
[DataField]

View File

@@ -1,14 +1,17 @@
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
namespace Content.Server._CP14.Farming.Components;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// Gradually wastes the plant's resources, killing it if there aren't enough. The waste gradually increases over time, reflecting the "Old Age" of the plant
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
[RegisterComponent, Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14PlantFadingComponent : Component
{
[DataField]
public TimeSpan BirthTime = TimeSpan.Zero;
[DataField]
public float ResourcePerMinute = 0f;

View File

@@ -1,9 +1,9 @@
using Content.Shared.EntityList;
using Content.Shared.Whitelist;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.Farming;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// Means that the plant can be harvested.
@@ -22,7 +22,6 @@ public sealed partial class CP14PlantGatherableComponent : Component
/// YAML example below
/// (Tag1, Tag2, LootTableID1, LootTableID2 are placeholders for example)
/// --------------------
/// useMappedLoot: true
/// toolWhitelist:
/// tags:
/// - Tag1
@@ -41,23 +40,29 @@ public sealed partial class CP14PlantGatherableComponent : Component
public float GatherOffset = 0.3f;
[DataField]
public TimeSpan Time = TimeSpan.FromSeconds(1f);
public TimeSpan GatherDelay = TimeSpan.FromSeconds(1f);
/// <summary>
/// after harvesting, should the plant be completely removed?
/// After harvesting, should the plant be completely removed?
/// </summary>
[DataField]
public bool DeleteAfterHarvest = false;
public bool DeleteAfterHarvest;
/// <summary>
/// after harvest, the growth level of the plant will be reduced by the specified value
/// After harvest, the growth level of the plant will be reduced by the specified value
/// </summary>
[DataField]
public float GrowthCostHarvest = 0.4f;
/// <summary>
/// what level of growth does a plant need to have before it can be harvested?
/// What level of growth does a plant need to have before it can be harvested?
/// </summary>
[DataField]
public float GrowthLevelToHarvest = 0.9f;
/// <summary>
/// Sound to play when gathering
/// </summary>
[DataField]
public SoundSpecifier GatherSound = new SoundCollectionSpecifier("CP14GrassGathering");
}

View File

@@ -1,9 +1,9 @@
namespace Content.Server._CP14.Farming.Components;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// Is trying to use up the plant's energy and resources to grow.
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
[RegisterComponent, Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14PlantGrowingComponent : Component
{
[DataField]

View File

@@ -2,12 +2,12 @@ using Content.Shared._CP14.Farming.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.Farming.Components;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// allows the plant to obtain resources by absorbing liquid from the ground
/// </summary>
[RegisterComponent, Access(typeof(CP14FarmingSystem))]
[RegisterComponent, Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14PlantMetabolizerComponent : Component
{
[DataField]

View File

@@ -0,0 +1,20 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.Farming.Components;
/// <summary>
/// a component that allows for the creation of the entity on the tile
/// </summary>
[RegisterComponent, Access(typeof(CP14SharedFarmingSystem))]
public sealed partial class CP14SeedComponent : Component
{
[DataField]
public TimeSpan PlantingTime = TimeSpan.FromSeconds(1f);
[DataField(required: true)]
public EntProtoId PlantProto;
[DataField]
public HashSet<ProtoId<ContentTileDefinition>> SoilTile = new() { "CP14FloorDirt" };
}

View File

@@ -1,3 +1,4 @@
using Content.Shared._CP14.Farming.Components;
using Content.Shared._CP14.Farming.Prototypes;
using Content.Shared.FixedPoint;

View File

@@ -1,3 +1,4 @@
using Content.Shared._CP14.Farming.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
@@ -6,7 +7,7 @@ using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.Farming.Prototypes;
/// <summary>
/// Allows the plant to drink chemicals from the soil. The effect of the drank reagents depends on the selected metabolizer.
/// Allows the plant to drink chemicals. The effect of the drank reagents depends on the selected metabolizer.
/// </summary>
[Prototype("CP14PlantMetabolizer")]
public sealed partial class CP14PlantMetabolizerPrototype : IPrototype

View File

@@ -0,0 +1,34 @@
using Content.Shared._CP14.Farming.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Shared._CP14.WeatherEffect;
public sealed partial class WateringPlant : CP14WeatherEffect
{
[DataField(required: true)]
public Dictionary<ProtoId<ReagentPrototype>, float> Reagents = new();
public override void ApplyEffect(IEntityManager entManager, IRobustRandom random, EntityUid target)
{
if (!random.Prob(Prob))
return;
if (!entManager.TryGetComponent<CP14PlantComponent>(target, out var plant))
return;
var solutionSystem = entManager.System<SharedSolutionContainerSystem>();
solutionSystem.TryGetSolution(target, plant.Solution, out var ent, out var solution);
if (ent is null)
return;
foreach (var r in Reagents)
{
solutionSystem.TryAddReagent(ent.Value, r.Key, r.Value);
}
}
}

View File

@@ -1,3 +1,5 @@
cp14-farming-soil-interact-plant-exist = There's already something planted here!
cp14-farming-soil-occupied = There's not enough room!
cp14-farming-soil-wrong = {$seed} require a different type of soil for planting!
cp14-farming-low-energy = The plant looks wilted and shriveled.
cp14-farming-low-resources = The plant looks dry.

View File

@@ -4,6 +4,7 @@ cp14-stack-wood-planks = wooden planks
cp14-stack-nails = nails
cp14-stack-cloth = rolls of fabric
cp14-stack-flora = tufts of grass
cp14-stack-compost = compost piles
cp14-stack-copper-bars = copper bars
cp14-stack-iron-bars = iron bars

View File

@@ -1,3 +1,5 @@
cp14-farming-soil-interact-plant-exist = Здесь уже что-то посажено!
cp14-farming-soil-occupied = Здесь недостаточно места!
cp14-farming-soil-wrong = {$seed} требуют другой тип почвы для посадки!
cp14-farming-low-energy = Растение выглядит увядшим и сморщенным.
cp14-farming-low-resources = Растение выглядит сухим.

View File

@@ -4,6 +4,7 @@ cp14-stack-wood-planks = деревянные доски
cp14-stack-nails = гвозди
cp14-stack-cloth = рулоны ткани
cp14-stack-flora = пучки травы
cp14-stack-compost = кучи компоста
cp14-stack-copper-bars = медные слитки
cp14-stack-iron-bars = железные слитки

View File

@@ -117,8 +117,8 @@
- type: entity
id: CP14WildSage
parent: CP14WildProduceBase
name: wild sage root
description: Root of a ubiquitous medicinal plant, not bad at healing physical injuries, and inducing coughing.
name: sage
description: Sage flowers. A good medicinal herb that works as a hallucinogen when properly processed.
components:
- type: Item
size: Tiny
@@ -135,6 +135,7 @@
base1: ""
base2: ""
base3: ""
base4: ""
- type: Extractable
juiceSolution:
reagents:
@@ -151,6 +152,16 @@
tags:
- CP14FitInMortar
- CP14AlchemicalHerbals
- type: Temperature
currentTemperature: 290
- type: InternalTemperature
thickness: 0.02
area: 0.02
- type: CP14TemperatureTransformation
entries:
- temperatureRange: 400, 500
transformTo: CP14GroundSage
- type: entity
id: CP14LumiMushroom

View File

@@ -0,0 +1,67 @@
- type: entity
id: CP14FloraMaterial1
parent: BaseItem
name: flora material
description: An organic material used for medicinal or construction purposes.
suffix: 1
categories: [ ForkFiltered ]
components:
- type: Appearance
- type: Item
size: Normal
- type: Stack
stackType: CP14FloraMaterial
count: 1
baseLayer: base
layerStates:
- grass_material1
- grass_material2
- grass_material3
- type: Sprite
sprite: _CP14/Objects/Materials/flora.rsi
layers:
- state: grass_material1
map: ["base"]
- type: Material
- type: entity
id: CP14FloraMaterial10
parent: CP14FloraMaterial1
suffix: 10
components:
- type: Stack
count: 10
- type: entity
id: CP14CompostMaterial1
parent: BaseItem
name: compost
description: It was once a beautiful and vibrant plant, or food. Now it's a stinking pile of decaying organic matter.
suffix: 1
categories: [ ForkFiltered ]
components:
- type: Appearance
- type: Item
size: Normal
- type: Stack
stackType: CP14Compost
count: 1
baseLayer: base
layerStates:
- compost1
- compost2
- compost3
- type: Sprite
sprite: _CP14/Objects/Materials/compost.rsi
layers:
- state: compost1
map: ["base"]
- type: Material
- type: entity
id: CP14CompostMaterial10
parent: CP14CompostMaterial1
suffix: 10
components:
- type: Stack
count: 10

View File

@@ -371,39 +371,6 @@
- type: Stack
count: 50
- type: entity
id: CP14FloraMaterial1
parent: BaseItem
name: flora material
description: An organic material used for medicinal or construction purposes.
suffix: 1
categories: [ ForkFiltered ]
components:
- type: Item
size: Normal
- type: Stack
stackType: CP14FloraMaterial
count: 1
baseLayer: base
layerStates:
- grass_material1
- grass_material2
- grass_material3
- type: Sprite
sprite: _CP14/Objects/Materials/flora.rsi
layers:
- state: grass_material1
map: ["base"]
- type: Material
- type: entity
id: CP14FloraMaterial10
parent: CP14FloraMaterial1
suffix: 10
components:
- type: Stack
count: 10
- type: entity
id: CP14String
parent: BaseItem

View File

@@ -8,6 +8,7 @@
size: Tiny
- type: Sprite
sprite: _CP14/Objects/Specific/Farming/seeds.rsi
- type: CP14Seed
- type: entity
id: CP14SeedWheat
@@ -99,3 +100,17 @@
- state: pepper
- type: CP14Seed
plantProto: CP14PlantPepper
- type: entity
id: CP14SeedSage
name: sage seeds
description: Sage seeds. It's time to grow some fun herbs!
parent: CP14BaseSeed
components:
- type: Sprite
layers:
- state: bag
- state: sage
- type: CP14Seed
plantProto: CP14PlantSage

View File

@@ -1,65 +1,21 @@
- type: entity
id: CP14PlantCabbage
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: cabbage
description: OOO # TODO
description: You see a cabbage in front of you. Perhaps you were born in one.
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/cabbage.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/cabbage.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 6
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.1 # 10 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.25 #20 minute from water
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherCabbage
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantCabbageDeath:
min: 1
max: 1
- type: entity
id: CP14PlantCabbageDeath
name: dead cabbage
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/cabbage.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherCabbage

View File

@@ -1,65 +1,21 @@
- type: entity
id: CP14PlantCucumber
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: cucumber
description: OOO # TODO
description: Don't trust people who know how to turn into pickles.
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/cucumber.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/cucumber.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 6
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.05 # 20 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.15
- type: CP14PlantGatherable
deleteAfterHarvest: false
loot:
All: CP14GatherCucumber
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantCucumberDeath:
min: 1
max: 1
- type: entity
id: CP14PlantCucumberDeath
name: dead cucumber
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/cucumber.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherCucumber

View File

@@ -1,65 +1,21 @@
- type: entity
id: CP14PlantOnion
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: onion
description: OOO # TODO
description: He's so cute it brings tears to my eyes to cut him up.
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/onion.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/onion.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 6
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.05 # 20 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.15
- type: CP14PlantGatherable
deleteAfterHarvest: false
loot:
All: CP14GatherOnion
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantTomatoesDeath:
min: 1
max: 1
- type: entity
id: CP14PlantOnionDeath
name: dead onion
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/onion.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherOnion

View File

@@ -1,65 +1,23 @@
- type: entity
id: CP14PlantPepper
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: pepper
description: OOO # TODO
description: Russian roulette. Are you hot, or are you sweet peppers?
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/pepper.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/pepper.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 5
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.05 # 20 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.15
- type: CP14PlantGatherable
deleteAfterHarvest: false
loot:
All: CP14GatherPepper
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantTomatoesDeath:
min: 1
max: 1
- type: entity
id: CP14PlantPepperDeath
name: dead pepper
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/pepper.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherPepper

View File

@@ -1,65 +1,23 @@
- type: entity
id: CP14PlantPotato
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: potato
description: OOO # TODO
description: Some like to associate themselves with potatoes. People like that are not bad people.
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/potato.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/potato.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 5
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.1 # 10 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.25 #20 minute from water
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherPotato
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantPotatoDeath:
min: 1
max: 1
- type: entity
id: CP14PlantPotatoDeath
name: dead potato
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/potato.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherPotato

View File

@@ -1,65 +1,21 @@
- type: entity
id: CP14PlantPumpkin
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: pumpkin
description: OOO # TODO
description: Legends say there is a pumpkin king who stares into your soul through the crowns of trees.
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/pumpkin.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/pumpkin.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 6
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.1 # 10 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.25 #20 minute from water
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherPumpkin
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantPumpkinDeath:
min: 1
max: 1
- type: entity
id: CP14PlantPumpkinDeath
name: dead pumpkin
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/pumpkin.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherPumpkin

View File

@@ -0,0 +1,27 @@
- type: entity
id: CP14PlantSage
parent: CP14GatherablePlantBoringBase
name: sage
description: Medicinal sage. Some love it for its medicinal properties, others for its narcotic properties. Which side are you on?
components:
- type: Sprite
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/sage.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantVisuals
growthSteps: 4
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherSage
- type: entityLootTable
id: CP14GatherSage
entries:
- id: CP14WildSage
amount: 1
maxAmount: 2

View File

@@ -1,65 +1,21 @@
- type: entity
id: CP14PlantTomatoes
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: tomatoes
description: OOO # TODO
description: On the one hand, it's a delicious fruit. But why eat it when it's much more fun to use tomatoes as a throwing projectile?
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/tomatoes.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/tomatoes.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 6
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.05 # 20 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.15
- type: CP14PlantGatherable
deleteAfterHarvest: false
loot:
All: CP14GatherTomatoes
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantTomatoesDeath:
min: 1
max: 1
- type: entity
id: CP14PlantTomatoesDeath
name: dead tomatoes
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/tomatoes.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: entityLootTable
id: CP14GatherTomatoes

View File

@@ -1,66 +1,23 @@
- type: entity
id: CP14PlantWheat
parent: CP14GatherablePlantBase
parent: CP14GatherablePlantBoringBase
name: wheat
description: Most popular crop. Unpretentious, it opens the way to an abundance of flour products.
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/wheat.rsi
layers:
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: grow-1
sprite: _CP14/Structures/Flora/Farm/wheat.rsi
map: ["enum.PlantVisualLayers.Base"]
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.1 # 10 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.25 #20 minute from water
- type: CP14PlantVisuals
growthSteps: 3
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherWheat
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 25
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTypeTrigger
damageType: Cellular
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14PlantWheatDeath:
min: 1
max: 1
- type: CP14WaveShader
speed: 2.8
dis: 4
- type: entity
id: CP14PlantWheatDeath
name: dead wheat
description: The sad spectacle of wasted food.
parent: CP14GatherableBase
components:
- type: Sprite
sprite: _CP14/Structures/Flora/Farm/wheat.rsi
state: death
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
- type: CP14WaveShader
speed: 2.8
dis: 4

View File

@@ -0,0 +1,30 @@
- type: entity
id: CP14GatherableBloodFlower
parent: CP14GatherableBase
name: blood rose
description: Scarlet flowers growing where blood has been spilled.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Flowers/red_rose.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherBloodFlower
- type: entityLootTable
id: CP14GatherBloodFlower
entries:
- id: CP14BloodFlower
amount: 1
maxAmount: 1

View File

@@ -0,0 +1,32 @@
- type: entity
id: CP14GatherableBlueAmanita
parent: CP14GatherableBase
name: blue Amanita
description: A sky blue flower known for its medicinal and magical properties.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/blue_amanita.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherBlueAmanita
- type: entityLootTable
id: CP14GatherBlueAmanita
entries:
- id: CP14BlueAmanita
amount: 1
maxAmount: 1

View File

@@ -0,0 +1,33 @@
- type: entity
id: CP14GatherableChromiumSlime
parent: CP14GatherableBase
name: chromium slime
description: This rare thick substance can be found in a stream of water as if it has a mind of its own. When trying to change the slime itself - the slime changes the reagent it interacts with.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/chromium_slime.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
- type: CP14PlantGatherable
deleteAfterHarvest: true
toolWhitelist:
components:
- Hands
loot:
All: CP14GatherChromiumSlime
- type: entityLootTable
id: CP14GatherChromiumSlime
entries:
- id: CP14ChromiumSlime
amount: 1
maxAmount: 1

View File

@@ -0,0 +1,32 @@
- type: entity
id: CP14GatherableDayflin
parent: CP14GatherableBase
name: yellow dayflin
description: A yellow sun flower that smells like melted milk. Can be processed into a yellow dye.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Flowers/yellow_dayflin.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherDayflin
- type: entityLootTable
id: CP14GatherDayflin
entries:
- id: CP14Dayflin
amount: 1
maxAmount: 2

View File

@@ -0,0 +1,33 @@
- type: entity
id: CP14GatherableFlyAgaric
parent: CP14GatherableBase
name: fly agaric
description: This poisonous mushroom can often be found near bodies of water or other wet areas. It is not recommended for consumption.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/agaric.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
world6: ""
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherFlyAgaric
- type: entityLootTable
id: CP14GatherFlyAgaric
entries:
- id: CP14AgaricMushroom
amount: 1
maxAmount: 2

View File

@@ -0,0 +1,36 @@
- type: entity
id: CP14GatherableLumiMushroom
parent: CP14GatherableBase
name: lumishroom
description: A faintly luminous mushroom. Often used by alchemists as a means of concentrating solutions.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/lumishroom.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
world6: ""
- type: PointLight
color: "#36c98f"
radius: 1.5
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherLumiMushroom
- type: entityLootTable
id: CP14GatherLumiMushroom
entries:
- id: CP14LumiMushroom
amount: 1
maxAmount: 1

View File

@@ -82,7 +82,7 @@
- type: entity
id: CP14GatherableWaterAirLily
parent:
- CP14GatherableWildBase
- CP14GatherableBase
- CP14WaterLilies
name: air lily
description: A light, delicate and airy flower. It is said that its special properties even allow it to breathe underwater...
@@ -104,7 +104,8 @@
big_flower2: ""
big_flower3: ""
big_flower4: ""
- type: Gatherable
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherAirLily

View File

@@ -0,0 +1,30 @@
- type: entity
id: CP14GatherableWildSage
parent: CP14GatherableBase
name: wild sage
description: Root of this ubiquitous medicinal plant not bad at healing physical injuries, and inducing coughing.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/wild_sage.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
- type: CP14PlantGatherable
deleteAfterHarvest: true
loot:
All: CP14GatherWildSage
- type: entityLootTable
id: CP14GatherWildSage
entries:
- id: CP14WildSage
amount: 1
maxAmount: 1

View File

@@ -4,6 +4,8 @@
abstract: true
categories: [ ForkFiltered ]
components:
- type: PlacementReplacement
key: CP14Plant
- type: Sprite
snapCardinals: true
drawdepth: FloorTiles
@@ -12,7 +14,6 @@
- type: Physics
canCollide: false
bodyType: Static
- type: CP14PlantAutoRoot
- type: Damageable
damageContainer: Biological
- type: MeleeSound
@@ -49,38 +50,124 @@
layer:
- MidImpassable
- LowImpassable
- type: entity
id: CP14GatherableWildBase
parent: CP14GatherableBase
abstract: true
components:
- type: Tag
tags:
- HideContextMenu
- type: Gatherable
toolWhitelist:
tags:
- CP14HerbalGathering
components:
- Sharp
- type: entity
id: CP14GatherablePlantBase
parent: CP14GatherableBase
abstract: true
components:
- type: Appearance
- type: CP14PlantVisuals
growthSteps: 5
growState: "grow-"
- type: CP14Plant
resource: 10
energy: 0
growthLevel: 0
fix2: #For melee or laser
hard: true
shape:
!type:PhysShapeAabb
bounds: "-0.35,-0.35,0.35,0.35"
mask:
- FullTileMask
layer:
- Opaque
- type: CP14PlantGatherable
toolWhitelist:
tags:
- CP14HerbalGathering
components:
- Sharp
- type: Appearance
- type: entity
id: CP14GatherablePlantBase
parent: CP14GatherableBase
abstract: true
components:
- type: CP14PlantVisuals
growthSteps: 5
growState: "grow-"
- type: CP14Plant
resource: 30
energy: 30
growthLevel: 0
solution: plant
- type: SolutionContainerManager
solutions:
plant:
maxVol: 200
food:
maxVol: 50
reagents:
- ReagentId: Nutriment
Quantity: 25
- type: Food
delay: 1.5
- type: RefillableSolution
solution: plant
maxRefill: 50
- type: ExaminableSolution
solution: plant
- type: SolutionContainerVisuals
maxFillLevels: 4
fillBaseName: liq-
solutionName: plant
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger #Overkill
damage: 35
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageGroupTrigger #Rot
damageGroup: Genetic
damage: 1
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14CompostMaterial1:
min: 2
max: 3
- trigger:
!type:DamageTypeTrigger #Heat
damageType: Heat
damage: 10
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14Ash1:
min: 0
max: 2
- trigger:
!type:DamageGroupTrigger #Brute
damageGroup: Brute
damage: 10
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
CP14FloraMaterial1:
min: 2
max: 3
- type: entity
id: CP14GatherablePlantBoringBase
parent:
- CP14BaseFlammableSpreading
- CP14GatherablePlantBase
abstract: true
components:
- type: Sprite
sprite: _CP14/Structures/Specific/Farming/seedbed.rsi
- type: CP14PlantMetabolizer
metabolizerId: Base
- type: CP14PlantEnergyFromLight
energy: 1
daytime: true
- type: CP14PlantVisuals
growthSteps: 6
- type: CP14PlantGrowing
energyCost: 1
resourceCost: 1
growthPerUpdate: 0.05 # 20 minute to full grow
- type: CP14PlantFading
resourcePerMinute: 0.25 #20 minute from water
- type: FireVisuals
sprite: _CP14/Effects/fire.rsi
normalState: full
alternateState: full2

View File

@@ -1,240 +0,0 @@
# BloodFlower
- type: entityLootTable
id: CP14GatherBloodFlower
entries:
- id: CP14BloodFlower
amount: 1
maxAmount: 1
- type: entity
id: CP14GatherableBloodFlower
parent: CP14GatherableWildBase
name: blood rose
description: Scarlet flowers growing where blood has been spilled.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Flowers/red_rose.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
- type: Gatherable
loot:
All: CP14GatherBloodFlower
# Dayflin
- type: entityLootTable
id: CP14GatherDayflin
entries:
- id: CP14Dayflin
amount: 1
maxAmount: 2
- type: entity
id: CP14GatherableDayflin
parent: CP14GatherableWildBase
name: yellow dayflin
description: A yellow sun flower that smells like melted milk. Can be processed into a yellow dye.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Flowers/yellow_dayflin.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
- type: Gatherable
loot:
All: CP14GatherDayflin
# Fly agaric
- type: entityLootTable
id: CP14GatherFlyAgaric
entries:
- id: CP14AgaricMushroom
amount: 1
maxAmount: 2
- type: entity
id: CP14GatherableFlyAgaric
parent: CP14GatherableWildBase
name: fly agaric
description: This poisonous mushroom can often be found near bodies of water or other wet areas. It is not recommended for consumption.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/agaric.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
world6: ""
- type: Gatherable
loot:
All: CP14GatherFlyAgaric
# Chromium slime
- type: entityLootTable
id: CP14GatherChromiumSlime
entries:
- id: CP14ChromiumSlime
amount: 1
maxAmount: 1
- type: entity
id: CP14GatherableChromiumSlime
parent: CP14GatherableWildBase
name: chromium slime
description: This rare thick substance can be found in a stream of water as if it has a mind of its own. When trying to change the slime itself - the slime changes the reagent it interacts with.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/chromium_slime.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
- type: Gatherable
toolWhitelist:
components:
- Hands
loot:
All: CP14GatherChromiumSlime
# Wild sage
- type: entityLootTable
id: CP14GatherWildSage
entries:
- id: CP14WildSage
amount: 1
maxAmount: 1
- type: entity
id: CP14GatherableWildSage
parent: CP14GatherableWildBase
name: wild sage
description: Root of this ubiquitous medicinal plant not bad at healing physical injuries, and inducing coughing.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/wild_sage.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
- type: Gatherable
loot:
All: CP14GatherWildSage
# LumiMushroom
- type: entityLootTable
id: CP14GatherLumiMushroom
entries:
- id: CP14LumiMushroom
amount: 1
maxAmount: 1
- type: entity
id: CP14GatherableLumiMushroom
parent: CP14GatherableWildBase
name: lumishroom
description: A faintly luminous mushroom. Often used by alchemists as a means of concentrating solutions.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/lumishroom.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
world6: ""
- type: PointLight
color: "#36c98f"
radius: 1.5
- type: Gatherable
loot:
All: CP14GatherLumiMushroom
# Blue amanita
- type: entityLootTable
id: CP14GatherBlueAmanita
entries:
- id: CP14BlueAmanita
amount: 1
maxAmount: 1
- type: entity
id: CP14GatherableBlueAmanita
parent: CP14GatherableWildBase
name: blue Amanita
description: A sky blue flower known for its medicinal and magical properties.
suffix: Gatherable
components:
- type: Sprite
drawdepth: FloorTiles
sprite: _CP14/Structures/Flora/Wild/blue_amanita.rsi
layers:
- state: world1
map: ["random"]
- type: RandomSprite
available:
- random:
world1: ""
world2: ""
world3: ""
world4: ""
world5: ""
- type: Gatherable
loot:
All: CP14GatherBlueAmanita

View File

@@ -1,74 +0,0 @@
- type: entity
id: CP14BaseFarmingSoil
abstract: true
categories: [ ForkFiltered ]
placement:
mode: SnapgridCenter
components:
- type: Clickable
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.45,-0.45,0.45,0.1"
density: 190
hard: false
mask:
- FullTileMask
layer:
- FullTileMask
- type: Appearance
- type: SolutionContainerManager
solutions:
soil:
maxVol: 200
- type: RefillableSolution
solution: soil
maxRefill: 50
- type: ExaminableSolution
solution: soil
- type: Transform
anchored: true
noRot: true
- type: CP14Soil
solution: soil
- type: entity
id: CP14SeedbedWooden
parent: CP14BaseFarmingSoil
name: seedbed
description: A wooden tub with a pile of earth adapted for growing plants.
components:
- type: Icon
sprite: _CP14/Structures/Specific/Farming/seedbed.rsi
state: seedbed_default
- type: SmoothEdge
- type: IconSmooth
key: walls
mode: NoSprite
- type: Sprite
drawdepth: BelowFloor
sprite: _CP14/Structures/Specific/Farming/seedbed.rsi
layers:
- state: seedbed_default
- state: liq-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- map: [ "enum.EdgeLayer.South" ]
state: seedbed_default_south
- map: [ "enum.EdgeLayer.East" ]
state: seedbed_default_east
- map: [ "enum.EdgeLayer.North" ]
state: seedbed_default_north
- map: [ "enum.EdgeLayer.West" ]
state: seedbed_default_west
- type: Construction
graph: CP14Seedbed
node: CP14SeedbedWooden
- type: SolutionContainerVisuals
maxFillLevels: 4
fillBaseName: liq-
solutionName: soil

View File

@@ -52,6 +52,28 @@
emote: Cough
probability: 0.3
- type: reagent
id: CP14WildSageSap
group: CP14Precurser
name: cp14-reagent-name-wild-sage-sap
desc: cp14-reagent-desc-wild-sage-sap
flavor: CP14Sweetly
color: "#b06bc7"
physicalDesc: cp14-reagent-physical-desc-cloudy
metabolisms:
Medicine:
effects:
- !type:HealthChange
damage:
types:
Blunt: 1
- !type:GenericStatusEffect
key: SeeingRainbows
component: SeeingRainbows
type: Add
time: 3
refresh: false
# Fungus based
- type: reagent
@@ -132,28 +154,6 @@
types:
Poison: 0.1
# Root based
- type: reagent
id: CP14WildSageSap
group: CP14Precurser
name: cp14-reagent-name-wild-sage-sap
desc: cp14-reagent-desc-wild-sage-sap
flavor: CP14Sweetly
color: "#6b462c"
physicalDesc: cp14-reagent-physical-desc-cloudy
metabolisms:
Medicine:
effects:
- !type:HealthChange
damage:
types:
Blunt: -1
- !type:Emote
emote: Cough
showInChat: true
probability: 0.15
# Slime based
- type: reagent

View File

@@ -1,32 +0,0 @@
- type: constructionGraph
id: CP14Seedbed
start: start
graph:
- node: start
actions:
- !type:DestroyEntity {}
edges:
- to: CP14SeedbedWooden
steps:
- material: CP14Dirt
amount: 1
doAfter: 2
- material: CP14WoodenPlanks
amount: 1
doAfter: 2
- node: CP14SeedbedWooden
entity: CP14SeedbedWooden
edges:
- to: start
steps:
- tool: CP14Digging
doAfter: 1
completed:
- !type:SpawnPrototype
prototype: CP14WoodenPlanks1
amount: 1
- !type:SpawnPrototype
prototype: CP14DirtBlock1
amount: 1
- !type:DeleteEntity {}

View File

@@ -1,20 +0,0 @@
- type: construction
crystallPunkAllowed: true
name: seedbed
description: A wooden tub with a pile of earth adapted for growing plants. Can only be built on dirt tiles.
id: CP14SeedbedWooden
graph: CP14Seedbed
startNode: start
targetNode: CP14SeedbedWooden
category: construction-category-structures
icon:
sprite: _CP14/Structures/Specific/Farming/seedbed.rsi
state: seedbed_default
objectType: Structure
placementMode: SnapgridCenter
canBuildInImpassable: false
conditions:
- !type:TileNotBlocked
- !type:TileType
targets:
- CP14FloorDirt

View File

@@ -14,4 +14,18 @@
- CP14EssenceOrder: 0.5
- CP14EssenceChaos: 0.5
# Admixture: By adding raw precursor to a potion with target solutions, we can reduce the amount of empty solution by modifying the target solutions.
# Admixture: By adding raw precursor to a potion with target solutions, we can reduce the amount of empty solution by modifying the target solutions.
- type: reaction
id: CP14WildSageAdmixture1
minTemp: 500
reactants:
CP14WildSageSap:
amount: 1
CP14BasicEffectEmpty:
amount: 1
CP14BasicEffectHealManaDepletion:
amount: 1
products:
CP14BasicEffectRainbow: 2
CP14BasicEffectEmoteCough: 1

View File

@@ -1,41 +0,0 @@
# More complex recipes made from T1-T2 essences and precursors as a base
# T1
# The result is always 50% empty solution
- type: reaction
id: CP14PrecurserBrewingHealMana
minTemp: 500
priority: 1
reactants:
CP14EssenceMagic:
amount: 2
CP14EssenceMotion:
amount: 1
CP14BlueAmanita:
amount: 1
products:
CP14BasicEffectEmpty: 1
CP14BasicEffectDrunk: 1
CP14BasicEffectHealMana: 2
effects:
- !type:CP14AffectSolutionTemperature
addTemperature: -150
- type: reaction
id: CP14PrecurserBrewingDamageMana
minTemp: 500
priority: 1
reactants:
CP14EssenceMagic:
amount: 2
CP14EssenceVoid:
amount: 1
CP14BlueAmanita:
amount: 1
products:
CP14BasicEffectEmpty: 1
CP14BasicEffectDrunk: 1
CP14BasicEffectDamageMana: 2
effects:
- !type:CP14AffectSolutionTemperature
addTemperature: -150

View File

@@ -1,4 +1,3 @@
# Red color dye
- type: reaction
id: CP14BloodFlowerBrewing
@@ -19,8 +18,6 @@
- !type:CreateEntityReactionEffect
entity: CP14DyeRed
# Yellow color dye
- type: reaction
id: CP14YellowDayflinBrewing
impact: Low
@@ -39,8 +36,6 @@
- !type:CreateEntityReactionEffect
entity: CP14DyeYellow
# Blue color dye
- type: reaction
id: CP14BlueAmanitaColor
minTemp: 393
@@ -58,3 +53,21 @@
addTemperature: -50
- !type:CreateEntityReactionEffect
entity: CP14DyeBlue
- type: reaction
id: CP14PurpleSageColor
minTemp: 393
priority: 1
quantized: true
conserveEnergy: false
reactants:
CP14WildSageSap:
amount: 10
Water:
amount: 1
catalyst: true
effects:
- !type:CP14AffectSolutionTemperature
addTemperature: -50
- !type:CreateEntityReactionEffect
entity: CP14DyePurple

View File

@@ -14,9 +14,10 @@
craftTime: 1
requirements:
- !type:ProtoIdResource
protoId: CP14FoodTomatoesSlice
protoId: CP14FoodTomatoes
count: 1
result: CP14SeedTomato
resultCount: 3
- type: CP14Recipe
id: CP14SeedCabbage
@@ -24,9 +25,10 @@
craftTime: 1
requirements:
- !type:ProtoIdResource
protoId: CP14FoodCabbageSlice
protoId: CP14FoodCabbage
count: 1
result: CP14SeedCabbage
resultCount: 3
- type: CP14Recipe
id: CP14SeedPumpkin
@@ -34,9 +36,10 @@
craftTime: 1
requirements:
- !type:ProtoIdResource
protoId: CP14FoodPumpkinSlice
protoId: CP14FoodPumpkin
count: 1
result: CP14SeedPumpkin
resultCount: 3
- type: CP14Recipe
id: CP14SeedCucumber
@@ -57,6 +60,7 @@
protoId: CP14FoodOnion
count: 1
result: CP14SeedOnion
resultCount: 2
- type: CP14Recipe
id: CP14SeedPepper
@@ -67,3 +71,15 @@
protoId: CP14FoodPepper
count: 1
result: CP14SeedPepper
resultCount: 3
- type: CP14Recipe
id: CP14SeedSage
tag: CP14RecipeCooking
craftTime: 1
requirements:
- !type:ProtoIdResource
protoId: CP14WildSage
count: 1
result: CP14SeedSage
resultCount: 1

View File

@@ -24,6 +24,16 @@
count: 1
result: CP14WoodenBeerMug
- type: CP14Recipe
id: CP14SmokingPipe
tag: CP14RecipeWorkbench
craftTime: 3
requirements:
- !type:StackResource
stack: CP14WoodenPlanks
count: 2
result: CP14SmokingPipe
- type: CP14Recipe
id: CP14Plate
tag: CP14RecipeWorkbench

View File

@@ -82,6 +82,13 @@
spawn: CP14FloraMaterial1
maxCount: 10
- type: stack
id: CP14Compost
name: cp14-stack-compost
icon: { sprite: "_CP14/Objects/Materials/compost.rsi", state: compost2 }
spawn: CP14CompostMaterial1
maxCount: 10
- type: stack
id: CP14Ash
name: cp14-stack-ash-pile

View File

@@ -14,6 +14,10 @@
prob: 0.2
effects:
- !type:ExtinguishReaction
- !type:WateringPlant
prob: 0.5
reagents:
Water: 5
- type: weather
id: CP14Storm
@@ -37,6 +41,10 @@
- !type:SpawnEntityOnTop
prob: 0.25
entity: CP14SkyLightning
- !type:WateringPlant
prob: 0.5
reagents:
Water: 5
- type: weather
id: CP14Mist

View File

@@ -16,28 +16,28 @@
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1,
0.1
0.3,
0.3,
0.3,
0.3
],
[
0.1,
0.1,
0.1,
0.1
0.3,
0.3,
0.3,
0.3
],
[
0.1,
0.1,
0.1,
0.1
0.3,
0.3,
0.3,
0.3
],
[
0.1,
0.1,
0.1,
0.1
0.3,
0.3,
0.3,
0.3
]
]
},
@@ -51,8 +51,8 @@
"name": "lit-icon",
"delays": [
[
0.1,
0.1
0.3,
0.3
]
]
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 B

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 B

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

View File

@@ -4,8 +4,8 @@
"x": 32,
"y": 32
},
"license": "All right reserved",
"copyright": "Created by Prazar",
"license": "CC-BY-SA-4.0",
"copyright": "Created by TheShuEd",
"states": [
{
"name": "base1"
@@ -15,6 +15,9 @@
},
{
"name": "base3"
},
{
"name": "base4"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

View File

@@ -0,0 +1,20 @@
{
"version": 1,
"license": "All right reserved",
"copyright": "Created by TheShuEd",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "compost1"
},
{
"name": "compost2"
},
{
"name": "compost3"
}
]
}

View File

@@ -36,6 +36,9 @@
},
{
"name": "wheat"
},
{
"name": "sage"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -24,9 +24,6 @@
},
{
"name": "grow-6"
},
{
"name": "death"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -24,9 +24,6 @@
},
{
"name": "grow-6"
},
{
"name": "death"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

View File

@@ -24,9 +24,6 @@
},
{
"name": "grow-6"
},
{
"name": "death"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -21,9 +21,6 @@
},
{
"name": "grow-5"
},
{
"name": "death"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -21,9 +21,6 @@
},
{
"name": "grow-5"
},
{
"name": "death"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -24,9 +24,6 @@
},
{
"name": "grow-6"
},
{
"name": "death"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

View File

@@ -0,0 +1,23 @@
{
"version": 1,
"license": "CC-BY-SA-4.0",
"copyright": "Created by TheShuEd (Discord)",
"size": {
"x": 48,
"y": 48
},
"states": [
{
"name": "grow-1"
},
{
"name": "grow-2"
},
{
"name": "grow-3"
},
{
"name": "grow-4"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -24,9 +24,6 @@
},
{
"name": "grow-6"
},
{
"name": "death"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -21,9 +21,6 @@
},
{
"name": "grow-5"
},
{
"name": "death"
}
]
}

View File

@@ -4,8 +4,8 @@
"x": 32,
"y": 32
},
"license": "All right reserved",
"copyright": "Created by Prazar ",
"license": "CC-BY-SA-4.0",
"copyright": "Created by TheShuEd",
"states": [
{
"name": "world1"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 730 B

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 680 B

View File

@@ -309,10 +309,20 @@ CP14BrassChestFilledSmallSpeedUp: CP14WoodenChestFilledSmallSpeedUp
CP14BrassChestFilledSmallRainbow: CP14WoodenChestFilledSmallRainbow
CP14BrassChestFilledFarmSeeds: CP14WoodenChestFilledFarmSeeds
CP14ClothingHeadCaptainCap: null
CP14ClothingHeadBeretBlack: null
#2025-02-04
CP14SeedbedWooden: null
CP14PlantCabbageDeath: CP14PlantCabbage
CP14PlantCucumberDeath: CP14PlantCucumber
CP14PlantOnionDeath: CP14PlantOnion
CP14PlantPepperDeath: CP14PlantPepper
CP14PlantPotatoDeath: CP14PlantPotato
CP14PlantPumpkinDeath: CP14PlantPumpkin
CP14PlantTomatoesDeath: CP14PlantTomatoes
CP14PlantWheatDeath: CP14PlantWheat
# <---> CrystallEdge migration zone end