Merge remote-tracking branch 'upstream/master' into upstream-sync

This commit is contained in:
Arthur 2022-04-20 13:02:48 +03:00
commit fd5b4bcee5
173 changed files with 134621 additions and 133704 deletions

View file

@ -11,7 +11,10 @@
</GridContainer>
</ScrollContainer>
<ColorSelectorSliders Name="ColorPicker" IsAlphaVisible="True" />
<BoxContainer Orientation="Vertical">
<ColorSelectorSliders Name="ColorPicker" IsAlphaVisible="True" />
<Button Name="PickerOpen" Text="{Loc 'decal-placer-window-palette'}" />
</BoxContainer>
<CheckBox Name="EnableColor" Text="{Loc 'decal-placer-window-use-color'}" />
<CheckBox Name="EnableSnap" Text="{Loc 'decal-placer-window-enable-snap'}" />
<CheckBox Name="EnableCleanable" Text="{Loc 'decal-placer-window-enable-cleanable'}" />

View file

@ -1,4 +1,5 @@
using Content.Client.Stylesheets;
using System.Linq;
using Content.Client.Stylesheets;
using Content.Shared.Decals;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
@ -19,6 +20,8 @@ public sealed partial class DecalPlacerWindow : DefaultWindow
public FloatSpinBox RotationSpinBox;
private PaletteColorPicker? _picker;
private Dictionary<string, Texture>? _decals;
private string? _selected;
private Color _color = Color.White;
@ -44,12 +47,34 @@ public sealed partial class DecalPlacerWindow : DefaultWindow
SpinBoxContainer.AddChild(RotationSpinBox);
Search.OnTextChanged += _ => RefreshList();
ColorPicker.OnColorChanged += color =>
ColorPicker.OnColorChanged += OnColorPicked;
PickerOpen.OnPressed += _ =>
{
_color = color;
UpdateDecalPlacementInfo();
RefreshList();
if (_picker is null)
{
_picker = new PaletteColorPicker();
_picker.OpenToLeft();
_picker.PaletteList.OnItemSelected += args =>
{
var color = (args.ItemList.GetSelected().First().Metadata as Color?)!.Value;
ColorPicker.Color = color;
OnColorPicked(color);
};
}
else
{
if (_picker.IsOpen)
{
_picker.Close();
}
else
{
_picker.Open();
}
}
};
RotationSpinBox.OnValueChanged += args =>
{
_rotation = args.Value;
@ -77,6 +102,13 @@ public sealed partial class DecalPlacerWindow : DefaultWindow
Populate();
}
private void OnColorPicked(Color color)
{
_color = color;
UpdateDecalPlacementInfo();
RefreshList();
}
private void UpdateDecalPlacementInfo()
{
if (_selected is null)

View file

@ -18,6 +18,7 @@ namespace Content.Client.Entry
"Explosive",
"ExplosionResistance",
"Vocal",
"Summonable",
"OnUseTimerTrigger",
"WarpPoint",
"EmitSoundOnUse",
@ -44,6 +45,9 @@ namespace Content.Client.Entry
"DiseaseDiagnoser",
"DiseaseVaccine",
"DiseaseVaccineCreator",
"DiseaseZombie",
"DiseaseBuildup",
"ZombieTransfer",
"Mineable",
"RangedMagazine",
"Ammo",

View file

@ -0,0 +1,15 @@
namespace Content.Client.Lathe;
/// <summary>
/// Holds the idle and running state for machines to control
/// playing animtions on the client.
/// </summary>
[RegisterComponent]
public sealed class LatheVisualsComponent : Component
{
[DataField("idleState", required: true)]
public string IdleState = default!;
[DataField("runningState", required: true)]
public string RunningState = default!;
}

View file

@ -0,0 +1,43 @@
using Robust.Client.GameObjects;
using Content.Shared.Lathe;
using Content.Shared.Power;
using Content.Client.Power;
using Content.Client.Wires.Visualizers;
using Content.Shared.Wires;
namespace Content.Client.Lathe
{
public sealed class LatheSystem : VisualizerSystem<LatheVisualsComponent>
{
protected override void OnAppearanceChange(EntityUid uid, LatheVisualsComponent component, ref AppearanceChangeEvent args)
{
if (TryComp(uid, out SpriteComponent? sprite))
{
if (args.Component.TryGetData(PowerDeviceVisuals.Powered, out bool powered))
sprite.LayerSetVisible(PowerDeviceVisualLayers.Powered, powered);
if (args.Component.TryGetData(SharedWiresComponent.WiresVisuals.MaintenancePanelState, out bool panel))
sprite.LayerSetVisible(WiresVisualizer.WiresVisualLayers.MaintenancePanel, panel);
// Lathe specific stuff
if (args.Component.TryGetData(LatheVisuals.IsRunning, out bool isRunning))
{
var state = isRunning ? component.RunningState : component.IdleState;
sprite.LayerSetAnimationTime(LatheVisualLayers.IsRunning, 0f);
sprite.LayerSetState(LatheVisualLayers.IsRunning, state);
}
if (args.Component.TryGetData(LatheVisuals.IsInserting, out bool isInserting))
{
if (args.Component.TryGetData(LatheVisuals.InsertingColor, out Color color))
sprite.LayerSetColor(LatheVisualLayers.IsInserting, color);
sprite.LayerSetAnimationTime(LatheVisualLayers.IsInserting, 0f);
sprite.LayerSetVisible(LatheVisualLayers.IsInserting, isInserting);
}
}
}
}
}
public enum LatheVisualLayers : byte
{
IsRunning,
IsInserting
}

View file

@ -1,134 +0,0 @@
using System;
using Content.Shared.Lathe;
using Content.Shared.Power;
using JetBrains.Annotations;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Client.Lathe.Visualizers
{
[UsedImplicitly]
public sealed class AutolatheVisualizer : AppearanceVisualizer
{
[Dependency] private readonly IEntityManager _entMan = default!;
private const string AnimationKey = "inserting_animation";
private Animation _buildingAnimation;
private Animation _insertingMetalAnimation;
private Animation _insertingGlassAnimation;
private Animation _insertingGoldAnimation;
private Animation _insertingPlasmaAnimation;
private Animation _insertingPlasticAnimation;
public AutolatheVisualizer()
{
_buildingAnimation = PopulateAnimation("building", "building_unlit", 0.5f);
_insertingMetalAnimation = PopulateAnimation("inserting_metal", "inserting_unlit", 0.5f);
_insertingGlassAnimation = PopulateAnimation("inserting_glass", "inserting_unlit", 0.5f);
_insertingGoldAnimation = PopulateAnimation("inserting_gold", "inserting_unlit", 0.5f);
_insertingPlasmaAnimation = PopulateAnimation("inserting_plasma", "inserting_unlit", 0.5f);
_insertingPlasticAnimation = PopulateAnimation("inserting_plastic", "inserting_unlit", 0.5f);
}
private Animation PopulateAnimation(string sprite, string spriteUnlit, float length)
{
var animation = new Animation {Length = TimeSpan.FromSeconds(length)};
var flick = new AnimationTrackSpriteFlick();
animation.AnimationTracks.Add(flick);
flick.LayerKey = AutolatheVisualLayers.Base;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(sprite, 0f));
var flickUnlit = new AnimationTrackSpriteFlick();
animation.AnimationTracks.Add(flickUnlit);
flickUnlit.LayerKey = AutolatheVisualLayers.BaseUnlit;
flickUnlit.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(spriteUnlit, 0f));
return animation;
}
public override void InitializeEntity(EntityUid entity)
{
IoCManager.InjectDependencies(this);
_entMan.EnsureComponent<AnimationPlayerComponent>(entity);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var sprite = _entMan.GetComponent<ISpriteComponent>(component.Owner);
var animPlayer = _entMan.GetComponent<AnimationPlayerComponent>(component.Owner);
if (!component.TryGetData(PowerDeviceVisuals.VisualState, out LatheVisualState state))
{
state = LatheVisualState.Idle;
}
sprite.LayerSetVisible(AutolatheVisualLayers.AnimationLayer, true);
switch (state)
{
case LatheVisualState.Idle:
if (animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Stop(AnimationKey);
}
sprite.LayerSetState(AutolatheVisualLayers.Base, "icon");
sprite.LayerSetState(AutolatheVisualLayers.BaseUnlit, "unlit");
sprite.LayerSetVisible(AutolatheVisualLayers.AnimationLayer, false);
break;
case LatheVisualState.Producing:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_buildingAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingMetal:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingMetalAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingGlass:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingGlassAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingGold:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingGoldAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingPlasma:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingPlasmaAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingPlastic:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingPlasticAnimation, AnimationKey);
}
break;
default:
throw new ArgumentOutOfRangeException();
}
var glowingPartsVisible = !(component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && !powered);
sprite.LayerSetVisible(AutolatheVisualLayers.BaseUnlit, glowingPartsVisible);
}
public enum AutolatheVisualLayers : byte
{
Base,
BaseUnlit,
AnimationLayer
}
}
}

View file

@ -1,134 +0,0 @@
using System;
using Content.Shared.Lathe;
using Content.Shared.Power;
using JetBrains.Annotations;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Client.Lathe.Visualizers
{
[UsedImplicitly]
public sealed class ProtolatheVisualizer : AppearanceVisualizer
{
[Dependency] private readonly IEntityManager _entMan = default!;
private const string AnimationKey = "inserting_animation";
private Animation _buildingAnimation;
private Animation _insertingMetalAnimation;
private Animation _insertingGlassAnimation;
private Animation _insertingGoldAnimation;
private Animation _insertingPlasmaAnimation;
private Animation _insertingPlasticAnimation;
public ProtolatheVisualizer()
{
_buildingAnimation = PopulateAnimation("building", "building_unlit", 0.8f);
_insertingMetalAnimation = PopulateAnimation("inserting_metal", "inserting_unlit", 0.8f);
_insertingGlassAnimation = PopulateAnimation("inserting_glass", "inserting_unlit", 0.8f);
_insertingGoldAnimation = PopulateAnimation("inserting_gold", "inserting_unlit", 0.8f);
_insertingPlasmaAnimation = PopulateAnimation("inserting_plasma", "inserting_unlit", 0.8f);
_insertingPlasticAnimation = PopulateAnimation("inserting_plastic", "inserting_unlit", 0.8f);
}
private Animation PopulateAnimation(string sprite, string spriteUnlit, float length)
{
var animation = new Animation { Length = TimeSpan.FromSeconds(length) };
var flick = new AnimationTrackSpriteFlick();
animation.AnimationTracks.Add(flick);
flick.LayerKey = ProtolatheVisualLayers.Base;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(sprite, 0f));
var flickUnlit = new AnimationTrackSpriteFlick();
animation.AnimationTracks.Add(flickUnlit);
flickUnlit.LayerKey = ProtolatheVisualLayers.BaseUnlit;
flickUnlit.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(spriteUnlit, 0f));
return animation;
}
public override void InitializeEntity(EntityUid entity)
{
IoCManager.InjectDependencies(this);
_entMan.EnsureComponent<AnimationPlayerComponent>(entity);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var sprite = _entMan.GetComponent<ISpriteComponent>(component.Owner);
var animPlayer = _entMan.GetComponent<AnimationPlayerComponent>(component.Owner);
if (!component.TryGetData(PowerDeviceVisuals.VisualState, out LatheVisualState state))
{
state = LatheVisualState.Idle;
}
sprite.LayerSetVisible(ProtolatheVisualLayers.AnimationLayer, true);
switch (state)
{
case LatheVisualState.Idle:
if (animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Stop(AnimationKey);
}
sprite.LayerSetState(ProtolatheVisualLayers.Base, "icon");
sprite.LayerSetState(ProtolatheVisualLayers.BaseUnlit, "unlit");
sprite.LayerSetVisible(ProtolatheVisualLayers.AnimationLayer, false);
break;
case LatheVisualState.Producing:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_buildingAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingMetal:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingMetalAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingGlass:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingGlassAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingGold:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingGoldAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingPlasma:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingPlasmaAnimation, AnimationKey);
}
break;
case LatheVisualState.InsertingPlastic:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(_insertingPlasticAnimation, AnimationKey);
}
break;
default:
throw new ArgumentOutOfRangeException();
}
var glowingPartsVisible = !(component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && !powered);
sprite.LayerSetVisible(ProtolatheVisualLayers.BaseUnlit, glowingPartsVisible);
}
public enum ProtolatheVisualLayers : byte
{
Base,
BaseUnlit,
AnimationLayer
}
}
}

View file

@ -31,7 +31,7 @@ namespace Content.Server.Atmos.EntitySystems
if (airtight.FixAirBlockedDirectionInitialize)
{
var rotateEvent = new RotateEvent(airtight.Owner, Angle.Zero, xform.WorldRotation, xform);
var rotateEvent = new RotateEvent(airtight.Owner, Angle.Zero, xform.LocalRotation, xform);
OnAirtightRotated(uid, airtight, ref rotateEvent);
}

View file

@ -9,6 +9,10 @@ namespace Content.Server.Atmos.EntitySystems
[Dependency] private readonly IConfigurationManager _cfg = default!;
public bool SpaceWind { get; private set; }
public float SpaceWindPressureForceDivisorThrow { get; private set; }
public float SpaceWindPressureForceDivisorPush { get; private set; }
public float SpaceWindMaxVelocity { get; private set; }
public float SpaceWindMaxPushForce { get; private set; }
public bool MonstermosEqualization { get; private set; }
public bool MonstermosDepressurization { get; private set; }
public bool MonstermosRipTiles { get; private set; }
@ -23,6 +27,10 @@ namespace Content.Server.Atmos.EntitySystems
private void InitializeCVars()
{
_cfg.OnValueChanged(CCVars.SpaceWind, value => SpaceWind = value, true);
_cfg.OnValueChanged(CCVars.SpaceWindPressureForceDivisorThrow, value => SpaceWindPressureForceDivisorThrow = value, true);
_cfg.OnValueChanged(CCVars.SpaceWindPressureForceDivisorPush, value => SpaceWindPressureForceDivisorPush = value, true);
_cfg.OnValueChanged(CCVars.SpaceWindMaxVelocity, value => SpaceWindMaxVelocity = value, true);
_cfg.OnValueChanged(CCVars.SpaceWindMaxPushForce, value => SpaceWindMaxPushForce = value, true);
_cfg.OnValueChanged(CCVars.MonstermosEqualization, value => MonstermosEqualization = value, true);
_cfg.OnValueChanged(CCVars.MonstermosDepressurization, value => MonstermosDepressurization = value, true);
_cfg.OnValueChanged(CCVars.MonstermosRipTiles, value => MonstermosRipTiles = value, true);

View file

@ -104,6 +104,9 @@ namespace Content.Server.Atmos.EntitySystems
}
}
// Used by ExperiencePressureDifference to correct push/throw directions from tile-relative to physics world.
var gridWorldRotation = xforms.GetComponent(gridAtmosphere.Owner).WorldRotation;
foreach (var entity in _lookup.GetEntitiesIntersecting(tile.GridIndex, tile.GridIndices))
{
// Ideally containers would have their own EntityQuery internally or something given recursively it may need to slam GetComp<T> anyway.
@ -125,6 +128,7 @@ namespace Content.Server.Atmos.EntitySystems
tile.PressureDifference,
tile.PressureDirection, 0,
tile.PressureSpecificTarget?.GridIndices.ToEntityCoordinates(tile.GridIndex, _mapManager) ?? EntityCoordinates.Invalid,
gridWorldRotation,
xforms.GetComponent(entity),
body);
}
@ -140,6 +144,7 @@ namespace Content.Server.Atmos.EntitySystems
_spaceWindSoundCooldown = 0;
}
// Called from AtmosphereSystem.LINDA.cs with SpaceWind CVar check handled there.
private void ConsiderPressureDifference(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, TileAtmosphere other, float difference)
{
gridAtmosphere.HighPressureDelta.Add(tile);
@ -157,6 +162,7 @@ namespace Content.Server.Atmos.EntitySystems
AtmosDirection direction,
float pressureResistanceProbDelta,
EntityCoordinates throwTarget,
Angle gridWorldRotation,
TransformComponent? xform = null,
PhysicsComponent? physics = null)
{
@ -188,18 +194,28 @@ namespace Content.Server.Atmos.EntitySystems
if (maxForce > MovedByPressureComponent.ThrowForce)
{
var moveForce = maxForce;
moveForce /= (throwTarget != EntityCoordinates.Invalid) ? SpaceWindPressureForceDivisorThrow : SpaceWindPressureForceDivisorPush;
moveForce *= MathHelper.Clamp(moveProb, 0, 100);
// Apply a sanity clamp to prevent being thrown through objects.
var maxSafeForceForObject = SpaceWindMaxVelocity * physics.Mass;
moveForce = MathF.Min(moveForce, maxSafeForceForObject);
// Grid-rotation adjusted direction
var dirVec = (direction.ToAngle() + gridWorldRotation).ToWorldVec();
// TODO: Technically these directions won't be correct but uhh I'm just here for optimisations buddy not to fix my old bugs.
if (throwTarget != EntityCoordinates.Invalid)
{
var moveForce = maxForce * MathHelper.Clamp(moveProb, 0, 100) / 15f;
var pos = ((throwTarget.Position - xform.Coordinates.Position).Normalized + direction.ToDirection().ToVec()).Normalized;
var pos = ((throwTarget.ToMap(EntityManager).Position - xform.WorldPosition).Normalized + dirVec).Normalized;
physics.ApplyLinearImpulse(pos * moveForce);
}
else
{
var moveForce = MathF.Min(maxForce * MathHelper.Clamp(moveProb, 0, 100) / 2500f, 20f);
physics.ApplyLinearImpulse(direction.ToDirection().ToVec() * moveForce);
moveForce = MathF.Min(moveForce, SpaceWindMaxPushForce);
physics.ApplyLinearImpulse(dirVec * moveForce);
}
component.LastHighPressureMovementAirCycle = cycle;

View file

@ -2,6 +2,10 @@ using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.MobState.Components;
using Content.Shared.Damage;
using Content.Shared.Verbs;
using Content.Shared.Tag;
using Content.Shared.ActionBlocker;
using Content.Shared.Actions;
using Content.Server.Cooldown;
using Content.Server.Bible.Components;
using Content.Server.Popups;
@ -10,7 +14,6 @@ using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Timing;
namespace Content.Server.Bible
{
public sealed class BibleSystem : EntitySystem
@ -20,12 +23,18 @@ namespace Content.Server.Bible
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BibleComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<SummonableComponent, GetVerbsEvent<AlternativeVerb>>(AddSummonVerb);
SubscribeLocalEvent<SummonableComponent, GetItemActionsEvent>(GetSummonAction);
SubscribeLocalEvent<SummonableComponent, SummonActionEvent>(OnSummon);
}
private void OnAfterInteract(EntityUid uid, BibleComponent component, AfterInteractEvent args)
@ -52,20 +61,20 @@ namespace Content.Server.Bible
{
_popupSystem.PopupEntity(Loc.GetString("bible-sizzle"), args.User, Filter.Entities(args.User));
SoundSystem.Play(Filter.Pvs(args.User), "/Audio/Effects/lightburn.ogg", args.User);
SoundSystem.Play(Filter.Pvs(args.User), component.SizzleSoundPath.GetSound(), args.User);
_damageableSystem.TryChangeDamage(args.User, component.DamageOnUntrainedUse, true);
return;
}
if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid))
if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid) && !_tagSystem.HasTag(args.Target.Value, "Familiar"))
{
if (_random.Prob(component.FailChance))
{
var othersFailMessage = Loc.GetString("bible-heal-fail-others", ("user", args.User),("target", args.Target),("bible", uid));
var othersFailMessage = Loc.GetString(component.LocPrefix + "-heal-fail-others", ("user", args.User),("target", args.Target),("bible", uid));
_popupSystem.PopupEntity(othersFailMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
var selfFailMessage = Loc.GetString("bible-heal-fail-self", ("target", args.Target),("bible", uid));
var selfFailMessage = Loc.GetString(component.LocPrefix + "-heal-fail-self", ("target", args.Target),("bible", uid));
_popupSystem.PopupEntity(selfFailMessage, args.User, Filter.Entities(args.User));
SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/hit_kick.ogg", args.User);
@ -74,15 +83,67 @@ namespace Content.Server.Bible
}
}
var othersMessage = Loc.GetString("bible-heal-success-others", ("user", args.User),("target", args.Target),("bible", uid));
var othersMessage = Loc.GetString(component.LocPrefix + "-heal-success-others", ("user", args.User),("target", args.Target),("bible", uid));
_popupSystem.PopupEntity(othersMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
var selfMessage = Loc.GetString("bible-heal-success-self", ("target", args.Target),("bible", uid));
var selfMessage = Loc.GetString(component.LocPrefix + "-heal-success-self", ("target", args.Target),("bible", uid));
_popupSystem.PopupEntity(selfMessage, args.User, Filter.Entities(args.User));
SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/holy.ogg", args.User);
SoundSystem.Play(Filter.Pvs(args.Target.Value), component.HealSoundPath.GetSound(), args.User);
_damageableSystem.TryChangeDamage(args.Target.Value, component.Damage, true);
}
private void AddSummonVerb(EntityUid uid, SummonableComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanInteract || !args.CanAccess || component.AlreadySummoned || component.SpecialItemPrototype == null)
return;
if (component.RequiresBibleUser && !HasComp<BibleUserComponent>(args.User))
return;
AlternativeVerb verb = new()
{
Act = () =>
{
TransformComponent? position = Comp<TransformComponent>(args.User);
AttemptSummon(component, args.User, position);
},
Text = Loc.GetString("bible-summon-verb"),
Priority = 2
};
args.Verbs.Add(verb);
}
private void GetSummonAction(EntityUid uid, SummonableComponent component, GetItemActionsEvent args)
{
if (component.AlreadySummoned)
return;
args.Actions.Add(component.SummonAction);
}
private void OnSummon(EntityUid uid, SummonableComponent component, SummonActionEvent args)
{
AttemptSummon(component, args.Performer, Transform(args.Performer));
}
private void AttemptSummon(SummonableComponent component, EntityUid user, TransformComponent? position)
{
if (component.AlreadySummoned || component.SpecialItemPrototype == null)
return;
if (component.RequiresBibleUser && !HasComp<BibleUserComponent>(user))
return;
if (!Resolve(user, ref position))
return;
if (component.Deleted || Deleted(component.Owner))
return;
if (!_blocker.CanInteract(user, component.Owner))
return;
EntityManager.SpawnEntity(component.SpecialItemPrototype, position.Coordinates);
component.AlreadySummoned = true;
_actionsSystem.RemoveAction(user, component.SummonAction);
}
}
public sealed class SummonActionEvent : InstantActionEvent
{}
}

View file

@ -1,18 +1,13 @@
using System;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
using Content.Shared.Sound;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.ViewVariables;
using Robust.Shared.Prototypes;
namespace Content.Server.Bible.Components
{
[RegisterComponent]
public sealed class BibleComponent : Component
{
// Damage that will be healed on a success
[DataField("damage", required: true)]
[ViewVariables(VVAccess.ReadWrite)]
@ -33,6 +28,15 @@ namespace Content.Server.Bible.Components
public TimeSpan LastAttackTime;
public TimeSpan CooldownEnd;
[DataField("cooldownTime")]
public float CooldownTime { get; } = 5f;
[DataField("sizzleSound")]
public SoundSpecifier SizzleSoundPath = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
[DataField("healSound")]
public SoundSpecifier HealSoundPath = new SoundPathSpecifier("/Audio/Effects/holy.ogg");
[DataField("locPrefix")]
public string LocPrefix = "bible";
}
}

View file

@ -0,0 +1,34 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Prototypes;
using Content.Shared.Actions.ActionTypes;
using Content.Server.Bible;
using Robust.Shared.Utility;
namespace Content.Server.Bible.Components
{
/// <summary>
/// This lets you summon a mob or item with an alternative verb on the item
/// </summary>
[RegisterComponent]
public sealed class SummonableComponent : Component
{
/// <summary>
/// Used for a special item only the Chaplain can summon. Usually a mob, but supports regular items too.
/// </summary>
[DataField("specialItem", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? SpecialItemPrototype = null;
public bool AlreadySummoned = false;
[DataField("requriesBibleUser")]
public bool RequiresBibleUser = true;
[DataField("summonAction")]
public InstantAction SummonAction = new()
{
Icon = new SpriteSpecifier.Texture(new ResourcePath("Clothing/Head/Hats/witch.rsi/icon.png")),
Name = "bible-summon-verb",
Description = "bible-summon-verb-desc",
Event = new SummonActionEvent(),
};
}
}

View file

@ -226,6 +226,14 @@ public sealed class BloodstreamSystem : EntitySystem
return (component.BloodSolution.CurrentVolume / component.BloodSolution.MaxVolume).Float();
}
public void SetBloodLossThreshold(EntityUid uid, float threshold, BloodstreamComponent? comp = null)
{
if (!Resolve(uid, ref comp))
return;
comp.BloodlossThreshold = threshold;
}
/// <summary>
/// Attempts to modify the blood level of this entity directly.
/// </summary>

View file

@ -0,0 +1,19 @@
namespace Content.Server.Disease.Components
{
/// <summary>
/// The component which records the buildup/progression of an infection
/// </summary>
[RegisterComponent]
public sealed class DiseaseBuildupComponent : Component
{
/// This could be served to be generalized to allow for multiple
/// diseases to build up at once, but it doesn't matter too much.
/// <summary>
/// The current amount of progression that has built up.
/// </summary>
[DataField("progression")]
[ViewVariables(VVAccess.ReadWrite)]
public float Progression = 0.00f;
}
}

View file

@ -1,7 +1,6 @@
using System.Threading;
using Content.Server.Disease.Components;
using Content.Shared.Disease;
using Content.Shared.Disease.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.Examine;
@ -151,7 +150,7 @@ namespace Content.Server.Disease
_popupSystem.PopupEntity(Loc.GetString("diagnoser-cant-use-swab", ("machine", uid), ("swab", args.Used)), uid, Filter.Entities(args.User));
return;
}
_popupSystem.PopupEntity(Loc.GetString("diagnoser-insert-swab", ("machine", uid), ("swab", args.Used)), uid, Filter.Entities(args.User));
_popupSystem.PopupEntity(Loc.GetString("machine-insert-item", ("machine", uid), ("item", args.Used)), uid, Filter.Entities(args.User));
machine.Disease = swab.Disease;
@ -183,7 +182,7 @@ namespace Content.Server.Disease
_popupSystem.PopupEntity(Loc.GetString("diagnoser-cant-use-swab", ("machine", uid), ("swab", args.Used)), uid, Filter.Entities(args.User));
return;
}
_popupSystem.PopupEntity(Loc.GetString("diagnoser-insert-swab", ("machine", uid), ("swab", args.Used)), uid, Filter.Entities(args.User));
_popupSystem.PopupEntity(Loc.GetString("machine-insert-item", ("machine", uid), ("item", args.Used)), uid, Filter.Entities(args.User));
var machine = Comp<DiseaseMachineComponent>(uid);
machine.Disease = swab.Disease;
EntityManager.DeleteEntity(args.Used);

View file

@ -94,8 +94,10 @@ namespace Content.Server.Disease
continue;
}
foreach (var disease in carrierComp.Diseases)
for (var i = 0; i < carrierComp.Diseases.Count; i++) //this is a for-loop so that it doesn't break when new diseases are added
{
var disease = carrierComp.Diseases[i];
var args = new DiseaseEffectArgs(carrierComp.Owner, disease, EntityManager);
disease.Accumulator += frameTime;
if (disease.Accumulator >= disease.TickTime)

View file

@ -0,0 +1,46 @@
using Content.Server.Disease.Components;
using JetBrains.Annotations;
using Content.Shared.Disease;
using Robust.Shared.IoC;
namespace Content.Server.Disease.Effects
{
/// <summary>
/// Handles a disease which incubates over a period of time
/// before adding another component to the infected entity
/// currently used for zombie virus
/// </summary>
[UsedImplicitly]
public sealed class DiseaseProgression : DiseaseEffect
{
/// <summary>
/// The rate that's increased over time. Defaults to 1% so the probability can be varied in yaml
/// </summary>
[DataField("rate")]
[ViewVariables(VVAccess.ReadWrite)]
public float Rate = 0.01f;
/// <summary>
/// The component that is added at the end of build up
/// </summary>
[DataField("comp")]
public string? Comp = null;
public override void Effect(DiseaseEffectArgs args)
{
args.EntityManager.EnsureComponent<DiseaseBuildupComponent>(args.DiseasedEntity, out var buildup);
if (buildup.Progression < 1) //increases steadily until 100%
{
buildup.Progression += Rate;
}
else if (Comp != null)//adds the component for the later stage of the disease.
{
EntityUid uid = args.DiseasedEntity;
var newComponent = (Component) IoCManager.Resolve<IComponentFactory>().GetComponent(Comp);
newComponent.Owner = uid;
if (!args.EntityManager.HasComponent(uid, newComponent.GetType()))
args.EntityManager.AddComponent(uid, newComponent);
}
}
}
}

View file

@ -0,0 +1,37 @@
namespace Content.Server.Disease.Zombie.Components
{
/// <summary>
/// The component which gives an entity zombie traits.
/// </summary>
[RegisterComponent]
public sealed class DiseaseZombieComponent : Component
{
/// <summary>
/// The probability that a given bite will infect a player.
/// zombie infection is not based on disease resist items like masks or gloves.
/// </summary>
[DataField("probability")]
[ViewVariables(VVAccess.ReadWrite)]
public float Probability = 0.33f;
/// <summary>
/// A multiplier on the movement speed that zombies recieve.
/// </summary>
[DataField("slowAmount")]
[ViewVariables(VVAccess.ReadWrite)]
public float SlowAmount = 0.75f;
/// <summary>
/// Whether or not the zombie needs all the zombie traits initialized upon component init
/// useful for entities that already are zombies and do not need the additional traits.
/// </summary>
[DataField("applyZombieTraits")]
public bool ApplyZombieTraits = true;
/// <summary>
/// The color of the zombie's skin
/// </summary>
[DataField("skinColor")]
public readonly Color SkinColor = (0.70f, 0.72f, 0.48f, 1);
}
}

View file

@ -0,0 +1,130 @@
using Robust.Shared.Player;
using Content.Server.Speech.Components;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Disease.Components;
using Content.Server.Disease.Zombie.Components;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Popups;
using Content.Server.Atmos.Components;
using Content.Server.Hands.Components;
using Content.Server.Nutrition.Components;
using Content.Server.Mind.Components;
using Content.Server.Chat.Managers;
using Content.Server.Inventory;
using Content.Shared.Damage;
using Content.Shared.MobState.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Movement.EntitySystems;
using Content.Shared.CharacterAppearance.Components;
using Content.Shared.CharacterAppearance.Systems;
using Content.Server.Weapons.Melee.ZombieTransfer.Components;
namespace Content.Server.Disease.Zombie
{
/// <summary>
/// Handles zombie propagation and inherent zombie traits
/// </summary>
public sealed class DiseaseZombieSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly ServerInventorySystem _serverInventory = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
[Dependency] private readonly SharedHandsSystem _sharedHands = default!;
[Dependency] private readonly SharedHumanoidAppearanceSystem _sharedHumanoidAppearance = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DiseaseZombieComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<DiseaseZombieComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
}
/// <remarks>
/// I would imagine that if this component got assigned to something other than a mob, it would throw hella errors.
/// </remarks>
private void OnComponentInit(EntityUid uid, DiseaseZombieComponent component, ComponentInit args)
{
if (!component.ApplyZombieTraits || !HasComp<MobStateComponent>(uid))
return;
RemComp<DiseaseCarrierComponent>(uid);
RemComp<DiseaseBuildupComponent>(uid);
RemComp<RespiratorComponent>(uid);
RemComp<BarotraumaComponent>(uid);
RemComp<HungerComponent>(uid);
RemComp<ThirstComponent>(uid);
EntityManager.EnsureComponent<BloodstreamComponent>(uid, out var bloodstream); //zoms need bloodstream anyway for healing
_bloodstream.SetBloodLossThreshold(uid, 0f, bloodstream);
_bloodstream.TryModifyBleedAmount(uid, -bloodstream.BleedAmount, bloodstream);
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
EntityManager.EnsureComponent<ReplacementAccentComponent>(uid).Accent = "zombie";
if (TryComp<DamageableComponent>(uid, out var comp))
{
_damageable.SetDamageModifierSetId(uid, "Zombie", comp);
_damageable.SetAllDamage(comp, 0);
}
if (TryComp<HumanoidAppearanceComponent>(uid, out var spritecomp))
{
var oldapp = spritecomp.Appearance;
var newapp = oldapp.WithSkinColor(component.SkinColor);
_sharedHumanoidAppearance.UpdateAppearance(uid, newapp);
_sharedHumanoidAppearance.ForceAppearanceUpdate(uid);
}
if (TryComp<HandsComponent>(uid, out var handcomp))
{
foreach (var hand in handcomp.Hands)
{
_sharedHands.TrySetActiveHand(uid, hand.Key);
_sharedHands.TryDrop(uid);
var pos = EntityManager.GetComponent<TransformComponent>(uid).Coordinates;
var claw = EntityManager.SpawnEntity("ZombieClaw", pos);
_sharedHands.DoPickup(uid, hand.Value, claw);
}
}
else
{
EnsureComp<ZombieTransferComponent>(uid);
}
if (TryComp<ServerInventoryComponent>(uid, out var servInvComp))
_serverInventory.TryUnequip(uid, "gloves", true, true, servInvComp);
_popupSystem.PopupEntity(Loc.GetString("zombie-transform", ("target", uid)), uid, Filter.Pvs(uid));
if (TryComp<MetaDataComponent>(uid, out var metacomp))
metacomp.EntityName = Loc.GetString("zombie-name-prefix", ("target", metacomp.EntityName));
var mindcomp = EnsureComp<MindComponent>(uid);
if (mindcomp.Mind != null && mindcomp.Mind.TryGetSession(out var session))
{
var chatMgr = IoCManager.Resolve<IChatManager>();
chatMgr.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
}
if (!HasComp<GhostRoleMobSpawnerComponent>(uid) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig
{
EntityManager.EnsureComponent<GhostTakeoverAvailableComponent>(uid, out var ghostcomp);
ghostcomp.RoleName = Loc.GetString("zombie-generic");
ghostcomp.RoleDescription = Loc.GetString("zombie-role-desc");
ghostcomp.RoleRules = Loc.GetString("zombie-role-rules");
}
}
private void OnRefreshMovementSpeedModifiers(EntityUid uid, DiseaseZombieComponent component, RefreshMovementSpeedModifiersEvent args)
{
args.ModifySpeed(component.SlowAmount, component.SlowAmount);
}
}
}

View file

@ -1,16 +1,11 @@
using System.Linq;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Disposal.Tube.Components;
using Content.Server.Disposal.Tube;
using Content.Server.Disposal.Unit.Components;
using JetBrains.Annotations;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Server.Disposal.Unit.EntitySystems
@ -21,6 +16,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly DisposalUnitSystem _disposalUnitSystem = default!;
[Dependency] private readonly DisposalTubeSystem _disposalTubeSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
public void ExitDisposals(EntityUid uid, DisposalHolderComponent? holder = null, TransformComponent? holderTransform = null)
{
@ -36,40 +32,37 @@ namespace Content.Server.Disposal.Unit.EntitySystems
// Check for a disposal unit to throw them into and then eject them from it.
// *This ejection also makes the target not collide with the unit.*
// *This is on purpose.*
var grid = _mapManager.GetGrid(holderTransform.GridID);
var gridTileContents = grid.GetLocal(holderTransform.Coordinates);
DisposalUnitComponent? duc = null;
foreach (var contentUid in gridTileContents)
if (_mapManager.TryGetGrid(holderTransform.GridID, out var grid))
{
if (EntityManager.TryGetComponent(contentUid, out duc))
break;
foreach (var contentUid in grid.GetLocal(holderTransform.Coordinates))
{
if (EntityManager.TryGetComponent(contentUid, out duc))
break;
}
}
foreach (var entity in holder.Container.ContainedEntities.ToArray())
{
if (HasComp<BeingDisposedComponent>(entity))
RemComp <BeingDisposedComponent>(entity);
RemComp<BeingDisposedComponent>(entity);
if (EntityManager.TryGetComponent(entity, out IPhysBody? physics))
{
physics.CanCollide = true;
}
holder.Container.ForceRemove(entity);
var meta = MetaData(entity);
holder.Container.ForceRemove(entity, EntityManager, meta);
if (EntityManager.GetComponent<TransformComponent>(entity).Parent == holderTransform)
{
if (duc != null)
{
// Insert into disposal unit
EntityManager.GetComponent<TransformComponent>(entity).Coordinates = new EntityCoordinates((duc).Owner, Vector2.Zero);
duc.Container.Insert(entity);
}
else
{
EntityManager.GetComponent<TransformComponent>(entity).AttachParentToContainerOrGrid();
}
}
var xform = Transform(entity);
if (xform.ParentUid != uid)
continue;
if (duc != null)
duc.Container.Insert(entity, EntityManager, xform, meta: meta);
else
xform.AttachParentToContainerOrGrid(EntityManager);
}
if (duc != null)
@ -77,11 +70,9 @@ namespace Content.Server.Disposal.Unit.EntitySystems
_disposalUnitSystem.TryEjectContents(duc);
}
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
if (atmosphereSystem.GetTileMixture(holderTransform.Coordinates, true) is {} environment)
if (_atmosphereSystem.GetTileMixture(holderTransform.Coordinates, true) is {} environment)
{
atmosphereSystem.Merge(environment, holder.Air);
_atmosphereSystem.Merge(environment, holder.Air);
holder.Air.Clear();
}

View file

@ -18,6 +18,7 @@ namespace Content.Server.Entry
"ClientEntitySpawner",
"CharacterInfo",
"ItemCabinetVisuals",
"LatheVisuals",
"DiseaseMachineVisuals",
"HandheldGPS",
"ToggleableLightVisuals",

View file

@ -1,219 +1,53 @@
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Materials;
using Content.Server.Power.Components;
using Content.Server.Research.Components;
using Content.Server.Stack;
using Content.Server.UserInterface;
using Content.Shared.Interaction;
using Content.Shared.Lathe;
using Content.Shared.Power;
using Content.Shared.Research.Prototypes;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Content.Shared.Sound;
namespace Content.Server.Lathe.Components
{
[RegisterComponent]
public sealed class LatheComponent : SharedLatheComponent, IInteractUsing
public sealed class LatheComponent : SharedLatheComponent
{
[Dependency] private readonly IEntityManager _entMan = default!;
public const int VolumePerSheet = 100;
/// <summary>
/// How much volume in cm^3 each sheet of material adds
/// </summary>
public int VolumePerSheet = 100;
/// <summary>
/// The lathe's construction queue
/// </summary>
[ViewVariables]
public Queue<LatheRecipePrototype> Queue { get; } = new();
/// <summary>
/// The recipe the lathe is currently producing
/// </summary>
[ViewVariables]
public bool Producing { get; private set; }
private LatheState _state = LatheState.Base;
private LatheState State
{
get => _state;
set => _state = value;
}
public LatheRecipePrototype? ProducingRecipe;
/// <summary>
/// How long the inserting animation will play
/// </summary>
[ViewVariables]
private LatheRecipePrototype? _producingRecipe;
public float InsertionTime = 0.79f; // 0.01 off for animation timing
/// <summary>
/// Update accumulator for the insertion time
/// </suummary>
public float InsertionAccumulator = 0f;
/// <summary>
/// Production accumulator for the production time.
/// </summary>
[ViewVariables]
private bool Powered => !_entMan.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) || receiver.Powered;
public float ProducingAccumulator = 0f;
private static readonly TimeSpan InsertionTime = TimeSpan.FromSeconds(0.9f);
/// <summary>
/// The sound that plays when the lathe is producing an item, if any
/// </summary>
[DataField("producingSound")]
public SoundSpecifier? ProducingSound;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(LatheUiKey.Key);
protected override void Initialize()
{
base.Initialize();
if (UserInterface != null)
{
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
}
}
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
{
if (!Powered)
return;
switch (message.Message)
{
case LatheQueueRecipeMessage msg:
PrototypeManager.TryIndex(msg.ID, out LatheRecipePrototype? recipe);
if (recipe != null!)
for (var i = 0; i < msg.Quantity; i++)
{
Queue.Enqueue(recipe);
UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue()));
}
break;
case LatheSyncRequestMessage _:
if (!_entMan.HasComponent<MaterialStorageComponent>(Owner)) return;
UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue()));
if (_producingRecipe != null)
UserInterface?.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID));
break;
case LatheServerSelectionMessage _:
if (!_entMan.TryGetComponent(Owner, out ResearchClientComponent? researchClient)) return;
researchClient.OpenUserInterface(message.Session);
break;
case LatheServerSyncMessage _:
if (!_entMan.TryGetComponent(Owner, out TechnologyDatabaseComponent? database)
|| !_entMan.TryGetComponent(Owner, out ProtolatheDatabaseComponent? protoDatabase)) return;
if (database.SyncWithServer())
protoDatabase.Sync();
break;
}
}
internal bool Produce(LatheRecipePrototype recipe)
{
if (Producing || !Powered || !CanProduce(recipe) || !_entMan.TryGetComponent(Owner, out MaterialStorageComponent? storage)) return false;
UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue()));
Producing = true;
_producingRecipe = recipe;
foreach (var (material, amount) in recipe.RequiredMaterials)
{
// This should always return true, otherwise CanProduce fucked up.
storage.RemoveMaterial(material, amount);
}
UserInterface?.SendMessage(new LatheProducingRecipeMessage(recipe.ID));
State = LatheState.Producing;
SetAppearance(LatheVisualState.Producing);
Owner.SpawnTimer(recipe.CompleteTime, () =>
{
Producing = false;
_producingRecipe = null;
_entMan.SpawnEntity(recipe.Result, _entMan.GetComponent<TransformComponent>(Owner).Coordinates);
UserInterface?.SendMessage(new LatheStoppedProducingRecipeMessage());
State = LatheState.Base;
SetAppearance(LatheVisualState.Idle);
});
return true;
}
public void OpenUserInterface(IPlayerSession session)
{
UserInterface?.Open(session);
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!_entMan.TryGetComponent(Owner, out MaterialStorageComponent? storage)
|| !_entMan.TryGetComponent(eventArgs.Using, out MaterialComponent? material)) return false;
var multiplier = 1;
if (_entMan.TryGetComponent(eventArgs.Using, out StackComponent? stack)) multiplier = stack.Count;
var totalAmount = 0;
// Check if it can insert all materials.
foreach (var mat in material.MaterialIds)
{
// TODO: Change how MaterialComponent works so this is not hard-coded.
if (!storage.CanInsertMaterial(mat, VolumePerSheet * multiplier)) return false;
totalAmount += VolumePerSheet * multiplier;
}
// Check if it can take ALL of the material's volume.
if (storage.CanTakeAmount(totalAmount)) return false;
foreach (var mat in material.MaterialIds)
{
storage.InsertMaterial(mat, VolumePerSheet * multiplier);
}
State = LatheState.Inserting;
switch (material.Materials.FirstOrDefault()?.ID)
{
case "Steel":
SetAppearance(LatheVisualState.InsertingMetal);
break;
case "Glass":
SetAppearance(LatheVisualState.InsertingGlass);
break;
case "Gold":
SetAppearance(LatheVisualState.InsertingGold);
break;
case "Plastic":
SetAppearance(LatheVisualState.InsertingPlastic);
break;
case "Plasma":
SetAppearance(LatheVisualState.InsertingPlasma);
break;
}
Owner.SpawnTimer(InsertionTime, () =>
{
State = LatheState.Base;
SetAppearance(LatheVisualState.Idle);
});
_entMan.DeleteEntity(eventArgs.Using);
return true;
}
private void SetAppearance(LatheVisualState state)
{
if (_entMan.TryGetComponent(Owner, out AppearanceComponent? appearance))
{
appearance.SetData(PowerDeviceVisuals.VisualState, state);
}
}
private Queue<string> GetIdQueue()
{
var queue = new Queue<string>();
foreach (var recipePrototype in Queue)
{
queue.Enqueue(recipePrototype.ID);
}
return queue;
}
private enum LatheState : byte
{
Base,
Inserting,
Producing
}
/// <summmary>
/// The lathe's UI.
/// </summary>
[ViewVariables] public BoundUserInterface? UserInterface;
}
}

View file

@ -0,0 +1,9 @@
namespace Content.Server.Lathe.Components
{
/// <summary>
/// For EntityQuery to keep track of which lathes are inserting
/// <summary>
[RegisterComponent]
public sealed class LatheInsertingComponent : Component
{}
}

View file

@ -0,0 +1,9 @@
namespace Content.Server.Lathe.Components
{
/// <summary>
/// For EntityQuery to keep track of which lathes are producing
/// <summary>
[RegisterComponent]
public sealed class LatheProducingComponent : Component
{}
}

View file

@ -1,21 +1,286 @@
using Content.Server.Lathe.Components;
using Content.Shared.Lathe;
using Content.Shared.Materials;
using Content.Shared.Research.Prototypes;
using Content.Server.Research.Components;
using Content.Shared.Interaction;
using Content.Server.Materials;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.Stack;
using Content.Server.UserInterface;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Player;
using Robust.Shared.Audio;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
namespace Content.Server.Lathe
{
[UsedImplicitly]
internal sealed class LatheSystem : EntitySystem
public sealed class LatheSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LatheComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<LatheComponent, ComponentInit>(OnComponentInit);
}
// These queues are to add/remove COMPONENTS to the lathes
private Queue<EntityUid> ProducingAddQueue = new();
private Queue<EntityUid> ProducingRemoveQueue = new();
private Queue<EntityUid> InsertingAddQueue = new();
private Queue<EntityUid> InsertingRemoveQueue = new();
public override void Update(float frameTime)
{
foreach (var comp in EntityManager.EntityQuery<LatheComponent>())
foreach (var uid in ProducingAddQueue)
EnsureComp<LatheProducingComponent>(uid);
ProducingAddQueue.Clear();
foreach (var uid in ProducingRemoveQueue)
RemComp<LatheProducingComponent>(uid);
ProducingRemoveQueue.Clear();
foreach (var uid in InsertingAddQueue)
EnsureComp<LatheInsertingComponent>(uid);
InsertingAddQueue.Clear();
foreach (var uid in InsertingRemoveQueue)
RemComp<LatheInsertingComponent>(uid);
InsertingRemoveQueue.Clear();
foreach (var (insertingComp, lathe) in EntityQuery<LatheInsertingComponent, LatheComponent>(false))
{
if (comp.Producing == false && comp.Queue.Count > 0)
if (lathe.InsertionAccumulator < lathe.InsertionTime)
{
comp.Produce(comp.Queue.Dequeue());
lathe.InsertionAccumulator += frameTime;
continue;
}
lathe.InsertionAccumulator = 0;
UpdateInsertingAppearance(lathe.Owner, false);
InsertingRemoveQueue.Enqueue(lathe.Owner);
}
foreach (var (producingComp, lathe) in EntityQuery<LatheProducingComponent, LatheComponent>(false))
{
if (lathe.ProducingRecipe == null)
continue;
if (lathe.ProducingAccumulator < lathe.ProducingRecipe.CompleteTime.TotalSeconds)
{
lathe.ProducingAccumulator += frameTime;
continue;
}
lathe.ProducingAccumulator = 0;
FinishProducing(lathe.ProducingRecipe, lathe);
}
}
/// <summary>
/// Initialize the UI and appearance.
/// Appearance requires initialization or the layers break
/// </summary>
private void OnComponentInit(EntityUid uid, LatheComponent component, ComponentInit args)
{
component.UserInterface = uid.GetUIOrNull(LatheUiKey.Key);
if (component.UserInterface != null)
{
component.UserInterface.OnReceiveMessage += msg => UserInterfaceOnOnReceiveMessage(uid, component, msg);
}
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
appearance.SetData(LatheVisuals.IsInserting, false);
appearance.SetData(LatheVisuals.IsRunning, false);
}
/// <summary>
/// When someone tries to use an item on the lathe,
/// insert it if it's a stack and fits inside
/// </summary>
private void OnInteractUsing(EntityUid uid, LatheComponent component, InteractUsingEvent args)
{
if (!TryComp<MaterialStorageComponent>(uid, out var storage) || !TryComp<MaterialComponent>(args.Used, out var material))
return;
var multiplier = 1;
if (TryComp<StackComponent>(args.Used, out var stack))
multiplier = stack.Count;
var totalAmount = 0;
// Check if it can insert all materials.
foreach (var mat in material.MaterialIds)
{
// TODO: Change how MaterialComponent works so this is not hard-coded.
if (!storage.CanInsertMaterial(mat, component.VolumePerSheet * multiplier))
return;
totalAmount += component.VolumePerSheet * multiplier;
}
// Check if it can take ALL of the material's volume.
if (storage.StorageLimit > 0 && !storage.CanTakeAmount(totalAmount))
return;
var lastMat = string.Empty;
foreach (var mat in material.MaterialIds)
{
storage.InsertMaterial(mat, component.VolumePerSheet * multiplier);
lastMat = mat;
}
/// We need the prototype to get the color
_prototypeManager.TryIndex(lastMat, out MaterialPrototype? matProto);
EntityManager.QueueDeleteEntity(args.Used);
InsertingAddQueue.Enqueue(uid);
_popupSystem.PopupEntity(Loc.GetString("machine-insert-item", ("machine", uid),
("item", args.Used)), uid, Filter.Entities(args.User));
if (matProto != null)
{
UpdateInsertingAppearance(uid, true, matProto.Color);
}
UpdateInsertingAppearance(uid, true);
}
/// <summary>
/// This handles the checks to start producing an item, and
/// starts up the sound and visuals
/// </summary>
private bool Produce(LatheComponent component, LatheRecipePrototype recipe, bool SkipCheck = false)
{
if (!component.CanProduce(recipe)
|| !TryComp(component.Owner, out MaterialStorageComponent? storage))
return false;
if (!SkipCheck && HasComp<LatheProducingComponent>(component.Owner))
return false;
if (TryComp<ApcPowerReceiverComponent>(component.Owner, out var receiver) && !receiver.Powered)
return false;
component.UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue(component)));
component.ProducingRecipe = recipe;
foreach (var (material, amount) in recipe.RequiredMaterials)
{
// This should always return true, otherwise CanProduce fucked up.
storage.RemoveMaterial(material, amount);
}
component.UserInterface?.SendMessage(new LatheProducingRecipeMessage(recipe.ID));
if (component.ProducingSound != null)
{
SoundSystem.Play(Filter.Pvs(component.Owner), component.ProducingSound.GetSound(), component.Owner);
}
UpdateRunningAppearance(component.Owner, true);
ProducingAddQueue.Enqueue(component.Owner);
return true;
}
/// <summary>
/// After the production timer is up, this spawns the recipe and
/// either cleans up or continues to the next item in the queue
/// </summary>
private void FinishProducing(LatheRecipePrototype recipe, LatheComponent component)
{
component.ProducingRecipe = null;
EntityManager.SpawnEntity(recipe.Result, Comp<TransformComponent>(component.Owner).Coordinates);
component.UserInterface?.SendMessage(new LatheStoppedProducingRecipeMessage());
// Continue to next in queue if there are items left
if (component.Queue.Count > 0)
{
Produce(component, component.Queue.Dequeue(), true);
return;
}
ProducingRemoveQueue.Enqueue(component.Owner);
UpdateRunningAppearance(component.Owner, false);
}
/// <summary>
/// Sets the machine sprite to either play the running animation
/// or stop.
/// </summary>
private void UpdateRunningAppearance(EntityUid uid, bool isRunning)
{
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
appearance.SetData(LatheVisuals.IsRunning, isRunning);
}
/// <summary>
/// Sets the machine sprite to play the inserting animation
/// and sets the color of the inserted mat if applicable
/// </summary>
private void UpdateInsertingAppearance(EntityUid uid, bool isInserting, Color? color = null)
{
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
appearance.SetData(LatheVisuals.IsInserting, isInserting);
if (color != null)
appearance.SetData(LatheVisuals.InsertingColor, color);
}
/// <summary>
/// Handles all the button presses in the lathe UI
/// </summary>
private void UserInterfaceOnOnReceiveMessage(EntityUid uid, LatheComponent component, ServerBoundUserInterfaceMessage message)
{
if (TryComp<ApcPowerReceiverComponent>(uid, out var receiver) && !receiver.Powered)
return;
switch (message.Message)
{
case LatheQueueRecipeMessage msg:
_prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype? recipe);
if (recipe != null!)
for (var i = 0; i < msg.Quantity; i++)
{
component.Queue.Enqueue(recipe);
component.UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue(component)));
}
if (!HasComp<LatheProducingComponent>(component.Owner) && component.Queue.Count > 0)
Produce(component, component.Queue.Dequeue());
break;
case LatheSyncRequestMessage _:
if (!HasComp<MaterialStorageComponent>(uid)) return;
component.UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue(component)));
if (component.ProducingRecipe != null)
component.UserInterface?.SendMessage(new LatheProducingRecipeMessage(component.ProducingRecipe.ID));
break;
case LatheServerSelectionMessage _:
if (!TryComp(uid, out ResearchClientComponent? researchClient)) return;
researchClient.OpenUserInterface(message.Session);
break;
case LatheServerSyncMessage _:
if (!TryComp(uid, out TechnologyDatabaseComponent? database)
|| !TryComp(uid, out ProtolatheDatabaseComponent? protoDatabase)) return;
if (database.SyncWithServer())
protoDatabase.Sync();
break;
}
}
/// <summary>
/// Gets all the prototypes in the lathe's construction queue
/// </summary>
private Queue<string> GetIdQueue(LatheComponent lathe)
{
var queue = new Queue<string>();
foreach (var recipePrototype in lathe.Queue)
{
queue.Enqueue(recipePrototype.ID);
}
return queue;
}
}
}

View file

@ -244,7 +244,6 @@ namespace Content.Server.Light.EntitySystems
}
else
{
powerReceiver.Load = (light.On && lightBulb.State == LightBulbState.Normal) ? lightBulb.PowerUse : 0;
switch (lightBulb.State)
{
@ -275,6 +274,8 @@ namespace Content.Server.Light.EntitySystems
appearance?.SetData(PoweredLightVisuals.BulbState, PoweredLightState.Burned);
break;
}
powerReceiver.Load = (light.On && lightBulb.State == LightBulbState.Normal) ? lightBulb.PowerUse : 0;
}
}

View file

@ -9,6 +9,7 @@ using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.MobState.Components;
using Content.Shared.Stacks;
using Robust.Shared.Audio;
using Robust.Shared.Player;
@ -35,6 +36,9 @@ public sealed class HealingSystem : EntitySystem
private void OnHealingComplete(EntityUid uid, DamageableComponent component, HealingCompleteEvent args)
{
if (TryComp<MobStateComponent>(uid, out var state) && state.IsDead())
return;
if (TryComp<StackComponent>(args.Component.Owner, out var stack) && stack.Count < 1) return;
if (component.DamageContainerID is not null &&
@ -95,6 +99,9 @@ public sealed class HealingSystem : EntitySystem
return;
}
if (TryComp<MobStateComponent>(target, out var state) && state.IsDead())
return;
if (!TryComp<DamageableComponent>(target, out var targetDamage))
return;

View file

@ -219,7 +219,7 @@ namespace Content.Server.Pointing.EntitySystems
public override void Update(float frameTime)
{
foreach (var component in EntityManager.EntityQuery<PointingArrowComponent>())
foreach (var component in EntityManager.EntityQuery<PointingArrowComponent>(true))
{
component.Update(frameTime);
}

View file

@ -0,0 +1,55 @@
using Robust.Shared.Random;
using Content.Server.Chat.Managers;
using Content.Server.Disease.Zombie.Components;
using Content.Shared.MobState.Components;
namespace Content.Server.StationEvents.Events
{
/// <summary>
/// Revives several dead entities as zombies
/// </summary>
public sealed class ZombieOutbreak : StationEvent
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
public override string Name => "ZombieOutbreak";
public override int EarliestStart => 50;
public override float Weight => WeightLow / 2;
public override string? StartAudio => "/Audio/Announcements/bloblarm.ogg";
protected override float EndAfter => 1.0f;
public override int? MaxOccurrences => 1;
/// <summary>
/// Finds 1-3 random, dead entities accross the station
/// and turns them into zombies.
/// </summary>
public override void Startup()
{
base.Startup();
List<MobStateComponent> deadList = new();
foreach (var mobState in _entityManager.EntityQuery<MobStateComponent>())
{
if (mobState.IsDead() || mobState.IsCritical())
deadList.Add(mobState);
}
_random.Shuffle(deadList);
var toInfect = _random.Next(1, 3);
/// Now we give it to people in the list of dead entities earlier.
foreach (var target in deadList)
{
if (toInfect-- == 0)
break;
_entityManager.EnsureComponent<DiseaseZombieComponent>(target.Owner);
}
_chatManager.DispatchStationAnnouncement(Loc.GetString("station-event-zombie-outbreak-announcement"),
playDefaultSound: false, colorOverride: Color.DarkMagenta);
}
}
}

View file

@ -9,6 +9,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using Content.Server.VendingMachines.systems;
using static Content.Shared.Wires.SharedWiresComponent;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.VendingMachines
{
@ -16,9 +17,10 @@ namespace Content.Server.VendingMachines
public sealed class VendingMachineComponent : SharedVendingMachineComponent, IWires
{
public bool Ejecting;
public bool Emagged = false;
public TimeSpan AnimationDuration = TimeSpan.Zero;
[DataField("pack")]
public string PackPrototypeId = string.Empty;
[ViewVariables] [DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))] public string PackPrototypeId = string.Empty;
[ViewVariables] [DataField("emagPack", customTypeSerializer:typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))] public string EmagPackPrototypeId = string.Empty;
public string SpriteName = "";
public bool Broken;
/// <summary>

View file

@ -10,6 +10,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Content.Shared.Acts;
using Content.Shared.Emag.Systems;
using static Content.Shared.VendingMachines.SharedVendingMachineComponent;
using Content.Shared.Throwing;
@ -31,6 +32,7 @@ namespace Content.Server.VendingMachines.systems
SubscribeLocalEvent<VendingMachineComponent, InventorySyncRequestMessage>(OnInventoryRequestMessage);
SubscribeLocalEvent<VendingMachineComponent, VendingMachineEjectMessage>(OnInventoryEjectMessage);
SubscribeLocalEvent<VendingMachineComponent, BreakageEventArgs>(OnBreak);
SubscribeLocalEvent<VendingMachineComponent, GotEmaggedEvent>(OnEmagged);
}
private void OnComponentInit(EntityUid uid, VendingMachineComponent component, ComponentInit args)
@ -75,6 +77,16 @@ namespace Content.Server.VendingMachines.systems
TryUpdateVisualState(uid, VendingMachineVisualState.Broken, vendComponent);
}
private void OnEmagged(EntityUid uid, VendingMachineComponent component, GotEmaggedEvent args)
{
if (component.Emagged || component.EmagPackPrototypeId == string.Empty)
return;
AddVendEntries(component, component.EmagPackPrototypeId);
component.Emagged = true;
args.Handled = true;
}
public bool IsPowered(EntityUid uid, VendingMachineComponent? vendComponent = null)
{
if (!Resolve(uid, ref vendComponent))
@ -121,6 +133,27 @@ namespace Content.Server.VendingMachines.systems
vendComponent.Inventory = inventory;
}
/// <summary>
/// Add more entries for any reason AFTER initialization (emag, machine upgrades, etc)
/// </summary>
public void AddVendEntries(VendingMachineComponent component, string pack)
{
if (!_prototypeManager.TryIndex(pack, out VendingMachineInventoryPrototype? packPrototype))
{
Logger.Error($"Pack has no valid inventory prototype: {pack}");
return;
}
foreach (var (id, amount) in packPrototype.StartingInventory)
{
if (!_prototypeManager.TryIndex(id, out EntityPrototype? prototype))
{
continue;
}
component.Inventory.Add(new VendingMachineInventoryEntry(id, amount));
}
}
public void Deny(EntityUid uid, VendingMachineComponent? vendComponent = null)
{
if (!Resolve(uid, ref vendComponent))

View file

@ -0,0 +1,7 @@
namespace Content.Server.Weapons.Melee.ZombieTransfer.Components
{
[RegisterComponent]
public sealed class ZombieTransferComponent : Component
{
}
}

View file

@ -0,0 +1,69 @@
using System.Linq;
using Robust.Shared.Random;
using Content.Server.Body.Systems;
using Content.Server.Disease.Components;
using Content.Server.Disease.Zombie.Components;
using Content.Server.Drone.Components;
using Content.Server.Weapon.Melee;
using Content.Shared.Chemistry.Components;
using Content.Shared.Damage;
using Content.Shared.MobState.Components;
using Content.Server.Disease;
using Content.Server.Weapons.Melee.ZombieTransfer.Components;
using Content.Server.Body.Components;
namespace Content.Server.Weapons.Melee.ZombieTransfer
{
public sealed class ZombieTransferSystem : EntitySystem
{
[Dependency] private readonly DiseaseSystem _disease = default!;
[Dependency] private readonly BodySystem _body = default!;
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ZombieTransferComponent, MeleeHitEvent>(OnMeleeHit);
}
private void OnMeleeHit(EntityUid uid, ZombieTransferComponent component, MeleeHitEvent args)
{
if (!EntityManager.TryGetComponent<DiseaseZombieComponent>(args.User, out var diseaseZombieComp))
return;
if (!args.HitEntities.Any())
return;
foreach (EntityUid entity in args.HitEntities)
{
if (args.User == entity)
continue;
if (!HasComp<MobStateComponent>(entity) || HasComp<DroneComponent>(entity))
continue;
if (_robustRandom.Prob(diseaseZombieComp.Probability) && HasComp<DiseaseCarrierComponent>(entity))
{
_disease.TryAddDisease(entity, "ZombieInfection");
}
EntityManager.EnsureComponent<MobStateComponent>(entity, out var mobState);
if ((mobState.IsDead() || mobState.IsCritical()) && !HasComp<DiseaseZombieComponent>(entity)) //dead entities are eautomatically infected. MAYBE: have activated infect ability?
{
EntityManager.AddComponent<DiseaseZombieComponent>(entity);
var dspec = new DamageSpecifier();
//these damages match the zombie claw
dspec.DamageDict.TryAdd("Slash", -12);
dspec.DamageDict.TryAdd("Piercing", -7);
args.BonusDamage += dspec;
}
else if (mobState.IsAlive()) //heals when zombies bite live entities
{
var healingSolution = new Solution();
healingSolution.AddReagent("Bicaridine", 1.00); //if OP, reduce/change chem
_bloodstream.TryAddToChemicals(args.User, healingSolution);
}
}
}
}
}

View file

@ -550,6 +550,32 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> SpaceWind =
CVarDef.Create("atmos.space_wind", true, CVar.SERVERONLY);
/// <summary>
/// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects.
/// </summary>
public static readonly CVarDef<float> SpaceWindPressureForceDivisorThrow =
CVarDef.Create("atmos.space_wind_pressure_force_divisor_throw", 15f, CVar.SERVERONLY);
/// <summary>
/// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects.
/// </summary>
public static readonly CVarDef<float> SpaceWindPressureForceDivisorPush =
CVarDef.Create("atmos.space_wind_pressure_force_divisor_push", 2500f, CVar.SERVERONLY);
/// <summary>
/// The maximum velocity (not force) that may be applied to an object by atmospheric pressure differences.
/// Useful to prevent clipping through objects.
/// </summary>
public static readonly CVarDef<float> SpaceWindMaxVelocity =
CVarDef.Create("atmos.space_wind_max_velocity", 30f, CVar.SERVERONLY);
/// <summary>
/// The maximum force that may be applied to an object by pushing (i.e. not throwing) atmospheric pressure differences.
/// A "throwing" atmospheric pressure difference ignores this limit, but not the max. velocity limit.
/// </summary>
public static readonly CVarDef<float> SpaceWindMaxPushForce =
CVarDef.Create("atmos.space_wind_max_push_force", 20f, CVar.SERVERONLY);
/// <summary>
/// Whether monstermos tile equalization is enabled.
/// </summary>

View file

@ -48,6 +48,17 @@ namespace Content.Shared.CharacterAppearance.Systems
RaiseLocalEvent(uid, new ChangedHumanoidAppearanceEvent(appearance, sex, gender, species));
}
public void UpdateAppearance(EntityUid uid, HumanoidCharacterAppearance appearance, HumanoidAppearanceComponent? component = null)
{
if (!Resolve(uid, ref component)) return;
component.Appearance = appearance;
component.Dirty();
RaiseLocalEvent(uid, new ChangedHumanoidAppearanceEvent(appearance, component.Sex, component.Gender, component.Species));
}
private void OnAppearanceGetState(EntityUid uid, HumanoidAppearanceComponent component, ref ComponentGetState args)
{
args.State = new HumanoidAppearanceComponentState(component.Appearance, component.Sex, component.Gender, component.Species);

View file

@ -186,6 +186,16 @@ namespace Content.Shared.Damage
DamageChanged(component, new DamageSpecifier());
}
public void SetDamageModifierSetId(EntityUid uid, string damageModifierSetId, DamageableComponent? comp = null)
{
if (!Resolve(uid, ref comp))
return;
comp.DamageModifierSetId = damageModifierSetId;
Dirty(comp);
}
private void DamageableGetState(EntityUid uid, DamageableComponent component, ref ComponentGetState args)
{
args.State = new DamageableComponentState(component.Damage.DamageDict, component.DamageModifierSetId);

View file

@ -170,7 +170,7 @@ public abstract class SharedDoorSystem : EntitySystem
protected virtual void OnActivate(EntityUid uid, DoorComponent door, ActivateInWorldEvent args)
{
// avoid client-mispredicts, as the server will definitely handle this event
args.Handled = true;
args.Handled = true;
}
private void OnExamine(EntityUid uid, DoorComponent door, ExaminedEvent args)
@ -433,7 +433,7 @@ public abstract class SharedDoorSystem : EntitySystem
if (!otherPhysics.CanCollide)
continue;
if ((physics.CollisionMask & otherPhysics.CollisionLayer) == 0
if (otherPhysics.BodyType == BodyType.Static || (physics.CollisionMask & otherPhysics.CollisionLayer) == 0
&& (otherPhysics.CollisionMask & physics.CollisionLayer) == 0)
continue;

View file

@ -0,0 +1,94 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Lathe;
/// <summary>
/// Sent to the server to sync material storage and the recipe queue.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheSyncRequestMessage : BoundUserInterfaceMessage
{
public LatheSyncRequestMessage()
{
}
}
/// <summary>
/// Sent to the server to sync the lathe's technology database with the research server.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheServerSyncMessage : BoundUserInterfaceMessage
{
public LatheServerSyncMessage()
{
}
}
/// <summary>
/// Sent to the server to open the ResearchClient UI.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheServerSelectionMessage : BoundUserInterfaceMessage
{
public LatheServerSelectionMessage()
{
}
}
/// <summary>
/// Sent to the client when the lathe is producing a recipe.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheProducingRecipeMessage : BoundUserInterfaceMessage
{
public readonly string ID;
public LatheProducingRecipeMessage(string id)
{
ID = id;
}
}
/// <summary>
/// Sent to the client when the lathe stopped/finished producing a recipe.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheStoppedProducingRecipeMessage : BoundUserInterfaceMessage
{
public LatheStoppedProducingRecipeMessage()
{
}
}
/// <summary>
/// Sent to the client to let it know about the recipe queue.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheFullQueueMessage : BoundUserInterfaceMessage
{
public readonly Queue<string> Recipes;
public LatheFullQueueMessage(Queue<string> recipes)
{
Recipes = recipes;
}
}
/// <summary>
/// Sent to the server when a client queues a new recipe.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheQueueRecipeMessage : BoundUserInterfaceMessage
{
public readonly string ID;
public readonly int Quantity;
public LatheQueueRecipeMessage(string id, int quantity)
{
ID = id;
Quantity = quantity;
}
}
[NetSerializable, Serializable]
public enum LatheUiKey
{
Key,
}

View file

@ -1,17 +0,0 @@
using System;
using Robust.Shared.Serialization;
namespace Content.Shared.Lathe
{
[Serializable, NetSerializable]
public enum LatheVisualState
{
Idle,
Producing,
InsertingMetal,
InsertingGlass,
InsertingGold,
InsertingPlasma,
InsertingPlastic
}
}

View file

@ -0,0 +1,17 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Lathe
{
[Serializable, NetSerializable]
/// <summary>
/// Stores bools for if the machine is on
/// and if it's currently running and/or inserting.
/// Used for the visualizer
/// </summary>
public enum LatheVisuals : byte
{
IsRunning,
IsInserting,
InsertingColor
}
}

View file

@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
using Content.Shared.Research.Prototypes;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Lathe
{
@ -24,7 +19,7 @@ namespace Content.Shared.Lathe
foreach (var (material, amount) in recipe.RequiredMaterials)
{
if (storage[material] <= (amount * quantity)) return false;
if (storage[material] < (amount * quantity)) return false;
}
return true;
@ -34,98 +29,5 @@ namespace Content.Shared.Lathe
{
return PrototypeManager.TryIndex(id, out LatheRecipePrototype? recipe) && CanProduce(recipe, quantity);
}
/// <summary>
/// Sent to the server to sync material storage and the recipe queue.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheSyncRequestMessage : BoundUserInterfaceMessage
{
public LatheSyncRequestMessage()
{
}
}
/// <summary>
/// Sent to the server to sync the lathe's technology database with the research server.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheServerSyncMessage : BoundUserInterfaceMessage
{
public LatheServerSyncMessage()
{
}
}
/// <summary>
/// Sent to the server to open the ResearchClient UI.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheServerSelectionMessage : BoundUserInterfaceMessage
{
public LatheServerSelectionMessage()
{
}
}
/// <summary>
/// Sent to the client when the lathe is producing a recipe.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheProducingRecipeMessage : BoundUserInterfaceMessage
{
public readonly string ID;
public LatheProducingRecipeMessage(string id)
{
ID = id;
}
}
/// <summary>
/// Sent to the client when the lathe stopped/finished producing a recipe.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheStoppedProducingRecipeMessage : BoundUserInterfaceMessage
{
public LatheStoppedProducingRecipeMessage()
{
}
}
/// <summary>
/// Sent to the client to let it know about the recipe queue.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheFullQueueMessage : BoundUserInterfaceMessage
{
public readonly Queue<string> Recipes;
public LatheFullQueueMessage(Queue<string> recipes)
{
Recipes = recipes;
}
}
/// <summary>
/// Sent to the server when a client queues a new recipe.
/// </summary>
[Serializable, NetSerializable]
public sealed class LatheQueueRecipeMessage : BoundUserInterfaceMessage
{
public readonly string ID;
public readonly int Quantity;
public LatheQueueRecipeMessage(string id, int quantity)
{
ID = id;
Quantity = quantity;
}
}
[NetSerializable, Serializable]
public enum LatheUiKey
{
Key,
}
}
}

View file

@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using Content.Shared.Materials;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Research.Prototypes
{
@ -32,7 +27,7 @@ namespace Content.Shared.Research.Prototypes
private string _result = string.Empty;
[DataField("completetime")]
private int _completeTime = 2500;
private TimeSpan _completeTime = TimeSpan.FromSeconds(5);
[DataField("materials", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MaterialPrototype>))]
private Dictionary<string, int> _requiredMaterials = new();
@ -102,6 +97,6 @@ namespace Content.Shared.Research.Prototypes
/// Might lower depending on the lathe's upgrade level.
/// </summary>
[ViewVariables]
public int CompleteTime => _completeTime;
public TimeSpan CompleteTime => _completeTime;
}
}

Binary file not shown.

View file

@ -1,3 +1,7 @@
diagnoser_printing.ogg taken from https://freesound.org/people/RobSp1derp1g/sounds/615419/ and edited
vaccinator_running.ogg taken from https://freesound.org/people/RutgerMuller/sounds/365413/ and edited
uniformprinter.ogg taken from https://freesound.org/people/sukaton/sounds/60640/ and edited
circuitprinter.ogg taken from https://freesound.org/people/OroborosNZ/sounds/273649/ and https://freesound.org/people/170048@virtualwindow.co.za/sounds/408041/ and edited

Binary file not shown.

View file

@ -1,112 +1,4 @@
Entries:
- author: DubiousDoggo
changes:
- {message: Added crafting recipe for substations, type: Add}
id: 848
time: '2022-01-09T06:05:54.0000000+00:00'
- author: DubiousDoggo
changes:
- {message: 'Added SMES construction - no more easy power crippling :)', type: Add}
id: 849
time: '2022-01-09T07:31:07.0000000+00:00'
- author: Efruit
changes:
- {message: 'The Syndicate has gotten smarter. Now, only traitors can access the
Uplink menu.', type: Tweak}
- {message: Removed PDA checks., type: Remove}
id: 850
time: '2022-01-09T08:02:07.0000000+00:00'
- author: ElectroJr
changes:
- {message: Fixed the charge indicators on tasers and laser weapons not properly
updating after charging., type: Fix}
id: 851
time: '2022-01-09T12:48:59.0000000+00:00'
- author: ElectroJr
changes:
- {message: Insulated gloves and galoshes no longer work when in your pockets. You
actually have to wear them., type: Fix}
id: 852
time: '2022-01-10T04:37:21.0000000+00:00'
- author: mirrorcult
changes:
- {message: Ghosts can now automatically follow entities by using a right click
Follow verb., type: Add}
id: 853
time: '2022-01-10T05:47:38.0000000+00:00'
- author: Zyme
changes:
- {message: Added ritual and cursed chair, type: Add}
id: 854
time: '2022-01-11T02:17:22.0000000+00:00'
- author: Peptide90
changes:
- {message: Some Autolathe recipes now require plastic instead of glass., type: Fix}
id: 855
time: '2022-01-11T02:20:35.0000000+00:00'
- author: TaralGit
changes:
- {message: Increased laser damage, type: Tweak}
id: 856
time: '2022-01-11T04:11:47.0000000+00:00'
- author: ElectroJr
changes:
- {message: Bodies once again fit in body bags., type: Fix}
id: 857
time: '2022-01-11T04:55:27.0000000+00:00'
- author: Rane
changes:
- {message: Saltern now has all the latest & greatest objects from the past 2 months.,
type: Add}
- {message: Saltern medical has been renovated., type: Tweak}
id: 858
time: '2022-01-11T06:27:30.0000000+00:00'
- author: Pancake
changes:
- {message: The singularity will no longer vaporize engineers in 2 seconds., type: Fix}
id: 859
time: '2022-01-11T06:30:17.0000000+00:00'
- author: Lamrr
changes:
- {message: The captain's sabre has returned! Cut down the enemies of the station
with wonderful bourgeois excellence!, type: Add}
id: 860
time: '2022-01-11T06:50:11.0000000+00:00'
- author: metalgearsloth
changes:
- {message: You can now toggle shuttle modes via the console., type: Add}
id: 861
time: '2022-01-11T07:17:55.0000000+00:00'
- author: metalgearsloth
changes:
- {message: Docking ports can now be saved to and loaded from maps, type: Add}
id: 862
time: '2022-01-11T13:47:13.0000000+00:00'
- author: MeltedPixel
changes:
- {message: Added Whisper chat functionality, type: Add}
id: 863
time: '2022-01-11T14:48:18.0000000+00:00'
- author: MeltedPixel
changes:
- {message: Ghost's now see unobfuscated messages when whispered., type: Fix}
id: 864
time: '2022-01-11T23:51:49.0000000+00:00'
- author: mirrorcult
changes:
- {message: Mining entities with pickaxes now has a delay., type: Tweak}
id: 865
time: '2022-01-12T02:12:08.0000000+00:00'
- author: metalgearsloth
changes:
- {message: Remove duplicate ghost takeovers when an admin controls a mob., type: Fix}
id: 866
time: '2022-01-12T07:25:05.0000000+00:00'
- author: Peptide90
changes:
- {message: Fixed trashbag so now only trash can be picked up., type: Fix}
id: 867
time: '2022-01-13T12:53:14.0000000+00:00'
- author: ElectroJr
changes:
- {message: 'Makes smoking even cooler (visuals fixed, but hopefully properly this
@ -3029,3 +2921,125 @@ Entries:
- {message: 'Carp, ticks, spiders, and bears now have replacement accents.', type: Tweak}
id: 1347
time: '2022-04-16T23:08:52.0000000+00:00'
- author: mirrorcult
changes:
- {message: You can no longer heal people out of death., type: Tweak}
id: 1348
time: '2022-04-17T06:29:31.0000000+00:00'
- author: Rane
changes:
- {message: Chaplains can now summon a familiar from their bible., type: Add}
- {message: Evil chaplains can now emag the Pietyvend for some goodies., type: Add}
- {message: You can now draw blood from most mobs., type: Fix}
id: 1349
time: '2022-04-17T07:16:03.0000000+00:00'
- author: Rane
changes:
- {message: The lathe visualizer now works., type: Fix}
- {message: Lathes now correctly let you produce something when you have the exact
amount of materials required., type: Fix}
- {message: Some lathes now have sounds that play., type: Add}
- {message: Lathes with inserting animations will dynamically color them based on
the color of the material., type: Add}
- {message: 'Increased most lathe production times between 4x and 10x. So, from
half a second to 2 seconds in most cases.', type: Tweak}
id: 1350
time: '2022-04-17T07:34:14.0000000+00:00'
- author: PJB3005
changes:
- {message: Made lobby art look less choppy if you aren't playing on exactly 1080p
fullscreen., type: Tweak}
id: 1351
time: '2022-04-17T11:14:53.0000000+00:00'
- author: Rane
changes:
- {message: The bible's Summon Familiar now appears in the action bar in addition
to being an alternative verb., type: Tweak}
- {message: Familiars can now open public and chapel doors by walking into them.,
type: Tweak}
- {message: Familiars now accurately show when they are dead when examined., type: Fix}
id: 1352
time: '2022-04-17T21:43:00.0000000+00:00'
- author: Rane
changes:
- {message: Fixed security techfab visuals, type: Fix}
id: 1353
time: '2022-04-17T21:55:23.0000000+00:00'
- author: ElectroJr
changes:
- {message: Fixed docking airlocks not having proper collision., type: Fix}
id: 1354
time: '2022-04-18T03:25:19.0000000+00:00'
- author: ElectroJr
changes:
- {message: Fixed most hardsuit helmets not having working lights., type: Fix}
id: 1355
time: '2022-04-18T06:56:37.0000000+00:00'
- author: ElectroJr
changes:
- {message: Fixed lamps and lanterns not having working lights., type: Fix}
id: 1356
time: '2022-04-18T13:23:21.0000000+00:00'
- author: 20kdc
changes:
- {message: You should be less likely to be phased through walls., type: Fix}
- {message: When pushed by high pressure differences ("space wind") you should be
pushed in the direction of the pressure difference again., type: Fix}
id: 1357
time: '2022-04-18T14:42:32.0000000+00:00'
- author: EmoGarbage404
changes:
- {message: 'Nanotrasen has reported sightings of corpses prowljng the halls, given
new life by unknown forces.', type: Add}
id: 1358
time: '2022-04-18T22:30:22.0000000+00:00'
- author: UKNOWH
changes:
- {message: You can grind pills to test for its substance, type: Add}
id: 1359
time: '2022-04-18T22:40:35.0000000+00:00'
- author: Mirino97
changes:
- {message: 'Bees cannot disarm anymore, so no more bee stunning!', type: Tweak}
id: 1360
time: '2022-04-18T22:41:07.0000000+00:00'
- author: CrzyPotato
changes:
- {message: 'Airlock Painter now has a lathe recipe and can be found in tool closets,
and tool vendors', type: Add}
id: 1361
time: '2022-04-18T22:43:19.0000000+00:00'
- author: Mirino97
changes:
- {message: Replaced light bulbs in fixtures will no longer remain off!, type: Fix}
id: 1362
time: '2022-04-18T22:47:04.0000000+00:00'
- author: ShadowCommander
changes:
- {message: Firelocks and airlocks now close when there are static entities in the
way (e.g. anchored tables)., type: Fix}
id: 1363
time: '2022-04-19T13:45:37.0000000+00:00'
- author: EmoGarbage404
changes:
- {message: Zombie names no longer spam fill the ghost role menu and only appear
when able to be taken over., type: Fix}
- {message: Probability adjustments for zombie outbreak event., type: Tweak}
id: 1364
time: '2022-04-20T01:54:11.0000000+00:00'
- author: UKNOWH
changes:
- {message: You can now put stuff in the chef hat, type: Add}
id: 1365
time: '2022-04-20T05:17:03.0000000+00:00'
- author: UKNOWH
changes:
- {message: Added a Flash payload that allows players to make modular flashbangs,
type: Add}
id: 1366
time: '2022-04-20T06:08:57.0000000+00:00'
- author: UKNOWH
changes:
- {message: mouse size changed form 0 to 5, type: Add}
id: 1367
time: '2022-04-20T07:19:33.0000000+00:00'

View file

@ -1,5 +1,11 @@
bible-heal-success-self = You hit {THE($target)} with {THE($bible)}, and their wounds close in a flash of holy light!
bible-heal-success-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and their wounds close in a flash of holy light!
bible-heal-fail-self = You hit {THE($target)} with {THE($bible)}, and it lands with a sad thwack, dazing them!
bible-heal-fail-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and it lands with a sad thack, dazing them!
bible-heal-success-self = You hit {THE($target)} with {THE($bible)}, and {POSS-ADJ($target)} wounds close in a flash of holy light!
bible-heal-success-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and {POSS-ADJ($target)} wounds close in a flash of holy light!
bible-heal-fail-self = You hit {THE($target)} with {THE($bible)}, and it lands with a sad thwack, dazing {OBJECT($target)}!
bible-heal-fail-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and it lands with a sad thack, dazing {OBJECT($target)}!
bible-sizzle = The book sizzles in your hands!
bible-summon-verb = Summon familiar
bible-summon-verb-desc = Summon a familiar that will aid you and gain humanlike intelligence once inhabited by a soul.
necro-heal-success-self = You hit {THE($target)} with {THE($bible)}, and {POSS-ADJ($target)} flesh warps as it melts!
necro-heal-success-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and {POSS-ADJ($target)} flesh warps as it melts!
necro-heal-fail-self = You hit {THE($target)} with {THE($bible)}, and it lands with a sad thwack, failing to smite {OBJECT($target)}.
necro-heal-fail-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and it lands with a sad thack, failing to smite {OBJECT($target)}.

View file

@ -4,4 +4,5 @@ decal-placer-window-rotation = Rotation
decal-placer-window-zindex = Draw Depth
decal-placer-window-enable-snap = Snap To Tile
decal-placer-window-enable-cleanable = Cleanable
decal-placer-window-palette = Palette
palette-color-picker-window-title = Palettes

View file

@ -0,0 +1,7 @@
zombie-transform = {CAPITALIZE(THE($target))} turned into a zombie!
zombie-infection-greeting = You have become a zombie. Your goal is to seek out the living and to try to infect them. Work together with your fellow zombies to overpower the remaining crewmates.
zombie-generic = zombie
zombie-name-prefix = zombified {$target}
zombie-role-desc = A malevolent creature of the dead.
zombie-role-rules = You are an antagonist. Search out the living and bite them in order to infect them and turn them into zombies. Work together with other the zombies to overtake the station.

View file

@ -0,0 +1 @@
machine-insert-item = You insert {THE($item)} into {THE($machine)}.

View file

@ -0,0 +1 @@
station-event-zombie-outbreak-announcement = Confirmed sightings of various undead aboard the station. All personnel should arm themselves, barricade doors, and secure their location in order to prevent further infection.

View file

@ -127290,13 +127290,6 @@ entities:
- pos: 0.5,-81.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- containers:
board: !type:Container
ents: []
@ -146801,13 +146794,6 @@ entities:
pos: 53.5,11.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 13115
type: TableWood
components:
@ -174387,13 +174373,6 @@ entities:
pos: 53.5,6.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 16226
type: SignCargoDock
components:
@ -195113,13 +195092,6 @@ entities:
pos: 34.5,42.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 18631
type: AirlockExternalLocked
components:
@ -195133,13 +195105,6 @@ entities:
pos: 34.5,33.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 18633
type: AirlockExternalLocked
components:
@ -195153,13 +195118,6 @@ entities:
pos: 42.5,33.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 18635
type: AirlockExternalShuttleLocked
components:
@ -195167,13 +195125,6 @@ entities:
pos: 42.5,42.5
parent: 61
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 18636
type: AirlockExternalLocked
components:

File diff suppressed because it is too large Load diff

View file

@ -74161,13 +74161,6 @@ entities:
pos: -55.5,0.5
parent: 33
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7115
type: AirlockExternalLocked
components:
@ -74187,13 +74180,6 @@ entities:
pos: -63.5,0.5
parent: 33
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7118
type: Poweredlight
components:

View file

@ -29565,13 +29565,6 @@ entities:
pos: -73.5,33.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 1445
type: AirlockExternalGlassShuttleLocked
components:
@ -29579,13 +29572,6 @@ entities:
pos: -67.5,33.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 1446
type: AirlockExternalGlassLocked
components:
@ -29605,13 +29591,6 @@ entities:
pos: -61.5,33.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 1449
type: ReinforcedWindow
components:
@ -34981,13 +34960,6 @@ entities:
pos: -46.5,46.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 2162
type: PoweredSmallLight
components:
@ -99894,13 +99866,6 @@ entities:
pos: -42.5,46.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 8313
type: WallReinforced
components:
@ -107670,13 +107635,6 @@ entities:
pos: -83.5,24.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9241
type: AirlockExternalGlassShuttleLocked
components:
@ -107684,13 +107642,6 @@ entities:
pos: -83.5,25.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9242
type: ReinforcedWindow
components:
@ -107809,13 +107760,6 @@ entities:
pos: -79.5,29.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9257
type: AirlockExternalGlassShuttleLocked
components:
@ -107823,13 +107767,6 @@ entities:
pos: -80.5,29.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9258
type: CableApcExtension
components:
@ -110046,13 +109983,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9482
type: AirlockShuttle
components:
@ -110065,13 +109995,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9483
type: WallReinforced
components:
@ -113056,13 +112979,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9801
type: AirlockShuttle
components:
@ -113076,13 +112992,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9802
type: SignShipDock
components:
@ -114596,13 +114505,6 @@ entities:
pos: -43.5,-29.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9979
type: FirelockGlass
components:
@ -114632,13 +114534,6 @@ entities:
pos: -43.5,-25.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 9983
type: ReinforcedWindow
components:
@ -114808,13 +114703,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 10009
type: AirlockShuttle
components:
@ -114827,13 +114715,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 10010
type: CableApcExtension
components:
@ -127412,13 +127293,6 @@ entities:
pos: 65.5,19.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11270
type: AirlockShuttle
components:
@ -127426,13 +127300,6 @@ entities:
pos: 66.5,16.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11271
type: AirlockExternalGlassShuttleLocked
components:
@ -127440,13 +127307,6 @@ entities:
pos: 66.5,0.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11272
type: AirlockExternalGlassShuttleLocked
components:
@ -127454,13 +127314,6 @@ entities:
pos: 66.5,4.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11273
type: AirlockExternalGlassShuttleLocked
components:
@ -127468,13 +127321,6 @@ entities:
pos: 66.5,7.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11274
type: AirlockExternalGlassShuttleLocked
components:
@ -127482,13 +127328,6 @@ entities:
pos: 66.5,11.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11275
type: Catwalk
components:
@ -137243,13 +137082,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12248
type: AirlockShuttle
components:
@ -137263,39 +137095,18 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12249
type: AirlockShuttle
components:
- pos: 0.5,-7.5
parent: 12185
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12250
type: AirlockShuttle
components:
- pos: 1.5,-7.5
parent: 12185
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12251
type: Thruster
components:
@ -139038,13 +138849,6 @@ entities:
pos: 25.5,36.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12428
type: ExtinguisherCabinetFilled
components:
@ -142112,13 +141916,6 @@ entities:
pos: -43.5,-24.5
parent: 130
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12723
type: BoxSterile
components:

View file

@ -14552,13 +14552,6 @@ entities:
- pos: -10.5,-8.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 39
type: CableApcExtension
components:
@ -14970,13 +14963,6 @@ entities:
- pos: -6.5,-13.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 97
type: Grille
components:
@ -16561,13 +16547,6 @@ entities:
pos: -1.5,10.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 324
type: AirlockExternalGlass
components:
@ -16587,13 +16566,6 @@ entities:
pos: -1.5,4.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 327
type: Chair
components:
@ -28644,13 +28616,6 @@ entities:
pos: 4.5,24.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 2002
type: AirlockExternalGlass
components:
@ -28670,13 +28635,6 @@ entities:
pos: 4.5,26.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 2005
type: Grille
components:
@ -128259,13 +128217,6 @@ entities:
- pos: -11.5,-1.5
parent: 2
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 12126
type: WallShuttle
components:

View file

@ -6985,13 +6985,6 @@ entities:
pos: -41.5,8.5
parent: 857
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- containers:
board: !type:Container
ents: []
@ -7042,13 +7035,6 @@ entities:
pos: -41.5,4.5
parent: 857
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- containers:
board: !type:Container
ents: []

View file

@ -24325,13 +24325,6 @@ entities:
pos: 11.5,14.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 539
type: WallSolid
components:
@ -29334,13 +29327,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 1203
type: WallReinforced
components:
@ -29642,13 +29628,6 @@ entities:
pos: -21.5,6.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- containers:
board: !type:Container
ents: []
@ -35838,13 +35817,6 @@ entities:
pos: 17.5,14.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 1958
type: WallSolid
components:
@ -36359,13 +36331,6 @@ entities:
changeAirtight: False
state: Opening
type: Door
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 2019
type: WallReinforced
components:
@ -41116,13 +41081,6 @@ entities:
pos: -51.5,14.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 2556
type: WallReinforced
components:
@ -83079,52 +83037,24 @@ entities:
- pos: 18.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7403
type: AirlockExternalGlassShuttleLocked
components:
- pos: 17.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7404
type: AirlockExternalGlassShuttleLocked
components:
- pos: 12.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7405
type: AirlockExternalGlassShuttleLocked
components:
- pos: 13.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7406
type: AirlockCargoGlassLocked
components:
@ -83485,26 +83415,12 @@ entities:
- pos: 2.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7466
type: AirlockExternalGlassShuttleLocked
components:
- pos: 3.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7467
type: Catwalk
components:
@ -84416,52 +84332,24 @@ entities:
- pos: -11.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7589
type: AirlockExternalGlassShuttleLocked
components:
- pos: -10.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7590
type: AirlockExternalGlassShuttleLocked
components:
- pos: -3.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7591
type: AirlockExternalGlassShuttleLocked
components:
- pos: -2.5,-135.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7592
type: AirlockExternalGlass
components:
@ -84775,13 +84663,6 @@ entities:
pos: -22.5,-131.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7644
type: AirlockExternalGlassShuttleLocked
components:
@ -84789,13 +84670,6 @@ entities:
pos: -22.5,-130.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 7645
type: Catwalk
components:
@ -115529,13 +115403,6 @@ entities:
pos: 45.5,-31.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 11293
type: AsteroidRock
components:
@ -203986,13 +203853,6 @@ entities:
pos: -45.5,14.5
parent: 112
type: Transform
- fixtures:
- shape: !type:PhysShapeCircle
position: 0,-0.5
radius: 0.2
hard: False
id: docking
type: Fixtures
- uid: 20452
type: Rack
components:

View file

@ -37,6 +37,8 @@
prob: 0.3
- id: CableApcStack
prob: 0.3
- id: AirlockPainter
prob: 0.7
- type: entity
id: LockerElectricalSuppliesFilled

View file

@ -152,6 +152,7 @@
- Flash
- Handcuffs
- Stunbaton
- FlashPayload
- type: technology
name: "non-lethal technology"

View file

@ -7,16 +7,25 @@
ClothingUniformJumpskirtChaplain: 2
ClothingOuterHoodieChaplain: 1
ClothingOuterHoodieBlack: 1
ClothingOuterRobesCult: 1
ClothingOuterArmorCult: 1
ClothingHeadHatHoodChaplainHood: 1
ClothingHeadHatHoodCulthood: 1
ClothingHeadHatHoodNunHood: 1
ClothingHeadHatFez: 1
ClothingHeadHatPlaguedoctor: 1
ClothingHeadHatWitch: 1
ClothingHeadHatWitch1: 1
ClothingHeadHelmetCult: 1
ClothingHeadsetService: 2
ClothingOuterPlagueSuit: 1
ClothingMaskPlague: 1
ClothingHeadsetService: 2
- type: vendingMachineInventory
id: PietyVendEmagInventory
spriteName: chapel
startingInventory:
ClothingOuterArmorCult: 1
ClothingHeadHelmetCult: 1
ClothingOuterRobesCult: 3
ClothingHeadHatHoodCulthood: 3
ClothingShoesCult: 4
BedsheetCult: 4
BibleNecronomicon: 1

View file

@ -14,3 +14,5 @@
ClothingHeadsetMedical: 4
ClothingOuterWinterMed: 2
ClothingOuterWinterPara: 2
ClothingHeadHelmetVoidParamed: 1
ClothingOuterHardsuitVoidParamed: 1

View file

@ -14,3 +14,4 @@
GasAnalyzer: 5
ClothingHandsGlovesColorYellowBudget: 5
ClothingBeltUtility: 3
AirlockPainter: 3

View file

@ -83,6 +83,18 @@
Cold: 1.5
Poison: 0.8
- type: damageModifierSet
id: Infernal
coefficients:
Blunt: 0.8
Slash: 0.8
Piercing: 0.8
Cold: 0.8
Heat: 0.2
# Holy: 3 If we ever get some holy or magic sort of damage type they should be vulnerable
flatReductions:
Heat: 3
- type: damageModifierSet
id: Scale # Skin tougher, bones weaker, strong stomachs, cold-blooded (kindof)
coefficients:
@ -92,6 +104,17 @@
Heat: 0.9
Poison: 0.9
- type: damageModifierSet
id: Zombie #Blunt resistent and immune to biological threats, but can be hacked apart and burned
coefficients:
Blunt: 0.4
Slash: 0.8
Piercing: 0.9
Shock: 0.8
Cold: 0.2
Heat: 3.0
Poison: 0.0
# Represents which damage types should be modified
# in relation to how they cause bloodloss damage.
- type: damageModifierSet

View file

@ -15,4 +15,29 @@
- !type:DiseaseReagentCure
reagent: Phalanximine
min: 15
### Once radiation is refactored I want it to have a small chance of giving you regular cancer
- type: disease
id: ZombieInfection
name: Zombie Infection #This is the incubation period of the zombie disease.
infectious: false
cureResist: 0.2
effects:
- !type:DiseaseHealthChange
probability: 0.05
damage:
types:
Blunt: 3
- !type:DiseaseSnough
probability: 0.005
snoughMessage: disease-cough
snoughSound:
collection: Coughs
- !type:DiseaseProgression
probability: 0.5
comp: DiseaseZombie
cures:
- !type:DiseaseReagentCure
reagent: Romerol
min: 10

View file

@ -86,6 +86,7 @@
map: [ "light" ]
- type: Clothing
HeldPrefix: off
- type: ToggleableLightVisuals
- type: PointLight
netsync: false
enabled: false

View file

@ -107,6 +107,8 @@
sprite: Clothing/Head/Hats/chefhat.rsi
- type: Clothing
sprite: Clothing/Head/Hats/chefhat.rsi
- type: Storage
capacity: 5
- type: entity
parent: ClothingHeadBase

View file

@ -16,7 +16,7 @@
coefficients:
Blunt: 0.5
Slash: 0.8
Piercing: 0.8
Piercing: 0.8
- type: entity
parent: ClothingHeadEVAHelmetBase
@ -41,6 +41,13 @@
- type: Clothing
sprite: Clothing/Head/Helmets/cult.rsi
- type: IngestionBlocker
- type: Armor
modifiers:
coefficients:
Blunt: 0.8
Slash: 0.8
Piercing: 0.9
Heat: 0.8
- type: entity
parent: ClothingHeadEVAHelmetBase
@ -204,7 +211,7 @@
Radiation: 1
- type: PressureProtection
highPressureMultiplier: 0.65
lowPressureMultiplier: 25
lowPressureMultiplier: 1000
- type: entity
parent: ClothingHeadHardsuitWithLightBase # hardsuitlight base for light and protection
@ -229,13 +236,13 @@
Radiation: .95
- type: PressureProtection
highPressureMultiplier: 0.45
lowPressureMultiplier: 25
lowPressureMultiplier: 1000
- type: entity
parent: ClothingHeadBase
id: ClothingHeadHelmetLing
name: chitinous helmet
description: Inflates the changeling's body into an all-consuming chitinous mass of armor. Provides extensive protection against physical damage, but less against other types. Its mass slows the changeling's movement, and maintaining its shape slows chemical generation.
description: Inflates the changeling's body into an all-consuming chitinous mass of armor.
components:
- type: Sprite
sprite: Clothing/Head/Helmets/linghelmet.rsi
@ -249,3 +256,24 @@
Piercing: 0.5
Heat: 0.9
- type: entity
parent: ClothingHeadEVAHelmetBase
id: ClothingHeadHelmetVoidParamed
name: Paramedic Void Helmet
description: A void helmet made for paramedics.
components:
- type: Sprite
sprite: Clothing/Head/Helmets/paramedhelm.rsi
- type: Clothing
sprite: Clothing/Head/Helmets/paramedhelm.rsi
- type: IngestionBlocker
- type: DiseaseProtection
protection: 0.15
- type: TemperatureProtection
coefficient: 0.1
- type: Armor
modifiers:
coefficients:
Slash: 0.95
Heat: 0.90
Radiation: 0.75

View file

@ -134,6 +134,8 @@
Slash: 0.4
Piercing: 0.9
Heat: 0.9
- type: ExplosionResistance
resistance: 0.9
- type: entity
parent: ClothingOuterBase
@ -152,6 +154,8 @@
Slash: 0.7
Piercing: 0.4
Heat: 0.9
- type: ExplosionResistance
resistance: 0.8
- type: entity
parent: ClothingOuterBase
@ -170,12 +174,14 @@
Slash: 0.5
Piercing: 0.6
Heat: 0.5
- type: ExplosionResistance
resistance: 0.65
- type: entity
parent: ClothingOuterBase
id: ClothingOuterArmorChangeling
name: chitinous armor
description: Inflates the changeling's body into an all-consuming chitinous mass of armor. Provides extensive protection against physical damage, but less against other types. Its mass slows the changeling's movement, and maintaining its shape slows chemical generation.
description: Inflates the changeling's body into an all-consuming chitinous mass of armor.
components:
- type: Sprite
sprite: Clothing/OuterClothing/Armor/lingarmor.rsi
@ -192,4 +198,5 @@
- type: ClothingSpeedModifier
walkModifier: 0.7
sprintModifier: 0.65
- type: ExplosionResistance
resistance: 0.5

View file

@ -34,6 +34,7 @@
Heat: 0.90
Radiation: 0.25
- type: DiseaseProtection
protection: 0.05
- type: entity
abstract: true
@ -52,3 +53,4 @@
- type: Clothing
size: 30
- type: DiseaseProtection
protection: 0.05

View file

@ -23,6 +23,13 @@
sprite: Clothing/OuterClothing/Coats/detective.rsi
- type: Storage
capacity: 10
- type: Armor
modifiers:
coefficients:
Blunt: 0.8
Slash: 0.8
Piercing: 0.6
Heat: 0.9
- type: entity
parent: ClothingOuterBase

View file

@ -13,7 +13,7 @@
lowPressureMultiplier: 10000
- type: ClothingSpeedModifier
walkModifier: 0.65
sprintModifier: 0.7
sprintModifier: 0.65
- type: Armor
modifiers:
coefficients:
@ -24,7 +24,9 @@
Radiation: 0.25
- type: TemperatureProtection
coefficient: 0.01
- type: ExplosionResistance
resistance: 0.8
- type: entity
parent: ClothingOuterHardsuitBase
id: ClothingOuterHardsuitCap
@ -49,6 +51,8 @@
Piercing: 0.75
Heat: 0.5
Radiation: 0.1
- type: ExplosionResistance
resistance: 0.5
- type: entity
parent: ClothingOuterHardsuitBase
@ -74,6 +78,8 @@
Piercing: 0.2
Heat: 0.2
Radiation: 0.2
- type: ExplosionResistance
resistance: 0.3
- type: entity
parent: ClothingOuterHardsuitBase
@ -99,7 +105,9 @@
Piercing: 0.85
Heat: 0.7
Radiation: 0.35
- type: ExplosionResistance
resistance: 0.8
- type: entity
parent: ClothingOuterHardsuitBase
id: ClothingOuterHardsuitEngineeringWhite
@ -124,6 +132,8 @@
Piercing: 0.8
Heat: 0.4
Radiation: 0.25
- type: ExplosionResistance
resistance: 0.8
#The voidsuit and eva suit are not techically 'hardsuits' but this seems to be the place for all EVA-capable outer clothing. This may be worth reevaluating when we have a lot more items.
- type: entity
@ -195,7 +205,7 @@
protection: 0.2
- type: ClothingSpeedModifier
walkModifier: 0.9
sprintModifier: 0.9
sprintModifier: 0.95
- type: Armor
modifiers:
coefficients:
@ -226,6 +236,8 @@
- type: ClothingSpeedModifier
walkModifier: 0.75
sprintModifier: 0.75
- type: ExplosionResistance
resistance: 0.7
- type: entity
parent: ClothingOuterHardsuitBase
@ -251,6 +263,8 @@
Piercing: 0.75
Heat: 0.85
Radiation: 0.5
- type: ExplosionResistance
resistance: 0.8
- type: entity
parent: ClothingOuterHardsuitBase
@ -268,11 +282,13 @@
- type: Armor
modifiers:
coefficients:
Blunt: 0.7
Slash: 0.7
Piercing: 0.7
Blunt: 0.6
Slash: 0.6
Piercing: 0.6
Heat: 0.8
Radiation: 0.25
- type: ExplosionResistance
resistance: 0.6
- type: entity
parent: ClothingOuterHardsuitSecurity
@ -289,15 +305,17 @@
lowPressureMultiplier: 10000
- type: ClothingSpeedModifier
walkModifier: 0.7
sprintModifier: 0.7
sprintModifier: 0.75
- type: Armor
modifiers:
coefficients:
Blunt: 0.7
Slash: 0.65
Piercing: 0.7
Blunt: 0.6
Slash: 0.6
Piercing: 0.6
Heat: 0.8
Radiation: 0.25
- type: ExplosionResistance
resistance: 0.6
- type: entity
parent: ClothingOuterHardsuitBase
@ -323,6 +341,8 @@
Piercing: 0.4
Heat: 0.4 #all the combat numbers are pumped up here
Radiation: 0.20
- type: ExplosionResistance
resistance: 0.5
- type: entity
parent: ClothingOuterHardsuitBase
@ -348,6 +368,8 @@
Piercing: 0.4
Heat: 0.25
Radiation: 0.20
- type: ExplosionResistance
resistance: 0.5
- type: entity
parent: ClothingOuterHardsuitBase
@ -373,6 +395,8 @@
Piercing: 1
Heat: 0.5
Radiation: 0.3
- type: ExplosionResistance
resistance: 0.8
- type: entity
parent: ClothingOuterHardsuitBase
@ -398,3 +422,31 @@
Piercing: 0.95
Heat: 0.9
Radiation: 0.5 #low physical but gave some rad protection in case of rad artifacts/rad storms
- type: entity
parent: ClothingOuterEVASuitBase
id: ClothingOuterHardsuitVoidParamed
name: Paramedic Void Suit
description: A void suit made for paramedics.
components:
- type: Sprite
sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi
- type: Clothing
sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi
- type: PressureProtection
highPressureMultiplier: 0.5
lowPressureMultiplier: 1000
- type: ClothingSpeedModifier
walkModifier: 0.9
sprintModifier: 0.9
- type: DiseaseProtection
protection: 0.15
- type: TemperatureProtection
coefficient: 0.1
- type: Armor
modifiers:
coefficients:
Slash: 0.95
Heat: 0.90
Radiation: 0.75

View file

@ -39,7 +39,7 @@
sprite: Clothing/OuterClothing/Suits/fire.rsi
- type: PressureProtection
highPressureMultiplier: 0.65
lowPressureMultiplier: 25
lowPressureMultiplier: 1000
- type: Clothing
sprite: Clothing/OuterClothing/Suits/fire.rsi
- type: Armor
@ -152,7 +152,7 @@
sprite: Clothing/OuterClothing/Suits/atmos_firesuit.rsi
- type: PressureProtection
highPressureMultiplier: 0.45
lowPressureMultiplier: 25
lowPressureMultiplier: 1000
- type: TemperatureProtection
coefficient: 0.01
- type: Clothing
@ -164,4 +164,4 @@
Heat: 0.35
- type: ClothingSpeedModifier
walkModifier: 0.7
sprintModifier: 0.7
sprintModifier: 0.75

View file

@ -15,7 +15,9 @@
Slash: 0.7
Piercing: 0.5
Heat: 0.9
- type: ExplosionResistance
resistance: 0.9
- type: entity
parent: ClothingOuterBase
id: ClothingOuterVestWeb
@ -33,6 +35,8 @@
Slash: 0.6
Piercing: 0.3
Heat: 0.9
- type: ExplosionResistance
resistance: 0.9
- type: entity
parent: ClothingOuterBase
@ -51,17 +55,28 @@
Slash: 0.9
Piercing: 0.4
Heat: 0.9
- type: ExplosionResistance
resistance: 0.9
- type: entity
parent: ClothingOuterBase
id: ClothingOuterVestDetective
name: detective's vest
description: A hard-boiled private investigator's grey trenchcoat.
description: A hard-boiled private investigator's armored vest.
components:
- type: Sprite
sprite: Clothing/OuterClothing/Vests/detvest.rsi
- type: Clothing
sprite: Clothing/OuterClothing/Vests/detvest.rsi
- type: Armor
modifiers:
coefficients:
Blunt: 0.8
Slash: 0.8
Piercing: 0.85
Heat: 0.9
- type: ExplosionResistance
resistance: 0.9
- type: entity
parent: ClothingOuterBase

View file

@ -15,6 +15,8 @@
coefficients:
Slash: 0.95
Heat: 0.75
- type: Storage
capacity: 10
- type: entity
parent: ClothingOuterWinterCoat

View file

@ -19,7 +19,7 @@
event: !type:ToggleActionEvent
- type: ClothingSpeedModifier
walkModifier: 0.85
sprintModifier: 0.65
sprintModifier: 0.8
enabled: false
- type: entity

View file

@ -1,6 +1,7 @@
- type: entity
name: pointing arrow
id: pointingarrow
save: false
components:
- type: Tag
tags:

View file

@ -8,7 +8,7 @@
description: Some cultures find them terrifying, others crunchy on the teeth.
components:
- type: MovementSpeedModifier
baseWalkSpeed : 6
baseWalkSpeed : 3
baseSprintSpeed : 6
- type: Sprite
drawdepth: Mobs
@ -49,6 +49,15 @@
flavorKind: organic
- type: Bloodstream
bloodMaxVolume: 50
- type: ReplacementAccent
accent: mouse
- type: UnarmedCombat
range: 1.5
arcwidth: 0
arc: bite
damage:
types:
Piercing: 5
- type: entity
name: bee
@ -56,6 +65,11 @@
id: MobBee
description: Nice to have, but you can't build a civilization on a foundation of honey alone.
components:
- type: CombatMode
disarmAction:
enabled: false
autoPopulate: false
name: action-name-disarm
- type: MovementSpeedModifier
baseWalkSpeed : 7
baseSprintSpeed : 7
@ -105,6 +119,11 @@
id: MobAngryBee
description: How nice a bee. Oh no, it looks angry and wants my pizza.
components:
- type: CombatMode
disarmAction:
enabled: false
autoPopulate: false
name: action-name-disarm
- type: UnarmedCombat
range: 0.3
arcwidth: 0
@ -644,6 +663,7 @@
state: mouse-0
sprite: Mobs/Animals/mouse.rsi
- type: Clothing
size: 5
quickEquip: false
sprite: Mobs/Animals/mouse.rsi
HeldPrefix: 0

View file

@ -88,6 +88,30 @@
- type: Grammar
attributes:
gender: epicene
- type: Bloodstream
bloodReagent: DemonsBlood
bloodlossDamage:
types:
Bloodloss:
1
bloodlossHealDamage:
types:
Bloodloss:
-0.25
- type: Damageable
damageContainer: Biological
damageModifierSet: Infernal
- type: Temperature
heatDamageThreshold: 4000 #They come from hell, so...
coldDamageThreshold: 260
currentTemperature: 310.15
coldDamage:
types:
Cold : 1 #per second, scales with temperature & other constants
specificHeat: 42
heatDamage:
types:
Heat : 1 #per second, scales with temperature & other constants
- type: entity
name: Ian

View file

@ -68,6 +68,8 @@
types:
Bloodloss:
-0.25
- type: DrawableSolution
solution: bloodstream
- type: Damageable
damageContainer: Biological
- type: AtmosExposed
@ -182,6 +184,5 @@
heatDamage:
types:
Heat : 1 #per second, scales with temperature & other constants
- type: Bloodstream
bloodMaxVolume: 150

View file

@ -0,0 +1,73 @@
- type: entity
name: Remilia
parent: MobBat
id: MobBatRemilia
description: The chaplain's familiar. Likes fruit.
components:
- type: GhostTakeoverAvailable
makeSentient: true
name: Remilia, the chaplain's familiar
description: Obey your master. Eat fruit.
rules: You are an intelligent fruit bat. Follow the chaplain around. Don't cause any trouble unless the chaplain tells you to.
- type: Grammar
attributes:
gender: female
proper: true
- type: Tag
tags:
- Familiar
- DoorBumpOpener
- type: Access
tags:
- Chapel
- type: Mind
showExamineInfo: true
- type: Alerts
- type: entity
name: Cerberus
parent: MobCorgiNarsi
id: MobCorgiCerberus
description: This pupper is not wholesome.
components:
- type: GhostTakeoverAvailable
makeSentient: true
name: Cerberus, Evil Familiar
description: Obey your master. Spread chaos.
rules: You are an intelligent, demonic dog. Try to help the chaplain and any of his flock. As an antagonist, you're otherwise unrestrained.
- type: UnarmedCombat
range: 1.5
arcwidth: 0
arc: bite
damage:
types:
Piercing: 8
Slash: 7
- type: UtilityAI
behaviorSets:
- Idle
- type: AiFactionTag
factions:
- SimpleNeutral
- type: InteractionPopup
successChance: 0.5
interactSuccessString: petting-success-corrupted-corgi
interactFailureString: petting-failure-corrupted-corgi
- type: MobState
thresholds:
0: !type:NormalMobState {}
80: !type:CriticalMobState {}
160: !type:DeadMobState {}
- type: Grammar
attributes:
gender: male
proper: true
- type: Tag
tags:
- Familiar
- DoorBumpOpener
- type: Access
tags:
- Chapel
- type: Mind
showExamineInfo: true

View file

@ -76,3 +76,19 @@
enum.ChemicalPayloadFilledSlots.Left: payload-chemical-left
enum.ChemicalPayloadFilledSlots.Right: payload-chemical-right
enum.ChemicalPayloadFilledSlots.Both: payload-chemical-armed
- type: entity
name: flash payload
parent: BasePayload
id: FlashPayload
description: A single-use flash payload.
components:
- type: Sprite
sprite: Objects/Devices/payload.rsi
state: payload-flash-armed
- type: DeleteOnTrigger
- type: FlashOnTrigger
range: 6
- type: EmitSoundOnTrigger
sound:
path: "/Audio/Effects/flash_bang.ogg"

View file

@ -12,6 +12,15 @@
netsync: false
- type: Item
sprite: Objects/Misc/Lights/lights.rsi
- type: PointLight
netsync: false
enabled: false
radius: 3
energy: 2
- type: ToggleableLightVisuals
- type: Appearance
visuals:
- type: FlashLightVisualizer # todo move to light visuals component.
- type: entity
name: lamp
@ -29,13 +38,6 @@
map: [ "light" ]
- type: Item
sprite: Objects/Misc/Lights/lamp.rsi
- type: PointLight
enabled: false
radius: 3
energy: 2
- type: Appearance
visuals:
- type: FlashLightVisualizer
- type: entity
name: banana lamp
@ -50,13 +52,6 @@
shader: unshaded
visible: false
map: [ "light" ]
- type: PointLight
enabled: false
radius: 3
energy: 2
- type: Appearance
visuals:
- type: FlashLightVisualizer
- type: entity
name: desk lamp
@ -74,13 +69,6 @@
map: [ "light" ]
- type: Item
sprite: Objects/Misc/Lights/lampgreen.rsi
- type: PointLight
enabled: false
radius: 3
energy: 2
- type: Appearance
visuals:
- type: FlashLightVisualizer
- type: entity
name: floodlight
@ -131,9 +119,6 @@
max: 1
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: Appearance
visuals:
- type: FlashLightVisualizer
- type: entity
name: broken floodlight

View file

@ -16,6 +16,8 @@
damageOnUntrainedUse: ## What a non-chaplain takes when attempting to heal someone
groups:
Burn: 30
- type: Summonable
specialItem: MobBatRemilia
- type: ItemCooldown
- type: Sprite
netsync: false
@ -30,3 +32,34 @@
storageSoundCollection:
collection: storageRustle
- type: entity
parent: Bible
name: necronomicon
description: "There's a note: Klatuu, Verata, Nikto -- Don't forget it again!"
id: BibleNecronomicon
components:
- type: Bible
damage:
groups:
Caustic: 20 ## ~15 dps
damageOnFail:
groups:
Brute: 15
Airloss: 25
damageOnUntrainedUse:
groups:
Caustic: 50
failChance: 0
locPrefix: "necro"
healSound: "/Audio/Effects/lightburn.ogg"
cooldownTime: 1.3
- type: Summonable
specialItem: MobCorgiCerberus
- type: Sprite
netsync: false
sprite: Objects/Specific/Chapel/necronomicon.rsi
state: icon
- type: Item
size: 15
sprite: Objects/Specific/Chapel/necronomicon.rsi
prefix: inhand

View file

@ -35,3 +35,13 @@
- type: HealthAnalyzer
fake: true
disease: OwOnavirus
- type: entity
parent: HandheldHealthAnalyzer
id: HandheldHealthAnalyzerZombie
name: Zombie Infector
suffix: DEBUG
components:
- type: HealthAnalyzer
fake: true
disease: ZombieInfection

View file

@ -273,6 +273,8 @@
solutions:
food:
maxVol: 50
- type: Extractable
grindableSolutionName: food
- type: entity
name: pill canister

View file

@ -13,7 +13,7 @@
- type: ExpendableLight
spentName: spent flare
spentDesc: It looks like this flare has burnt out. What a bummer.
glowDuration: 165
glowDuration: 225
fadeOutDuration: 15
iconStateOn: flare_unlit
iconStateSpent: flare_spent
@ -47,6 +47,7 @@
color: "#FF8080"
radius: 1.0
energy: 9.0
netsync: false
- type: LightBehaviour
behaviours:
- !type:RandomizeBehaviour # immediately make it bright and flickery
@ -61,7 +62,7 @@
- !type:FadeBehaviour # have the radius start small and get larger as it starts to burn
id: turn_on
interpolate: Linear
maxDuration: 45.0 #duration of light
maxDuration: 45.0
startValue: 2.5
endValue: 10.0
property: Radius
@ -78,6 +79,6 @@
id: fade_out
interpolate: Linear
maxDuration: 15.0
startValue: 8.0
startValue: 10.0
endValue: 1.0
property: Radius

View file

@ -26,6 +26,7 @@
- type: Appearance
visuals:
- type: LanternVisualizer
- type: ToggleableLightVisuals
- type: PowerCellSlot
cellSlot:
startingItem: PowerCellSmallHigh

View file

@ -0,0 +1,22 @@
# Special entity used to fill zombie's hands when they turn undead
- type: entity
id: ZombieClaw
name: Zombie Claw
noSpawn: true
components:
- type: Sprite
sprite: Objects/Weapons/Melee/zombie_claw.rsi
state: icon
- type: Item
- type: Sharp
- type: ZombieTransfer
- type: Unremoveable
- type: MeleeWeapon
damage:
types:
Slash: 13
Piercing: 7
range: 1
arcwidth: 0
arc: claw

View file

@ -9,14 +9,18 @@
netsync: false
layers:
- state: icon
map: ["enum.AutolatheVisualLayers.Base"]
map: ["enum.LatheVisualLayers.IsRunning"]
- state: unlit
shader: unshaded
map: ["enum.AutolatheVisualLayers.BaseUnlit"]
- state: building
map: ["enum.AutolatheVisualLayers.AnimationLayer"]
map: ["enum.PowerDeviceVisualLayers.Powered"]
- state: inserting
map: ["enum.LatheVisualLayers.IsInserting"]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: Appearance
- type: LatheVisuals
idleState: icon
runningState: building
- type: Physics
bodyType: Static
- type: Fixtures
@ -60,16 +64,13 @@
- Wrench
- Crowbar
- Multitool
- AirlockPainter
- MiniHoe
- Shovel
- Spade
- CableStack
- HandheldGPSBasic
- HandheldHealthAnalyzer
- type: Appearance
visuals:
- type: AutolatheVisualizer
- type: WiresVisualizer
- type: ActivatableUI
key: enum.LatheUiKey.Key
- type: ActivatableUIRequiresPower
@ -93,14 +94,18 @@
netsync: false
layers:
- state: icon
map: ["enum.ProtolatheVisualLayers.Base"]
map: ["enum.LatheVisualLayers.IsRunning"]
- state: unlit
shader: unshaded
map: ["enum.ProtolatheVisualLayers.BaseUnlit"]
- state: building
map: ["enum.ProtolatheVisualLayers.AnimationLayer"]
map: ["enum.PowerDeviceVisualLayers.Powered"]
- state: inserting
map: ["enum.LatheVisualLayers.IsInserting"]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: Appearance
- type: LatheVisuals
idleState: icon
runningState: building
- type: Physics
bodyType: Static
- type: Fixtures
@ -187,6 +192,7 @@
- FlashlightLantern
- TimerTrigger
- ChemicalPayload
- FlashPayload
- type: ActivatableUI
key: enum.LatheUiKey.Key #Yes only having 1 of them here doesn't break anything
- type: ActivatableUIRequiresPower
@ -196,10 +202,6 @@
type: LatheBoundUserInterface
- key: enum.ResearchClientUiKey.Key
type: ResearchClientBoundUserInterface
- type: Appearance
visuals:
- type: ProtolatheVisualizer
- type: WiresVisualizer
- type: Transform
anchored: true
- type: Pullable
@ -216,12 +218,10 @@
sprite: Structures/Machines/circuit_imprinter.rsi
layers:
- state: icon
map: ["enum.ProtolatheVisualLayers.Base"]
map: ["enum.LatheVisualLayers.IsRunning"]
- state: unlit
shader: unshaded
map: ["enum.ProtolatheVisualLayers.BaseUnlit"]
- state: building
map: ["enum.ProtolatheVisualLayers.AnimationLayer"]
map: ["enum.PowerDeviceVisualLayers.Powered"]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: ProtolatheDatabase
@ -248,6 +248,8 @@
- StasisBedMachineCircuitboard
- type: Machine
board: CircuitImprinterMachineCircuitboard
- type: Lathe
producingSound: /Audio/Machines/circuitprinter.ogg
- type: entity
parent: Protolathe
@ -260,14 +262,17 @@
sprite: Structures/Machines/security_techfab.rsi
layers:
- state: icon
map: ["enum.ProtolatheVisualLayers.Base"]
map: ["enum.LatheVisualLayers.IsRunning"]
- state: unlit
shader: unshaded
map: ["enum.ProtolatheVisualLayers.BaseUnlit"]
- state: icon
map: ["enum.ProtolatheVisualLayers.AnimationLayer"]
map: ["enum.PowerDeviceVisualLayers.Powered"]
- state: inserting
map: ["enum.LatheVisualLayers.IsInserting"]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: LatheVisuals
idleState: icon
runningState: icon
- type: ProtolatheDatabase
protolatherecipes:
- Flash
@ -362,26 +367,21 @@
- ClothingUniformJumpskirtSec
- ClothingUniformJumpsuitWarden
- ClothingUniformJumpskirtWarden
- ClothingOuterWinterCap
- ClothingOuterWinterCap
- ClothingOuterWinterCE
- ClothingOuterWinterCMO
- ClothingOuterWinterHoP
- ClothingOuterWinterHoS
- ClothingOuterWinterQM
- ClothingOuterWinterRD
- type: Sprite
sprite: Structures/Machines/uniform_printer.rsi
netsync: false
layers:
- state: icon
map: ["enum.AutolatheVisualLayers.Base"]
- state: unlit
shader: unshaded
map: ["enum.AutolatheVisualLayers.BaseUnlit"]
- state: building
map: ["enum.AutolatheVisualLayers.AnimationLayer"]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
map: ["enum.LatheVisualLayers.IsRunning"]
- type: Machine
board: UniformPrinterMachineCircuitboard
- type: Lathe
producingSound: /Audio/Machines/uniformprinter.ogg

View file

@ -924,6 +924,7 @@
components:
- type: VendingMachine
pack: PietyVendInventory
emagPack: PietyVendEmagInventory
- type: Sprite
sprite: Structures/Machines/VendingMachines/chapdrobe.rsi
layers:

View file

@ -726,6 +726,14 @@
- type: Sprite
state: xenolab
- type: entity
parent: BaseSign
id: SignZomlab
name: zombie lab sign
components:
- type: Sprite
state: zomlab
- type: entity
parent: BaseSign
id: SignSecureMedRed

View file

@ -3,33 +3,39 @@
stack: Glass
name: glass
icon: Objects/Materials/Sheets/glass.rsi/glass.png
color: "#a8ccd7"
- type: material
id: ReinforcedGlass
stack: ReinforcedGlass
name: reinforced glass
icon: Objects/Materials/Sheets/glass.rsi/rglass.png
color: "#549bb0"
- type: material
id: PlasmaGlass
stack: PlasmaGlass
name: plasma glass
icon: Objects/Materials/Sheets/glass.rsi/pglass.png
color: "#b35989"
- type: material
id: ReinforcedPlasmaGlass
stack: ReinforcedPlasmaGlass
name: reinforced plasma glass
icon: Objects/Materials/Sheets/glass.rsi/rpglass.png
color: "#8c4069"
- type: material
id: TitaniumGlass
stack: TitaniumGlass
name: titanium glass
icon: Objects/Materials/Sheets/glass.rsi/titaniumglass.png
color: "#333135"
- type: material
id: PlastitaniumGlass
stack: PlastitaniumGlass
name: plastitanium glass
icon: Objects/Materials/Sheets/glass.rsi/plastitaniumglass.png
color: "#232127"

View file

@ -4,33 +4,39 @@
stack: Cloth
name: cloth
icon: /Textures/Objects/Materials/materials.rsi/cloth.png
color: "#e7e7de"
- type: material
id: Durathread
stack: Durathread
name: durathread
icon: /Textures/Objects/Materials/materials.rsi/durathread.png
color: "#8291a1"
- type: material
id: Plasma
stack: Plasma
name: plasma
icon: Objects/Materials/Sheets/other.rsi/plasma.png
color: "#7e009e"
- type: material
id: Phoron
stack: Phoron
name: phoron
icon: Objects/Materials/Sheets/other.rsi/phoron.png
color: "#FF3300"
- type: material
id: Plastic
stack: Plastic
name: plastic
icon: Objects/Materials/Sheets/other.rsi/plastic.png
color: "#d9d9d9"
- type: material
id: Wood
stack: WoodPlank
name: wood
icon: Objects/Materials/materials.rsi/wood.png
color: "#966F33"

View file

@ -9,18 +9,21 @@
stack: Adamantine
name: adamantine
icon: Objects/Materials/ingots.rsi/adamantine.png
color: "#7dc37f"
- type: material
id: Copper
stack: Copper
name: copper
icon: Objects/Materials/ingots.rsi/copper.png
color: "#B87333"
- type: material
id: Gold
stack: Gold
name: gold
icon: Objects/Materials/ingots.rsi/gold.png
color: "#FFD700"
- type: material
id: Hydrogen
@ -32,34 +35,39 @@
id: Iron
stack: Iron
name: iron
icon: Objects/Materials/ingots.rsi/iron.png
icon: Objects/Materials/ingots.rsi/iron.png #Do we even distinguish between steel and iron?
- type: material
id: Silver
stack: Silver
name: silver
icon: Objects/Materials/ingots.rsi/silver.png
color: "#C0C0C0"
- type: material
id: Plasteel
stack: Plasteel
name: plasteel
icon: Objects/Materials/Sheets/metal.rsi/plasteel.png
color: "#696969" #Okay, this is epic
- type: material
id: Brass
stack: Brass
name: brass
icon: Objects/Materials/Sheets/metal.rsi/brass.png
color: "#E1C16E"
- type: material
id: Titanium
stack: Titanium
name: titanium
icon: Objects/Materials/Sheets/metal.rsi/titanium.png
color: "#878681"
- type: material
id: Plastitanium
stack: Plastitanium
name: plastitanium
icon: Objects/Materials/Sheets/metal.rsi/plastitanium.png
color: "#4e4e4b"

View file

@ -319,6 +319,21 @@
Cellular: -1
Radiation: 1
- type: reagent
id: Romerol
name: romerol
group: Medicine
desc: A difficult to procure chemical used in the reversal of the zombification process. Tastes like death.
physicalDesc: acrid
color: "#7e916e"
metabolisms:
Medicine:
effects:
- !type:HealthChange
damage:
types:
Poison: 2
- type: reagent
id: PulpedBananaPeel
name: pulped banana peel

View file

@ -2,7 +2,7 @@
id: CapacitorStockPart
icon: Objects/Misc/stock_parts.rsi/capacitor.png
result: CapacitorStockPart
completetime: 250
completetime: 1
materials:
Steel: 50
Plastic: 50
@ -11,7 +11,7 @@
id: MatterBinStockPart
icon: Objects/Misc/stock_parts.rsi/matter_bin.png
result: MatterBinStockPart
completetime: 250
completetime: 1
materials:
Steel: 50
Plastic: 50
@ -20,7 +20,7 @@
id: MicroLaserStockPart
icon: Objects/Misc/stock_parts.rsi/micro_laser.png
result: MicroLaserStockPart
completetime: 250
completetime: 1
materials:
Steel: 50
Glass: 50
@ -30,7 +30,7 @@
id: MicroManipulatorStockPart
icon: Objects/Misc/stock_parts.rsi/micro_mani.png
result: MicroManipulatorStockPart
completetime: 250
completetime: 1
materials:
Steel: 50
Plastic: 50
@ -39,7 +39,7 @@
id: ScanningModuleStockPart
icon: Objects/Misc/stock_parts.rsi/scan_module_static.png
result: ScanningModuleStockPart
completetime: 250
completetime: 1
materials:
Steel: 50
Glass: 50

View file

@ -4,7 +4,7 @@
sprite: Objects/Tools/Hydroponics/hoe.rsi
state: icon
result: HydroponicsToolMiniHoe
completetime: 500
completetime: 2
materials:
Steel: 200
Plastic: 100
@ -15,7 +15,7 @@
sprite: Objects/Tools/Hydroponics/scythe.rsi
state: icon
result: HydroponicsToolScythe
completetime: 500
completetime: 2
materials:
Steel: 300
Plastic: 200
@ -26,7 +26,7 @@
sprite: Objects/Tools/Hydroponics/hatchet.rsi
state: icon
result: HydroponicsToolHatchet
completetime: 500
completetime: 2
materials:
Steel: 200
Plastic: 100
@ -37,7 +37,7 @@
sprite: Objects/Tools/Hydroponics/spade.rsi
state: icon
result: HydroponicsToolSpade
completetime: 500
completetime: 2
materials:
Steel: 200
Plastic: 100

View file

@ -4,7 +4,7 @@
sprite: Structures/conveyor.rsi
state: conveyor_loose
result: ConveyorBeltAssembly
completetime: 1000
completetime: 4
materials:
Steel: 500
Plastic: 50

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