diff --git a/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs b/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs index 69660882a6..29a00acff3 100644 --- a/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs +++ b/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs @@ -56,23 +56,39 @@ public sealed class ChargeActionSystem : SharedChargingSystem { base.Update(frameTime); - if (_playerManager.LocalEntity is not { } user) + if (!_timing.IsFirstTimePredicted) return; + if (_playerManager.LocalEntity is not { } user) + { + Reset(); + return; + } + if (!_mobState.IsAlive(user) || _statusEffects.HasStatusEffect(user, "Incorporeal")) + { + Reset(); return; + } - if (!_timing.IsFirstTimePredicted || _controller == null || _controller.SelectingTargetFor is not { } actionId) + if (_controller == null || _controller.SelectingTargetFor is not { } actionId) + { + Reset(); return; + } if (!_actionsSystem.TryGetActionData(actionId, out var baseAction) || baseAction is not BaseTargetActionComponent action || !action.IsChargeEnabled) + { + Reset(); return; + } if (!action.Enabled || action is { Charges: 0, RenewCharges: false } || action.Cooldown.HasValue && action.Cooldown.Value.End > _timing.CurTime) { + Reset(); return; } @@ -139,6 +155,17 @@ public sealed class ChargeActionSystem : SharedChargingSystem } } + private void Reset() + { + _charging = false; + _prevCharging = false; + _chargeTime = 0f; + _chargeLevel = 0; + _prevChargeLevel = 0; + _isChargingPlaying = false; + _isChargedPlaying = false; + } + private void HandleAction(EntityUid actionId, BaseTargetActionComponent action, EntityUid user, int chargeLevel) { var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition); diff --git a/Content.Client/_White/TTS/HumanoidProfileEditor.TTS.cs b/Content.Client/_White/TTS/HumanoidProfileEditor.TTS.cs index b60ec12d0f..28e5d2319f 100644 --- a/Content.Client/_White/TTS/HumanoidProfileEditor.TTS.cs +++ b/Content.Client/_White/TTS/HumanoidProfileEditor.TTS.cs @@ -87,7 +87,7 @@ public sealed partial class HumanoidProfileEditor if (_previewDummy is null || Profile is null) return; - _ttsSys.StopAllStreams(); + _ttsSys.StopCurrentTTS(_previewDummy.Value); _ttsMgr.RequestTTS(_previewDummy.Value, IoCManager.Resolve().Pick(_sampleText), Profile.Voice); } } \ No newline at end of file diff --git a/Content.Client/_White/TTS/TTSSystem.cs b/Content.Client/_White/TTS/TTSSystem.cs index ce533e1e63..fa10569647 100644 --- a/Content.Client/_White/TTS/TTSSystem.cs +++ b/Content.Client/_White/TTS/TTSSystem.cs @@ -1,38 +1,29 @@ -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using Content.Shared.Physics; +using System.IO; using Content.Shared._White; using Content.Shared._White.TTS; using Robust.Client.Audio; -using Robust.Client.GameObjects; -using Robust.Client.Graphics; -using Robust.Shared.Audio.Sources; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Components; using Robust.Shared.Configuration; -using Robust.Shared.Map; -using Robust.Shared.Physics; -using Robust.Shared.Physics.Systems; +// ReSharper disable InconsistentNaming namespace Content.Client._White.TTS; /// /// Plays TTS audio in world /// -// ReSharper disable once InconsistentNaming public sealed class TTSSystem : EntitySystem { - [Dependency] private readonly IAudioManager _audioSystem = default!; - [Dependency] private readonly IEntityManager _entity = default!; - [Dependency] private readonly IEyeManager _eye = default!; + [Dependency] private readonly IAudioManager _audioManager = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] private readonly SharedPhysicsSystem _broadPhase = default!; - [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; private float _volume; - private const int TTSCollisionMask = (int)CollisionGroup.Impassable; - - private readonly HashSet _currentStreams = new(); - private readonly Dictionary> _entityQueues = new(); + private readonly Dictionary _currentlyPlaying = new(); + private readonly Dictionary> _enquedStreams = new(); + + // Same as Server.ChatSystem.VoiceRange + private const float VoiceRange = 10; public override void Initialize() { @@ -44,54 +35,35 @@ public sealed class TTSSystem : EntitySystem { base.Shutdown(); _cfg.UnsubValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged); - EndStreams(); + ClearQueues(); } - // Little bit of duplication logic from AudioSystem public override void FrameUpdate(float frameTime) { - var streamToRemove = new HashSet(); - - var ourPos = _eye.CurrentEye.Position.Position; - foreach (var stream in _currentStreams) + foreach (var (uid, audioComponent) in _currentlyPlaying) { - if (!stream.Source.Playing || - !_entity.TryGetComponent(stream.Uid, out var meta) || - Deleted(stream.Uid, meta) || - !_entity.TryGetComponent(stream.Uid, out var xform)) - { - stream.Source.Dispose(); - streamToRemove.Add(stream); - continue; - } - - var mapPos = _transform.GetMapCoordinates(xform); - if (mapPos.MapId != MapId.Nullspace) - { - stream.Source.Position = mapPos.Position; - } - - if (mapPos.MapId != _eye.CurrentMap) + if (audioComponent is { Running: true, Playing: true }) { continue; } - var sourceRelative = ourPos - mapPos.Position; - var occlusion = 0f; - if (sourceRelative.Length() > 0) + if (!_enquedStreams.TryGetValue(uid, out var queue)) { - occlusion = _broadPhase.IntersectRayPenetration(mapPos.MapId, - new CollisionRay(mapPos.Position, sourceRelative.Normalized(), TTSCollisionMask), - sourceRelative.Length(), stream.Uid); + continue; } - stream.Source.Occlusion = occlusion; - } + if (!queue.TryDequeue(out var toPlay)) + { + continue; + } - foreach (var audioStream in streamToRemove) - { - _currentStreams.Remove(audioStream); - ProcessEntityQueue(audioStream.Uid); + var audio = _audioSystem.PlayEntity(toPlay.Stream, uid, toPlay.Params); + if (!audio.HasValue) + { + continue; + } + + _currentlyPlaying[uid] = audio.Value.Component; } } @@ -102,114 +74,76 @@ public sealed class TTSSystem : EntitySystem private void OnPlayTTS(PlayTTSEvent ev) { - if (_volume <= -20f) - return; - - var volume = _volume; - if (ev.BoostVolume) - volume += 5f; - if (!TryCreateAudioSource(ev.Data, out var source, volume)) - return; - - var stream = new AudioStream(GetEntity(ev.Uid), source); - AddEntityStreamToQueue(stream); + PlayTTS(GetEntity(ev.Uid), ev.Data, ev.BoostVolume ? _volume + 5 : _volume); } - public void PlayCustomText(string text) + public void PlayTTS(EntityUid uid, byte[] data, float volume) { - RaiseNetworkEvent(new RequestTTSEvent(text)); + if (_volume <= -20f) + { + return; + } + + var stream = CreateAudioStream(data); + + var audioParams = new AudioParams + { + Volume = volume, + MaxDistance = VoiceRange + }; + + var audioStream = new AudioStreamWithParams(stream, audioParams); + EnqueueAudio(uid, audioStream); } - private bool TryCreateAudioSource(byte[] data, [NotNullWhen(true)] out IAudioSource? source, float volume = 0f) + public void StopCurrentTTS(EntityUid uid) + { + if (!_currentlyPlaying.TryGetValue(uid, out var audio)) + { + return; + } + + _audioSystem.Stop(audio.Owner); + } + + private void EnqueueAudio(EntityUid uid, AudioStreamWithParams audioStream) + { + if (!_currentlyPlaying.ContainsKey(uid)) + { + var audio = _audioSystem.PlayEntity(audioStream.Stream, uid, audioStream.Params); + if (!audio.HasValue) + { + return; + } + + _currentlyPlaying[uid] = audio.Value.Component; + return; + } + + if (_enquedStreams.TryGetValue(uid, out var queue)) + { + queue.Enqueue(audioStream); + return; + } + + queue = new Queue(); + queue.Enqueue(audioStream); + _enquedStreams[uid] = queue; + } + + private void ClearQueues() + { + foreach (var (_, queue) in _enquedStreams) + { + queue.Clear(); + } + } + + private AudioStream CreateAudioStream(byte[] data) { var dataStream = new MemoryStream(data) { Position = 0 }; - var audioStream = _audioSystem.LoadAudioOggVorbis(dataStream); - source = _audioSystem.CreateAudioSource(audioStream); - if (source == null) - { - return false; - } - - source.Volume = volume == 0f ? _volume : volume; - return true; + return _audioManager.LoadAudioOggVorbis(dataStream); } - private void AddEntityStreamToQueue(AudioStream stream) - { - if (_entityQueues.TryGetValue(stream.Uid, out var queue)) - { - queue.Enqueue(stream); - } - else - { - _entityQueues.Add(stream.Uid, new Queue(new[] { stream })); - - if (!IsEntityCurrentlyPlayStream(stream.Uid)) - ProcessEntityQueue(stream.Uid); - } - } - - private bool IsEntityCurrentlyPlayStream(EntityUid uid) - { - return _currentStreams.Any(s => s.Uid == uid); - } - - private void ProcessEntityQueue(EntityUid uid) - { - if (TryTakeEntityStreamFromQueue(uid, out var stream)) - PlayEntity(stream); - } - - private bool TryTakeEntityStreamFromQueue(EntityUid uid, [NotNullWhen(true)] out AudioStream? stream) - { - if (_entityQueues.TryGetValue(uid, out var queue)) - { - stream = queue.Dequeue(); - if (queue.Count == 0) - _entityQueues.Remove(uid); - - return true; - } - - stream = null; - return false; - } - - private void PlayEntity(AudioStream stream) - { - if (!_entity.TryGetComponent(stream.Uid, out var xform)) - return; - - stream.Source.Position = _transform.GetWorldPosition(xform); - stream.Source.StartPlaying(); - _currentStreams.Add(stream); - } - - public void StopAllStreams() - { - foreach (var stream in _currentStreams) - { - stream.Source.StopPlaying(); - } - } - - private void EndStreams() - { - foreach (var stream in _currentStreams) - { - stream.Source.StopPlaying(); - stream.Source.Dispose(); - } - - _currentStreams.Clear(); - _entityQueues.Clear(); - } - - // ReSharper disable once InconsistentNaming - private sealed class AudioStream(EntityUid uid, IAudioSource source) - { - public EntityUid Uid { get; } = uid; - - public IAudioSource Source { get; } = source; - } + private record AudioStreamWithParams(AudioStream Stream, AudioParams Params); } \ No newline at end of file diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index 042bac3956..942882f7ae 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -152,7 +152,7 @@ public sealed partial class AdminVerbSystem Act = () => { // Fuck you. Burn Forever. - flammable.FireStacks = flammable.MaximumFireStacks; + flammable.FireStacks = FlammableSystem.MaximumFireStacks; _flammableSystem.Ignite(args.Target, args.User); var xform = Transform(args.Target); _popupSystem.PopupEntity(Loc.GetString("admin-smite-set-alight-self"), args.Target, diff --git a/Content.Server/Atmos/Components/FlammableComponent.cs b/Content.Server/Atmos/Components/FlammableComponent.cs index e00f5efbdc..679b551058 100644 --- a/Content.Server/Atmos/Components/FlammableComponent.cs +++ b/Content.Server/Atmos/Components/FlammableComponent.cs @@ -11,65 +11,49 @@ namespace Content.Server.Atmos.Components [ViewVariables(VVAccess.ReadWrite)] [DataField] - public bool OnFire; + public bool OnFire { get; set; } [ViewVariables(VVAccess.ReadWrite)] [DataField] - public float FireStacks; + public float FireStacks { get; set; } [ViewVariables(VVAccess.ReadWrite)] - [DataField] - public float MaximumFireStacks = 10f; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField] - public float MinimumFireStacks = -10f; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField] - public string FlammableFixtureID = "flammable"; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField] - public float MinIgnitionTemperature = 373.15f; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField] + [DataField("fireSpread")] public bool FireSpread { get; private set; } = false; [ViewVariables(VVAccess.ReadWrite)] - [DataField] + [DataField("canResistFire")] public bool CanResistFire { get; private set; } = false; - [DataField(required: true)] + [DataField("damage", required: true)] [ViewVariables(VVAccess.ReadWrite)] public DamageSpecifier Damage = new(); // Empty by default, we don't want any funny NREs. /// /// Used for the fixture created to handle passing firestacks when two flammable objects collide. /// - [DataField] + [DataField("flammableCollisionShape")] public IPhysShape FlammableCollisionShape = new PhysShapeCircle(0.35f); /// /// Should the component be set on fire by interactions with isHot entities /// [ViewVariables(VVAccess.ReadWrite)] - [DataField] + [DataField("alwaysCombustible")] public bool AlwaysCombustible = false; /// /// Can the component anyhow lose its FireStacks? /// [ViewVariables(VVAccess.ReadWrite)] - [DataField] + [DataField("canExtinguish")] public bool CanExtinguish = true; /// /// How many firestacks should be applied to component when being set on fire? /// [ViewVariables(VVAccess.ReadWrite)] - [DataField] + [DataField("firestacksOnIgnite")] public float FirestacksOnIgnite = 2.0f; /// diff --git a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs index bc6e56e765..84f7616675 100644 --- a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs +++ b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs @@ -52,11 +52,13 @@ namespace Content.Server.Atmos.EntitySystems [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SpellBladeSystem _spellBlade = default!; // WD - private EntityQuery _physicsQuery; - - // This should probably be moved to the component, requires a rewrite, all fires tick at the same time + public const float MinimumFireStacks = -10f; + public const float MaximumFireStacks = 20f; private const float UpdateTime = 1f; + public const float MinIgnitionTemperature = 373.15f; + public const string FlammableFixtureID = "flammable"; + private float _timer; private readonly Dictionary, float> _fireEvents = new(); @@ -65,8 +67,6 @@ namespace Content.Server.Atmos.EntitySystems { UpdatesAfter.Add(typeof(AtmosphereSystem)); - _physicsQuery = GetEntityQuery(); - SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnInteractUsing); SubscribeLocalEvent(OnCollide); @@ -141,7 +141,7 @@ namespace Content.Server.Atmos.EntitySystems if (!TryComp(uid, out var body)) return; - _fixture.TryCreateFixture(uid, component.FlammableCollisionShape, component.FlammableFixtureID, hard: false, + _fixture.TryCreateFixture(uid, component.FlammableCollisionShape, FlammableFixtureID, hard: false, collisionMask: (int) CollisionGroup.FullTileLayer, body: body); } @@ -199,7 +199,7 @@ namespace Content.Server.Atmos.EntitySystems // Normal hard collisions, though this isn't generally possible since most flammable things are mobs // which don't collide with one another, shouldn't work here. - if (args.OtherFixtureId != flammable.FlammableFixtureID && args.OurFixtureId != flammable.FlammableFixtureID) + if (args.OtherFixtureId != FlammableFixtureID && args.OurFixtureId != FlammableFixtureID) return; if (!flammable.FireSpread) @@ -211,30 +211,49 @@ namespace Content.Server.Atmos.EntitySystems if (!flammable.OnFire && !otherFlammable.OnFire) return; // Neither are on fire - // Both are on fire -> equalize fire stacks. - // Weight each thing's firestacks by its mass - var mass1 = 1f; - var mass2 = 1f; - if (_physicsQuery.TryComp(uid, out var physics) && _physicsQuery.TryComp(otherUid, out var otherPhys)) + // WD START + var weHold = _spellBlade.IsHoldingItemWithComponent(uid); + var theyHold = _spellBlade.IsHoldingItemWithComponent(otherUid); + // WD END + + if (flammable.OnFire && otherFlammable.OnFire) { - mass1 = physics.Mass; - mass2 = otherPhys.Mass; + if (weHold && !theyHold || theyHold && !weHold) // WD + return; + // Both are on fire -> equalize fire stacks. + var avg = (flammable.FireStacks + otherFlammable.FireStacks) / 2; + flammable.FireStacks = flammable.CanExtinguish ? avg : Math.Max(flammable.FireStacks, avg); + otherFlammable.FireStacks = otherFlammable.CanExtinguish ? avg : Math.Max(otherFlammable.FireStacks, avg); + UpdateAppearance(uid, flammable); + UpdateAppearance(otherUid, otherFlammable); + return; } - // when the thing on fire is more massive than the other, the following happens: - // - the thing on fire loses a small number of firestacks - // - the other thing gains a large number of firestacks - // so a person on fire engulfs a mouse, but an engulfed mouse barely does anything to a person - var total = mass1 + mass2; - var avg = (flammable.FireStacks + otherFlammable.FireStacks) / total; - - // swap the entity losing stacks depending on whichever has the most firestack kilos - var (src, dest) = flammable.FireStacks * mass1 > otherFlammable.FireStacks * mass2 - ? (-1f, 1f) - : (1f, -1f); - // bring each entity to the same firestack mass, firestacks being scaled by the other's mass - AdjustFireStacks(uid, src * avg * mass2, flammable, ignite: true); - AdjustFireStacks(otherUid, dest * avg * mass1, otherFlammable, ignite: true); + // Only one is on fire -> attempt to spread the fire. + if (flammable.OnFire) + { + if (theyHold) // WD + return; + otherFlammable.FireStacks += flammable.FireStacks / 2; + Ignite(otherUid, uid, otherFlammable); + if (flammable.CanExtinguish) + { + flammable.FireStacks /= 2; + UpdateAppearance(uid, flammable); + } + } + else + { + if (weHold) // WD + return; + flammable.FireStacks += otherFlammable.FireStacks / 2; + Ignite(uid, otherUid, flammable); + if (otherFlammable.CanExtinguish) + { + otherFlammable.FireStacks /= 2; + UpdateAppearance(otherUid, otherFlammable); + } + } } private void OnIsHot(EntityUid uid, FlammableComponent flammable, IsHotEvent args) @@ -244,7 +263,7 @@ namespace Content.Server.Atmos.EntitySystems private void OnTileFire(Entity ent, ref TileFireEvent args) { - var tempDelta = args.Temperature - ent.Comp.MinIgnitionTemperature; + var tempDelta = args.Temperature - MinIgnitionTemperature; _fireEvents.TryGetValue(ent, out var maxTemp); @@ -272,30 +291,17 @@ namespace Content.Server.Atmos.EntitySystems _appearance.SetData(uid, ToggleableLightVisuals.Enabled, flammable.OnFire, appearance); } - public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null, bool ignite = false) + public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null) { if (!Resolve(uid, ref flammable)) return; - SetFireStacks(uid, flammable.FireStacks + relativeFireStacks, flammable, ignite); - } + flammable.FireStacks = MathF.Min(MathF.Max(MinimumFireStacks, flammable.FireStacks + relativeFireStacks), MaximumFireStacks); - public void SetFireStacks(EntityUid uid, float stacks, FlammableComponent? flammable = null, bool ignite = false) - { - if (!Resolve(uid, ref flammable)) - return; - - flammable.FireStacks = MathF.Min(MathF.Max(flammable.MinimumFireStacks, stacks), flammable.MaximumFireStacks); - - if (flammable.FireStacks <= 0) - { + if (flammable.OnFire && flammable.FireStacks <= 0) Extinguish(uid, flammable); - } else - { - flammable.OnFire = ignite; UpdateAppearance(uid, flammable); - } } public void Extinguish(EntityUid uid, FlammableComponent? flammable = null) @@ -444,11 +450,13 @@ namespace Content.Server.Atmos.EntitySystems EnsureComp(uid); _ignitionSourceSystem.SetIgnited(uid); + var damageScale = MathF.Min( flammable.FireStacks, 5); + if (TryComp(uid, out TemperatureComponent? temp)) - _temperatureSystem.ChangeHeat(uid, 12500 * flammable.FireStacks, false, temp); + _temperatureSystem.ChangeHeat(uid, 12500 * damageScale, false, temp); if (!_spellBlade.IsHoldingItemWithComponent(uid)) // WD EDIT - _damageableSystem.TryChangeDamage(uid, flammable.Damage * flammable.FireStacks, interruptsDoAfters: false); + _damageableSystem.TryChangeDamage(uid, flammable.Damage * damageScale, interruptsDoAfters: false); AdjustFireStacks(uid, flammable.FirestackFade * (flammable.Resisting ? 10f : 1f), flammable); } diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index 1a3c0473a4..896e1e944c 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -108,13 +108,18 @@ public partial class SeedData /// /// If true, the properties of this seed cannot be modified. + /// to spare others like me: this DOES NOT prevent mutations /// [DataField("immutable")] public bool Immutable; + /// + /// If true, you cannot clip this plant for more seeds, used for special plants such as the gnome plant + /// + [DataField("unclippable")] public bool Unclippable; + /// /// If true, there is only a single reference to this seed and it's properties can be directly modified without /// needing to clone the seed. - /// [ViewVariables] public bool Unique = false; // seed-prototypes or yaml-defined seeds for entity prototypes will not generally be unique. #endregion @@ -255,6 +260,7 @@ public partial class SeedData { DebugTools.Assert(!Immutable, "There should be no need to clone an immutable seed."); + var newSeed = new SeedData { Name = Name, @@ -290,6 +296,7 @@ public partial class SeedData HarvestRepeat = HarvestRepeat, Potency = Potency, + Unclippable = Unclippable, Seedless = Seedless, Viable = Viable, Slip = Slip, diff --git a/Content.Server/Botany/Systems/PlantHolderSystem.cs b/Content.Server/Botany/Systems/PlantHolderSystem.cs index 4e35495f43..e47e703364 100644 --- a/Content.Server/Botany/Systems/PlantHolderSystem.cs +++ b/Content.Server/Botany/Systems/PlantHolderSystem.cs @@ -245,6 +245,13 @@ public sealed class PlantHolderSystem : EntitySystem _popup.PopupCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"), args.User); return; } + //rejects clipping of unclippable plants + if (component.Seed.Unclippable) + { + _popup.PopupCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"), args.User); + return; + } + if (component.Sampled) { diff --git a/Content.Server/Magic/MagicSystem.cs b/Content.Server/Magic/MagicSystem.cs index a512446826..8b4ce53231 100644 --- a/Content.Server/Magic/MagicSystem.cs +++ b/Content.Server/Magic/MagicSystem.cs @@ -164,8 +164,7 @@ public sealed class MagicSystem : EntitySystem if (!_wizardSpells.CanCast(args)) // WD EDIT return; - args.Handled = true; - Speak(args); + _wizardSpells.Cast(args); // WD EDIT var transform = Transform(args.Performer); var coords = transform.Coordinates; @@ -190,9 +189,7 @@ public sealed class MagicSystem : EntitySystem if (!_wizardSpells.CanCast(ev)) // WD EDIT return; - ev.Handled = true; - - Speak(ev); + _wizardSpells.Cast(ev); // WD EDIT var direction = _transformSystem.GetMapCoordinates(ev.Target).Position - _transformSystem.GetMapCoordinates(ev.Performer).Position; var impulseVector = direction * 10000; diff --git a/Content.Server/Repairable/RepairableSystem.cs b/Content.Server/Repairable/RepairableSystem.cs index 5bd580756d..57afea39cd 100644 --- a/Content.Server/Repairable/RepairableSystem.cs +++ b/Content.Server/Repairable/RepairableSystem.cs @@ -6,15 +6,37 @@ using Content.Shared.Popups; using Content.Shared.Repairable; using Content.Shared.Tools; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; +using Content.Server.DoAfter; +using Content.Server.EUI; +using Content.Server.Ghost; +using Content.Server.Popups; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Interaction; +using Content.Shared.Interaction.Components; +using Content.Shared.Interaction.Events; +using Content.Shared.Mind; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Robust.Shared.Player; +using Robust.Shared.Timing; +using Content.Shared.Tools.Components; +using Content.Server.Construction.Conditions; +//many of these arent reqired but some seem neessesary so ill leave them for now namespace Content.Server.Repairable { public sealed class RepairableSystem : SharedRepairableSystem { + [Dependency] private readonly EuiManager _euiManager = default!; [Dependency] private readonly SharedToolSystem _toolSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly IAdminLogManager _adminLogger= default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + [Dependency] private readonly SharedMindSystem _mind = default!; public override void Initialize() { @@ -24,6 +46,8 @@ namespace Content.Server.Repairable private void OnRepairFinished(EntityUid uid, RepairableComponent component, RepairFinishedEvent args) { + ICommonSession? session = null; + if (args.Cancelled) return; @@ -34,15 +58,36 @@ namespace Content.Server.Repairable { var damageChanged = _damageableSystem.TryChangeDamage(uid, component.Damage, true, false, origin: args.User); _adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} by {damageChanged?.GetTotal()}"); - } - + } else { // Repair all damage _damageableSystem.SetAllDamage(uid, damageable, 0); _adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} back to full health"); - } + // this is to revive gnomes and call their ghost back + //check for target for threshholds, i hardly understand WHY this works but it does so i wont touch it + if (TryComp(uid, out MobThresholdsComponent? mobthresholds)) + { + if (_mobThreshold.TryGetThresholdForState(uid, MobState.Dead, out var threshold) && + TryComp(uid, out var damageableComponent) && + damageableComponent.TotalDamage < threshold) + { + _mobState.ChangeMobState(uid, MobState.Alive, null, uid); + } + if (_mind.TryGetMind(uid, out _, out var mind) && + mind.Session is { } playerSession) + { + session = playerSession; + // notify them they're being revived. + if (mind.CurrentEntity != uid) + { + _euiManager.OpenEui(new ReturnToBodyEui(mind, _mind), session); + } + } + } + + } var str = Loc.GetString("comp-repairable-repair", ("target", uid), ("tool", args.Used!)); diff --git a/Content.Server/Speech/Components/GnomeAccentComponent.cs b/Content.Server/Speech/Components/GnomeAccentComponent.cs new file mode 100644 index 0000000000..939df9f753 --- /dev/null +++ b/Content.Server/Speech/Components/GnomeAccentComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server.Speech.Components; + +/// +/// garden time +/// +[RegisterComponent] +public sealed partial class GnomeAccentComponent : Component +{} diff --git a/Content.Server/Speech/EntitySystems/GnomeAccentSystem.cs b/Content.Server/Speech/EntitySystems/GnomeAccentSystem.cs new file mode 100644 index 0000000000..0ea3a311cc --- /dev/null +++ b/Content.Server/Speech/EntitySystems/GnomeAccentSystem.cs @@ -0,0 +1,52 @@ +using Content.Server.Speech.Components; +using System.Text.RegularExpressions; + +namespace Content.Server.Speech.EntitySystems; + +/// +/// System that Gnomes the Gnomes talking +/// +public sealed class GnomeAccentSystem : EntitySystem +{ + [Dependency] private readonly ReplacementAccentSystem _replacement = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAccentGet); + } + public string Accentuate(string message, GnomeAccentComponent component) + { + var msg = message; + + msg = _replacement.ApplyReplacements(msg, "gnome"); + + // Пиздец, а не код + + msg = Regex.Replace(msg, @"(? Meteors = new(); [DataField] - public MinMax Waves = new(3, 3); + public MinMax Waves = new(2, 4); [DataField] public MinMax MeteorsPerWave = new(3, 4); [DataField] - public MinMax WaveCooldown = new (10, 60); + public MinMax WaveCooldown = new (30, 60); } diff --git a/Content.Server/_White/Announcement/ArrivalNotificationSystem.cs b/Content.Server/_White/Announcement/ArrivalNotificationSystem.cs new file mode 100644 index 0000000000..a70a2bedba --- /dev/null +++ b/Content.Server/_White/Announcement/ArrivalNotificationSystem.cs @@ -0,0 +1,69 @@ +using System.Globalization; +using Content.Server.Chat.Systems; +using Content.Server.GameTicking; +using Content.Server.Radio.EntitySystems; +using Content.Shared._White.Announcement; +using Content.Shared.Radio; +using Content.Shared.Roles; +using Robust.Shared.Prototypes; + +namespace Content.Server._White.Announcement; + +public sealed class ArrivalNotificationSystem : EntitySystem +{ + [Dependency] private readonly ChatSystem _chatSystem = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly RadioSystem _radioSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeAllEvent(OnPlayerSpawn); + } + + private void OnPlayerSpawn(PlayerSpawnCompleteEvent args) + { + if (args.JobId == null) + return; + + if (!_prototypeManager.TryIndex(args.JobId, out var jobPrototype)) + return; + + if (jobPrototype.AnnouncementPrototype == null) + return; + + if (!_prototypeManager.TryIndex(jobPrototype.AnnouncementPrototype, out var notification)) + return; + + var message = GetMessage(args.Mob, + jobPrototype, + notification.UseGlobalAnnouncement ? notification.GlobalMessage : notification.Message); + + var senderName = Loc.GetString("head-arrived-sender"); + var source = args.Station; + + if (notification.UseGlobalAnnouncement) + _chatSystem.DispatchGlobalAnnouncement(message, senderName, colorOverride: Color.Gold); + + message = GetMessage(args.Mob, jobPrototype, notification.Message); // Changing message type for radio notification + + foreach (var channel in notification.RadioChannelsPrototypes) + { + if (!_prototypeManager.TryIndex(channel, out _)) + continue; + + _radioSystem.SendRadioMessage(source, message, channel, args.Mob); + } + + } + + private string GetMessage(EntityUid mob, JobPrototype jobPrototype, string type) + { + var message = Loc.GetString(type, + ("character", MetaData(mob).EntityName), + ("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Loc.GetString(jobPrototype.Name)))); + + return message; + } +} diff --git a/Content.Server/_White/Other/DeathGasps/DeathGaspsComponent.cs b/Content.Server/_White/Other/DeathGasps/DeathGaspsComponent.cs index 7d5a3b8358..b9f38193bb 100644 --- a/Content.Server/_White/Other/DeathGasps/DeathGaspsComponent.cs +++ b/Content.Server/_White/Other/DeathGasps/DeathGaspsComponent.cs @@ -1,6 +1,16 @@ +using Robust.Shared.Audio; + namespace Content.Server._White.Other.DeathGasps; [RegisterComponent] public sealed partial class DeathGaspsComponent : Component { + [DataField] + public SoundSpecifier DeathSounds = new SoundCollectionSpecifier("deathSounds"); + + [DataField] + public SoundSpecifier HeartSounds = new SoundCollectionSpecifier("heartSounds"); + + [DataField] + public bool CanOtherHearDeathSound; } diff --git a/Content.Server/_White/Other/DeathGasps/OnDeath.cs b/Content.Server/_White/Other/DeathGasps/OnDeath.cs index 3832a9135e..be870db706 100644 --- a/Content.Server/_White/Other/DeathGasps/OnDeath.cs +++ b/Content.Server/_White/Other/DeathGasps/OnDeath.cs @@ -16,8 +16,7 @@ public sealed class OnDeath : EntitySystem } private readonly Dictionary _playingStreams = new(); - private static readonly SoundSpecifier DeathSounds = new SoundCollectionSpecifier("deathSounds"); - private static readonly SoundSpecifier HeartSounds = new SoundCollectionSpecifier("heartSounds"); + private void HandleDeathEvent(EntityUid uid, DeathGaspsComponent component, MobStateChangedEvent args) { @@ -31,23 +30,23 @@ public sealed class OnDeath : EntitySystem StopPlayingStream(uid); break; case MobState.Critical: - PlayPlayingStream(uid); + PlayPlayingStream(uid, component); break; case MobState.Dead: StopPlayingStream(uid); - PlayDeathSound(uid); + PlayDeathSound(uid, component); break; } } - private void PlayPlayingStream(EntityUid uid) + private void PlayPlayingStream(EntityUid uid, DeathGaspsComponent component) { if (_playingStreams.TryGetValue(uid, out var currentStream)) { _audio.Stop(currentStream); } - var newStream = _audio.PlayEntity(HeartSounds, uid, uid, AudioParams.Default.WithLoop(true)); + var newStream = _audio.PlayEntity(component.HeartSounds, uid, uid, AudioParams.Default.WithLoop(true)); if (newStream.HasValue) { @@ -64,9 +63,12 @@ public sealed class OnDeath : EntitySystem _playingStreams.Remove(uid); } - private void PlayDeathSound(EntityUid uid) + private void PlayDeathSound(EntityUid uid, DeathGaspsComponent component) { - _audio.PlayEntity(DeathSounds, uid, uid, AudioParams.Default); + if (component.CanOtherHearDeathSound) + _audio.PlayPvs(component.DeathSounds, uid, AudioParams.Default); + else + _audio.PlayEntity(component.DeathSounds, uid, uid, AudioParams.Default); } private void OnDetach(EntityUid uid, DeathGaspsComponent component, PlayerDetachedEvent args) diff --git a/Content.Server/_White/TTS/TTSSystem.cs b/Content.Server/_White/TTS/TTSSystem.cs index b1ec1082ea..ba8455948a 100644 --- a/Content.Server/_White/TTS/TTSSystem.cs +++ b/Content.Server/_White/TTS/TTSSystem.cs @@ -63,7 +63,9 @@ public sealed partial class TTSSystem : EntitySystem Filter filter; if (ev.Global) + { filter = Filter.Broadcast(); + } else { var station = _stationSystem.GetOwningStation(ev.Source); @@ -132,11 +134,7 @@ public sealed partial class TTSSystem : EntitySystem private async void OnEntitySpoke(EntityUid uid, SharedTTSComponent component, EntitySpokeEvent args) { - if (!_isEnabled || - args.Message.Length > MaxMessageChars) - return; - - if (string.IsNullOrEmpty(_apiUrl)) + if (!_isEnabled || string.IsNullOrEmpty(_apiUrl) || args.Message.Length > MaxMessageChars) { return; } @@ -154,6 +152,7 @@ public sealed partial class TTSSystem : EntitySystem var soundData = await GenerateTTS(uid, message, protoVoice.Speaker); if (soundData is null) return; + var ttsEvent = new PlayTTSEvent(GetNetEntity(uid), soundData, false); // Say @@ -182,7 +181,6 @@ public sealed partial class TTSSystem : EntitySystem var sourcePos = _xforms.GetWorldPosition(xformQuery.GetComponent(uid), xformQuery); var receptions = Filter.Pvs(uid).Recipients; - foreach (var session in receptions) { if (!session.AttachedEntity.HasValue) diff --git a/Content.Server/_White/Wizard/Charging/ChargingSystem.cs b/Content.Server/_White/Wizard/Charging/ChargingSystem.cs index f5e8f840fe..63b36002bc 100644 --- a/Content.Server/_White/Wizard/Charging/ChargingSystem.cs +++ b/Content.Server/_White/Wizard/Charging/ChargingSystem.cs @@ -1,6 +1,7 @@ using Content.Shared._White.Wizard; using Content.Shared._White.Wizard.Charging; using Content.Shared.Follower; +using Content.Shared.Mobs; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; @@ -25,10 +26,13 @@ public sealed class ChargingSystem : SharedChargingSystem SubscribeNetworkEvent(OnCharging); SubscribeNetworkEvent(OnCharged); SubscribeNetworkEvent(OnStop); + SubscribeLocalEvent(OnDetach); + SubscribeLocalEvent(OnStateChanged); SubscribeNetworkEvent(Add); SubscribeNetworkEvent(Remove); + } #region Audio @@ -103,40 +107,29 @@ public sealed class ChargingSystem : SharedChargingSystem if (user == null) return; - if (_chargingLoops.TryGetValue(user.Value, out var currentStream)) - { - _audio.Stop(currentStream); - _chargingLoops.Remove(user.Value); - } - - if (_chargedLoop.TryGetValue(user.Value, out var chargedLoop)) - { - _audio.Stop(chargedLoop); - _chargedLoop.Remove(user.Value); - } - } - - private void OnDetach(PlayerDetachedEvent msg, EntitySessionEventArgs args) - { - var user = msg.Entity; - - if (_chargingLoops.TryGetValue(user, out var currentStream)) - { - _audio.Stop(currentStream); - _chargingLoops.Remove(user); - } - - if (_chargedLoop.TryGetValue(user, out var chargedLoop)) - { - _audio.Stop(chargedLoop); - _chargedLoop.Remove(user); - } + StopAllSounds(user.Value); } #endregion #region Charges + private void OnDetach(PlayerDetachedEvent msg) + { + var user = msg.Entity; + + RemoveAllCharges(user); + StopAllSounds(user); + } + + private void OnStateChanged(MobStateChangedEvent ev) + { + var user = ev.Target; + + RemoveAllCharges(user); + StopAllSounds(user); + } + private void Add(AddWizardChargeEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity != null) @@ -153,6 +146,21 @@ public sealed class ChargingSystem : SharedChargingSystem #region Helpers + public void StopAllSounds(EntityUid uid) + { + if (_chargingLoops.TryGetValue(uid, out var currentStream)) + { + _audio.Stop(currentStream); + _chargingLoops.Remove(uid); + } + + if (_chargedLoop.TryGetValue(uid, out var chargedLoop)) + { + _audio.Stop(chargedLoop); + _chargedLoop.Remove(uid); + } + } + public void AddCharge(EntityUid uid, string msgChargeProto) { var itemEnt = Spawn(msgChargeProto, Transform(uid).Coordinates); diff --git a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs index 3a43e05cf9..1599db00fd 100644 --- a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs +++ b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Numerics; using Content.Server._White.Cult; using Content.Server._White.IncorporealSystem; +using Content.Server._White.Wizard.Charging; using Content.Server._White.Wizard.Magic.Amaterasu; using Content.Server._White.Wizard.Magic.Other; using Content.Server._White.Wizard.Magic.TeslaProjectile; @@ -80,6 +81,7 @@ public sealed class WizardSpellsSystem : EntitySystem [Dependency] private readonly EuiManager _euiManager = default!; [Dependency] private readonly MindSystem _mindSystem = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!; + [Dependency] private readonly ChargingSystem _charging = default!; #endregion @@ -125,7 +127,7 @@ public sealed class WizardSpellsSystem : EntitySystem return; } - msg.Handled = true; + Cast(msg); } #endregion @@ -143,8 +145,7 @@ public sealed class WizardSpellsSystem : EntitySystem var comp = EnsureComp(ent); comp.Uid = msg.Performer; - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -187,8 +188,7 @@ public sealed class WizardSpellsSystem : EntitySystem _standing.TryLieDown(uid); _standing.TryLieDown(target); - msg.Handled = true; - Speak(msg); + Cast(msg); SwapComponent(uid, target); SwapComponent(uid, target); @@ -213,8 +213,7 @@ public sealed class WizardSpellsSystem : EntitySystem _euiManager.OpenEui(eui, actor.PlayerSession); eui.StateDirty(); - msg.Handled = true; - Speak(msg); + Cast(msg, false); } #endregion @@ -264,8 +263,7 @@ public sealed class WizardSpellsSystem : EntitySystem _handsSystem.TryForcePickupAnyHand(msg.Performer, recallComponent.Item.Value); _audio.PlayPvs(recallComponent.RecallSound, msg.Performer); - msg.Handled = true; - Speak(msg); + Cast(msg); return; } @@ -293,8 +291,7 @@ public sealed class WizardSpellsSystem : EntitySystem Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates); - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -317,8 +314,7 @@ public sealed class WizardSpellsSystem : EntitySystem Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates); - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -340,8 +336,7 @@ public sealed class WizardSpellsSystem : EntitySystem Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates); - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -357,8 +352,7 @@ public sealed class WizardSpellsSystem : EntitySystem _empSystem.EmpPulse(coords, 15, 1000000, 60f); - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -381,8 +375,7 @@ public sealed class WizardSpellsSystem : EntitySystem _statusEffectsSystem.TryAddStatusEffect(msg.Performer, "Incorporeal", TimeSpan.FromSeconds(10), false); - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -434,8 +427,7 @@ public sealed class WizardSpellsSystem : EntitySystem Spawn("AdminInstantEffectSmoke3", oldCoords); Spawn("AdminInstantEffectSmoke3", coords); - msg.Handled = true; - Speak(msg); + Cast(msg); } #endregion @@ -460,9 +452,7 @@ public sealed class WizardSpellsSystem : EntitySystem break; } - SetCooldown(msg.Action, msg.ActionUseType); - msg.Handled = true; - Speak(msg); + Cast(msg); } private void ForcewallSpellDefault(ForceWallSpellEvent msg) @@ -533,9 +523,7 @@ public sealed class WizardSpellsSystem : EntitySystem if (!result) return; - SetCooldown(msg.Action, msg.ActionUseType); - msg.Handled = true; - Speak(msg); + Cast(msg); } private void CardsSpellDefault(CardsSpellEvent msg) @@ -638,9 +626,7 @@ public sealed class WizardSpellsSystem : EntitySystem if (!result) return; - SetCooldown(msg.Action, msg.ActionUseType); - msg.Handled = true; - Speak(msg); + Cast(msg); } private void FireballSpellDefault(FireballSpellEvent msg) @@ -725,9 +711,7 @@ public sealed class WizardSpellsSystem : EntitySystem if (!result) return; - SetCooldown(msg.Action, msg.ActionUseType); - msg.Handled = true; - Speak(msg); + Cast(msg); } private bool ForceSpellAlt(ForceSpellEvent msg) @@ -782,9 +766,7 @@ public sealed class WizardSpellsSystem : EntitySystem if (!result) return; - SetCooldown(msg.Action, msg.ActionUseType); - msg.Handled = true; - Speak(msg); + Cast(msg); } private bool ArcSpellDefault(ArcSpellEvent msg) @@ -844,6 +826,17 @@ public sealed class WizardSpellsSystem : EntitySystem RaiseLocalEvent(uid, new EnergyDomeClothesTurnOffEvent()); } + public void Cast(BaseActionEvent msg, bool removeAllCharges = true) + { + SetCooldown(msg.Action, msg.ActionUseType); + msg.Handled = true; + Speak(msg); + if (!removeAllCharges) + return; + _charging.RemoveAllCharges(msg.Performer); + _charging.StopAllSounds(msg.Performer); + } + public bool CanCast(BaseActionEvent msg) { return !msg.Handled && CheckRequirements(msg.Action, msg.Performer) && diff --git a/Content.Server/_White/Wizard/Teleport/WizardTeleportSpellEui.cs b/Content.Server/_White/Wizard/Teleport/WizardTeleportSpellEui.cs index c9848c24bd..19e74ce393 100644 --- a/Content.Server/_White/Wizard/Teleport/WizardTeleportSpellEui.cs +++ b/Content.Server/_White/Wizard/Teleport/WizardTeleportSpellEui.cs @@ -1,4 +1,5 @@ -using Content.Server.EUI; +using Content.Server._White.Wizard.Charging; +using Content.Server.EUI; using Content.Server.Popups; using Content.Shared._White.Wizard.Teleport; using Content.Shared.Eui; @@ -15,6 +16,7 @@ public sealed class WizardTeleportSpellEui : BaseEui private readonly TeleportLocationSystem _teleportLocation; private readonly PullingSystem _pulling; private readonly PopupSystem _popupSystem; + private readonly ChargingSystem _charging; private readonly EntityUid _performer; @@ -28,6 +30,7 @@ public sealed class WizardTeleportSpellEui : BaseEui _pulling = _entityManager.System(); _teleportLocation = _entityManager.System(); _popupSystem = _entityManager.System(); + _charging = _entityManager.System(); _performer = performer; @@ -107,6 +110,9 @@ public sealed class WizardTeleportSpellEui : BaseEui _entityManager.SpawnEntity("AdminInstantEffectSmoke10", oldCoords); _entityManager.SpawnEntity("AdminInstantEffectSmoke10", coords); + _charging.RemoveAllCharges(_performer); + _charging.StopAllSounds(_performer); + Close(); } } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index bf207c1ee1..c8b854d0c6 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -125,13 +125,13 @@ namespace Content.Shared.CCVar /// Minimum time between meteor swarms in minutes. /// public static readonly CVarDef - MeteorSwarmMinTime = CVarDef.Create("events.meteor_swarm_min_time", 12.5f, CVar.ARCHIVE | CVar.SERVERONLY); + MeteorSwarmMinTime = CVarDef.Create("events.meteor_swarm_min_time", 20f, CVar.ARCHIVE | CVar.SERVERONLY); /// /// Maximum time between meteor swarms in minutes. /// public static readonly CVarDef - MeteorSwarmMaxTime = CVarDef.Create("events.meteor_swarm_max_time", 17.5f, CVar.ARCHIVE | CVar.SERVERONLY); + MeteorSwarmMaxTime = CVarDef.Create("events.meteor_swarm_max_time", 30f, CVar.ARCHIVE | CVar.SERVERONLY); /* * Game diff --git a/Content.Shared/Roles/JobPrototype.cs b/Content.Shared/Roles/JobPrototype.cs index 54f5fa4f4c..bd40d0803f 100644 --- a/Content.Shared/Roles/JobPrototype.cs +++ b/Content.Shared/Roles/JobPrototype.cs @@ -19,16 +19,16 @@ namespace Content.Shared.Roles [IdDataField] public string ID { get; private set; } = default!; - [DataField("playTimeTracker", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] public string PlayTimeTracker { get; private set; } = string.Empty; - [DataField("supervisors")] + [DataField] public string Supervisors { get; private set; } = "nobody"; /// /// The name of this job as displayed to players. /// - [DataField("name")] + [DataField] public string Name { get; private set; } = string.Empty; [ViewVariables(VVAccess.ReadOnly)] @@ -37,22 +37,25 @@ namespace Content.Shared.Roles /// /// The name of this job as displayed to players. /// - [DataField("description")] + [DataField] public string? Description { get; private set; } [ViewVariables(VVAccess.ReadOnly)] public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description); - [DataField("requirements")] + [DataField] public HashSet? Requirements; - [DataField("joinNotifyCrew")] + [DataField] public bool JoinNotifyCrew { get; private set; } = false; - [DataField("requireAdminNotify")] + [DataField] + public string? AnnouncementPrototype; + + [DataField] public bool RequireAdminNotify { get; private set; } = false; - [DataField("setPreference")] + [DataField] public bool SetPreference { get; private set; } = true; /// @@ -62,14 +65,14 @@ namespace Content.Shared.Roles [DataField] public bool? OverrideConsoleVisibility { get; private set; } = null; - [DataField("canBeAntag")] + [DataField] public bool CanBeAntag { get; private set; } = true; /// /// Whether this job is a head. /// The job system will try to pick heads before other jobs on the same priority level. /// - [DataField("weight")] + [DataField] public int Weight { get; private set; } /// @@ -86,10 +89,10 @@ namespace Content.Shared.Roles /// A numerical score for how much easier this job is for antagonists. /// For traitors, reduces starting TC by this amount. Other gamemodes can use it for whatever they find fitting. /// - [DataField("antagAdvantage")] + [DataField] public int AntagAdvantage = 0; - [DataField("startingGear", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string? StartingGear { get; private set; } /// @@ -97,28 +100,28 @@ namespace Content.Shared.Roles /// Starting gear will be ignored. /// If you want to just add special attributes to a humanoid, use AddComponentSpecial instead. /// - [DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string? JobEntity = null; - [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string Icon { get; private set; } = "JobIconUnknown"; - [DataField("special", serverOnly: true)] + [DataField(serverOnly: true)] public JobSpecial[] Special { get; private set; } = Array.Empty(); - [DataField("access")] + [DataField] public IReadOnlyCollection> Access { get; private set; } = Array.Empty>(); - [DataField("accessGroups")] + [DataField] public IReadOnlyCollection> AccessGroups { get; private set; } = Array.Empty>(); - [DataField("extendedAccess")] + [DataField] public IReadOnlyCollection> ExtendedAccess { get; private set; } = Array.Empty>(); - [DataField("extendedAccessGroups")] + [DataField] public IReadOnlyCollection> ExtendedAccessGroups { get; private set; } = Array.Empty>(); - [DataField("whitelistedSpecies")] + [DataField] public IReadOnlyCollection> WhitelistedSpecies { get; private set; } = Array.Empty>(); } diff --git a/Content.Shared/_White/Announcement/ArrivalNotificationPrototype.cs b/Content.Shared/_White/Announcement/ArrivalNotificationPrototype.cs new file mode 100644 index 0000000000..2dda26fd6e --- /dev/null +++ b/Content.Shared/_White/Announcement/ArrivalNotificationPrototype.cs @@ -0,0 +1,33 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared._White.Announcement; + +[Prototype("arrivalNotification")] +public sealed partial class ArrivalNotificationPrototype : IPrototype +{ + [IdDataField] public string ID { get; } = default!; + + /// + /// The message that the department will receive upon the player arrival + /// + [DataField(required: true)] + public string Message = default!; + + /// + /// The message that the station will receive upon the player arrival + /// + [DataField] + public string GlobalMessage = default!; + + /// + /// ID of the channel where the player arrival will be announced. + /// + [DataField(required: true)] + public HashSet RadioChannelsPrototypes = default!; + + /// + /// Determines whether the notification will be made to the entire station. If false, the notification will be on the department radio channel + /// + [DataField] + public bool UseGlobalAnnouncement; +} diff --git a/Resources/Audio/Voice/Gnome/Gnome_Clumsy_Sound_Effect.ogg b/Resources/Audio/Voice/Gnome/Gnome_Clumsy_Sound_Effect.ogg new file mode 100644 index 0000000000..b72ca67320 Binary files /dev/null and b/Resources/Audio/Voice/Gnome/Gnome_Clumsy_Sound_Effect.ogg differ diff --git a/Resources/Audio/Voice/Gnome/Gnome_Woo_Sound_Effect.ogg b/Resources/Audio/Voice/Gnome/Gnome_Woo_Sound_Effect.ogg new file mode 100644 index 0000000000..23f7efbe11 Binary files /dev/null and b/Resources/Audio/Voice/Gnome/Gnome_Woo_Sound_Effect.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Death1.ogg b/Resources/Audio/White/Voice/Gnomes/Death1.ogg new file mode 100644 index 0000000000..df3cc6a5f6 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Death1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Death2.ogg b/Resources/Audio/White/Voice/Gnomes/Death2.ogg new file mode 100644 index 0000000000..fc71df7e87 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Death2.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Death3.ogg b/Resources/Audio/White/Voice/Gnomes/Death3.ogg new file mode 100644 index 0000000000..1a9874d3f9 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Death3.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Death4.ogg b/Resources/Audio/White/Voice/Gnomes/Death4.ogg new file mode 100644 index 0000000000..70a8fc22ca Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Death4.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome1V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome1V1.ogg new file mode 100644 index 0000000000..3062f7385e Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome1V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome2V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome2V1.ogg new file mode 100644 index 0000000000..229079183a Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome2V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome3V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome3V1.ogg new file mode 100644 index 0000000000..3f122101ff Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome3V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome4V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome4V1.ogg new file mode 100644 index 0000000000..a2ce742c72 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome4V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome5V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome5V1.ogg new file mode 100644 index 0000000000..14bbc3f65e Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome5V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome6V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome6V1.ogg new file mode 100644 index 0000000000..9028e4f9c0 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome6V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome7V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome7V1.ogg new file mode 100644 index 0000000000..14a47dc500 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome7V1.ogg differ diff --git a/Resources/Audio/White/Voice/Gnomes/Gnome8V1.ogg b/Resources/Audio/White/Voice/Gnomes/Gnome8V1.ogg new file mode 100644 index 0000000000..1aa31c7422 Binary files /dev/null and b/Resources/Audio/White/Voice/Gnomes/Gnome8V1.ogg differ diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index dc48adccbb..5b937abeb2 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -5264,3 +5264,140 @@ id: 339 time: '2024-06-30T07:04:16.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/400 +- author: Warete + changes: + - message: "\u0423\u043F\u0440\u043E\u0449\u0435\u043D \u043A\u0440\u0430\u0444\u0442\ + \ \u043F\u0430\u0440\u044B \u0440\u0435\u0446\u0435\u043F\u0442\u043E\u0432" + type: Fix + id: 340 + time: '2024-07-01T04:33:47.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/401 +- author: ThereDrD + changes: + - message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u043E \u043E\u043F\u043E\ + \u0432\u0435\u0449\u0435\u043D\u0438\u0435 \u043E \u043F\u0440\u0438\u0431\u044B\ + \u0442\u0438\u0438 \u0433\u043B\u0430\u0432 \u043E\u0442\u0434\u0435\u043B\u043E\ + \u0432 \u0432 \u043A\u0430\u043D\u0430\u043B\u044B \u043E\u0442\u0434\u0435\u043B\ + \u0430 \u0438 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0435 \u043E\ + \u043F\u043E\u0432\u0435\u0449\u0435\u043D\u0438\u0435" + type: Add + id: 341 + time: '2024-07-01T10:10:32.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/402 +- author: Aviu + changes: + - message: "\u0423 \u0441\u0432\u0435\u0442\u043E\u0432\u043E\u0433\u043E \u043A\ + \u043E\u043F\u044C\u044F \u0446\u0435\u043D\u0430 \u0441\u043D\u043E\u0432\u0430\ + \ 10, \u0443\u0440\u043E\u043D \u043E\u0442 \u0431\u0440\u043E\u0441\u043A\u0430\ + \ \u0441\u043D\u043E\u0432\u0430 60, \u043D\u043E \u043A\u0434 \u0442\u0435\u043F\ + \u0435\u0440\u044C 2.5 \u0441\u0435\u043A\u0443\u043D\u0434." + type: Add + id: 342 + time: '2024-07-01T11:36:15.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/405 +- author: ThereDrD + changes: + - message: "\u0423\u0431\u0440\u0430\u043D\u043E \u043B\u0438\u0448\u043D\u0435\u0435\ + \ \u043E\u043F\u043E\u0432\u0435\u0449\u0435\u043D\u0438\u0435 \u0441\u0442\u0430\ + \u043D\u0446\u0438\u0438 \u043E \u043F\u0440\u0438\u0431\u044B\u0442\u0438\u0438\ + \ \u0433\u043B\u0430\u0432\u044B" + type: Fix + id: 343 + time: '2024-07-01T13:02:51.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/407 +- author: Aviu + changes: + - message: "\u041E\u0442\u043A\u0430\u0442 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\ + \u0438\u0439, \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0445 \u0441\ + \ \u043E\u0433\u043D\u0435\u043C, \u043D\u043E \u043E\u0433\u043E\u043D\u044C\ + \ \u0432\u0441\u0435 \u0435\u0449\u0435 \u043C\u0435\u043D\u0435\u0435 \u043E\ + \u043F\u0430\u0441\u0435\u043D." + type: Fix + id: 344 + time: '2024-07-01T13:27:22.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/408 +- author: ThereDrD + changes: + - message: "\u041E\u043F\u043E\u0432\u0435\u0449\u0435\u043D\u0438\u0435 \u043E\ + \ \u0433\u043B\u0430\u0432\u0435 \u043E\u0442\u0434\u0435\u043B\u0430 \u0442\ + \u0435\u043F\u0435\u0440\u044C \u043E\u043F\u043E\u0432\u0435\u0449\u0430\u0435\ + \u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u043E\u0434\u0438\ + \u043D \u043A\u0430\u043D\u0430\u043B" + type: Tweak + id: 345 + time: '2024-07-01T13:46:56.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/409 +- author: ThereDrD + changes: + - message: "\u041C\u0435\u0442\u0435\u043E\u0440\u043E\u0432 \u0434\u043E\u043B\u0436\ + \u043D\u043E \u0441\u0442\u0430\u0442\u044C \u043D\u0435\u043C\u043D\u043E\u0433\ + \u043E \u043C\u0435\u043D\u044C\u0448\u0435" + type: Add + id: 346 + time: '2024-07-02T09:55:38.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/410 +- author: ThereDrD + changes: + - message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u0413\u041D\u041E\ + \u041C\u042B. \u041E\u043D\u0438 \u043C\u043E\u0433\u0443\u0442 \u043F\u043E\ + \u043C\u043E\u0433\u0430\u0442\u044C \u0432 \u0441\u0430\u0434\u0443, \u0441\ + \u043C\u0435\u0448\u043D\u043E \u0433\u043E\u0432\u043E\u0440\u0438\u0442\u044C\ + , \u0441\u043C\u0435\u0448\u043D\u043E \u043A\u0440\u0438\u0447\u0430\u0442\u044C\ + , \u0441\u0438\u0434\u0435\u0442\u044C \u043D\u0430 \u0433\u043E\u043B\u043E\ + \u0432\u0435, \u0432\u043E\u0440\u043E\u0432\u0430\u0442\u044C, \u0438\u0441\ + \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C\u0441\u044F \u043A\ + \u0430\u043A \u043E\u0442\u0432\u0435\u0440\u0442\u043A\u0430 \u0438 \u0440\u0430\ + \u0437\u0431\u0438\u0432\u0430\u0442\u044C\u0441\u044F \u043E\u0431 \u0441\u0442\ + \u0435\u043D\u043A\u0443. \u0418\u0445 \u043C\u043E\u0436\u043D\u043E \u0432\ + \u044B\u0440\u0430\u0441\u0442\u0438\u0442\u044C, \u0438\u0441\u043F\u043E\u043B\ + \u044C\u0437\u0443\u044F \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\ + \u044B\u0435 \u0441\u0435\u043C\u0435\u043D\u0430. \u041D\u0435\u0441\u043A\u043E\ + \u043B\u044C\u043A\u043E \u0441\u0435\u043C\u044F\u043D \u043C\u043E\u0436\u043D\ + \u043E \u043D\u0430\u0439\u0442\u0438 \u0432 \u0432\u0435\u043D\u0434\u043E\u043C\ + \u0430\u0442\u0435 \u0431\u043E\u0442\u0430\u043D\u0438\u043A\u0430" + type: Add + id: 347 + time: '2024-07-02T09:55:25.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/411 +- author: ThereDrD + changes: + - message: "\u0423\u043C\u0435\u043D\u044C\u0448\u0435\u043D\u043E \u043A\u043E\u043B\ + \u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0441\u0435\u043C\u044F\u043D \u0433\ + \u043D\u043E\u043C\u043E\u0432 \u0432 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\ + \u0435 \u0431\u043E\u0442\u0430\u043D\u0438\u043A\u0430 \u0434\u043E 1" + type: Tweak + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0434\u043B\u044F \u043F\u043E\ + \u043B\u0443\u0447\u0435\u043D\u0438\u044F \u0441\u0435\u043C\u044F\u043D \u0433\ + \u043D\u043E\u043C\u043E\u0432 \u0430\u0432\u0442\u043E\u043C\u0430\u0442 \u0431\ + \u043E\u0442\u0430\u043D\u0438\u043A\u043E\u0432 \u0442\u0440\u0435\u0431\u0443\ + \u0435\u0442\u0441\u044F \u0432\u0437\u043B\u043E\u043C\u0430\u0442\u044C" + type: Tweak + - message: "\u0423\u0440\u043E\u043D \u0433\u043D\u043E\u043C\u043E\u0432 \u043E\ + \u0442 \u0434\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0443\u043C\u0435\u043D\ + \u044C\u0448\u0435\u043D" + type: Tweak + - message: "\u0420\u0430\u043D\u0434\u043E\u043C \u0438\u0433\u0440\u043E\u043A\u043E\ + \u0432 \u0434\u043B\u044F \u0433\u043E\u0441\u0442\u0440\u043E\u043B\u0438 \u0433\ + \u043D\u043E\u043C\u0430" + type: Tweak + - message: "\u0421\u0435\u043C\u0435\u043D\u0430 \u0433\u043D\u043E\u043C\u043E\u0432\ + \ \u0432 \u044F\u0449\u0438\u043A \u0441 \u044D\u043A\u0437\u043E\u0442\u0438\ + \u0447\u0435\u0441\u043A\u0438\u043C\u0438 \u0440\u0430\u0441\u0442\u0435\u043D\ + \u0438\u044F\u043C\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0437\u0430\ + \u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u0432 \u043A\u0430\ + \u0440\u0433\u043E" + type: Tweak + id: 348 + time: '2024-07-02T15:12:29.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/412 +- author: Remuchi + changes: + - message: "\u0422\u0422\u0421 \u0441\u043E \u0432\u0441\u0435\u0439 \u0441\u0442\ + \u0430\u043D\u0446\u0438\u0438 \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\ + \ \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0441\u043B\ + \u044B\u0448\u0435\u043D \u0432 \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u044B\ + \u0445 \u043C\u0435\u0441\u0442\u0430\u0445 \u043A\u0430\u0440\u0442\u044B." + type: Fix + id: 349 + time: '2024-07-02T15:56:53.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/413 diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 23a178d282..2db4d291aa 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -232,3 +232,7 @@ ghost-role-information-artifact-name = Sentient Artifact ghost-role-information-artifact-description = Enact your eldritch whims. Forcibly activate your nodes for good or for evil. + + +ghost-role-information-gnome-name = Garden Gnome +ghost-role-information-gnome-description = You are the trusted keeper of the station garden, keep your domain safe. diff --git a/Resources/Locale/en-US/seeds/seeds.ftl b/Resources/Locale/en-US/seeds/seeds.ftl index b398378288..965c9c6100 100644 --- a/Resources/Locale/en-US/seeds/seeds.ftl +++ b/Resources/Locale/en-US/seeds/seeds.ftl @@ -111,3 +111,5 @@ seeds-pumpkin-name = pumpkin seeds-pumpkin-display-name = pumpkins seeds-cotton-name = cotton seeds-cotton-display-name = cotton plant +seeds-gome-name = gnome +seeds-gnome-display-name = gnome plant diff --git a/Resources/Locale/ru-RU/_white/announce/announce.ftl b/Resources/Locale/ru-RU/_white/announce/announce.ftl new file mode 100644 index 0000000000..ba3450dcc1 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/announce/announce.ftl @@ -0,0 +1,3 @@ +head-arrived-message = { $character }, { $job }, Глава отдела +head-arrived-message-global = { $job } { $character } на станции +head-arrived-sender = Автоматическая Система Оповещений diff --git a/Resources/Locale/ru-RU/_white/mobs/gnomes.ftl b/Resources/Locale/ru-RU/_white/mobs/gnomes.ftl new file mode 100644 index 0000000000..0ac3fc7794 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/mobs/gnomes.ftl @@ -0,0 +1,6 @@ +ent-MobGnome = гном + .desc = Добросовестный помощник по саду +ent-GnomeSeeds = пакет семян гнома + .desc = { ent-SeedBase.desc } +ent-ClothingHeadHatGnome = шляпа гнома + .desc = Шляпа настоящего садового помощника diff --git a/Resources/Prototypes/Body/Prototypes/bot.yml b/Resources/Prototypes/Body/Prototypes/bot.yml index 848db2a4fd..9662860427 100644 --- a/Resources/Prototypes/Body/Prototypes/bot.yml +++ b/Resources/Prototypes/Body/Prototypes/bot.yml @@ -1,4 +1,4 @@ -- type: body +- type: body id: Bot name: "bot" root: hand 1 diff --git a/Resources/Prototypes/Body/Prototypes/gnome.yml b/Resources/Prototypes/Body/Prototypes/gnome.yml new file mode 100644 index 0000000000..617c3f7ef3 --- /dev/null +++ b/Resources/Prototypes/Body/Prototypes/gnome.yml @@ -0,0 +1,19 @@ +- type: body + id: gnome + name: "gnome" + root: torso + slots: + torso: + part: TorsoAnimal + connections: + - hands + - legs + organs: + hands: + part: HandsAnimal + legs: + part: LegsAnimal + connections: + - feet + feet: + part: FeetAnimal diff --git a/Resources/Prototypes/Catalog/Fills/Crates/botany.yml b/Resources/Prototypes/Catalog/Fills/Crates/botany.yml index c0d8a422f2..653f3ed377 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/botany.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/botany.yml @@ -20,6 +20,8 @@ amount: 2 - id: BungoSeeds amount: 2 + - id: GnomeSeeds + amount: 1 - type: entity id: CrateHydroponicsSeedsMedicinal diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml index bf2a25d723..b54e42b8f8 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml @@ -125,7 +125,19 @@ - id: Soap prob: 0.10 - id: PlushieCarp - prob: 0.1 + prob: 0.2 + orGroup: carp + - id: ClothingHeadHatGnome + prob: 0.2 + - id: PlushieHolocarp + prob: 0.05 + orGroup: carp + - id: PlushieMagicarp + prob: 0.05 + orGroup: carp + - id: PlushieRainbowCarp + prob: 0.03 + orGroup: carp - id: PlushieSlime prob: 0.1 - id: PlushieSnake diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/seeds.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/seeds.yml index a9646559d9..ff654abd0f 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/seeds.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/seeds.yml @@ -37,5 +37,7 @@ BerrySeeds: 5 PeaSeeds: 5 CottonSeeds: 5 + contrabandInventory: + GnomeSeeds: 1 emaggedInventory: FlyAmanitaSeeds: 1 diff --git a/Resources/Prototypes/Entities/Clothing/Head/hats.yml b/Resources/Prototypes/Entities/Clothing/Head/hats.yml index a420eab361..d2704c317b 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/hats.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/hats.yml @@ -1108,3 +1108,19 @@ sprite: Clothing/Head/Hats/beret_medic.rsi - type: Clothing sprite: Clothing/Head/Hats/beret_medic.rsi + +- type: entity + parent: ClothingHeadBase + id: ClothingHeadHatGnome + name: gnome hat + description: The cap of a true garden helper + components: + - type: Sprite + sprite: Clothing/Head/Hats/hat_gnome.rsi + - type: Clothing + sprite: Clothing/Head/Hats/hat_gnome.rsi + - type: Seed + seedId: gnome + - type: AddAccentClothing + accent: GnomeAccent + diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 2e719e4dcc..3ffcc02561 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -819,3 +819,182 @@ # - type: AlwaysRevolutionaryConvertible - type: StealTarget stealGroup: AnimalTropico + + +- type: entity #WHY MUST YOU THROW ERRORS HOW DARE YOU + name: Gnome #this thing is covered in comments, its for my sanity, ignore them please. + parent: [BaseSimpleMob, MobCombat, MobAtmosExposed] + id: MobGnome + description: "A garden's trusty helper" + components: + - type: Inventory + templateId: gnome + speciesId: gnome + - type: InventorySlots + - type: RotationVisuals + defaultRotation: 90 + horizontalRotation: 90 + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle #displays error, works anyways so i wont touch it, whatever it does + radius: 0.2 + density: 80 + mask: + - SmallMobMask #lets em go under doors for escapes from sec/greytide/hunting mice + layer: + - SmallMobLayer + - type: Stripping + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: GhostRole + prob: 1 + makeSentient: true + allowSpeech: true + allowMovement: true + name: ghost-role-information-gnome-name + description: ghost-role-information-gnome-description + raffle: + settings: short + - type: GhostTakeoverAvailable + - type: Flashable + - type: Tag + tags: + - CannotSuicide + - VimPilot + - type: MobThresholds + thresholds: #VERY easy to kill, if it was harder to kill them the sneaky fuckers would rule the world + 0: Alive + 10: Dead + - type: DamageStateVisuals + states: + Alive: + Base: Gnome-0 + Dead: + Base: dead-1 + - type: GnomeAccent + - type: NameIdentifier + group: Gnome + - type: Sprite + drawdepth: SmallMobs + sprite: Mobs/Animals/gnome.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: Gnome-0 + - type: Item + size: Small + - type: Clothing #TO VALLHALLA + quickEquip: false + sprite: Mobs/Animals/gnome.rsi + equippedPrefix: 1 + slots: + - HEAD + - type: IdExaminable + - type: InteractionPopup + interactSuccessString: hugging-success-generic + interactSuccessSound: /Audio/Effects/thudswoosh.ogg + messagePerceivedByOthers: hugging-success-generic-others + - type: MeleeWeapon + soundHit: + collection: ToySqueak + angle: 30 + animation: WeaponArcPunch + damage: + types: + Piercing: 3 + - type: Puller #dont need hands because they are at a disadvantage anyway, this way they can hold a light and drag a box for a backpack + needsHands: false + - type: CanHostGuardian #touch this stuff to make the fuckers hold still when not possesed (NOT THE GAURDIAN) + - type: FactionException + - type: NpcFactionMember + factions: + - Passive + - type: Hands #gives em hands, the item sprites for holding things look all strange but its FINE, I DONT WANNA FIX IT ITS FINE ILL DO IT LATER + - type: Body #gives em a body, is needed for organs and hands + prototype: gnome + requiredLegs: 0 + - type: Clumsy #no guns for youuuu if they shoot a gun they die >:3 + clumsyDamage: + types: + Blunt: 2 + Piercing: 7 + groups: + Burn: 2 + clumsySound: + path: /Audio/Voice/Gnome/Gnome_Clumsy_Sound_Effect.ogg + - type: Barotrauma #gnomes instantly explode in space, gnomes shouldnt go in space + damage: + types: + Blunt: 20 #per second, scales with pressure and other constants. + - type: Repairable + fuelCost: 5 + qualityNeeded: Gluing + doAfterDelay: 8 + - type: ZombieImmune + - type: Damageable + damageContainer: StructuralInorganic + - type: CanEscapeInventory + - type: Destructible + thresholds: + - trigger: + !type:DamageTypeTrigger #gnomes gib once they are in enough bits that they cant be glued back together + damageType: Blunt + damage: 60 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: GlassBreak + - !type:SpawnEntitiesBehavior + spawn: + ClothingHeadHatGnome: + min: 1 + max: 1 + ShardGlass: + min: 1 + max: 3 + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: DamageOnHighSpeedImpact #gnomes break when thrown, another anti gnometide device + minimumSpeed: 10 + damage: + types: + Blunt: 20 + soundHit: + collection: GlassBreak + - type: Vocal + sounds: + Male: Gnome + Female: Gnome + Unsexed: Gnome + wilhelmProbability: 0.0001 + - type: Unrevivable + - type: Tool + qualities: + - Screwing + useSound: + collection: Screwdriver + - type: FelinidFood + - type: Speech + speechSounds: GnomesSpeech + speechVerb: SmallMob + - type: Extractable + grindableSolutionName: food + - type: SolutionContainerManager + solutions: + food: + reagents: + - ReagentId: UnstableMutagen + Quantity: 5 + - type: BadFood + - type: DeathGasps + deathSounds: + collection: GnomesDeathCollection + canOtherHearDeathSound: True + - type: Thieving + stripTimeReduction: 4 + - type: Pacified + diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml index 2fd2331f91..338d6f8089 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml @@ -19,6 +19,8 @@ map: [ "enum.SolutionContainerLayers.Overlay" ] - type: Appearance - type: Glue + - type: RefillableSolution + solution: drink - type: SolutionContainerManager solutions: drink: @@ -26,6 +28,11 @@ reagents: - ReagentId: SpaceGlue Quantity: 30 + Welder: + reagents: + - ReagentId: SpaceGlue + Quantity: 30 + maxVol: 30 - type: SolutionContainerVisuals maxFillLevels: 6 fillBaseName: fill @@ -38,8 +45,15 @@ - type: Tag tags: - DrinkSpaceGlue + - GlueTool - type: TrashOnSolutionEmpty solution: drink + - type: Tool + qualities: Gluing + - type: Welder #this here uses welding code to take fuel out of the bottle (fuel being glue) + fuelSolutionName: drink + fuelReagent: SpaceGlue + hiddenInfo: true - type: entity parent: DrinkBase diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index 5ca48cbbe0..d5c01ce77a 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -1514,6 +1514,8 @@ - type: Tag tags: - DrinkSpaceGlue + - type: Tool + qualities: Gluing - type: entity parent: BaseItem diff --git a/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/seeds.yml b/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/seeds.yml index 2b232d643d..172aa932fb 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/seeds.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/seeds.yml @@ -571,3 +571,13 @@ seedId: cotton - type: Sprite sprite: Objects/Specific/Hydroponics/cotton.rsi + +- type: entity #you should never see this, this is for testing, if someone has these then I FUCKED UP and you should ping BITTERLYNX + parent: SeedBase + name: packet of Gnome seeds + id: GnomeSeeds + components: + - type: Seed + seedId: gnome + - type: Sprite + sprite: Objects/Specific/Hydroponics/cotton.rsi diff --git a/Resources/Prototypes/Hydroponics/seeds.yml b/Resources/Prototypes/Hydroponics/seeds.yml index eae58ce94a..be95649d93 100644 --- a/Resources/Prototypes/Hydroponics/seeds.yml +++ b/Resources/Prototypes/Hydroponics/seeds.yml @@ -1501,3 +1501,22 @@ Max: 10 PotencyDivisor: 20 +- type: seed #once again, replacing learning with comments because ive been in this file for 10 hours + id: gnome + name: seeds-gome-name #the name of the seeds + noun: seeds-noun-seeds + displayName: seeds-gnome-display-name #name of the plant when looking at the tray + plantRsi: Objects/Specific/Hydroponics/gnome.rsi + packetPrototype: GnomeSeeds #seeds you get when clipping? BUT YOU CANT CLIP THIS PLANT TAKE THAT BOTANISTS! + productPrototypes: + - MobGnome #THE THING THAT SPAWNS! + lifespan: 25 + maturation: 10 + production: 1 + yield: 1 + potency: 1 + idealLight: 8 + growthStages: 2 + waterConsumption: 0 + seedless: true #fuckin does nothing but im keeping it just in case someone wants botany to riot + unclippable: true diff --git a/Resources/Prototypes/InventoryTemplates/gome_inventory_template.yml b/Resources/Prototypes/InventoryTemplates/gome_inventory_template.yml new file mode 100644 index 0000000000..e80dbe8e22 --- /dev/null +++ b/Resources/Prototypes/InventoryTemplates/gome_inventory_template.yml @@ -0,0 +1,13 @@ +- type: inventoryTemplate + id: gnome + #slots: i was on the fence to give them an id slot so ill comment this out for now + # - name: id + # slotTexture: id + # slotFlags: IDCARD + # slotGroup: SecondHotbar + # stripTime: 6 + # uiWindowPos: 2,1 + # strippingWindowPos: 2,4 + # dependsOn: jumpsuit + # displayName: ID + diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml index 03a70cb7fe..486df4678e 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml @@ -32,12 +32,5 @@ icon: sprite: Objects/Misc/stock_parts.rsi state: capacitor - doAfter: 5 - - tag: CapacitorStockPart - name: capacitor - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor - doAfter: 5 - node: medsecHud entity: ClothingEyesHudMedSec diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml index e3f972cfda..39094bfdc7 100644 --- a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml @@ -65,10 +65,5 @@ icon: sprite: Objects/Misc/stock_parts.rsi state: capacitor - - tag: CapacitorStockPart - name: capacitor - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor - node: potatoaichip - entity: PotatoAIChip \ No newline at end of file + entity: PotatoAIChip diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml index c3608cbb00..1806692ac5 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml @@ -15,6 +15,7 @@ weight: 10 startingGear: QuartermasterGear icon: "JobIconQuarterMaster" + announcementPrototype: QuartermasterArrivalNotification supervisors: job-supervisors-captain whitelistedSpecies: - Human diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index 205183db64..9ad550b950 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -20,6 +20,7 @@ icon: "JobIconCaptain" requireAdminNotify: true joinNotifyCrew: true + announcementPrototype: CaptainArrivalNotification supervisors: job-supervisors-centcom whitelistedSpecies: - Human diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml index fdc5f38ae5..cde2a2a738 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml @@ -19,6 +19,7 @@ startingGear: HoPGear icon: "JobIconHeadOfPersonnel" requireAdminNotify: true + announcementPrototype: HeadOfPersonnelArrivalNotification supervisors: job-supervisors-captain whitelistedSpecies: - Human diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index 9f19e8e622..2be4b76c18 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -16,6 +16,7 @@ startingGear: ChiefEngineerGear icon: "JobIconChiefEngineer" requireAdminNotify: true + announcementPrototype: ChiefEngineerArrivalNotification supervisors: job-supervisors-captain whitelistedSpecies: - Human diff --git a/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml b/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml index 780bd76cf0..3176d34bfd 100644 --- a/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml +++ b/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml @@ -14,6 +14,7 @@ time: 36000 #10 hrs startingGear: InspectorGear icon: "JobIconInspector" + announcementPrototype: InspectorArrivalNotification supervisors: job-supervisors-captain access: - Service diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index ebcf13b4d9..009c294984 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -14,6 +14,7 @@ weight: 10 startingGear: CMOGear icon: "JobIconChiefMedicalOfficer" + announcementPrototype: ChiefMedicalOfficerArrivalNotification requireAdminNotify: true supervisors: job-supervisors-captain whitelistedSpecies: diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index a731829a46..918c9cb993 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -13,6 +13,7 @@ startingGear: ResearchDirectorGear icon: "JobIconResearchDirector" requireAdminNotify: true + announcementPrototype: ResearchDirectorArrivalNotification supervisors: job-supervisors-captain whitelistedSpecies: - Human diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index b550081863..be693bb9f4 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -16,6 +16,7 @@ startingGear: HoSGear icon: "JobIconHeadOfSecurity" requireAdminNotify: true + announcementPrototype: HeadOfSecurityArrivalNotification supervisors: job-supervisors-captain whitelistedSpecies: - Human diff --git a/Resources/Prototypes/Voice/speech_emote_sounds.yml b/Resources/Prototypes/Voice/speech_emote_sounds.yml index 6109b7d5ce..182adf5c96 100644 --- a/Resources/Prototypes/Voice/speech_emote_sounds.yml +++ b/Resources/Prototypes/Voice/speech_emote_sounds.yml @@ -620,3 +620,13 @@ path: /Audio/Animals/parrot_raught.ogg params: variation: 0.125 + +- type: emoteSounds + id: Gnome + params: + variation: 0.125 + sounds: + Scream: + path: /Audio/Voice/Gnome/Gnome_Woo_Sound_Effect.ogg + Weh: + collection: Weh diff --git a/Resources/Prototypes/_White/Actions/types.yml b/Resources/Prototypes/_White/Actions/types.yml index d6b15755d9..ed478a94d6 100644 --- a/Resources/Prototypes/_White/Actions/types.yml +++ b/Resources/Prototypes/_White/Actions/types.yml @@ -20,7 +20,7 @@ noSpawn: true components: - type: InstantAction - useDelay: 1.5 + useDelay: 2.5 itemIconStyle: BigAction priority: -20 icon: diff --git a/Resources/Prototypes/_White/Announcement/ArrivalNotification.yml b/Resources/Prototypes/_White/Announcement/ArrivalNotification.yml new file mode 100644 index 0000000000..f956742e3d --- /dev/null +++ b/Resources/Prototypes/_White/Announcement/ArrivalNotification.yml @@ -0,0 +1,49 @@ +- type: arrivalNotification + id: CaptainArrivalNotification + message: head-arrived-message + globalMessage: head-arrived-message-global + radioChannelsPrototypes: + - Command + useGlobalAnnouncement: True + +- type: arrivalNotification + id: HeadOfPersonnelArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Service + +- type: arrivalNotification + id: HeadOfSecurityArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Security + +- type: arrivalNotification + id: ChiefMedicalOfficerArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Medical + +- type: arrivalNotification + id: ChiefEngineerArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Engineering + +- type: arrivalNotification + id: ResearchDirectorArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Science + +- type: arrivalNotification + id: QuartermasterArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Cargo + +- type: arrivalNotification + id: InspectorArrivalNotification + message: head-arrived-message + radioChannelsPrototypes: + - Security diff --git a/Resources/Prototypes/_White/Catalog/uplink.yml b/Resources/Prototypes/_White/Catalog/uplink.yml index d46520b412..7140266856 100644 --- a/Resources/Prototypes/_White/Catalog/uplink.yml +++ b/Resources/Prototypes/_White/Catalog/uplink.yml @@ -93,7 +93,7 @@ icon: { sprite: /Textures/White/Objects/Weapons/hardlight_spear.rsi, state: spear } productEntity: HardlightSpearImplanter cost: - Telecrystal: 12 + Telecrystal: 10 categories: - UplinkImplants conditions: diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/hardlight_spear.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/hardlight_spear.yml index afa4339a54..56570149b5 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Weapons/hardlight_spear.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/hardlight_spear.yml @@ -18,8 +18,8 @@ - type: DamageOtherOnHit damage: types: - Piercing: 20 - Heat: 20 + Piercing: 30 + Heat: 30 - type: Wieldable - type: IncreaseDamageOnWield damage: diff --git a/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml b/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml index d168f5e4ae..1cd431a0a4 100644 --- a/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml +++ b/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml @@ -61,8 +61,8 @@ ckey: reider207 sprite: White/Ghosts/reider207-ghost.rsi alpha: 0.8 - ghostName: Соня - ghostDescription: Видишь спит соня? Так не буди + ghostName: Tighnari + ghostDescription: But what are they going to do, lock me up? size: 0.8, 0.8 #mikvisan diff --git a/Resources/Prototypes/_White/Sound/Speech/gnomes.yml b/Resources/Prototypes/_White/Sound/Speech/gnomes.yml new file mode 100644 index 0000000000..d7e8b9f819 --- /dev/null +++ b/Resources/Prototypes/_White/Sound/Speech/gnomes.yml @@ -0,0 +1,8 @@ +- type: speechSounds + id: GnomesSpeech + saySound: + collection: GnomesSpeechCollection + askSound: + collection: GnomesSpeechCollection + exclaimSound: + collection: GnomesSpeechCollection diff --git a/Resources/Prototypes/_White/SoundCollections/gnomes.yml b/Resources/Prototypes/_White/SoundCollections/gnomes.yml new file mode 100644 index 0000000000..daec0b9ea3 --- /dev/null +++ b/Resources/Prototypes/_White/SoundCollections/gnomes.yml @@ -0,0 +1,19 @@ +- type: soundCollection + id: GnomesSpeechCollection + files: + - /Audio/White/Voice/Gnomes/Gnome1V1.ogg + - /Audio/White/Voice/Gnomes/Gnome2V1.ogg + - /Audio/White/Voice/Gnomes/Gnome3V1.ogg + - /Audio/White/Voice/Gnomes/Gnome4V1.ogg + - /Audio/White/Voice/Gnomes/Gnome5V1.ogg + - /Audio/White/Voice/Gnomes/Gnome6V1.ogg + - /Audio/White/Voice/Gnomes/Gnome7V1.ogg + - /Audio/White/Voice/Gnomes/Gnome8V1.ogg + +- type: soundCollection + id: GnomesDeathCollection + files: + - /Audio/White/Voice/Gnomes/Death1.ogg + - /Audio/White/Voice/Gnomes/Death2.ogg + - /Audio/White/Voice/Gnomes/Death3.ogg + - /Audio/White/Voice/Gnomes/Death4.ogg diff --git a/Resources/Prototypes/_White/Spawners/spawners.yml b/Resources/Prototypes/_White/Spawners/spawners.yml new file mode 100644 index 0000000000..31a9fc1bba --- /dev/null +++ b/Resources/Prototypes/_White/Spawners/spawners.yml @@ -0,0 +1,12 @@ +- type: entity + name: Gnome spawner + id: SpawnMobGnome + parent: MarkerBase + components: + - type: Sprite + layers: + - state: green + - state: ai + - type: ConditionalSpawner + prototypes: + - MobGnome diff --git a/Resources/Prototypes/_White/Wizard/magic_items.yml b/Resources/Prototypes/_White/Wizard/magic_items.yml index 60836bd1d5..4adfd2e9c8 100644 --- a/Resources/Prototypes/_White/Wizard/magic_items.yml +++ b/Resources/Prototypes/_White/Wizard/magic_items.yml @@ -15,12 +15,15 @@ - type: Clothing sprite: White/Objects/Weapons/Chaplain/hfrequency.rsi slots: - - back - - suitStorage + - none - type: Reflect reflectProb: 0.4 - type: Item sprite: White/Objects/Weapons/Chaplain/hfrequency.rsi + size: Large + storedRotation: 44 + shape: + - 0, 0, 3, 0 - type: entity name: клинок заклинаний diff --git a/Resources/Prototypes/game_presets.yml b/Resources/Prototypes/game_presets.yml index 3a41de0e53..0a48d7faae 100644 --- a/Resources/Prototypes/game_presets.yml +++ b/Resources/Prototypes/game_presets.yml @@ -8,6 +8,7 @@ rules: - RampingStationEventScheduler - BasicRoundstartVariation + - GameRuleMeteorScheduler - type: gamePreset id: AllAtOnce @@ -24,6 +25,7 @@ - Cult - Wizard - BasicRoundstartVariation + - GameRuleMeteorScheduler - type: gamePreset id: Extended @@ -175,6 +177,7 @@ - Pirates - BasicStationEventScheduler - BasicRoundstartVariation + - GameRuleMeteorScheduler #WD EDIT START - type: gamePreset @@ -190,6 +193,7 @@ - SubGamemodesRule - BasicStationEventScheduler - BasicRoundstartVariation + - GameRuleMeteorScheduler - type: gamePreset id: Changeling @@ -204,6 +208,7 @@ - SubGamemodesRule - BasicStationEventScheduler - BasicRoundstartVariation + - GameRuleMeteorScheduler - type: gamePreset id: Wizard @@ -219,4 +224,5 @@ - SubGamemodesRule - BasicStationEventScheduler - BasicRoundstartVariation + - GameRuleMeteorScheduler #WD EDIT END diff --git a/Resources/Prototypes/name_identifier_groups.yml b/Resources/Prototypes/name_identifier_groups.yml index 7df370035e..d9193df161 100644 --- a/Resources/Prototypes/name_identifier_groups.yml +++ b/Resources/Prototypes/name_identifier_groups.yml @@ -1,8 +1,12 @@ -# Non-fungible apes, anyone? +# Non-fungible apes, anyone? - type: nameIdentifierGroup id: Monkey prefix: MK +- type: nameIdentifierGroup + id: Gnome + prefix: GN + - type: nameIdentifierGroup id: Kobold prefix: KB diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 388a6e1033..4a22996ef3 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -644,6 +644,9 @@ - type: Tag id: Grenade +- type: Tag # tag to make a glue tool use glue on repair + id: GlueTool + - type: Tag id: HudMedical @@ -1325,5 +1328,3 @@ - type: Tag id: WriteIgnoreStamps - -# ALPHABETICAL diff --git a/Resources/Prototypes/tool_qualities.yml b/Resources/Prototypes/tool_qualities.yml index e62fa5bfed..24301573a7 100644 --- a/Resources/Prototypes/tool_qualities.yml +++ b/Resources/Prototypes/tool_qualities.yml @@ -74,3 +74,10 @@ toolName: tool-quality-rolling-tool-name spawn: RollingPin icon: { sprite: Objects/Tools/rolling_pin.rsi, state: icon } + +- type: tool + id: Gluing + name: tool-quality-gluing-name + toolName: tool-quality-rolling-tool-name + spawn: DrinkSpaceGlue + icon: { sprite: Objects/Tools/rolling_pin.rsi, state: icon } diff --git a/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/equipped-HELMET.png b/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/equipped-HELMET.png new file mode 100644 index 0000000000..ef8104f306 Binary files /dev/null and b/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/equipped-HELMET.png differ diff --git a/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/icon.png b/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/icon.png new file mode 100644 index 0000000000..f3ea78c5e5 Binary files /dev/null and b/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/meta.json b/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/meta.json new file mode 100644 index 0000000000..2a989f0557 --- /dev/null +++ b/Resources/Textures/Clothing/Head/Hats/hat_gnome.rsi/meta.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprited by DanoftheE (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + + { + "name": "equipped-HELMET", + "directions": 4 + }, + + { + "name": "icon" + + } + ] +} diff --git a/Resources/Textures/Mobs/Animals/gnome.rsi/0-equipped-HELMET.png b/Resources/Textures/Mobs/Animals/gnome.rsi/0-equipped-HELMET.png new file mode 100644 index 0000000000..6e48f410a0 Binary files /dev/null and b/Resources/Textures/Mobs/Animals/gnome.rsi/0-equipped-HELMET.png differ diff --git a/Resources/Textures/Mobs/Animals/gnome.rsi/1-equipped-HELMET.png b/Resources/Textures/Mobs/Animals/gnome.rsi/1-equipped-HELMET.png new file mode 100644 index 0000000000..6e48f410a0 Binary files /dev/null and b/Resources/Textures/Mobs/Animals/gnome.rsi/1-equipped-HELMET.png differ diff --git a/Resources/Textures/Mobs/Animals/gnome.rsi/Gnome-0.png b/Resources/Textures/Mobs/Animals/gnome.rsi/Gnome-0.png new file mode 100644 index 0000000000..b51b957e15 Binary files /dev/null and b/Resources/Textures/Mobs/Animals/gnome.rsi/Gnome-0.png differ diff --git a/Resources/Textures/Mobs/Animals/gnome.rsi/Gnome-1.png b/Resources/Textures/Mobs/Animals/gnome.rsi/Gnome-1.png new file mode 100644 index 0000000000..b51b957e15 Binary files /dev/null and b/Resources/Textures/Mobs/Animals/gnome.rsi/Gnome-1.png differ diff --git a/Resources/Textures/Mobs/Animals/gnome.rsi/dead-1.png b/Resources/Textures/Mobs/Animals/gnome.rsi/dead-1.png new file mode 100644 index 0000000000..e07631d60a Binary files /dev/null and b/Resources/Textures/Mobs/Animals/gnome.rsi/dead-1.png differ diff --git a/Resources/Textures/Mobs/Animals/gnome.rsi/meta.json b/Resources/Textures/Mobs/Animals/gnome.rsi/meta.json new file mode 100644 index 0000000000..77a8f27d03 --- /dev/null +++ b/Resources/Textures/Mobs/Animals/gnome.rsi/meta.json @@ -0,0 +1,63 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Sprited by DanoftheE (Discord)", + "states": [ + { + "name": "dead-1", + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "Gnome-0", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "Gnome-1", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "0-equipped-HELMET", + "directions": 4 + }, + { + "name": "1-equipped-HELMET", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/dead.png b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/dead.png new file mode 100644 index 0000000000..a6830d5b5a Binary files /dev/null and b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/dead.png differ diff --git a/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/harvest.png b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/harvest.png new file mode 100644 index 0000000000..c31348eab2 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/harvest.png differ diff --git a/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/meta.json b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/meta.json new file mode 100644 index 0000000000..cf5c98cf9d --- /dev/null +++ b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprited by DanoftheE (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "dead" + }, + { + "name": "harvest" + }, + { + "name": "stage-1" + }, + { + "name": "stage-2" + } + ] +} diff --git a/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/stage-1.png b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/stage-1.png new file mode 100644 index 0000000000..439131961a Binary files /dev/null and b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/stage-1.png differ diff --git a/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/stage-2.png b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/stage-2.png new file mode 100644 index 0000000000..c601075335 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Hydroponics/gnome.rsi/stage-2.png differ diff --git a/Resources/Textures/White/Ghosts/reider207-ghost.rsi/animated.png b/Resources/Textures/White/Ghosts/reider207-ghost.rsi/animated.png index 55f58f51ac..d3cb68caf5 100644 Binary files a/Resources/Textures/White/Ghosts/reider207-ghost.rsi/animated.png and b/Resources/Textures/White/Ghosts/reider207-ghost.rsi/animated.png differ diff --git a/Resources/Textures/White/Ghosts/reider207-ghost.rsi/meta.json b/Resources/Textures/White/Ghosts/reider207-ghost.rsi/meta.json index 629cfacf7a..86f69ea44f 100644 --- a/Resources/Textures/White/Ghosts/reider207-ghost.rsi/meta.json +++ b/Resources/Textures/White/Ghosts/reider207-ghost.rsi/meta.json @@ -3,8 +3,8 @@ "license": "CC-BY-SA-3.0", "copyright": "reider207", "size": { - "x": 64, - "y": 64 + "x": 128, + "y": 128 }, "states": [ {