Cherrypicks 5 (#399)

* Give moldy food the "Trash" tag (#29380)

Make moldy food items have the "Trash" tag, so they can be collected.

* Add "Structure" tag to switches, buttons, and levers (#29378)
shit
Co-authored-by: Eoin Mcloughlin <helloworld@eoinrul.es>

* Revamped Meteor Swarm (#28974)

* meteor code and balanced values

* Meteor Swarms

* Update meteors.yml

* Update meteors.yml

* HOO! (fix overkill bug and buff space dust)

* undo BloodstreamComponent.cs changes

* DamageDistribution -> DamageTypes

* part 2.

* meteor fixes

* improve meteor spawning (#29057)

* Decrease meteor frequency (#29194)

* Make Projectiles Only Hit a Variety of Station Objects Unless Clicked on (#28571)

* Revert "Make Projectiles Only Hit a Variety of Station Objects Unless Clicked on (#28571)"

This reverts commit 4f934f02f17ce55cabc03b965eb1df7738d63148.

* Makes machine parts stackable, removes unused field in stack prototypes (#28434)

* Makes machine parts stacks, removes unused field in stack prototypes

* forgor

* Fix tests

* Fixes lathe construction. Yes. This sucks but there's no better way that doesnt involve refactoring machine parts completely

* detail

* a

* Add pressure and temperature warning text to firelocks (#28341)

* fix firelocks

* missing nukies can be filled in by ghost roles (#28316)

* Revert "missing nukies can be filled in by ghost roles (#28316)"

This reverts commit 99f13e1e45bc778a4941316fde5d89d7b91337ce.

* welding gas mask (#27108)

* welding gas mask

* eek

* Canes + Cane Blade for Syndicate Librarians (#25873)

* Cane + Cane Blade

* Add - type: ContainerContainer

* Add another - type: ContainerContainer

* Fix and add proper ContainerContainer component

* Add UserInterface component

* Remove Space

* Stat Changes

* review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>

* Fix stupid NPC. (#26868)

* init commit

* Review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>

* fixes

---------

Co-authored-by: VeritableCalamity <34698192+Veritable-Calamity@users.noreply.github.com>
Co-authored-by: eoineoineoin <github@eoinrul.es>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: Ps3Moira <113228053+ps3moira@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
Co-authored-by: Vigers Ray <60344369+VigersRay@users.noreply.github.com>
This commit is contained in:
ThereDrD0
2024-06-30 10:04:27 +03:00
committed by GitHub
parent e2d41d6802
commit 164251ffa7
108 changed files with 1857 additions and 494 deletions

View File

@@ -102,7 +102,7 @@ public sealed class MaterialArbitrageTest
continue; continue;
var stackProto = protoManager.Index<StackPrototype>(materialStep.MaterialPrototypeId); var stackProto = protoManager.Index<StackPrototype>(materialStep.MaterialPrototypeId);
var spawnProto = protoManager.Index<EntityPrototype>(stackProto.Spawn); var spawnProto = protoManager.Index(stackProto.Spawn);
if (!spawnProto.Components.ContainsKey(materialName) || if (!spawnProto.Components.ContainsKey(materialName) ||
!spawnProto.Components.TryGetValue(compositionName, out var compositionReg)) !spawnProto.Components.TryGetValue(compositionName, out var compositionReg))

View File

@@ -59,23 +59,27 @@ public sealed class MachineFrameSystem : EntitySystem
return; return;
} }
// Machine parts cannot currently satisfy stack/component/tag restrictions. Similarly stacks cannot satisfy // If this changes in the future, then RegenerateProgress() also needs to be updated.
// component/tag restrictions. However, there is no reason this cannot be supported in the future. If this
// changes, then RegenerateProgress() also needs to be updated.
//
// Note that one entity is ALLOWED to satisfy more than one kind of component or tag requirements. This is // Note that one entity is ALLOWED to satisfy more than one kind of component or tag requirements. This is
// necessary in order to avoid weird entity-ordering shenanigans in RegenerateProgress(). // necessary in order to avoid weird entity-ordering shenanigans in RegenerateProgress().
var stack = CompOrNull<StackComponent>(args.Used);
var machinePart = CompOrNull<MachinePartComponent>(args.Used);
if (stack != null && machinePart != null)
{
if (TryInsertPartStack(uid, args.Used, component, machinePart, stack))
args.Handled = true;
return;
}
// Handle parts // Handle parts
if (TryComp<MachinePartComponent>(args.Used, out var machinePart)) if (machinePart != null)
{ {
if (TryInsertPart(uid, args.Used, component, machinePart)) if (TryInsertPart(uid, args.Used, component, machinePart))
args.Handled = true; args.Handled = true;
return; return;
} }
// Handle stacks if (stack != null)
if (TryComp<StackComponent>(args.Used, out var stack))
{ {
if (TryInsertStack(uid, args.Used, component, stack)) if (TryInsertStack(uid, args.Used, component, stack))
args.Handled = true; args.Handled = true;
@@ -191,6 +195,44 @@ public sealed class MachineFrameSystem : EntitySystem
return true; return true;
} }
/// <returns>Whether or not the function had any effect. Does not indicate success.</returns>
private bool TryInsertPartStack(EntityUid uid, EntityUid used, MachineFrameComponent component, MachinePartComponent machinePart, StackComponent stack)
{
if (!component.Requirements.ContainsKey(machinePart.PartType))
return false;
var progress = component.Progress[machinePart.PartType];
var requirement = component.Requirements[machinePart.PartType];
var needed = requirement - progress;
if (needed <= 0)
return false;
var count = stack.Count;
if (count < needed)
{
if (!_container.Insert(used, component.PartContainer))
return true;
component.Progress[machinePart.PartType] += count;
return true;
}
var splitStack = _stack.Split(used, needed, Transform(uid).Coordinates, stack);
if (splitStack == null)
return false;
if (!_container.Insert(splitStack.Value, component.PartContainer))
return true;
component.Progress[machinePart.PartType] += needed;
if (IsComplete(component))
_popupSystem.PopupEntity(Loc.GetString("machine-frame-component-on-complete"), uid);
return true;
}
/// <returns>Whether or not the function had any effect. Does not indicate success.</returns> /// <returns>Whether or not the function had any effect. Does not indicate success.</returns>
private bool TryInsertStack(EntityUid uid, EntityUid used, MachineFrameComponent component, StackComponent stack) private bool TryInsertStack(EntityUid uid, EntityUid used, MachineFrameComponent component, StackComponent stack)
{ {
@@ -328,8 +370,6 @@ public sealed class MachineFrameSystem : EntitySystem
{ {
if (TryComp<MachinePartComponent>(part, out var machinePart)) if (TryComp<MachinePartComponent>(part, out var machinePart))
{ {
DebugTools.Assert(!HasComp<StackComponent>(part));
// Check this is part of the requirements... // Check this is part of the requirements...
if (!component.Requirements.ContainsKey(machinePart.PartType)) if (!component.Requirements.ContainsKey(machinePart.PartType))
continue; continue;
@@ -338,7 +378,6 @@ public sealed class MachineFrameSystem : EntitySystem
component.Progress[machinePart.PartType] = 1; component.Progress[machinePart.PartType] = 1;
else else
component.Progress[machinePart.PartType]++; component.Progress[machinePart.PartType]++;
continue; continue;
} }

View File

@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
@@ -90,6 +91,16 @@ namespace Content.Server.Destructible
} }
} }
public bool TryGetDestroyedAt(Entity<DestructibleComponent?> ent, [NotNullWhen(true)] out FixedPoint2? destroyedAt)
{
destroyedAt = null;
if (!Resolve(ent, ref ent.Comp, false))
return false;
destroyedAt = DestroyedAt(ent, ent.Comp);
return true;
}
// FFS this shouldn't be this hard. Maybe this should just be a field of the destructible component. Its not // FFS this shouldn't be this hard. Maybe this should just be a field of the destructible component. Its not
// like there is currently any entity that is NOT just destroyed upon reaching a total-damage value. // like there is currently any entity that is NOT just destroyed upon reaching a total-damage value.
/// <summary> /// <summary>

View File

@@ -1,13 +1,25 @@
namespace Content.Server.Destructible.Thresholds using Robust.Shared.Random;
namespace Content.Server.Destructible.Thresholds
{ {
[Serializable] [DataDefinition, Serializable]
[DataDefinition]
public partial struct MinMax public partial struct MinMax
{ {
[DataField("min")] [DataField]
public int Min; public int Min;
[DataField("max")] [DataField]
public int Max; public int Max;
public MinMax(int min, int max)
{
Min = min;
Max = max;
}
public int Next(IRobustRandom random)
{
return random.Next(Min, Max + 1);
}
} }
} }

View File

@@ -1,71 +1,60 @@
using Content.Server.Atmos.Components; using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Systems; using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Popups;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems; using Content.Server.Power.EntitySystems;
using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Components;
using Content.Shared.Access.Systems;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Monitor;
using Content.Shared.Doors;
using Content.Shared.Doors.Components; using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems; using Content.Shared.Doors.Systems;
using Content.Shared.Popups; using Robust.Server.GameObjects;
using Content.Shared.Prying.Components;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
namespace Content.Server.Doors.Systems namespace Content.Server.Doors.Systems
{ {
public sealed class FirelockSystem : EntitySystem public sealed class FirelockSystem : SharedFirelockSystem
{ {
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedDoorSystem _doorSystem = default!; [Dependency] private readonly SharedDoorSystem _doorSystem = default!;
[Dependency] private readonly AtmosAlarmableSystem _atmosAlarmable = default!; [Dependency] private readonly AtmosAlarmableSystem _atmosAlarmable = default!;
[Dependency] private readonly AtmosphereSystem _atmosSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; [Dependency] private readonly SharedMapSystem _mapping = default!;
[Dependency] private readonly PointLightSystem _pointLight = default!;
private static float _visualUpdateInterval = 0.5f; private const int UpdateInterval = 30;
private float _accumulatedFrameTime; private int _accumulatedTicks;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<FirelockComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
SubscribeLocalEvent<FirelockComponent, GetPryTimeModifierEvent>(OnDoorGetPryTimeModifier);
SubscribeLocalEvent<FirelockComponent, DoorStateChangedEvent>(OnUpdateState);
SubscribeLocalEvent<FirelockComponent, BeforeDoorAutoCloseEvent>(OnBeforeDoorAutoclose);
SubscribeLocalEvent<FirelockComponent, AtmosAlarmEvent>(OnAtmosAlarm); SubscribeLocalEvent<FirelockComponent, AtmosAlarmEvent>(OnAtmosAlarm);
// Visuals
SubscribeLocalEvent<FirelockComponent, MapInitEvent>(UpdateVisuals);
SubscribeLocalEvent<FirelockComponent, ComponentStartup>(UpdateVisuals);
SubscribeLocalEvent<FirelockComponent, PowerChangedEvent>(PowerChanged); SubscribeLocalEvent<FirelockComponent, PowerChangedEvent>(PowerChanged);
} }
private void PowerChanged(EntityUid uid, FirelockComponent component, ref PowerChangedEvent args) private void PowerChanged(EntityUid uid, FirelockComponent component, ref PowerChangedEvent args)
{ {
// TODO this should REALLLLY not be door specific appearance thing. // TODO this should REALLLLY not be door specific appearance thing.
_appearance.SetData(uid, DoorVisuals.Powered, args.Powered); _appearance.SetData(uid, DoorVisuals.Powered, args.Powered);
component.Powered = args.Powered;
Dirty(uid, component);
} }
#region Visuals
private void UpdateVisuals(EntityUid uid, FirelockComponent component, EntityEventArgs args) => UpdateVisuals(uid, component);
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
_accumulatedFrameTime += frameTime; _accumulatedTicks += 1;
if (_accumulatedFrameTime < _visualUpdateInterval) if (_accumulatedTicks < UpdateInterval)
return; return;
_accumulatedFrameTime -= _visualUpdateInterval; _accumulatedTicks = 0;
var airtightQuery = GetEntityQuery<AirtightComponent>(); var airtightQuery = GetEntityQuery<AirtightComponent>();
var appearanceQuery = GetEntityQuery<AppearanceComponent>(); var appearanceQuery = GetEntityQuery<AppearanceComponent>();
var xformQuery = GetEntityQuery<TransformComponent>(); var xformQuery = GetEntityQuery<TransformComponent>();
var pointLightQuery = GetEntityQuery<PointLightComponent>();
var query = EntityQueryEnumerator<FirelockComponent, DoorComponent>(); var query = EntityQueryEnumerator<FirelockComponent, DoorComponent>();
while (query.MoveNext(out var uid, out var firelock, out var door)) while (query.MoveNext(out var uid, out var firelock, out var door))
@@ -82,109 +71,20 @@ namespace Content.Server.Doors.Systems
&& xformQuery.TryGetComponent(uid, out var xform) && xformQuery.TryGetComponent(uid, out var xform)
&& appearanceQuery.TryGetComponent(uid, out var appearance)) && appearanceQuery.TryGetComponent(uid, out var appearance))
{ {
var (fire, pressure) = CheckPressureAndFire(uid, firelock, xform, airtight, airtightQuery); var (pressure, fire) = CheckPressureAndFire(uid, firelock, xform, airtight, airtightQuery);
_appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance); _appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance);
firelock.Temperature = fire;
firelock.Pressure = pressure;
Dirty(uid, firelock);
if (pointLightQuery.TryComp(uid, out var pointLight))
{
_pointLight.SetEnabled(uid, fire | pressure, pointLight);
}
} }
} }
} }
private void UpdateVisuals(EntityUid uid,
FirelockComponent? firelock = null,
DoorComponent? door = null,
AirtightComponent? airtight = null,
AppearanceComponent? appearance = null,
TransformComponent? xform = null)
{
if (!Resolve(uid, ref door, ref appearance, false))
return;
// only bother to check pressure on doors that are some variation of closed.
if (door.State != DoorState.Closed
&& door.State != DoorState.Welded
&& door.State != DoorState.Denying)
{
_appearance.SetData(uid, DoorVisuals.ClosedLights, false, appearance);
return;
}
var query = GetEntityQuery<AirtightComponent>();
if (!Resolve(uid, ref firelock, ref airtight, ref appearance, ref xform, false) || !query.Resolve(uid, ref airtight, false))
return;
var (fire, pressure) = CheckPressureAndFire(uid, firelock, xform, airtight, query);
_appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance);
}
#endregion
public bool EmergencyPressureStop(EntityUid uid, FirelockComponent? firelock = null, DoorComponent? door = null)
{
if (!Resolve(uid, ref firelock, ref door))
return false;
if (door.State == DoorState.Open)
{
if (_doorSystem.TryClose(uid, door))
{
return _doorSystem.OnPartialClose(uid, door);
}
}
return false;
}
private void OnBeforeDoorOpened(EntityUid uid, FirelockComponent component, BeforeDoorOpenedEvent args)
{
// Give the Door remote the ability to force a firelock open even if it is holding back dangerous gas
var overrideAccess = (args.User != null) && _accessReaderSystem.IsAllowed(args.User.Value, uid);
if (!this.IsPowered(uid, EntityManager) || (!overrideAccess && IsHoldingPressureOrFire(uid, component)))
args.Cancel();
}
private void OnDoorGetPryTimeModifier(EntityUid uid, FirelockComponent component, ref GetPryTimeModifierEvent args)
{
var state = CheckPressureAndFire(uid, component);
if (state.Fire)
{
_popupSystem.PopupEntity(Loc.GetString("firelock-component-is-holding-fire-message"),
uid, args.User, PopupType.MediumCaution);
}
else if (state.Pressure)
{
_popupSystem.PopupEntity(Loc.GetString("firelock-component-is-holding-pressure-message"),
uid, args.User, PopupType.MediumCaution);
}
if (state.Fire || state.Pressure)
args.PryTimeModifier *= component.LockedPryTimeModifier;
}
private void OnUpdateState(EntityUid uid, FirelockComponent component, DoorStateChangedEvent args)
{
var ev = new BeforeDoorAutoCloseEvent();
RaiseLocalEvent(uid, ev);
UpdateVisuals(uid, component, args);
if (ev.Cancelled)
{
return;
}
_doorSystem.SetNextStateChange(uid, component.AutocloseDelay);
}
private void OnBeforeDoorAutoclose(EntityUid uid, FirelockComponent component, BeforeDoorAutoCloseEvent args)
{
if (!this.IsPowered(uid, EntityManager))
args.Cancel();
// Make firelocks autoclose, but only if the last alarm type it
// remembers was a danger. This is to prevent people from
// flooding hallways with endless bad air/fire.
if (component.AlarmAutoClose &&
(_atmosAlarmable.TryGetHighestAlert(uid, out var alarm) && alarm != AtmosAlarmType.Danger || alarm == null))
args.Cancel();
}
private void OnAtmosAlarm(EntityUid uid, FirelockComponent component, AtmosAlarmEvent args) private void OnAtmosAlarm(EntityUid uid, FirelockComponent component, AtmosAlarmEvent args)
{ {
if (!this.IsPowered(uid, EntityManager)) if (!this.IsPowered(uid, EntityManager))
@@ -193,7 +93,7 @@ namespace Content.Server.Doors.Systems
if (!TryComp<DoorComponent>(uid, out var doorComponent)) if (!TryComp<DoorComponent>(uid, out var doorComponent))
return; return;
if (args.AlarmType == AtmosAlarmType.Normal || args.AlarmType == AtmosAlarmType.Warning) if (args.AlarmType == AtmosAlarmType.Normal)
{ {
if (doorComponent.State == DoorState.Closed) if (doorComponent.State == DoorState.Closed)
_doorSystem.TryOpen(uid); _doorSystem.TryOpen(uid);
@@ -204,12 +104,6 @@ namespace Content.Server.Doors.Systems
} }
} }
public bool IsHoldingPressureOrFire(EntityUid uid, FirelockComponent firelock)
{
var result = CheckPressureAndFire(uid, firelock);
return result.Pressure || result.Fire;
}
public (bool Pressure, bool Fire) CheckPressureAndFire(EntityUid uid, FirelockComponent firelock) public (bool Pressure, bool Fire) CheckPressureAndFire(EntityUid uid, FirelockComponent firelock)
{ {
var query = GetEntityQuery<AirtightComponent>(); var query = GetEntityQuery<AirtightComponent>();
@@ -234,17 +128,17 @@ namespace Content.Server.Doors.Systems
return (false, false); return (false, false);
} }
if (!TryComp(xform.ParentUid, out GridAtmosphereComponent? gridAtmosphere)) if (!HasComp<GridAtmosphereComponent>(xform.ParentUid))
return (false, false); return (false, false);
var grid = Comp<MapGridComponent>(xform.ParentUid); var grid = Comp<MapGridComponent>(xform.ParentUid);
var pos = grid.CoordinatesToTile(xform.Coordinates); var pos = _mapping.CoordinatesToTile(xform.ParentUid, grid, xform.Coordinates);
var minPressure = float.MaxValue; var minPressure = float.MaxValue;
var maxPressure = float.MinValue; var maxPressure = float.MinValue;
var minTemperature = float.MaxValue; var minTemperature = float.MaxValue;
var maxTemperature = float.MinValue; var maxTemperature = float.MinValue;
bool holdingFire = false; var holdingFire = false;
bool holdingPressure = false; var holdingPressure = false;
// We cannot simply use `_atmosSystem.GetAdjacentTileMixtures` because of how the `includeBlocked` option // We cannot simply use `_atmosSystem.GetAdjacentTileMixtures` because of how the `includeBlocked` option
// works, we want to ignore the firelock's blocking, while including blockers on other tiles. // works, we want to ignore the firelock's blocking, while including blockers on other tiles.
@@ -284,7 +178,7 @@ namespace Content.Server.Doors.Systems
{ {
// Is there some airtight entity blocking this direction? If yes, don't include this direction in the // Is there some airtight entity blocking this direction? If yes, don't include this direction in the
// pressure differential // pressure differential
if (HasAirtightBlocker(grid.GetAnchoredEntities(adjacentPos), dir.GetOpposite(), airtightQuery)) if (HasAirtightBlocker(_mapping.GetAnchoredEntities(xform.ParentUid, grid, adjacentPos), dir.GetOpposite(), airtightQuery))
continue; continue;
var p = gas.Pressure; var p = gas.Pressure;

View File

@@ -141,4 +141,9 @@ public abstract partial class GameRuleSystem<T> where T: IComponent
return found; return found;
} }
protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null)
{
GameTicker.EndGameRule(uid, component);
}
} }

View File

@@ -0,0 +1,25 @@
using Content.Shared.Damage;
namespace Content.Server.Mining;
/// <summary>
/// This is used for meteors which hit objects, dealing damage to destroy/kill the object and dealing equal damage back to itself.
/// </summary>
[RegisterComponent, Access(typeof(MeteorSystem))]
public sealed partial class MeteorComponent : Component
{
/// <summary>
/// Damage specifier that is multiplied against the calculated damage amount to determine what damage is applied to the colliding entity.
/// </summary>
/// <remarks>
/// The values of this should add up to 1 or else the damage will be scaled.
/// </remarks>
[DataField]
public DamageSpecifier DamageTypes = new();
/// <summary>
/// A list of entities that this meteor has collided with. used to ensure no double collisions occur.
/// </summary>
[DataField]
public HashSet<EntityUid> HitList = new();
}

View File

@@ -0,0 +1,65 @@
using Content.Server.Administration.Logs;
using Content.Server.Destructible;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs.Systems;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;
namespace Content.Server.Mining;
public sealed class MeteorSystem : EntitySystem
{
[Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly DestructibleSystem _destructible = default!;
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<MeteorComponent, StartCollideEvent>(OnCollide);
}
private void OnCollide(EntityUid uid, MeteorComponent component, ref StartCollideEvent args)
{
if (TerminatingOrDeleted(args.OtherEntity) || TerminatingOrDeleted(uid))
return;
if (component.HitList.Contains(args.OtherEntity))
return;
FixedPoint2 threshold;
if (_mobThreshold.TryGetDeadThreshold(args.OtherEntity, out var mobThreshold))
{
threshold = mobThreshold.Value;
if (HasComp<ActorComponent>(args.OtherEntity))
_adminLog.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.OtherEntity):player} was struck by meteor {ToPrettyString(uid):ent} and killed instantly.");
}
else if (_destructible.TryGetDestroyedAt(args.OtherEntity, out var destroyThreshold))
{
threshold = destroyThreshold.Value;
}
else
{
threshold = FixedPoint2.MaxValue;
}
var otherEntDamage = CompOrNull<DamageableComponent>(args.OtherEntity)?.TotalDamage ?? FixedPoint2.Zero;
// account for the damage that the other entity has already taken: don't overkill
threshold -= otherEntDamage;
// The max amount of damage our meteor can take before breaking.
var maxMeteorDamage = _destructible.DestroyedAt(uid) - CompOrNull<DamageableComponent>(uid)?.TotalDamage ?? FixedPoint2.Zero;
// Cap damage so we don't overkill the meteor
var trueDamage = FixedPoint2.Min(maxMeteorDamage, threshold);
var damage = component.DamageTypes * trueDamage;
_damageable.TryChangeDamage(args.OtherEntity, damage, true, origin: uid);
_damageable.TryChangeDamage(uid, damage);
if (!TerminatingOrDeleted(args.OtherEntity))
component.HitList.Add(args.OtherEntity);
}
}

View File

@@ -0,0 +1,27 @@
using Robust.Server.Containers;
namespace Content.Server.NPC.HTN.Preconditions;
/// <summary>
/// Checks if the owner in container or not
/// </summary>
public sealed partial class InContainerPrecondition : HTNPrecondition
{
private ContainerSystem _container = default!;
[ViewVariables(VVAccess.ReadWrite)] [DataField("isInContainer")] public bool IsInContainer = true;
public override void Initialize(IEntitySystemManager sysManager)
{
base.Initialize(sysManager);
_container = sysManager.GetEntitySystem<ContainerSystem>();
}
public override bool IsMet(NPCBlackboard blackboard)
{
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
return IsInContainer && _container.IsEntityInContainer(owner) ||
!IsInContainer && !_container.IsEntityInContainer(owner);
}
}

View File

@@ -0,0 +1,40 @@
using Robust.Server.Containers;
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
public sealed partial class ContainerOperator : HTNOperator
{
[Dependency] private readonly IEntityManager _entManager = default!;
private ContainerSystem _container = default!;
private EntityQuery<TransformComponent> _transformQuery;
[DataField("shutdownState")]
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
[DataField("targetKey", required: true)]
public string TargetKey = default!;
public override void Initialize(IEntitySystemManager sysManager)
{
base.Initialize(sysManager);
_container = sysManager.GetEntitySystem<ContainerSystem>();
_transformQuery = _entManager.GetEntityQuery<TransformComponent>();
}
public override void Startup(NPCBlackboard blackboard)
{
base.Startup(blackboard);
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
if (!_container.TryGetOuterContainer(owner, _transformQuery.GetComponent(owner), out var outerContainer) && outerContainer == null)
return;
var target = outerContainer.Owner;
blackboard.SetValue(TargetKey, target);
}
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
{
return HTNOperatorStatus.Finished;
}
}

View File

@@ -0,0 +1,140 @@
using System.Threading;
using System.Threading.Tasks;
using Content.Server.NPC.Components;
using Content.Server.Storage.EntitySystems;
using Content.Shared.CombatMode;
using Robust.Server.Containers;
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat.Melee;
public sealed partial class EscapeOperator : HTNOperator, IHtnConditionalShutdown
{
[Dependency] private readonly IEntityManager _entManager = default!;
private ContainerSystem _container = default!;
private EntityStorageSystem _entityStorage = default!;
[DataField("shutdownState")]
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
[DataField("targetKey", required: true)]
public string TargetKey = default!;
public override void Initialize(IEntitySystemManager sysManager)
{
base.Initialize(sysManager);
_container = sysManager.GetEntitySystem<ContainerSystem>();
_entityStorage = sysManager.GetEntitySystem<EntityStorageSystem>();
}
public override void Startup(NPCBlackboard blackboard)
{
base.Startup(blackboard);
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
var target = blackboard.GetValue<EntityUid>(TargetKey);
if (_entityStorage.TryOpenStorage(owner, target))
{
TaskShutdown(blackboard, HTNOperatorStatus.Finished);
return;
}
var melee = _entManager.EnsureComponent<NPCMeleeCombatComponent>(owner);
melee.MissChance = blackboard.GetValueOrDefault<float>(NPCBlackboard.MeleeMissChance, _entManager);
melee.Target = target;
}
public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
CancellationToken cancelToken)
{
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
if (!blackboard.TryGetValue<EntityUid>(TargetKey, out var target, _entManager))
{
return (false, null);
}
if (!_container.IsEntityInContainer(owner))
{
return (false, null);
}
if (_entityStorage.TryOpenStorage(owner, target))
{
return (false, null);
}
return (true, null);
}
public void ConditionalShutdown(NPCBlackboard blackboard)
{
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
_entManager.System<SharedCombatModeSystem>().SetInCombatMode(owner, false);
_entManager.RemoveComponent<NPCMeleeCombatComponent>(owner);
blackboard.Remove<EntityUid>(TargetKey);
}
public override void TaskShutdown(NPCBlackboard blackboard, HTNOperatorStatus status)
{
base.TaskShutdown(blackboard, status);
ConditionalShutdown(blackboard);
}
public override void PlanShutdown(NPCBlackboard blackboard)
{
base.PlanShutdown(blackboard);
ConditionalShutdown(blackboard);
}
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
{
base.Update(blackboard, frameTime);
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
HTNOperatorStatus status;
if (_entManager.TryGetComponent<NPCMeleeCombatComponent>(owner, out var combat) &&
blackboard.TryGetValue<EntityUid>(TargetKey, out var target, _entManager))
{
combat.Target = target;
// Success
if (!_container.IsEntityInContainer(owner))
{
status = HTNOperatorStatus.Finished;
}
else
{
if (_entityStorage.TryOpenStorage(owner, target))
{
status = HTNOperatorStatus.Finished;
}
else
{
switch (combat.Status)
{
case CombatStatus.TargetOutOfRange:
case CombatStatus.Normal:
status = HTNOperatorStatus.Continuing;
break;
default:
status = HTNOperatorStatus.Failed;
break;
}
}
}
}
else
{
status = HTNOperatorStatus.Failed;
}
// Mark it as finished to continue the plan.
if (status == HTNOperatorStatus.Continuing && ShutdownState == HTNPlanState.PlanFinished)
{
status = HTNOperatorStatus.Finished;
}
return status;
}
}

View File

@@ -0,0 +1,35 @@
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
public sealed partial class UnPullOperator : HTNOperator
{
[Dependency] private readonly IEntityManager _entManager = default!;
private PullingSystem _pulling = default!;
private EntityQuery<PullableComponent> _pullableQuery;
[DataField("shutdownState")]
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
public override void Initialize(IEntitySystemManager sysManager)
{
base.Initialize(sysManager);
_pulling = sysManager.GetEntitySystem<PullingSystem>();
_pullableQuery = _entManager.GetEntityQuery<PullableComponent>();
}
public override void Startup(NPCBlackboard blackboard)
{
base.Startup(blackboard);
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
_pulling.TryStopPull(owner, _pullableQuery.GetComponent(owner), owner);
}
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
{
return HTNOperatorStatus.Finished;
}
}

View File

@@ -0,0 +1,34 @@
using Content.Server.Buckle.Systems;
using Content.Shared.Buckle.Components;
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
public sealed partial class UnbuckleOperator : HTNOperator
{
[Dependency] private readonly IEntityManager _entManager = default!;
private BuckleSystem _buckle = default!;
[DataField("shutdownState")]
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
public override void Initialize(IEntitySystemManager sysManager)
{
base.Initialize(sysManager);
_buckle = sysManager.GetEntitySystem<BuckleSystem>();
}
public override void Startup(NPCBlackboard blackboard)
{
base.Startup(blackboard);
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
if (!_entManager.TryGetComponent<BuckleComponent>(owner, out var buckle) || !buckle.Buckled)
return;
_buckle.TryUnbuckle(owner, owner, true, buckle);
}
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
{
return HTNOperatorStatus.Finished;
}
}

View File

@@ -51,7 +51,7 @@ namespace Content.Server.Stack
// Get a prototype ID to spawn the new entity. Null is also valid, although it should rarely be picked... // Get a prototype ID to spawn the new entity. Null is also valid, although it should rarely be picked...
var prototype = _prototypeManager.TryIndex<StackPrototype>(stack.StackTypeId, out var stackType) var prototype = _prototypeManager.TryIndex<StackPrototype>(stack.StackTypeId, out var stackType)
? stackType.Spawn ? stackType.Spawn.ToString()
: Prototype(uid)?.ID; : Prototype(uid)?.ID;
// Set the output parameter in the event instance to the newly split stack. // Set the output parameter in the event instance to the newly split stack.

View File

@@ -0,0 +1,35 @@
using Content.Shared.Random;
using Robust.Shared.Prototypes;
namespace Content.Server.StationEvents.Components;
/// <summary>
/// This is used for running meteor swarm events at regular intervals.
/// </summary>
[RegisterComponent, Access(typeof(MeteorSchedulerSystem)), AutoGenerateComponentPause]
public sealed partial class MeteorSchedulerComponent : Component
{
/// <summary>
/// The weights for which swarms will be selected.
/// </summary>
[DataField]
public ProtoId<WeightedRandomEntityPrototype> Config = "DefaultConfig";
/// <summary>
/// The time at which the next swarm occurs.
/// </summary>
[DataField, AutoPausedField]
public TimeSpan NextSwarmTime = TimeSpan.Zero;
/// <summary>
/// The minimum time between swarms
/// </summary>
[DataField]
public TimeSpan MinSwarmDelay = TimeSpan.FromMinutes(7.5f);
/// <summary>
/// The maximum time between swarms
/// </summary>
[DataField]
public TimeSpan MaxSwarmDelay = TimeSpan.FromMinutes(12.5f);
}

View File

@@ -0,0 +1,58 @@
using Content.Server.Destructible.Thresholds;
using Content.Server.StationEvents.Events;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Server.StationEvents.Components;
[RegisterComponent, Access(typeof(MeteorSwarmSystem)), AutoGenerateComponentPause]
public sealed partial class MeteorSwarmComponent : Component
{
[DataField, AutoPausedField]
public TimeSpan NextWaveTime;
/// <summary>
/// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer.
/// </summary>
[DataField]
public int WaveCounter;
[DataField]
public float MeteorVelocity = 10f;
/// <summary>
/// If true, meteors will be thrown from all angles instead of from a singular source
/// </summary>
[DataField]
public bool NonDirectional;
/// <summary>
/// The announcement played when a meteor swarm begins.
/// </summary>
[DataField]
public LocId? Announcement = "station-event-meteor-swarm-start-announcement";
[DataField]
public SoundSpecifier? AnnouncementSound = new SoundPathSpecifier("/Audio/Announcements/meteors.ogg")
{
Params = new()
{
Volume = -4
}
};
/// <summary>
/// Each meteor entity prototype and their corresponding weight in being picked.
/// </summary>
[DataField]
public Dictionary<EntProtoId, float> Meteors = new();
[DataField]
public MinMax Waves = new(3, 3);
[DataField]
public MinMax MeteorsPerWave = new(3, 4);
[DataField]
public MinMax WaveCooldown = new (10, 60);
}

View File

@@ -1,40 +0,0 @@
using Content.Server.StationEvents.Events;
namespace Content.Server.StationEvents.Components;
[RegisterComponent, Access(typeof(MeteorSwarmRule))]
public sealed partial class MeteorSwarmRuleComponent : Component
{
[DataField("cooldown")]
public float Cooldown;
/// <summary>
/// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer.
/// </summary>
[DataField("waveCounter")]
public int WaveCounter;
[DataField("minimumWaves")]
public int MinimumWaves = 3;
[DataField("maximumWaves")]
public int MaximumWaves = 8;
[DataField("minimumCooldown")]
public float MinimumCooldown = 10f;
[DataField("maximumCooldown")]
public float MaximumCooldown = 60f;
[DataField("meteorsPerWave")]
public int MeteorsPerWave = 5;
[DataField("meteorVelocity")]
public float MeteorVelocity = 10f;
[DataField("maxAngularVelocity")]
public float MaxAngularVelocity = 0.25f;
[DataField("minAngularVelocity")]
public float MinAngularVelocity = -0.25f;
}

View File

@@ -1,84 +0,0 @@
using System.Numerics;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.StationEvents.Components;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Spawners;
namespace Content.Server.StationEvents.Events
{
public sealed class MeteorSwarmRule : StationEventSystem<MeteorSwarmRuleComponent>
{
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
protected override void Started(EntityUid uid, MeteorSwarmRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
component.WaveCounter = RobustRandom.Next(component.MinimumWaves, component.MaximumWaves);
}
protected override void ActiveTick(EntityUid uid, MeteorSwarmRuleComponent component, GameRuleComponent gameRule, float frameTime)
{
if (component.WaveCounter <= 0)
{
ForceEndSelf(uid, gameRule);
return;
}
component.Cooldown -= frameTime;
if (component.Cooldown > 0f)
return;
component.WaveCounter--;
component.Cooldown += (component.MaximumCooldown - component.MinimumCooldown) * RobustRandom.NextFloat() + component.MinimumCooldown;
Box2? playableArea = null;
var mapId = GameTicker.DefaultMap;
var query = AllEntityQuery<MapGridComponent, TransformComponent>();
while (query.MoveNext(out var gridId, out _, out var xform))
{
if (xform.MapID != mapId)
continue;
var aabb = _physics.GetWorldAABB(gridId);
playableArea = playableArea?.Union(aabb) ?? aabb;
}
if (playableArea == null)
{
ForceEndSelf(uid, gameRule);
return;
}
var minimumDistance = (playableArea.Value.TopRight - playableArea.Value.Center).Length() + 50f;
var maximumDistance = minimumDistance + 100f;
var center = playableArea.Value.Center;
for (var i = 0; i < component.MeteorsPerWave; i++)
{
var angle = new Angle(RobustRandom.NextFloat() * MathF.Tau);
var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0));
var spawnPosition = new MapCoordinates(center + offset, mapId);
var meteor = Spawn("MeteorLarge", spawnPosition);
var physics = EntityManager.GetComponent<PhysicsComponent>(meteor);
_physics.SetBodyStatus(meteor, physics, BodyStatus.InAir);
_physics.SetLinearDamping(meteor, physics, 0f);
_physics.SetAngularDamping(meteor, physics, 0f);
_physics.ApplyLinearImpulse(meteor, -offset.Normalized() * component.MeteorVelocity * physics.Mass, body: physics);
_physics.ApplyAngularImpulse(
meteor,
physics.Mass * ((component.MaxAngularVelocity - component.MinAngularVelocity) * RobustRandom.NextFloat() + component.MinAngularVelocity),
body: physics);
EnsureComp<TimedDespawnComponent>(meteor).Lifetime = 120f;
}
}
}
}

View File

@@ -0,0 +1,88 @@
using System.Numerics;
using Content.Server.Chat.Systems;
using Content.Server.GameTicking.Rules;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Server.StationEvents.Components;
using Robust.Server.Audio;
using Robust.Shared.Map;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Player;
using Robust.Shared.Random;
namespace Content.Server.StationEvents.Events;
public sealed class MeteorSwarmSystem : GameRuleSystem<MeteorSwarmComponent>
{
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly StationSystem _station = default!;
protected override void Added(EntityUid uid, MeteorSwarmComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
{
base.Added(uid, component, gameRule, args);
component.WaveCounter = component.Waves.Next(RobustRandom);
if (component.Announcement is { } locId)
_chat.DispatchGlobalAnnouncement(Loc.GetString(locId), playSound: false, colorOverride: Color.Yellow);
_audio.PlayGlobal(component.AnnouncementSound, Filter.Broadcast(), true);
}
protected override void ActiveTick(EntityUid uid, MeteorSwarmComponent component, GameRuleComponent gameRule, float frameTime)
{
if (Timing.CurTime < component.NextWaveTime)
return;
component.NextWaveTime += TimeSpan.FromSeconds(component.WaveCooldown.Next(RobustRandom));
if (_station.GetStations().Count == 0)
return;
var station = RobustRandom.Pick(_station.GetStations());
if (_station.GetLargestGrid(Comp<StationDataComponent>(station)) is not { } grid)
return;
var mapId = Transform(grid).MapID;
var playableArea = _physics.GetWorldAABB(grid);
var minimumDistance = (playableArea.TopRight - playableArea.Center).Length() + 50f;
var maximumDistance = minimumDistance + 100f;
var center = playableArea.Center;
var meteorsToSpawn = component.MeteorsPerWave.Next(RobustRandom);
for (var i = 0; i < meteorsToSpawn; i++)
{
var spawnProto = RobustRandom.Pick(component.Meteors).Key;
var angle = component.NonDirectional
? RobustRandom.NextAngle()
: new Random(uid.Id).NextAngle();
var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0));
// the line at which spawns occur is perpendicular to the offset.
// This means the meteors are less likely to bunch up and hit the same thing.
var subOffsetAngle = RobustRandom.Prob(0.5f)
? angle + Math.PI / 2
: angle - Math.PI / 2;
var subOffset = subOffsetAngle.RotateVec(new Vector2( (playableArea.TopRight - playableArea.Center).Length() / 3 * RobustRandom.NextFloat(), 0));
var spawnPosition = new MapCoordinates(center + offset + subOffset, mapId);
var meteor = Spawn(spawnProto, spawnPosition);
var physics = Comp<PhysicsComponent>(meteor);
_physics.ApplyLinearImpulse(meteor, -offset.Normalized() * component.MeteorVelocity * physics.Mass, body: physics);
}
component.WaveCounter--;
if (component.WaveCounter <= 0)
{
ForceEndSelf(uid, gameRule);
}
}
}

View File

@@ -0,0 +1,39 @@
using Content.Server.GameTicking.Rules;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.Random.Helpers;
using Robust.Shared.Prototypes;
namespace Content.Server.StationEvents;
/// <summary>
/// This handles scheduling and launching meteors at a station at regular intervals.
/// TODO: there is 100% a world in which this is genericized and can be used for lots of basic event scheduling
/// </summary>
public sealed class MeteorSchedulerSystem : GameRuleSystem<MeteorSchedulerComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
protected override void Started(EntityUid uid, MeteorSchedulerComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
component.NextSwarmTime = Timing.CurTime + RobustRandom.Next(component.MinSwarmDelay, component.MaxSwarmDelay);
}
protected override void ActiveTick(EntityUid uid, MeteorSchedulerComponent component, GameRuleComponent gameRule, float frameTime)
{
base.ActiveTick(uid, component, gameRule, frameTime);
if (Timing.CurTime < component.NextSwarmTime)
return;
RunSwarm((uid, component));
component.NextSwarmTime += RobustRandom.Next(component.MinSwarmDelay, component.MaxSwarmDelay);
}
private void RunSwarm(Entity<MeteorSchedulerComponent> ent)
{
var swarmWeights = _prototypeManager.Index(ent.Comp.Config);
GameTicker.StartGameRule(swarmWeights.Pick(RobustRandom));
}
}

View File

@@ -121,6 +121,18 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<float> public static readonly CVarDef<float>
EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 6f, CVar.ARCHIVE | CVar.SERVERONLY); EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 6f, CVar.ARCHIVE | CVar.SERVERONLY);
/// <summary>
/// Minimum time between meteor swarms in minutes.
/// </summary>
public static readonly CVarDef<float>
MeteorSwarmMinTime = CVarDef.Create("events.meteor_swarm_min_time", 12.5f, CVar.ARCHIVE | CVar.SERVERONLY);
/// <summary>
/// Maximum time between meteor swarms in minutes.
/// </summary>
public static readonly CVarDef<float>
MeteorSwarmMaxTime = CVarDef.Create("events.meteor_swarm_max_time", 17.5f, CVar.ARCHIVE | CVar.SERVERONLY);
/* /*
* Game * Game
*/ */

View File

@@ -87,9 +87,9 @@ namespace Content.Shared.Construction
foreach (var (stackId, amount) in comp.MaterialIdRequirements) foreach (var (stackId, amount) in comp.MaterialIdRequirements)
{ {
var stackProto = _prototype.Index<StackPrototype>(stackId); var stackProto = _prototype.Index<StackPrototype>(stackId);
var defaultProto = _prototype.Index(stackProto.Spawn);
if (_prototype.TryIndex(stackProto.Spawn, out var defaultProto) && if (defaultProto.TryGetComponent<PhysicalCompositionComponent>(out var physComp))
defaultProto.TryGetComponent<PhysicalCompositionComponent>(out var physComp))
{ {
foreach (var (mat, matAmount) in physComp.MaterialComposition) foreach (var (mat, matAmount) in physComp.MaterialComposition)
{ {

View File

@@ -1,4 +1,4 @@
using Content.Shared.Doors.Components; using Robust.Shared.GameStates;
namespace Content.Shared.Doors.Components namespace Content.Shared.Doors.Components
{ {
@@ -7,9 +7,11 @@ namespace Content.Shared.Doors.Components
/// auto-closing on depressurization, air/fire alarm interactions, and preventing normal door functions when /// auto-closing on depressurization, air/fire alarm interactions, and preventing normal door functions when
/// retaining pressure.. /// retaining pressure..
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class FirelockComponent : Component public sealed partial class FirelockComponent : Component
{ {
#region Settings
/// <summary> /// <summary>
/// Pry time modifier to be used when the firelock is currently closed due to fire or pressure. /// Pry time modifier to be used when the firelock is currently closed due to fire or pressure.
/// </summary> /// </summary>
@@ -17,8 +19,6 @@ namespace Content.Shared.Doors.Components
[DataField("lockedPryTimeModifier"), ViewVariables(VVAccess.ReadWrite)] [DataField("lockedPryTimeModifier"), ViewVariables(VVAccess.ReadWrite)]
public float LockedPryTimeModifier = 1.5f; public float LockedPryTimeModifier = 1.5f;
[DataField("autocloseDelay")] public TimeSpan AutocloseDelay = TimeSpan.FromSeconds(3f);
/// <summary> /// <summary>
/// Maximum pressure difference before the firelock will refuse to open, in kPa. /// Maximum pressure difference before the firelock will refuse to open, in kPa.
/// </summary> /// </summary>
@@ -39,5 +39,47 @@ namespace Content.Shared.Doors.Components
/// </summary> /// </summary>
[DataField("alarmAutoClose"), ViewVariables(VVAccess.ReadWrite)] [DataField("alarmAutoClose"), ViewVariables(VVAccess.ReadWrite)]
public bool AlarmAutoClose = true; public bool AlarmAutoClose = true;
/// <summary>
/// The cooldown duration before a firelock can automatically close due to a hazardous environment after it has
/// been pried open. Measured in seconds.
/// </summary>
[DataField]
public TimeSpan EmergencyCloseCooldownDuration = TimeSpan.FromSeconds(2);
#endregion
#region Set by system
/// <summary>
/// When the firelock will be allowed to automatically close again due to a hazardous environment.
/// </summary>
[DataField]
public TimeSpan? EmergencyCloseCooldown;
/// <summary>
/// Whether the firelock can open, or is locked due to its environment.
/// </summary>
public bool IsLocked => Pressure || Temperature;
/// <summary>
/// Whether the firelock is holding back a hazardous pressure.
/// </summary>
[DataField, AutoNetworkedField]
public bool Pressure;
/// <summary>
/// Whether the firelock is holding back extreme temperatures.
/// </summary>
[DataField, AutoNetworkedField]
public bool Temperature;
/// <summary>
/// Whether the airlock is powered.
/// </summary>
[DataField, AutoNetworkedField]
public bool Powered;
#endregion
} }
} }

View File

@@ -0,0 +1,124 @@
using Content.Shared.Access.Systems;
using Content.Shared.Doors.Components;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Content.Shared.Prying.Components;
using Robust.Shared.Timing;
namespace Content.Shared.Doors.Systems;
public abstract class SharedFirelockSystem : EntitySystem
{
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override void Initialize()
{
base.Initialize();
// Access/Prying
SubscribeLocalEvent<FirelockComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
SubscribeLocalEvent<FirelockComponent, GetPryTimeModifierEvent>(OnDoorGetPryTimeModifier);
SubscribeLocalEvent<FirelockComponent, PriedEvent>(OnAfterPried);
// Visuals
SubscribeLocalEvent<FirelockComponent, MapInitEvent>(UpdateVisuals);
SubscribeLocalEvent<FirelockComponent, ComponentStartup>(UpdateVisuals);
SubscribeLocalEvent<FirelockComponent, ExaminedEvent>(OnExamined);
}
public bool EmergencyPressureStop(EntityUid uid, FirelockComponent? firelock = null, DoorComponent? door = null)
{
if (!Resolve(uid, ref firelock, ref door))
return false;
if (door.State != DoorState.Open
|| firelock.EmergencyCloseCooldown != null
&& _gameTiming.CurTime < firelock.EmergencyCloseCooldown)
return false;
if (!_doorSystem.TryClose(uid, door))
return false;
return _doorSystem.OnPartialClose(uid, door);
}
#region Access/Prying
private void OnBeforeDoorOpened(EntityUid uid, FirelockComponent component, BeforeDoorOpenedEvent args)
{
// Give the Door remote the ability to force a firelock open even if it is holding back dangerous gas
var overrideAccess = (args.User != null) && _accessReaderSystem.IsAllowed(args.User.Value, uid);
if (!component.Powered || (!overrideAccess && component.IsLocked))
args.Cancel();
}
private void OnDoorGetPryTimeModifier(EntityUid uid, FirelockComponent component, ref GetPryTimeModifierEvent args)
{
if (component.Temperature)
{
_popupSystem.PopupClient(Loc.GetString("firelock-component-is-holding-fire-message"),
uid, args.User, PopupType.MediumCaution);
}
else if (component.Pressure)
{
_popupSystem.PopupClient(Loc.GetString("firelock-component-is-holding-pressure-message"),
uid, args.User, PopupType.MediumCaution);
}
if (component.IsLocked)
args.PryTimeModifier *= component.LockedPryTimeModifier;
}
private void OnAfterPried(EntityUid uid, FirelockComponent component, ref PriedEvent args)
{
component.EmergencyCloseCooldown = _gameTiming.CurTime + component.EmergencyCloseCooldownDuration;
}
#endregion
#region Visuals
private void UpdateVisuals(EntityUid uid, FirelockComponent component, EntityEventArgs args) => UpdateVisuals(uid, component);
private void UpdateVisuals(EntityUid uid,
FirelockComponent? firelock = null,
DoorComponent? door = null,
AppearanceComponent? appearance = null)
{
if (!Resolve(uid, ref door, ref appearance, false))
return;
// only bother to check pressure on doors that are some variation of closed.
if (door.State != DoorState.Closed
&& door.State != DoorState.Welded
&& door.State != DoorState.Denying)
{
_appearance.SetData(uid, DoorVisuals.ClosedLights, false, appearance);
return;
}
if (!Resolve(uid, ref firelock, ref appearance, false))
return;
_appearance.SetData(uid, DoorVisuals.ClosedLights, firelock.IsLocked, appearance);
}
#endregion
private void OnExamined(Entity<FirelockComponent> ent, ref ExaminedEvent args)
{
using (args.PushGroup(nameof(FirelockComponent)))
{
if (ent.Comp.Pressure)
args.PushMarkup(Loc.GetString("firelock-component-examine-pressure-warning"));
if (ent.Comp.Temperature)
args.PushMarkup(Loc.GetString("firelock-component-examine-temperature-warning"));
}
}
}

View File

@@ -29,7 +29,7 @@ namespace Content.Shared.Materials
/// include which stack we should spawn by default. /// include which stack we should spawn by default.
/// </summary> /// </summary>
[DataField] [DataField]
public ProtoId<EntityPrototype>? StackEntity; public EntProtoId? StackEntity;
[DataField] [DataField]
public string Name = string.Empty; public string Name = string.Empty;

View File

@@ -212,7 +212,7 @@ public sealed class MobThresholdSystem : EntitySystem
MobThresholdsComponent? thresholdComponent = null) MobThresholdsComponent? thresholdComponent = null)
{ {
threshold = null; threshold = null;
if (!Resolve(target, ref thresholdComponent)) if (!Resolve(target, ref thresholdComponent, false))
return false; return false;
return TryGetThresholdForState(target, MobState.Dead, out threshold, thresholdComponent); return TryGetThresholdForState(target, MobState.Dead, out threshold, thresholdComponent);

View File

@@ -4,7 +4,7 @@ using Robust.Shared.Utility;
namespace Content.Shared.Stacks; namespace Content.Shared.Stacks;
[Prototype("stack")] [Prototype]
public sealed partial class StackPrototype : IPrototype public sealed partial class StackPrototype : IPrototype
{ {
[ViewVariables] [ViewVariables]
@@ -15,33 +15,26 @@ public sealed partial class StackPrototype : IPrototype
/// Human-readable name for this stack type e.g. "Steel" /// Human-readable name for this stack type e.g. "Steel"
/// </summary> /// </summary>
/// <remarks>This is a localization string ID.</remarks> /// <remarks>This is a localization string ID.</remarks>
[DataField("name")] [DataField]
public string Name { get; private set; } = string.Empty; public string Name { get; private set; } = string.Empty;
/// <summary> /// <summary>
/// An icon that will be used to represent this stack type. /// An icon that will be used to represent this stack type.
/// </summary> /// </summary>
[DataField("icon")] [DataField]
public SpriteSpecifier? Icon { get; private set; } public SpriteSpecifier? Icon { get; private set; }
/// <summary> /// <summary>
/// The entity id that will be spawned by default from this stack. /// The entity id that will be spawned by default from this stack.
/// </summary> /// </summary>
[DataField("spawn", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))] [DataField(required: true)]
public string Spawn { get; private set; } = string.Empty; public EntProtoId Spawn { get; private set; } = string.Empty;
/// <summary> /// <summary>
/// The maximum amount of things that can be in a stack. /// The maximum amount of things that can be in a stack.
/// Can be overriden on <see cref="StackComponent"/> /// Can be overriden on <see cref="StackComponent"/>
/// if null, simply has unlimited max count. /// if null, simply has unlimited max count.
/// </summary> /// </summary>
[DataField("maxCount")] [DataField]
public int? MaxCount { get; private set; } public int? MaxCount { get; private set; }
/// <summary>
/// The size of an individual unit of this stack.
/// </summary>
[DataField("itemSize")]
public int? ItemSize;
} }

View File

@@ -117,3 +117,10 @@
license: "CC0-1.0" license: "CC0-1.0"
copyright: "Original sound by stomachache on freesound.org, processed by vanilla" copyright: "Original sound by stomachache on freesound.org, processed by vanilla"
source: "https://freesound.org/s/262213/" source: "https://freesound.org/s/262213/"
- files:
- "sheath.ogg"
- "unsheath.ogg"
license: "CC-BY-SA-3.0"
copyright: "Taken from tgstation."
source: "https://github.com/tgstation/tgstation/blob/a7f525bce9a359ab5282fc754078cd4b5678a006/sound/items"

Binary file not shown.

Binary file not shown.

View File

@@ -1,2 +1,4 @@
firelock-component-is-holding-pressure-message = A gush of air blows in your face... Maybe you should reconsider. firelock-component-is-holding-pressure-message = A gush of air blows in your face... Maybe you should reconsider.
firelock-component-is-holding-fire-message = A gush of warm air blows in your face... Maybe you should reconsider. firelock-component-is-holding-fire-message = A gush of warm air blows in your face... Maybe you should reconsider.
firelock-component-examine-pressure-warning = The [color=red]extreme pressure[/color] differential warning is active.
firelock-component-examine-temperature-warning = The [color=red]extreme temperature[/color] warning is active.

View File

@@ -1,2 +1,5 @@
station-event-meteor-swarm-start-announcement = Meteors are on a collision course with the station. Brace for impact. station-event-meteor-swarm-start-announcement = Meteors have been detected on collision course with the station.
station-event-meteor-swarm-end-announcement = The meteor swarm has passed. Please return to your stations. station-event-meteor-swarm-end-announcement = The meteor swarm has passed. Please return to your stations.
station-event-space-dust-start-announcement = The station is passing through a debris cloud, expect minor damage to external fittings and fixtures.
station-event-meteor-urist-start-announcement = The station is colliding with an unidentified swarm of debris. Please stay calm and do not listen to them.

View File

@@ -293,6 +293,9 @@ uplink-disposable-turret-desc = Looks and functions like a normal electrical too
uplink-cluster-banana-peel-name = Cluster Banana uplink-cluster-banana-peel-name = Cluster Banana
uplink-cluster-banana-peel-desc = Splits into 6 explosive banana peels after being thrown, the peels detonate automatically after 20 seconds if nobody slips on them. uplink-cluster-banana-peel-desc = Splits into 6 explosive banana peels after being thrown, the peels detonate automatically after 20 seconds if nobody slips on them.
uplink-cane-blade-name = Cane Blade
uplink-cane-blade-desc = A cane that has a hidden blade that can be unsheathed.
# Armor # Armor
uplink-chameleon-name = Chameleon Kit uplink-chameleon-name = Chameleon Kit
uplink-chameleon-desc = A backpack full of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! uplink-chameleon-desc = A backpack full of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more!

View File

@@ -4,6 +4,7 @@
BooksBag: 2 BooksBag: 2
BriefcaseBrown: 2 BriefcaseBrown: 2
HandLabeler: 2 HandLabeler: 2
Cane: 3
ClothingEyesGlasses: 2 ClothingEyesGlasses: 2
ClothingEyesGlassesJamjar: 2 ClothingEyesGlassesJamjar: 2
ClothingNeckScarfStripedGreen: 2 ClothingNeckScarfStripedGreen: 2

View File

@@ -1715,3 +1715,22 @@
- ResearchDirector - ResearchDirector
- Chef - Chef
- ResearchAssistant - ResearchAssistant
- type: listing
id: UplinkCaneBlade
name: uplink-cane-blade-name
description: uplink-cane-blade-desc
icon: { sprite: Objects/Weapons/Melee/cane.rsi, state: cane}
productEntity: CaneSheathFilled
cost:
Telecrystal: 5
categories:
- UplinkJob
conditions:
- !type:BuyerJobCondition
whitelist:
- Librarian
- !type:BuyerWhitelistCondition
blacklist:
components:
- SurplusBundle

View File

@@ -7,7 +7,7 @@
components: components:
- type: Tag - type: Tag
tags: # ignore "WhitelistChameleon" tag tags: # ignore "WhitelistChameleon" tag
- HidesNose - HidesNose
- type: Sprite - type: Sprite
sprite: Clothing/Mask/gas.rsi sprite: Clothing/Mask/gas.rsi
- type: Clothing - type: Clothing
@@ -19,8 +19,8 @@
- type: IdentityBlocker # need that for default ClothingMaskGas - type: IdentityBlocker # need that for default ClothingMaskGas
- type: UserInterface - type: UserInterface
interfaces: interfaces:
- key: enum.ChameleonUiKey.Key - key: enum.ChameleonUiKey.Key
type: ChameleonBoundUserInterface type: ChameleonBoundUserInterface
- type: entity - type: entity
parent: ClothingMaskGasChameleon parent: ClothingMaskGasChameleon
@@ -28,3 +28,29 @@
suffix: Voice Mask, Chameleon suffix: Voice Mask, Chameleon
components: components:
- type: VoiceMasker - type: VoiceMasker
- type: entity
parent: ClothingMaskBase
id: ClothingMaskWeldingGas
name: welding gas mask
description: A gas mask with built in welding goggles and face shield. Looks like a skull, clearly designed by a nerd.
components:
- type: Sprite
sprite: Clothing/Mask/welding-gas.rsi
state: icon
- type: Clothing
sprite: Clothing/Mask/welding-gas.rsi
- type: BreathMask
- type: IngestionBlocker
- type: IdentityBlocker
- type: FlashImmunity
- type: EyeProtection
- type: PhysicalComposition
materialComposition:
Steel: 200
Glass: 100
- type: StaticPrice
price: 100
- type: Tag
tags:
- WhitelistChameleon

View File

@@ -742,6 +742,9 @@
- type: Sprite - type: Sprite
layers: layers:
- state: moldy-slice - state: moldy-slice
- type: Tag
tags:
- Trash
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
food: food:

View File

@@ -521,6 +521,9 @@
- type: Sprite - type: Sprite
layers: layers:
- state: moldy-slice - state: moldy-slice
- type: Tag
tags:
- Trash
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
food: food:

View File

@@ -9,6 +9,8 @@
sprite: Objects/Misc/stock_parts.rsi sprite: Objects/Misc/stock_parts.rsi
- type: Item - type: Item
size: Tiny size: Tiny
- type: Stack
count: 1
- type: entity - type: entity
id: CapacitorStockPart id: CapacitorStockPart
@@ -25,6 +27,8 @@
- type: Tag - type: Tag
tags: tags:
- CapacitorStockPart - CapacitorStockPart
- type: Stack
stackType: Capacitor
- type: entity - type: entity
id: MicroManipulatorStockPart id: MicroManipulatorStockPart
@@ -38,6 +42,8 @@
- type: MachinePart - type: MachinePart
part: Manipulator part: Manipulator
rating: 1 rating: 1
- type: Stack
stackType: MicroManipulator
- type: entity - type: entity
id: MatterBinStockPart id: MatterBinStockPart
@@ -51,3 +57,5 @@
- type: MachinePart - type: MachinePart
part: MatterBin part: MatterBin
rating: 1 rating: 1
- type: Stack
stackType: MatterBin

View File

@@ -7,7 +7,6 @@
state: extraction_pack state: extraction_pack
spawn: Fulton1 spawn: Fulton1
maxCount: 10 maxCount: 10
itemSize: 2
# Entities # Entities
- type: entity - type: entity

View File

@@ -420,7 +420,7 @@
whitelist: whitelist:
tags: tags:
- CartridgeRocket - CartridgeRocket
proto: MeteorLarge proto: MeteorMedium
- type: GiftIgnore - type: GiftIgnore
- type: entity - type: entity

View File

@@ -1,40 +1,206 @@
- type: entity - type: entity
id: MeteorLarge id: BaseMeteor
name: meteor name: meteor
noSpawn: true description: You prefer them when they're burning up in the atmosphere.
abstract: true
components: components:
- type: Sprite - type: Sprite
noRot: false noRot: false
sprite: Objects/Weapons/Guns/Projectiles/meteor.rsi sprite: Objects/Misc/meteor.rsi
scale: 4,4
layers:
- state: large
shader: unshaded
- type: ExplodeOnTrigger
- type: DeleteOnTrigger
- type: TriggerOnCollide
fixtureID: projectile
- type: Projectile - type: Projectile
damage: {} damage: {}
deleteOnCollide: false deleteOnCollide: false
- type: Explosive - type: Meteor
explosionType: Default damageTypes:
totalIntensity: 600.0 types:
intensitySlope: 30 Blunt: 1
maxIntensity: 45 - type: TimedDespawn
lifetime: 120
- type: Clickable
- type: Physics - type: Physics
bodyType: Dynamic bodyType: Dynamic
bodyStatus: InAir
angularDamping: 0
linearDamping: 0
- type: Fixtures - type: Fixtures
fixtures: fixtures:
projectile: projectile:
shape: shape:
!type:PhysShapeCircle !type:PhysShapeCircle
radius: 0.8 radius: 0.4
density: 100 density: 100
hard: true hard: false
# Didn't use MapGridComponent for now as the bounds are stuffed.
layer: layer:
- LargeMobLayer - LargeMobLayer
mask: mask:
- Impassable - Impassable
- BulletImpassable - BulletImpassable
- type: Damageable
damageContainer: Inorganic
- type: Explosive
explosionType: Default
intensitySlope: 4
maxIntensity: 100
- type: entity
parent: BaseMeteor
id: MeteorSpaceDust
name: space dust
description: Makes a station sneeze.
components:
- type: Sprite
state: space_dust
- type: Fixtures
fixtures:
projectile:
shape:
!type:PhysShapeCircle
radius: 0.45
density: 100
hard: false
layer:
- LargeMobLayer
mask:
- Impassable
- BulletImpassable
- type: Explosive
totalIntensity: 25
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:ExplodeBehavior
- type: entity
parent: BaseMeteor
id: MeteorSmall
suffix: Small
components:
- type: Sprite
state: small
- type: Fixtures
fixtures:
projectile:
shape:
!type:PhysShapeCircle
radius: 0.25
density: 100
hard: false
layer:
- LargeMobLayer
mask:
- Impassable
- BulletImpassable
- type: Explosive
totalIntensity: 100
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 1250
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:ExplodeBehavior
- type: entity
parent: BaseMeteor
id: MeteorMedium
suffix: Medium
components:
- type: Sprite
state: medium
- type: Fixtures
fixtures:
projectile:
shape:
!type:PhysShapeCircle
radius: 0.3
density: 100
hard: false
layer:
- LargeMobLayer
mask:
- Impassable
- BulletImpassable
- type: Explosive
totalIntensity: 200
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 1750
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:ExplodeBehavior
- type: entity
parent: BaseMeteor
id: MeteorLarge
suffix: Large
components:
- type: Sprite
state: big
- type: Explosive
totalIntensity: 300
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 2500
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:ExplodeBehavior
- type: entity
parent: BaseMeteor
id: MeteorUrist
name: Urist McMeteor
description: As a successful member of society with a stable unflinching psyche and limitless drive, natural affinity for finance and domination, you have been selected, no, you have been effortlessly guided by divine (biological) trauma towards this moment. The gates of destiny fling open, and once again you're left standing on pulsating nothingness. A strobing headache of the soul.
suffix: Meteor
components:
- type: Sprite
state: human_pixel
- type: SolutionContainerManager
solutions:
blood:
maxVol: 1000
reagents:
- ReagentId: Blood
Quantity: 1000
- type: Explosive
totalIntensity: 25
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 3000
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MaleScreams
params:
volume: 10
- !type:SpillBehavior
solution: blood
- !type:ExplodeBehavior

View File

@@ -0,0 +1,97 @@
- type: entity
parent: BaseItem
id: Cane
name: cane
description: A wooden cane.
components:
- type: Sprite
sprite: Objects/Weapons/Melee/cane.rsi
state: cane
- type: Item
size: Normal
sprite: Objects/Weapons/Melee/cane.rsi
- type: Appearance
- type: MeleeWeapon
wideAnimationRotation: 45
damage:
types:
Blunt: 5
- type: StaminaDamageOnHit
damage: 5
- type: Wieldable
- type: IncreaseDamageOnWield
damage:
types:
Blunt: 3
- type: UseDelay
delay: 1
- type: entity
name: cane blade
parent: BaseItem
id: CaneBlade
description: A sharp blade with a cane shaped hilt.
components:
- type: Sharp
- type: Sprite
sprite: Objects/Weapons/Melee/cane_blade.rsi
state: icon
- type: MeleeWeapon
wideAnimationRotation: 65
attackRate: 1.5
damage:
types:
Slash: 14
soundHit:
path: /Audio/Weapons/bladeslice.ogg
- type: Item
size: Normal
sprite: Objects/Weapons/Melee/cane_blade.rsi
- type: Tag
tags:
- CaneBlade
- type: DisarmMalus
- type: entity
parent: Cane
id: CaneSheath
suffix: Empty
components:
- type: Sprite
sprite: Objects/Weapons/Melee/cane.rsi
state: cane-empty
- type: ContainerContainer
containers:
storagebase: !type:Container
ents: []
- type: UserInterface
interfaces:
- key: enum.StorageUiKey.Key
type: StorageBoundUserInterface
- type: ItemSlots
slots:
item:
name: CaneBlade
insertVerbText: sheath-insert-verb
ejectVerbText: sheath-eject-verb
whitelist:
tags:
- CaneBlade
insertSound: /Audio/Items/sheath.ogg
ejectSound: /Audio/Items/unsheath.ogg
- type: ItemMapper
mapLayers:
cane:
whitelist:
tags:
- CaneBlade
- type: entity
id: CaneSheathFilled
parent: CaneSheath
suffix: Filled
components:
- type: ContainerFill
containers:
item:
- CaneBlade

View File

@@ -317,6 +317,7 @@
- PowerCellMicroreactor - PowerCellMicroreactor
- PowerCellHigh - PowerCellHigh
- WeaponPistolCHIMP - WeaponPistolCHIMP
- ClothingMaskWeldingGas
- WeaponGauntletGorilla - WeaponGauntletGorilla
- SynthesizerInstrument - SynthesizerInstrument
- ClothingShoesBootsMagSci - ClothingShoesBootsMagSci

View File

@@ -32,7 +32,9 @@
collection: MetalBreak collection: MetalBreak
- type: UseDelay - type: UseDelay
delay: 0.2 # prevent light-toggling auto-clickers. delay: 0.2 # prevent light-toggling auto-clickers.
# WD edit start - type: Tag
tags:
- Structure
- type: entity - type: entity
id: SignalSwitch id: SignalSwitch

View File

@@ -158,25 +158,6 @@
duration: 240 duration: 240
- type: KudzuGrowthRule - type: KudzuGrowthRule
- type: entity
id: MeteorSwarm
parent: BaseGameRule
noSpawn: true
components:
- type: StationEvent
earliestStart: 30
weight: 7.5
minimumPlayers: 10 #Enough to hopefully have at least one engineering guy
startAnnouncement: station-event-meteor-swarm-start-announcement
endAnnouncement: station-event-meteor-swarm-end-announcement
startAudio:
path: /Audio/Announcements/meteors.ogg
params:
volume: -4
duration: null #ending is handled by MeteorSwarmRule
startDelay: 30
- type: MeteorSwarmRule
- type: entity - type: entity
id: MouseMigration id: MouseMigration
parent: BaseGameRule parent: BaseGameRule

View File

@@ -0,0 +1,111 @@
- type: entity
parent: BaseGameRule
id: GameRuleMeteorScheduler
noSpawn: true
components:
- type: GameRule
minPlayers: 25
- type: MeteorScheduler
- type: weightedRandomEntity
id: DefaultConfig
weights:
GameRuleSpaceDustMinor: 44
GameRuleSpaceDustMajor: 22
GameRuleMeteorSwarmSmall: 18
GameRuleMeteorSwarmMedium: 10
GameRuleMeteorSwarmLarge: 5
GameRuleUristSwarm: 0.05
- type: entity
parent: BaseGameRule
id: GameRuleMeteorSwarm
noSpawn: true
components:
- type: GameRule
- type: MeteorSwarm
- type: entity
parent: GameRuleMeteorSwarm
id: GameRuleSpaceDustMinor
noSpawn: true
components:
- type: MeteorSwarm
announcement: null
announcementSound: null
nonDirectional: true
meteors:
MeteorSpaceDust: 1
waves:
min: 2
max: 3
meteorsPerWave:
min: 3
max: 5
- type: entity
parent: GameRuleMeteorSwarm
id: GameRuleSpaceDustMajor
noSpawn: true
components:
- type: MeteorSwarm
announcement: station-event-space-dust-start-announcement
announcementSound: /Audio/Announcements/attention.ogg
nonDirectional: true
meteors:
MeteorSpaceDust: 1
waves:
min: 2
max: 3
meteorsPerWave:
min: 8
max: 12
- type: entity
parent: GameRuleMeteorSwarm
id: GameRuleMeteorSwarmSmall
noSpawn: true
components:
- type: MeteorSwarm
meteors:
MeteorSmall: 7
MeteorMedium: 3
- type: entity
parent: GameRuleMeteorSwarm
id: GameRuleMeteorSwarmMedium
noSpawn: true
components:
- type: MeteorSwarm
meteors:
MeteorSmall: 3
MeteorMedium: 6
MeteorLarge: 1
- type: entity
parent: GameRuleMeteorSwarm
id: GameRuleMeteorSwarmLarge
noSpawn: true
components:
- type: MeteorSwarm
meteors:
MeteorSmall: 2
MeteorMedium: 4
MeteorLarge: 4
- type: entity
parent: GameRuleMeteorSwarm
id: GameRuleUristSwarm
noSpawn: true
components:
- type: MeteorSwarm
announcement: station-event-meteor-urist-start-announcement
announcementSound: /Audio/Announcements/attention.ogg
meteors:
MeteorUrist: 1
waves:
min: 3
max: 3
meteorsPerWave:
min: 10
max: 10

View File

@@ -17,6 +17,29 @@
- !type:HTNCompoundTask - !type:HTNCompoundTask
task: PickupMeleeCompound task: PickupMeleeCompound
- preconditions:
- !type:BuckledPrecondition
isBuckled: true
tasks:
- !type:HTNPrimitiveTask
shutdownState: TaskFinished
operator: !type:UnbuckleOperator
- preconditions:
- !type:InContainerPrecondition
isInContainer: true
tasks:
- !type:HTNCompoundTask
task: EscapeCompound
- preconditions:
- !type:PulledPrecondition
isPulled: true
tasks:
- !type:HTNPrimitiveTask
shutdownState: TaskFinished
operator: !type:UnPullOperator
# Melee combat (unarmed or otherwise) # Melee combat (unarmed or otherwise)
- tasks: - tasks:
- !type:HTNPrimitiveTask - !type:HTNPrimitiveTask
@@ -101,6 +124,21 @@
proto: NearbyMeleeTargets proto: NearbyMeleeTargets
key: Target key: Target
- type: htnCompound
id: EscapeCompound
branches:
- tasks:
- !type:HTNPrimitiveTask
shutdownState: TaskFinished
operator: !type:ContainerOperator
targetKey: Target
- !type:HTNPrimitiveTask
operator: !type:EscapeOperator
targetKey: Target
preconditions:
- !type:InContainerPrecondition
isInContainer: true
- type: htnCompound - type: htnCompound
id: MeleeAttackOrderedTargetCompound id: MeleeAttackOrderedTargetCompound
branches: branches:

View File

@@ -76,7 +76,7 @@
Steel: 100 Steel: 100
Plastic: 200 Plastic: 200
Glass: 100 Glass: 100
- type: latheRecipe - type: latheRecipe
id: SignallerAdvanced id: SignallerAdvanced
result: RemoteSignallerAdvanced result: RemoteSignallerAdvanced
@@ -175,6 +175,14 @@
Plasma: 1500 Plasma: 1500
Uranium: 150 Uranium: 150
- type: latheRecipe
id: ClothingMaskWeldingGas
result: ClothingMaskWeldingGas
completetime: 3
materials:
Steel: 600
Glass: 200
- type: latheRecipe - type: latheRecipe
id: WeaponForceGun id: WeaponForceGun
result: WeaponForceGun result: WeaponForceGun

View File

@@ -14,6 +14,7 @@
- BorgModuleMining - BorgModuleMining
- OreProcessorIndustrialMachineCircuitboard - OreProcessorIndustrialMachineCircuitboard
- OreBagOfHolding - OreBagOfHolding
- ClothingMaskWeldingGas
- type: technology - type: technology
id: AdvancedPowercells id: AdvancedPowercells

View File

@@ -4,7 +4,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: glass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: glass }
spawn: SheetGlass1 spawn: SheetGlass1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: ReinforcedGlass id: ReinforcedGlass
@@ -12,7 +11,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: rglass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: rglass }
spawn: SheetRGlass1 spawn: SheetRGlass1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: PlasmaGlass id: PlasmaGlass
@@ -20,7 +18,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: pglass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: pglass }
spawn: SheetPGlass1 spawn: SheetPGlass1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: ReinforcedPlasmaGlass id: ReinforcedPlasmaGlass
@@ -28,7 +25,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: rpglass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: rpglass }
spawn: SheetRPGlass1 spawn: SheetRPGlass1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: UraniumGlass id: UraniumGlass
@@ -36,7 +32,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: uglass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: uglass }
spawn: SheetUGlass1 spawn: SheetUGlass1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: ReinforcedUraniumGlass id: ReinforcedUraniumGlass
@@ -44,7 +39,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: ruglass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: ruglass }
spawn: SheetRUGlass1 spawn: SheetRUGlass1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: ClockworkGlass id: ClockworkGlass
@@ -52,4 +46,3 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: cglass } icon: { sprite: /Textures/Objects/Materials/Sheets/glass.rsi, state: cglass }
spawn: SheetClockworkGlass1 spawn: SheetClockworkGlass1
maxCount: 30 maxCount: 30
itemSize: 1

View File

@@ -4,7 +4,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/metal.rsi, state: steel } icon: { sprite: /Textures/Objects/Materials/Sheets/metal.rsi, state: steel }
spawn: SheetSteel1 spawn: SheetSteel1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Plasteel id: Plasteel
@@ -12,7 +11,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/metal.rsi, state: plasteel } icon: { sprite: /Textures/Objects/Materials/Sheets/metal.rsi, state: plasteel }
spawn: SheetPlasteel1 spawn: SheetPlasteel1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Brass id: Brass
@@ -20,4 +18,3 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/metal.rsi, state: brass } icon: { sprite: /Textures/Objects/Materials/Sheets/metal.rsi, state: brass }
spawn: SheetBrass1 spawn: SheetBrass1
maxCount: 30 maxCount: 30
itemSize: 1

View File

@@ -4,7 +4,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: paper } icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: paper }
spawn: SheetPaper1 spawn: SheetPaper1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Plasma id: Plasma
@@ -12,7 +11,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: plasma } icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: plasma }
spawn: SheetPlasma1 spawn: SheetPlasma1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Plastic id: Plastic
@@ -20,7 +18,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: plastic } icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: plastic }
spawn: SheetPlastic1 spawn: SheetPlastic1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Uranium id: Uranium
@@ -28,4 +25,3 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: uranium } icon: { sprite: /Textures/Objects/Materials/Sheets/other.rsi, state: uranium }
spawn: SheetUranium1 spawn: SheetUranium1
maxCount: 30 maxCount: 30
itemSize: 1

View File

@@ -3,4 +3,3 @@
name: telecrystal name: telecrystal
icon: Objects/Specific/Syndicate/telecrystal.rsi icon: Objects/Specific/Syndicate/telecrystal.rsi
spawn: Telecrystal1 spawn: Telecrystal1
itemSize: 1

View File

@@ -4,7 +4,6 @@
icon: { sprite: "/Textures/Objects/Materials/ingots.rsi", state: gold } icon: { sprite: "/Textures/Objects/Materials/ingots.rsi", state: gold }
spawn: IngotGold1 spawn: IngotGold1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Silver id: Silver
@@ -12,4 +11,3 @@
icon: { sprite: "/Textures/Objects/Materials/ingots.rsi", state: silver } icon: { sprite: "/Textures/Objects/Materials/ingots.rsi", state: silver }
spawn: IngotSilver1 spawn: IngotSilver1
maxCount: 30 maxCount: 30
itemSize: 1

View File

@@ -1,66 +1,65 @@
- type: stack - type: stack
id: Biomass id: Biomass
name: биомасса name: biomass
icon: { sprite: /Textures/Objects/Misc/monkeycube.rsi, state: cube } icon: { sprite: /Textures/Objects/Misc/monkeycube.rsi, state: cube }
spawn: MaterialBiomass1 spawn: MaterialBiomass1
maxCount: 100 maxCount: 100
itemSize: 1
- type: stack - type: stack
id: WoodPlank id: WoodPlank
name: древесина name: wood plank
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: wood } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: wood }
spawn: MaterialWoodPlank1 spawn: MaterialWoodPlank1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Cardboard id: Cardboard
name: картонная коробка name: cardboard
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cardboard } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cardboard }
spawn: MaterialCardboard1 spawn: MaterialCardboard1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Cloth id: Cloth
name: ткань name: cloth
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cloth } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cloth }
spawn: MaterialCloth1 spawn: MaterialCloth1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Durathread id: Durathread
name: дюраткань name: durathread
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: durathread } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: durathread }
spawn: MaterialDurathread1 spawn: MaterialDurathread1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Diamond id: Diamond
name: алмаз name: diamond
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: diamond } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: diamond }
spawn: MaterialDiamond1 spawn: MaterialDiamond1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: Cotton id: Cotton
name: хлопок name: cotton
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cotton } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cotton }
spawn: MaterialCotton1 spawn: MaterialCotton1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack
id: Pyrotton
name: pyrotton
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: pyrotton }
spawn: MaterialPyrotton1
maxCount: 30
- type: stack - type: stack
id: Bananium id: Bananium
name: бананиум name: bananium
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: bananium } icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: bananium }
spawn: MaterialBananium1 spawn: MaterialBananium1
maxCount: 10 maxCount: 10
itemSize: 2
- type: stack - type: stack
id: MeatSheets id: MeatSheets
@@ -68,7 +67,6 @@
icon: { sprite: /Textures/Objects/Materials/Sheets/meaterial.rsi, state: meat } icon: { sprite: /Textures/Objects/Materials/Sheets/meaterial.rsi, state: meat }
spawn: MaterialSheetMeat1 spawn: MaterialSheetMeat1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: WebSilk id: WebSilk
@@ -76,7 +74,6 @@
icon: { sprite: /Textures/Objects/Materials/silk.rsi, state: icon } icon: { sprite: /Textures/Objects/Materials/silk.rsi, state: icon }
spawn: MaterialWebSilk1 spawn: MaterialWebSilk1
maxCount: 50 maxCount: 50
itemSize: 1
- type: stack - type: stack
id: Bones id: Bones
@@ -84,7 +81,6 @@
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: bones} icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: bones}
spawn: MaterialBones1 spawn: MaterialBones1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: RunicMetalSheets id: RunicMetalSheets
@@ -92,12 +88,10 @@
icon: { sprite: /Textures/White/Cult/Entities/runic_metal.rsi, state: runic} icon: { sprite: /Textures/White/Cult/Entities/runic_metal.rsi, state: runic}
spawn: CultRunicMetal1 spawn: CultRunicMetal1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: Gunpowder id: Gunpowder
name: порох name: gunpowder
icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile } icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile }
spawn: MaterialGunpowder spawn: MaterialGunpowder
maxCount: 60 maxCount: 60
itemSize: 1

View File

@@ -4,7 +4,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: gold } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: gold }
spawn: GoldOre1 spawn: GoldOre1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: SteelOre id: SteelOre
@@ -12,7 +11,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: iron } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: iron }
spawn: SteelOre1 spawn: SteelOre1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: PlasmaOre id: PlasmaOre
@@ -20,7 +18,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: plasma } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: plasma }
spawn: PlasmaOre1 spawn: PlasmaOre1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: SilverOre id: SilverOre
@@ -28,7 +25,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: silver } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: silver }
spawn: SilverOre1 spawn: SilverOre1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: SpaceQuartz id: SpaceQuartz
@@ -36,7 +32,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: spacequartz } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: spacequartz }
spawn: SpaceQuartz1 spawn: SpaceQuartz1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: UraniumOre id: UraniumOre
@@ -44,7 +39,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: uranium } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: uranium }
spawn: UraniumOre1 spawn: UraniumOre1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
@@ -53,7 +47,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: bananium } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: bananium }
spawn: BananiumOre1 spawn: BananiumOre1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: Coal id: Coal
@@ -61,7 +54,6 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: coal } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: coal }
spawn: Coal1 spawn: Coal1
maxCount: 30 maxCount: 30
itemSize: 2
- type: stack - type: stack
id: SaltOre id: SaltOre
@@ -69,4 +61,3 @@
icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: salt } icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: salt }
spawn: Salt1 spawn: Salt1
maxCount: 30 maxCount: 30
itemSize: 2

View File

@@ -4,4 +4,3 @@
icon: { sprite: /Textures/Objects/Materials/parts.rsi, state: rods } icon: { sprite: /Textures/Objects/Materials/parts.rsi, state: rods }
spawn: PartRodMetal1 spawn: PartRodMetal1
maxCount: 30 maxCount: 30
itemSize: 1

View File

@@ -5,7 +5,6 @@
name: pancake name: pancake
spawn: FoodBakedPancake spawn: FoodBakedPancake
maxCount: 3 maxCount: 3
itemSize: 1
# Food Containers # Food Containers
@@ -15,54 +14,60 @@
icon: { sprite: Objects/Consumable/Food/Baked/pizza.rsi, state: box } icon: { sprite: Objects/Consumable/Food/Baked/pizza.rsi, state: box }
spawn: FoodBoxPizza spawn: FoodBoxPizza
maxCount: 30 maxCount: 30
itemSize: 10
# Smokeables # Smokeables
- type: stack - type: stack
id: PaperRolling id: PaperRolling
name: самокрутка name: rolling paper
icon: { sprite: /Textures/Objects/Consumable/Smokeables/Cigarettes/paper.rsi, state: cigpaper } icon: { sprite: /Textures/Objects/Consumable/Smokeables/Cigarettes/paper.rsi, state: cigpaper }
spawn: PaperRolling spawn: PaperRolling
maxCount: 5 maxCount: 5
itemSize: 1
- type: stack - type: stack
id: CigaretteFilter id: CigaretteFilter
name: фильтр name: cigarette filter
icon: { sprite: /Textures/Objects/Consumable/Smokeables/Cigarettes/paper.rsi, state: cigfilter } icon: { sprite: /Textures/Objects/Consumable/Smokeables/Cigarettes/paper.rsi, state: cigfilter }
spawn: CigaretteFilter spawn: CigaretteFilter
maxCount: 5 maxCount: 5
itemSize: 2
- type: stack - type: stack
id: GroundTobacco id: GroundTobacco
name: измельчённый табак name: ground tobacco
icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile } icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile }
spawn: GroundTobacco spawn: GroundTobacco
maxCount: 5 maxCount: 5
itemSize: 1
- type: stack - type: stack
id: GroundCannabis id: GroundCannabis
name: измельчённый каннабис name: ground cannabis
icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile } icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile }
spawn: GroundCannabis spawn: GroundCannabis
maxCount: maxCount:
itemSize: 1
- type: stack
id: GroundCannabisRainbow
name: ground rainbow cannabis
icon: { sprite: /Textures/Objects/Specific/Hydroponics/rainbow_cannabis.rsi, state: powderpile_rainbow }
spawn: GroundCannabisRainbow
maxCount:
- type: stack - type: stack
id: LeavesTobaccoDried id: LeavesTobaccoDried
name: высушеные листья табака name: dried tobacco leaves
icon: { sprite: /Textures/Objects/Specific/Hydroponics/tobacco.rsi, state: dried } icon: { sprite: /Textures/Objects/Specific/Hydroponics/tobacco.rsi, state: dried }
spawn: LeavesTobaccoDried spawn: LeavesTobaccoDried
maxCount: 5 maxCount: 5
itemSize: 5
- type: stack - type: stack
id: LeavesCannabisDried id: LeavesCannabisDried
name: высушеные листья каннабиса name: dried cannabis leaves
icon: { sprite: /Textures/Objects/Specific/Hydroponics/tobacco.rsi, state: dried } icon: { sprite: /Textures/Objects/Specific/Hydroponics/tobacco.rsi, state: dried }
spawn: LeavesCannabisDried spawn: LeavesCannabisDried
maxCount: 5 maxCount: 5
itemSize: 5
- type: stack
id: LeavesCannabisRainbowDried
name: dried rainbow cannabis leaves
icon: { sprite: /Textures/Objects/Specific/Hydroponics/rainbow_cannabis.rsi, state: dried }
spawn: LeavesCannabisRainbowDried

View File

@@ -4,11 +4,9 @@
name: inflatable wall name: inflatable wall
spawn: InflatableWallStack1 spawn: InflatableWallStack1
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: InflatableDoor id: InflatableDoor
name: inflatable door name: inflatable door
spawn: InflatableDoorStack1 spawn: InflatableDoorStack1
maxCount: 4 maxCount: 4
itemSize: 1

View File

@@ -3,469 +3,402 @@
name: steel tile name: steel tile
spawn: FloorTileItemSteel spawn: FloorTileItemSteel
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMetalDiamond id: FloorTileMetalDiamond
name: steel tile name: steel tile
spawn: FloorTileItemMetalDiamond spawn: FloorTileItemMetalDiamond
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileWood id: FloorTileWood
name: wood floor name: wood floor
spawn: FloorTileItemWood spawn: FloorTileItemWood
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileWhite id: FloorTileWhite
name: white tile name: white tile
spawn: FloorTileItemWhite spawn: FloorTileItemWhite
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileDark id: FloorTileDark
name: dark tile name: dark tile
spawn: FloorTileItemDark spawn: FloorTileItemDark
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileTechmaint id: FloorTileTechmaint
name: techmaint floor name: techmaint floor
spawn: FloorTileItemTechmaint spawn: FloorTileItemTechmaint
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileFreezer id: FloorTileFreezer
name: freezer tile name: freezer tile
spawn: FloorTileItemFreezer spawn: FloorTileItemFreezer
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileShowroom id: FloorTileShowroom
name: showroom tile name: showroom tile
spawn: FloorTileItemShowroom spawn: FloorTileItemShowroom
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileGCircuit id: FloorTileGCircuit
name: green-circuit floor name: green-circuit floor
spawn: FloorTileItemGCircuit spawn: FloorTileItemGCircuit
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileGold id: FloorTileGold
name: gold floor name: gold floor
spawn: FloorTileItemGold spawn: FloorTileItemGold
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileReinforced id: FloorTileReinforced
name: reinforced tile name: reinforced tile
spawn: FloorTileItemReinforced spawn: FloorTileItemReinforced
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMono id: FloorTileMono
name: mono tile name: mono tile
spawn: FloorTileItemMono spawn: FloorTileItemMono
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileBrassFilled id: FloorTileBrassFilled
name: filled brass plate name: filled brass plate
spawn: FloorTileItemBrassFilled spawn: FloorTileItemBrassFilled
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileBrassReebe id: FloorTileBrassReebe
name: smooth brass plate name: smooth brass plate
spawn: FloorTileItemBrassReebe spawn: FloorTileItemBrassReebe
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileLino id: FloorTileLino
name: linoleum floor name: linoleum floor
spawn: FloorTileItemLino spawn: FloorTileItemLino
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileHydro id: FloorTileHydro
name: hydro tile name: hydro tile
spawn: FloorTileItemHydro spawn: FloorTileItemHydro
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileLime id: FloorTileLime
name: lime tile name: lime tile
spawn: FloorTileItemLime spawn: FloorTileItemLime
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileDirty id: FloorTileDirty
name: dirty tile name: dirty tile
spawn: FloorTileItemDirty spawn: FloorTileItemDirty
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttleWhite id: FloorTileStackShuttleWhite
name: white shuttle tile name: white shuttle tile
spawn: FloorTileItemShuttleWhite spawn: FloorTileItemShuttleWhite
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttleBlue id: FloorTileStackShuttleBlue
name: blue shuttle tile name: blue shuttle tile
spawn: FloorTileItemShuttleBlue spawn: FloorTileItemShuttleBlue
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttleOrange id: FloorTileStackShuttleOrange
name: orange shuttle tile name: orange shuttle tile
spawn: FloorTileItemShuttleOrange spawn: FloorTileItemShuttleOrange
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttlePurple id: FloorTileStackShuttlePurple
name: purple shuttle tile name: purple shuttle tile
spawn: FloorTileItemShuttlePurple spawn: FloorTileItemShuttlePurple
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttleRed id: FloorTileStackShuttleRed
name: red shuttle tile name: red shuttle tile
spawn: FloorTileItemShuttleRed spawn: FloorTileItemShuttleRed
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttleGrey id: FloorTileStackShuttleGrey
name: grey shuttle tile name: grey shuttle tile
spawn: FloorTileItemShuttleGrey spawn: FloorTileItemShuttleGrey
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackShuttleBlack id: FloorTileStackShuttleBlack
name: black shuttle tile name: black shuttle tile
spawn: FloorTileItemShuttleBlack spawn: FloorTileItemShuttleBlack
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackEighties id: FloorTileStackEighties
name: eighties floor tile name: eighties floor tile
spawn: FloorTileItemEighties spawn: FloorTileItemEighties
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackArcadeBlue id: FloorTileStackArcadeBlue
name: blue arcade tile name: blue arcade tile
spawn: FloorTileItemArcadeBlue spawn: FloorTileItemArcadeBlue
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackArcadeBlue2 id: FloorTileStackArcadeBlue2
name: blue arcade tile name: blue arcade tile
spawn: FloorTileItemArcadeBlue2 spawn: FloorTileItemArcadeBlue2
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackArcadeRed id: FloorTileStackArcadeRed
name: red arcade tile name: red arcade tile
spawn: FloorTileItemArcadeRed spawn: FloorTileItemArcadeRed
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetRed id: FloorCarpetRed
name: red carpet tile name: red carpet tile
spawn: FloorCarpetItemRed spawn: FloorCarpetItemRed
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetBlack id: FloorCarpetBlack
name: block carpet tile name: block carpet tile
spawn: FloorCarpetItemBlack spawn: FloorCarpetItemBlack
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetBlue id: FloorCarpetBlue
name: blue carpet tile name: blue carpet tile
spawn: FloorCarpetItemBlue spawn: FloorCarpetItemBlue
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetGreen id: FloorCarpetGreen
name: green carpet tile name: green carpet tile
spawn: FloorCarpetItemGreen spawn: FloorCarpetItemGreen
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetOrange id: FloorCarpetOrange
name: orange carpet tile name: orange carpet tile
spawn: FloorCarpetItemOrange spawn: FloorCarpetItemOrange
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetSkyBlue id: FloorCarpetSkyBlue
name: skyblue carpet tile name: skyblue carpet tile
spawn: FloorCarpetItemSkyBlue spawn: FloorCarpetItemSkyBlue
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetPurple id: FloorCarpetPurple
name: purple carpet tile name: purple carpet tile
spawn: FloorCarpetItemPurple spawn: FloorCarpetItemPurple
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetPink id: FloorCarpetPink
name: pink carpet tile name: pink carpet tile
spawn: FloorCarpetItemPink spawn: FloorCarpetItemPink
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetCyan id: FloorCarpetCyan
name: cyan carpet tile name: cyan carpet tile
spawn: FloorCarpetItemCyan spawn: FloorCarpetItemCyan
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorCarpetWhite id: FloorCarpetWhite
name: white carpet tile name: white carpet tile
spawn: FloorCarpetItemWhite spawn: FloorCarpetItemWhite
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackCarpetClown id: FloorTileStackCarpetClown
name: clown carpet tile name: clown carpet tile
spawn: FloorTileItemCarpetClown spawn: FloorTileItemCarpetClown
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackCarpetOffice id: FloorTileStackCarpetOffice
name: office carpet tile name: office carpet tile
spawn: FloorTileItemCarpetOffice spawn: FloorTileItemCarpetOffice
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackBoxing id: FloorTileStackBoxing
name: boxing ring tile name: boxing ring tile
spawn: FloorTileItemBoxing spawn: FloorTileItemBoxing
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileStackGym id: FloorTileStackGym
name: gym floor tile name: gym floor tile
spawn: FloorTileItemGym spawn: FloorTileItemGym
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileElevatorShaft id: FloorTileElevatorShaft
name: elevator shaft tile name: elevator shaft tile
spawn: FloorTileItemElevatorShaft spawn: FloorTileItemElevatorShaft
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileRockVault id: FloorTileRockVault
name: rock vault tile name: rock vault tile
spawn: FloorTileItemRockVault spawn: FloorTileItemRockVault
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileBlue id: FloorTileBlue
name: blue floor tile name: blue floor tile
spawn: FloorTileItemBlue spawn: FloorTileItemBlue
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMining id: FloorTileMining
name: mining floor tile name: mining floor tile
spawn: FloorTileItemMining spawn: FloorTileItemMining
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMiningDark id: FloorTileMiningDark
name: dark mining floor tile name: dark mining floor tile
spawn: FloorTileItemMiningDark spawn: FloorTileItemMiningDark
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMiningLight id: FloorTileMiningLight
name: light mining floor tile name: light mining floor tile
spawn: FloorTileItemMiningLight spawn: FloorTileItemMiningLight
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileBar id: FloorTileBar
name: item bar floor tile name: item bar floor tile
spawn: FloorTileItemBar spawn: FloorTileItemBar
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileClown id: FloorTileClown
name: clown floor tile name: clown floor tile
spawn: FloorTileItemClown spawn: FloorTileItemClown
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMime id: FloorTileMime
name: mime floor tile name: mime floor tile
spawn: FloorTileItemMime spawn: FloorTileItemMime
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileKitchen id: FloorTileKitchen
name: kitchen floor tile name: kitchen floor tile
spawn: FloorTileItemKitchen spawn: FloorTileItemKitchen
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileLaundry id: FloorTileLaundry
name: laundry floor tile name: laundry floor tile
spawn: FloorTileItemLaundry spawn: FloorTileItemLaundry
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileConcrete id: FloorTileConcrete
name: concrete tile name: concrete tile
spawn: FloorTileItemGrayConcrete spawn: FloorTileItemGrayConcrete
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileGrayConcrete id: FloorTileGrayConcrete
name: gray concrete tile name: gray concrete tile
spawn: FloorTileItemLaundry spawn: FloorTileItemLaundry
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileOldConcrete id: FloorTileOldConcrete
name: old concrete tile name: old concrete tile
spawn: FloorTileItemOldConcrete spawn: FloorTileItemOldConcrete
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileSilver id: FloorTileSilver
name: silver floor tile name: silver floor tile
spawn: FloorTileItemSilver spawn: FloorTileItemSilver
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileBCircuit id: FloorTileBCircuit
name: bcircuit floor tile name: bcircuit floor tile
spawn: FloorTileItemBCircuit spawn: FloorTileItemBCircuit
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileGrass id: FloorTileGrass
name: grass floor tile name: grass floor tile
spawn: FloorTileItemGrass spawn: FloorTileItemGrass
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileGrassJungle id: FloorTileGrassJungle
name: grass jungle floor tile name: grass jungle floor tile
spawn: FloorTileItemGrassJungle spawn: FloorTileItemGrassJungle
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileSnow id: FloorTileSnow
name: snow floor tile name: snow floor tile
spawn: FloorTileItemSnow spawn: FloorTileItemSnow
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileWoodPattern id: FloorTileWoodPattern
name: wood pattern floor name: wood pattern floor
spawn: FloorTileItemWoodPattern spawn: FloorTileItemWoodPattern
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileFlesh id: FloorTileFlesh
name: flesh floor name: flesh floor
spawn: FloorTileItemFlesh spawn: FloorTileItemFlesh
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileSteelMaint id: FloorTileSteelMaint
name: steel maint floor name: steel maint floor
spawn: FloorTileItemSteelMaint spawn: FloorTileItemSteelMaint
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileGratingMaint id: FloorTileGratingMaint
name: grating maint floor name: grating maint floor
spawn: FloorTileItemGratingMaint spawn: FloorTileItemGratingMaint
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileWeb id: FloorTileWeb
name: web tile name: web tile
spawn: FloorTileItemWeb spawn: FloorTileItemWeb
maxCount: 30 maxCount: 30
itemSize: 5
# Faux science tiles # Faux science tiles
- type: stack - type: stack
@@ -473,38 +406,33 @@
name: astro-grass floor name: astro-grass floor
spawn: FloorTileItemAstroGrass spawn: FloorTileItemAstroGrass
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileMowedAstroGrass id: FloorTileMowedAstroGrass
name: mowed astro-grass floor name: mowed astro-grass floor
spawn: FloorTileItemMowedAstroGrass spawn: FloorTileItemMowedAstroGrass
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileJungleAstroGrass id: FloorTileJungleAstroGrass
name: jungle astro-grass floor name: jungle astro-grass floor
spawn: FloorTileItemJungleAstroGrass spawn: FloorTileItemJungleAstroGrass
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileAstroIce id: FloorTileAstroIce
name: astro-ice floor name: astro-ice floor
spawn: FloorTileItemAstroIce spawn: FloorTileItemAstroIce
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileAstroSnow id: FloorTileAstroSnow
name: astro-snow floor name: astro-snow floor
spawn: FloorTileItemAstroSnow spawn: FloorTileItemAstroSnow
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack - type: stack
id: FloorTileWoodLarge id: FloorTileWoodLarge
name: large wood floor name: large wood floor
spawn: FloorTileItemWoodLarge spawn: FloorTileItemWoodLarge
maxCount: 30 maxCount: 30

View File

@@ -4,7 +4,6 @@
icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: ointment } icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: ointment }
spawn: Ointment spawn: Ointment
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: AloeCream id: AloeCream
@@ -12,7 +11,6 @@
icon: { sprite: "/Textures/Objects/Specific/Hydroponics/aloe.rsi", state: cream } icon: { sprite: "/Textures/Objects/Specific/Hydroponics/aloe.rsi", state: cream }
spawn: AloeCream spawn: AloeCream
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: Gauze id: Gauze
@@ -20,7 +18,6 @@
icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: gauze } icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: gauze }
spawn: Gauze spawn: Gauze
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: Brutepack id: Brutepack
@@ -28,7 +25,6 @@
icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: gauze } icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: gauze }
spawn: Brutepack spawn: Brutepack
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: Bloodpack id: Bloodpack
@@ -36,7 +32,6 @@
icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: bloodpack } icon: { sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: bloodpack }
spawn: Bloodpack spawn: Bloodpack
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: MedicatedSuture id: MedicatedSuture
@@ -44,7 +39,6 @@
icon: {sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: medicated-suture } icon: {sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: medicated-suture }
spawn: MedicatedSuture spawn: MedicatedSuture
maxCount: 10 maxCount: 10
itemSize: 1
- type: stack - type: stack
id: RegenerativeMesh id: RegenerativeMesh
@@ -52,6 +46,4 @@
icon: {sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: regenerative-mesh} icon: {sprite: "/Textures/Objects/Specific/Medical/medical.rsi", state: regenerative-mesh}
spawn: RegenerativeMesh spawn: RegenerativeMesh
maxCount: 10 maxCount: 10
itemSize: 1

View File

@@ -4,7 +4,6 @@
icon: { sprite: "/Textures/Objects/Tools/cable-coils.rsi", state: coil-30 } icon: { sprite: "/Textures/Objects/Tools/cable-coils.rsi", state: coil-30 }
spawn: CableApcStack1 spawn: CableApcStack1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: CableMV id: CableMV
@@ -12,7 +11,6 @@
icon: { sprite: "/Textures/Objects/Tools/cable-coils.rsi", state: coilmv-30 } icon: { sprite: "/Textures/Objects/Tools/cable-coils.rsi", state: coilmv-30 }
spawn: CableMVStack1 spawn: CableMVStack1
maxCount: 30 maxCount: 30
itemSize: 1
- type: stack - type: stack
id: CableHV id: CableHV
@@ -20,4 +18,3 @@
icon: { sprite: "/Textures/Objects/Tools/cable-coils.rsi", state: coilhv-30 } icon: { sprite: "/Textures/Objects/Tools/cable-coils.rsi", state: coilhv-30 }
spawn: CableHVStack1 spawn: CableHVStack1
maxCount: 30 maxCount: 30
itemSize: 1

View File

@@ -3,4 +3,21 @@
name: artifact fragment name: artifact fragment
spawn: ArtifactFragment1 spawn: ArtifactFragment1
maxCount: 30 maxCount: 30
itemSize: 5
- type: stack
id: Capacitor
name: capacitor
spawn: CapacitorStockPart
maxCount: 10
- type: stack
id: MicroManipulator
name: micro manipulator
spawn: MicroManipulatorStockPart
maxCount: 10
- type: stack
id: MatterBin
name: matter bin
spawn: MatterBinStockPart
maxCount: 10

View File

@@ -35,6 +35,7 @@
description: extended-description description: extended-description
rules: rules:
- BasicStationEventScheduler - BasicStationEventScheduler
- GameRuleMeteorScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- type: gamePreset - type: gamePreset
@@ -68,6 +69,7 @@
description: secret-description description: secret-description
rules: rules:
- BasicStationEventScheduler - BasicStationEventScheduler
- GameRuleMeteorScheduler
- type: gamePreset - type: gamePreset
id: SecretGreenshift #For Admin Use: Runs Greenshift but shows "Secret" in lobby. id: SecretGreenshift #For Admin Use: Runs Greenshift but shows "Secret" in lobby.
@@ -99,6 +101,7 @@
- Traitor - Traitor
- SubGamemodesRule - SubGamemodesRule
- BasicStationEventScheduler - BasicStationEventScheduler
- GameRuleMeteorScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- type: gamePreset - type: gamePreset
@@ -125,6 +128,7 @@
- Nukeops - Nukeops
- SubGamemodesRule - SubGamemodesRule
- BasicStationEventScheduler - BasicStationEventScheduler
- GameRuleMeteorScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- type: gamePreset - type: gamePreset
@@ -140,6 +144,7 @@
- Revolutionary - Revolutionary
- SubGamemodesRule - SubGamemodesRule
- BasicStationEventScheduler - BasicStationEventScheduler
- GameRuleMeteorScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- type: gamePreset - type: gamePreset
@@ -156,6 +161,7 @@
rules: rules:
- Zombie - Zombie
- BasicStationEventScheduler - BasicStationEventScheduler
- GameRuleMeteorScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- type: gamePreset - type: gamePreset

View File

@@ -258,6 +258,9 @@
- type: Tag - type: Tag
id: CableCoil id: CableCoil
- type: Tag
id: CaneBlade
- type: Tag - type: Tag
id: CannonBall id: CannonBall
@@ -1319,3 +1322,5 @@
- type: Tag - type: Tag
id: WriteIgnoreStamps id: WriteIgnoreStamps
# ALPHABETICAL

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

View File

@@ -0,0 +1,49 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/6f5ca45e3ac06b30fb1957042214a888d8c01722. Inhands, worn sprites, and vox sprites created by EmoGarbage404 (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "icon-up"
},
{
"name": "equipped-MASK",
"directions": 4
},
{
"name": "up-equipped-MASK",
"directions": 4
},
{
"name": "equipped-MASK-vox",
"directions": 4
},
{
"name": "up-equipped-MASK-vox",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
},
{
"name": "up-inhand-left",
"directions": 4
},
{
"name": "up-inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,271 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from vgstation13 at https://github.com/vgstation-coders/vgstation13/blob/31dd6749bfe32810c46e7913efc99a187479cd51/icons/obj/meteor.dmi",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "small",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "small_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "small_flash",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "small_flash_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "space_dust"
},
{
"name": "medium",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "medium_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "medium_piercing",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "medium_piercing_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "medium_radioactive",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "medium_radioactive_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "big",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "big_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "big_cluster",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "big_cluster_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "human",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "human_pixel",
"delays": [
[
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "firework_pixel"
},
{
"name": "firework"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Some files were not shown because too many files have changed in this diff Show More