Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jabak
2024-07-02 21:26:29 +03:00
94 changed files with 1225 additions and 372 deletions

View File

@@ -56,23 +56,39 @@ public sealed class ChargeActionSystem : SharedChargingSystem
{ {
base.Update(frameTime); base.Update(frameTime);
if (_playerManager.LocalEntity is not { } user) if (!_timing.IsFirstTimePredicted)
return; return;
if (_playerManager.LocalEntity is not { } user)
{
Reset();
return;
}
if (!_mobState.IsAlive(user) || _statusEffects.HasStatusEffect(user, "Incorporeal")) if (!_mobState.IsAlive(user) || _statusEffects.HasStatusEffect(user, "Incorporeal"))
{
Reset();
return; return;
}
if (!_timing.IsFirstTimePredicted || _controller == null || _controller.SelectingTargetFor is not { } actionId) if (_controller == null || _controller.SelectingTargetFor is not { } actionId)
{
Reset();
return; return;
}
if (!_actionsSystem.TryGetActionData(actionId, out var baseAction) || if (!_actionsSystem.TryGetActionData(actionId, out var baseAction) ||
baseAction is not BaseTargetActionComponent action || !action.IsChargeEnabled) baseAction is not BaseTargetActionComponent action || !action.IsChargeEnabled)
{
Reset();
return; return;
}
if (!action.Enabled if (!action.Enabled
|| action is { Charges: 0, RenewCharges: false } || action is { Charges: 0, RenewCharges: false }
|| action.Cooldown.HasValue && action.Cooldown.Value.End > _timing.CurTime) || action.Cooldown.HasValue && action.Cooldown.Value.End > _timing.CurTime)
{ {
Reset();
return; 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) private void HandleAction(EntityUid actionId, BaseTargetActionComponent action, EntityUid user, int chargeLevel)
{ {
var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition); var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition);

View File

@@ -87,7 +87,7 @@ public sealed partial class HumanoidProfileEditor
if (_previewDummy is null || Profile is null) if (_previewDummy is null || Profile is null)
return; return;
_ttsSys.StopAllStreams(); _ttsSys.StopCurrentTTS(_previewDummy.Value);
_ttsMgr.RequestTTS(_previewDummy.Value, IoCManager.Resolve<IRobustRandom>().Pick(_sampleText), Profile.Voice); _ttsMgr.RequestTTS(_previewDummy.Value, IoCManager.Resolve<IRobustRandom>().Pick(_sampleText), Profile.Voice);
} }
} }

View File

@@ -1,38 +1,29 @@
using System.Diagnostics.CodeAnalysis; using System.IO;
using System.IO;
using System.Linq;
using Content.Shared.Physics;
using Content.Shared._White; using Content.Shared._White;
using Content.Shared._White.TTS; using Content.Shared._White.TTS;
using Robust.Client.Audio; using Robust.Client.Audio;
using Robust.Client.GameObjects; using Robust.Shared.Audio;
using Robust.Client.Graphics; using Robust.Shared.Audio.Components;
using Robust.Shared.Audio.Sources;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Map; // ReSharper disable InconsistentNaming
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;
namespace Content.Client._White.TTS; namespace Content.Client._White.TTS;
/// <summary> /// <summary>
/// Plays TTS audio in world /// Plays TTS audio in world
/// </summary> /// </summary>
// ReSharper disable once InconsistentNaming
public sealed class TTSSystem : EntitySystem public sealed class TTSSystem : EntitySystem
{ {
[Dependency] private readonly IAudioManager _audioSystem = default!; [Dependency] private readonly IAudioManager _audioManager = default!;
[Dependency] private readonly IEntityManager _entity = default!;
[Dependency] private readonly IEyeManager _eye = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly SharedPhysicsSystem _broadPhase = default!; [Dependency] private readonly AudioSystem _audioSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
private float _volume; private float _volume;
private const int TTSCollisionMask = (int)CollisionGroup.Impassable; private readonly Dictionary<EntityUid, AudioComponent> _currentlyPlaying = new();
private readonly Dictionary<EntityUid, Queue<AudioStreamWithParams>> _enquedStreams = new();
private readonly HashSet<AudioStream> _currentStreams = new();
private readonly Dictionary<EntityUid, Queue<AudioStream>> _entityQueues = new(); // Same as Server.ChatSystem.VoiceRange
private const float VoiceRange = 10;
public override void Initialize() public override void Initialize()
{ {
@@ -44,54 +35,35 @@ public sealed class TTSSystem : EntitySystem
{ {
base.Shutdown(); base.Shutdown();
_cfg.UnsubValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged); _cfg.UnsubValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged);
EndStreams(); ClearQueues();
} }
// Little bit of duplication logic from AudioSystem
public override void FrameUpdate(float frameTime) public override void FrameUpdate(float frameTime)
{ {
var streamToRemove = new HashSet<AudioStream>(); foreach (var (uid, audioComponent) in _currentlyPlaying)
var ourPos = _eye.CurrentEye.Position.Position;
foreach (var stream in _currentStreams)
{ {
if (!stream.Source.Playing || if (audioComponent is { Running: true, Playing: true })
!_entity.TryGetComponent<MetaDataComponent>(stream.Uid, out var meta) ||
Deleted(stream.Uid, meta) ||
!_entity.TryGetComponent<TransformComponent>(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)
{ {
continue; continue;
} }
var sourceRelative = ourPos - mapPos.Position; if (!_enquedStreams.TryGetValue(uid, out var queue))
var occlusion = 0f;
if (sourceRelative.Length() > 0)
{ {
occlusion = _broadPhase.IntersectRayPenetration(mapPos.MapId, continue;
new CollisionRay(mapPos.Position, sourceRelative.Normalized(), TTSCollisionMask),
sourceRelative.Length(), stream.Uid);
} }
stream.Source.Occlusion = occlusion; if (!queue.TryDequeue(out var toPlay))
} {
continue;
}
foreach (var audioStream in streamToRemove) var audio = _audioSystem.PlayEntity(toPlay.Stream, uid, toPlay.Params);
{ if (!audio.HasValue)
_currentStreams.Remove(audioStream); {
ProcessEntityQueue(audioStream.Uid); continue;
}
_currentlyPlaying[uid] = audio.Value.Component;
} }
} }
@@ -102,114 +74,76 @@ public sealed class TTSSystem : EntitySystem
private void OnPlayTTS(PlayTTSEvent ev) private void OnPlayTTS(PlayTTSEvent ev)
{ {
if (_volume <= -20f) PlayTTS(GetEntity(ev.Uid), ev.Data, ev.BoostVolume ? _volume + 5 : _volume);
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);
} }
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<AudioStreamWithParams>();
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 dataStream = new MemoryStream(data) { Position = 0 };
var audioStream = _audioSystem.LoadAudioOggVorbis(dataStream); return _audioManager.LoadAudioOggVorbis(dataStream);
source = _audioSystem.CreateAudioSource(audioStream);
if (source == null)
{
return false;
}
source.Volume = volume == 0f ? _volume : volume;
return true;
} }
private void AddEntityStreamToQueue(AudioStream stream) private record AudioStreamWithParams(AudioStream Stream, AudioParams Params);
{
if (_entityQueues.TryGetValue(stream.Uid, out var queue))
{
queue.Enqueue(stream);
}
else
{
_entityQueues.Add(stream.Uid, new Queue<AudioStream>(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<TransformComponent>(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;
}
} }

View File

@@ -152,7 +152,7 @@ public sealed partial class AdminVerbSystem
Act = () => Act = () =>
{ {
// Fuck you. Burn Forever. // Fuck you. Burn Forever.
flammable.FireStacks = flammable.MaximumFireStacks; flammable.FireStacks = FlammableSystem.MaximumFireStacks;
_flammableSystem.Ignite(args.Target, args.User); _flammableSystem.Ignite(args.Target, args.User);
var xform = Transform(args.Target); var xform = Transform(args.Target);
_popupSystem.PopupEntity(Loc.GetString("admin-smite-set-alight-self"), args.Target, _popupSystem.PopupEntity(Loc.GetString("admin-smite-set-alight-self"), args.Target,

View File

@@ -11,65 +11,49 @@ namespace Content.Server.Atmos.Components
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField]
public bool OnFire; public bool OnFire { get; set; }
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField]
public float FireStacks; public float FireStacks { get; set; }
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField("fireSpread")]
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]
public bool FireSpread { get; private set; } = false; public bool FireSpread { get; private set; } = false;
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField("canResistFire")]
public bool CanResistFire { get; private set; } = false; public bool CanResistFire { get; private set; } = false;
[DataField(required: true)] [DataField("damage", required: true)]
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public DamageSpecifier Damage = new(); // Empty by default, we don't want any funny NREs. public DamageSpecifier Damage = new(); // Empty by default, we don't want any funny NREs.
/// <summary> /// <summary>
/// Used for the fixture created to handle passing firestacks when two flammable objects collide. /// Used for the fixture created to handle passing firestacks when two flammable objects collide.
/// </summary> /// </summary>
[DataField] [DataField("flammableCollisionShape")]
public IPhysShape FlammableCollisionShape = new PhysShapeCircle(0.35f); public IPhysShape FlammableCollisionShape = new PhysShapeCircle(0.35f);
/// <summary> /// <summary>
/// Should the component be set on fire by interactions with isHot entities /// Should the component be set on fire by interactions with isHot entities
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField("alwaysCombustible")]
public bool AlwaysCombustible = false; public bool AlwaysCombustible = false;
/// <summary> /// <summary>
/// Can the component anyhow lose its FireStacks? /// Can the component anyhow lose its FireStacks?
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField("canExtinguish")]
public bool CanExtinguish = true; public bool CanExtinguish = true;
/// <summary> /// <summary>
/// How many firestacks should be applied to component when being set on fire? /// How many firestacks should be applied to component when being set on fire?
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField] [DataField("firestacksOnIgnite")]
public float FirestacksOnIgnite = 2.0f; public float FirestacksOnIgnite = 2.0f;
/// <summary> /// <summary>

View File

@@ -52,11 +52,13 @@ namespace Content.Server.Atmos.EntitySystems
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SpellBladeSystem _spellBlade = default!; // WD [Dependency] private readonly SpellBladeSystem _spellBlade = default!; // WD
private EntityQuery<PhysicsComponent> _physicsQuery; public const float MinimumFireStacks = -10f;
public const float MaximumFireStacks = 20f;
// This should probably be moved to the component, requires a rewrite, all fires tick at the same time
private const float UpdateTime = 1f; private const float UpdateTime = 1f;
public const float MinIgnitionTemperature = 373.15f;
public const string FlammableFixtureID = "flammable";
private float _timer; private float _timer;
private readonly Dictionary<Entity<FlammableComponent>, float> _fireEvents = new(); private readonly Dictionary<Entity<FlammableComponent>, float> _fireEvents = new();
@@ -65,8 +67,6 @@ namespace Content.Server.Atmos.EntitySystems
{ {
UpdatesAfter.Add(typeof(AtmosphereSystem)); UpdatesAfter.Add(typeof(AtmosphereSystem));
_physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<FlammableComponent, MapInitEvent>(OnMapInit); SubscribeLocalEvent<FlammableComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<FlammableComponent, InteractUsingEvent>(OnInteractUsing); SubscribeLocalEvent<FlammableComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<FlammableComponent, StartCollideEvent>(OnCollide); SubscribeLocalEvent<FlammableComponent, StartCollideEvent>(OnCollide);
@@ -141,7 +141,7 @@ namespace Content.Server.Atmos.EntitySystems
if (!TryComp<PhysicsComponent>(uid, out var body)) if (!TryComp<PhysicsComponent>(uid, out var body))
return; return;
_fixture.TryCreateFixture(uid, component.FlammableCollisionShape, component.FlammableFixtureID, hard: false, _fixture.TryCreateFixture(uid, component.FlammableCollisionShape, FlammableFixtureID, hard: false,
collisionMask: (int) CollisionGroup.FullTileLayer, body: body); 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 // 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. // 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; return;
if (!flammable.FireSpread) if (!flammable.FireSpread)
@@ -211,30 +211,49 @@ namespace Content.Server.Atmos.EntitySystems
if (!flammable.OnFire && !otherFlammable.OnFire) if (!flammable.OnFire && !otherFlammable.OnFire)
return; // Neither are on fire return; // Neither are on fire
// Both are on fire -> equalize fire stacks. // WD START
// Weight each thing's firestacks by its mass var weHold = _spellBlade.IsHoldingItemWithComponent<FireAspectComponent>(uid);
var mass1 = 1f; var theyHold = _spellBlade.IsHoldingItemWithComponent<FireAspectComponent>(otherUid);
var mass2 = 1f; // WD END
if (_physicsQuery.TryComp(uid, out var physics) && _physicsQuery.TryComp(otherUid, out var otherPhys))
if (flammable.OnFire && otherFlammable.OnFire)
{ {
mass1 = physics.Mass; if (weHold && !theyHold || theyHold && !weHold) // WD
mass2 = otherPhys.Mass; 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: // Only one is on fire -> attempt to spread the fire.
// - the thing on fire loses a small number of firestacks if (flammable.OnFire)
// - 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 if (theyHold) // WD
var total = mass1 + mass2; return;
var avg = (flammable.FireStacks + otherFlammable.FireStacks) / total; otherFlammable.FireStacks += flammable.FireStacks / 2;
Ignite(otherUid, uid, otherFlammable);
// swap the entity losing stacks depending on whichever has the most firestack kilos if (flammable.CanExtinguish)
var (src, dest) = flammable.FireStacks * mass1 > otherFlammable.FireStacks * mass2 {
? (-1f, 1f) flammable.FireStacks /= 2;
: (1f, -1f); UpdateAppearance(uid, flammable);
// 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); 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) private void OnIsHot(EntityUid uid, FlammableComponent flammable, IsHotEvent args)
@@ -244,7 +263,7 @@ namespace Content.Server.Atmos.EntitySystems
private void OnTileFire(Entity<FlammableComponent> ent, ref TileFireEvent args) private void OnTileFire(Entity<FlammableComponent> ent, ref TileFireEvent args)
{ {
var tempDelta = args.Temperature - ent.Comp.MinIgnitionTemperature; var tempDelta = args.Temperature - MinIgnitionTemperature;
_fireEvents.TryGetValue(ent, out var maxTemp); _fireEvents.TryGetValue(ent, out var maxTemp);
@@ -272,30 +291,17 @@ namespace Content.Server.Atmos.EntitySystems
_appearance.SetData(uid, ToggleableLightVisuals.Enabled, flammable.OnFire, appearance); _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)) if (!Resolve(uid, ref flammable))
return; 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 (flammable.OnFire && flammable.FireStacks <= 0)
{
if (!Resolve(uid, ref flammable))
return;
flammable.FireStacks = MathF.Min(MathF.Max(flammable.MinimumFireStacks, stacks), flammable.MaximumFireStacks);
if (flammable.FireStacks <= 0)
{
Extinguish(uid, flammable); Extinguish(uid, flammable);
}
else else
{
flammable.OnFire = ignite;
UpdateAppearance(uid, flammable); UpdateAppearance(uid, flammable);
}
} }
public void Extinguish(EntityUid uid, FlammableComponent? flammable = null) public void Extinguish(EntityUid uid, FlammableComponent? flammable = null)
@@ -444,11 +450,13 @@ namespace Content.Server.Atmos.EntitySystems
EnsureComp<IgnitionSourceComponent>(uid); EnsureComp<IgnitionSourceComponent>(uid);
_ignitionSourceSystem.SetIgnited(uid); _ignitionSourceSystem.SetIgnited(uid);
var damageScale = MathF.Min( flammable.FireStacks, 5);
if (TryComp(uid, out TemperatureComponent? temp)) if (TryComp(uid, out TemperatureComponent? temp))
_temperatureSystem.ChangeHeat(uid, 12500 * flammable.FireStacks, false, temp); _temperatureSystem.ChangeHeat(uid, 12500 * damageScale, false, temp);
if (!_spellBlade.IsHoldingItemWithComponent<FireAspectComponent>(uid)) // WD EDIT if (!_spellBlade.IsHoldingItemWithComponent<FireAspectComponent>(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); AdjustFireStacks(uid, flammable.FirestackFade * (flammable.Resisting ? 10f : 1f), flammable);
} }

View File

@@ -108,13 +108,18 @@ public partial class SeedData
/// <summary> /// <summary>
/// If true, the properties of this seed cannot be modified. /// If true, the properties of this seed cannot be modified.
/// to spare others like me: this DOES NOT prevent mutations
/// </summary> /// </summary>
[DataField("immutable")] public bool Immutable; [DataField("immutable")] public bool Immutable;
/// <summary>
/// If true, you cannot clip this plant for more seeds, used for special plants such as the gnome plant
/// </summary>
[DataField("unclippable")] public bool Unclippable;
/// <summary> /// <summary>
/// If true, there is only a single reference to this seed and it's properties can be directly modified without /// 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. /// needing to clone the seed.
/// </summary>
[ViewVariables] [ViewVariables]
public bool Unique = false; // seed-prototypes or yaml-defined seeds for entity prototypes will not generally be unique. public bool Unique = false; // seed-prototypes or yaml-defined seeds for entity prototypes will not generally be unique.
#endregion #endregion
@@ -255,6 +260,7 @@ public partial class SeedData
{ {
DebugTools.Assert(!Immutable, "There should be no need to clone an immutable seed."); DebugTools.Assert(!Immutable, "There should be no need to clone an immutable seed.");
var newSeed = new SeedData var newSeed = new SeedData
{ {
Name = Name, Name = Name,
@@ -290,6 +296,7 @@ public partial class SeedData
HarvestRepeat = HarvestRepeat, HarvestRepeat = HarvestRepeat,
Potency = Potency, Potency = Potency,
Unclippable = Unclippable,
Seedless = Seedless, Seedless = Seedless,
Viable = Viable, Viable = Viable,
Slip = Slip, Slip = Slip,

View File

@@ -245,6 +245,13 @@ public sealed class PlantHolderSystem : EntitySystem
_popup.PopupCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"), args.User); _popup.PopupCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"), args.User);
return; 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) if (component.Sampled)
{ {

View File

@@ -164,8 +164,7 @@ public sealed class MagicSystem : EntitySystem
if (!_wizardSpells.CanCast(args)) // WD EDIT if (!_wizardSpells.CanCast(args)) // WD EDIT
return; return;
args.Handled = true; _wizardSpells.Cast(args); // WD EDIT
Speak(args);
var transform = Transform(args.Performer); var transform = Transform(args.Performer);
var coords = transform.Coordinates; var coords = transform.Coordinates;
@@ -190,9 +189,7 @@ public sealed class MagicSystem : EntitySystem
if (!_wizardSpells.CanCast(ev)) // WD EDIT if (!_wizardSpells.CanCast(ev)) // WD EDIT
return; return;
ev.Handled = true; _wizardSpells.Cast(ev); // WD EDIT
Speak(ev);
var direction = _transformSystem.GetMapCoordinates(ev.Target).Position - _transformSystem.GetMapCoordinates(ev.Performer).Position; var direction = _transformSystem.GetMapCoordinates(ev.Target).Position - _transformSystem.GetMapCoordinates(ev.Performer).Position;
var impulseVector = direction * 10000; var impulseVector = direction * 10000;

View File

@@ -6,15 +6,37 @@ using Content.Shared.Popups;
using Content.Shared.Repairable; using Content.Shared.Repairable;
using Content.Shared.Tools; using Content.Shared.Tools;
using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; 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 namespace Content.Server.Repairable
{ {
public sealed class RepairableSystem : SharedRepairableSystem public sealed class RepairableSystem : SharedRepairableSystem
{ {
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!; [Dependency] private readonly SharedToolSystem _toolSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly IAdminLogManager _adminLogger= 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() public override void Initialize()
{ {
@@ -24,6 +46,8 @@ namespace Content.Server.Repairable
private void OnRepairFinished(EntityUid uid, RepairableComponent component, RepairFinishedEvent args) private void OnRepairFinished(EntityUid uid, RepairableComponent component, RepairFinishedEvent args)
{ {
ICommonSession? session = null;
if (args.Cancelled) if (args.Cancelled)
return; return;
@@ -34,15 +58,36 @@ namespace Content.Server.Repairable
{ {
var damageChanged = _damageableSystem.TryChangeDamage(uid, component.Damage, true, false, origin: args.User); 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()}"); _adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} by {damageChanged?.GetTotal()}");
} }
else else
{ {
// Repair all damage // Repair all damage
_damageableSystem.SetAllDamage(uid, damageable, 0); _damageableSystem.SetAllDamage(uid, damageable, 0);
_adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} back to full health"); _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<DamageableComponent>(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", var str = Loc.GetString("comp-repairable-repair",
("target", uid), ("target", uid),
("tool", args.Used!)); ("tool", args.Used!));

View File

@@ -0,0 +1,8 @@
namespace Content.Server.Speech.Components;
/// <summary>
/// garden time
/// </summary>
[RegisterComponent]
public sealed partial class GnomeAccentComponent : Component
{}

View File

@@ -0,0 +1,52 @@
using Content.Server.Speech.Components;
using System.Text.RegularExpressions;
namespace Content.Server.Speech.EntitySystems;
/// <summary>
/// System that Gnomes the Gnomes talking
/// </summary>
public sealed class GnomeAccentSystem : EntitySystem
{
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GnomeAccentComponent, AccentGetEvent>(OnAccentGet);
}
public string Accentuate(string message, GnomeAccentComponent component)
{
var msg = message;
msg = _replacement.ApplyReplacements(msg, "gnome");
// Пиздец, а не код
msg = Regex.Replace(msg, @"(?<!\w)\bне", "ГНЕМ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bнет", "ГНЕМТ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bнахуй", "ГНАМХУЙ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bпидоры", "ГНОМЕРЫ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bхуесос", "ГНОХУСОМ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bебал", "ГНОМИЛ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bзаебал", "ЗАГНОМИЛ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bубил", "УГНОМИЛ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bубит", "УГНОМЛЕН", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bебнул", "УГНОМЛЕН", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bстрелял", "СТРЕГНОМИЛ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bзаколол", "СГНОМИЛ", RegexOptions.IgnoreCase);
msg = Regex.Replace(msg, @"(?<!\w)\bмой", "муй", RegexOptions.None);
msg = Regex.Replace(msg, @"(?<!\w)\bдруг", "бро", RegexOptions.None);
msg = Regex.Replace(msg, @"(?<!\w)\bдрузья", "друганы", RegexOptions.None);
return msg;
}
private void OnAccentGet(EntityUid uid, GnomeAccentComponent component, AccentGetEvent args)
{
args.Message = Accentuate(args.Message, component);
}
}

View File

@@ -48,11 +48,11 @@ public sealed partial class MeteorSwarmComponent : Component
public Dictionary<EntProtoId, float> Meteors = new(); public Dictionary<EntProtoId, float> Meteors = new();
[DataField] [DataField]
public MinMax Waves = new(3, 3); public MinMax Waves = new(2, 4);
[DataField] [DataField]
public MinMax MeteorsPerWave = new(3, 4); public MinMax MeteorsPerWave = new(3, 4);
[DataField] [DataField]
public MinMax WaveCooldown = new (10, 60); public MinMax WaveCooldown = new (30, 60);
} }

View File

@@ -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<PlayerSpawnCompleteEvent>(OnPlayerSpawn);
}
private void OnPlayerSpawn(PlayerSpawnCompleteEvent args)
{
if (args.JobId == null)
return;
if (!_prototypeManager.TryIndex<JobPrototype>(args.JobId, out var jobPrototype))
return;
if (jobPrototype.AnnouncementPrototype == null)
return;
if (!_prototypeManager.TryIndex<ArrivalNotificationPrototype>(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<RadioChannelPrototype>(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;
}
}

View File

@@ -1,6 +1,16 @@
using Robust.Shared.Audio;
namespace Content.Server._White.Other.DeathGasps; namespace Content.Server._White.Other.DeathGasps;
[RegisterComponent] [RegisterComponent]
public sealed partial class DeathGaspsComponent : Component public sealed partial class DeathGaspsComponent : Component
{ {
[DataField]
public SoundSpecifier DeathSounds = new SoundCollectionSpecifier("deathSounds");
[DataField]
public SoundSpecifier HeartSounds = new SoundCollectionSpecifier("heartSounds");
[DataField]
public bool CanOtherHearDeathSound;
} }

View File

@@ -16,8 +16,7 @@ public sealed class OnDeath : EntitySystem
} }
private readonly Dictionary<EntityUid, EntityUid> _playingStreams = new(); private readonly Dictionary<EntityUid, EntityUid> _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) private void HandleDeathEvent(EntityUid uid, DeathGaspsComponent component, MobStateChangedEvent args)
{ {
@@ -31,23 +30,23 @@ public sealed class OnDeath : EntitySystem
StopPlayingStream(uid); StopPlayingStream(uid);
break; break;
case MobState.Critical: case MobState.Critical:
PlayPlayingStream(uid); PlayPlayingStream(uid, component);
break; break;
case MobState.Dead: case MobState.Dead:
StopPlayingStream(uid); StopPlayingStream(uid);
PlayDeathSound(uid); PlayDeathSound(uid, component);
break; break;
} }
} }
private void PlayPlayingStream(EntityUid uid) private void PlayPlayingStream(EntityUid uid, DeathGaspsComponent component)
{ {
if (_playingStreams.TryGetValue(uid, out var currentStream)) if (_playingStreams.TryGetValue(uid, out var currentStream))
{ {
_audio.Stop(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) if (newStream.HasValue)
{ {
@@ -64,9 +63,12 @@ public sealed class OnDeath : EntitySystem
_playingStreams.Remove(uid); _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) private void OnDetach(EntityUid uid, DeathGaspsComponent component, PlayerDetachedEvent args)

View File

@@ -63,7 +63,9 @@ public sealed partial class TTSSystem : EntitySystem
Filter filter; Filter filter;
if (ev.Global) if (ev.Global)
{
filter = Filter.Broadcast(); filter = Filter.Broadcast();
}
else else
{ {
var station = _stationSystem.GetOwningStation(ev.Source); 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) private async void OnEntitySpoke(EntityUid uid, SharedTTSComponent component, EntitySpokeEvent args)
{ {
if (!_isEnabled || if (!_isEnabled || string.IsNullOrEmpty(_apiUrl) || args.Message.Length > MaxMessageChars)
args.Message.Length > MaxMessageChars)
return;
if (string.IsNullOrEmpty(_apiUrl))
{ {
return; return;
} }
@@ -154,6 +152,7 @@ public sealed partial class TTSSystem : EntitySystem
var soundData = await GenerateTTS(uid, message, protoVoice.Speaker); var soundData = await GenerateTTS(uid, message, protoVoice.Speaker);
if (soundData is null) if (soundData is null)
return; return;
var ttsEvent = new PlayTTSEvent(GetNetEntity(uid), soundData, false); var ttsEvent = new PlayTTSEvent(GetNetEntity(uid), soundData, false);
// Say // Say
@@ -182,7 +181,6 @@ public sealed partial class TTSSystem : EntitySystem
var sourcePos = _xforms.GetWorldPosition(xformQuery.GetComponent(uid), xformQuery); var sourcePos = _xforms.GetWorldPosition(xformQuery.GetComponent(uid), xformQuery);
var receptions = Filter.Pvs(uid).Recipients; var receptions = Filter.Pvs(uid).Recipients;
foreach (var session in receptions) foreach (var session in receptions)
{ {
if (!session.AttachedEntity.HasValue) if (!session.AttachedEntity.HasValue)

View File

@@ -1,6 +1,7 @@
using Content.Shared._White.Wizard; using Content.Shared._White.Wizard;
using Content.Shared._White.Wizard.Charging; using Content.Shared._White.Wizard.Charging;
using Content.Shared.Follower; using Content.Shared.Follower;
using Content.Shared.Mobs;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Player; using Robust.Shared.Player;
@@ -25,10 +26,13 @@ public sealed class ChargingSystem : SharedChargingSystem
SubscribeNetworkEvent<RequestSpellChargingAudio>(OnCharging); SubscribeNetworkEvent<RequestSpellChargingAudio>(OnCharging);
SubscribeNetworkEvent<RequestSpellChargedAudio>(OnCharged); SubscribeNetworkEvent<RequestSpellChargedAudio>(OnCharged);
SubscribeNetworkEvent<RequestAudioSpellStop>(OnStop); SubscribeNetworkEvent<RequestAudioSpellStop>(OnStop);
SubscribeLocalEvent<PlayerDetachedEvent>(OnDetach); SubscribeLocalEvent<PlayerDetachedEvent>(OnDetach);
SubscribeLocalEvent<MobStateChangedEvent>(OnStateChanged);
SubscribeNetworkEvent<AddWizardChargeEvent>(Add); SubscribeNetworkEvent<AddWizardChargeEvent>(Add);
SubscribeNetworkEvent<RemoveWizardChargeEvent>(Remove); SubscribeNetworkEvent<RemoveWizardChargeEvent>(Remove);
} }
#region Audio #region Audio
@@ -103,40 +107,29 @@ public sealed class ChargingSystem : SharedChargingSystem
if (user == null) if (user == null)
return; return;
if (_chargingLoops.TryGetValue(user.Value, out var currentStream)) StopAllSounds(user.Value);
{
_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);
}
} }
#endregion #endregion
#region Charges #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) private void Add(AddWizardChargeEvent msg, EntitySessionEventArgs args)
{ {
if (args.SenderSession.AttachedEntity != null) if (args.SenderSession.AttachedEntity != null)
@@ -153,6 +146,21 @@ public sealed class ChargingSystem : SharedChargingSystem
#region Helpers #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) public void AddCharge(EntityUid uid, string msgChargeProto)
{ {
var itemEnt = Spawn(msgChargeProto, Transform(uid).Coordinates); var itemEnt = Spawn(msgChargeProto, Transform(uid).Coordinates);

View File

@@ -2,6 +2,7 @@ using System.Linq;
using System.Numerics; using System.Numerics;
using Content.Server._White.Cult; using Content.Server._White.Cult;
using Content.Server._White.IncorporealSystem; using Content.Server._White.IncorporealSystem;
using Content.Server._White.Wizard.Charging;
using Content.Server._White.Wizard.Magic.Amaterasu; using Content.Server._White.Wizard.Magic.Amaterasu;
using Content.Server._White.Wizard.Magic.Other; using Content.Server._White.Wizard.Magic.Other;
using Content.Server._White.Wizard.Magic.TeslaProjectile; 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 EuiManager _euiManager = default!;
[Dependency] private readonly MindSystem _mindSystem = default!; [Dependency] private readonly MindSystem _mindSystem = default!;
[Dependency] private readonly ActionContainerSystem _actionContainer = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!;
[Dependency] private readonly ChargingSystem _charging = default!;
#endregion #endregion
@@ -125,7 +127,7 @@ public sealed class WizardSpellsSystem : EntitySystem
return; return;
} }
msg.Handled = true; Cast(msg);
} }
#endregion #endregion
@@ -143,8 +145,7 @@ public sealed class WizardSpellsSystem : EntitySystem
var comp = EnsureComp<PreventCollideComponent>(ent); var comp = EnsureComp<PreventCollideComponent>(ent);
comp.Uid = msg.Performer; comp.Uid = msg.Performer;
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -187,8 +188,7 @@ public sealed class WizardSpellsSystem : EntitySystem
_standing.TryLieDown(uid); _standing.TryLieDown(uid);
_standing.TryLieDown(target); _standing.TryLieDown(target);
msg.Handled = true; Cast(msg);
Speak(msg);
SwapComponent<WizardComponent>(uid, target); SwapComponent<WizardComponent>(uid, target);
SwapComponent<RevolutionaryComponent>(uid, target); SwapComponent<RevolutionaryComponent>(uid, target);
@@ -213,8 +213,7 @@ public sealed class WizardSpellsSystem : EntitySystem
_euiManager.OpenEui(eui, actor.PlayerSession); _euiManager.OpenEui(eui, actor.PlayerSession);
eui.StateDirty(); eui.StateDirty();
msg.Handled = true; Cast(msg, false);
Speak(msg);
} }
#endregion #endregion
@@ -264,8 +263,7 @@ public sealed class WizardSpellsSystem : EntitySystem
_handsSystem.TryForcePickupAnyHand(msg.Performer, recallComponent.Item.Value); _handsSystem.TryForcePickupAnyHand(msg.Performer, recallComponent.Item.Value);
_audio.PlayPvs(recallComponent.RecallSound, msg.Performer); _audio.PlayPvs(recallComponent.RecallSound, msg.Performer);
msg.Handled = true; Cast(msg);
Speak(msg);
return; return;
} }
@@ -293,8 +291,7 @@ public sealed class WizardSpellsSystem : EntitySystem
Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates); Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates);
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -317,8 +314,7 @@ public sealed class WizardSpellsSystem : EntitySystem
Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates); Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates);
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -340,8 +336,7 @@ public sealed class WizardSpellsSystem : EntitySystem
Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates); Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates);
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -357,8 +352,7 @@ public sealed class WizardSpellsSystem : EntitySystem
_empSystem.EmpPulse(coords, 15, 1000000, 60f); _empSystem.EmpPulse(coords, 15, 1000000, 60f);
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -381,8 +375,7 @@ public sealed class WizardSpellsSystem : EntitySystem
_statusEffectsSystem.TryAddStatusEffect<IncorporealComponent>(msg.Performer, "Incorporeal", _statusEffectsSystem.TryAddStatusEffect<IncorporealComponent>(msg.Performer, "Incorporeal",
TimeSpan.FromSeconds(10), false); TimeSpan.FromSeconds(10), false);
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -434,8 +427,7 @@ public sealed class WizardSpellsSystem : EntitySystem
Spawn("AdminInstantEffectSmoke3", oldCoords); Spawn("AdminInstantEffectSmoke3", oldCoords);
Spawn("AdminInstantEffectSmoke3", coords); Spawn("AdminInstantEffectSmoke3", coords);
msg.Handled = true; Cast(msg);
Speak(msg);
} }
#endregion #endregion
@@ -460,9 +452,7 @@ public sealed class WizardSpellsSystem : EntitySystem
break; break;
} }
SetCooldown(msg.Action, msg.ActionUseType); Cast(msg);
msg.Handled = true;
Speak(msg);
} }
private void ForcewallSpellDefault(ForceWallSpellEvent msg) private void ForcewallSpellDefault(ForceWallSpellEvent msg)
@@ -533,9 +523,7 @@ public sealed class WizardSpellsSystem : EntitySystem
if (!result) if (!result)
return; return;
SetCooldown(msg.Action, msg.ActionUseType); Cast(msg);
msg.Handled = true;
Speak(msg);
} }
private void CardsSpellDefault(CardsSpellEvent msg) private void CardsSpellDefault(CardsSpellEvent msg)
@@ -638,9 +626,7 @@ public sealed class WizardSpellsSystem : EntitySystem
if (!result) if (!result)
return; return;
SetCooldown(msg.Action, msg.ActionUseType); Cast(msg);
msg.Handled = true;
Speak(msg);
} }
private void FireballSpellDefault(FireballSpellEvent msg) private void FireballSpellDefault(FireballSpellEvent msg)
@@ -725,9 +711,7 @@ public sealed class WizardSpellsSystem : EntitySystem
if (!result) if (!result)
return; return;
SetCooldown(msg.Action, msg.ActionUseType); Cast(msg);
msg.Handled = true;
Speak(msg);
} }
private bool ForceSpellAlt(ForceSpellEvent msg) private bool ForceSpellAlt(ForceSpellEvent msg)
@@ -782,9 +766,7 @@ public sealed class WizardSpellsSystem : EntitySystem
if (!result) if (!result)
return; return;
SetCooldown(msg.Action, msg.ActionUseType); Cast(msg);
msg.Handled = true;
Speak(msg);
} }
private bool ArcSpellDefault(ArcSpellEvent msg) private bool ArcSpellDefault(ArcSpellEvent msg)
@@ -844,6 +826,17 @@ public sealed class WizardSpellsSystem : EntitySystem
RaiseLocalEvent(uid, new EnergyDomeClothesTurnOffEvent()); 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) public bool CanCast(BaseActionEvent msg)
{ {
return !msg.Handled && CheckRequirements(msg.Action, msg.Performer) && return !msg.Handled && CheckRequirements(msg.Action, msg.Performer) &&

View File

@@ -1,4 +1,5 @@
using Content.Server.EUI; using Content.Server._White.Wizard.Charging;
using Content.Server.EUI;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared._White.Wizard.Teleport; using Content.Shared._White.Wizard.Teleport;
using Content.Shared.Eui; using Content.Shared.Eui;
@@ -15,6 +16,7 @@ public sealed class WizardTeleportSpellEui : BaseEui
private readonly TeleportLocationSystem _teleportLocation; private readonly TeleportLocationSystem _teleportLocation;
private readonly PullingSystem _pulling; private readonly PullingSystem _pulling;
private readonly PopupSystem _popupSystem; private readonly PopupSystem _popupSystem;
private readonly ChargingSystem _charging;
private readonly EntityUid _performer; private readonly EntityUid _performer;
@@ -28,6 +30,7 @@ public sealed class WizardTeleportSpellEui : BaseEui
_pulling = _entityManager.System<PullingSystem>(); _pulling = _entityManager.System<PullingSystem>();
_teleportLocation = _entityManager.System<TeleportLocationSystem>(); _teleportLocation = _entityManager.System<TeleportLocationSystem>();
_popupSystem = _entityManager.System<PopupSystem>(); _popupSystem = _entityManager.System<PopupSystem>();
_charging = _entityManager.System<ChargingSystem>();
_performer = performer; _performer = performer;
@@ -107,6 +110,9 @@ public sealed class WizardTeleportSpellEui : BaseEui
_entityManager.SpawnEntity("AdminInstantEffectSmoke10", oldCoords); _entityManager.SpawnEntity("AdminInstantEffectSmoke10", oldCoords);
_entityManager.SpawnEntity("AdminInstantEffectSmoke10", coords); _entityManager.SpawnEntity("AdminInstantEffectSmoke10", coords);
_charging.RemoveAllCharges(_performer);
_charging.StopAllSounds(_performer);
Close(); Close();
} }
} }

View File

@@ -125,13 +125,13 @@ namespace Content.Shared.CCVar
/// Minimum time between meteor swarms in minutes. /// Minimum time between meteor swarms in minutes.
/// </summary> /// </summary>
public static readonly CVarDef<float> public static readonly CVarDef<float>
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);
/// <summary> /// <summary>
/// Maximum time between meteor swarms in minutes. /// Maximum time between meteor swarms in minutes.
/// </summary> /// </summary>
public static readonly CVarDef<float> public static readonly CVarDef<float>
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 * Game

View File

@@ -19,16 +19,16 @@ namespace Content.Shared.Roles
[IdDataField] [IdDataField]
public string ID { get; private set; } = default!; public string ID { get; private set; } = default!;
[DataField("playTimeTracker", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))] [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))]
public string PlayTimeTracker { get; private set; } = string.Empty; public string PlayTimeTracker { get; private set; } = string.Empty;
[DataField("supervisors")] [DataField]
public string Supervisors { get; private set; } = "nobody"; public string Supervisors { get; private set; } = "nobody";
/// <summary> /// <summary>
/// The name of this job as displayed to players. /// The name of this job as displayed to players.
/// </summary> /// </summary>
[DataField("name")] [DataField]
public string Name { get; private set; } = string.Empty; public string Name { get; private set; } = string.Empty;
[ViewVariables(VVAccess.ReadOnly)] [ViewVariables(VVAccess.ReadOnly)]
@@ -37,22 +37,25 @@ namespace Content.Shared.Roles
/// <summary> /// <summary>
/// The name of this job as displayed to players. /// The name of this job as displayed to players.
/// </summary> /// </summary>
[DataField("description")] [DataField]
public string? Description { get; private set; } public string? Description { get; private set; }
[ViewVariables(VVAccess.ReadOnly)] [ViewVariables(VVAccess.ReadOnly)]
public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description); public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description);
[DataField("requirements")] [DataField]
public HashSet<JobRequirement>? Requirements; public HashSet<JobRequirement>? Requirements;
[DataField("joinNotifyCrew")] [DataField]
public bool JoinNotifyCrew { get; private set; } = false; public bool JoinNotifyCrew { get; private set; } = false;
[DataField("requireAdminNotify")] [DataField]
public string? AnnouncementPrototype;
[DataField]
public bool RequireAdminNotify { get; private set; } = false; public bool RequireAdminNotify { get; private set; } = false;
[DataField("setPreference")] [DataField]
public bool SetPreference { get; private set; } = true; public bool SetPreference { get; private set; } = true;
/// <summary> /// <summary>
@@ -62,14 +65,14 @@ namespace Content.Shared.Roles
[DataField] [DataField]
public bool? OverrideConsoleVisibility { get; private set; } = null; public bool? OverrideConsoleVisibility { get; private set; } = null;
[DataField("canBeAntag")] [DataField]
public bool CanBeAntag { get; private set; } = true; public bool CanBeAntag { get; private set; } = true;
/// <summary> /// <summary>
/// Whether this job is a head. /// Whether this job is a head.
/// The job system will try to pick heads before other jobs on the same priority level. /// The job system will try to pick heads before other jobs on the same priority level.
/// </summary> /// </summary>
[DataField("weight")] [DataField]
public int Weight { get; private set; } public int Weight { get; private set; }
/// <summary> /// <summary>
@@ -86,10 +89,10 @@ namespace Content.Shared.Roles
/// A numerical score for how much easier this job is for antagonists. /// 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. /// For traitors, reduces starting TC by this amount. Other gamemodes can use it for whatever they find fitting.
/// </summary> /// </summary>
[DataField("antagAdvantage")] [DataField]
public int AntagAdvantage = 0; public int AntagAdvantage = 0;
[DataField("startingGear", customTypeSerializer: typeof(PrototypeIdSerializer<StartingGearPrototype>))] [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<StartingGearPrototype>))]
public string? StartingGear { get; private set; } public string? StartingGear { get; private set; }
/// <summary> /// <summary>
@@ -97,28 +100,28 @@ namespace Content.Shared.Roles
/// Starting gear will be ignored. /// Starting gear will be ignored.
/// If you want to just add special attributes to a humanoid, use AddComponentSpecial instead. /// If you want to just add special attributes to a humanoid, use AddComponentSpecial instead.
/// </summary> /// </summary>
[DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? JobEntity = null; public string? JobEntity = null;
[DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))] [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
public string Icon { get; private set; } = "JobIconUnknown"; public string Icon { get; private set; } = "JobIconUnknown";
[DataField("special", serverOnly: true)] [DataField(serverOnly: true)]
public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>(); public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();
[DataField("access")] [DataField]
public IReadOnlyCollection<ProtoId<AccessLevelPrototype>> Access { get; private set; } = Array.Empty<ProtoId<AccessLevelPrototype>>(); public IReadOnlyCollection<ProtoId<AccessLevelPrototype>> Access { get; private set; } = Array.Empty<ProtoId<AccessLevelPrototype>>();
[DataField("accessGroups")] [DataField]
public IReadOnlyCollection<ProtoId<AccessGroupPrototype>> AccessGroups { get; private set; } = Array.Empty<ProtoId<AccessGroupPrototype>>(); public IReadOnlyCollection<ProtoId<AccessGroupPrototype>> AccessGroups { get; private set; } = Array.Empty<ProtoId<AccessGroupPrototype>>();
[DataField("extendedAccess")] [DataField]
public IReadOnlyCollection<ProtoId<AccessLevelPrototype>> ExtendedAccess { get; private set; } = Array.Empty<ProtoId<AccessLevelPrototype>>(); public IReadOnlyCollection<ProtoId<AccessLevelPrototype>> ExtendedAccess { get; private set; } = Array.Empty<ProtoId<AccessLevelPrototype>>();
[DataField("extendedAccessGroups")] [DataField]
public IReadOnlyCollection<ProtoId<AccessGroupPrototype>> ExtendedAccessGroups { get; private set; } = Array.Empty<ProtoId<AccessGroupPrototype>>(); public IReadOnlyCollection<ProtoId<AccessGroupPrototype>> ExtendedAccessGroups { get; private set; } = Array.Empty<ProtoId<AccessGroupPrototype>>();
[DataField("whitelistedSpecies")] [DataField]
public IReadOnlyCollection<ProtoId<SpeciesPrototype>> WhitelistedSpecies { get; private set; } = Array.Empty<ProtoId<SpeciesPrototype>>(); public IReadOnlyCollection<ProtoId<SpeciesPrototype>> WhitelistedSpecies { get; private set; } = Array.Empty<ProtoId<SpeciesPrototype>>();
} }

View File

@@ -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!;
/// <summary>
/// The message that the department will receive upon the player arrival
/// </summary>
[DataField(required: true)]
public string Message = default!;
/// <summary>
/// The message that the station will receive upon the player arrival
/// </summary>
[DataField]
public string GlobalMessage = default!;
/// <summary>
/// ID of the channel where the player arrival will be announced.
/// </summary>
[DataField(required: true)]
public HashSet<string> RadioChannelsPrototypes = default!;
/// <summary>
/// Determines whether the notification will be made to the entire station. If false, the notification will be on the department radio channel
/// </summary>
[DataField]
public bool UseGlobalAnnouncement;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -5264,3 +5264,140 @@
id: 339 id: 339
time: '2024-06-30T07:04:16.0000000+00:00' time: '2024-06-30T07:04:16.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/400 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

View File

@@ -232,3 +232,7 @@ ghost-role-information-artifact-name = Sentient Artifact
ghost-role-information-artifact-description = ghost-role-information-artifact-description =
Enact your eldritch whims. Enact your eldritch whims.
Forcibly activate your nodes for good or for evil. 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.

View File

@@ -111,3 +111,5 @@ seeds-pumpkin-name = pumpkin
seeds-pumpkin-display-name = pumpkins seeds-pumpkin-display-name = pumpkins
seeds-cotton-name = cotton seeds-cotton-name = cotton
seeds-cotton-display-name = cotton plant seeds-cotton-display-name = cotton plant
seeds-gome-name = gnome
seeds-gnome-display-name = gnome plant

View File

@@ -0,0 +1,3 @@
head-arrived-message = { $character }, { $job }, Глава отдела
head-arrived-message-global = { $job } { $character } на станции
head-arrived-sender = Автоматическая Система Оповещений

View File

@@ -0,0 +1,6 @@
ent-MobGnome = гном
.desc = Добросовестный помощник по саду
ent-GnomeSeeds = пакет семян гнома
.desc = { ent-SeedBase.desc }
ent-ClothingHeadHatGnome = шляпа гнома
.desc = Шляпа настоящего садового помощника

View File

@@ -1,4 +1,4 @@
- type: body - type: body
id: Bot id: Bot
name: "bot" name: "bot"
root: hand 1 root: hand 1

View File

@@ -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

View File

@@ -20,6 +20,8 @@
amount: 2 amount: 2
- id: BungoSeeds - id: BungoSeeds
amount: 2 amount: 2
- id: GnomeSeeds
amount: 1
- type: entity - type: entity
id: CrateHydroponicsSeedsMedicinal id: CrateHydroponicsSeedsMedicinal

View File

@@ -125,7 +125,19 @@
- id: Soap - id: Soap
prob: 0.10 prob: 0.10
- id: PlushieCarp - 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 - id: PlushieSlime
prob: 0.1 prob: 0.1
- id: PlushieSnake - id: PlushieSnake

View File

@@ -37,5 +37,7 @@
BerrySeeds: 5 BerrySeeds: 5
PeaSeeds: 5 PeaSeeds: 5
CottonSeeds: 5 CottonSeeds: 5
contrabandInventory:
GnomeSeeds: 1
emaggedInventory: emaggedInventory:
FlyAmanitaSeeds: 1 FlyAmanitaSeeds: 1

View File

@@ -1108,3 +1108,19 @@
sprite: Clothing/Head/Hats/beret_medic.rsi sprite: Clothing/Head/Hats/beret_medic.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Hats/beret_medic.rsi 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

View File

@@ -819,3 +819,182 @@
# - type: AlwaysRevolutionaryConvertible # - type: AlwaysRevolutionaryConvertible
- type: StealTarget - type: StealTarget
stealGroup: AnimalTropico 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

View File

@@ -19,6 +19,8 @@
map: [ "enum.SolutionContainerLayers.Overlay" ] map: [ "enum.SolutionContainerLayers.Overlay" ]
- type: Appearance - type: Appearance
- type: Glue - type: Glue
- type: RefillableSolution
solution: drink
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
drink: drink:
@@ -26,6 +28,11 @@
reagents: reagents:
- ReagentId: SpaceGlue - ReagentId: SpaceGlue
Quantity: 30 Quantity: 30
Welder:
reagents:
- ReagentId: SpaceGlue
Quantity: 30
maxVol: 30
- type: SolutionContainerVisuals - type: SolutionContainerVisuals
maxFillLevels: 6 maxFillLevels: 6
fillBaseName: fill fillBaseName: fill
@@ -38,8 +45,15 @@
- type: Tag - type: Tag
tags: tags:
- DrinkSpaceGlue - DrinkSpaceGlue
- GlueTool
- type: TrashOnSolutionEmpty - type: TrashOnSolutionEmpty
solution: drink 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 - type: entity
parent: DrinkBase parent: DrinkBase

View File

@@ -1514,6 +1514,8 @@
- type: Tag - type: Tag
tags: tags:
- DrinkSpaceGlue - DrinkSpaceGlue
- type: Tool
qualities: Gluing
- type: entity - type: entity
parent: BaseItem parent: BaseItem

View File

@@ -571,3 +571,13 @@
seedId: cotton seedId: cotton
- type: Sprite - type: Sprite
sprite: Objects/Specific/Hydroponics/cotton.rsi 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

View File

@@ -1501,3 +1501,22 @@
Max: 10 Max: 10
PotencyDivisor: 20 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

View File

@@ -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

View File

@@ -32,12 +32,5 @@
icon: icon:
sprite: Objects/Misc/stock_parts.rsi sprite: Objects/Misc/stock_parts.rsi
state: capacitor state: capacitor
doAfter: 5
- tag: CapacitorStockPart
name: capacitor
icon:
sprite: Objects/Misc/stock_parts.rsi
state: capacitor
doAfter: 5
- node: medsecHud - node: medsecHud
entity: ClothingEyesHudMedSec entity: ClothingEyesHudMedSec

View File

@@ -65,10 +65,5 @@
icon: icon:
sprite: Objects/Misc/stock_parts.rsi sprite: Objects/Misc/stock_parts.rsi
state: capacitor state: capacitor
- tag: CapacitorStockPart
name: capacitor
icon:
sprite: Objects/Misc/stock_parts.rsi
state: capacitor
- node: potatoaichip - node: potatoaichip
entity: PotatoAIChip entity: PotatoAIChip

View File

@@ -15,6 +15,7 @@
weight: 10 weight: 10
startingGear: QuartermasterGear startingGear: QuartermasterGear
icon: "JobIconQuarterMaster" icon: "JobIconQuarterMaster"
announcementPrototype: QuartermasterArrivalNotification
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
whitelistedSpecies: whitelistedSpecies:
- Human - Human

View File

@@ -20,6 +20,7 @@
icon: "JobIconCaptain" icon: "JobIconCaptain"
requireAdminNotify: true requireAdminNotify: true
joinNotifyCrew: true joinNotifyCrew: true
announcementPrototype: CaptainArrivalNotification
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom
whitelistedSpecies: whitelistedSpecies:
- Human - Human

View File

@@ -19,6 +19,7 @@
startingGear: HoPGear startingGear: HoPGear
icon: "JobIconHeadOfPersonnel" icon: "JobIconHeadOfPersonnel"
requireAdminNotify: true requireAdminNotify: true
announcementPrototype: HeadOfPersonnelArrivalNotification
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
whitelistedSpecies: whitelistedSpecies:
- Human - Human

View File

@@ -16,6 +16,7 @@
startingGear: ChiefEngineerGear startingGear: ChiefEngineerGear
icon: "JobIconChiefEngineer" icon: "JobIconChiefEngineer"
requireAdminNotify: true requireAdminNotify: true
announcementPrototype: ChiefEngineerArrivalNotification
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
whitelistedSpecies: whitelistedSpecies:
- Human - Human

View File

@@ -14,6 +14,7 @@
time: 36000 #10 hrs time: 36000 #10 hrs
startingGear: InspectorGear startingGear: InspectorGear
icon: "JobIconInspector" icon: "JobIconInspector"
announcementPrototype: InspectorArrivalNotification
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
access: access:
- Service - Service

View File

@@ -14,6 +14,7 @@
weight: 10 weight: 10
startingGear: CMOGear startingGear: CMOGear
icon: "JobIconChiefMedicalOfficer" icon: "JobIconChiefMedicalOfficer"
announcementPrototype: ChiefMedicalOfficerArrivalNotification
requireAdminNotify: true requireAdminNotify: true
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
whitelistedSpecies: whitelistedSpecies:

View File

@@ -13,6 +13,7 @@
startingGear: ResearchDirectorGear startingGear: ResearchDirectorGear
icon: "JobIconResearchDirector" icon: "JobIconResearchDirector"
requireAdminNotify: true requireAdminNotify: true
announcementPrototype: ResearchDirectorArrivalNotification
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
whitelistedSpecies: whitelistedSpecies:
- Human - Human

View File

@@ -16,6 +16,7 @@
startingGear: HoSGear startingGear: HoSGear
icon: "JobIconHeadOfSecurity" icon: "JobIconHeadOfSecurity"
requireAdminNotify: true requireAdminNotify: true
announcementPrototype: HeadOfSecurityArrivalNotification
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
whitelistedSpecies: whitelistedSpecies:
- Human - Human

View File

@@ -620,3 +620,13 @@
path: /Audio/Animals/parrot_raught.ogg path: /Audio/Animals/parrot_raught.ogg
params: params:
variation: 0.125 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

View File

@@ -20,7 +20,7 @@
noSpawn: true noSpawn: true
components: components:
- type: InstantAction - type: InstantAction
useDelay: 1.5 useDelay: 2.5
itemIconStyle: BigAction itemIconStyle: BigAction
priority: -20 priority: -20
icon: icon:

View File

@@ -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

View File

@@ -93,7 +93,7 @@
icon: { sprite: /Textures/White/Objects/Weapons/hardlight_spear.rsi, state: spear } icon: { sprite: /Textures/White/Objects/Weapons/hardlight_spear.rsi, state: spear }
productEntity: HardlightSpearImplanter productEntity: HardlightSpearImplanter
cost: cost:
Telecrystal: 12 Telecrystal: 10
categories: categories:
- UplinkImplants - UplinkImplants
conditions: conditions:

View File

@@ -18,8 +18,8 @@
- type: DamageOtherOnHit - type: DamageOtherOnHit
damage: damage:
types: types:
Piercing: 20 Piercing: 30
Heat: 20 Heat: 30
- type: Wieldable - type: Wieldable
- type: IncreaseDamageOnWield - type: IncreaseDamageOnWield
damage: damage:

View File

@@ -61,8 +61,8 @@
ckey: reider207 ckey: reider207
sprite: White/Ghosts/reider207-ghost.rsi sprite: White/Ghosts/reider207-ghost.rsi
alpha: 0.8 alpha: 0.8
ghostName: Соня ghostName: Tighnari
ghostDescription: Видишь спит соня? Так не буди ghostDescription: But what are they going to do, lock me up?
size: 0.8, 0.8 size: 0.8, 0.8
#mikvisan #mikvisan

View File

@@ -0,0 +1,8 @@
- type: speechSounds
id: GnomesSpeech
saySound:
collection: GnomesSpeechCollection
askSound:
collection: GnomesSpeechCollection
exclaimSound:
collection: GnomesSpeechCollection

View File

@@ -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

View File

@@ -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

View File

@@ -15,12 +15,15 @@
- type: Clothing - type: Clothing
sprite: White/Objects/Weapons/Chaplain/hfrequency.rsi sprite: White/Objects/Weapons/Chaplain/hfrequency.rsi
slots: slots:
- back - none
- suitStorage
- type: Reflect - type: Reflect
reflectProb: 0.4 reflectProb: 0.4
- type: Item - type: Item
sprite: White/Objects/Weapons/Chaplain/hfrequency.rsi sprite: White/Objects/Weapons/Chaplain/hfrequency.rsi
size: Large
storedRotation: 44
shape:
- 0, 0, 3, 0
- type: entity - type: entity
name: клинок заклинаний name: клинок заклинаний

View File

@@ -8,6 +8,7 @@
rules: rules:
- RampingStationEventScheduler - RampingStationEventScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- GameRuleMeteorScheduler
- type: gamePreset - type: gamePreset
id: AllAtOnce id: AllAtOnce
@@ -24,6 +25,7 @@
- Cult - Cult
- Wizard - Wizard
- BasicRoundstartVariation - BasicRoundstartVariation
- GameRuleMeteorScheduler
- type: gamePreset - type: gamePreset
id: Extended id: Extended
@@ -175,6 +177,7 @@
- Pirates - Pirates
- BasicStationEventScheduler - BasicStationEventScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- GameRuleMeteorScheduler
#WD EDIT START #WD EDIT START
- type: gamePreset - type: gamePreset
@@ -190,6 +193,7 @@
- SubGamemodesRule - SubGamemodesRule
- BasicStationEventScheduler - BasicStationEventScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- GameRuleMeteorScheduler
- type: gamePreset - type: gamePreset
id: Changeling id: Changeling
@@ -204,6 +208,7 @@
- SubGamemodesRule - SubGamemodesRule
- BasicStationEventScheduler - BasicStationEventScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- GameRuleMeteorScheduler
- type: gamePreset - type: gamePreset
id: Wizard id: Wizard
@@ -219,4 +224,5 @@
- SubGamemodesRule - SubGamemodesRule
- BasicStationEventScheduler - BasicStationEventScheduler
- BasicRoundstartVariation - BasicRoundstartVariation
- GameRuleMeteorScheduler
#WD EDIT END #WD EDIT END

View File

@@ -1,8 +1,12 @@
# Non-fungible apes, anyone? # Non-fungible apes, anyone?
- type: nameIdentifierGroup - type: nameIdentifierGroup
id: Monkey id: Monkey
prefix: MK prefix: MK
- type: nameIdentifierGroup
id: Gnome
prefix: GN
- type: nameIdentifierGroup - type: nameIdentifierGroup
id: Kobold id: Kobold
prefix: KB prefix: KB

View File

@@ -644,6 +644,9 @@
- type: Tag - type: Tag
id: Grenade id: Grenade
- type: Tag # tag to make a glue tool use glue on repair
id: GlueTool
- type: Tag - type: Tag
id: HudMedical id: HudMedical
@@ -1325,5 +1328,3 @@
- type: Tag - type: Tag
id: WriteIgnoreStamps id: WriteIgnoreStamps
# ALPHABETICAL

View File

@@ -74,3 +74,10 @@
toolName: tool-quality-rolling-tool-name toolName: tool-quality-rolling-tool-name
spawn: RollingPin spawn: RollingPin
icon: { sprite: Objects/Tools/rolling_pin.rsi, state: icon } 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 }

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

View File

@@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

View File

@@ -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
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

View File

@@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -3,8 +3,8 @@
"license": "CC-BY-SA-3.0", "license": "CC-BY-SA-3.0",
"copyright": "reider207", "copyright": "reider207",
"size": { "size": {
"x": 64, "x": 128,
"y": 64 "y": 128
}, },
"states": [ "states": [
{ {