Merge branch 'master' into offmed-staging

This commit is contained in:
Janet Blackquill
2025-10-02 20:36:12 -04:00
34 changed files with 613 additions and 307 deletions

View File

@@ -77,18 +77,21 @@ namespace Content.Client.Entry
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly ClientsidePlaytimeTrackingManager _clientsidePlaytimeManager = default!;
public override void Init()
public override void PreInit()
{
ClientContentIoC.Register();
ClientContentIoC.Register(Dependencies);
foreach (var callback in TestingCallbacks)
{
var cast = (ClientModuleTestingCallbacks) callback;
cast.ClientBeforeIoC?.Invoke();
}
}
IoCManager.BuildGraph();
IoCManager.InjectDependencies(this);
public override void Init()
{
Dependencies.BuildGraph();
Dependencies.InjectDependencies(this);
_contentLoc.Initialize();
_componentFactory.DoAutoRegistrations();

View File

@@ -23,6 +23,7 @@ using Content.Client.Lobby;
using Content.Client.Players.RateLimiting;
using Content.Shared.Administration.Managers;
using Content.Shared.Chat;
using Content.Shared.IoC;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Players.RateLimiting;
@@ -30,10 +31,9 @@ namespace Content.Client.IoC
{
internal static class ClientContentIoC
{
public static void Register()
public static void Register(IDependencyCollection collection)
{
var collection = IoCManager.Instance!;
SharedContentIoC.Register(collection);
collection.Register<IParallaxManager, ParallaxManager>();
collection.Register<GeneratedParallaxCache>();
collection.Register<IChatManager, ChatManager>();

View File

@@ -126,6 +126,9 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
if (_random.Prob(anomaly.Comp.Continuity))
SetBehavior(anomaly, GetRandomBehavior());
}
var ev = new AnomalyAffectedByParticleEvent(anomaly, args.OtherEntity);
RaiseLocalEvent(anomaly, ref ev);
}
/// <summary>

View File

@@ -1,9 +1,9 @@
using Content.Server.Anomaly.Components;
using Content.Shared.Anomaly.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Random;
namespace Content.Server.Anomaly.Effects;
public sealed class ShuffleParticlesAnomalySystem : EntitySystem
{
[Dependency] private readonly AnomalySystem _anomaly = default!;
@@ -12,19 +12,16 @@ public sealed class ShuffleParticlesAnomalySystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<ShuffleParticlesAnomalyComponent, AnomalyPulseEvent>(OnPulse);
SubscribeLocalEvent<ShuffleParticlesAnomalyComponent, StartCollideEvent>(OnStartCollide);
SubscribeLocalEvent<ShuffleParticlesAnomalyComponent, AnomalyAffectedByParticleEvent>(OnAffectedByParticle);
}
private void OnStartCollide(Entity<ShuffleParticlesAnomalyComponent> ent, ref StartCollideEvent args)
private void OnAffectedByParticle(Entity<ShuffleParticlesAnomalyComponent> ent, ref AnomalyAffectedByParticleEvent args)
{
if (!TryComp<AnomalyComponent>(ent, out var anomaly))
return;
if (!HasComp<AnomalousParticleComponent>(args.OtherEntity))
if (!TryComp<AnomalyComponent>(ent, out var anomalyComp))
return;
if (ent.Comp.ShuffleOnParticleHit && _random.Prob(ent.Comp.Prob))
_anomaly.ShuffleParticlesEffect((ent, anomaly));
_anomaly.ShuffleParticlesEffect((args.Anomaly, anomalyComp));
}
private void OnPulse(Entity<ShuffleParticlesAnomalyComponent> ent, ref AnomalyPulseEvent args)

View File

@@ -174,7 +174,10 @@ public sealed partial class AntagSelectionSystem
if (roles.Count == 0)
return false;
var pref = (HumanoidCharacterProfile) _pref.GetPreferences(session.UserId).SelectedCharacter;
if (!_pref.TryGetCachedPreferences(session.UserId, out var pref))
return false;
var character = (HumanoidCharacterProfile) pref.SelectedCharacter;
var valid = false;
@@ -183,8 +186,7 @@ public sealed partial class AntagSelectionSystem
{
var list = new List<ProtoId<AntagPrototype>>{role};
if (pref.AntagPreferences.Contains(role)
if (character.AntagPreferences.Contains(role)
&& !_ban.IsRoleBanned(session, list)
&& _playTime.IsAllowed(session, list))
valid = true;

View File

@@ -15,8 +15,6 @@ using Content.Server.Info;
using Content.Server.IoC;
using Content.Server.Maps;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.Objectives;
using Content.Server.Players;
using Content.Server.Players.JobWhitelist;
using Content.Server.Players.PlayTimeTracking;
using Content.Server.Players.RateLimiting;
@@ -42,124 +40,131 @@ namespace Content.Server.Entry
internal const string ConfigPresetsDir = "/ConfigPresets/";
private const string ConfigPresetsDirBuild = $"{ConfigPresetsDir}Build/";
private EuiManager _euiManager = default!;
private IVoteManager _voteManager = default!;
private ServerUpdateManager _updateManager = default!;
private PlayTimeTrackingManager? _playTimeTracking;
private IEntitySystemManager? _sysMan;
private IServerDbManager? _dbManager;
private IWatchlistWebhookManager _watchlistWebhookManager = default!;
private IConnectionManager? _connectionManager;
[Dependency] private readonly CVarControlManager _cvarCtrl = default!;
[Dependency] private readonly ContentLocalizationManager _loc = default!;
[Dependency] private readonly ContentNetworkResourceManager _netResMan = default!;
[Dependency] private readonly DiscordChatLink _discordChatLink = default!;
[Dependency] private readonly DiscordLink _discordLink = default!;
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly GhostKickManager _ghostKick = default!;
[Dependency] private readonly IAdminManager _admin = default!;
[Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly IAfkManager _afk = default!;
[Dependency] private readonly IBanManager _ban = default!;
[Dependency] private readonly IChatManager _chatSan = default!;
[Dependency] private readonly IChatSanitizationManager _chat = default!;
[Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IConnectionManager _connection = default!;
[Dependency] private readonly IEntitySystemManager _entSys = default!;
[Dependency] private readonly IGameMapManager _gameMap = default!;
[Dependency] private readonly ILogManager _log = default!;
[Dependency] private readonly INodeGroupFactory _nodeFactory = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IResourceManager _res = default!;
[Dependency] private readonly IServerDbManager _dbManager = default!;
[Dependency] private readonly IServerPreferencesManager _preferences = default!;
[Dependency] private readonly IStatusHost _host = default!;
[Dependency] private readonly IVoteManager _voteManager = default!;
[Dependency] private readonly IWatchlistWebhookManager _watchlistWebhookManager = default!;
[Dependency] private readonly JobWhitelistManager _job = default!;
[Dependency] private readonly MultiServerKickManager _multiServerKick = default!;
[Dependency] private readonly PlayTimeTrackingManager _playTimeTracking = default!;
[Dependency] private readonly PlayerRateLimitManager _rateLimit = default!;
[Dependency] private readonly RecipeManager _recipe = default!;
[Dependency] private readonly RulesManager _rules = default!;
[Dependency] private readonly ServerApi _serverApi = default!;
[Dependency] private readonly ServerInfoManager _serverInfo = default!;
[Dependency] private readonly ServerUpdateManager _updateManager = default!;
public override void PreInit()
{
ServerContentIoC.Register(Dependencies);
foreach (var callback in TestingCallbacks)
{
var cast = (ServerModuleTestingCallbacks)callback;
cast.ServerBeforeIoC?.Invoke();
}
}
/// <inheritdoc />
public override void Init()
{
base.Init();
Dependencies.BuildGraph();
Dependencies.InjectDependencies(this);
var cfg = IoCManager.Resolve<IConfigurationManager>();
var res = IoCManager.Resolve<IResourceManager>();
var logManager = IoCManager.Resolve<ILogManager>();
LoadConfigPresets(_cfg, _res, _log.GetSawmill("configpreset"));
LoadConfigPresets(cfg, res, logManager.GetSawmill("configpreset"));
var aczProvider = new ContentMagicAczProvider(Dependencies);
_host.SetMagicAczProvider(aczProvider);
var aczProvider = new ContentMagicAczProvider(IoCManager.Resolve<IDependencyCollection>());
IoCManager.Resolve<IStatusHost>().SetMagicAczProvider(aczProvider);
_factory.DoAutoRegistrations();
_factory.IgnoreMissingComponents("Visuals");
_factory.RegisterIgnore(IgnoredComponents.List);
_factory.GenerateNetIds();
var factory = IoCManager.Resolve<IComponentFactory>();
var prototypes = IoCManager.Resolve<IPrototypeManager>();
_proto.RegisterIgnore("parallax");
factory.DoAutoRegistrations();
factory.IgnoreMissingComponents("Visuals");
_loc.Initialize();
factory.RegisterIgnore(IgnoredComponents.List);
var dest = _cfg.GetCVar(CCVars.DestinationFile);
if (!string.IsNullOrEmpty(dest))
return; //hacky but it keeps load times for the generator down.
prototypes.RegisterIgnore("parallax");
_log.GetSawmill("Storage").Level = LogLevel.Info;
_log.GetSawmill("db.ef").Level = LogLevel.Info;
ServerContentIoC.Register();
foreach (var callback in TestingCallbacks)
{
var cast = (ServerModuleTestingCallbacks) callback;
cast.ServerBeforeIoC?.Invoke();
}
IoCManager.BuildGraph();
factory.GenerateNetIds();
var configManager = IoCManager.Resolve<IConfigurationManager>();
var dest = configManager.GetCVar(CCVars.DestinationFile);
IoCManager.Resolve<ContentLocalizationManager>().Initialize();
if (string.IsNullOrEmpty(dest)) //hacky but it keeps load times for the generator down.
{
_euiManager = IoCManager.Resolve<EuiManager>();
_voteManager = IoCManager.Resolve<IVoteManager>();
_updateManager = IoCManager.Resolve<ServerUpdateManager>();
_playTimeTracking = IoCManager.Resolve<PlayTimeTrackingManager>();
_connectionManager = IoCManager.Resolve<IConnectionManager>();
_sysMan = IoCManager.Resolve<IEntitySystemManager>();
_dbManager = IoCManager.Resolve<IServerDbManager>();
_watchlistWebhookManager = IoCManager.Resolve<IWatchlistWebhookManager>();
logManager.GetSawmill("Storage").Level = LogLevel.Info;
logManager.GetSawmill("db.ef").Level = LogLevel.Info;
IoCManager.Resolve<IAdminLogManager>().Initialize();
IoCManager.Resolve<IConnectionManager>().Initialize();
_dbManager.Init();
IoCManager.Resolve<IServerPreferencesManager>().Init();
IoCManager.Resolve<INodeGroupFactory>().Initialize();
IoCManager.Resolve<ContentNetworkResourceManager>().Initialize();
IoCManager.Resolve<GhostKickManager>().Initialize();
IoCManager.Resolve<ServerInfoManager>().Initialize();
IoCManager.Resolve<ServerApi>().Initialize();
_voteManager.Initialize();
_updateManager.Initialize();
_playTimeTracking.Initialize();
_watchlistWebhookManager.Initialize();
IoCManager.Resolve<JobWhitelistManager>().Initialize();
IoCManager.Resolve<PlayerRateLimitManager>().Initialize();
}
_adminLog.Initialize();
_connection.Initialize();
_dbManager.Init();
_preferences.Init();
_nodeFactory.Initialize();
_netResMan.Initialize();
_ghostKick.Initialize();
_serverInfo.Initialize();
_serverApi.Initialize();
_voteManager.Initialize();
_updateManager.Initialize();
_playTimeTracking.Initialize();
_watchlistWebhookManager.Initialize();
_job.Initialize();
_rateLimit.Initialize();
}
public override void PostInit()
{
base.PostInit();
IoCManager.Resolve<IChatSanitizationManager>().Initialize();
IoCManager.Resolve<IChatManager>().Initialize();
var configManager = IoCManager.Resolve<IConfigurationManager>();
var resourceManager = IoCManager.Resolve<IResourceManager>();
var dest = configManager.GetCVar(CCVars.DestinationFile);
_chatSan.Initialize();
_chat.Initialize();
var dest = _cfg.GetCVar(CCVars.DestinationFile);
if (!string.IsNullOrEmpty(dest))
{
var resPath = new ResPath(dest).ToRootedPath();
var file = resourceManager.UserData.OpenWriteText(resPath.WithName("chem_" + dest));
var file = _res.UserData.OpenWriteText(resPath.WithName("chem_" + dest));
ChemistryJsonGenerator.PublishJson(file);
file.Flush();
file = resourceManager.UserData.OpenWriteText(resPath.WithName("react_" + dest));
file = _res.UserData.OpenWriteText(resPath.WithName("react_" + dest));
ReactionJsonGenerator.PublishJson(file);
file.Flush();
IoCManager.Resolve<IBaseServer>().Shutdown("Data generation done");
Dependencies.Resolve<IBaseServer>().Shutdown("Data generation done");
return;
}
else
{
IoCManager.Resolve<RecipeManager>().Initialize();
IoCManager.Resolve<IAdminManager>().Initialize();
IoCManager.Resolve<IAfkManager>().Initialize();
IoCManager.Resolve<RulesManager>().Initialize();
IoCManager.Resolve<DiscordLink>().Initialize();
IoCManager.Resolve<DiscordChatLink>().Initialize();
_euiManager.Initialize();
IoCManager.Resolve<IGameMapManager>().Initialize();
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GameTicker>().PostInitialize();
IoCManager.Resolve<IBanManager>().Initialize();
IoCManager.Resolve<IConnectionManager>().PostInit();
IoCManager.Resolve<MultiServerKickManager>().Initialize();
IoCManager.Resolve<CVarControlManager>().Initialize();
}
_recipe.Initialize();
_admin.Initialize();
_afk.Initialize();
_rules.Initialize();
_discordLink.Initialize();
_discordChatLink.Initialize();
_euiManager.Initialize();
_gameMap.Initialize();
_entSys.GetEntitySystem<GameTicker>().PostInitialize();
_ban.Initialize();
_connection.PostInit();
_multiServerKick.Initialize();
_cvarCtrl.Initialize();
}
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
@@ -177,21 +182,27 @@ namespace Content.Server.Entry
case ModUpdateLevel.FramePostEngine:
_updateManager.Update();
_playTimeTracking?.Update();
_playTimeTracking.Update();
_watchlistWebhookManager.Update();
_connectionManager?.Update();
_connection.Update();
break;
}
}
protected override void Dispose(bool disposing)
{
_playTimeTracking?.Shutdown();
_dbManager?.Shutdown();
IoCManager.Resolve<ServerApi>().Shutdown();
var dest = _cfg.GetCVar(CCVars.DestinationFile);
if (!string.IsNullOrEmpty(dest))
{
_playTimeTracking.Shutdown();
_dbManager.Shutdown();
}
IoCManager.Resolve<DiscordLink>().Shutdown();
IoCManager.Resolve<DiscordChatLink>().Shutdown();
_serverApi.Shutdown();
// TODO Should this be awaited?
_discordLink.Shutdown();
_discordChatLink.Shutdown();
}
private static void LoadConfigPresets(IConfigurationManager cfg, IResourceManager res, ISawmill sawmill)

View File

@@ -26,59 +26,59 @@ using Content.Server.Worldgen.Tools;
using Content.Shared.Administration.Logs;
using Content.Shared.Administration.Managers;
using Content.Shared.Chat;
using Content.Shared.IoC;
using Content.Shared.Kitchen;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Players.RateLimiting;
namespace Content.Server.IoC
{
internal static class ServerContentIoC
{
public static void Register()
{
IoCManager.Register<IChatManager, ChatManager>();
IoCManager.Register<ISharedChatManager, ChatManager>();
IoCManager.Register<IChatSanitizationManager, ChatSanitizationManager>();
IoCManager.Register<IServerPreferencesManager, ServerPreferencesManager>();
IoCManager.Register<IServerDbManager, ServerDbManager>();
IoCManager.Register<RecipeManager, RecipeManager>();
IoCManager.Register<INodeGroupFactory, NodeGroupFactory>();
IoCManager.Register<IConnectionManager, ConnectionManager>();
IoCManager.Register<ServerUpdateManager>();
IoCManager.Register<IAdminManager, AdminManager>();
IoCManager.Register<ISharedAdminManager, AdminManager>();
IoCManager.Register<EuiManager, EuiManager>();
IoCManager.Register<IVoteManager, VoteManager>();
IoCManager.Register<IPlayerLocator, PlayerLocator>();
IoCManager.Register<IAfkManager, AfkManager>();
IoCManager.Register<IGameMapManager, GameMapManager>();
IoCManager.Register<RulesManager, RulesManager>();
IoCManager.Register<IBanManager, BanManager>();
IoCManager.Register<ContentNetworkResourceManager>();
IoCManager.Register<IAdminNotesManager, AdminNotesManager>();
IoCManager.Register<GhostKickManager>();
IoCManager.Register<ISharedAdminLogManager, AdminLogManager>();
IoCManager.Register<IAdminLogManager, AdminLogManager>();
IoCManager.Register<PlayTimeTrackingManager>();
IoCManager.Register<UserDbDataManager>();
IoCManager.Register<ServerInfoManager>();
IoCManager.Register<PoissonDiskSampler>();
IoCManager.Register<DiscordWebhook>();
IoCManager.Register<VoteWebhooks>();
IoCManager.Register<ServerDbEntryManager>();
IoCManager.Register<ISharedPlaytimeManager, PlayTimeTrackingManager>();
IoCManager.Register<ServerApi>();
IoCManager.Register<JobWhitelistManager>();
IoCManager.Register<PlayerRateLimitManager>();
IoCManager.Register<SharedPlayerRateLimitManager, PlayerRateLimitManager>();
IoCManager.Register<MappingManager>();
IoCManager.Register<IWatchlistWebhookManager, WatchlistWebhookManager>();
IoCManager.Register<ConnectionManager>();
IoCManager.Register<MultiServerKickManager>();
IoCManager.Register<CVarControlManager>();
namespace Content.Server.IoC;
IoCManager.Register<DiscordLink>();
IoCManager.Register<DiscordChatLink>();
}
internal static class ServerContentIoC
{
public static void Register(IDependencyCollection deps)
{
SharedContentIoC.Register(deps);
deps.Register<IChatManager, ChatManager>();
deps.Register<ISharedChatManager, ChatManager>();
deps.Register<IChatSanitizationManager, ChatSanitizationManager>();
deps.Register<IServerPreferencesManager, ServerPreferencesManager>();
deps.Register<IServerDbManager, ServerDbManager>();
deps.Register<RecipeManager, RecipeManager>();
deps.Register<INodeGroupFactory, NodeGroupFactory>();
deps.Register<IConnectionManager, ConnectionManager>();
deps.Register<ServerUpdateManager>();
deps.Register<IAdminManager, AdminManager>();
deps.Register<ISharedAdminManager, AdminManager>();
deps.Register<EuiManager, EuiManager>();
deps.Register<IVoteManager, VoteManager>();
deps.Register<IPlayerLocator, PlayerLocator>();
deps.Register<IAfkManager, AfkManager>();
deps.Register<IGameMapManager, GameMapManager>();
deps.Register<RulesManager, RulesManager>();
deps.Register<IBanManager, BanManager>();
deps.Register<ContentNetworkResourceManager>();
deps.Register<IAdminNotesManager, AdminNotesManager>();
deps.Register<GhostKickManager>();
deps.Register<ISharedAdminLogManager, AdminLogManager>();
deps.Register<IAdminLogManager, AdminLogManager>();
deps.Register<PlayTimeTrackingManager>();
deps.Register<UserDbDataManager>();
deps.Register<ServerInfoManager>();
deps.Register<PoissonDiskSampler>();
deps.Register<DiscordWebhook>();
deps.Register<VoteWebhooks>();
deps.Register<ServerDbEntryManager>();
deps.Register<ISharedPlaytimeManager, PlayTimeTrackingManager>();
deps.Register<ServerApi>();
deps.Register<JobWhitelistManager>();
deps.Register<PlayerRateLimitManager>();
deps.Register<SharedPlayerRateLimitManager, PlayerRateLimitManager>();
deps.Register<MappingManager>();
deps.Register<IWatchlistWebhookManager, WatchlistWebhookManager>();
deps.Register<ConnectionManager>();
deps.Register<MultiServerKickManager>();
deps.Register<CVarControlManager>();
deps.Register<DiscordLink>();
deps.Register<DiscordChatLink>();
}
}

View File

@@ -1,7 +1,4 @@
using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components;
namespace Content.Server.Anomaly.Components;
namespace Content.Shared.Anomaly.Components;
/// <summary>
/// This is used for projectiles which affect anomalies through colliding with them.

View File

@@ -324,3 +324,10 @@ public readonly record struct AnomalyHealthChangedEvent(EntityUid Anomaly, float
/// </summary>
[ByRefEvent]
public readonly record struct AnomalyBehaviorChangedEvent(EntityUid Anomaly, ProtoId<AnomalyBehaviorPrototype>? Old, ProtoId<AnomalyBehaviorPrototype>? New);
/// <summary>
/// Event of anomaly being affected by exotic particle.
/// Is raised when particle collides with artifact.
/// </summary>
[ByRefEvent]
public record struct AnomalyAffectedByParticleEvent(EntityUid Anomaly, EntityUid Particle);

View File

@@ -27,7 +27,6 @@ namespace Content.Shared.Entry
public override void PreInit()
{
IoCManager.InjectDependencies(this);
SharedContentIoC.Register();
}
public override void Shutdown()

View File

@@ -5,10 +5,10 @@ namespace Content.Shared.IoC
{
public static class SharedContentIoC
{
public static void Register()
public static void Register(IDependencyCollection deps)
{
IoCManager.Register<MarkingManager, MarkingManager>();
IoCManager.Register<ContentLocalizationManager, ContentLocalizationManager>();
deps.Register<MarkingManager, MarkingManager>();
deps.Register<ContentLocalizationManager, ContentLocalizationManager>();
}
}
}

View File

@@ -2,8 +2,8 @@ using System.Collections.Generic;
using System.Reflection;
using Content.Client.IoC;
using Content.Server.IoC;
using Content.Shared.IoC;
using Robust.Shared.Analyzers;
using Robust.Shared.IoC;
using Robust.UnitTesting;
using EntryPoint = Content.Server.Entry.EntryPoint;
@@ -15,16 +15,15 @@ namespace Content.Tests
protected override void OverrideIoC()
{
base.OverrideIoC();
SharedContentIoC.Register();
var dependencies = IoCManager.Instance!;
if (Project == UnitTestProject.Server)
{
ServerContentIoC.Register();
ServerContentIoC.Register(dependencies);
}
else if (Project == UnitTestProject.Client)
{
ClientContentIoC.Register();
ClientContentIoC.Register(dependencies);
}
}

View File

@@ -87,3 +87,8 @@
license: "CC0-1.0"
copyright: "Taken from 0ne_one111yt on freesound.org"
source: "https://freesound.org/people/0ne_one111yt/sounds/478213/"
- files: ["utilityknifeopen.ogg, utilityknifeclose.ogg"]
license: "CC0-1.0"
copyright: "Taken from FilmOrbit on freesound.org"
source: "https://freesound.org/s/554299/"

Binary file not shown.

Binary file not shown.

View File

@@ -202,14 +202,16 @@
- type: cargoBounty
id: BountyKnife
reward: 6000
reward: 2000
description: bounty-description-knife
entries:
- name: bounty-item-knife
amount: 5
whitelist:
components:
- Sharp
- Sharp
tags:
- UtilityKnife # required because retracted utility knives are not Sharp
- type: cargoBounty
id: BountyLemon

View File

@@ -35,6 +35,7 @@
- GPS
- WeldingMask
- RemoteSignaller
- UtilityKnife
components:
- StationMap
- SprayPainter
@@ -120,6 +121,7 @@
- HolofanProjector
- Multitool
- AppraisalTool
- UtilityKnife
components:
- StationMap
- SprayPainter

View File

@@ -1,4 +1,4 @@
# Be careful with these as they get removed on shutdown too!
# Be careful with these as they get removed on shutdown too!
- type: entity
id: AiHeld
description: Components added / removed from an entity that gets inserted into an AI core.
@@ -169,7 +169,7 @@
# Empty AI core
- type: entity
id: PlayerStationAiEmpty
name: AI Core
name: AI core
description: The latest in Artificial Intelligences.
parent:
- BaseStructure
@@ -330,7 +330,7 @@
- type: entity
parent: BaseStructure
id: PlayerStationAiAssembly
name: AI Core Assembly
name: AI core assembly
description: An unfinished computer core for housing an artifical intelligence.
components:
- type: Anchorable

View File

@@ -1,4 +1,4 @@
- type: entity
- type: entity
parent: BaseItem
id: BaseComputerCircuitboard
name: computer board
@@ -564,7 +564,7 @@
- type: entity
parent: BaseComputerCircuitboard
id: StationAiFixerCircuitboard
name: AI restoration console
name: AI restoration console board
description: A computer printed circuit board for an AI restoration console console.
components:
- type: Sprite

View File

@@ -336,3 +336,67 @@
- ItemMask
restitution: 0.3
friction: 0.2
- type: entity
name: utility knife
parent: BaseItem
id: UtilityKnife
description: A knife with a retractable, tiny blade. Useful as a box cutter and letter opener, among other things.
components:
- type: Appearance
- type: ComponentToggler
components:
- type: Execution
doAfterDuration: 4.0
- type: Sharp
- type: Utensil
types:
- Knife
- type: Tool
qualities:
- Slicing
useSound:
path: /Audio/Items/Culinary/chop.ogg
- type: Item
size: Tiny
sprite: Objects/Weapons/Melee/utility_knife.rsi
- type: ItemToggle
soundActivate:
path: /Audio/Weapons/utilityknifeopen.ogg
soundDeactivate:
path: /Audio/Weapons/utilityknifeclose.ogg
- type: ItemToggleMeleeWeapon
activatedSoundOnHit:
path: /Audio/Weapons/bladeslice.ogg
activatedDamage:
types:
Slash: 4
- type: MeleeWeapon
wideAnimationRotation: -135
attackRate: 1
damage:
types:
Blunt: 1
- type: PhysicalComposition
materialComposition:
Steel: 50
- type: Sprite
sprite: Objects/Weapons/Melee/utility_knife.rsi
layers:
- state: utility_knife_handle
- state: utility_knife_blade
visible: false
map: [ "blade" ]
- type: Tag
tags:
- Knife
- UtilityKnife
- type: ToggleableVisuals
spriteLayer: blade
inhandVisuals:
left:
- state: inhand-left-blade
right:
- state: inhand-right-blade
- type: UseDelay
delay: 0.2

View File

@@ -55,7 +55,7 @@
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
damage: 300
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
@@ -69,6 +69,8 @@
components:
- type: NavMapDoor
### Metal doors ###
- type: entity
id: MetalDoor
name: metal door
@@ -77,6 +79,183 @@
- type: Construction
graph: DoorGraph
node: metalDoor
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel1:
min: 3
max: 5
- type: entity
id: PlasmaDoor
name: plasma door
parent: BaseMaterialDoorNavMap
description: A door, where will it lead?
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/plasma_door.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- type: Construction
graph: DoorGraph
node: plasmaDoor
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
SheetPlasma1:
min: 3
max: 5
- type: entity
id: GoldDoor
name: gold door
parent: BaseMaterialDoorNavMap
description: A door, where will it lead?
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/gold_door.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- type: Construction
graph: DoorGraph
node: goldDoor
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
IngotGold1:
min: 3
max: 5
- type: entity
id: SilverDoor
name: silver door
parent: BaseMaterialDoorNavMap
description: A door, where will it lead?
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/silver_door.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- type: Construction
graph: DoorGraph
node: silverDoor
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
IngotSilver1:
min: 3
max: 5
- type: entity
id: BananiumDoor
name: bananium door
parent: BaseMaterialDoorNavMap
description: A door, where will it lead?
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/bananium_door.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- type: Door
openSound:
path: /Audio/Items/bikehorn.ogg
closeSound:
path: /Audio/Items/bikehorn.ogg
- type: Construction
graph: DoorGraph
node: bananiumDoor
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
MaterialBananium1:
min: 1
max: 2
### Other doors ###
- type: entity
id: WoodDoor
@@ -90,6 +269,9 @@
path: /Audio/Effects/door_open.ogg
closeSound:
path: /Audio/Effects/door_close.ogg
- type: Construction
graph: DoorGraph
node: woodDoor
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Wood
@@ -97,97 +279,69 @@
thresholds:
- trigger:
!type:DamageTrigger
damage: 100
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Construction
graph: DoorGraph
node: woodDoor
- trigger:
!type:DamageTrigger
damage: 75
behaviors:
- !type:PlaySoundBehavior
sound:
collection: WoodDestroy
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
MaterialWoodPlank1:
min: 3
max: 5
- type: entity
id: PaperDoor
name: paper door
parent: BaseMaterialDoorNavMap
description: A door, where will it lead?
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/paper_door.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- type: Door
openSound:
path: /Audio/Effects/paperdoor_openclose.ogg
closeSound:
path: /Audio/Effects/paperdoor_openclose.ogg
- type: Construction
graph: DoorGraph
node: paperDoor
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Wood
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 50
behaviors:
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/poster_broken.ogg
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Construction
graph: DoorGraph
node: paperDoor
- type: Door
openSound:
path: /Audio/Effects/paperdoor_openclose.ogg
closeSound:
path: /Audio/Effects/paperdoor_openclose.ogg
- type: entity
id: PlasmaDoor
name: plasma door
parent: BaseMaterialDoorNavMap
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/plasma_door.rsi
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: StructuralMetallicStrong
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 300
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Construction
graph: DoorGraph
node: plasmaDoor
- type: entity
id: GoldDoor
name: gold door
parent: BaseMaterialDoorNavMap
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/gold_door.rsi
- type: Construction
graph: DoorGraph
node: goldDoor
- type: entity
id: SilverDoor
name: silver door
parent: BaseMaterialDoorNavMap
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/silver_door.rsi
- type: Construction
graph: DoorGraph
node: silverDoor
- type: entity
id: BananiumDoor
name: bananium door
parent: BaseMaterialDoorNavMap
components:
- type: Sprite
sprite: Structures/Doors/MineralDoors/bananium_door.rsi
- type: Construction
graph: DoorGraph
node: bananiumDoor
- type: Door
openSound:
path: /Audio/Items/bikehorn.ogg
closeSound:
path: /Audio/Items/bikehorn.ogg
- !type:SpawnEntitiesBehavior
spawn:
SheetPaper1:
min: 3
max: 5
- type: entity
id: WebDoor
@@ -197,9 +351,19 @@
components:
- type: Sprite
sprite: Structures/Doors/web_door.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- type: Door
closeSound:
path: /Audio/Effects/rustle1.ogg
openSound:
path: /Audio/Effects/rustle2.ogg
- type: Construction
graph: WebStructures
node: door
- type: Damageable
damageModifierSet: Web
- type: Destructible
thresholds:
- trigger: # Excess damage, don't spawn entities
@@ -211,6 +375,12 @@
collection: WoodDestroy
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 150
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- trigger:
!type:DamageTrigger
damage: 50
@@ -222,16 +392,9 @@
collection: WoodDestroy
- !type:SpawnEntitiesBehavior
spawn:
MaterialWebSilk:
min: 3
max: 5
- type: Damageable
damageModifierSet: Web
- type: Door
closeSound:
path: /Audio/Effects/rustle1.ogg
openSound:
path: /Audio/Effects/rustle2.ogg
MaterialWebSilk1:
min: 1
max: 2
- type: entity
id: CardDoor
@@ -245,6 +408,9 @@
path: /Audio/Effects/card_drag.ogg
closeSound:
path: /Audio/Effects/card_drag.ogg
- type: Construction
graph: DoorGraph
node: cardDoor
- type: MeleeSound
soundGroups:
Brute:
@@ -265,13 +431,13 @@
!type:DamageTrigger
damage: 30
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: WoodDestroy
- !type:SpawnEntitiesBehavior
spawn:
MaterialCardboard:
min: 2
max: 4
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: Construction
graph: DoorGraph
node: cardDoor
min: 3
max: 5

View File

@@ -489,6 +489,8 @@
- CrateMask #this is so they can go under plastic flaps
layer:
- MachineLayer
- type: Paintable
group: null
- type: entity
id: CrateLockBoxEngineering

View File

@@ -11,57 +11,57 @@
- !type:SnapToGrid { }
steps:
- material: Steel
amount: 20
doAfter: 15
amount: 10
doAfter: 8
- to: woodDoor
completed:
- !type:SnapToGrid { }
steps:
- material: WoodPlank
amount: 20
doAfter: 15
amount: 10
doAfter: 8
- to: plasmaDoor
completed:
- !type:SnapToGrid { }
steps:
- material: Plasma
amount: 20
doAfter: 15
amount: 10
doAfter: 8
- to: goldDoor
completed:
- !type:SnapToGrid { }
steps:
- material: Gold
amount: 20
doAfter: 15
amount: 10
doAfter: 8
- to: silverDoor
completed:
- !type:SnapToGrid { }
steps:
- material: Silver
amount: 20
doAfter: 15
amount: 10
doAfter: 8
- to: bananiumDoor
completed:
- !type:SnapToGrid { }
steps:
- material: Bananium
amount: 5
doAfter: 15
doAfter: 8
- to: paperDoor
completed:
- !type:SnapToGrid { }
steps:
- material: Paper
amount: 20
doAfter: 15
amount: 10
doAfter: 8
- to: cardDoor
completed:
- !type:SnapToGrid { }
steps:
- material: Cardboard
amount: 5
doAfter: 6
amount: 10
doAfter: 8
- node: metalDoor
entity: MetalDoor
edges:
@@ -69,10 +69,10 @@
completed:
- !type:SpawnPrototype
prototype: SheetSteel1
amount: 20
amount: 10
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8
- node: woodDoor
entity: WoodDoor
edges:
@@ -80,10 +80,10 @@
completed:
- !type:SpawnPrototype
prototype: MaterialWoodPlank1
amount: 20
amount: 10
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8
- node: plasmaDoor
entity: PlasmaDoor
edges:
@@ -91,10 +91,10 @@
completed:
- !type:SpawnPrototype
prototype: SheetPlasma
amount: 20
amount: 10
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8
- node: goldDoor
entity: GoldDoor
edges:
@@ -102,10 +102,10 @@
completed:
- !type:SpawnPrototype
prototype: IngotGold1
amount: 20
amount: 10
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8
- node: silverDoor
entity: SilverDoor
edges:
@@ -113,10 +113,10 @@
completed:
- !type:SpawnPrototype
prototype: IngotSilver1
amount: 20
amount: 10
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8
- node: paperDoor
entity: PaperDoor
edges:
@@ -124,10 +124,10 @@
completed:
- !type:SpawnPrototype
prototype: SheetPaper1
amount: 20
amount: 10
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8
- node: cardDoor
entity: CardDoor
edges:
@@ -137,7 +137,7 @@
sound: /Audio/Items/Toys/ToyFall2.ogg
- !type:SpawnPrototype
prototype: MaterialCardboard1
amount: 5
amount: 8
- !type:DeleteEntity {}
steps:
- tool: Slicing
@@ -152,4 +152,4 @@
amount: 5
steps:
- tool: Anchoring
doAfter: 15
doAfter: 8

View File

@@ -5,6 +5,7 @@
recipes:
- AppraisalTool
- Pickaxe
- UtilityKnife
- type: latheRecipePack
id: CargoBoardsStatic

View File

@@ -12,3 +12,10 @@
completetime: 4
materials:
Steel: 500
- type: latheRecipe
id: UtilityKnife
result: UtilityKnife
completetime: 2
materials:
Steel: 100

View File

@@ -1460,6 +1460,9 @@
- type: Tag
id: UtilityBelt
- type: Tag
id: UtilityKnife
- type: Tag
id: Vegetable

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

View File

@@ -0,0 +1,36 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Icon sprited for SS14 by GitHub user sudobeans. Inhand sprites sprited for SS14 by Github user TiniestShark.",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "utility_knife_blade"
},
{
"name": "utility_knife_handle"
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
},
{
"name": "inhand-right-blade",
"directions": 4
},
{
"name": "inhand-left-blade",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B