upstream merge 2/11 (#2090)

* Fix multiplying colors of differing nullabilities (#32991)

* revert the temporary hack

* Make atmos alert computer colors private variables (#32992)

* Add flash reaction effect (#32377)

add flash reaction effect

* Automatic changelog update

* Fix loneop spawnrate by reverting it to not use the shuttle event system. (#32942)

Fix loneop spawnrate by reverting it to not use the custom shuttle event system.

* Automatic changelog update

* add atmosia to devmap (#32460)

change

* bowls now make drinking sounds (#32819)

* Automatic changelog update

* Add health analyzer unrevivability warning (#32636)

* Add health analyzer unrevivability warning

* Remove errornous comment

* Automatic changelog update

* Removed the name "Hujsak" (#32998)

removed hujsak

* fix pie throwing sound not playing (#33017)

* Automatic changelog update

* Fix TestSuicideByHeldItem and TestSuicideByHeldItemSpreadDamage (#33030)

* make ai speak robotically (#33025)

* Automatic changelog update

* Extends the minimum round time for meteor swarm events (#32876)

* adjusted minimum timers in meteorswarms.yml

* Updated timer minimum from 20 to 15 minutes

* Reduced minimum timer to 10 minutes as a result of other meteor changes

---------

Co-authored-by: august-sun <45527070+august.sun@users.noreply.github.com>

* Automatic changelog update

* add StartDelay bool to actions (#33026)

* add StartDelay bool to actions

* forgot summary

* Updated an incorrect sprite in the smite menu (#33043)

changed the synth sprite used in the icon for the instrumentify smite out for the more accurate supersynth sprite

* fix lava expeds (#33042)

Co-authored-by: deltanedas <@deltanedas:kde.org>

* Automatic changelog update

* Fix separated game screen bumping (#33046)

I don't really understand why RecordedSplitContainer exists but removing it looks identical and fixes the panel bumping occasionally.

* Automatic changelog update

* Fix: Make Plushie Damage Unexaminable (#33061)

Set hidden to true

* fix chameleon projector bot whitelist (#33055)

fix

* Various Vaugely Connected Sprite Updates™: Encryption Keys, Station Map, Brig Timer (#32786)

* various resprites (encryption keys + signal screens + station map)

* brig timer update

* fixes n shit

* Give proto-kinetic crushers, glaives, and daggers better inhands. Update the crusher and glaive icons. (#32212)

* inhands

* better inhands

* indent

* Automatic changelog update

* Make the security belt contain more useful items by default (#32291)

* replace tear gas and flashbang with holobarrier and sec radio

* holobarrier-belt-fix

* revert changes of 32291

* Automatic changelog update

* Add 3 bottle boxes to nanomed plus (#33018)

three bottle boxes in nanomed plus

* Automatic changelog update

* Nukie med bundle now costs 24 tc and contains a unique defibrillator (#32720)

* a-few-injectors

* comment

* defib-ops-when

* Automatic changelog update

* Pill Bottles can only store pills now (#33074)

* no longer absurd

* Update Resources/Prototypes/Entities/Objects/Specific/chemistry.yml

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Automatic changelog update

* Add a spare bible to PietyVend (#32363)

Update chapel.yml

* Automatic changelog update

* [#28722 fix] Add notification for dependent wearables being dropped (#33078)

* add notification for dependent wearables being dropped

* fix dropped item popup redundancy
- did a check to see if any item was dropped, instead of making a notification for each item being dropped.

* change popup to client-only variant

* fix redundant messages, add plural locale string

* fix conventions, fix locale input to be more intuitive

---------

Co-authored-by: Justin <justinbrick1@gmail.com>

* Automatic changelog update

* More pda space (#32601)

* Rebalance the max programs that a PDA can hold

* Give Caps PDA more programs too.

* Make the max programs a static 8

* I forgor sec and med

* CaseCase

* Empty commit to re-run checks

* The final change, I hope.

* Automatic changelog update

* Fixed spelling mistake in water blaster description. (#33087)

Fixed minor spelling mistake

* [#20285 fix] Carp Plush and Rehydratables can now be put into mop bucket (#33079)

* Make shark plush janitor-bucketable

* fix bucketed grey shark texture

* Make sprites less shiny and adapt copyright notice

* Made shark way way less shiny

* Allow carp plush and rehydratables in mop bucket.

* Remove old mop bucket shark sprites

* Fix post-merge bugs

* Fix errors

* Move ReactiveContainer stuff to shared

That should mean it is now predicted.

* Custom eject verb for the mop bucket

* Fixes OnSolutionChange, removes pop-up as there already is one.

* .ftl is not necessary as the custom pop-up was removed

* Review fixes

* Update Content.Shared/Chemistry/Components/ReactiveContainerComponent.cs

* Update Content.Shared/Chemistry/EntitySystems/ReactiveContainerSystem.cs

---------

Co-authored-by: Psychpsyo <psychpsyo@gmail.com>
Co-authored-by: Psychpsyo <60073468+Psychpsyo@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Automatic changelog update

* remove now duplicated nyano PlushieCarp tag

* Fixes tailthump breaking positional audio by making it mono (#33092)

* Automatic changelog update

* ExaminableDamage now puts its message at the bottom and in color (#32820)

* the examineableDamage component now puts its messages at the bottom, and in color

* god help us if something is priority -100 :godo:

* Automatic changelog update

* Lower in-round votekick requirements (#32953)

Initial commit

* Allow votekicks to be initiated in the lobby (#32528)

Initial commit

* Automatic changelog update

* Fixes bolt lights of previously unpowered bolted doors (#33063)

fix

* Automatic changelog update

* Muffins (#29318)

* Update meta.json

* Add files via upload

* Update misc.yml

* Update meal_recipes.yml

* Update meta.json

* Add files via upload

* Update plate.yml

* Update food_baked_single.yml

* Update dinnerware.yml

* Update cooking.yml

* Update misc.yml

* Add files via upload

* Delete Resources/Textures/Objects/Consumable/Food/Baked/misc.rsi/muffin-cherry.png

* Add files via upload

* Update meta.json

* Update misc.yml

* Update meal_recipes.yml

* Update meta.json

* Fix meta.json

* Fix meta.json again

* Update misc.yml

* Update misc.yml

* Update misc.yml

* Update misc.yml

* Update meta.json

* Update meta.json

* Update misc.yml

* Update meal_recipes.yml

* Update Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/misc.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update dinnerware.yml

* Delete cherry

* Add files via upload

* Delete banana

* Add banana

* Delete chocolate

* Add chocolate

* lathe recipe fix

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Automatic changelog update

* Borgs can no longer see mindshield + AI can no longer toggle off seeing job icons (#33069)

* :(

* Removed the sprite + updated RSI

* Automatic changelog update

* Add CanLoad for biomes (#33050)

CPUJob to come later.

* Remove CargoPallet component from the cargo pallet (#33022)

* Change cargo shuttle pallets to catwalks.

* Remove CargoPallet component from the cargo pallet.

* Undo cargo shuttle changes.

* Automatic changelog update

* Minor antagonist guidebook changes (#32824)

* took a two month nap. accidentally pushed too many buttons. let's try this again. added thieves to antagonists.xml

* even after that nap, i don't feel well-rested at all.

* please don't kill me for using webedit

* capitalization, typo

* Apply suggestions from code review (more period moving)

Thanks Evan, very cool

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* guess you could say im not pro-proper noun

* typo

* Update Resources/ServerInfo/Guidebook/Antagonist/Nuclear Operatives.xml

* ok

Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>

* Give Nukies a Hand Labeler (#33053)

* Add hand-labeler to nukie planet

* Rearrange nukie chem table

* Fix `ItemSlotSystem` popup Logic (#28856)

* move popup call out of `CanInsert` into `OnInteractUsing`

* im stupid and `reason` is completely unnecessary

Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>

* return early when `itemSlots.Slots.Count == 0`

* tweak logic for triggering popups

* change popup logic again

* Consolidate whitelist check

* Get any popup message not just last failed slot

* Apply suggestions from code review

Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>

* yoink

Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>

---------

Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>

* Add cvars to votekick to customize requirements for the initiator. (#32490)

* Automatic changelog update

* Add on-call functionality for adminning (#30443)

* Add on-call functionality for adminning

The first time an ahelp gets SOS it gets relayed to the specified channel with the specified ping. Every time after that it doesn't until it gets a non-SOS response received.

* Remove redundant name

Pretty sure this already gets chucked on the name of the msg itself I think it just didn't show in screenshot because they were subsequent.

* Update Content.Server/Administration/Systems/BwoinkSystem.cs

Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>

---------

Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>
Co-authored-by: deathride58 <deathride58@users.noreply.github.com>

* Automatic changelog update

* Pills are explosion resistant (partially reverts #15851) (#32458)

* idk how to revert a pr so I just deleted some lines

* pill destructible with explosion resistance

* comment for explosion resist

* "and" to "but"

---------

Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>

* Automatic changelog update

* Hasten handcraft gauze recipe & decrease techfab gauze cost (#32744)

* med lathe gauze price reduction

* gauze craft doafter time

* 3 second doafter craft

* Automatic changelog update

* Service workers antagonist fix. (#31359)

* add

* Revert "add"

This reverts commit 25da34b0fead5812fe5800c9bf5dd7b10ef48d7d.

* antagonism allowed™️

* Automatic changelog update

* Adds a new AME sound effect! (#33097)

* Changes the AME sound effect to not be the default MetalThud.

* Was told on discord to make a minor change to autorerun the tests due to the Build & Test Debug failing!

* Attribution and licensing, as requsted by deathride58

* Fixes the high-pitched squeak audible to some people!

* Audio file tweaked by SlamBamActionMan to eliminate a weird squeak they were still able to hear. Thanks!

* Automatic changelog update

* Allow for the ai's laws to be changed from its core and eye (#32461)

* Allow for the ai's laws to be changed from its core and eye

* Address reviews

* Automatic changelog update

* clean up tools lathe recipes (#31521)

* clean up tools lathe recipes

* add medical and cooking tools

* add result

* add result to others

* review

* engine

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>

* Automatic changelog update

* Intercoms and Radios both pick up proximate speech (#32737)

* Deduping of recent messages should consider the channel it's being sent to

* rerun actions

* Automatic changelog update

* Adds headphones to loadouts (#33067)

added headphones to trinkets

* Automatic changelog update

* Cardboard Box Capacity 4 -> 5 (#32743)

* capacity upgrade

* comment update

* remove our duplicate pill whitelist

* fix

* remove broken crew monitor from dev map, how did it even get there

---------

Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>
Co-authored-by: deltanedas <@deltanedas:kde.org>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
Co-authored-by: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com>
Co-authored-by: Ilya246 <57039557+Ilya246@users.noreply.github.com>
Co-authored-by: Moomoobeef <62638182+Moomoobeef@users.noreply.github.com>
Co-authored-by: Saphire Lattice <lattice@saphi.re>
Co-authored-by: FluffMe <1780586+FluffMe@users.noreply.github.com>
Co-authored-by: Theodore Lukin <66275205+pheenty@users.noreply.github.com>
Co-authored-by: August Sun <45527070+august-sun@users.noreply.github.com>
Co-authored-by: august-sun <45527070+august.sun@users.noreply.github.com>
Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: Preston Smith <92108534+thetolbean@users.noreply.github.com>
Co-authored-by: Milon <plmilonpl@gmail.com>
Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>
Co-authored-by: Alzore <140123969+Blackern5000@users.noreply.github.com>
Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Co-authored-by: Jarmer123 <148848017+Jarmer123@users.noreply.github.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Co-authored-by: Justin <justinbrick1@gmail.com>
Co-authored-by: SpaceLizard <the.justice.league.of.canada@gmail.com>
Co-authored-by: Psychpsyo <psychpsyo@gmail.com>
Co-authored-by: Psychpsyo <60073468+Psychpsyo@users.noreply.github.com>
Co-authored-by: deathride58 <deathride58@users.noreply.github.com>
Co-authored-by: PopGamer46 <yt1popgamer@gmail.com>
Co-authored-by: RumiTiger <154005209+RumiTiger@users.noreply.github.com>
Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: Minemoder5000 <minemoder50000@gmail.com>
Co-authored-by: UBlueberry <161545003+UBlueberry@users.noreply.github.com>
Co-authored-by: Brandon Li <48413902+aspiringLich@users.noreply.github.com>
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Co-authored-by: Vasilis <vasilis@pikachu.systems>
Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>
Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com>
Co-authored-by: Ubaser <134914314+UbaserB@users.noreply.github.com>
Co-authored-by: AftrLite <61218133+AftrLite@users.noreply.github.com>
Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
Co-authored-by: Centronias <me@centronias.com>
Co-authored-by: joshepvodka <86210200+joshepvodka@users.noreply.github.com>
Co-authored-by: Scribbles0 <91828755+Scribbles0@users.noreply.github.com>
This commit is contained in:
deltanedas 2024-11-07 20:09:25 +00:00 committed by GitHub
parent 6508f8b6de
commit 2620eb48a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
186 changed files with 5042 additions and 1578 deletions

View File

@ -43,6 +43,18 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
private const float SilencingDuration = 2.5f;
// Colors
private Color _wallColor = new Color(64, 64, 64);
private Color _tileColor = new Color(28, 28, 28);
private Color _monitorBlipColor = Color.Cyan;
private Color _untrackedEntColor = Color.DimGray;
private Color _regionBaseColor = new Color(154, 154, 154);
private Color _inactiveColor = StyleNano.DisabledFore;
private Color _statusTextColor = StyleNano.GoodGreenFore;
private Color _goodColor = Color.LimeGreen;
private Color _warningColor = new Color(255, 182, 72);
private Color _dangerColor = new Color(255, 67, 67);
public AtmosAlertsComputerWindow(AtmosAlertsComputerBoundUserInterface userInterface, EntityUid? owner)
{
RobustXamlLoader.Load(this);
@ -55,8 +67,8 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
NavMap.Owner = _owner;
// Set nav map colors
NavMap.WallColor = new Color(64, 64, 64);
NavMap.TileColor = Color.DimGray * NavMap.WallColor;
NavMap.WallColor = _wallColor;
NavMap.TileColor = _tileColor;
// Set nav map grid uid
var stationName = Loc.GetString("atmos-alerts-window-unknown-location");
@ -214,7 +226,7 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
if (consoleCoords != null && consoleUid != null)
{
var texture = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")));
var blip = new NavMapBlip(consoleCoords.Value, texture, Color.Cyan, true, false);
var blip = new NavMapBlip(consoleCoords.Value, texture, _monitorBlipColor, true, false);
NavMap.TrackedEntities[consoleUid.Value] = blip;
}
@ -263,7 +275,7 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
VerticalAlignment = VAlignment.Center,
};
label.SetMarkup(Loc.GetString("atmos-alerts-window-no-active-alerts", ("color", StyleNano.GoodGreenFore.ToHexNoAlpha())));
label.SetMarkup(Loc.GetString("atmos-alerts-window-no-active-alerts", ("color", _statusTextColor.ToHexNoAlpha())));
AlertsTable.AddChild(label);
}
@ -292,7 +304,7 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
if (!TryGetSensorRegionColor(regionOwner, alarmState, out var regionColor))
continue;
regionOverlay.Color = regionColor.Value;
regionOverlay.Color = regionColor;
var priority = (_trackedEntity == regionOwner) ? 999 : (int)alarmState;
prioritizedRegionOverlays.Add(regionOverlay, priority);
@ -323,7 +335,7 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
var coords = _entManager.GetCoordinates(metaData.NetCoordinates);
if (_trackedEntity != null && _trackedEntity != metaData.NetEntity)
color *= Color.DimGray;
color *= _untrackedEntColor;
var selectable = true;
var blip = new NavMapBlip(coords, _spriteSystem.Frame0(texture), color, _trackedEntity == metaData.NetEntity, selectable);
@ -331,23 +343,20 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
NavMap.TrackedEntities[metaData.NetEntity] = blip;
}
private bool TryGetSensorRegionColor(NetEntity regionOwner, AtmosAlarmType alarmState, [NotNullWhen(true)] out Color? color)
private bool TryGetSensorRegionColor(NetEntity regionOwner, AtmosAlarmType alarmState, out Color color)
{
color = null;
color = Color.White;
var blip = GetBlipTexture(alarmState);
if (blip == null)
return false;
// DeltaV: fix client until upstream does
// Color the region based on alarm state and entity tracking
var output = blip.Value.Item2 * new Color(154, 154, 154);
color = blip.Value.Item2 * _regionBaseColor;
if (_trackedEntity != null && _trackedEntity != regionOwner)
output *= Color.DimGray;
color = output;
color *= _untrackedEntColor;
return true;
}
@ -588,13 +597,13 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
switch (alarmState)
{
case AtmosAlarmType.Invalid:
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")), StyleNano.DisabledFore); break;
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")), _inactiveColor); break;
case AtmosAlarmType.Normal:
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")), Color.LimeGreen); break;
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")), _goodColor); break;
case AtmosAlarmType.Warning:
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_triangle.png")), new Color(255, 182, 72)); break;
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_triangle.png")), _warningColor); break;
case AtmosAlarmType.Danger:
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_square.png")), new Color(255, 67, 67)); break;
output = (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_square.png")), _dangerColor); break;
}
return output;

View File

@ -47,8 +47,7 @@
<PanelContainer Name="AlertsDivider" Visible="False" StyleClasses="LowDivider" />
<BoxContainer Name="AlertsContainer" Visible="False" Margin="0 5" Orientation="Horizontal"
HorizontalExpand="True" HorizontalAlignment="Center">
<BoxContainer Name="AlertsContainer" Visible="False" Margin="0 5" Orientation="Vertical" HorizontalAlignment="Center">
</BoxContainer>

View File

@ -110,18 +110,29 @@ namespace Content.Client.HealthAnalyzer.UI
// Alerts
AlertsDivider.Visible = msg.Bleeding == true;
AlertsContainer.Visible = msg.Bleeding == true;
var showAlerts = msg.Unrevivable == true || msg.Bleeding == true;
AlertsDivider.Visible = showAlerts;
AlertsContainer.Visible = showAlerts;
if (showAlerts)
AlertsContainer.DisposeAllChildren();
if (msg.Unrevivable == true)
AlertsContainer.AddChild(new RichTextLabel
{
Text = Loc.GetString("health-analyzer-window-entity-unrevivable-text"),
Margin = new Thickness(0, 4),
MaxWidth = 300
});
if (msg.Bleeding == true)
{
AlertsContainer.DisposeAllChildren();
AlertsContainer.AddChild(new Label
AlertsContainer.AddChild(new RichTextLabel
{
Text = Loc.GetString("health-analyzer-window-entity-bleeding-text"),
FontColorOverride = Color.Red,
Margin = new Thickness(0, 4),
MaxWidth = 300
});
}
// Damage Groups

View File

@ -8,7 +8,7 @@
VerticalExpand="False"
VerticalAlignment="Bottom"
HorizontalAlignment="Center">
<controls:RecordedSplitContainer Name="ScreenContainer" HorizontalExpand="True"
<SplitContainer Name="ScreenContainer" HorizontalExpand="True"
VerticalExpand="True" SplitWidth="0"
StretchDirection="TopLeft">
<BoxContainer Orientation="Vertical" VerticalExpand="True" Name="SpawnContainer" MinWidth="200" SetWidth="600">
@ -82,5 +82,5 @@
</BoxContainer>
</PanelContainer>
</LayoutContainer>
</controls:RecordedSplitContainer>
</SplitContainer>
</mapping:MappingScreen>

View File

@ -197,7 +197,6 @@ public sealed partial class MappingScreen : InGameScreen
public override void SetChatSize(Vector2 size)
{
ScreenContainer.DesiredSplitCenter = size.X;
ScreenContainer.ResizeMode = SplitContainer.SplitResizeMode.RespectChildrenMinSize;
}

View File

@ -1,29 +0,0 @@
using System.Numerics;
using Robust.Client.UserInterface.Controls;
namespace Content.Client.UserInterface.Controls;
/// <summary>
/// A split container that performs an action when the split resizing is finished.
/// </summary>
public sealed class RecordedSplitContainer : SplitContainer
{
public double? DesiredSplitCenter;
protected override Vector2 ArrangeOverride(Vector2 finalSize)
{
if (ResizeMode == SplitResizeMode.RespectChildrenMinSize
&& DesiredSplitCenter != null
&& !finalSize.Equals(Vector2.Zero))
{
SplitFraction = (float) DesiredSplitCenter.Value;
if (!Size.Equals(Vector2.Zero))
{
DesiredSplitCenter = null;
}
}
return base.ArrangeOverride(finalSize);
}
}

View File

@ -14,7 +14,7 @@
VerticalExpand="False"
VerticalAlignment="Bottom"
HorizontalAlignment="Center">
<controls:RecordedSplitContainer Name="ScreenContainer" HorizontalExpand="True" VerticalExpand="True" SplitWidth="0" StretchDirection="TopLeft">
<SplitContainer Name="ScreenContainer" HorizontalExpand="True" VerticalExpand="True" SplitWidth="0" StretchDirection="TopLeft">
<LayoutContainer Name="ViewportContainer" HorizontalExpand="True" VerticalExpand="True">
<controls:MainViewport Name="MainViewport"/>
<widgets:GhostGui Name="Ghost" Access="Protected" />
@ -26,7 +26,7 @@
</BoxContainer>
<alerts:AlertsUI Name="Alerts" Access="Protected" />
</LayoutContainer>
<PanelContainer HorizontalExpand="True" MinWidth="300">
<PanelContainer Name="SeparatedChatPanel" MinWidth="300">
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#2B2C3B" />
</PanelContainer.PanelOverride>
@ -36,5 +36,5 @@
<chat:ChatBox VerticalExpand="True" HorizontalExpand="True" Name="Chat" Access="Protected" MinSize="0 0"/>
</BoxContainer>
</PanelContainer>
</controls:RecordedSplitContainer>
</SplitContainer>
</screens:SeparatedChatGameScreen>

View File

@ -40,7 +40,6 @@ public sealed partial class SeparatedChatGameScreen : InGameScreen
public override void SetChatSize(Vector2 size)
{
ScreenContainer.DesiredSplitCenter = size.X;
ScreenContainer.ResizeMode = SplitContainer.SplitResizeMode.RespectChildrenMinSize;
}
}

View File

@ -1,5 +1,6 @@
using System.Linq;
using System.Numerics;
using Content.Client.Gameplay;
using Content.Client.Stylesheets;
using Content.Shared.Administration;
using Content.Shared.CCVar;
@ -8,6 +9,7 @@ using Content.Shared.Voting;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.State;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
@ -28,6 +30,7 @@ namespace Content.Client.Voting.UI
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEntityNetworkManager _entNetManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IStateManager _state = default!;
private VotingSystem _votingSystem;
@ -62,7 +65,7 @@ namespace Content.Client.Voting.UI
Stylesheet = IoCManager.Resolve<IStylesheetManager>().SheetSpace;
CloseButton.OnPressed += _ => Close();
VoteNotTrustedLabel.Text = Loc.GetString("ui-vote-trusted-users-notice", ("timeReq", _cfg.GetCVar(CCVars.VotekickEligibleVoterDeathtime) / 60));
VoteNotTrustedLabel.Text = Loc.GetString("ui-vote-trusted-users-notice", ("timeReq", _cfg.GetCVar(CCVars.VotekickEligibleVoterDeathtime)));
foreach (StandardVoteType voteType in Enum.GetValues<StandardVoteType>())
{
@ -70,6 +73,7 @@ namespace Content.Client.Voting.UI
VoteTypeButton.AddItem(Loc.GetString(option.Name), (int)voteType);
}
_state.OnStateChanged += OnStateChanged;
VoteTypeButton.OnItemSelected += VoteTypeSelected;
CreateButton.OnPressed += CreatePressed;
FollowButton.OnPressed += FollowSelected;
@ -101,6 +105,14 @@ namespace Content.Client.Voting.UI
UpdateVoteTimeout();
}
private void OnStateChanged(StateChangedEventArgs obj)
{
if (obj.NewState is not GameplayState)
return;
Close();
}
private void CanCallVoteChanged(bool obj)
{
if (!obj)

View File

@ -19,11 +19,6 @@ public sealed class VotingSystem : EntitySystem
private void OnVotePlayerListResponseEvent(VotePlayerListResponseEvent msg)
{
if (!_ghostSystem.IsGhost)
{
return;
}
VotePlayerListResponse?.Invoke(msg);
}

View File

@ -168,7 +168,7 @@ public sealed class SuicideCommandTests
await pair.CleanReturnAsync();
}
/// <summary>
/// <summary>
/// Run the suicide command in the console
/// Should only ghost the player but not kill them
/// </summary>
@ -241,6 +241,7 @@ public sealed class SuicideCommandTests
var mindSystem = entManager.System<SharedMindSystem>();
var mobStateSystem = entManager.System<MobStateSystem>();
var transformSystem = entManager.System<TransformSystem>();
var damageableSystem = entManager.System<DamageableSystem>();
// We need to know the player and whether they can be hurt, killed, and whether they have a mind
var player = playerMan.Sessions.First().AttachedEntity!.Value;
@ -276,6 +277,8 @@ public sealed class SuicideCommandTests
// and that all the damage is concentrated in the Slash category
await server.WaitAssertion(() =>
{
// Heal all damage first (possible low pressure damage taken)
damageableSystem.SetAllDamage(player, damageableComp, 0);
consoleHost.GetSessionShell(playerMan.Sessions.First()).ExecuteCommand("suicide");
var lethalDamageThreshold = mobThresholdsComp.Thresholds.Keys.Last();
@ -313,6 +316,7 @@ public sealed class SuicideCommandTests
var mindSystem = entManager.System<SharedMindSystem>();
var mobStateSystem = entManager.System<MobStateSystem>();
var transformSystem = entManager.System<TransformSystem>();
var damageableSystem = entManager.System<DamageableSystem>();
// We need to know the player and whether they can be hurt, killed, and whether they have a mind
var player = playerMan.Sessions.First().AttachedEntity!.Value;
@ -348,6 +352,8 @@ public sealed class SuicideCommandTests
// and that slash damage is split in half
await server.WaitAssertion(() =>
{
// Heal all damage first (possible low pressure damage taken)
damageableSystem.SetAllDamage(player, damageableComp, 0);
consoleHost.GetSessionShell(playerMan.Sessions.First()).ExecuteCommand("suicide");
var lethalDamageThreshold = mobThresholdsComp.Thresholds.Keys.Last();

View File

@ -654,7 +654,7 @@ public sealed partial class AdminVerbSystem
{
Text = "admin-smite-become-mouse-name",
Category = VerbCategory.Smite,
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/Instruments/h_synthesizer.rsi"), "icon"),
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/Instruments/h_synthesizer.rsi"), "supersynth"),
Act = () =>
{
_polymorphSystem.PolymorphEntity(args.Target, "AdminInstrumentSmite");

View File

@ -35,8 +35,10 @@ using Robust.Shared.Toolshed;
using Robust.Shared.Utility;
using System.Linq;
using Content.Server.Silicons.Laws;
using Content.Shared.Movement.Components;
using Content.Shared.Silicons.Laws.Components;
using Robust.Server.Player;
using Content.Shared.Silicons.StationAi;
using Robust.Shared.Physics.Components;
using static Content.Shared.Configurable.ConfigurationComponent;
@ -345,7 +347,30 @@ namespace Content.Server.Administration.Systems
Impact = LogImpact.Low
});
if (TryComp<SiliconLawBoundComponent>(args.Target, out var lawBoundComponent))
// This logic is needed to be able to modify the AI's laws through its core and eye.
EntityUid? target = null;
SiliconLawBoundComponent? lawBoundComponent = null;
if (TryComp(args.Target, out lawBoundComponent))
{
target = args.Target;
}
// When inspecting the core we can find the entity with its laws by looking at the AiHolderComponent.
else if (TryComp<StationAiHolderComponent>(args.Target, out var holder) && holder.Slot.Item != null
&& TryComp(holder.Slot.Item, out lawBoundComponent))
{
target = holder.Slot.Item.Value;
// For the eye we can find the entity with its laws as the source of the movement relay since the eye
// is just a proxy for it to move around and look around the station.
}
else if (TryComp<MovementRelayTargetComponent>(args.Target, out var relay)
&& TryComp(relay.Source, out lawBoundComponent))
{
target = relay.Source;
}
if (lawBoundComponent != null && target != null)
{
args.Verbs.Add(new Verb()
{
@ -359,7 +384,7 @@ namespace Content.Server.Administration.Systems
return;
}
_euiManager.OpenEui(ui, session);
ui.UpdateLaws(lawBoundComponent, args.Target);
ui.UpdateLaws(lawBoundComponent, target.Value);
},
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/Actions/actions_borg.rsi"), "state-laws"),
});

View File

@ -47,20 +47,23 @@ namespace Content.Server.Administration.Systems
[GeneratedRegex(@"^https://discord\.com/api/webhooks/(\d+)/((?!.*/).*)$")]
private static partial Regex DiscordRegex();
private ISawmill _sawmill = default!;
private readonly HttpClient _httpClient = new();
private string _webhookUrl = string.Empty;
private WebhookData? _webhookData;
private string _onCallUrl = string.Empty;
private WebhookData? _onCallData;
private ISawmill _sawmill = default!;
private readonly HttpClient _httpClient = new();
private string _footerIconUrl = string.Empty;
private string _avatarUrl = string.Empty;
private string _serverName = string.Empty;
private readonly
Dictionary<NetUserId, (string? id, string username, string description, string? characterName, GameRunLevel
lastRunLevel)> _relayMessages = new();
private readonly Dictionary<NetUserId, DiscordRelayInteraction> _relayMessages = new();
private Dictionary<NetUserId, string> _oldMessageIds = new();
private readonly Dictionary<NetUserId, Queue<string>> _messageQueues = new();
private readonly Dictionary<NetUserId, Queue<DiscordRelayedData>> _messageQueues = new();
private readonly HashSet<NetUserId> _processingChannels = new();
private readonly Dictionary<NetUserId, (TimeSpan Timestamp, bool Typing)> _typingUpdateTimestamps = new();
private string _overrideClientName = string.Empty;
@ -82,12 +85,16 @@ namespace Content.Server.Administration.Systems
public override void Initialize()
{
base.Initialize();
Subs.CVar(_config, CCVars.DiscordOnCallWebhook, OnCallChanged, true);
Subs.CVar(_config, CCVars.DiscordAHelpWebhook, OnWebhookChanged, true);
Subs.CVar(_config, CCVars.DiscordAHelpFooterIcon, OnFooterIconChanged, true);
Subs.CVar(_config, CCVars.DiscordAHelpAvatar, OnAvatarChanged, true);
Subs.CVar(_config, CVars.GameHostName, OnServerNameChanged, true);
Subs.CVar(_config, CCVars.AdminAhelpOverrideClientName, OnOverrideChanged, true);
_sawmill = IoCManager.Resolve<ILogManager>().GetSawmill("AHELP");
var defaultParams = new AHelpMessageParams(
string.Empty,
string.Empty,
@ -96,7 +103,7 @@ namespace Content.Server.Administration.Systems
_gameTicker.RunLevel,
playedSound: false
);
_maxAdditionalChars = GenerateAHelpMessage(defaultParams).Length;
_maxAdditionalChars = GenerateAHelpMessage(defaultParams).Message.Length;
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameRunLevelChanged);
@ -111,6 +118,33 @@ namespace Content.Server.Administration.Systems
);
}
private async void OnCallChanged(string url)
{
_onCallUrl = url;
if (url == string.Empty)
return;
var match = DiscordRegex().Match(url);
if (!match.Success)
{
Log.Error("On call URL does not appear to be valid.");
return;
}
if (match.Groups.Count <= 2)
{
Log.Error("Could not get webhook ID or token for on call URL.");
return;
}
var webhookId = match.Groups[1].Value;
var webhookToken = match.Groups[2].Value;
_onCallData = await GetWebhookData(webhookId, webhookToken);
}
private void PlayerRateLimitedAction(ICommonSession obj)
{
RaiseNetworkEvent(
@ -259,13 +293,13 @@ namespace Content.Server.Administration.Systems
// Store the Discord message IDs of the previous round
_oldMessageIds = new Dictionary<NetUserId, string>();
foreach (var message in _relayMessages)
foreach (var (user, interaction) in _relayMessages)
{
var id = message.Value.id;
var id = interaction.Id;
if (id == null)
return;
_oldMessageIds[message.Key] = id;
_oldMessageIds[user] = id;
}
_relayMessages.Clear();
@ -330,10 +364,10 @@ namespace Content.Server.Administration.Systems
var webhookToken = match.Groups[2].Value;
// Fire and forget
await SetWebhookData(webhookId, webhookToken);
_webhookData = await GetWebhookData(webhookId, webhookToken);
}
private async Task SetWebhookData(string id, string token)
private async Task<WebhookData?> GetWebhookData(string id, string token)
{
var response = await _httpClient.GetAsync($"https://discord.com/api/v10/webhooks/{id}/{token}");
@ -342,10 +376,10 @@ namespace Content.Server.Administration.Systems
{
_sawmill.Log(LogLevel.Error,
$"Discord returned bad status code when trying to get webhook data (perhaps the webhook URL is invalid?): {response.StatusCode}\nResponse: {content}");
return;
return null;
}
_webhookData = JsonSerializer.Deserialize<WebhookData>(content);
return JsonSerializer.Deserialize<WebhookData>(content);
}
private void OnFooterIconChanged(string url)
@ -358,14 +392,14 @@ namespace Content.Server.Administration.Systems
_avatarUrl = url;
}
private async void ProcessQueue(NetUserId userId, Queue<string> messages)
private async void ProcessQueue(NetUserId userId, Queue<DiscordRelayedData> messages)
{
// Whether an embed already exists for this player
var exists = _relayMessages.TryGetValue(userId, out var existingEmbed);
// Whether the message will become too long after adding these new messages
var tooLong = exists && messages.Sum(msg => Math.Min(msg.Length, MessageLengthCap) + "\n".Length)
+ existingEmbed.description.Length > DescriptionMax;
var tooLong = exists && messages.Sum(msg => Math.Min(msg.Message.Length, MessageLengthCap) + "\n".Length)
+ existingEmbed?.Description.Length > DescriptionMax;
// If there is no existing embed, or it is getting too long, we create a new embed
if (!exists || tooLong)
@ -385,10 +419,10 @@ namespace Content.Server.Administration.Systems
// If we have all the data required, we can link to the embed of the previous round or embed that was too long
if (_webhookData is { GuildId: { } guildId, ChannelId: { } channelId })
{
if (tooLong && existingEmbed.id != null)
if (tooLong && existingEmbed?.Id != null)
{
linkToPrevious =
$"**[Go to previous embed of this round](https://discord.com/channels/{guildId}/{channelId}/{existingEmbed.id})**\n";
$"**[Go to previous embed of this round](https://discord.com/channels/{guildId}/{channelId}/{existingEmbed.Id})**\n";
}
else if (_oldMessageIds.TryGetValue(userId, out var id) && !string.IsNullOrEmpty(id))
{
@ -398,13 +432,22 @@ namespace Content.Server.Administration.Systems
}
var characterName = _minds.GetCharacterName(userId);
existingEmbed = (null, lookup.Username, linkToPrevious, characterName, _gameTicker.RunLevel);
existingEmbed = new DiscordRelayInteraction()
{
Id = null,
CharacterName = characterName,
Description = linkToPrevious,
Username = lookup.Username,
LastRunLevel = _gameTicker.RunLevel,
};
_relayMessages[userId] = existingEmbed;
}
// Previous message was in another RunLevel, so show that in the embed
if (existingEmbed.lastRunLevel != _gameTicker.RunLevel)
if (existingEmbed!.LastRunLevel != _gameTicker.RunLevel)
{
existingEmbed.description += _gameTicker.RunLevel switch
existingEmbed.Description += _gameTicker.RunLevel switch
{
GameRunLevel.PreRoundLobby => "\n\n:arrow_forward: _**Pre-round lobby started**_\n",
GameRunLevel.InRound => "\n\n:arrow_forward: _**Round started**_\n",
@ -413,26 +456,35 @@ namespace Content.Server.Administration.Systems
$"{_gameTicker.RunLevel} was not matched."),
};
existingEmbed.lastRunLevel = _gameTicker.RunLevel;
existingEmbed.LastRunLevel = _gameTicker.RunLevel;
}
// If last message of the new batch is SOS then relay it to on-call.
// ... as long as it hasn't been relayed already.
var discordMention = messages.Last();
var onCallRelay = !discordMention.Receivers && !existingEmbed.OnCall;
// Add available messages to the embed description
while (messages.TryDequeue(out var message))
{
// In case someone thinks they're funny
if (message.Length > MessageLengthCap)
message = message[..(MessageLengthCap - TooLongText.Length)] + TooLongText;
string text;
existingEmbed.description += $"\n{message}";
// In case someone thinks they're funny
if (message.Message.Length > MessageLengthCap)
text = message.Message[..(MessageLengthCap - TooLongText.Length)] + TooLongText;
else
text = message.Message;
existingEmbed.Description += $"\n{text}";
}
var payload = GeneratePayload(existingEmbed.description,
existingEmbed.username,
existingEmbed.characterName);
var payload = GeneratePayload(existingEmbed.Description,
existingEmbed.Username,
existingEmbed.CharacterName);
// If there is no existing embed, create a new one
// Otherwise patch (edit) it
if (existingEmbed.id == null)
if (existingEmbed.Id == null)
{
var request = await _httpClient.PostAsync($"{_webhookUrl}?wait=true",
new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"));
@ -455,11 +507,11 @@ namespace Content.Server.Administration.Systems
return;
}
existingEmbed.id = id.ToString();
existingEmbed.Id = id.ToString();
}
else
{
var request = await _httpClient.PatchAsync($"{_webhookUrl}/messages/{existingEmbed.id}",
var request = await _httpClient.PatchAsync($"{_webhookUrl}/messages/{existingEmbed.Id}",
new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"));
if (!request.IsSuccessStatusCode)
@ -474,6 +526,43 @@ namespace Content.Server.Administration.Systems
_relayMessages[userId] = existingEmbed;
// Actually do the on call relay last, we just need to grab it before we dequeue every message above.
if (onCallRelay &&
_onCallData != null)
{
existingEmbed.OnCall = true;
var roleMention = _config.GetCVar(CCVars.DiscordAhelpMention);
if (!string.IsNullOrEmpty(roleMention))
{
var message = new StringBuilder();
message.AppendLine($"<@&{roleMention}>");
message.AppendLine("Unanswered SOS");
// Need webhook data to get the correct link for that channel rather than on-call data.
if (_webhookData is { GuildId: { } guildId, ChannelId: { } channelId })
{
message.AppendLine(
$"**[Go to ahelp](https://discord.com/channels/{guildId}/{channelId}/{existingEmbed.Id})**");
}
payload = GeneratePayload(message.ToString(), existingEmbed.Username, existingEmbed.CharacterName);
var request = await _httpClient.PostAsync($"{_onCallUrl}?wait=true",
new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"));
var content = await request.Content.ReadAsStringAsync();
if (!request.IsSuccessStatusCode)
{
_sawmill.Log(LogLevel.Error, $"Discord returned bad status code when posting relay message (perhaps the message is too long?): {request.StatusCode}\nResponse: {content}");
}
}
}
else
{
existingEmbed.OnCall = false;
}
_processingChannels.Remove(userId);
}
@ -652,7 +741,7 @@ namespace Content.Server.Administration.Systems
if (sendsWebhook)
{
if (!_messageQueues.ContainsKey(msg.UserId))
_messageQueues[msg.UserId] = new Queue<string>();
_messageQueues[msg.UserId] = new Queue<DiscordRelayedData>();
var str = message.Text;
var unameLength = senderSession.Name.Length;
@ -701,7 +790,7 @@ namespace Content.Server.Administration.Systems
.ToList();
}
private static string GenerateAHelpMessage(AHelpMessageParams parameters)
private static DiscordRelayedData GenerateAHelpMessage(AHelpMessageParams parameters)
{
var stringbuilder = new StringBuilder();
@ -718,13 +807,57 @@ namespace Content.Server.Administration.Systems
stringbuilder.Append($" **{parameters.RoundTime}**");
if (!parameters.PlayedSound)
stringbuilder.Append(" **(S)**");
if (parameters.Icon == null)
stringbuilder.Append($" **{parameters.Username}:** ");
else
stringbuilder.Append($" **{parameters.Username}** ");
stringbuilder.Append(parameters.Message);
return stringbuilder.ToString();
return new DiscordRelayedData()
{
Receivers = !parameters.NoReceivers,
Message = stringbuilder.ToString(),
};
}
private record struct DiscordRelayedData
{
/// <summary>
/// Was anyone online to receive it.
/// </summary>
public bool Receivers;
/// <summary>
/// What's the payload to send to discord.
/// </summary>
public string Message;
}
/// <summary>
/// Class specifically for holding information regarding existing Discord embeds
/// </summary>
private sealed class DiscordRelayInteraction
{
public string? Id;
public string Username = String.Empty;
public string? CharacterName;
/// <summary>
/// Contents for the discord message.
/// </summary>
public string Description = string.Empty;
/// <summary>
/// Run level of the last interaction. If different we'll link to the last Id.
/// </summary>
public GameRunLevel LastRunLevel;
/// <summary>
/// Did we relay this interaction to OnCall previously.
/// </summary>
public bool OnCall;
}
}

View File

@ -55,7 +55,7 @@ public sealed partial class AmeControllerComponent : SharedAmeControllerComponen
/// </summary>
[DataField("injectSound")]
[ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier InjectSound = new SoundCollectionSpecifier("MetalThud");
public SoundSpecifier InjectSound = new SoundPathSpecifier("/Audio/Machines/ame_fuelinjection.ogg");
/// <summary>
/// The last time this could have injected fuel into the AME.

View File

@ -39,7 +39,7 @@ public sealed class ExaminableDamageSystem : EntitySystem
var level = GetDamageLevel(uid, component);
var msg = Loc.GetString(messages[level]);
args.PushMarkup(msg);
args.PushMarkup(msg,-99);
}
private int GetDamageLevel(EntityUid uid, ExaminableDamageComponent? component = null,

View File

@ -46,8 +46,8 @@ public sealed class DoorSystem : SharedDoorSystem
SetBoltsDown(ent, true);
}
UpdateBoltLightStatus(ent);
ent.Comp.Powered = args.Powered;
Dirty(ent, ent.Comp);
UpdateBoltLightStatus(ent);
}
}

View File

@ -0,0 +1,82 @@
using Content.Shared.EntityEffects;
using Content.Server.Flash;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Server.EntityEffects.Effects;
[DataDefinition]
public sealed partial class FlashReactionEffect : EntityEffect
{
/// <summary>
/// Flash range per unit of reagent.
/// </summary>
[DataField]
public float RangePerUnit = 0.2f;
/// <summary>
/// Maximum flash range.
/// </summary>
[DataField]
public float MaxRange = 10f;
/// <summary>
/// How much to entities are slowed down.
/// </summary>
[DataField]
public float SlowTo = 0.5f;
/// <summary>
/// The time entities will be flashed in seconds.
/// The default is chosen to be better than the hand flash so it is worth using it for grenades etc.
/// </summary>
[DataField]
public float Duration = 4f;
/// <summary>
/// The prototype ID used for the visual effect.
/// </summary>
[DataField]
public EntProtoId? FlashEffectPrototype = "ReactionFlash";
/// <summary>
/// The sound the flash creates.
/// </summary>
[DataField]
public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Weapons/flash.ogg");
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
=> Loc.GetString("reagent-effect-guidebook-flash-reaction-effect", ("chance", Probability));
public override void Effect(EntityEffectBaseArgs args)
{
var transform = args.EntityManager.GetComponent<TransformComponent>(args.TargetEntity);
var transformSystem = args.EntityManager.System<SharedTransformSystem>();
var range = 1f;
if (args is EntityEffectReagentArgs reagentArgs)
range = MathF.Min((float)(reagentArgs.Quantity * RangePerUnit), MaxRange);
args.EntityManager.System<FlashSystem>().FlashArea(
args.TargetEntity,
null,
range,
Duration * 1000,
slowTo: SlowTo,
sound: Sound);
if (FlashEffectPrototype == null)
return;
var uid = args.EntityManager.SpawnEntity(FlashEffectPrototype, transformSystem.GetMapCoordinates(transform));
transformSystem.AttachToGridOrMap(uid);
if (!args.EntityManager.TryGetComponent<PointLightComponent>(uid, out var pointLightComp))
return;
var pointLightSystem = args.EntityManager.System<SharedPointLightSystem>();
// PointLights with a radius lower than 1.1 are too small to be visible, so this is hardcoded
pointLightSystem.SetRadius(uid, MathF.Max(1.1f, range), pointLightComp);
}
}

View File

@ -213,14 +213,7 @@ namespace Content.Server.Ghost
private void OnMapInit(EntityUid uid, GhostComponent component, MapInitEvent args)
{
if (_actions.AddAction(uid, ref component.BooActionEntity, out var act, component.BooAction)
&& act.UseDelay != null)
{
var start = _gameTiming.CurTime;
var end = start + act.UseDelay.Value;
_actions.SetCooldown(component.BooActionEntity.Value, start, end);
}
_actions.AddAction(uid, ref component.BooActionEntity, component.BooAction);
_actions.AddAction(uid, ref component.ToggleGhostHearingActionEntity, component.ToggleGhostHearingAction);
_actions.AddAction(uid, ref component.ToggleLightingActionEntity, component.ToggleLightingAction);
_actions.AddAction(uid, ref component.ToggleFoVActionEntity, component.ToggleFoVAction);

View File

@ -201,6 +201,7 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem
? bloodSolution.FillFraction
: 0,
null,
null,
null
));
}

View File

@ -2,6 +2,7 @@ using Content.Server.Body.Components;
using Content.Server.Medical.Components;
using Content.Server.PowerCell;
using Content.Server.Temperature.Components;
using Content.Server.Traits.Assorted;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.DoAfter;
@ -196,6 +197,7 @@ public sealed class HealthAnalyzerSystem : EntitySystem
var bloodAmount = float.NaN;
var bleeding = false;
var unrevivable = false;
if (TryComp<BloodstreamComponent>(target, out var bloodstream) &&
_solutionContainerSystem.ResolveSolution(target, bloodstream.BloodSolutionName,
@ -205,12 +207,16 @@ public sealed class HealthAnalyzerSystem : EntitySystem
bleeding = bloodstream.BleedAmount > 0;
}
if (HasComp<UnrevivableComponent>(target))
unrevivable = true;
_uiSystem.ServerSendUiMessage(healthAnalyzer, HealthAnalyzerUiKey.Key, new HealthAnalyzerScannedUserMessage(
GetNetEntity(target),
bodyTemperature,
bloodAmount,
scanMode,
bleeding
bleeding,
unrevivable
));
}
}

View File

@ -40,7 +40,9 @@ namespace Content.Server.Nutrition.EntitySystems
protected override void SplattedCreamPie(EntityUid uid, CreamPieComponent creamPie)
{
_audio.PlayPvs(_audio.GetSound(creamPie.Sound), uid, AudioParams.Default.WithVariation(0.125f));
// The entity is deleted, so play the sound at its position rather than parenting
var coordinates = Transform(uid).Coordinates;
_audio.PlayPvs(_audio.GetSound(creamPie.Sound), coordinates, AudioParams.Default.WithVariation(0.125f));
if (EntityManager.TryGetComponent(uid, out FoodComponent? foodComp))
{

View File

@ -10,6 +10,7 @@ using Content.Server.Shuttles.Events;
using Content.Server.Shuttles.Systems;
using Content.Shared.Atmos;
using Content.Shared.Decals;
using Content.Shared.Ghost;
using Content.Shared.Gravity;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Parallax.Biomes.Layers;
@ -51,6 +52,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
private EntityQuery<BiomeComponent> _biomeQuery;
private EntityQuery<FixturesComponent> _fixturesQuery;
private EntityQuery<GhostComponent> _ghostQuery;
private EntityQuery<TransformComponent> _xformQuery;
private readonly HashSet<EntityUid> _handledEntities = new();
@ -81,6 +83,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
Log.Level = LogLevel.Debug;
_biomeQuery = GetEntityQuery<BiomeComponent>();
_fixturesQuery = GetEntityQuery<FixturesComponent>();
_ghostQuery = GetEntityQuery<GhostComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<BiomeComponent, MapInitEvent>(OnBiomeMapInit);
SubscribeLocalEvent<FTLStartedEvent>(OnFTLStarted);
@ -315,6 +318,11 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
}
}
private bool CanLoad(EntityUid uid)
{
return !_ghostQuery.HasComp(uid);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
@ -332,7 +340,8 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
if (_xformQuery.TryGetComponent(pSession.AttachedEntity, out var xform) &&
_handledEntities.Add(pSession.AttachedEntity.Value) &&
_biomeQuery.TryGetComponent(xform.MapUid, out var biome) &&
biome.Enabled)
biome.Enabled &&
CanLoad(pSession.AttachedEntity.Value))
{
var worldPos = _transform.GetWorldPosition(xform);
AddChunksInRange(biome, worldPos);
@ -349,7 +358,8 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
if (!_handledEntities.Add(viewer) ||
!_xformQuery.TryGetComponent(viewer, out xform) ||
!_biomeQuery.TryGetComponent(xform.MapUid, out biome) ||
!biome.Enabled)
!biome.Enabled ||
!CanLoad(viewer))
{
continue;
}

View File

@ -30,7 +30,7 @@ public sealed class RadioDeviceSystem : EntitySystem
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
// Used to prevent a shitter from using a bunch of radios to spam chat.
private HashSet<(string, EntityUid)> _recentlySent = new();
private HashSet<(string, EntityUid, RadioChannelPrototype)> _recentlySent = new();
public override void Initialize()
{
@ -114,7 +114,7 @@ public sealed class RadioDeviceSystem : EntitySystem
{
if (args.Powered)
return;
SetMicrophoneEnabled(uid, null, false, true, component);
SetMicrophoneEnabled(uid, null, false, true, component);
}
public void SetMicrophoneEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioMicrophoneComponent? component = null)
@ -191,8 +191,9 @@ public sealed class RadioDeviceSystem : EntitySystem
if (HasComp<RadioSpeakerComponent>(args.Source))
return; // no feedback loops please.
if (_recentlySent.Add((args.Message, args.Source)))
_radio.SendRadioMessage(args.Source, args.Message, _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel), uid);
var channel = _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel)!;
if (_recentlySent.Add((args.Message, args.Source, channel)))
_radio.SendRadioMessage(args.Source, args.Message, channel, uid);
}
private void OnAttemptListen(EntityUid uid, RadioMicrophoneComponent component, ListenAttemptEvent args)
@ -279,7 +280,7 @@ public sealed class RadioDeviceSystem : EntitySystem
if (TryComp<RadioMicrophoneComponent>(ent, out var mic))
mic.BroadcastChannel = channel;
if (TryComp<RadioSpeakerComponent>(ent, out var speaker))
speaker.Channels = new(){ channel };
speaker.Channels = new() { channel };
Dirty(ent);
}
}

View File

@ -32,6 +32,7 @@ namespace Content.Server.Voting.Managers
private VotingSystem? _votingSystem;
private RoleSystem? _roleSystem;
private GameTicker? _gameTicker;
private static readonly Dictionary<StandardVoteType, CVarDef<bool>> _voteTypesToEnableCVars = new()
{
@ -70,8 +71,8 @@ namespace Content.Server.Voting.Managers
default:
throw new ArgumentOutOfRangeException(nameof(voteType), voteType, null);
}
var ticker = _entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
ticker.UpdateInfoText();
_gameTicker = _entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
_gameTicker.UpdateInfoText();
if (timeoutVote)
TimeoutStandardVote(voteType);
}
@ -346,8 +347,14 @@ namespace Content.Server.Voting.Managers
return;
}
var voterEligibility = _cfg.GetCVar(CCVars.VotekickVoterGhostRequirement) ? VoterEligibility.GhostMinimumPlaytime : VoterEligibility.MinimumPlaytime;
if (_cfg.GetCVar(CCVars.VotekickIgnoreGhostReqInLobby) && _gameTicker!.RunLevel == GameRunLevel.PreRoundLobby)
voterEligibility = VoterEligibility.MinimumPlaytime;
var eligibleVoterNumberRequirement = _cfg.GetCVar(CCVars.VotekickEligibleNumberRequirement);
var eligibleVoterNumber = _cfg.GetCVar(CCVars.VotekickVoterGhostRequirement) ? CalculateEligibleVoterNumber(VoterEligibility.GhostMinimumPlaytime) : CalculateEligibleVoterNumber(VoterEligibility.MinimumPlaytime);
var eligibleVoterNumber = CalculateEligibleVoterNumber(voterEligibility);
string target = args[0];
string reason = args[1];
@ -441,7 +448,7 @@ namespace Content.Server.Voting.Managers
},
Duration = TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.VotekickTimer)),
InitiatorTimeout = TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.VotekickTimeout)),
VoterEligibility = _cfg.GetCVar(CCVars.VotekickVoterGhostRequirement) ? VoterEligibility.GhostMinimumPlaytime : VoterEligibility.MinimumPlaytime,
VoterEligibility = voterEligibility,
DisplayVotes = false,
TargetEntity = targetNetEntity
};

View File

@ -1,5 +1,6 @@
using Content.Server.Administration.Managers;
using Content.Server.Database;
using Content.Server.GameTicking;
using Content.Server.Ghost;
using Content.Server.Roles.Jobs;
using Content.Shared.CCVar;
@ -12,6 +13,7 @@ using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using System.Threading.Tasks;
using Content.Shared.Players.PlayTimeTracking;
namespace Content.Server.Voting;
@ -24,6 +26,8 @@ public sealed class VotingSystem : EntitySystem
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly JobSystem _jobs = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly ISharedPlaytimeManager _playtimeManager = default!;
public override void Initialize()
{
@ -34,8 +38,7 @@ public sealed class VotingSystem : EntitySystem
private async void OnVotePlayerListRequestEvent(VotePlayerListRequestEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not { Valid: true } entity
|| !await CheckVotekickInitEligibility(args.SenderSession))
if (!await CheckVotekickInitEligibility(args.SenderSession))
{
var deniedResponse = new VotePlayerListResponseEvent(new (NetUserId, NetEntity, string)[0], true);
RaiseNetworkEvent(deniedResponse, args.SenderSession.Channel);
@ -46,17 +49,23 @@ public sealed class VotingSystem : EntitySystem
foreach (var player in _playerManager.Sessions)
{
if (player.AttachedEntity is not { Valid: true } attached)
continue;
if (attached == entity) continue;
if (args.SenderSession == player) continue;
if (_adminManager.IsAdmin(player, false)) continue;
var playerName = GetPlayerVoteListName(attached);
var netEntity = GetNetEntity(attached);
if (player.AttachedEntity is not { Valid: true } attached)
{
var playerName = player.Name;
var netEntity = NetEntity.Invalid;
players.Add((player.UserId, netEntity, playerName));
}
else
{
var playerName = GetPlayerVoteListName(attached);
var netEntity = GetNetEntity(attached);
players.Add((player.UserId, netEntity, playerName));
players.Add((player.UserId, netEntity, playerName));
}
}
var response = new VotePlayerListResponseEvent(players.ToArray(), false);
@ -86,22 +95,29 @@ public sealed class VotingSystem : EntitySystem
if (initiator.AttachedEntity != null && _adminManager.IsAdmin(initiator.AttachedEntity.Value, false))
return true;
if (_cfg.GetCVar(CCVars.VotekickInitiatorGhostRequirement))
// If cvar enabled, skip the ghost requirement in the preround lobby
if (!_cfg.GetCVar(CCVars.VotekickIgnoreGhostReqInLobby) || (_cfg.GetCVar(CCVars.VotekickIgnoreGhostReqInLobby) && _gameTicker.RunLevel != GameRunLevel.PreRoundLobby))
{
// Must be ghost
if (!TryComp(initiator.AttachedEntity, out GhostComponent? ghostComp))
return false;
if (_cfg.GetCVar(CCVars.VotekickInitiatorGhostRequirement))
{
// Must be ghost
if (!TryComp(initiator.AttachedEntity, out GhostComponent? ghostComp))
return false;
// Must have been dead for x seconds
if ((int)_gameTiming.RealTime.Subtract(ghostComp.TimeOfDeath).TotalSeconds < _cfg.GetCVar(CCVars.VotekickEligibleVoterDeathtime))
return false;
// Must have been dead for x seconds
if ((int)_gameTiming.RealTime.Subtract(ghostComp.TimeOfDeath).TotalSeconds < _cfg.GetCVar(CCVars.VotekickEligibleVoterDeathtime))
return false;
}
}
// Must be whitelisted
if (!await _dbManager.GetWhitelistStatusAsync(initiator.UserId))
if (!await _dbManager.GetWhitelistStatusAsync(initiator.UserId) && _cfg.GetCVar(CCVars.VotekickInitiatorWhitelistedRequirement))
return false;
return true;
// Must be eligible to vote
var playtime = _playtimeManager.GetPlayTimes(initiator);
return playtime.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out TimeSpan overallTime) && (overallTime >= TimeSpan.FromHours(_cfg.GetCVar(CCVars.VotekickEligibleVoterPlaytime))
|| !_cfg.GetCVar(CCVars.VotekickInitiatorTimeRequirement));
}
/// <summary>

View File

@ -76,6 +76,11 @@ public abstract partial class BaseActionComponent : Component
// TODO serialization
public (TimeSpan Start, TimeSpan End)? Cooldown;
/// <summary>
/// If true, the action will have an initial cooldown applied upon addition.
/// </summary>
[DataField] public bool StartDelay = false;
/// <summary>
/// Time interval between action uses.
/// </summary>

View File

@ -813,6 +813,9 @@ public abstract class SharedActionsSystem : EntitySystem
if (action.AttachedEntity != null)
RemoveAction(action.AttachedEntity.Value, actionId, action: action);
if (action.StartDelay && action.UseDelay != null)
SetCooldown(actionId, action.UseDelay.Value);
DebugTools.AssertOwner(performer, comp);
comp ??= EnsureComp<ActionsComponent>(performer);
action.AttachedEntity = performer;

View File

@ -130,9 +130,6 @@ public sealed partial class SleepingSystem : EntitySystem
RaiseLocalEvent(ent, ref ev);
_blindableSystem.UpdateIsBlind(ent.Owner);
_actionsSystem.AddAction(ent, ref ent.Comp.WakeAction, WakeActionId, ent);
// TODO remove hardcoded time.
_actionsSystem.SetCooldown(ent.Comp.WakeAction, _gameTiming.CurTime, _gameTiming.CurTime + TimeSpan.FromSeconds(2f));
}
private void OnSpeakAttempt(Entity<SleepingComponent> ent, ref SpeakAttemptEvent args)

View File

@ -461,6 +461,18 @@ namespace Content.Shared.CCVar
* Discord
*/
/// <summary>
/// The role that will get mentioned if a new SOS ahelp comes in.
/// </summary>
public static readonly CVarDef<string> DiscordAhelpMention =
CVarDef.Create("discord.on_call_ping", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL);
/// <summary>
/// URL of the discord webhook to relay unanswered ahelp messages.
/// </summary>
public static readonly CVarDef<string> DiscordOnCallWebhook =
CVarDef.Create("discord.on_call_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL);
/// <summary>
/// URL of the Discord webhook which will relay all ahelp messages.
/// </summary>
@ -1469,7 +1481,7 @@ namespace Content.Shared.CCVar
/// Config for when the votekick should be allowed to be called based on number of eligible voters.
/// </summary>
public static readonly CVarDef<int> VotekickEligibleNumberRequirement =
CVarDef.Create("votekick.eligible_number", 10, CVar.SERVERONLY);
CVarDef.Create("votekick.eligible_number", 5, CVar.SERVERONLY);
/// <summary>
/// Whether a votekick initiator must be a ghost or not.
@ -1477,6 +1489,18 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> VotekickInitiatorGhostRequirement =
CVarDef.Create("votekick.initiator_ghost_requirement", true, CVar.SERVERONLY);
/// <summary>
/// Should the initiator be whitelisted to initiate a votekick?
/// </summary>
public static readonly CVarDef<bool> VotekickInitiatorWhitelistedRequirement =
CVarDef.Create("votekick.initiator_whitelist_requirement", true, CVar.SERVERONLY);
/// <summary>
/// Should the initiator be able to start a votekick if they are bellow the votekick.voter_playtime requirement?
/// </summary>
public static readonly CVarDef<bool> VotekickInitiatorTimeRequirement =
CVarDef.Create("votekick.initiator_time_requirement", false, CVar.SERVERONLY);
/// <summary>
/// Whether a votekick voter must be a ghost or not.
/// </summary>
@ -1493,7 +1517,7 @@ namespace Content.Shared.CCVar
/// Config for how many seconds a player must have been dead to initiate a votekick / be able to vote on a votekick.
/// </summary>
public static readonly CVarDef<int> VotekickEligibleVoterDeathtime =
CVarDef.Create("votekick.voter_deathtime", 180, CVar.REPLICATED | CVar.SERVER);
CVarDef.Create("votekick.voter_deathtime", 30, CVar.REPLICATED | CVar.SERVER);
/// <summary>
/// The required ratio of eligible voters that must agree for a votekick to go through.
@ -1537,6 +1561,12 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<int> VotekickBanDuration =
CVarDef.Create("votekick.ban_duration", 180, CVar.SERVERONLY);
/// <summary>
/// Whether the ghost requirement settings for votekicks should be ignored for the lobby.
/// </summary>
public static readonly CVarDef<bool> VotekickIgnoreGhostReqInLobby =
CVarDef.Create("votekick.ignore_ghost_req_in_lobby", true, CVar.SERVERONLY);
/*
* BAN
*/

View File

@ -33,7 +33,7 @@ public sealed partial class CartridgeLoaderComponent : Component
/// The maximum amount of programs that can be installed on the cartridge loader entity
/// </summary>
[DataField]
public int DiskSpace = 5;
public int DiskSpace = 8;
/// <summary>
/// Controls whether the cartridge loader will play notifications if it supports it at all

View File

@ -0,0 +1,21 @@
namespace Content.Shared.Chemistry.Components;
/// <summary>
/// Represents a container that also contains a solution.
/// This means that reactive entities react when inserted into the container.
/// </summary>
[RegisterComponent]
public sealed partial class ReactiveContainerComponent : Component
{
/// <summary>
/// The container that holds the solution.
/// </summary>
[DataField(required: true)]
public string Container = default!;
/// <summary>
/// The solution in the container.
/// </summary>
[DataField(required: true)]
public string Solution = default!;
}

View File

@ -0,0 +1,53 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
using Robust.Shared.Containers;
namespace Content.Shared.Chemistry.EntitySystems;
public sealed class ReactiveContainerSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReactiveContainerComponent, EntInsertedIntoContainerMessage>(OnInserted);
SubscribeLocalEvent<ReactiveContainerComponent, SolutionContainerChangedEvent>(OnSolutionChange);
}
private void OnInserted(EntityUid uid, ReactiveContainerComponent comp, EntInsertedIntoContainerMessage args)
{
// Only reactive entities can react with the solution
if (!HasComp<ReactiveComponent>(args.Entity))
return;
if (!_solutionContainerSystem.TryGetSolution(uid, comp.Solution, out _, out var solution))
return;
if (solution.Volume == 0)
return;
_reactiveSystem.DoEntityReaction(args.Entity, solution, ReactionMethod.Touch);
}
private void OnSolutionChange(EntityUid uid, ReactiveContainerComponent comp, SolutionContainerChangedEvent args)
{
if (!_solutionContainerSystem.TryGetSolution(uid, comp.Solution, out _, out var solution))
return;
if (solution.Volume == 0)
return;
if (!TryComp<ContainerManagerComponent>(uid, out var manager))
return;
if (!_containerSystem.TryGetContainer(uid, comp.Container, out var container))
return;
foreach (var entity in container.ContainedEntities)
{
if (!HasComp<ReactiveComponent>(entity))
continue;
_reactiveSystem.DoEntityReaction(entity, solution, ReactionMethod.Touch);
}
}
}

View File

@ -60,6 +60,7 @@ namespace Content.Shared.Containers.ItemSlots
}
#region ComponentManagement
/// <summary>
/// Spawn in starting items for any item slots that should have one.
/// </summary>
@ -70,7 +71,8 @@ namespace Content.Shared.Containers.ItemSlots
if (slot.HasItem || string.IsNullOrEmpty(slot.StartingItem))
continue;
var item = EntityManager.SpawnEntity(slot.StartingItem, EntityManager.GetComponent<TransformComponent>(uid).Coordinates);
var item = Spawn(slot.StartingItem, Transform(uid).Coordinates);
if (slot.ContainerSlot != null)
_containers.Insert(item, slot.ContainerSlot);
}
@ -99,7 +101,8 @@ namespace Content.Shared.Containers.ItemSlots
if (itemSlots.Slots.TryGetValue(id, out var existing))
{
if (existing.Local)
Log.Error($"Duplicate item slot key. Entity: {EntityManager.GetComponent<MetaDataComponent>(uid).EntityName} ({uid}), key: {id}");
Log.Error(
$"Duplicate item slot key. Entity: {EntityManager.GetComponent<MetaDataComponent>(uid).EntityName} ({uid}), key: {id}");
else
// server state takes priority
slot.CopyFrom(existing);
@ -134,7 +137,10 @@ namespace Content.Shared.Containers.ItemSlots
Dirty(uid, itemSlots);
}
public bool TryGetSlot(EntityUid uid, string slotId, [NotNullWhen(true)] out ItemSlot? itemSlot, ItemSlotsComponent? component = null)
public bool TryGetSlot(EntityUid uid,
string slotId,
[NotNullWhen(true)] out ItemSlot? itemSlot,
ItemSlotsComponent? component = null)
{
itemSlot = null;
@ -143,9 +149,11 @@ namespace Content.Shared.Containers.ItemSlots
return component.Slots.TryGetValue(slotId, out itemSlot);
}
#endregion
#region Interactions
/// <summary>
/// Attempt to take an item from a slot, if any are set to EjectOnInteract.
/// </summary>
@ -201,20 +209,50 @@ namespace Content.Shared.Containers.ItemSlots
if (!EntityManager.TryGetComponent(args.User, out HandsComponent? hands))
return;
if (itemSlots.Slots.Count == 0)
return;
// If any slot can be inserted into don't show popup.
// If any whitelist passes, but slot is locked, then show locked.
// If whitelist fails all, show whitelist fail.
// valid, insertable slots (if any)
var slots = new List<ItemSlot>();
string? whitelistFailPopup = null;
string? lockedFailPopup = null;
foreach (var slot in itemSlots.Slots.Values)
{
if (!slot.InsertOnInteract)
continue;
if (!CanInsert(uid, args.Used, args.User, slot, swap: slot.Swap, popup: args.User))
continue;
if (CanInsert(uid, args.Used, args.User, slot, slot.Swap))
{
slots.Add(slot);
}
else
{
var allowed = CanInsertWhitelist(args.Used, slot);
if (lockedFailPopup == null && slot.LockedFailPopup != null && allowed && slot.Locked)
lockedFailPopup = slot.LockedFailPopup;
slots.Add(slot);
if (whitelistFailPopup == null && slot.WhitelistFailPopup != null)
whitelistFailPopup = slot.WhitelistFailPopup;
}
}
if (slots.Count == 0)
{
// it's a bit weird that the popupMessage is stored with the item slots themselves, but in practice
// the popup messages will just all be the same, so it's probably fine.
//
// doing a check to make sure that they're all the same or something is probably frivolous
if (lockedFailPopup != null)
_popupSystem.PopupClient(Loc.GetString(lockedFailPopup), uid, args.User);
else if (whitelistFailPopup != null)
_popupSystem.PopupClient(Loc.GetString(whitelistFailPopup), uid, args.User);
return;
}
// Drop the held item onto the floor. Return if the user cannot drop.
if (!_handsSystem.TryDrop(args.User, args.Used, handsComp: hands))
@ -236,23 +274,31 @@ namespace Content.Shared.Containers.ItemSlots
return;
}
}
#endregion
#region Insert
/// <summary>
/// Insert an item into a slot. This does not perform checks, so make sure to also use <see
/// cref="CanInsert"/> or just use <see cref="TryInsert"/> instead.
/// </summary>
/// <param name="excludeUserAudio">If true, will exclude the user when playing sound. Does nothing client-side.
/// Useful for predicted interactions</param>
private void Insert(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? user, bool excludeUserAudio = false)
private void Insert(EntityUid uid,
ItemSlot slot,
EntityUid item,
EntityUid? user,
bool excludeUserAudio = false)
{
bool? inserted = slot.ContainerSlot != null ? _containers.Insert(item, slot.ContainerSlot) : null;
// ContainerSlot automatically raises a directed EntInsertedIntoContainerMessage
// Logging
if (inserted != null && inserted.Value && user != null)
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value)} inserted {ToPrettyString(item)} into {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
_adminLogger.Add(LogType.Action,
LogImpact.Low,
$"{ToPrettyString(user.Value)} inserted {ToPrettyString(item)} into {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
_audioSystem.PlayPredicted(slot.InsertSound, uid, excludeUserAudio ? user : null);
}
@ -261,46 +307,53 @@ namespace Content.Shared.Containers.ItemSlots
/// Check whether a given item can be inserted into a slot. Unless otherwise specified, this will return
/// false if the slot is already filled.
/// </summary>
/// <remarks>
/// If a popup entity is given, and if the item slot is set to generate a popup message when it fails to
/// pass the whitelist or due to slot being locked, then this will generate an appropriate popup.
/// </remarks>
public bool CanInsert(EntityUid uid, EntityUid usedUid, EntityUid? user, ItemSlot slot, bool swap = false, EntityUid? popup = null)
public bool CanInsert(EntityUid uid,
EntityUid usedUid,
EntityUid? user,
ItemSlot slot,
bool swap = false)
{
if (slot.ContainerSlot == null)
return false;
if (_whitelistSystem.IsWhitelistFail(slot.Whitelist, usedUid) || _whitelistSystem.IsBlacklistPass(slot.Blacklist, usedUid))
{
if (popup.HasValue && slot.WhitelistFailPopup.HasValue)
_popupSystem.PopupClient(Loc.GetString(slot.WhitelistFailPopup), uid, popup.Value);
if (slot.HasItem && (!swap || swap && !CanEject(uid, user, slot)))
return false;
if (!CanInsertWhitelist(usedUid, slot))
return false;
}
if (slot.Locked)
{
if (popup.HasValue && slot.LockedFailPopup.HasValue)
_popupSystem.PopupClient(Loc.GetString(slot.LockedFailPopup), uid, popup.Value);
return false;
}
if (slot.HasItem && (!swap || (swap && !CanEject(uid, user, slot))))
return false;
var ev = new ItemSlotInsertAttemptEvent(uid, usedUid, user, slot);
RaiseLocalEvent(uid, ref ev);
RaiseLocalEvent(usedUid, ref ev);
if (ev.Cancelled)
{
return false;
}
return _containers.CanInsert(usedUid, slot.ContainerSlot, assumeEmpty: swap);
}
private bool CanInsertWhitelist(EntityUid usedUid, ItemSlot slot)
{
if (_whitelistSystem.IsWhitelistFail(slot.Whitelist, usedUid)
|| _whitelistSystem.IsBlacklistPass(slot.Blacklist, usedUid))
return false;
return true;
}
/// <summary>
/// Tries to insert item into a specific slot.
/// </summary>
/// <returns>False if failed to insert item</returns>
public bool TryInsert(EntityUid uid, string id, EntityUid item, EntityUid? user, ItemSlotsComponent? itemSlots = null, bool excludeUserAudio = false)
public bool TryInsert(EntityUid uid,
string id,
EntityUid item,
EntityUid? user,
ItemSlotsComponent? itemSlots = null,
bool excludeUserAudio = false)
{
if (!Resolve(uid, ref itemSlots))
return false;
@ -315,7 +368,11 @@ namespace Content.Shared.Containers.ItemSlots
/// Tries to insert item into a specific slot.
/// </summary>
/// <returns>False if failed to insert item</returns>
public bool TryInsert(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? user, bool excludeUserAudio = false)
public bool TryInsert(EntityUid uid,
ItemSlot slot,
EntityUid item,
EntityUid? user,
bool excludeUserAudio = false)
{
if (!CanInsert(uid, item, user, slot))
return false;
@ -329,7 +386,11 @@ namespace Content.Shared.Containers.ItemSlots
/// Does not check action blockers.
/// </summary>
/// <returns>False if failed to insert item</returns>
public bool TryInsertFromHand(EntityUid uid, ItemSlot slot, EntityUid user, HandsComponent? hands = null, bool excludeUserAudio = false)
public bool TryInsertFromHand(EntityUid uid,
ItemSlot slot,
EntityUid user,
HandsComponent? hands = null,
bool excludeUserAudio = false)
{
if (!Resolve(user, ref hands, false))
return false;
@ -406,6 +467,7 @@ namespace Content.Shared.Containers.ItemSlots
return 1;
}
#endregion
#region Eject
@ -425,7 +487,7 @@ namespace Content.Shared.Containers.ItemSlots
return false;
}
if (slot.ContainerSlot?.ContainedEntity is not {} item)
if (slot.ContainerSlot?.ContainedEntity is not { } item)
return false;
var ev = new ItemSlotEjectAttemptEvent(uid, item, user, slot);
@ -450,7 +512,9 @@ namespace Content.Shared.Containers.ItemSlots
// Logging
if (ejected != null && ejected.Value && user != null)
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value)} ejected {ToPrettyString(item)} from {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
_adminLogger.Add(LogType.Action,
LogImpact.Low,
$"{ToPrettyString(user.Value)} ejected {ToPrettyString(item)} from {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
_audioSystem.PlayPredicted(slot.EjectSound, uid, excludeUserAudio ? user : null);
}
@ -459,7 +523,11 @@ namespace Content.Shared.Containers.ItemSlots
/// Try to eject an item from a slot.
/// </summary>
/// <returns>False if item slot is locked or has no item inserted</returns>
public bool TryEject(EntityUid uid, ItemSlot slot, EntityUid? user, [NotNullWhen(true)] out EntityUid? item, bool excludeUserAudio = false)
public bool TryEject(EntityUid uid,
ItemSlot slot,
EntityUid? user,
[NotNullWhen(true)] out EntityUid? item,
bool excludeUserAudio = false)
{
item = null;
@ -481,8 +549,12 @@ namespace Content.Shared.Containers.ItemSlots
/// Try to eject item from a slot.
/// </summary>
/// <returns>False if the id is not valid, the item slot is locked, or it has no item inserted</returns>
public bool TryEject(EntityUid uid, string id, EntityUid? user,
[NotNullWhen(true)] out EntityUid? item, ItemSlotsComponent? itemSlots = null, bool excludeUserAudio = false)
public bool TryEject(EntityUid uid,
string id,
EntityUid? user,
[NotNullWhen(true)] out EntityUid? item,
ItemSlotsComponent? itemSlots = null,
bool excludeUserAudio = false)
{
item = null;
@ -513,12 +585,16 @@ namespace Content.Shared.Containers.ItemSlots
return true;
}
#endregion
#region Verbs
private void AddAlternativeVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetVerbsEvent<AlternativeVerb> args)
private void AddAlternativeVerbs(EntityUid uid,
ItemSlotsComponent itemSlots,
GetVerbsEvent<AlternativeVerb> args)
{
if (args.Hands == null || !args.CanAccess ||!args.CanInteract)
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
{
return;
}
@ -612,7 +688,9 @@ namespace Content.Shared.Containers.ItemSlots
}
}
private void AddInteractionVerbsVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetVerbsEvent<InteractionVerb> args)
private void AddInteractionVerbsVerbs(EntityUid uid,
ItemSlotsComponent itemSlots,
GetVerbsEvent<InteractionVerb> args)
{
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
return;
@ -671,7 +749,7 @@ namespace Content.Shared.Containers.ItemSlots
new SpriteSpecifier.Texture(
new ResPath("/Textures/Interface/VerbIcons/insert.svg.192dpi.png"));
}
else if(slot.EjectOnInteract)
else if (slot.EjectOnInteract)
{
// Inserting/ejecting is a primary interaction for this entity. Instead of using the insert
// category, we will use a single "Place <item>" verb.
@ -690,9 +768,11 @@ namespace Content.Shared.Containers.ItemSlots
args.Verbs.Add(insertVerb);
}
}
#endregion
#region BUIs
private void HandleButtonPressed(EntityUid uid, ItemSlotsComponent component, ItemSlotButtonPressedEvent args)
{
if (!component.Slots.TryGetValue(args.SlotId, out var slot))
@ -703,6 +783,7 @@ namespace Content.Shared.Containers.ItemSlots
else if (args.TryInsert && !slot.HasItem)
TryInsertFromHand(uid, slot, args.Actor);
}
#endregion
/// <summary>

View File

@ -47,7 +47,7 @@ public abstract partial class InventorySystem
private void OnEntRemoved(EntityUid uid, InventoryComponent component, EntRemovedFromContainerMessage args)
{
if(!TryGetSlot(uid, args.Container.ID, out var slotDef, inventory: component))
if (!TryGetSlot(uid, args.Container.ID, out var slotDef, inventory: component))
return;
var unequippedEvent = new DidUnequipEvent(uid, args.Entity, slotDef);
@ -59,8 +59,8 @@ public abstract partial class InventorySystem
private void OnEntInserted(EntityUid uid, InventoryComponent component, EntInsertedIntoContainerMessage args)
{
if(!TryGetSlot(uid, args.Container.ID, out var slotDef, inventory: component))
return;
if (!TryGetSlot(uid, args.Container.ID, out var slotDef, inventory: component))
return;
var equippedEvent = new DidEquipEvent(uid, args.Entity, slotDef);
RaiseLocalEvent(uid, equippedEvent, true);
@ -118,7 +118,7 @@ public abstract partial class InventorySystem
RaiseLocalEvent(held.Value, new HandDeselectedEvent(actor));
TryEquip(actor, actor, held.Value, ev.Slot, predicted: true, inventory: inventory, force: true, checkDoafter:true);
TryEquip(actor, actor, held.Value, ev.Slot, predicted: true, inventory: inventory, force: true, checkDoafter: true);
}
public bool TryEquip(EntityUid uid, EntityUid itemUid, string slot, bool silent = false, bool force = false, bool predicted = false,
@ -365,6 +365,25 @@ public abstract partial class InventorySystem
ClothingComponent? clothing = null,
bool reparent = true,
bool checkDoafter = false)
{
var itemsDropped = 0;
return TryUnequip(actor, target, slot, out removedItem, ref itemsDropped,
silent, force, predicted, inventory, clothing, reparent, checkDoafter);
}
private bool TryUnequip(
EntityUid actor,
EntityUid target,
string slot,
[NotNullWhen(true)] out EntityUid? removedItem,
ref int itemsDropped,
bool silent = false,
bool force = false,
bool predicted = false,
InventoryComponent? inventory = null,
ClothingComponent? clothing = null,
bool reparent = true,
bool checkDoafter = false)
{
removedItem = null;
@ -423,17 +442,27 @@ public abstract partial class InventorySystem
return false;
}
if (!_containerSystem.Remove(removedItem.Value, slotContainer, force: force, reparent: reparent))
return false;
// this is in order to keep track of whether this is the first instance of a recursion call
var firstRun = itemsDropped == 0;
++itemsDropped;
foreach (var slotDef in inventory.Slots)
{
if (slotDef != slotDefinition && slotDef.DependsOn == slotDefinition.Name)
{
//this recursive call might be risky
TryUnequip(actor, target, slotDef.Name, true, true, predicted, inventory, reparent: reparent);
TryUnequip(actor, target, slotDef.Name, out _, ref itemsDropped, true, true, predicted, inventory, reparent: reparent);
}
}
if (!_containerSystem.Remove(removedItem.Value, slotContainer, force: force, reparent: reparent))
return false;
// we check if any items were dropped, and make a popup if they were.
// the reason we check for > 1 is because the first item is always the one we are trying to unequip,
// whereas we only want to notify for extra dropped items.
if (!silent && _gameTiming.IsFirstTimePredicted && firstRun && itemsDropped > 1)
_popup.PopupClient(Loc.GetString("inventory-component-dropped-from-unequip", ("items", itemsDropped - 1)), target, target);
// TODO: Inventory needs a hot cleanup hoo boy
// Check if something else (AKA toggleable) dumped it into a container.
@ -466,7 +495,7 @@ public abstract partial class InventorySystem
if ((containerSlot == null || slotDefinition == null) && !TryGetSlotContainer(target, slot, out containerSlot, out slotDefinition, inventory))
return false;
if (containerSlot.ContainedEntity is not {} itemUid)
if (containerSlot.ContainedEntity is not { } itemUid)
return false;
if (!_containerSystem.CanRemove(itemUid, containerSlot))

View File

@ -13,14 +13,16 @@ public sealed class HealthAnalyzerScannedUserMessage : BoundUserInterfaceMessage
public float BloodLevel;
public bool? ScanMode;
public bool? Bleeding;
public bool? Unrevivable;
public HealthAnalyzerScannedUserMessage(NetEntity? targetEntity, float temperature, float bloodLevel, bool? scanMode, bool? bleeding)
public HealthAnalyzerScannedUserMessage(NetEntity? targetEntity, float temperature, float bloodLevel, bool? scanMode, bool? bleeding, bool? unrevivable)
{
TargetEntity = targetEntity;
Temperature = temperature;
BloodLevel = bloodLevel;
ScanMode = scanMode;
Bleeding = bleeding;
Unrevivable = unrevivable;
}
}

Binary file not shown.

View File

@ -181,3 +181,8 @@
license: "CC0-1.0"
copyright: "by ScarKy0"
source: "https://github.com/space-wizards/space-station-14/pull/32012"
- files: ["ame_fuelinjection.ogg"]
license: "CC0-1.0"
copyright: "by AftrLite (Github). Uses audio from hypospray.ogg and hiss.ogg (Found in Resources/Audio/Items)"
source: "https://github.com/space-wizards/space-station-14/pull/33097"

View File

@ -567,5 +567,28 @@ Entries:
id: 70
time: '2024-10-16T22:24:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32844
- author: BramvanZijp
changes:
- message: CC, ERT, Admin, and Deathsquad PDA's now have all departmental programs
pre-installed.
type: Tweak
id: 71
time: '2024-10-31T14:53:38.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32601
- author: metalgearsloth
changes:
- message: Added on-call functionality for discord relay to get notified on unanswered
ahelps.
type: Add
id: 72
time: '2024-11-02T09:29:16.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30443
- author: nikthechampiongr
changes:
- message: It is now possible to edit the AI's laws through its core and eye.
type: Fix
id: 73
time: '2024-11-02T13:21:10.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32461
Name: Admin
Order: 3

View File

@ -1,271 +1,4 @@
Entries:
- author: Errant
changes:
- message: Medical Mask sprite now works on vox.
type: Fix
id: 7052
time: '2024-08-07T03:41:40.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30702
- author: Lyroth001
changes:
- message: Dragons are immune to flashes
type: Tweak
id: 7053
time: '2024-08-07T07:42:00.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30658
- author: ShadowCommander
changes:
- message: Rollerbeds can now be dragged to the player to fold and pick them up.
type: Add
id: 7054
time: '2024-08-07T09:19:10.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30002
- author: Errant
changes:
- message: Survivors arriving via the Unknown Shuttle event, ERT and CBURN agents,
and Death Squad members are now equipped with the appropriate species-specific
survival gear.
type: Fix
- message: Unknown Shuttle event can once again spawn vox characters.
type: Tweak
id: 7055
time: '2024-08-07T09:26:40.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29746
- author: IProduceWidgets
changes:
- message: butter is slippery
type: Tweak
id: 7056
time: '2024-08-07T21:47:03.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29772
- author: Mervill
changes:
- message: Gas Miners now have detailed examine text
type: Tweak
id: 7057
time: '2024-08-08T02:14:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30480
- author: BackeTako
changes:
- message: "!, \u203D and multiple punctuations now work for Spanish."
type: Tweak
id: 7058
time: '2024-08-08T03:08:28.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30551
- author: strO0pwafel
changes:
- message: Fixed inconsistent naming of CentComm.
type: Fix
id: 7059
time: '2024-08-08T10:04:20.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29217
- author: Plykiya
changes:
- message: Buffed the range of EMP implants from a radius of 1.75 tiles to 2.75
tiles.
type: Tweak
- message: Buffed the range of EMP grenades from a radius of 4 tiles to 5.5 tiles.
type: Tweak
id: 7060
time: '2024-08-08T10:04:50.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30660
- author: Plykiya
changes:
- message: You can drop food or drinks from your hands to interrupt eating it, again.
type: Fix
- message: Barber scissors are now interrupted if the item is dropped or if the
user changes hands.
type: Tweak
id: 7061
time: '2024-08-08T11:39:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30361
- author: TheShuEd
changes:
- message: Add "thieving beacon" to Thief antag - a device that counts objects within
a radius of itself as stolen.
type: Add
- message: Return thief structures stealing objectives.
type: Add
- message: Animal theft objectives can no longer appear if the animals are not on
the station.
type: Fix
id: 7062
time: '2024-08-08T13:17:50.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29997
- author: lzk228
changes:
- message: RD labcoat added in RD's dresser.
type: Add
id: 7063
time: '2024-08-08T22:50:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30671
- author: SlamBamActionman
changes:
- message: Animal DNA now shows up as "unknown DNA" in the Forensic Scanner.
type: Tweak
- message: Forensic Scanner can now scan fluid containers for DNA in reagents.
type: Tweak
- message: Fluids keep their DNA data when moved.
type: Fix
- message: Fluids now stain containers they're in with DNA. Make sure to scrub your
blood bucket after use!
type: Add
- message: Vomit now includes DNA!
type: Add
id: 7064
time: '2024-08-08T23:27:28.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26699
- author: themias
changes:
- message: Butter can be sliced, cookie and toast recipes now use butter slices.
type: Tweak
- message: Chefvend butter reduced from 4 to 3.
type: Tweak
id: 7065
time: '2024-08-08T23:32:42.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30789
- author: EmoGarbage404
changes:
- message: You should have significantly less friction when moving in space.
type: Tweak
id: 7066
time: '2024-08-09T04:52:25.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29383
- author: Plykiya
changes:
- message: Hardsuits and EVA suits now count as protection for unscrewing lightbulbs.
type: Add
- message: More gloves were given the ability to unscrew light bulbs.
type: Add
- message: Behonkers no longer hurt you when melee attacking them or interacting
with them.
type: Remove
id: 7067
time: '2024-08-09T05:32:41.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30244
- author: Ian321
changes:
- message: The warden is now an important job.
type: Tweak
id: 7068
time: '2024-08-09T05:45:51.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30745
- author: slarticodefast
changes:
- message: Added tooltips to the agent ID job icons
type: Add
id: 7069
time: '2024-08-09T06:14:07.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28575
- author: stalengd
changes:
- message: Head bandana no longer blocks food eating.
type: Fix
id: 7070
time: '2024-08-09T06:17:51.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28910
- author: Ubaser
changes:
- message: Oxygen and nitrogen canisters now have new sprites when worn.
type: Add
id: 7071
time: '2024-08-09T10:32:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30809
- author: Plykiya
changes:
- message: Buckling someone now triggers a short do-after.
type: Tweak
id: 7072
time: '2024-08-09T15:43:02.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29621
- author: Ubaser
changes:
- message: Normal crowbars cannot be placed in pockets, but can now fit in belts.
type: Tweak
- message: Depending on where you obtained the crowbars, they will now have different
colours.
type: Tweak
id: 7073
time: '2024-08-09T19:29:00.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28988
- author: lzk228
changes:
- message: Hotplate works again.
type: Fix
id: 7074
time: '2024-08-10T01:10:39.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30830
- author: EmoGarbage404
changes:
- message: Maintenance closets have more variety in what they can contain.
type: Tweak
id: 7075
time: '2024-08-10T02:12:40.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30579
- author: Ko4erga
changes:
- message: Changed chemistry airlock color.
type: Tweak
id: 7076
time: '2024-08-10T03:23:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30666
- author: Blackern5000
changes:
- message: Bent pipes now deal 8 thrown damage instead of 3.
type: Tweak
id: 7077
time: '2024-08-10T03:30:43.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30634
- author: shampunj
changes:
- message: Rat king can now wideswing
type: Tweak
id: 7078
time: '2024-08-10T12:47:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30808
- author: BackeTako
changes:
- message: Added a suitskirt for the psychologist
type: Add
id: 7079
time: '2024-08-10T12:51:54.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30709
- author: Unkn0wnGh0st333
changes:
- message: ERT Chaplain starting gear was fixed and will no longer give the ERT
Engineer gear
type: Fix
id: 7080
time: '2024-08-10T12:55:20.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30855
- author: Ubaser
changes:
- message: Light tube structures now have new sprites.
type: Tweak
id: 7081
time: '2024-08-10T15:00:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29091
- author: lzk228
changes:
- message: Standartized some clothing recipes.
type: Tweak
id: 7082
time: '2024-08-10T18:16:56.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29315
- author: TheShuEd
changes:
- message: You cat cut burger bun into two halfs, and make custom burgers now!
type: Add
id: 7083
time: '2024-08-10T19:31:32.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30755
- author: thetolbean
changes:
- message: Updated Core's boxing ring beacon label to be correct
type: Tweak
id: 7084
time: '2024-08-10T19:50:08.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30800
- author: Flareguy
changes:
- message: Added vox sprites for most of the remaining common mask items.
@ -3927,3 +3660,264 @@
id: 7551
time: '2024-10-24T03:41:03.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32965
- author: slarticodefast
changes:
- message: Mix 1u aluminium, 1u potassium and 1u sulfur for a flash reaction effect.
The radius scales with the reagent amount.
type: Add
id: 7552
time: '2024-10-25T22:47:12.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32377
- author: BramvanZijp
changes:
- message: Fixed the Lone Nuclear Operative mid-round antagonist being extremely
rare.
type: Fix
id: 7553
time: '2024-10-26T02:16:45.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32942
- author: Moomoobeef
changes:
- message: Bowls no longer make an eating sound when drinking from them.
type: Fix
id: 7554
time: '2024-10-26T04:00:49.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32819
- author: SaphireLattice
changes:
- message: Added a warning about unrevivability in the health analyzer UI.
type: Add
id: 7555
time: '2024-10-26T17:22:09.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32636
- author: slarticodefast
changes:
- message: Fixed pie throwing sound not playing.
type: Fix
id: 7556
time: '2024-10-27T04:25:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33017
- author: stalengd
changes:
- message: Fixed playtime labels not being able to correctly display time greater
than 24 hours
type: Fix
id: 7557
time: '2024-10-28T18:00:00.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32974
- author: august-sun
changes:
- message: Extended the minimum round time for meteor swarm events.
type: Tweak
id: 7558
time: '2024-10-28T21:25:34.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32876
- author: deltanedas
changes:
- message: Fixed lava planet expeditions not working.
type: Fix
id: 7559
time: '2024-10-29T05:00:29.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33042
- author: metalgearsloth
changes:
- message: Fix separated game screen bumping slightly.
type: Fix
id: 7560
time: '2024-10-29T05:07:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33046
- author: Blackern5000
changes:
- message: Proto-kitentic crushers, glaives, and daggers now have more accurate
inhand sprites.
type: Tweak
id: 7561
time: '2024-10-30T07:38:19.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32212
- author: Blackern5000
changes:
- message: Security belts now contain a holobarrier projector and a handheld security
radio by default rather than tear gas and a flashbang.
type: Tweak
id: 7562
time: '2024-10-30T07:40:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32291
- author: Blackern5000
changes:
- message: Added three bottle boxes to the nanomed plus inventory for doctors to
carry small amounts of chemicals on their person
type: Add
id: 7563
time: '2024-10-30T07:41:51.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33018
- author: Blackern5000
changes:
- message: Added the interdyne defibrillator, a black-and-red defibrillator that
can be used as a melee weapon.
type: Add
- message: The syndicate medical bundle now contains an interdyne defibrillator,
a collection of various instant injectors, tourniquets, and several combat kits.
The price has been raised to 24 tc.
type: Tweak
id: 7564
time: '2024-10-30T09:15:30.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32720
- author: Boaz1111
changes:
- message: Pill bottles can now only store pills.
type: Tweak
id: 7565
time: '2024-10-31T10:56:07.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33074
- author: Jarmer123
changes:
- message: You can now find a spare bible in the PietyVend
type: Add
id: 7566
time: '2024-10-31T13:26:46.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32363
- author: justinbrick
changes:
- message: Added a pop-up notification when extra items are dropped while unequipping
something.
type: Tweak
id: 7567
time: '2024-10-31T14:12:26.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33078
- author: BramvanZijp
changes:
- message: The maximum amount of programs that can be installed on a PDA has been
increased from 5 to 8
type: Tweak
- message: The Detective and Head of Security now get the logprobe program pre-installed
on their PDA.
type: Tweak
id: 7568
time: '2024-10-31T14:53:38.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32601
- author: Psychpsyo
changes:
- message: Carp plushies can now be placed in mop buckets, along with other rehydratable
things like monkey cubes.
type: Add
id: 7569
time: '2024-10-31T18:46:19.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33079
- author: Bhijn and Myr
changes:
- message: Tail thumping has been downmixed to mono to fix the sound lacking any
sort of positioning. They're now capable of having a presence in the actual
soundspace, in turn meaning lizards are no longer occupying your headset at
all times of day.
type: Fix
id: 7570
time: '2024-10-31T21:30:58.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33092
- author: reesque
changes:
- message: pie not dropping tin on thrown
type: Fix
id: 7571
time: '2024-11-01T01:43:11.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33013
- author: SlamBamActionman
changes:
- message: Votekicks can now be initiated during the pregame lobby.
type: Fix
id: 7572
time: '2024-11-01T01:52:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32528
- author: PopGamer46
changes:
- message: Fixed bolt lights of recently unpowered bolted doors
type: Fix
id: 7573
time: '2024-11-01T02:04:09.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33063
- author: RumiTiger
changes:
- message: A chocolate and banana muffin has been added to the game. The berry and
cherry muffins have also been resprited!
type: Add
- message: Now you can make a regular, chocolate, banana, and berry muffin!
type: Tweak
- message: Muffin tins have been added to the game. They are needed for making muffins!
type: Add
id: 7574
time: '2024-11-01T02:06:46.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29318
- author: ScarKy0
changes:
- message: AI can no longer toggle seeing jobs off.
type: Tweak
- message: Borgs can no longer see mindshield status.
type: Fix
id: 7575
time: '2024-11-01T02:32:28.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33069
- author: Minemoder5000
changes:
- message: The cargo shuttle's cargo pallets can no longer sell or buy.
type: Fix
id: 7576
time: '2024-11-01T06:22:39.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33022
- author: aspiringLich
changes:
- message: Fixed the logic triggering popups when inserting items into machines.
type: Fix
id: 7577
time: '2024-11-02T01:33:26.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28856
- author: K-Dynamic
changes:
- message: Pills are explosion resistant.
type: Tweak
id: 7578
time: '2024-11-02T09:51:45.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32458
- author: K-Dynamic
changes:
- message: Handcrafted gauze now takes 3 seconds instead of 10 seconds of crafting
type: Tweak
- message: Medical techfab gauze recipe now takes 1 cloth instead of 2
type: Tweak
id: 7579
time: '2024-11-02T09:53:19.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32744
- author: Ubaser
changes:
- message: Service workers can now be antagonists.
type: Fix
id: 7580
time: '2024-11-02T10:07:52.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31359
- author: AftrLite
changes:
- message: The AME now has a new sound effect for fuel injection!
type: Add
id: 7581
time: '2024-11-02T13:19:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33097
- author: deltanedas
changes:
- message: Printing cables in an autolathe is now 20 times faster.
type: Tweak
id: 7582
time: '2024-11-02T13:24:08.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31521
- author: Centronias
changes:
- message: Fixed a bug where attempting to speak into a handheld radio and an intercom
simultaneously would lead to only one device transmitting the message.
type: Fix
id: 7583
time: '2024-11-02T15:04:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32737
- author: joshepvodka
changes:
- message: Headphones are now selectable in loadouts.
type: Add
id: 7584
time: '2024-11-02T15:12:26.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33067

View File

@ -37,6 +37,12 @@ reagent-effect-guidebook-emp-reaction-effect =
*[other] cause
} an electromagnetic pulse
reagent-effect-guidebook-flash-reaction-effect =
{ $chance ->
[1] Causes
*[other] cause
} a blinding flash
reagent-effect-guidebook-foam-area-reaction-effect =
{ $chance ->
[1] Creates

View File

@ -2,3 +2,9 @@ inventory-component-can-equip-cannot = You can't equip this!
inventory-component-can-equip-does-not-fit = This doesn't fit!
inventory-component-can-unequip-cannot = You can't unequip this!
inventory-component-dropped-from-unequip =
You dropped {$items ->
[1] an item!
*[other] some items!
}

View File

@ -1,5 +1,6 @@
# mop bucket
mop-bucket-slot-component-slot-name-shark = Shark
mop-bucket-slot-component-slot-name-item = Item
mop-bucket-slot-component-eject-verb = Take out
# janitorial trolley
janitorial-trolley-slot-component-slot-name-plunger = Plunger
janitorial-trolley-slot-component-slot-name-sign = Sign

View File

@ -15,7 +15,8 @@ health-analyzer-window-entity-damage-total-text = Total Damage:
health-analyzer-window-damage-group-text = {$damageGroup}: {$amount}
health-analyzer-window-damage-type-text = {$damageType}: {$amount}
health-analyzer-window-entity-bleeding-text = Patient is bleeding!
health-analyzer-window-entity-unrevivable-text = [color=red]Unique body composition detected! Patient can not be resuscitated by normal means![/color]
health-analyzer-window-entity-bleeding-text = [color=red]Patient is bleeding![/color]
health-analyzer-window-scan-mode-text = Scan Mode:
health-analyzer-window-scan-mode-active = Active

View File

@ -218,8 +218,8 @@ uplink-chemistry-kit-desc = A starter kit for the aspiring chemist, includes tox
uplink-knives-kit-name = Throwing Knives Kit
uplink-knives-kit-desc = A set of 4 syndicate branded throwing knives, perfect for embedding into the body of your victims.
uplink-meds-bundle-name = Medical Bundle
uplink-meds-bundle-desc = All you need to get your comrades back in the fight: mainly a combat medkit, a defibrillator and three combat medipens.
uplink-meds-bundle-name = Interdyne Medical Bundle
uplink-meds-bundle-desc = An assortment of autoinjectors and premium medical equipment to cover for every possible situation. Contains an elite compact defibrillator that can be used as a weapon.
uplink-ammo-bundle-name = Ammo Bundle
uplink-ammo-bundle-desc = Reloading! Contains 4 magazines for the C-20r, 4 drums for the Bulldog, and 2 ammo boxes for the L6 SAW.

View File

@ -25,8 +25,8 @@ ui-vote-type-not-available = This vote type has been disabled
# Vote option only available for specific users.
ui-vote-trusted-users-notice =
This vote option is only available to whitelisted players.
In addition, you must have been a ghost for { $timeReq } minutes.
This vote option is only available to players who have enough playtime or are whitelisted.
In addition, you must have been a ghost for { $timeReq } seconds.
# Warning to not abuse a specific vote option.
ui-vote-abuse-warning =

View File

@ -2,13 +2,14 @@
# Shown when examining the window. Each entry represents the window's health condition
comp-window-damaged-1 = It looks fully intact.
comp-window-damaged-2 = It has a few scratches
comp-window-damaged-2 = It has a few scratches.
comp-window-damaged-3 = It has a few small cracks.
comp-window-damaged-4 = It has several big cracks running along its surface.
comp-window-damaged-5 = It has deep cracks across multiple layers.
comp-window-damaged-6 = It's extremely cracked and on the verge of shattering.
comp-window-damaged-4 = [color=yellow]It has several big cracks running along its surface.[/color]
comp-window-damaged-5 = [color=orange]It has deep cracks across multiple layers.[/color]
comp-window-damaged-6 = [color=red]It's extremely cracked and on the verge of shattering.[/color]
### Interaction Messages
# Shown when knocking on a window
comp-window-knock = *knock knock*

View File

@ -6576,7 +6576,7 @@ entities:
- uid: 2031
components:
- type: Transform
pos: 3.6114278,-10.732791
pos: 4.0109396,-12.223828
parent: 104
- uid: 2095
components:
@ -10993,6 +10993,13 @@ entities:
- type: Transform
pos: 11.5,-6.5
parent: 104
- proto: HandLabeler
entities:
- uid: 1826
components:
- type: Transform
pos: 3.4542694,-10.616036
parent: 104
- proto: KitchenKnife
entities:
- uid: 1061

File diff suppressed because it is too large Load Diff

View File

@ -5,35 +5,20 @@
description: Sends your eye back to the core.
components:
- type: InstantAction
priority: -10
priority: -9
itemIconStyle: BigAction
icon:
sprite: Interface/Actions/actions_ai.rsi
state: ai_core
event: !type:JumpToCoreEvent
- type: entity
id: ActionShowJobIcons
name: Show job icons
description: Shows job icons for crew members.
components:
- type: InstantAction
priority: -5
itemIconStyle: BigAction
icon:
sprite: Interface/Actions/actions_ai.rsi
state: job_view
event: !type:ActionComponentChangeEvent
components:
- type: ShowJobIcons
- type: entity
id: ActionSurvCameraLights
name: Toggle camera lights
description: Enable surveillance camera lights near wherever you're viewing.
components:
- type: InstantAction
priority: -6
priority: -5
itemIconStyle: BigAction
icon:
sprite: Interface/Actions/actions_ai.rsi

View File

@ -280,6 +280,8 @@
checkCanInteract: false
checkConsciousness: false
event: !type:WakeActionEvent
startDelay: true
useDelay: 2
- type: entity
id: ActionActivateHonkImplant

View File

@ -302,13 +302,19 @@
components:
- type: StorageFill
contents:
- id: DefibrillatorSyndicate
- id: MedkitCombatFilled
- id: Defibrillator
amount: 4
- id: Tourniquet
amount: 4
- id: CombatMedipen
amount: 3
- id: ClothingHandsGlovesNitrile
- id: SyringeTranexamicAcid
- id: SyringeHyronalin
amount: 4
- id: PunctAutoInjector
amount: 4
- id: PyraAutoInjector
amount: 4
- id: AirlossAutoInjector
amount: 4
- type: entity
parent: ClothingBackpackDuffelSyndicateBundle

View File

@ -46,10 +46,12 @@
table: !type:AllSelector
children:
- id: Stunbaton
- id: GrenadeFlashBang
- id: TearGasGrenade
- id: GrenadeFlashBang # DeltaV: revert upstream #32291
- id: TearGasGrenade # DeltaV
- id: Handcuffs
- id: Handcuffs
#- id: HoloprojectorSecurity # DeltaV
#- id: RadioHandheldSecurity # DeltaV
- type: entity
id: ClothingBeltSecurityFilled

View File

@ -20,7 +20,8 @@
BoxCandle: 2
BoxCandleSmall: 2
Urn: 5
SilverRing: 2 # Delta-V (Isn't the stuff above also deltav??)
Bible: 1
SilverRing: 2 # Delta-V
RingBox: 2 # Delta-V
emaggedInventory:
ClothingOuterArmorCult: 1

View File

@ -11,6 +11,7 @@
FoodPlate: 10
FoodPlateSmall: 10
FoodPlateTin: 5
FoodPlateMuffinTin: 5
FoodKebabSkewer: 5
DrinkGlass: 5
Beaker: 5

View File

@ -7,6 +7,7 @@
Bloodpack: 5
EpinephrineChemistryBottle: 3
Syringe: 5
BoxBottle: 3
Portafib: 1 # DeltaV - Add Portafibs, see Prototypes/DeltaV/Entities/Objects/Devices/Medical/portafib.yml
ClothingEyesHudMedical: 2
ClothingEyesEyepatchHudMedical: 2

View File

@ -699,9 +699,9 @@
productEntity: ClothingBackpackDuffelSyndicateMedicalBundleFilled
discountCategory: rareDiscounts
discountDownTo:
Telecrystal: 12
Telecrystal: 16
cost:
Telecrystal: 20
Telecrystal: 24
categories:
- UplinkChemicals
conditions:

View File

@ -219,7 +219,6 @@
- Howe
- Huey
- Hughes
- Hujsak
- Hunt
- Hunter
- Hussain

View File

@ -495,7 +495,6 @@
- CartridgeAmmo
- DoorRemote
- Whistle
- HolosignProjector
- BalloonPopper
- type: ItemMapper # DeltaV - adjust for DeltaV sprites.
mapLayers:

View File

@ -222,3 +222,16 @@
state: metal_foam-north
- map: [ "enum.EdgeLayer.West" ]
state: metal_foam-west
- type: entity
id: ReactionFlash
categories: [ HideSpawnMenu ]
components:
- type: PointLight
enabled: true
radius: 2
energy: 8
- type: LightFade
duration: 0.5
- type: TimedDespawn
lifetime: 0.5

View File

@ -46,6 +46,8 @@
- FoodBakedMuffinBerry
- FoodBakedMuffinCherry
- FoodBakedMuffinBluecherry
- FoodBakedMuffinChocolate
- FoodBakedMuffinBanana
- FoodBakedBunHoney
- FoodBakedBunHotX
- FoodBakedBunMeat

View File

@ -289,7 +289,6 @@
- type: AccessReader
access: [["Command"], ["Research"]]
- type: ShowJobIcons
- type: ShowMindShieldIcons
- type: entity
id: BaseBorgChassisSyndicate

View File

@ -133,7 +133,7 @@
icon: { sprite: Interface/Actions/actions_ai.rsi, state: mass_scanner }
iconOn: Interface/Actions/actions_ai.rsi/mass_scanner.png
keywords: [ "AI", "console", "interface" ]
priority: -7
priority: -6
event: !type:ToggleIntrinsicUIEvent { key: enum.RadarConsoleUiKey.Key }
- type: entity
@ -157,7 +157,7 @@
icon: { sprite: Interface/Actions/actions_ai.rsi, state: crew_monitor }
iconOn: Interface/Actions/actions_ai.rsi/crew_monitor.png
keywords: [ "AI", "console", "interface" ]
priority: -9
priority: -8
event: !type:ToggleIntrinsicUIEvent { key: enum.CrewMonitoringUIKey.Key }
- type: entity
@ -169,5 +169,5 @@
icon: { sprite: Interface/Actions/actions_ai.rsi, state: station_records }
iconOn: Interface/Actions/actions_ai.rsi/station_records.png
keywords: [ "AI", "console", "interface" ]
priority: -8
priority: -7
event: !type:ToggleIntrinsicUIEvent { key: enum.GeneralStationRecordConsoleKey.Key }

View File

@ -84,6 +84,7 @@
icon: Interface/Actions/scream.png
checkCanInteract: false
event: !type:BooActionEvent
startDelay: true
useDelay: 120
- type: entity

View File

@ -33,7 +33,6 @@
- type: ActionGrant
actions:
- ActionJumpToCore
- ActionShowJobIcons
- ActionSurvCameraLights
- ActionAIViewLaws
- type: UserInterface
@ -70,6 +69,9 @@
canShuttle: false
title: comms-console-announcement-title-station-ai
color: "#2ed2fd"
- type: Speech
speechVerb: Robotic
- type: ShowJobIcons
- type: entity
id: AiHeldIntellicard

View File

@ -19,44 +19,84 @@
- type: Item
size: Tiny
# Muffins/Buns
# Muffins
- type: entity
name: muffin
parent: FoodBakedBase
parent: FoodInjectableBase
id: FoodBakedMuffin
description: A delicious and spongy little cake.
components:
- type: Food
trash:
- FoodPlateMuffinTin
- type: Sprite
sprite: Objects/Consumable/Food/Baked/misc.rsi
state: muffin
- type: SolutionContainerManager
solutions:
food:
maxVol: 10
reagents:
- ReagentId: Nutriment
Quantity: 6
- ReagentId: Vitamin
Quantity: 2
- type: FlavorProfile
flavors:
- sweet
- type: Item
size: Tiny
- type: entity
name: berry muffin
parent: FoodBakedBase
parent: FoodBakedMuffin
id: FoodBakedMuffinBerry
description: A delicious and spongy little cake, with berries.
components:
- type: Sprite
state: muffin-berry
- type: SolutionContainerManager
solutions:
food:
maxVol: 12
reagents:
- ReagentId: Nutriment
Quantity: 6
- ReagentId: Vitamin
Quantity: 2
- ReagentId: JuiceBerry
Quantity: 2
- type: Tag
tags:
- Fruit
- type: entity
name: cherry muffin
parent: FoodBakedBase
parent: FoodBakedMuffin
id: FoodBakedMuffinCherry
description: A sweet muffin with cherry bits.
components:
- type: Sprite
state: muffin-cherry
- type: SolutionContainerManager
solutions:
food:
maxVol: 12
reagents:
- ReagentId: Nutriment
Quantity: 6
- ReagentId: Vitamin
Quantity: 2
- ReagentId: JuiceCherry
Quantity: 2
- type: Tag
tags:
- Fruit
- type: entity
name: bluecherry muffin
parent: FoodBakedBase
parent: FoodBakedMuffin
id: FoodBakedMuffinBluecherry
description: Blue cherries inside a delicious muffin.
components:
@ -66,6 +106,51 @@
tags:
- Fruit
- type: entity
name: chocolate muffin
parent: FoodBakedMuffin
id: FoodBakedMuffinChocolate
description: A delicious and spongy chocolate muffin.
components:
- type: Sprite
state: muffin-chocolate
- type: SolutionContainerManager
solutions:
food:
maxVol: 12
reagents:
- ReagentId: Nutriment
Quantity: 6
- ReagentId: Vitamin
Quantity: 2
- ReagentId: CocoaPowder
Quantity: 2
- type: entity
name: banana muffin
parent: FoodBakedMuffin
id: FoodBakedMuffinBanana
description: A delicious and spongy banana muffin.
components:
- type: Sprite
state: muffin-banana
- type: SolutionContainerManager
solutions:
food:
maxVol: 12
reagents:
- ReagentId: Nutriment
Quantity: 6
- ReagentId: Vitamin
Quantity: 2
- ReagentId: JuiceBanana
Quantity: 2
- type: Tag
tags:
- Fruit
# Buns
- type: entity
name: honey bun #TODO honey
parent: FoodBakedBase

View File

@ -21,6 +21,10 @@
visible: false
- type: MixableSolution
solution: food
- type: Drink
solution: food
useSound:
path: /Audio/Items/drink.ogg
- type: DamageOnLand
damage:
types:

View File

@ -178,3 +178,27 @@
materialComposition:
Steel: 60
- type: SpaceGarbage
# Muffin Tin
- type: entity
name: muffin tin
parent: BaseItem
id: FoodPlateMuffinTin
description: A cheap foil tin for muffins.
components:
- type: Sprite
sprite: Objects/Consumable/Food/plates.rsi
state: muffin-tin
- type: Item
size: Small
shape:
- 0,0,1,0
storedOffset: 0,-3
- type: Tag
tags:
- Trash
- type: PhysicalComposition
materialComposition:
Steel: 30
- type: SpaceGarbage

View File

@ -121,6 +121,7 @@
- type: Tag
tags:
- HolofanProjector
- SecBeltEquip
- type: StaticPrice
price: 50

View File

@ -730,6 +730,14 @@
accentHColor: "#447987"
- type: Icon
state: pda-hos
- type: CartridgeLoader
preinstalled:
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- CrimeAssistCartridge # DeltaV
- SecWatchCartridge # DeltaV: SecWatch replaces WantedList
- LogProbeCartridge
- type: entity
parent: BaseSecurityPDA
@ -778,6 +786,16 @@
borderColor: "#00842e"
- type: Icon
state: pda-centcom
- type: CartridgeLoader
uiKey: enum.PdaUiKey.Key
preinstalled:
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- MedTekCartridge
- SecWatchCartridge # DeltaV: SecWatch replaces WantedList
- LogProbeCartridge
- AstroNavCartridge
- type: entity
parent: CentcomPDA
@ -799,6 +817,9 @@
- NotekeeperCartridge
- NewsReaderCartridge
- LogProbeCartridge
- SecWatchCartridge # DeltaV: SecWatch replaces WantedList
- MedTekCartridge
- AstroNavCartridge
- StockTradingCartridge # Delta-V
- type: entity
@ -893,14 +914,6 @@
uiKey: enum.PdaUiKey.Key
preinstalled:
- NotekeeperCartridge
cartridgeSlot:
priority: -1
name: Cartridge
ejectSound: /Audio/Machines/id_swipe.ogg
insertSound: /Audio/Machines/id_insert.ogg
whitelist:
components:
- Cartridge
- type: entity
parent: BaseSecurityPDA
@ -918,6 +931,16 @@
accentVColor: "#447987"
- type: Icon
state: pda-ert
- type: CartridgeLoader
uiKey: enum.PdaUiKey.Key
preinstalled:
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- MedTekCartridge
- SecWatchCartridge # DeltaV: SecWatch replaces WantedList
- LogProbeCartridge
- AstroNavCartridge
- type: entity
parent: ERTLeaderPDA
@ -958,14 +981,6 @@
components:
- type: Pda
id: ERTMedicIDCard
- type: CartridgeLoader
uiKey: enum.PdaUiKey.Key
preinstalled:
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- MedTekCartridge
- SecWatchCartridge # DeltaV: SecWatch replaces wantedList
- type: entity
parent: ERTLeaderPDA
@ -1073,6 +1088,14 @@
borderColor: "#774705"
- type: Icon
state: pda-detective
- type: CartridgeLoader
preinstalled:
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- CrimeAssistCartridge # DeltaV
- SecWatchCartridge # DeltaV: SecWatch replaces WantedList
- LogProbeCartridge
- type: entity
parent: BaseMedicalPDA
@ -1089,14 +1112,14 @@
accentVColor: "#d7d7d0"
- type: Icon
state: pda-brigmedic
- type: CartridgeLoader # DeltaV - Crime Assist + SecWatch, increased diskSpace by 2 to fit them
diskSpace: 7
- type: CartridgeLoader
preinstalled:
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- CrimeAssistCartridge
- SecWatchCartridge
- CrewManifestCartridge
- NotekeeperCartridge
- NewsReaderCartridge
- CrimeAssistCartridge # DeltaV
- SecWatchCartridge # DeltaV: SecWatch replaces WantedList
- MedTekCartridge
- type: entity
parent: ClownPDA
@ -1213,11 +1236,3 @@
preinstalled:
- NotekeeperCartridge
- MedTekCartridge
cartridgeSlot:
priority: -1
name: Cartridge
ejectSound: /Audio/Machines/id_swipe.ogg
insertSound: /Audio/Machines/id_insert.ogg
whitelist:
components:
- Cartridge

View File

@ -35,6 +35,7 @@
damage:
types:
Blunt: 0
hidden: true
- type: PhysicalComposition
materialComposition:
Cloth: 100
@ -600,7 +601,9 @@
animation: WeaponArcBite # Rrrr!
- type: Tag
tags:
- PlushieCarp # DeltaV - fish labeler craft
- Payload
- ClothMade
- PlushieCarp
- type: entity
parent: PlushieCarp

View File

@ -20,8 +20,6 @@
density: 15
mask:
- MachineMask
- type: CargoPallet
palletType: All
- type: StaticPrice
price: 100
- type: Sprite

View File

@ -71,3 +71,69 @@
id: DefibrillatorOneHandedUnpowered
parent: BaseDefibrillator
suffix: One-Handed, Unpowered
- type: entity
id: DefibrillatorCompact # This should be a research item at some point
parent: [ BaseDefibrillator, PowerCellSlotMediumItem ]
name: compact defibrillator
description: Now in fun size!
components:
- type: Sprite
sprite: Objects/Specific/Medical/defibsmall.rsi
layers:
- state: icon
- state: screen
map: [ "enum.ToggleVisuals.Layer" ]
visible: false
shader: unshaded
- state: ready
map: ["enum.PowerDeviceVisualLayers.Powered"]
shader: unshaded
- type: Item
size: Normal
- type: ToggleCellDraw
- type: PowerCellDraw
useRate: 100
- type: Defibrillator
zapHeal:
types:
Asphyxiation: -40
doAfterDuration: 6
- type: DoAfter
- type: UseDelay
- type: entity
id: DefibrillatorSyndicate
parent: DefibrillatorCompact
name: interdyne defibrillator
description: Doubles as a self-defense weapon against war-crime inclined tiders.
components:
- type: Sprite
sprite: Objects/Specific/Medical/defibsyndi.rsi
layers:
- state: icon
- state: screen
map: [ "enum.ToggleVisuals.Layer" ]
visible: false
shader: unshaded
- state: ready
map: ["enum.PowerDeviceVisualLayers.Powered"]
shader: unshaded
- type: MeleeWeapon
damage:
types:
Blunt: 8
- type: ItemToggleMeleeWeapon
activatedSoundOnHit:
path: /Audio/Items/Defib/defib_zap.ogg
params:
variation: 0.250
activatedSoundOnHitNoDamage:
path: /Audio/Items/Defib/defib_zap.ogg
params:
variation: 0.250
volume: -10
activatedDamage:
types:
Blunt: 8
Shock: 16

View File

@ -271,7 +271,6 @@
transferAmount: 20
onlyAffectsMobs: false
injectOnly: true
- type: SolutionContainerManager
solutions:
pen:
@ -284,6 +283,102 @@
- type: Tag
tags: []
- type: entity
name: puncturase auto-injector
parent: ChemicalMedipen
id: PunctAutoInjector
description: A rapid dose of puncturase and tranexamic acid, intended for combat applications.
components:
- type: Sprite
sprite: Objects/Specific/Medical/medipen.rsi
layers:
- state: punctpen
map: ["enum.SolutionContainerLayers.Fill"]
- type: SolutionContainerVisuals
maxFillLevels: 1
changeColor: false
emptySpriteName: punctpen_empty
- type: Hypospray
solutionName: pen
transferAmount: 15
onlyAffectsMobs: false
injectOnly: true
- type: SolutionContainerManager
solutions:
pen:
maxVol: 15
reagents:
- ReagentId: Puncturase
Quantity: 10
- ReagentId: TranexamicAcid
Quantity: 5
- type: Tag
tags: []
- type: entity
name: pyrazine auto-injector
parent: ChemicalMedipen
id: PyraAutoInjector
description: A rapid dose of pyrazine and dermaline, intended for combat applications.
components:
- type: Sprite
sprite: Objects/Specific/Medical/medipen.rsi
layers:
- state: pyrapen
map: ["enum.SolutionContainerLayers.Fill"]
- type: SolutionContainerVisuals
maxFillLevels: 1
changeColor: false
emptySpriteName: pyrapen_empty
- type: Hypospray
solutionName: pen
transferAmount: 20
onlyAffectsMobs: false
injectOnly: true
- type: SolutionContainerManager
solutions:
pen:
maxVol: 20
reagents:
- ReagentId: Pyrazine
Quantity: 10
- ReagentId: Dermaline
Quantity: 10
- type: Tag
tags: []
- type: entity
name: airloss auto-injector
parent: ChemicalMedipen
id: AirlossAutoInjector
description: A rapid dose of saline and dexalin plus, intended to get someone up quickly.
components:
- type: Sprite
sprite: Objects/Specific/Medical/medipen.rsi
layers:
- state: dexpen
map: ["enum.SolutionContainerLayers.Fill"]
- type: SolutionContainerVisuals
maxFillLevels: 1
changeColor: false
emptySpriteName: dexpen_empty
- type: Hypospray
solutionName: pen
transferAmount: 40
onlyAffectsMobs: false
injectOnly: true
- type: SolutionContainerManager
solutions:
pen:
maxVol: 40
reagents:
- ReagentId: Saline
Quantity: 20
- ReagentId: DexalinPlus
Quantity: 20
- type: Tag
tags: []
- type: entity
name: space medipen
parent: ChemicalMedipen

View File

@ -550,12 +550,8 @@
solutions:
food:
maxVol: 20
- type: SolutionSpiker
sourceSolution: food
- type: Extractable
grindableSolutionName: food
- type: StaticPrice
price: 0
- type: ExplosionResistance
damageCoefficient: 0.025 # survives conventional explosives but not minibombs and nukes
- type: Damageable
damageContainer: Inorganic
- type: Destructible
@ -568,6 +564,12 @@
solution: food
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: SolutionSpiker
sourceSolution: food
- type: Extractable
grindableSolutionName: food
- type: StaticPrice
price: 0
- type: Tag
tags:
- Pill
@ -588,9 +590,6 @@
tags:
- PillCanister
- type: Storage
whitelist: # DeltaV - Remove the ability to store anything other than pills in pill canisters
tags:
- Pill
grid:
- 0,0,4,1
quickInsert: true
@ -598,4 +597,7 @@
areaInsertRadius: 1
storageInsertSound: /Audio/Effects/pill_insert.ogg
storageRemoveSound: /Audio/Effects/pill_remove.ogg
whitelist:
tags:
- Pill
- type: Dumpable

View File

@ -209,8 +209,9 @@
handle: false
sound:
path: /Audio/Effects/bite.ogg
- type: Tag
tags: [] # DeltaV - remove PlushieCarp tag to prevent wasting
- type: Tag # DeltaV - remove PlushieCarp and ClothMade tag to prevent wasting/eating
tags:
- Payload
- type: entity #why is this all redefined down here as a parent of base object instead of just being parented to monkeycube?? TODO: Fix this shit
parent: BaseItem

View File

@ -1,4 +1,4 @@
- type: entity
- type: entity
id: WeaponWaterGunBase
abstract: true
parent: BaseItem
@ -71,7 +71,7 @@
id: WeaponWaterBlaster
parent: WeaponWaterGunBase
name: water blaster
description: With this bad boy, you'll be the cooleste kid at the summer barbecue.
description: With this bad boy, you'll be the coolest kid at the summer barbecue.
components:
- type: Gun
cameraRecoilScalar: 0 #no recoil

View File

@ -153,6 +153,7 @@
- type: GunRequiresWield
- type: Item
size: Ginormous
sprite: Objects/Weapons/Melee/crusher-inhands.rsi
- type: DisarmMalus
- type: Prying
@ -195,3 +196,6 @@
- type: Tag
tags:
- Pickaxe
- type: Item
size: Ginormous
sprite: Objects/Weapons/Melee/crusher_glaive-inhands.rsi

View File

@ -163,6 +163,7 @@
- FoodPlateSmallPlastic
- FoodBowlBig
- FoodPlateTin
- FoodPlateMuffinTin
- FoodKebabSkewer
- SprayBottle
- MopItem

View File

@ -113,6 +113,14 @@
- type: GasMiner
spawnGas: Tritium
- type: entity
name: frezon gas miner
parent: GasMinerBase
id: GasMinerFrezon
components:
- type: GasMiner
spawnGas: Frezon
- type: entity
name: water vapor gas miner
parent: GasMinerBase

View File

@ -47,19 +47,30 @@
whitelist:
tags:
- PlushieSharkGrey
sprite: Objects/Fun/sharkplush.rsi
mopbucket_carpplush:
whitelist:
tags:
- PlushieCarp
sprite: Objects/Specific/Janitorial/janitorial.rsi
- type: Transform
noRot: true
- type: ItemSlots
slots:
shark_slot:
name: mop-bucket-slot-component-slot-name-shark
item_slot:
name: mop-bucket-slot-component-slot-name-item
ejectVerbText: mop-bucket-slot-component-eject-verb
whitelist:
tags:
- PlushieSharkBlue
- PlushieSharkPink
- PlushieSharkGrey
- PlushieCarp
components:
- Rehydratable
priority: 3 # Higher than drinking priority
- type: ReactiveContainer
solution: bucket
container: item_slot
- type: Drink
solution: bucket
- type: Appearance
@ -70,7 +81,7 @@
containers:
storagebase: !type:Container
ents: []
shark_slot: !type:ContainerSlot {}
item_slot: !type:ContainerSlot {}
- type: GuideHelp
guides:
- Janitorial

View File

@ -29,7 +29,7 @@
isCollidableWhenOpen: false
openOnMove: false
airtight: false
capacity: 4 #4 Entities seems like a nice comfy fit for a cardboard box.
capacity: 5 #5 entity capacity to fit all of your friends (or teammates on your nuclear operation without reinforcements).
- type: ContainerContainer
containers:
entity_storage: !type:Container

View File

@ -64,8 +64,8 @@
canEditLabel: true
- type: TextScreenVisuals
color: FloralWhite
textOffset: 0,8
timerOffset: 0,8
textOffset: 0,6
timerOffset: 0,6
textLength: 5
rows: 1
- type: Sprite

View File

@ -39,6 +39,7 @@
- id: RevenantSpawn
- id: SleeperAgents
- id: ZombieOutbreak
- id: LoneOpsSpawn
- type: entity
id: BaseStationEvent
@ -457,7 +458,7 @@
duration: 1
- type: RuleGrids
- type: LoadMapRule
preloadedGrid: ShuttleStriker
mapPath: /Maps/Shuttles/ShuttleEvent/striker.yml
- type: NukeopsRule
roundEndBehavior: Nothing
- type: AntagSelection

View File

@ -57,7 +57,7 @@
components:
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 300 # 5 min
minimumTimeUntilFirstEvent: 600 # 10 min
minMaxEventTiming:
min: 750 # 12.5 min
max: 930 # 17.5 min
@ -70,7 +70,7 @@
components:
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 300 # 5 min
minimumTimeUntilFirstEvent: 600 # 10 min
minMaxEventTiming:
min: 750 # 12.5 min
max: 930 # 17.5 min

View File

@ -20,7 +20,6 @@
#- id: UnknownShuttleMeatZone
#- id: UnknownShuttleMicroshuttle
#- id: UnknownShuttleSpacebus
#- id: UnknownShuttleInstigator # DeltaV - remove random ops
- type: entityTable
id: UnknownShuttlesFreelanceTable
@ -33,10 +32,10 @@
- type: entityTable
id: UnknownShuttlesHostileTable
table: !type:AllSelector # we need to pass a list of rules, since rules have further restrictions to consider via StationEventComp
children:
- id: LoneOpsSpawn
children: [] # DeltaV: empty list to remove instigator
#- id: UnknownShuttleInstigator # DeltaV: remove random ops
# Shuttle Game Rules
# Shuttle Game Rules
- type: entity
abstract: true

View File

@ -21,6 +21,13 @@
back:
- ClothingHeadHatHairflower
# Headphones
- type: loadout
id: Headphones
storage:
back:
- ClothingNeckHeadphones
# Plushies
- type: loadout
id: PlushieLizard
@ -165,7 +172,7 @@
!type:OverallPlaytimeRequirement
time: 36000 # 10hr
storage:
back:
back:
- TowelColorWhite
- type: loadout
@ -176,9 +183,9 @@
!type:OverallPlaytimeRequirement
time: 1800000 # 500hr
storage:
back:
back:
- TowelColorSilver
- type: loadout
id: TowelColorGold
effects:
@ -187,7 +194,7 @@
!type:OverallPlaytimeRequirement
time: 3600000 # 1000hr
storage:
back:
back:
- TowelColorGold
- type: loadout
@ -199,7 +206,7 @@
department: Logistics # DeltaV: Logistics replaces Cargo
time: 360000 # 100hr
storage:
back:
back:
- TowelColorLightBrown
- type: loadout
@ -211,7 +218,7 @@
department: Civilian
time: 360000 # 100hr
storage:
back:
back:
- TowelColorGreen
- type: loadout
@ -223,7 +230,7 @@
department: Command
time: 360000 # 100hr
storage:
back:
back:
- TowelColorDarkBlue
- type: loadout
@ -235,9 +242,9 @@
department: Engineering
time: 360000 # 100hr
storage:
back:
back:
- TowelColorOrange
- type: loadout
id: TowelColorLightBlue
effects:
@ -247,7 +254,7 @@
department: Medical
time: 360000 # 100hr
storage:
back:
back:
- TowelColorLightBlue
- type: loadout
@ -259,7 +266,7 @@
department: Epistemics # DeltaV: Epistemics replaces Science
time: 360000 # 100hr
storage:
back:
back:
- TowelColorPurple
- type: loadout
@ -271,7 +278,7 @@
department: Security
time: 360000 # 100hr
storage:
back:
back:
- TowelColorRed
- type: loadout
@ -283,7 +290,7 @@
role: JobPassenger
time: 360000 # 100hr
storage:
back:
back:
- TowelColorGray
- type: loadout
@ -295,7 +302,7 @@
role: JobChaplain
time: 360000 # 100hr
storage:
back:
back:
- TowelColorBlack
- type: loadout
@ -307,7 +314,7 @@
role: JobLibrarian
time: 360000 # 100hr
storage:
back:
back:
- TowelColorDarkGreen
- type: loadout
@ -319,7 +326,7 @@
role: JobLawyer
time: 360000 # 100hr
storage:
back:
back:
- TowelColorMaroon
- type: loadout
@ -331,7 +338,7 @@
role: JobClown
time: 360000 # 100hr
storage:
back:
back:
- TowelColorYellow
- type: loadout
@ -343,5 +350,5 @@
role: JobMime
time: 360000 # 100hr
storage:
back:
back:
- TowelColorMime

View File

@ -7,6 +7,7 @@
loadouts:
- FlowerWreath
- Hairflower
- Headphones
- PlushieLizard
- PlushieSpaceLizard
- Lighter

View File

@ -12,6 +12,3 @@
- type: Tag
id: NormalityCrystal
- type: Tag
id: PlushieCarp

View File

@ -127,6 +127,8 @@
Junction: BaseAirlock
WallMounts: ScienceLabsWalls
Window: BaseWindow
tiles:
FallbackTile: FloorDark
whitelists:
Rooms:
tags:

View File

@ -1779,6 +1779,67 @@
FoodOrange: 1
FoodAmbrosiaVulgaris: 1
# Muffins
- type: microwaveMealRecipe
id: RecipeMuffin
name: muffin recipe
result: FoodBakedMuffin
time: 15
solids:
FoodPlateMuffinTin: 1
FoodDoughSlice: 1
reagents:
Sugar: 10
- type: microwaveMealRecipe
id: RecipeMuffinChocolate
name: chocolate muffin recipe
result: FoodBakedMuffinChocolate
time: 15
solids:
FoodPlateMuffinTin: 1
FoodDoughSlice: 1
FoodSnackChocolateBar: 1
reagents:
Sugar: 10
- type: microwaveMealRecipe
id: RecipeMuffinBerry
name: berry muffin recipe
result: FoodBakedMuffinBerry
time: 15
solids:
FoodPlateMuffinTin: 1
FoodDoughSlice: 1
FoodBerries: 1
reagents:
Sugar: 10
- type: microwaveMealRecipe
id: RecipeMuffinBanana
name: banana muffin recipe
result: FoodBakedMuffinBanana
time: 15
solids:
FoodPlateMuffinTin: 1
FoodDoughSlice: 1
FoodBanana: 1
reagents:
Sugar: 10
- type: microwaveMealRecipe
id: RecipeMuffinCherry
name: cherry muffin recipe
result: FoodBakedMuffinCherry
time: 15
solids:
FoodPlateMuffinTin: 1
FoodDoughSlice: 1
FoodCherry: 3
reagents:
Sugar: 10
# NOT ACTUAL FOOD
- type: microwaveMealRecipe

View File

@ -8,6 +8,6 @@
steps:
- material: Cloth
amount: 2
doAfter: 10
doAfter: 3
- node: gauze
entity: Gauze1

View File

@ -1,39 +1,39 @@
# Base prototypes
- type: latheRecipe
id: MiniHoe
result: HydroponicsToolMiniHoe
completetime: 2
abstract: true
parent: BaseToolRecipe
id: BaseHydroToolRecipe
materials:
Steel: 200
Plastic: 100
# Recipes
- type: latheRecipe
parent: BaseHydroToolRecipe
id: HydroponicsToolMiniHoe
result: HydroponicsToolMiniHoe
- type: latheRecipe
parent: BaseHydroToolRecipe
id: HydroponicsToolScythe
result: HydroponicsToolScythe
completetime: 2
materials:
Steel: 300
Plastic: 200
- type: latheRecipe
parent: BaseHydroToolRecipe
id: HydroponicsToolHatchet
result: HydroponicsToolHatchet
completetime: 2
materials:
Steel: 200
Plastic: 100
- type: latheRecipe
id: Spade
parent: BaseHydroToolRecipe
id: HydroponicsToolSpade
result: HydroponicsToolSpade
completetime: 2
materials:
Steel: 200
Plastic: 100
- type: latheRecipe
id: Clippers
parent: BaseHydroToolRecipe
id: HydroponicsToolClippers
result: HydroponicsToolClippers
completetime: 2
materials:
Steel: 200
Plastic: 100

View File

@ -1,67 +1,65 @@
- type: latheRecipe
parent: BaseToolRecipe
id: ButchCleaver
result: ButchCleaver
completetime: 2
materials:
Steel: 300
Plastic: 50
- type: latheRecipe
parent: BaseToolRecipe
id: KitchenKnife
result: KitchenKnife
completetime: 2
materials:
Steel: 200
Plastic: 50
- type: latheRecipe
id: DrinkMug
result: DrinkMug
abstract: true
id: BaseGlasswareRecipe
completetime: 0.8
materials:
Glass: 100
- type: latheRecipe
parent: BaseGlasswareRecipe
id: DrinkMug
result: DrinkMug
- type: latheRecipe
parent: DrinkMug
id: DrinkMugMetal
result: DrinkMugMetal
completetime: 0.8
materials:
Steel: 100
- type: latheRecipe
parent: DrinkMug
id: DrinkGlass
result: DrinkGlass
completetime: 0.8
materials:
Glass: 100
- type: latheRecipe
parent: DrinkMug
id: DrinkShotGlass
result: DrinkShotGlass
completetime: 0.4
materials:
Glass: 100
- type: latheRecipe
parent: DrinkMug
id: DrinkGlassCoupeShaped
result: DrinkGlassCoupeShaped
completetime: 0.8
materials:
Glass: 100
- type: latheRecipe
id: CustomDrinkJug
result: CustomDrinkJug
completetime: 2
materials:
Plastic: 200
- type: latheRecipe
id: CustomDrinkJug
result: CustomDrinkJug
completetime: 2
materials:
Plastic: 200
- type: latheRecipe
parent: BaseGlasswareRecipe
id: FoodPlate
result: FoodPlate
completetime: 0.8
materials:
Glass: 100
- type: latheRecipe
id: FoodPlateSmall
@ -71,25 +69,23 @@
Glass: 50
- type: latheRecipe
parent: FoodPlate
id: FoodPlatePlastic
result: FoodPlatePlastic
completetime: 0.8
materials:
Plastic: 100
- type: latheRecipe
parent: FoodPlateSmall
id: FoodPlateSmallPlastic
result: FoodPlateSmallPlastic
completetime: 0.4
materials:
Plastic: 50
- type: latheRecipe
parent: FoodPlate
id: FoodBowlBig
result: FoodBowlBig
completetime: 0.8
materials:
Glass: 100
- type: latheRecipe
id: FoodPlateTin
@ -98,6 +94,13 @@
materials:
Steel: 100
- type: latheRecipe
parent: FoodPlateTin
id: FoodPlateMuffinTin
result: FoodPlateMuffinTin
materials:
Steel: 50
- type: latheRecipe
id: FoodKebabSkewer
result: FoodKebabSkewer

View File

@ -1,51 +1,46 @@
# Base prototypes
- type: latheRecipe
abstract: true
parent: BaseToolRecipe
id: BaseSurgicalRecipe
materials:
Steel: 200
# Recipes
- type: latheRecipe
parent: BaseSurgicalRecipe
id: Scalpel
result: Scalpel
category: Tools
completetime: 2
materials:
Steel: 200
- type: latheRecipe
parent: BaseSurgicalRecipe
id: Retractor
result: Retractor
category: Tools
completetime: 2
materials:
Steel: 200
- type: latheRecipe
parent: BaseSurgicalRecipe
id: Cautery
result: Cautery
category: Tools
completetime: 2
materials:
Steel: 200
- type: latheRecipe
parent: BaseToolRecipe
id: Drill
result: Drill
category: Tools
completetime: 2
materials:
Steel: 200
Plastic: 100
- type: latheRecipe
parent: BaseSurgicalRecipe
id: Saw
result: Saw
category: Tools
completetime: 2
materials:
Steel: 200
- type: latheRecipe
parent: BaseSurgicalRecipe
id: Hemostat
result: Hemostat
category: Tools
completetime: 2
materials:
Steel: 200
- type: latheRecipe
id: BodyBag
@ -75,7 +70,7 @@
result: Gauze1
completetime: 1
materials:
Cloth: 200
Cloth: 100 # lathe more efficient than handcrafting
- type: latheRecipe
id: HandheldCrewMonitor
@ -150,66 +145,51 @@
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitBurn
result: MedkitBurn
name: lathe-recipe-MedkitBurn-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitToxin
result: MedkitToxin
name: lathe-recipe-MedkitToxin-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitO2
result: MedkitO2
name: lathe-recipe-MedkitO2-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitBrute
result: MedkitBrute
name: lathe-recipe-MedkitBrute-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitAdvanced
result: MedkitAdvanced
name: lathe-recipe-MedkitAdvanced-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitRadiation
result: MedkitRadiation
name: lathe-recipe-MedkitRadiation-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: Medkit
id: MedkitCombat
result: MedkitCombat
name: lathe-recipe-MedkitCombat-name
completetime: 2
materials:
Plastic: 300
- type: latheRecipe
parent: BaseToolRecipe
id: HandLabeler
result: HandLabeler
category: Tools
completetime: 2
materials:
Plastic: 100
@ -229,20 +209,14 @@
Plastic: 300
- type: latheRecipe
parent: RollerBedSpawnFolded
id: CheapRollerBedSpawnFolded
result: CheapRollerBedSpawnFolded
completetime: 1
materials:
Steel: 600
Plastic: 300
- type: latheRecipe
parent: RollerBedSpawnFolded
id: EmergencyRollerBedSpawnFolded
result: EmergencyRollerBedSpawnFolded
completetime: 1
materials:
Steel: 600
Plastic: 300
- type: latheRecipe
id: WhiteCane

View File

@ -1,40 +1,51 @@
# Base prototypes
- type: latheRecipe
abstract: true
id: BaseToolRecipe
category: Tools
completetime: 2
materials:
Steel: 200
Plastic: 50
- type: latheRecipe
abstract: true
parent: BaseToolRecipe
id: BaseBigToolRecipe
materials:
Steel: 800
Glass: 300
# Recipes
- type: latheRecipe
parent: BaseToolRecipe
id: Wirecutter
result: Wirecutter
icon:
sprite: Objects/Tools/wirecutters.rsi
state: cutters-map
result: Wirecutter
category: Tools
completetime: 2
materials:
Steel: 200
Plastic: 50
- type: latheRecipe
parent: BaseToolRecipe
id: Screwdriver
result: Screwdriver
icon:
sprite: Objects/Tools/screwdriver.rsi
state: screwdriver-map
result: Screwdriver
category: Tools
completetime: 2
materials:
Steel: 200
Plastic: 50
- type: latheRecipe
parent: BaseToolRecipe
id: Welder
result: Welder
category: Tools
completetime: 2
materials:
Steel: 400
- type: latheRecipe
parent: BaseToolRecipe
id: Wrench
result: Wrench
category: Tools
completetime: 2
materials:
Steel: 200
@ -42,155 +53,122 @@
id: CableStack
result: CableApcStack1
category: Parts
completetime: 2
completetime: 0.1
materials:
Steel: 30
- type: latheRecipe
parent: CableStack
id: CableMVStack
result: CableMVStack1
category: Parts
completetime: 2
materials:
Steel: 30
- type: latheRecipe
parent: CableStack
id: CableHVStack
result: CableHVStack1
category: Parts
completetime: 2
materials:
Steel: 30
- type: latheRecipe
parent: BaseToolRecipe
id: CrowbarGreen
result: CrowbarGreen
category: Tools
completetime: 2
materials:
Steel: 200
- type: latheRecipe
parent: BaseToolRecipe
id: Pickaxe
result: Pickaxe
category: Tools
completetime: 4
materials:
Steel: 1000
Wood: 500
- type: latheRecipe
parent: BaseToolRecipe
id: Shovel
result: Shovel
category: Tools
completetime: 2
materials:
Steel: 200
Wood: 100
- type: latheRecipe
parent: BaseToolRecipe
id: Multitool
result: Multitool
category: Tools
completetime: 2
materials:
Steel: 200
Plastic: 200
- type: latheRecipe
parent: Multitool
id: NetworkConfigurator
result: NetworkConfigurator
category: Tools
completetime: 2
materials:
Steel: 200
Plastic: 200
- type: latheRecipe
parent: BaseToolRecipe
id: PowerDrill
result: PowerDrill
category: Tools
completetime: 2
materials:
Steel: 600
Plastic: 200
- type: latheRecipe
parent: BaseToolRecipe
id: RCD
result: RCDEmpty
category: Tools
completetime: 4
materials:
Steel: 1000
Plastic: 300
- type: latheRecipe
parent: BaseToolRecipe
id: RCDAmmo
result: RCDAmmo
category: Tools
completetime: 2.4
materials:
Steel: 500
Plastic: 250
- type: latheRecipe
parent: BaseBigToolRecipe
id: HandHeldMassScanner
result: HandHeldMassScannerEmpty
category: Tools
completetime: 2
materials:
Steel: 800
Glass: 300
- type: latheRecipe
parent: BaseBigToolRecipe
id: HandheldGPSBasic
result: HandheldGPSBasic
category: Tools
completetime: 2
materials:
Steel: 800
Glass: 300
- type: latheRecipe
parent: BaseBigToolRecipe
id: TRayScanner
result: trayScanner
category: Tools
completetime: 2
materials:
Steel: 800
Glass: 300
- type: latheRecipe
parent: BaseBigToolRecipe
id: GasAnalyzer
result: GasAnalyzer
category: Tools
completetime: 2
materials:
Steel: 800
Glass: 300
- type: latheRecipe
parent: BaseToolRecipe
id: SprayPainter
result: SprayPainter
category: Tools
completetime: 2
materials:
Steel: 300
Plastic: 100
- type: latheRecipe
parent: BaseToolRecipe
id: UtilityBelt
result: ClothingBeltUtility
category: Tools
completetime: 2
materials:
Cloth: 100
Steel: 50
- type: latheRecipe
parent: BaseToolRecipe
id: HolofanProjector
result: HolofanProjectorEmpty
category: Tools
completetime: 8
materials:
Steel: 300
@ -198,18 +176,18 @@
Plastic: 50
- type: latheRecipe
parent: BaseToolRecipe
id: WelderExperimental
result: WelderExperimental
category: Tools
completetime: 6
materials:
Steel: 800
Plasma: 200
- type: latheRecipe
parent: BaseToolRecipe
id: JawsOfLife
result: JawsOfLife
category: Tools
completetime: 6
materials:
Steel: 1000
@ -218,9 +196,9 @@
Gold: 50
- type: latheRecipe
parent: BaseToolRecipe
id: HoloprojectorField
result: HoloprojectorFieldEmpty
category: Tools
completetime: 3
materials:
Steel: 500
@ -228,9 +206,9 @@
Glass: 100
- type: latheRecipe
parent: BaseToolRecipe
id: WeaponParticleDecelerator
result: WeaponParticleDecelerator
category: Tools
completetime: 6
materials:
Steel: 750

View File

@ -81,7 +81,7 @@
amount: 1
Sulfur:
amount: 1
Oxygen:
Oxygen:
amount: 2
products:
SulfuricAcid: 3
@ -205,6 +205,20 @@
energyConsumption: 12500
duration: 15
- type: reaction
id: Flash
impact: High
priority: 20
reactants:
Aluminium:
amount: 1
Potassium:
amount: 1
Sulfur:
amount: 1
effects:
- !type:FlashReactionEffect
- type: reaction
id: TableSalt
minTemp: 370
@ -501,3 +515,4 @@
amount: 1
products:
Tazinide: 1

View File

@ -1,4 +1,4 @@
- type: job
- type: job
id: ServiceWorker
name: job-name-serviceworker
description: job-description-serviceworker
@ -6,7 +6,6 @@
startingGear: ServiceWorkerGear
icon: "JobIconServiceWorker"
supervisors: job-supervisors-service
canBeAntag: true # DeltaV - Can be antagonist
access:
- Service
- Maintenance

View File

@ -1,8 +1,3 @@
- type: preloadedGrid
id: ShuttleStriker
path: /Maps/Shuttles/ShuttleEvent/striker.yml
copies: 2
- type: preloadedGrid
id: ShuttleCargoLost
path: /Maps/Shuttles/ShuttleEvent/lost_cargo.yml

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