2022-02-06 13:14:41 -07:00
using Content.Server.Botany.Components ;
2022-12-18 13:12:28 -05:00
using Content.Server.Popups ;
2024-09-02 06:26:04 -05:00
using Content.Shared.Chemistry.EntitySystems ;
2022-03-13 03:11:03 -07:00
using Content.Shared.Botany ;
2022-02-06 13:14:41 -07:00
using Content.Shared.Examine ;
2023-03-06 02:37:57 +00:00
using Content.Shared.Hands.EntitySystems ;
2022-07-09 02:09:52 -07:00
using Content.Shared.Popups ;
2023-10-15 22:56:09 -07:00
using Content.Shared.Random ;
2022-02-06 13:14:41 -07:00
using Content.Shared.Random.Helpers ;
using Robust.Server.GameObjects ;
using Robust.Shared.Map ;
2022-12-18 13:12:28 -05:00
using Robust.Shared.Prototypes ;
2022-02-06 13:14:41 -07:00
using Robust.Shared.Random ;
2023-12-29 04:47:43 -08:00
using System.Diagnostics.CodeAnalysis ;
using System.Linq ;
2025-03-20 20:56:51 +01:00
using Content.Shared.Administration.Logs ;
using Content.Shared.Database ;
2025-08-19 20:56:36 +03:00
using Content.Shared.Kitchen.Components ;
2022-02-06 13:14:41 -07:00
namespace Content.Server.Botany.Systems ;
2022-12-18 13:12:28 -05:00
public sealed partial class BotanySystem : EntitySystem
2022-02-06 13:14:41 -07:00
{
2022-12-18 13:12:28 -05:00
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
[Dependency] private readonly IRobustRandom _robustRandom = default ! ;
2023-09-11 19:18:06 +10:00
[Dependency] private readonly AppearanceSystem _appearance = default ! ;
[Dependency] private readonly PopupSystem _popupSystem = default ! ;
[Dependency] private readonly SharedHandsSystem _hands = default ! ;
2024-09-02 06:26:04 -05:00
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default ! ;
2023-08-28 11:20:31 +02:00
[Dependency] private readonly MetaDataSystem _metaData = default ! ;
2023-10-15 22:56:09 -07:00
[Dependency] private readonly RandomHelperSystem _randomHelper = default ! ;
2025-03-20 20:56:51 +01:00
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default ! ;
2022-12-18 13:12:28 -05:00
public override void Initialize ( )
2022-02-06 13:14:41 -07:00
{
2022-12-18 13:12:28 -05:00
base . Initialize ( ) ;
2022-02-06 13:14:41 -07:00
SubscribeLocalEvent < SeedComponent , ExaminedEvent > ( OnExamined ) ;
2025-04-29 00:45:10 -04:00
SubscribeLocalEvent < ProduceComponent , ExaminedEvent > ( OnProduceExamined ) ;
2022-02-06 13:14:41 -07:00
}
2022-04-16 17:32:35 +12:00
public bool TryGetSeed ( SeedComponent comp , [ NotNullWhen ( true ) ] out SeedData ? seed )
2022-02-06 13:14:41 -07:00
{
2022-04-16 17:32:35 +12:00
if ( comp . Seed ! = null )
{
seed = comp . Seed ;
return true ;
}
2022-02-06 13:14:41 -07:00
2022-04-16 17:32:35 +12:00
if ( comp . SeedId ! = null
& & _prototypeManager . TryIndex ( comp . SeedId , out SeedPrototype ? protoSeed ) )
{
seed = protoSeed ;
return true ;
}
2022-02-06 13:14:41 -07:00
2022-04-16 17:32:35 +12:00
seed = null ;
return false ;
}
2022-02-06 13:14:41 -07:00
2022-04-16 17:32:35 +12:00
public bool TryGetSeed ( ProduceComponent comp , [ NotNullWhen ( true ) ] out SeedData ? seed )
{
if ( comp . Seed ! = null )
2022-02-06 13:14:41 -07:00
{
2022-04-16 17:32:35 +12:00
seed = comp . Seed ;
return true ;
2022-02-06 13:14:41 -07:00
}
2022-04-16 17:32:35 +12:00
if ( comp . SeedId ! = null
& & _prototypeManager . TryIndex ( comp . SeedId , out SeedPrototype ? protoSeed ) )
2022-02-06 13:14:41 -07:00
{
2022-04-16 17:32:35 +12:00
seed = protoSeed ;
return true ;
2022-02-06 13:14:41 -07:00
}
2022-04-16 17:32:35 +12:00
seed = null ;
return false ;
}
private void OnExamined ( EntityUid uid , SeedComponent component , ExaminedEvent args )
{
if ( ! args . IsInDetailsRange )
return ;
if ( ! TryGetSeed ( component , out var seed ) )
return ;
2025-02-09 00:16:06 +01:00
using ( args . PushGroup ( nameof ( SeedComponent ) , 1 ) )
2024-01-05 23:53:13 -07:00
{
var name = Loc . GetString ( seed . DisplayName ) ;
args . PushMarkup ( Loc . GetString ( $"seed-component-description" , ( "seedName" , name ) ) ) ;
args . PushMarkup ( Loc . GetString ( $"seed-component-plant-yield-text" , ( "seedYield" , seed . Yield ) ) ) ;
args . PushMarkup ( Loc . GetString ( $"seed-component-plant-potency-text" , ( "seedPotency" , seed . Potency ) ) ) ;
}
2022-02-06 13:14:41 -07:00
}
#region SeedPrototype prototype stuff
2023-03-06 02:37:57 +00:00
/// <summary>
/// Spawns a new seed packet on the floor at a position, then tries to put it in the user's hands if possible.
/// </summary>
2024-02-17 06:02:12 +01:00
public EntityUid SpawnSeedPacket ( SeedData proto , EntityCoordinates coords , EntityUid user , float? healthOverride = null )
2022-02-06 13:14:41 -07:00
{
2023-03-06 02:37:57 +00:00
var seed = Spawn ( proto . PacketPrototype , coords ) ;
2022-02-06 13:14:41 -07:00
var seedComp = EnsureComp < SeedComponent > ( seed ) ;
2022-04-16 17:32:35 +12:00
seedComp . Seed = proto ;
2024-02-17 06:02:12 +01:00
seedComp . HealthOverride = healthOverride ;
2022-02-06 13:14:41 -07:00
2022-12-20 23:25:34 +01:00
var name = Loc . GetString ( proto . Name ) ;
var noun = Loc . GetString ( proto . Noun ) ;
var val = Loc . GetString ( "botany-seed-packet-name" , ( "seedName" , name ) , ( "seedNoun" , noun ) ) ;
2023-08-28 11:20:31 +02:00
_metaData . SetEntityName ( seed , val ) ;
2022-02-06 13:14:41 -07:00
2023-03-06 02:37:57 +00:00
// try to automatically place in user's other hand
_hands . TryPickupAnyHand ( user , seed ) ;
2022-02-06 13:14:41 -07:00
return seed ;
}
2022-04-16 17:32:35 +12:00
public IEnumerable < EntityUid > AutoHarvest ( SeedData proto , EntityCoordinates position , int yieldMod = 1 )
2022-02-06 13:14:41 -07:00
{
if ( position . IsValid ( EntityManager ) & &
proto . ProductPrototypes . Count > 0 )
2025-03-20 20:56:51 +01:00
{
if ( proto . HarvestLogImpact ! = null )
_adminLogger . Add ( LogType . Botany , proto . HarvestLogImpact . Value , $"Auto-harvested {Loc.GetString(proto.Name):seed} at Pos:{position}." ) ;
2022-02-06 13:14:41 -07:00
return GenerateProduct ( proto , position , yieldMod ) ;
2025-03-20 20:56:51 +01:00
}
2022-02-06 13:14:41 -07:00
return Enumerable . Empty < EntityUid > ( ) ;
}
2022-04-16 17:32:35 +12:00
public IEnumerable < EntityUid > Harvest ( SeedData proto , EntityUid user , int yieldMod = 1 )
2022-02-06 13:14:41 -07:00
{
if ( proto . ProductPrototypes . Count = = 0 | | proto . Yield < = 0 )
{
2022-12-19 10:41:47 +13:00
_popupSystem . PopupCursor ( Loc . GetString ( "botany-harvest-fail-message" ) , user , PopupType . Medium ) ;
2022-02-06 13:14:41 -07:00
return Enumerable . Empty < EntityUid > ( ) ;
}
2022-12-20 23:25:34 +01:00
var name = Loc . GetString ( proto . DisplayName ) ;
_popupSystem . PopupCursor ( Loc . GetString ( "botany-harvest-success-message" , ( "name" , name ) ) , user , PopupType . Medium ) ;
2025-03-20 20:56:51 +01:00
if ( proto . HarvestLogImpact ! = null )
_adminLogger . Add ( LogType . Botany , proto . HarvestLogImpact . Value , $"{ToPrettyString(user):player} harvested {Loc.GetString(proto.Name):seed} at Pos:{Transform(user).Coordinates}." ) ;
2022-02-06 13:14:41 -07:00
return GenerateProduct ( proto , Transform ( user ) . Coordinates , yieldMod ) ;
}
2022-04-16 17:32:35 +12:00
public IEnumerable < EntityUid > GenerateProduct ( SeedData proto , EntityCoordinates position , int yieldMod = 1 )
2022-02-06 13:14:41 -07:00
{
var totalYield = 0 ;
if ( proto . Yield > - 1 )
{
if ( yieldMod < 0 )
totalYield = proto . Yield ;
else
totalYield = proto . Yield * yieldMod ;
totalYield = Math . Max ( 1 , totalYield ) ;
}
var products = new List < EntityUid > ( ) ;
2022-04-16 17:32:35 +12:00
if ( totalYield > 1 | | proto . HarvestRepeat ! = HarvestType . NoRepeat )
proto . Unique = false ;
2022-07-09 02:09:52 -07:00
2022-02-06 13:14:41 -07:00
for ( var i = 0 ; i < totalYield ; i + + )
{
var product = _robustRandom . Pick ( proto . ProductPrototypes ) ;
var entity = Spawn ( product , position ) ;
2023-10-15 22:56:09 -07:00
_randomHelper . RandomOffset ( entity , 0.25f ) ;
2022-02-06 13:14:41 -07:00
products . Add ( entity ) ;
var produce = EnsureComp < ProduceComponent > ( entity ) ;
2022-04-16 17:32:35 +12:00
produce . Seed = proto ;
2022-02-06 13:14:41 -07:00
ProduceGrown ( entity , produce ) ;
2022-12-18 13:12:28 -05:00
_appearance . SetData ( entity , ProduceVisuals . Potency , proto . Potency ) ;
2022-03-13 03:11:03 -07:00
2022-02-06 13:14:41 -07:00
if ( proto . Mysterious )
{
var metaData = MetaData ( entity ) ;
2023-08-28 11:20:31 +02:00
_metaData . SetEntityName ( entity , metaData . EntityName + "?" , metaData ) ;
_metaData . SetEntityDescription ( entity ,
metaData . EntityDescription + " " + Loc . GetString ( "botany-mysterious-description-addon" ) , metaData ) ;
2022-02-06 13:14:41 -07:00
}
}
return products ;
}
2022-04-16 17:32:35 +12:00
public bool CanHarvest ( SeedData proto , EntityUid ? held = null )
2022-02-06 13:14:41 -07:00
{
2022-02-18 15:57:42 -07:00
return ! proto . Ligneous | | proto . Ligneous & & held ! = null & & HasComp < SharpComponent > ( held ) ;
2022-02-06 13:14:41 -07:00
}
#endregion
}