2022-10-23 00:46:28 +02:00
using Content.Server.Body.Systems ;
2023-12-29 04:47:43 -08:00
using Content.Server.Chemistry.Containers.EntitySystems ;
2022-06-12 16:43:28 -07:00
using Content.Server.Construction ;
2024-01-23 17:59:09 -05:00
using Content.Server.Explosion.EntitySystems ;
2023-11-04 12:44:59 +00:00
using Content.Server.DeviceLinking.Events ;
using Content.Server.DeviceLinking.Systems ;
2022-07-31 14:56:26 +12:00
using Content.Server.Hands.Systems ;
2022-10-23 00:46:28 +02:00
using Content.Server.Kitchen.Components ;
2022-08-27 19:40:29 -04:00
using Content.Server.Power.Components ;
2023-11-04 12:44:59 +00:00
using Content.Server.Power.EntitySystems ;
2022-08-27 19:40:29 -04:00
using Content.Server.Temperature.Components ;
using Content.Server.Temperature.Systems ;
2022-10-23 00:46:28 +02:00
using Content.Shared.Body.Components ;
using Content.Shared.Body.Part ;
2023-10-14 09:45:28 -07:00
using Content.Shared.Chemistry.Components.SolutionManager ;
using Content.Shared.Chemistry.EntitySystems ;
2023-06-29 08:35:54 -04:00
using Content.Shared.Construction.EntitySystems ;
2022-10-23 00:46:28 +02:00
using Content.Shared.Destructible ;
2022-08-27 19:40:29 -04:00
using Content.Shared.FixedPoint ;
2022-10-23 00:46:28 +02:00
using Content.Shared.Interaction ;
using Content.Shared.Interaction.Events ;
2024-01-23 17:59:09 -05:00
using Robust.Shared.Random ;
using Robust.Shared.Audio ;
using Content.Server.Lightning ;
2022-10-23 00:46:28 +02:00
using Content.Shared.Item ;
2022-08-27 19:40:29 -04:00
using Content.Shared.Kitchen ;
2022-10-23 00:46:28 +02:00
using Content.Shared.Kitchen.Components ;
2022-08-27 19:40:29 -04:00
using Content.Shared.Popups ;
using Content.Shared.Power ;
using Content.Shared.Tag ;
using Robust.Server.GameObjects ;
2023-11-27 22:12:34 +11:00
using Robust.Shared.Audio.Systems ;
2022-08-27 19:40:29 -04:00
using Robust.Shared.Containers ;
2022-10-23 00:46:28 +02:00
using Robust.Shared.Player ;
2023-12-29 04:47:43 -08:00
using System.Linq ;
2024-01-23 17:59:09 -05:00
using Robust.Shared.Prototypes ;
using Robust.Shared.Timing ;
2020-05-28 15:28:35 -05:00
2021-06-09 22:19:39 +02:00
namespace Content.Server.Kitchen.EntitySystems
2020-05-28 15:28:35 -05:00
{
2022-08-27 19:40:29 -04:00
public sealed class MicrowaveSystem : EntitySystem
2020-05-28 15:28:35 -05:00
{
2022-10-23 00:46:28 +02:00
[Dependency] private readonly BodySystem _bodySystem = default ! ;
2023-11-04 12:44:59 +00:00
[Dependency] private readonly DeviceLinkSystem _deviceLink = default ! ;
2022-08-27 19:40:29 -04:00
[Dependency] private readonly SharedPopupSystem _popupSystem = default ! ;
2023-11-04 12:44:59 +00:00
[Dependency] private readonly PowerReceiverSystem _power = default ! ;
2022-08-27 19:40:29 -04:00
[Dependency] private readonly RecipeManager _recipeManager = default ! ;
[Dependency] private readonly SharedAppearanceSystem _appearance = default ! ;
[Dependency] private readonly SharedAudioSystem _audio = default ! ;
2024-01-23 17:59:09 -05:00
[Dependency] private readonly LightningSystem _lightning = default ! ;
[Dependency] private readonly IRobustRandom _random = default ! ;
[Dependency] private readonly IGameTiming _gameTiming = default ! ;
[Dependency] private readonly ExplosionSystem _explosion = default ! ;
[Dependency] private readonly SharedContainerSystem _container = default ! ;
2022-08-27 19:40:29 -04:00
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default ! ;
[Dependency] private readonly TagSystem _tag = default ! ;
[Dependency] private readonly TemperatureSystem _temperature = default ! ;
[Dependency] private readonly UserInterfaceSystem _userInterface = default ! ;
2022-07-31 14:56:26 +12:00
[Dependency] private readonly HandsSystem _handsSystem = default ! ;
2024-01-14 00:11:09 +03:00
[Dependency] private readonly SharedItemSystem _item = default ! ;
2022-07-31 14:56:26 +12:00
2024-01-23 17:59:09 -05:00
[ValidatePrototypeId<EntityPrototype>]
private const string MalfunctionSpark = "Spark" ;
2021-09-06 15:49:44 +02:00
public override void Initialize ( )
{
base . Initialize ( ) ;
2022-08-27 19:40:29 -04:00
SubscribeLocalEvent < MicrowaveComponent , ComponentInit > ( OnInit ) ;
2023-11-04 12:44:59 +00:00
SubscribeLocalEvent < MicrowaveComponent , MapInitEvent > ( OnMapInit ) ;
2023-12-29 04:47:43 -08:00
SubscribeLocalEvent < MicrowaveComponent , SolutionContainerChangedEvent > ( OnSolutionChange ) ;
2024-01-12 03:42:41 -05:00
SubscribeLocalEvent < MicrowaveComponent , EntInsertedIntoContainerMessage > ( OnContentUpdate ) ;
SubscribeLocalEvent < MicrowaveComponent , EntRemovedFromContainerMessage > ( OnContentUpdate ) ;
2023-07-08 09:02:17 -07:00
SubscribeLocalEvent < MicrowaveComponent , InteractUsingEvent > ( OnInteractUsing , after : new [ ] { typeof ( AnchorableSystem ) } ) ;
2022-05-03 01:43:25 +03:00
SubscribeLocalEvent < MicrowaveComponent , BreakageEventArgs > ( OnBreak ) ;
2022-08-27 19:40:29 -04:00
SubscribeLocalEvent < MicrowaveComponent , PowerChangedEvent > ( OnPowerChanged ) ;
2024-01-03 19:36:31 -05:00
SubscribeLocalEvent < MicrowaveComponent , AnchorStateChangedEvent > ( OnAnchorChanged ) ;
2022-05-12 05:05:16 -07:00
SubscribeLocalEvent < MicrowaveComponent , SuicideEvent > ( OnSuicide ) ;
2022-08-27 19:40:29 -04:00
2023-11-04 12:44:59 +00:00
SubscribeLocalEvent < MicrowaveComponent , SignalReceivedEvent > ( OnSignalReceived ) ;
2023-07-08 09:02:17 -07:00
SubscribeLocalEvent < MicrowaveComponent , MicrowaveStartCookMessage > ( ( u , c , m ) = > Wzhzhzh ( u , c , m . Session . AttachedEntity ) ) ;
2022-08-27 19:40:29 -04:00
SubscribeLocalEvent < MicrowaveComponent , MicrowaveEjectMessage > ( OnEjectMessage ) ;
SubscribeLocalEvent < MicrowaveComponent , MicrowaveEjectSolidIndexedMessage > ( OnEjectIndex ) ;
SubscribeLocalEvent < MicrowaveComponent , MicrowaveSelectCookTimeMessage > ( OnSelectTime ) ;
SubscribeLocalEvent < ActiveMicrowaveComponent , ComponentStartup > ( OnCookStart ) ;
SubscribeLocalEvent < ActiveMicrowaveComponent , ComponentShutdown > ( OnCookStop ) ;
2024-01-12 03:42:41 -05:00
SubscribeLocalEvent < ActiveMicrowaveComponent , EntInsertedIntoContainerMessage > ( OnActiveMicrowaveInsert ) ;
SubscribeLocalEvent < ActiveMicrowaveComponent , EntRemovedFromContainerMessage > ( OnActiveMicrowaveRemove ) ;
SubscribeLocalEvent < ActivelyMicrowavedComponent , OnConstructionTemperatureEvent > ( OnConstructionTemp ) ;
2022-08-27 19:40:29 -04:00
}
2023-12-29 04:47:43 -08:00
private void OnCookStart ( Entity < ActiveMicrowaveComponent > ent , ref ComponentStartup args )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
if ( ! TryComp < MicrowaveComponent > ( ent , out var microwaveComponent ) )
2022-08-27 19:40:29 -04:00
return ;
2023-12-29 04:47:43 -08:00
SetAppearance ( ent . Owner , MicrowaveVisualState . Cooking , microwaveComponent ) ;
2022-08-27 19:40:29 -04:00
microwaveComponent . PlayingStream =
2023-12-29 04:47:43 -08:00
_audio . PlayPvs ( microwaveComponent . LoopingSound , ent , AudioParams . Default . WithLoop ( true ) . WithMaxDistance ( 5 ) ) . Value . Entity ;
2022-08-27 19:40:29 -04:00
}
2023-12-29 04:47:43 -08:00
private void OnCookStop ( Entity < ActiveMicrowaveComponent > ent , ref ComponentShutdown args )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
if ( ! TryComp < MicrowaveComponent > ( ent , out var microwaveComponent ) )
2022-08-27 19:40:29 -04:00
return ;
2024-01-23 17:59:09 -05:00
SetAppearance ( ent . Owner , MicrowaveVisualState . Idle , microwaveComponent ) ;
2023-11-27 22:12:34 +11:00
microwaveComponent . PlayingStream = _audio . Stop ( microwaveComponent . PlayingStream ) ;
2024-01-23 17:59:09 -05:00
}
2024-01-12 03:42:41 -05:00
private void OnActiveMicrowaveInsert ( Entity < ActiveMicrowaveComponent > ent , ref EntInsertedIntoContainerMessage args )
{
AddComp < ActivelyMicrowavedComponent > ( args . Entity ) ;
}
private void OnActiveMicrowaveRemove ( Entity < ActiveMicrowaveComponent > ent , ref EntRemovedFromContainerMessage args )
{
EntityManager . RemoveComponentDeferred < ActivelyMicrowavedComponent > ( args . Entity ) ;
}
private void OnConstructionTemp ( Entity < ActivelyMicrowavedComponent > ent , ref OnConstructionTemperatureEvent args )
{
args . Result = HandleResult . False ;
return ;
}
2022-08-27 19:40:29 -04:00
/// <summary>
/// Adds temperature to every item in the microwave,
/// based on the time it took to microwave.
/// </summary>
/// <param name="component">The microwave that is heating up.</param>
/// <param name="time">The time on the microwave, in seconds.</param>
private void AddTemperature ( MicrowaveComponent component , float time )
{
2024-01-06 20:16:39 -05:00
var heatToAdd = time * component . BaseHeatMultiplier ;
2022-08-27 19:40:29 -04:00
foreach ( var entity in component . Storage . ContainedEntities )
{
if ( TryComp < TemperatureComponent > ( entity , out var tempComp ) )
2024-01-06 20:16:39 -05:00
_temperature . ChangeHeat ( entity , heatToAdd * component . ObjectHeatMultiplier , false , tempComp ) ;
2022-08-27 19:40:29 -04:00
if ( ! TryComp < SolutionContainerManagerComponent > ( entity , out var solutions ) )
continue ;
2023-12-29 04:47:43 -08:00
foreach ( var ( _ , soln ) in _solutionContainer . EnumerateSolutions ( ( entity , solutions ) ) )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
var solution = soln . Comp . Solution ;
2022-08-27 19:40:29 -04:00
if ( solution . Temperature > component . TemperatureUpperThreshold )
continue ;
2023-12-29 04:47:43 -08:00
_solutionContainer . AddThermalEnergy ( soln , heatToAdd ) ;
2022-08-27 19:40:29 -04:00
}
}
}
private void SubtractContents ( MicrowaveComponent component , FoodRecipePrototype recipe )
{
2023-09-05 09:55:10 +12:00
// TODO Turn recipe.IngredientsReagents into a ReagentQuantity[]
2022-08-27 19:40:29 -04:00
var totalReagentsToRemove = new Dictionary < string , FixedPoint2 > ( recipe . IngredientsReagents ) ;
// this is spaghetti ngl
foreach ( var item in component . Storage . ContainedEntities )
{
if ( ! TryComp < SolutionContainerManagerComponent > ( item , out var solMan ) )
continue ;
// go over every solution
2023-12-29 04:47:43 -08:00
foreach ( var ( _ , soln ) in _solutionContainer . EnumerateSolutions ( ( item , solMan ) ) )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
var solution = soln . Comp . Solution ;
2022-08-27 19:40:29 -04:00
foreach ( var ( reagent , _ ) in recipe . IngredientsReagents )
{
// removed everything
if ( ! totalReagentsToRemove . ContainsKey ( reagent ) )
continue ;
2023-09-05 09:55:10 +12:00
var quant = solution . GetTotalPrototypeQuantity ( reagent ) ;
2022-08-27 19:40:29 -04:00
if ( quant > = totalReagentsToRemove [ reagent ] )
{
quant = totalReagentsToRemove [ reagent ] ;
totalReagentsToRemove . Remove ( reagent ) ;
}
else
{
totalReagentsToRemove [ reagent ] - = quant ;
}
2023-12-29 04:47:43 -08:00
_solutionContainer . RemoveReagent ( soln , reagent , quant ) ;
2022-08-27 19:40:29 -04:00
}
}
}
foreach ( var recipeSolid in recipe . IngredientsSolids )
{
for ( var i = 0 ; i < recipeSolid . Value ; i + + )
{
foreach ( var item in component . Storage . ContainedEntities )
{
var metaData = MetaData ( item ) ;
if ( metaData . EntityPrototype = = null )
{
continue ;
}
if ( metaData . EntityPrototype . ID = = recipeSolid . Key )
{
2024-01-23 17:59:09 -05:00
_container . Remove ( item , component . Storage ) ;
2022-08-27 19:40:29 -04:00
EntityManager . DeleteEntity ( item ) ;
break ;
}
}
}
}
}
2023-11-04 12:44:59 +00:00
private void OnInit ( Entity < MicrowaveComponent > ent , ref ComponentInit args )
{
// this really does have to be in ComponentInit
ent . Comp . Storage = _container . EnsureContainer < Container > ( ent , "microwave_entity_container" ) ;
}
private void OnMapInit ( Entity < MicrowaveComponent > ent , ref MapInitEvent args )
2022-08-27 19:40:29 -04:00
{
2023-11-04 12:44:59 +00:00
_deviceLink . EnsureSinkPorts ( ent , ent . Comp . OnPort ) ;
2022-05-12 05:05:16 -07:00
}
2023-12-29 04:47:43 -08:00
private void OnSuicide ( Entity < MicrowaveComponent > ent , ref SuicideEvent args )
2022-05-12 05:05:16 -07:00
{
2022-08-27 19:40:29 -04:00
if ( args . Handled )
return ;
2022-05-12 05:05:16 -07:00
args . SetHandled ( SuicideKind . Heat ) ;
var victim = args . Victim ;
var headCount = 0 ;
2022-10-23 00:46:28 +02:00
if ( TryComp < BodyComponent > ( victim , out var body ) )
2022-05-12 05:05:16 -07:00
{
2022-10-23 00:46:28 +02:00
var headSlots = _bodySystem . GetBodyChildrenOfType ( victim , BodyPartType . Head , body ) ;
2022-05-12 05:05:16 -07:00
2022-10-23 00:46:28 +02:00
foreach ( var part in headSlots )
2022-05-12 05:05:16 -07:00
{
2023-12-29 04:47:43 -08:00
_container . Insert ( part . Id , ent . Comp . Storage ) ;
2022-10-23 00:46:28 +02:00
headCount + + ;
2022-05-12 05:05:16 -07:00
}
}
var othersMessage = headCount > 1
? Loc . GetString ( "microwave-component-suicide-multi-head-others-message" , ( "victim" , victim ) )
: Loc . GetString ( "microwave-component-suicide-others-message" , ( "victim" , victim ) ) ;
var selfMessage = headCount > 1
? Loc . GetString ( "microwave-component-suicide-multi-head-message" )
: Loc . GetString ( "microwave-component-suicide-message" ) ;
2022-12-19 10:41:47 +13:00
_popupSystem . PopupEntity ( othersMessage , victim , Filter . PvsExcept ( victim ) , true ) ;
_popupSystem . PopupEntity ( selfMessage , victim , victim ) ;
2021-09-06 15:49:44 +02:00
2023-12-29 04:47:43 -08:00
_audio . PlayPvs ( ent . Comp . ClickSound , ent . Owner , AudioParams . Default . WithVolume ( - 2 ) ) ;
ent . Comp . CurrentCookTimerTime = 10 ;
Wzhzhzh ( ent . Owner , ent . Comp , args . Victim ) ;
UpdateUserInterfaceState ( ent . Owner , ent . Comp ) ;
2021-09-06 15:49:44 +02:00
}
2023-12-29 04:47:43 -08:00
private void OnSolutionChange ( Entity < MicrowaveComponent > ent , ref SolutionContainerChangedEvent args )
2020-05-28 15:28:35 -05:00
{
2023-12-29 04:47:43 -08:00
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2020-05-28 15:28:35 -05:00
}
2022-04-15 17:20:20 -04:00
2024-01-12 03:42:41 -05:00
private void OnContentUpdate ( EntityUid uid , MicrowaveComponent component , ContainerModifiedMessage args ) // For some reason ContainerModifiedMessage just can't be used at all with Entity<T>. TODO: replace with Entity<T> syntax once that's possible
{
UpdateUserInterfaceState ( uid , component ) ;
}
2023-12-29 04:47:43 -08:00
private void OnInteractUsing ( Entity < MicrowaveComponent > ent , ref InteractUsingEvent args )
2022-04-15 17:20:20 -04:00
{
2023-07-08 09:02:17 -07:00
if ( args . Handled )
2022-08-27 19:40:29 -04:00
return ;
2023-12-29 04:47:43 -08:00
if ( ! ( TryComp < ApcPowerReceiverComponent > ( ent , out var apc ) & & apc . Powered ) )
2022-04-15 17:20:20 -04:00
{
2023-12-29 04:47:43 -08:00
_popupSystem . PopupEntity ( Loc . GetString ( "microwave-component-interact-using-no-power" ) , ent , args . User ) ;
2022-04-15 17:20:20 -04:00
return ;
}
2023-12-29 04:47:43 -08:00
if ( ent . Comp . Broken )
2022-04-15 17:20:20 -04:00
{
2023-12-29 04:47:43 -08:00
_popupSystem . PopupEntity ( Loc . GetString ( "microwave-component-interact-using-broken" ) , ent , args . User ) ;
2022-04-15 17:20:20 -04:00
return ;
}
2024-01-14 00:11:09 +03:00
if ( TryComp < ItemComponent > ( args . Used , out var item ) )
2022-04-15 17:20:20 -04:00
{
2024-01-14 00:11:09 +03:00
// check if size of an item you're trying to put in is too big
if ( _item . GetSizePrototype ( item . Size ) > _item . GetSizePrototype ( ent . Comp . MaxItemSize ) )
{
_popupSystem . PopupEntity ( Loc . GetString ( "microwave-component-interact-item-too-big" , ( "item" , args . Used ) ) , ent , args . User ) ;
return ;
}
}
else
{
// check if thing you're trying to put in isn't an item
2023-12-29 04:47:43 -08:00
_popupSystem . PopupEntity ( Loc . GetString ( "microwave-component-interact-using-transfer-fail" ) , ent , args . User ) ;
2022-04-15 17:20:20 -04:00
return ;
}
2024-01-05 20:03:48 +00:00
if ( ent . Comp . Storage . Count > = ent . Comp . Capacity )
{
_popupSystem . PopupEntity ( Loc . GetString ( "microwave-component-interact-full" ) , ent , args . User ) ;
return ;
}
2022-06-12 16:43:28 -07:00
args . Handled = true ;
2023-12-29 04:47:43 -08:00
_handsSystem . TryDropIntoContainer ( args . User , args . Used , ent . Comp . Storage ) ;
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2022-04-15 17:20:20 -04:00
}
2022-05-03 01:43:25 +03:00
2023-12-29 04:47:43 -08:00
private void OnBreak ( Entity < MicrowaveComponent > ent , ref BreakageEventArgs args )
2022-05-03 01:43:25 +03:00
{
2023-12-29 04:47:43 -08:00
ent . Comp . Broken = true ;
SetAppearance ( ent , MicrowaveVisualState . Broken , ent . Comp ) ;
2024-01-24 01:14:55 +00:00
StopCooking ( ent ) ;
2024-01-23 17:59:09 -05:00
_container . EmptyContainer ( ent . Comp . Storage ) ;
2023-12-29 04:47:43 -08:00
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2022-08-27 19:40:29 -04:00
}
2023-12-29 04:47:43 -08:00
private void OnPowerChanged ( Entity < MicrowaveComponent > ent , ref PowerChangedEvent args )
2022-08-27 19:40:29 -04:00
{
if ( ! args . Powered )
{
2023-12-29 04:47:43 -08:00
SetAppearance ( ent , MicrowaveVisualState . Idle , ent . Comp ) ;
2024-01-24 01:14:55 +00:00
StopCooking ( ent ) ;
2022-08-27 19:40:29 -04:00
}
2023-12-29 04:47:43 -08:00
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2022-08-27 19:40:29 -04:00
}
2024-01-03 19:36:31 -05:00
private void OnAnchorChanged ( EntityUid uid , MicrowaveComponent component , ref AnchorStateChangedEvent args )
{
2024-01-23 17:59:09 -05:00
if ( ! args . Anchored )
_container . EmptyContainer ( component . Storage ) ;
2024-01-03 19:36:31 -05:00
}
2023-11-04 12:44:59 +00:00
private void OnSignalReceived ( Entity < MicrowaveComponent > ent , ref SignalReceivedEvent args )
{
if ( args . Port ! = ent . Comp . OnPort )
return ;
if ( ent . Comp . Broken | | ! _power . IsPowered ( ent ) )
return ;
Wzhzhzh ( ent . Owner , ent . Comp , null ) ;
}
2022-08-27 19:40:29 -04:00
public void UpdateUserInterfaceState ( EntityUid uid , MicrowaveComponent component )
{
var ui = _userInterface . GetUiOrNull ( uid , MicrowaveUiKey . Key ) ;
if ( ui = = null )
return ;
2023-07-08 09:02:17 -07:00
2023-09-11 09:42:41 +10:00
_userInterface . SetUiState ( ui , new MicrowaveUpdateUserInterfaceState (
GetNetEntityArray ( component . Storage . ContainedEntities . ToArray ( ) ) ,
2022-08-27 19:40:29 -04:00
HasComp < ActiveMicrowaveComponent > ( uid ) ,
component . CurrentCookTimeButtonIndex ,
2024-02-14 06:16:00 +08:00
component . CurrentCookTimerTime ,
component . CurrentCookTimeEnd
2023-07-08 09:02:17 -07:00
) ) ;
2022-08-27 19:40:29 -04:00
}
2023-09-03 00:03:05 -04:00
public void SetAppearance ( EntityUid uid , MicrowaveVisualState state , MicrowaveComponent ? component = null , AppearanceComponent ? appearanceComponent = null )
2022-08-27 19:40:29 -04:00
{
2023-09-03 00:03:05 -04:00
if ( ! Resolve ( uid , ref component , ref appearanceComponent , false ) )
return ;
2022-08-27 19:40:29 -04:00
var display = component . Broken ? MicrowaveVisualState . Broken : state ;
2023-09-03 00:03:05 -04:00
_appearance . SetData ( uid , PowerDeviceVisuals . VisualState , display , appearanceComponent ) ;
2022-08-27 19:40:29 -04:00
}
2023-07-08 09:02:17 -07:00
public static bool HasContents ( MicrowaveComponent component )
2022-08-27 19:40:29 -04:00
{
return component . Storage . ContainedEntities . Any ( ) ;
}
2024-01-23 17:59:09 -05:00
/// <summary>
/// Handles the attempted cooking of unsafe objects
/// </summary>
/// <remarks>
/// Returns false if the microwave didn't explode, true if it exploded.
/// </remarks>
private void RollMalfunction ( Entity < ActiveMicrowaveComponent , MicrowaveComponent > ent )
{
if ( ent . Comp1 . MalfunctionTime = = TimeSpan . Zero )
return ;
if ( ent . Comp1 . MalfunctionTime > _gameTiming . CurTime )
return ;
ent . Comp1 . MalfunctionTime = _gameTiming . CurTime + TimeSpan . FromSeconds ( ent . Comp2 . MalfunctionInterval ) ;
if ( _random . Prob ( ent . Comp2 . ExplosionChance ) )
{
_explosion . TriggerExplosive ( ent ) ;
return ; // microwave is fucked, stop the cooking.
}
if ( _random . Prob ( ent . Comp2 . LightningChance ) )
_lightning . ShootRandomLightnings ( ent , 1.0f , 2 , MalfunctionSpark , triggerLightningEvents : false ) ;
}
2022-08-27 19:40:29 -04:00
/// <summary>
/// Starts Cooking
/// </summary>
/// <remarks>
/// It does not make a "wzhzhzh" sound, it makes a "mmmmmmmm" sound!
/// -emo
/// </remarks>
2023-02-10 17:45:38 -06:00
public void Wzhzhzh ( EntityUid uid , MicrowaveComponent component , EntityUid ? user )
2022-08-27 19:40:29 -04:00
{
2024-01-03 19:36:31 -05:00
if ( ! HasContents ( component ) | | HasComp < ActiveMicrowaveComponent > ( uid ) | | ! ( TryComp < ApcPowerReceiverComponent > ( uid , out var apc ) & & apc . Powered ) )
2022-08-27 19:40:29 -04:00
return ;
var solidsDict = new Dictionary < string , int > ( ) ;
var reagentDict = new Dictionary < string , FixedPoint2 > ( ) ;
2024-01-23 17:59:09 -05:00
var malfunctioning = false ;
2023-09-05 09:55:10 +12:00
// TODO use lists of Reagent quantities instead of reagent prototype ids.
2024-01-23 17:59:09 -05:00
foreach ( var item in component . Storage . ContainedEntities . ToArray ( ) )
2022-08-27 19:40:29 -04:00
{
// special behavior when being microwaved ;)
2023-02-10 17:45:38 -06:00
var ev = new BeingMicrowavedEvent ( uid , user ) ;
2022-08-27 19:40:29 -04:00
RaiseLocalEvent ( item , ev ) ;
if ( ev . Handled )
{
UpdateUserInterfaceState ( uid , component ) ;
return ;
}
2024-01-23 17:59:09 -05:00
if ( _tag . HasTag ( item , "Metal" ) )
2022-08-27 19:40:29 -04:00
{
2024-01-23 17:59:09 -05:00
malfunctioning = true ;
2022-08-27 19:40:29 -04:00
}
2024-01-23 17:59:09 -05:00
if ( _tag . HasTag ( item , "Plastic" ) )
2022-08-27 19:40:29 -04:00
{
var junk = Spawn ( component . BadRecipeEntityId , Transform ( uid ) . Coordinates ) ;
2023-12-27 21:30:03 -08:00
_container . Insert ( junk , component . Storage ) ;
2024-01-23 17:59:09 -05:00
Del ( item ) ;
continue ;
2022-08-27 19:40:29 -04:00
}
2024-01-12 03:42:41 -05:00
AddComp < ActivelyMicrowavedComponent > ( item ) ;
2022-08-27 19:40:29 -04:00
var metaData = MetaData ( item ) ; //this simply begs for cooking refactor
if ( metaData . EntityPrototype = = null )
continue ;
if ( solidsDict . ContainsKey ( metaData . EntityPrototype . ID ) )
{
solidsDict [ metaData . EntityPrototype . ID ] + + ;
}
else
{
solidsDict . Add ( metaData . EntityPrototype . ID , 1 ) ;
}
if ( ! TryComp < SolutionContainerManagerComponent > ( item , out var solMan ) )
continue ;
2023-12-29 04:47:43 -08:00
foreach ( var ( _ , soln ) in _solutionContainer . EnumerateSolutions ( ( item , solMan ) ) )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
var solution = soln . Comp . Solution ;
2023-09-05 09:55:10 +12:00
foreach ( var ( reagent , quantity ) in solution . Contents )
2022-08-27 19:40:29 -04:00
{
2023-09-05 09:55:10 +12:00
if ( reagentDict . ContainsKey ( reagent . Prototype ) )
reagentDict [ reagent . Prototype ] + = quantity ;
2022-08-27 19:40:29 -04:00
else
2023-09-05 09:55:10 +12:00
reagentDict . Add ( reagent . Prototype , quantity ) ;
2022-08-27 19:40:29 -04:00
}
}
}
// Check recipes
var portionedRecipe = _recipeManager . Recipes . Select ( r = >
CanSatisfyRecipe ( component , r , solidsDict , reagentDict ) ) . FirstOrDefault ( r = > r . Item2 > 0 ) ;
_audio . PlayPvs ( component . StartCookingSound , uid ) ;
var activeComp = AddComp < ActiveMicrowaveComponent > ( uid ) ; //microwave is now cooking
activeComp . CookTimeRemaining = component . CurrentCookTimerTime * component . CookTimeMultiplier ;
2022-10-30 03:14:20 -04:00
activeComp . TotalTime = component . CurrentCookTimerTime ; //this doesn't scale so that we can have the "actual" time
2022-08-27 19:40:29 -04:00
activeComp . PortionedRecipe = portionedRecipe ;
2024-02-14 06:16:00 +08:00
component . CurrentCookTimeEnd = _gameTiming . CurTime + TimeSpan . FromSeconds ( component . CurrentCookTimerTime ) ;
2024-01-23 17:59:09 -05:00
if ( malfunctioning )
activeComp . MalfunctionTime = _gameTiming . CurTime + TimeSpan . FromSeconds ( component . MalfunctionInterval ) ;
2022-08-27 19:40:29 -04:00
UpdateUserInterfaceState ( uid , component ) ;
}
2024-01-24 01:14:55 +00:00
private void StopCooking ( Entity < MicrowaveComponent > ent )
{
RemCompDeferred < ActiveMicrowaveComponent > ( ent ) ;
foreach ( var solid in ent . Comp . Storage . ContainedEntities )
{
RemCompDeferred < ActivelyMicrowavedComponent > ( solid ) ;
}
}
2023-07-08 09:02:17 -07:00
public static ( FoodRecipePrototype , int ) CanSatisfyRecipe ( MicrowaveComponent component , FoodRecipePrototype recipe , Dictionary < string , int > solids , Dictionary < string , FixedPoint2 > reagents )
2022-08-27 19:40:29 -04:00
{
var portions = 0 ;
2023-07-08 09:02:17 -07:00
if ( component . CurrentCookTimerTime % recipe . CookTime ! = 0 )
2022-08-27 19:40:29 -04:00
{
//can't be a multiple of this recipe
return ( recipe , 0 ) ;
}
foreach ( var solid in recipe . IngredientsSolids )
{
if ( ! solids . ContainsKey ( solid . Key ) )
return ( recipe , 0 ) ;
if ( solids [ solid . Key ] < solid . Value )
return ( recipe , 0 ) ;
portions = portions = = 0
? solids [ solid . Key ] / solid . Value . Int ( )
: Math . Min ( portions , solids [ solid . Key ] / solid . Value . Int ( ) ) ;
}
foreach ( var reagent in recipe . IngredientsReagents )
{
2023-09-05 09:55:10 +12:00
// TODO Turn recipe.IngredientsReagents into a ReagentQuantity[]
2022-08-27 19:40:29 -04:00
if ( ! reagents . ContainsKey ( reagent . Key ) )
return ( recipe , 0 ) ;
if ( reagents [ reagent . Key ] < reagent . Value )
return ( recipe , 0 ) ;
portions = portions = = 0
? reagents [ reagent . Key ] . Int ( ) / reagent . Value . Int ( )
: Math . Min ( portions , reagents [ reagent . Key ] . Int ( ) / reagent . Value . Int ( ) ) ;
}
//cook only as many of those portions as time allows
2023-07-08 09:02:17 -07:00
return ( recipe , ( int ) Math . Min ( portions , component . CurrentCookTimerTime / recipe . CookTime ) ) ;
2022-08-27 19:40:29 -04:00
}
public override void Update ( float frameTime )
{
base . Update ( frameTime ) ;
2023-07-08 09:02:17 -07:00
var query = EntityQueryEnumerator < ActiveMicrowaveComponent , MicrowaveComponent > ( ) ;
while ( query . MoveNext ( out var uid , out var active , out var microwave ) )
2022-08-27 19:40:29 -04:00
{
2024-01-23 17:59:09 -05:00
2022-08-27 19:40:29 -04:00
active . CookTimeRemaining - = frameTime ;
2024-01-23 17:59:09 -05:00
2024-02-14 06:16:00 +08:00
RollMalfunction ( ( uid , active , microwave ) ) ;
2024-01-23 17:59:09 -05:00
//check if there's still cook time left
2022-08-27 19:40:29 -04:00
if ( active . CookTimeRemaining > 0 )
2024-01-06 20:16:39 -05:00
{
AddTemperature ( microwave , frameTime ) ;
2022-08-27 19:40:29 -04:00
continue ;
2024-01-06 20:16:39 -05:00
}
2022-08-27 19:40:29 -04:00
//this means the microwave has finished cooking.
2024-01-06 20:16:39 -05:00
AddTemperature ( microwave , Math . Max ( frameTime + active . CookTimeRemaining , 0 ) ) ; //Though there's still a little bit more heat to pump out
2022-08-27 19:40:29 -04:00
if ( active . PortionedRecipe . Item1 ! = null )
{
2023-07-08 09:02:17 -07:00
var coords = Transform ( uid ) . Coordinates ;
2022-08-27 19:40:29 -04:00
for ( var i = 0 ; i < active . PortionedRecipe . Item2 ; i + + )
{
SubtractContents ( microwave , active . PortionedRecipe . Item1 ) ;
Spawn ( active . PortionedRecipe . Item1 . Result , coords ) ;
}
}
2024-01-23 17:59:09 -05:00
_container . EmptyContainer ( microwave . Storage ) ;
2024-02-14 06:16:00 +08:00
microwave . CurrentCookTimeEnd = TimeSpan . Zero ;
2023-07-08 09:02:17 -07:00
UpdateUserInterfaceState ( uid , microwave ) ;
2024-01-23 17:59:09 -05:00
_audio . PlayPvs ( microwave . FoodDoneSound , uid ) ;
2024-01-24 01:14:55 +00:00
StopCooking ( ( uid , microwave ) ) ;
2022-08-27 19:40:29 -04:00
}
}
#region ui
2023-12-29 04:47:43 -08:00
private void OnEjectMessage ( Entity < MicrowaveComponent > ent , ref MicrowaveEjectMessage args )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
if ( ! HasContents ( ent . Comp ) | | HasComp < ActiveMicrowaveComponent > ( ent ) )
2022-08-27 19:40:29 -04:00
return ;
2024-01-23 17:59:09 -05:00
_container . EmptyContainer ( ent . Comp . Storage ) ;
2023-12-29 04:47:43 -08:00
_audio . PlayPvs ( ent . Comp . ClickSound , ent , AudioParams . Default . WithVolume ( - 2 ) ) ;
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2022-08-27 19:40:29 -04:00
}
2023-12-29 04:47:43 -08:00
private void OnEjectIndex ( Entity < MicrowaveComponent > ent , ref MicrowaveEjectSolidIndexedMessage args )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
if ( ! HasContents ( ent . Comp ) | | HasComp < ActiveMicrowaveComponent > ( ent ) )
2022-08-27 19:40:29 -04:00
return ;
2024-01-23 17:59:09 -05:00
_container . Remove ( EntityManager . GetEntity ( args . EntityID ) , ent . Comp . Storage ) ;
2023-12-29 04:47:43 -08:00
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2022-08-27 19:40:29 -04:00
}
2023-12-29 04:47:43 -08:00
private void OnSelectTime ( Entity < MicrowaveComponent > ent , ref MicrowaveSelectCookTimeMessage args )
2022-08-27 19:40:29 -04:00
{
2023-12-29 04:47:43 -08:00
if ( ! HasContents ( ent . Comp ) | | HasComp < ActiveMicrowaveComponent > ( ent ) | | ! ( TryComp < ApcPowerReceiverComponent > ( ent , out var apc ) & & apc . Powered ) )
2022-08-27 19:40:29 -04:00
return ;
2023-06-07 19:44:42 +00:00
// some validation to prevent trollage
2023-12-29 04:47:43 -08:00
if ( args . NewCookTime % 5 ! = 0 | | args . NewCookTime > ent . Comp . MaxCookTime )
2023-06-07 19:44:42 +00:00
return ;
2023-12-29 04:47:43 -08:00
ent . Comp . CurrentCookTimeButtonIndex = args . ButtonIndex ;
ent . Comp . CurrentCookTimerTime = args . NewCookTime ;
2024-02-14 06:16:00 +08:00
ent . Comp . CurrentCookTimeEnd = TimeSpan . Zero ;
2023-12-29 04:47:43 -08:00
_audio . PlayPvs ( ent . Comp . ClickSound , ent , AudioParams . Default . WithVolume ( - 2 ) ) ;
UpdateUserInterfaceState ( ent , ent . Comp ) ;
2022-05-03 01:43:25 +03:00
}
2022-08-27 19:40:29 -04:00
#endregion
2020-05-28 15:28:35 -05:00
}
}