R
z&M>RHXub%s^HMv`-1EC!6(|^9t=*Ujl%@fxv*wzOT+)o7i
zv9k+3)5h-u*%o4J06&prI)xyfFPFHnuNf8C*VLa-Dhm;F|m%PMjHM+yg
z0cLE1nGkelbsnsB0s9}8GIL&{)n5DT!&L#s+j$WA1%#kqP}fx2@Ud|e|0UQiX9Ix1
dfxv;lfnQV1WiT-mDvSUC002ovPDHLkV1oQr3V{Fs
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-left.png b/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e6ce0b9b9f63977587e93de8f8fc7812843f4d5
GIT binary patch
literal 564
zcmV-40?Yl0P)Px$?ny*JRCr$Pnn6oKK@i91;TJG0q$q?86b*XdLAvw}BItt#QgraxrBmQVQK&;;
zf~6ExP!PPBg$EWU`F6M2ZU67IymfYFe)FGw9wwr|pD6JB2>_sgzzLuQ0v7--L9_r`
zAaDX`fxrcTuK-#AEf6>Xv_Rkjz*pc;TA;jBNp7wOnSJTnFH(8tpcWn4*gr^k|LXE0
z;&rjGLgVQpJw1%+Hz0KFmuYLG05DNgT(N%jHxIqx%VQ^8E0-Ubjo-?Gm-y?YVw+
z?UzYB{jD(o&1N%setl8rzQ27?rCL>0X8?nKUnM>q-Ko7=y-ugClP|t??Xx7$Hbwv(
z9vvrKU4B*zd74b06o5{rqu%Y-D%9=uXfJNeZ3SKXtjQY#z?W2ht*EM<_BsPNKWjz2
zm&$(jKH&Qy4P4h=8~_Kv{ky(ZQWxL%wYm?6w<=-YOV_i3>)L09V59}II(NYi09>eo
zWDHP%Bz+frLjf*SK{5s?K$5--zM%jYsvsEy6d+081>aDB3ssPe0Sb_$?}BeAz=bME
z#sCFK(s#i(6yQP?Bx8UAB+Z+^
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-right.png b/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..41ca0dddfb5127675137c8cb082dd3c4be81aba7
GIT binary patch
literal 567
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z-+Q_^hE&A8
zo#p7w6ew^!{Uf)8SdfSlTNj&d#RR?DW{zJA8bxGn%3g|81d6;8n315#DJsGtZM-2U
z@Z%lPv}xb(U*7b7{ejPaI2j%=oabD?YGcmOrVz!T`@oWMOT%-v
z1K|w14PqbWFhm_FW`3ak;0n{zyR{3*hHcbfGuTof3Bvn}YGfMwSrqNu^
z2EXOX=f7o(zWP>GB4FmT%}MGnQ$xE;-C~WaebsXrW8$_j#dYWYFO~aHv%%=Yr5Euk
z2mfx~89eFW_s?<94t|LH_9?0+pVeWFc4wV&=#?f;hNvfNkF+wc332jfms#L?&nw2_
zfS2l)k^_vSN~}4;82PVWL9ik9-2JUuucgX089dM3k8RC(Tg*1$%b!?n!|OZz7%t7(
zznkmgt>-KXXMgSvOIlYrm*K
Date: Wed, 8 May 2024 00:21:01 +0000
Subject: [PATCH 024/215] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 3ce8ccd5ec7..96c8b20e766 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Whisper
- changes:
- - message: Iron and copper no longer grant infinite blood!
- type: Fix
- id: 6050
- time: '2024-02-28T21:56:22.0000000+00:00'
- url: https://github.com/space-wizards/space-station-14/pull/25678
- author: Cojoke-dot
changes:
- message: E-sword now lights plasma fires
@@ -3853,3 +3846,12 @@
id: 6549
time: '2024-05-07T18:20:44.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25515
+- author: OnsenCapy
+ changes:
+ - message: Combat gloves now have their own unique sprite.
+ type: Tweak
+ - message: Combat gloves now have heat resistance to match their fireproof description.
+ type: Tweak
+ id: 6550
+ time: '2024-05-08T00:19:55.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/27373
From dc4de10036abd14ff1d936926d370db1dfc6dc2b Mon Sep 17 00:00:00 2001
From: pigeonpeas <147350443+pigeonpeas@users.noreply.github.com>
Date: Tue, 7 May 2024 20:22:25 -0400
Subject: [PATCH 025/215] Make the floppy lizard ears have two colors. (#27679)
* Make the floppy lizard ears have two colors.
* please fix whatever the hell happened
* fix the error
* suggestion from Ubaser
* another suggestion from ubaser
---
Resources/Locale/en-US/markings/reptilian.ftl | 3 ++-
.../Mobs/Customization/Markings/reptilian.yml | 4 +++-
.../Prototypes/Entities/Mobs/NPCs/animals.yml | 1 -
...g => horns_floppy_kobold_ears_primary.png} | Bin 1717 -> 1696 bytes
.../horns_floppy_kobold_ears_secondary.png | Bin 0 -> 197 bytes
.../reptilian_parts.rsi/meta.json | 6 +++++-
6 files changed, 10 insertions(+), 4 deletions(-)
rename Resources/Textures/Mobs/Customization/reptilian_parts.rsi/{horns_floppy_kobold_ears.png => horns_floppy_kobold_ears_primary.png} (74%)
create mode 100644 Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png
diff --git a/Resources/Locale/en-US/markings/reptilian.ftl b/Resources/Locale/en-US/markings/reptilian.ftl
index 470af07361d..c2a2df4b3ba 100644
--- a/Resources/Locale/en-US/markings/reptilian.ftl
+++ b/Resources/Locale/en-US/markings/reptilian.ftl
@@ -96,7 +96,8 @@ marking-LizardHornsBighorn = Lizard Horns (Bighorn)
marking-LizardHornsKoboldEars-horns_kobold_ears = Lizard Ears (Kobold)
marking-LizardHornsKoboldEars = Lizard Ears (Kobold)
-marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears = Lizard Ears (Floppy Kobold)
+marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears_primary = Lizard Ears (Floppy Kobold)
+marking-LizardHornsFloppyKoboldEars-horns-floppy_kobold_ears_secondary = Lizard Ears (Floppy Kobold)
marking-LizardHornsFloppyKoboldEars = Lizard Ears (Floppy Kobold)
marking-LizardChestUnderbelly-body_underbelly = Lizard Chest (Underbelly)
diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml
index 5a52e09bf2d..95cfb72e875 100644
--- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml
+++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml
@@ -310,7 +310,9 @@
speciesRestriction: [Reptilian]
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
- state: horns_floppy_kobold_ears
+ state: horns_floppy_kobold_ears_primary
+ - sprite: Mobs/Customization/reptilian_parts.rsi
+ state: horns_floppy_kobold_ears_secondary
- type: marking
id: LizardChestUnderbelly
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
index 7fb431fabb5..6bc0d7a598f 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
@@ -1434,7 +1434,6 @@
horns_bighorn: KoboldHornColors
horns_argali: KoboldHornColors
horns_ayrshire: KoboldHornColors
- horns_floppy_kobold_ears: Inherit
horns_double: Inherit
horns_kobold_ears: Inherit
- type: Butcherable
diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png
similarity index 74%
rename from Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png
rename to Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png
index 061c0100cc5cc0d2216f0e25819a546421c7d300..89d7eaef817d3abd4702b58e71d92c1ffdda29b4 100644
GIT binary patch
delta 321
zcmV-H0lxmV4WJFM-2plbP)t-sdU|@dx3{FEqyPW_*0rV`00004bW%=J|Ns90Kq{&9
z00009a7bBm001bK001bK0nAOV#j_g%kpq9@Nkl{xl=
z5rPmfAqW8z0xNL#vcg~Ql*syhK<#EN;QiUd8`NrD1&;>qxfAFOw?Qv=C6Ei?*%sSn
z1j|xgF#i`Ipm|*3F0|XxFe0j#lh1%UrL`w`gR^l4TaSl4LJ$Hb1R-F4EvWSapJ^^9
Tc?DQO00000NkvXXu0mjfcEE>}
delta 343
zcmV-d0jU0<4Yduh-2pxiP)t-sdU|@dx3{FEq?DAD0000ux)%Ka000GaQchF<|Ns90
z`?d~K00009a7bBm001bN001bN0lI?#-?JA2kpqA9Nkl
zFrv3a!%{BlYApt#?Mr)@E(BbJ;sIKlvI&s=(hFjD5M)i8U|9%IYhHo3Mh`sz<~!uK
zXaIkpg~bG@=`sM=fodOgwGPheHNaB<0w4-N07L=U0ZuM2^5dP07QYW#vUvqaeyY9E
z60IlTksvd70JS&r0qp{KW@?|>07s}E+P*IU!24&a8{%w7!f@QrZ~g{6*+#X%8@yW=
p;pponPXP#kC;$Nv{Tfi~2lKN%Lkjt^{s0RA002ovPDHLkV1hgVk!An@
diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png
new file mode 100644
index 0000000000000000000000000000000000000000..b40d099eabd5c9969e85ab0a30ac36185fdccf56
GIT binary patch
literal 197
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl
z_H+M9WCij$3p^r=85sEXgD|57Yp@DXFv`=#F{C2y?IlCL1_KV(fG=}w?cu7{dLP*Y(}<
Date: Wed, 8 May 2024 00:25:41 +0000
Subject: [PATCH 026/215] make dragons breathe fire (#26746)
* add ActionGun system
* add RepeatingTrigger
* dragons breath projectile, repeatedly explodes
* give dragon fire breathing action, fireproof it
* oop
* oop 2
* prevent troll
* proper repeating thing
* pro
* webedit ops
* realops
---------
Co-authored-by: deltanedas <@deltanedas:kde.org>
---
.../Components/ExplosiveComponent.cs | 7 +++
.../Components/RepeatingTriggerComponent.cs | 25 +++++++++++
.../EntitySystems/ExplosionSystem.cs | 2 +-
.../Explosion/EntitySystems/TriggerSystem.cs | 21 +++++++++
.../Ranged/Components/ActionGunComponent.cs | 37 +++++++++++++++
.../Weapons/Ranged/Systems/ActionGunSystem.cs | 41 +++++++++++++++++
.../Entities/Mobs/Player/dragon.yml | 45 +++++++++++++++++++
.../Weapons/Guns/Projectiles/magic.yml | 33 ++++++++++++++
8 files changed, 210 insertions(+), 1 deletion(-)
create mode 100644 Content.Server/Explosion/Components/RepeatingTriggerComponent.cs
create mode 100644 Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs
create mode 100644 Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs
diff --git a/Content.Server/Explosion/Components/ExplosiveComponent.cs b/Content.Server/Explosion/Components/ExplosiveComponent.cs
index 04a08955a35..2b27a89d9db 100644
--- a/Content.Server/Explosion/Components/ExplosiveComponent.cs
+++ b/Content.Server/Explosion/Components/ExplosiveComponent.cs
@@ -81,6 +81,13 @@ public sealed partial class ExplosiveComponent : Component
[DataField("deleteAfterExplosion")]
public bool? DeleteAfterExplosion;
+ ///
+ /// Whether to not set to true, allowing it to explode multiple times.
+ /// This should never be used if it is damageable.
+ ///
+ [DataField]
+ public bool Repeatable;
+
///
/// Avoid somehow double-triggering this explosion (e.g. by damaging this entity from its own explosion.
///
diff --git a/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs b/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs
new file mode 100644
index 00000000000..cc08de53f90
--- /dev/null
+++ b/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs
@@ -0,0 +1,25 @@
+using Content.Server.Explosion.EntitySystems;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Server.Explosion.Components;
+
+///
+/// Constantly triggers after being added to an entity.
+///
+[RegisterComponent, Access(typeof(TriggerSystem))]
+[AutoGenerateComponentPause]
+public sealed partial class RepeatingTriggerComponent : Component
+{
+ ///
+ /// How long to wait between triggers.
+ /// The first trigger starts this long after the component is added.
+ ///
+ [DataField]
+ public TimeSpan Delay = TimeSpan.FromSeconds(1);
+
+ ///
+ /// When the next trigger will be.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
+ public TimeSpan NextTrigger;
+}
diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
index 23543895e6f..8734c054d64 100644
--- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
+++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
@@ -160,7 +160,7 @@ public void TriggerExplosive(EntityUid uid, ExplosiveComponent? explosive = null
if (explosive.Exploded)
return;
- explosive.Exploded = true;
+ explosive.Exploded = !explosive.Repeatable;
// Override the explosion intensity if optional arguments were provided.
if (radius != null)
diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs
index 3675c214b14..8e0a75ea24f 100644
--- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs
+++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs
@@ -94,6 +94,7 @@ public override void Initialize()
SubscribeLocalEvent(OnStepTriggered);
SubscribeLocalEvent(OnSlipTriggered);
SubscribeLocalEvent(OnEmptyTriggered);
+ SubscribeLocalEvent(OnRepeatInit);
SubscribeLocalEvent(OnSpawnTrigger);
SubscribeLocalEvent(HandleDeleteTrigger);
@@ -241,6 +242,11 @@ private void OnEmptyTriggered(EntityUid uid, TriggerWhenEmptyComponent component
Trigger(uid, args.EmptyGun);
}
+ private void OnRepeatInit(Entity ent, ref MapInitEvent args)
+ {
+ ent.Comp.NextTrigger = _timing.CurTime + ent.Comp.Delay;
+ }
+
public bool Trigger(EntityUid trigger, EntityUid? user = null)
{
var triggerEvent = new TriggerEvent(trigger, user);
@@ -323,6 +329,7 @@ public override void Update(float frameTime)
UpdateProximity();
UpdateTimer(frameTime);
UpdateTimedCollide(frameTime);
+ UpdateRepeat();
}
private void UpdateTimer(float frameTime)
@@ -357,5 +364,19 @@ private void UpdateTimer(float frameTime)
_appearance.SetData(uid, TriggerVisuals.VisualState, TriggerVisualState.Unprimed, appearance);
}
}
+
+ private void UpdateRepeat()
+ {
+ var now = _timing.CurTime;
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var comp))
+ {
+ if (comp.NextTrigger > now)
+ continue;
+
+ comp.NextTrigger = now + comp.Delay;
+ Trigger(uid);
+ }
+ }
}
}
diff --git a/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs b/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs
new file mode 100644
index 00000000000..112339efd74
--- /dev/null
+++ b/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs
@@ -0,0 +1,37 @@
+using Content.Shared.Actions;
+using Content.Shared.Weapons.Ranged.Systems;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Weapons.Ranged.Components;
+
+///
+/// Lets you shoot a gun using an action.
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(ActionGunSystem))]
+public sealed partial class ActionGunComponent : Component
+{
+ ///
+ /// Action to create, must use .
+ ///
+ [DataField(required: true)]
+ public EntProtoId Action = string.Empty;
+
+ [DataField]
+ public EntityUid? ActionEntity;
+
+ ///
+ /// Prototype of gun entity to spawn.
+ /// Deleted when this component is removed.
+ ///
+ [DataField(required: true)]
+ public EntProtoId GunProto = string.Empty;
+
+ [DataField]
+ public EntityUid? Gun;
+}
+
+///
+/// Action event for to shoot at a position.
+///
+public sealed partial class ActionGunShootEvent : WorldTargetActionEvent;
diff --git a/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs
new file mode 100644
index 00000000000..f3dfe8a2a03
--- /dev/null
+++ b/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs
@@ -0,0 +1,41 @@
+using Content.Shared.Actions;
+using Content.Shared.Weapons.Ranged.Components;
+
+namespace Content.Shared.Weapons.Ranged.Systems;
+
+public sealed class ActionGunSystem : EntitySystem
+{
+ [Dependency] private readonly SharedActionsSystem _actions = default!;
+ [Dependency] private readonly SharedGunSystem _gun = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnMapInit);
+ SubscribeLocalEvent(OnShutdown);
+ SubscribeLocalEvent(OnShoot);
+ }
+
+ private void OnMapInit(Entity ent, ref MapInitEvent args)
+ {
+ if (string.IsNullOrEmpty(ent.Comp.Action))
+ return;
+
+ _actions.AddAction(ent, ref ent.Comp.ActionEntity, ent.Comp.Action);
+ ent.Comp.Gun = Spawn(ent.Comp.GunProto);
+ }
+
+ private void OnShutdown(Entity ent, ref ComponentShutdown args)
+ {
+ if (ent.Comp.Gun is {} gun)
+ QueueDel(gun);
+ }
+
+ private void OnShoot(Entity ent, ref ActionGunShootEvent args)
+ {
+ if (TryComp(ent.Comp.Gun, out var gun))
+ _gun.AttemptShoot(ent, ent.Comp.Gun.Value, gun, args.Target);
+ }
+}
+
diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml
index ee0db34fc2d..cb9dc1c911a 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml
@@ -91,6 +91,12 @@
speedModifierThresholds:
250: 0.7
400: 0.5
+ # disable taking damage from fire, since its a fire breathing dragon
+ - type: Flammable
+ damage:
+ types: {}
+ - type: Temperature
+ heatDamageThreshold: 800
- type: Metabolizer
solutionOnBody: false
updateInterval: 0.25
@@ -141,10 +147,33 @@
spawnRiftAction: ActionSpawnRift
- type: GenericAntag
rule: Dragon
+ - type: ActionGun
+ action: ActionDragonsBreath
+ gunProto: DragonsBreathGun
- type: GuideHelp
guides:
- MinorAntagonists
+- type: entity
+ noSpawn: true
+ id: DragonsBreathGun
+ name: dragon's lung
+ description: For dragon's breathing
+ components:
+ - type: RechargeBasicEntityAmmo
+ rechargeCooldown: 5
+ rechargeSound:
+ path: /Audio/Animals/space_dragon_roar.ogg
+ - type: BasicEntityAmmoProvider
+ proto: ProjectileDragonsBreath
+ capacity: 1
+ count: 1
+ - type: Gun
+ soundGunshot:
+ path: /Audio/Animals/space_dragon_roar.ogg
+ soundEmpty: null
+ projectileSpeed: 5
+
- type: entity
parent: BaseMobDragon
id: MobDragonDungeon
@@ -183,6 +212,7 @@
state: icon
event: !type:DragonSpawnRiftActionEvent
useDelay: 1
+ priority: 3
- type: entity
id: ActionDevour
@@ -194,3 +224,18 @@
icon: { sprite : Interface/Actions/devour.rsi, state: icon }
iconOn: { sprite : Interface/Actions/devour.rsi, state: icon-on }
event: !type:DevourActionEvent
+ priority: 1
+
+- type: entity
+ noSpawn: true
+ id: ActionDragonsBreath
+ name: "[color=orange]Dragon's Breath[/color]"
+ description: Spew out flames at anyone foolish enough to attack you!
+ components:
+ - type: WorldTargetAction
+ # TODO: actual sprite
+ icon: { sprite : Objects/Weapons/Guns/Projectiles/magic.rsi, state: fireball }
+ event: !type:ActionGunShootEvent
+ priority: 2
+ checkCanAccess: false
+ range: 0
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml
index 3556d1c8f8b..d6adcd614e3 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml
@@ -30,6 +30,39 @@
- type: IgniteOnCollide
fireStacks: 0.35
+- type: entity
+ noSpawn: true
+ parent: BaseBulletTrigger
+ id: ProjectileDragonsBreath
+ name: dragon's breath
+ description: Try not to get toasted.
+ components:
+ - type: PointLight
+ color: "#E25822"
+ radius: 3.0
+ energy: 5.0
+ - type: Sprite
+ sprite: Objects/Weapons/Guns/Projectiles/magic.rsi
+ layers:
+ - state: fireball
+ shader: unshaded
+ - type: IgnitionSource
+ temperature: 1000
+ ignited: true
+ - type: RepeatingTrigger
+ delay: 0.5 # line of fire as well as if it hits something
+ - type: ExplodeOnTrigger
+ - type: Explosive
+ explosionType: FireBomb
+ totalIntensity: 5 # low intensity, the point is to burn attackers not to break open walls, dragons can just eat them
+ intensitySlope: 1
+ maxIntensity: 3
+ canCreateVacuum: false
+ deleteAfterExplosion: false
+ repeatable: true
+ - type: TimedDespawn
+ lifetime: 5
+
- type: entity
id: ProjectileAnomalyFireball
name: fireball
From fd11738a1d07931f30690bcfdefdfc6b2253a084 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Wed, 8 May 2024 00:26:47 +0000
Subject: [PATCH 027/215] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 96c8b20e766..96ce6aed314 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Cojoke-dot
- changes:
- - message: E-sword now lights plasma fires
- type: Tweak
- id: 6051
- time: '2024-02-28T21:59:35.0000000+00:00'
- url: https://github.com/space-wizards/space-station-14/pull/25665
- author: lzk228
changes:
- message: Engineering structures orders in cargo now supplied via flatpacks (e.g.
@@ -3855,3 +3848,10 @@
id: 6550
time: '2024-05-08T00:19:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/27373
+- author: deltanedas
+ changes:
+ - message: Dragons can now breathe fire.
+ type: Add
+ id: 6551
+ time: '2024-05-08T00:25:41.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/26746
From fa2223ed8deda5b4b3ec6cfc8806cbd4013c997b Mon Sep 17 00:00:00 2001
From: Pieter-Jan Briers
Date: Wed, 8 May 2024 04:24:54 +0200
Subject: [PATCH 028/215] Fix preferences sent to client not being sanitized
(#27789)
Fucking whoops
In #27742 I made it so sanitization of character profiles was moved to be *after* database load. Except that means I moved it to be after the copy of all character profiles got sent to the client.
Move the sending to *also* be in that second load stage, and rename it. Fixes the issue.
---
Content.Server/Database/UserDbDataManager.cs | 2 +-
.../Managers/IServerPreferencesManager.cs | 2 +-
.../Managers/ServerPreferencesManager.cs | 27 ++++++++++---------
3 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/Content.Server/Database/UserDbDataManager.cs b/Content.Server/Database/UserDbDataManager.cs
index 3f6659840ad..c58c594dbad 100644
--- a/Content.Server/Database/UserDbDataManager.cs
+++ b/Content.Server/Database/UserDbDataManager.cs
@@ -67,7 +67,7 @@ await Task.WhenAll(
_playTimeTracking.LoadData(session, cancel));
cancel.ThrowIfCancellationRequested();
- _prefs.SanitizeData(session);
+ _prefs.FinishLoad(session);
_sawmill.Verbose($"Load complete for user {session}");
}
diff --git a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs
index 92e7adf22ad..63c267f154a 100644
--- a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs
+++ b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs
@@ -12,7 +12,7 @@ public interface IServerPreferencesManager
void Init();
Task LoadData(ICommonSession session, CancellationToken cancel);
- void SanitizeData(ICommonSession session);
+ void FinishLoad(ICommonSession session);
void OnClientDisconnected(ICommonSession session);
bool TryGetCachedPreferences(NetUserId userId, [NotNullWhen(true)] out PlayerPreferences? playerPreferences);
diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs
index 55532f1ff5b..7a80757435e 100644
--- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs
+++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs
@@ -199,27 +199,28 @@ async Task LoadPrefs()
{
var prefs = await GetOrCreatePreferencesAsync(session.UserId, cancel);
prefsData.Prefs = prefs;
- prefsData.PrefsLoaded = true;
-
- var msg = new MsgPreferencesAndSettings();
- msg.Preferences = prefs;
- msg.Settings = new GameSettings
- {
- MaxCharacterSlots = MaxCharacterSlots
- };
- _netManager.ServerSendMessage(msg, session.Channel);
}
}
}
- public void SanitizeData(ICommonSession session)
+ public void FinishLoad(ICommonSession session)
{
// This is a separate step from the actual database load.
// Sanitizing preferences requires play time info due to loadouts.
// And play time info is loaded concurrently from the DB with preferences.
- var data = _cachedPlayerPrefs[session.UserId];
- DebugTools.Assert(data.Prefs != null);
- data.Prefs = SanitizePreferences(session, data.Prefs, _dependencies);
+ var prefsData = _cachedPlayerPrefs[session.UserId];
+ DebugTools.Assert(prefsData.Prefs != null);
+ prefsData.Prefs = SanitizePreferences(session, prefsData.Prefs, _dependencies);
+
+ prefsData.PrefsLoaded = true;
+
+ var msg = new MsgPreferencesAndSettings();
+ msg.Preferences = prefsData.Prefs;
+ msg.Settings = new GameSettings
+ {
+ MaxCharacterSlots = MaxCharacterSlots
+ };
+ _netManager.ServerSendMessage(msg, session.Channel);
}
public void OnClientDisconnected(ICommonSession session)
From 42e5ecf35b5c7ef57596bb4a1d1053666b69b819 Mon Sep 17 00:00:00 2001
From: Flareguy <78941145+Flareguy@users.noreply.github.com>
Date: Tue, 7 May 2024 22:48:42 -0500
Subject: [PATCH 029/215] Revert "Make the floppy lizard ears have two colors."
(#27790)
Revert "Make the floppy lizard ears have two colors. (#27679)"
This reverts commit bd06aa2365d6ce093ac47462deb69858c6cc18c0.
---
Resources/Locale/en-US/markings/reptilian.ftl | 3 +--
.../Mobs/Customization/Markings/reptilian.yml | 4 +---
.../Prototypes/Entities/Mobs/NPCs/animals.yml | 1 +
...imary.png => horns_floppy_kobold_ears.png} | Bin 1696 -> 1717 bytes
.../horns_floppy_kobold_ears_secondary.png | Bin 197 -> 0 bytes
.../reptilian_parts.rsi/meta.json | 6 +-----
6 files changed, 4 insertions(+), 10 deletions(-)
rename Resources/Textures/Mobs/Customization/reptilian_parts.rsi/{horns_floppy_kobold_ears_primary.png => horns_floppy_kobold_ears.png} (74%)
delete mode 100644 Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png
diff --git a/Resources/Locale/en-US/markings/reptilian.ftl b/Resources/Locale/en-US/markings/reptilian.ftl
index c2a2df4b3ba..470af07361d 100644
--- a/Resources/Locale/en-US/markings/reptilian.ftl
+++ b/Resources/Locale/en-US/markings/reptilian.ftl
@@ -96,8 +96,7 @@ marking-LizardHornsBighorn = Lizard Horns (Bighorn)
marking-LizardHornsKoboldEars-horns_kobold_ears = Lizard Ears (Kobold)
marking-LizardHornsKoboldEars = Lizard Ears (Kobold)
-marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears_primary = Lizard Ears (Floppy Kobold)
-marking-LizardHornsFloppyKoboldEars-horns-floppy_kobold_ears_secondary = Lizard Ears (Floppy Kobold)
+marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears = Lizard Ears (Floppy Kobold)
marking-LizardHornsFloppyKoboldEars = Lizard Ears (Floppy Kobold)
marking-LizardChestUnderbelly-body_underbelly = Lizard Chest (Underbelly)
diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml
index 95cfb72e875..5a52e09bf2d 100644
--- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml
+++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml
@@ -310,9 +310,7 @@
speciesRestriction: [Reptilian]
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
- state: horns_floppy_kobold_ears_primary
- - sprite: Mobs/Customization/reptilian_parts.rsi
- state: horns_floppy_kobold_ears_secondary
+ state: horns_floppy_kobold_ears
- type: marking
id: LizardChestUnderbelly
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
index 6bc0d7a598f..7fb431fabb5 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
@@ -1434,6 +1434,7 @@
horns_bighorn: KoboldHornColors
horns_argali: KoboldHornColors
horns_ayrshire: KoboldHornColors
+ horns_floppy_kobold_ears: Inherit
horns_double: Inherit
horns_kobold_ears: Inherit
- type: Butcherable
diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png
similarity index 74%
rename from Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png
rename to Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png
index 89d7eaef817d3abd4702b58e71d92c1ffdda29b4..061c0100cc5cc0d2216f0e25819a546421c7d300 100644
GIT binary patch
delta 343
zcmV-d0jU0<4Yduh-2pxiP)t-sdU|@dx3{FEq?DAD0000ux)%Ka000GaQchF<|Ns90
z`?d~K00009a7bBm001bN001bN0lI?#-?JA2kpqA9Nkl
zFrv3a!%{BlYApt#?Mr)@E(BbJ;sIKlvI&s=(hFjD5M)i8U|9%IYhHo3Mh`sz<~!uK
zXaIkpg~bG@=`sM=fodOgwGPheHNaB<0w4-N07L=U0ZuM2^5dP07QYW#vUvqaeyY9E
z60IlTksvd70JS&r0qp{KW@?|>07s}E+P*IU!24&a8{%w7!f@QrZ~g{6*+#X%8@yW=
p;pponPXP#kC;$Nv{Tfi~2lKN%Lkjt^{s0RA002ovPDHLkV1hgVk!An@
delta 321
zcmV-H0lxmV4WJFM-2plbP)t-sdU|@dx3{FEqyPW_*0rV`00004bW%=J|Ns90Kq{&9
z00009a7bBm001bK001bK0nAOV#j_g%kpq9@Nkl{xl=
z5rPmfAqW8z0xNL#vcg~Ql*syhK<#EN;QiUd8`NrD1&;>qxfAFOw?Qv=C6Ei?*%sSn
z1j|xgF#i`Ipm|*3F0|XxFe0j#lh1%UrL`w`gR^l4TaSl4LJ$Hb1R-F4EvWSapJ^^9
Tc?DQO00000NkvXXu0mjfcEE>}
diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png
deleted file mode 100644
index b40d099eabd5c9969e85ab0a30ac36185fdccf56..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 197
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl
z_H+M9WCij$3p^r=85sEXgD|57Yp@DXFv`=#F{C2y?IlCL1_KV(fG=}w?cu7{dLP*Y(}<
Date: Tue, 7 May 2024 23:23:26 -0700
Subject: [PATCH 030/215] Fix the changelog window being very laggy until a tab
is clicked (#27795)
---
Content.Client/Changelog/ChangelogWindow.xaml.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/Content.Client/Changelog/ChangelogWindow.xaml.cs b/Content.Client/Changelog/ChangelogWindow.xaml.cs
index e5f492900c2..9b7fd754369 100644
--- a/Content.Client/Changelog/ChangelogWindow.xaml.cs
+++ b/Content.Client/Changelog/ChangelogWindow.xaml.cs
@@ -87,14 +87,12 @@ private void TabsUpdated()
if (!tab.AdminOnly || isAdmin)
{
Tabs.SetTabVisible(i, true);
- tab.Visible = true;
visibleTabs++;
firstVisible ??= i;
}
else
{
Tabs.SetTabVisible(i, false);
- tab.Visible = false;
}
}
From d442be160d8a09579f265cb85382f058719ecda6 Mon Sep 17 00:00:00 2001
From: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Date: Wed, 8 May 2024 01:46:03 -0500
Subject: [PATCH 031/215] Shoot Over Racks (#27797)
Racks now have table collisions
---
Resources/Prototypes/Entities/Structures/Storage/storage.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Resources/Prototypes/Entities/Structures/Storage/storage.yml b/Resources/Prototypes/Entities/Structures/Storage/storage.yml
index 79a1e357998..d0b468ca53d 100644
--- a/Resources/Prototypes/Entities/Structures/Storage/storage.yml
+++ b/Resources/Prototypes/Entities/Structures/Storage/storage.yml
@@ -27,9 +27,9 @@
bounds: "-0.3,-0.3,0.3,0.3"
density: 140
mask:
- - MachineMask
+ - TableMask
layer:
- - MachineLayer
+ - TableLayer
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Metallic
From d6406eafef90852c90116d0ebc5f88154bf6e4ec Mon Sep 17 00:00:00 2001
From: Verm <32827189+Vermidia@users.noreply.github.com>
Date: Wed, 8 May 2024 01:46:48 -0500
Subject: [PATCH 032/215] Fix cak and breaddog not being able to escape
inventories (#27794)
Fix cak and breaddog
---
.../Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml | 1 +
.../Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml | 1 +
2 files changed, 2 insertions(+)
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml
index 71b3066a265..e40ac40a289 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml
@@ -829,6 +829,7 @@
- type: Puller
needsHands: false
- type: Examiner
+ - type: DoAfter
- type: CombatMode
- type: MeleeWeapon
soundHit:
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml
index cbb9ff2c45b..c939dec52c6 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml
@@ -691,6 +691,7 @@
- type: Puller
needsHands: false
- type: Examiner
+ - type: DoAfter
- type: CombatMode
- type: MeleeWeapon
soundHit:
From 0e8c8110d1af646e38d7e94bfe6d127bddd18b86 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Wed, 8 May 2024 06:47:10 +0000
Subject: [PATCH 033/215] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 96ce6aed314..bc1f2b6dd65 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,14 +1,4 @@
Entries:
-- author: lzk228
- changes:
- - message: Engineering structures orders in cargo now supplied via flatpacks (e.g.
- tesla & singulo generators, other stuff for them).
- type: Tweak
- - message: Thrusters and gyroscopes now supplied in crates via flatpacks.
- type: Tweak
- id: 6052
- time: '2024-02-28T22:02:02.0000000+00:00'
- url: https://github.com/space-wizards/space-station-14/pull/25647
- author: c4llv07e
changes:
- message: Cryo won't remove you from the new body if you chose a new ghost role
@@ -3855,3 +3845,10 @@
id: 6551
time: '2024-05-08T00:25:41.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26746
+- author: Cojoke-dot
+ changes:
+ - message: You can now shoot over racks
+ type: Tweak
+ id: 6552
+ time: '2024-05-08T06:46:04.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/27797
From bf559f6e275bde59c5f5d7cb14dc452b8cd19497 Mon Sep 17 00:00:00 2001
From: ShadowCommander
Date: Tue, 7 May 2024 23:49:28 -0700
Subject: [PATCH 034/215] Fix pull not stopping when character is downed
(#27796)
---
.../Movement/Pulling/Systems/PullingSystem.cs | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
index 3c265d5a027..81b2fee5695 100644
--- a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
+++ b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
@@ -13,6 +13,7 @@
using Content.Shared.Movement.Pulling.Events;
using Content.Shared.Movement.Systems;
using Content.Shared.Pulling.Events;
+using Content.Shared.Standing;
using Content.Shared.Throwing;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
@@ -62,6 +63,7 @@ public override void Initialize()
SubscribeLocalEvent(OnPullerUnpaused);
SubscribeLocalEvent(OnVirtualItemDeleted);
SubscribeLocalEvent(OnRefreshMovespeed);
+ SubscribeLocalEvent(OnDropHandItems);
CommandBinds.Builder
.Bind(ContentKeyFunctions.MovePulledObject, new PointerInputCmdHandler(OnRequestMovePulledObject))
@@ -69,6 +71,17 @@ public override void Initialize()
.Register();
}
+ private void OnDropHandItems(EntityUid uid, PullerComponent pullerComp, DropHandItemsEvent args)
+ {
+ if (pullerComp.Pulling == null || pullerComp.NeedsHands)
+ return;
+
+ if (!TryComp(pullerComp.Pulling, out PullableComponent? pullableComp))
+ return;
+
+ TryStopPull(pullerComp.Pulling.Value, pullableComp, uid);
+ }
+
private void OnPullerContainerInsert(Entity ent, ref EntGotInsertedIntoContainerMessage args)
{
if (ent.Comp.Pulling == null) return;
From 49e26b17829f195928d513d7b8addc7dd9e314ef Mon Sep 17 00:00:00 2001
From: PJBot
Date: Wed, 8 May 2024 06:50:34 +0000
Subject: [PATCH 035/215] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index bc1f2b6dd65..e078db59e76 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,12 +1,4 @@
Entries:
-- author: c4llv07e
- changes:
- - message: Cryo won't remove you from the new body if you chose a new ghost role
- before cryo deleted your old body.
- type: Fix
- id: 6053
- time: '2024-02-28T22:09:02.0000000+00:00'
- url: https://github.com/space-wizards/space-station-14/pull/24991
- author: Nairodian
changes:
- message: You can now remove the rust from reinforced walls with a welder.
@@ -3852,3 +3844,10 @@
id: 6552
time: '2024-05-08T06:46:04.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/27797
+- author: ShadowCommander
+ changes:
+ - message: Lizards now stop tail pulling when they are downed.
+ type: Fix
+ id: 6553
+ time: '2024-05-08T06:49:28.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/27796
From 540aeb289f69d35b35b64d644170fd2cef528b20 Mon Sep 17 00:00:00 2001
From: Kukutis96513 <146854220+Kukutis96513@users.noreply.github.com>
Date: Wed, 8 May 2024 09:57:21 +0300
Subject: [PATCH 036/215] Secoff senior uniform fix (#27775)
* weh.
* get the weh out of my repository
* add best lizard figurine
* remove umbra stuff from master
* remove the additional pixels from the senior secoff jumpskirt sprite
* fix the fix
---
.../equipped-INNERCLOTHING.png | Bin 1316 -> 1245 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/Resources/Textures/Clothing/Uniforms/Jumpskirt/senior_officer.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/Clothing/Uniforms/Jumpskirt/senior_officer.rsi/equipped-INNERCLOTHING.png
index b3ecbd97129997ad4c081960cc16e9231023ace4..7dce3cbc9b1d6851e24e3f95c75047d1e19824f9 100644
GIT binary patch
delta 1205
zcmV;m1WNm)3f&2iBpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks%m=a!Eu%RCr$P
zn$JsAQ546Izsk`8Ar%o7GzEolA`){U;i80yf*`P+yB0w~iyb4V
zk%XWLk&OfiPD&VqxEdLMl*%;U+nnk8oMzs6zV{5e9~kbB_vU`jIrqLd=s9FC7z_r3
z!C(*&4u?~juEIL@n%>@j-jwx|xg@42)7oOFxlIXu>}aFT&Q6L%B1Le1VPS#JeOXfX
zjI1n))|3GK*79|kAsd{ysfxZlq)~Nx@){Zmz6SLrICc
z_HJ|2lOS02;q2E7=jrtO56XF``o)bsC*Sa|VR=(Z4qguAR5P6>!jy{}=_w~~H>nSxKDlJv5
z{u1Ko16=1LdzANofv(T%V{JYWI($#r~t
zx|$Lj8&q6eO!M>es>K-dxb7uZ{k65VBkPL-0GgVbsJ6D2y1Kd!w3zn;xAkoYpuN34
z1);jSIyFZ0dwP0kc6L^^%gf8u-QBJ3Q#ZH_*2VhJ(RE=5fL*XpsxLYLEiEkv9AHp5Agr&iD-lE+(MLNs
zH>c+K+Vu3a>%Ro}lb6>=%Z~%wp=bUjAgn~#I@5J#n$YINEc#9m1z=`ohTdGcmMuQu3@pTBu~>HOCCb^f
z7CWqKI@t(O08k*o!szEpi~9+*VFTmj6o>-A4zts2K(2}nud&u8uw8mU>>zq$BPnsB
ztSmG7Lm&{y)(eb}k9+znFfcHX;+ll*^vBA7&)r>7f<*i)P@R4QLqu=&dI7J|YZ7wV
zB1Ig4a7e)Cd?127|#aM85#$L_`}9
Tg<@cy00000NkvXXu0mjfQIt&a
delta 1278
zcmVYXc~GI%D|?*eQN^fNd(NGg>IB$G*ZdwZJ?Uc3ZgHv3X(PF4NBa2U&RkT^tF&a3Lz
zJa{J7@7`@~1z@jK;+I%AhlhtmA`w2x?$Tu#0IU`YO-VwfzU4T)8of>L;|==4;kxyM
zD&nh!0svixakA*Hf38!DzuVgCRZ63%)ED;m_sgEwqkmxn=H}+y2alH6E0stWi|mz3
zz)2E1Iy$_?%j-ZxlOSaec>0#(&=(HV*4E~gzF+^rqb26%=4#TvFag=w6ab|!KL_yc
zze?nM>n}b7{*C)0&b?Rsn@(4lkO2IPm2r}kh23l*T`aO%D4ZIn
zieG4$0wqVl<1g-uRAe(+tPv))%PRp)gac)Rn$MOSyt1&2UO|{m(j23V^9c%LfmR^XaC@U
zU@*wm))v8Fko|)LZnd`)3SC%Gm!eYNw(U#nD6(gG#MTqE<5)0^eBthL!QGd4CxCX-=gWQ0T_f6-!Ro3b3cwm
zyspfRufMwTMEDo}*SFt!vHW&;sGJ0)!BgEae^(lx(vp(LOYgr&@8gZ8Iz-^4Vft$H
zHus)Br^_%{EfhS1g!BVdlAzoeiOnP#_~Uo4AGcR3(PbFid-|M%srwB#NBEhE^}7dC
z_r1l7CqVoG;vi8$DFGinoMCculEuYEaueeWg+iWqWtX;@_?x2Atv<`Qa1lz)w6(Q0
ze~j;cAnQ0VG46GWEyuwEEX%@ZP*=Db>0*(RWtEvF{9Ryiuc)9@0r}+>FVp$ul`^lu
z=0HEjvln&k#I>@pn++JxUa&dP50v{7;B5EGc_>vtr8%O~D{z%m`V#yOk_Cl%loIgk
z4TE;M1&07*qoM6N<$f=N4s-v9sr
From cf43305d9ee4262c7d6e14f9c83e12446cdc9e60 Mon Sep 17 00:00:00 2001
From: Plykiya <58439124+Plykiya@users.noreply.github.com>
Date: Wed, 8 May 2024 00:30:03 -0700
Subject: [PATCH 037/215] Reimplement supplybots as non-vehicles (#27769)
* Reimplement supplybots as non-vehicles
* what the hell is a container container?
* Dumpable
* let them hear supply comms
* unmigrate
* no more QM access
* Skill issue
---------
Co-authored-by: plykiya
---
Resources/Migrations/migration.yml | 2 +-
.../Prototypes/Entities/Mobs/NPCs/silicon.yml | 54 +++++++++++++++++++
.../Crafting/Graphs/bots/supplybot.yml | 23 ++++++++
3 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml
diff --git a/Resources/Migrations/migration.yml b/Resources/Migrations/migration.yml
index 99b24d98c22..974fca5effb 100644
--- a/Resources/Migrations/migration.yml
+++ b/Resources/Migrations/migration.yml
@@ -188,7 +188,7 @@ ActionVehicleHorn: null
CrateFunATV: null
CrateFunSyndicateSegway: null
MobTaxiBot: null
-MobSupplyBot: null
+# MobSupplyBot: null
SpawnVehicleMotobike: null
SpawnVehicleATV: null
SpawnVehicleSecway: null
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
index 2423082fd8d..b405a67d069 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
@@ -327,3 +327,57 @@
interactFailureString: petting-failure-mimebot
- type: Inventory
templateId: head
+
+- type: entity
+ parent: MobSiliconBase
+ id: MobSupplyBot
+ name: supplybot
+ description: Delivers cargo!
+ components:
+ - type: Sprite
+ sprite: Mobs/Silicon/Bots/supplybot.rsi
+ layers:
+ - state: supplybot
+ - type: GhostRole
+ name: ghost-role-information-supplybot-name
+ description: ghost-role-information-supplybot-description
+ - type: Construction
+ graph: SupplyBot
+ node: bot
+ - type: Access
+ tags:
+ - Cargo
+ - Maintenance
+ - Salvage
+ - type: Dumpable
+ - type: Storage
+ maxItemSize: Huge
+ grid:
+ - 0,0,9,3
+ - type: UserInterface
+ interfaces:
+ enum.StorageUiKey.Key:
+ type: StorageBoundUserInterface
+ - type: ContainerContainer
+ containers:
+ storagebase: !type:Container
+ ents: []
+ - type: UnpoweredFlashlight
+ - type: PointLight
+ enabled: false
+ radius: 3.5
+ softness: 2
+ mask: /Textures/Effects/LightMasks/cone.png
+ autoRot: true
+ - type: FootstepModifier
+ footstepSoundCollection:
+ collection: FootstepBorg
+ - type: Tag
+ tags:
+ - DoorBumpOpener
+ - FootstepSound
+ - type: ActiveRadio
+ channels:
+ - Binary
+ - Common
+ - Supply
diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml
new file mode 100644
index 00000000000..efabb849bbc
--- /dev/null
+++ b/Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml
@@ -0,0 +1,23 @@
+- type: constructionGraph
+ id: SupplyBot
+ start: start
+ graph:
+ - node: start
+ edges:
+ - to: bot
+ steps:
+ - tag: ProximitySensor
+ icon:
+ sprite: Objects/Misc/proximity_sensor.rsi
+ state: icon
+ name: proximity sensor
+ - tag: BorgHead
+ icon:
+ sprite: Objects/Specific/Robotics/cyborg_parts.rsi
+ state: borg_head
+ name: borg head
+ doAfter: 1
+ - material: Steel
+ amount: 10
+ - node: bot
+ entity: MobSupplyBot
From 5007684cecb361bb8db483c887599f4d3f853528 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Wed, 8 May 2024 07:31:59 +0000
Subject: [PATCH 038/215] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index e078db59e76..87acc64faf7 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,18 +1,4 @@
Entries:
-- author: Nairodian
- changes:
- - message: You can now remove the rust from reinforced walls with a welder.
- type: Fix
- id: 6054
- time: '2024-02-29T00:44:01.0000000+00:00'
- url: https://github.com/space-wizards/space-station-14/pull/25690
-- author: Ubaser
- changes:
- - message: Eris UI theme has been removed.
- type: Remove
- id: 6055
- time: '2024-02-29T05:53:48.0000000+00:00'
- url: https://github.com/space-wizards/space-station-14/pull/25673
- author: Rainfey
changes:
- message: Disallow multiple antag roles per player
@@ -3851,3 +3837,17 @@
id: 6553
time: '2024-05-08T06:49:28.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/27796
+- author: Plykiya
+ changes:
+ - message: Re-added supplybots.
+ type: Add
+ id: 6554
+ time: '2024-05-08T07:30:04.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/27769
+- author: Hobbitmax
+ changes:
+ - message: Replaced Syndicate Jaws Of Life with a Pyjama bundle on the Train map.
+ type: Tweak
+ id: 6555
+ time: '2024-05-08T07:30:53.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/27734
From 094ea59b956c6649615efcb4c571108284af223b Mon Sep 17 00:00:00 2001
From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com>
Date: Wed, 8 May 2024 19:18:03 +1000
Subject: [PATCH 039/215] Added new HTN operations and preconditions (#27486)
* Added new HTN operations & preconditions
* Ok I forgot about partial
* Namespace pierce the skies
* Some fixes, debug and new operators
* Bruh git eat my files
---
.../HTN/Preconditions/GunAmmoPrecondition.cs | 2 +-
.../Preconditions/KeyNotExistsPrecondition.cs | 12 +++
.../Math/KeyBoolEqualsPrecondition.cs | 23 +++++
.../Math/KeyFloatEqualsPrecondition.cs | 18 ++++
.../Math/KeyFloatGreaterPrecondition.cs | 17 ++++
.../Math/KeyFloatLessPrecondition.cs | 17 ++++
.../Operators/Math/AddFloatOperator.cs | 33 +++++++
.../Operators/Math/SetBoolOperator.cs | 28 ++++++
.../Operators/{ => Math}/SetFloatOperator.cs | 18 ++--
.../Operators/Math/SetRandomFloatOperator.cs | 34 +++++++
.../Operators/PlaySoundOperator.cs | 28 ++++++
.../Operators/SayKeyOperator.cs | 36 ++++++++
.../Entities/Mobs/Debugging/debug_counter.yml | 53 +++++++++++
Resources/Prototypes/NPCs/debug.yml | 90 +++++++++++++++++++
14 files changed, 401 insertions(+), 8 deletions(-)
create mode 100644 Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs
create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs
create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs
create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs
create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs
create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs
create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs
rename Content.Server/NPC/HTN/PrimitiveTasks/Operators/{ => Math}/SetFloatOperator.cs (52%)
create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs
create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs
create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs
create mode 100644 Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml
create mode 100644 Resources/Prototypes/NPCs/debug.yml
diff --git a/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs
index fe3b844ae34..58647d88749 100644
--- a/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs
+++ b/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs
@@ -35,7 +35,7 @@ public override bool IsMet(NPCBlackboard blackboard)
else
percent = ammoEv.Count / (float) ammoEv.Capacity;
- percent = Math.Clamp(percent, 0f, 1f);
+ percent = System.Math.Clamp(percent, 0f, 1f);
if (MaxPercent < percent)
return false;
diff --git a/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs
new file mode 100644
index 00000000000..c12663901c7
--- /dev/null
+++ b/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs
@@ -0,0 +1,12 @@
+namespace Content.Server.NPC.HTN.Preconditions;
+
+public sealed partial class KeyNotExistsPrecondition : HTNPrecondition
+{
+ [DataField(required: true)]
+ public string Key = string.Empty;
+
+ public override bool IsMet(NPCBlackboard blackboard)
+ {
+ return !blackboard.ContainsKey(Key);
+ }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs
new file mode 100644
index 00000000000..8c7920e8be5
--- /dev/null
+++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs
@@ -0,0 +1,23 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+///
+/// Checks for the presence of data in the blackboard and makes a comparison with the specified boolean
+///
+public sealed partial class KeyBoolEqualsPrecondition : HTNPrecondition
+{
+ [Dependency] private readonly IEntityManager _entManager = default!;
+
+ [DataField(required: true)]
+ public string Key = string.Empty;
+
+ [DataField(required: true)]
+ public bool Value;
+
+ public override bool IsMet(NPCBlackboard blackboard)
+ {
+ if (!blackboard.TryGetValue(Key, out var value, _entManager))
+ return false;
+
+ return Value == value;
+ }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs
new file mode 100644
index 00000000000..802fdaf2b9c
--- /dev/null
+++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs
@@ -0,0 +1,18 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+public sealed partial class KeyFloatEqualsPrecondition : HTNPrecondition
+{
+ [Dependency] private readonly IEntityManager _entManager = default!;
+
+ [DataField(required: true)]
+ public string Key = string.Empty;
+
+ [DataField(required: true)]
+ public float Value;
+
+ public override bool IsMet(NPCBlackboard blackboard)
+ {
+ return blackboard.TryGetValue(Key, out var value, _entManager) &&
+ MathHelper.CloseTo(value, value);
+ }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs
new file mode 100644
index 00000000000..3a9ac366980
--- /dev/null
+++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs
@@ -0,0 +1,17 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+public sealed partial class KeyFloatGreaterPrecondition : HTNPrecondition
+{
+ [Dependency] private readonly IEntityManager _entManager = default!;
+
+ [DataField(required: true)]
+ public string Key = string.Empty;
+
+ [DataField(required: true)]
+ public float Value;
+
+ public override bool IsMet(NPCBlackboard blackboard)
+ {
+ return blackboard.TryGetValue(Key, out var value, _entManager) && value > Value;
+ }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs
new file mode 100644
index 00000000000..5cd51d7a7c5
--- /dev/null
+++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs
@@ -0,0 +1,17 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+public sealed partial class KeyFloatLessPrecondition : HTNPrecondition
+{
+ [Dependency] private readonly IEntityManager _entManager = default!;
+
+ [DataField(required: true)]
+ public string Key = string.Empty;
+
+ [DataField(required: true)]
+ public float Value;
+
+ public override bool IsMet(NPCBlackboard blackboard)
+ {
+ return blackboard.TryGetValue(Key, out var value, _entManager) && value < Value;
+ }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs
new file mode 100644
index 00000000000..00404517c9e
--- /dev/null
+++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs
@@ -0,0 +1,33 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
+
+///
+/// Gets the key, and adds the value to that float
+///
+public sealed partial class AddFloatOperator : HTNOperator
+{
+ [Dependency] private readonly IEntityManager _entManager = default!;
+
+ [DataField(required: true)]
+ public string TargetKey = string.Empty;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public float Amount;
+
+ public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard,
+ CancellationToken cancelToken)
+ {
+ if (!blackboard.TryGetValue(TargetKey, out var value, _entManager))
+ return (false, null);
+
+ return (
+ true,
+ new Dictionary
+ {
+ { TargetKey, value + Amount }
+ }
+ );
+ }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs
new file mode 100644
index 00000000000..a40b96798d4
--- /dev/null
+++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs
@@ -0,0 +1,28 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
+
+///
+/// Just sets a blackboard key to a bool
+///
+public sealed partial class SetBoolOperator : HTNOperator
+{
+ [DataField(required: true)]
+ public string TargetKey = string.Empty;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool Value;
+
+ public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard,
+ CancellationToken cancelToken)
+ {
+ return (
+ true,
+ new Dictionary
+ {
+ { TargetKey, Value }
+ }
+ );
+ }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs
similarity index 52%
rename from Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs
rename to Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs
index 7a460592cb4..76842b431f7 100644
--- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs
+++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs
@@ -1,24 +1,28 @@
using System.Threading;
using System.Threading.Tasks;
-namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
///
/// Just sets a blackboard key to a float
///
public sealed partial class SetFloatOperator : HTNOperator
{
- [DataField("targetKey", required: true)] public string TargetKey = string.Empty;
+ [DataField(required: true)]
+ public string TargetKey = string.Empty;
- [ViewVariables(VVAccess.ReadWrite), DataField("amount")]
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
public float Amount;
public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard,
CancellationToken cancelToken)
{
- return (true, new Dictionary()
- {
- {TargetKey, Amount},
- });
+ return (
+ true,
+ new Dictionary
+ {
+ { TargetKey, Amount }
+ }
+ );
}
}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs
new file mode 100644
index 00000000000..999756f1f74
--- /dev/null
+++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs
@@ -0,0 +1,34 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Robust.Shared.Random;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
+
+///
+/// Sets a random float from MinAmount to MaxAmount to blackboard
+///
+public sealed partial class SetRandomFloatOperator : HTNOperator
+{
+ [Dependency] private readonly IRobustRandom _random = default!;
+
+ [DataField(required: true)]
+ public string TargetKey = string.Empty;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public float MaxAmount = 1f;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public float MinAmount = 0f;
+
+ public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard,
+ CancellationToken cancelToken)
+ {
+ return (
+ true,
+ new Dictionary
+ {
+ { TargetKey, _random.NextFloat(MinAmount, MaxAmount) }
+ }
+ );
+ }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs
new file mode 100644
index 00000000000..57cc2e91e44
--- /dev/null
+++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs
@@ -0,0 +1,28 @@
+using Robust.Server.Audio;
+using Robust.Shared.Audio;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
+
+public sealed partial class PlaySoundOperator : HTNOperator
+{
+ private AudioSystem _audio = default!;
+
+ [DataField(required: true)]
+ public SoundSpecifier? Sound;
+
+ public override void Initialize(IEntitySystemManager sysManager)
+ {
+ base.Initialize(sysManager);
+
+ _audio = IoCManager.Resolve().GetEntitySystem();
+ }
+
+ public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
+ {
+ var uid = blackboard.GetValue(NPCBlackboard.Owner);
+
+ _audio.PlayPvs(Sound, uid);
+
+ return base.Update(blackboard, frameTime);
+ }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs
new file mode 100644
index 00000000000..d1c7d619150
--- /dev/null
+++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs
@@ -0,0 +1,36 @@
+using Content.Server.Chat.Systems;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
+
+public sealed partial class SayKeyOperator : HTNOperator
+{
+ [Dependency] private readonly IEntityManager _entManager = default!;
+
+ private ChatSystem _chat = default!;
+
+ [DataField(required: true)]
+ public string Key = string.Empty;
+
+ ///
+ /// Whether to hide message from chat window and logs.
+ ///
+ [DataField]
+ public bool Hidden;
+
+ public override void Initialize(IEntitySystemManager sysManager)
+ {
+ base.Initialize(sysManager);
+ _chat = IoCManager.Resolve().GetEntitySystem();
+ }
+
+ public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
+ {
+ if (!blackboard.TryGetValue