diff --git a/Content.Server/Climbing/ClimbSystem.cs b/Content.Server/Climbing/ClimbSystem.cs index 38f7ad8b30..f06bcf8210 100644 --- a/Content.Server/Climbing/ClimbSystem.cs +++ b/Content.Server/Climbing/ClimbSystem.cs @@ -10,6 +10,7 @@ using Content.Shared.Body.Part; using Content.Shared.Buckle.Components; using Content.Shared.CCVar; using Content.Shared.Climbing; +using Content.Shared.Climbing.Events; using Content.Shared.Damage; using Content.Shared.DragDrop; using Content.Shared.GameTicking; @@ -280,6 +281,8 @@ public sealed class ClimbSystem : SharedClimbSystem climbing.IsClimbing = false; climbing.OwnerIsTransitioning = false; + var ev = new EndClimbEvent(); + RaiseLocalEvent(uid, ref ev); Dirty(climbing); } diff --git a/Content.Server/Damage/Systems/DamageOnLandSystem.cs b/Content.Server/Damage/Systems/DamageOnLandSystem.cs index 293f9b5069..f44bfeacce 100644 --- a/Content.Server/Damage/Systems/DamageOnLandSystem.cs +++ b/Content.Server/Damage/Systems/DamageOnLandSystem.cs @@ -14,7 +14,7 @@ namespace Content.Server.Damage.Systems SubscribeLocalEvent(DamageOnLand); } - private void DamageOnLand(EntityUid uid, DamageOnLandComponent component, LandEvent args) + private void DamageOnLand(EntityUid uid, DamageOnLandComponent component, ref LandEvent args) { _damageableSystem.TryChangeDamage(uid, component.Damage, component.IgnoreResistances); } diff --git a/Content.Server/Dice/DiceSystem.cs b/Content.Server/Dice/DiceSystem.cs index d21ea00670..88bffcf95f 100644 --- a/Content.Server/Dice/DiceSystem.cs +++ b/Content.Server/Dice/DiceSystem.cs @@ -40,7 +40,7 @@ namespace Content.Server.Dice Roll(uid, component); } - private void OnLand(EntityUid uid, DiceComponent component, LandEvent args) + private void OnLand(EntityUid uid, DiceComponent component, ref LandEvent args) { Roll(uid, component); } diff --git a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs index 00a4af77a9..32fbe0e769 100644 --- a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs @@ -95,7 +95,7 @@ public sealed class SpillableSystem : EntitySystem : SpillAt(solution, transformComponent.Coordinates, prototype, sound: sound, combine: combine); } - private void SpillOnLand(EntityUid uid, SpillableComponent component, LandEvent args) + private void SpillOnLand(EntityUid uid, SpillableComponent component, ref LandEvent args) { if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution)) return; diff --git a/Content.Server/Light/EntitySystems/LightBulbSystem.cs b/Content.Server/Light/EntitySystems/LightBulbSystem.cs index 90215ec5ad..e11880e723 100644 --- a/Content.Server/Light/EntitySystems/LightBulbSystem.cs +++ b/Content.Server/Light/EntitySystems/LightBulbSystem.cs @@ -25,7 +25,7 @@ namespace Content.Server.Light.EntitySystems SetState(uid, bulb.State, bulb); } - private void HandleLand(EntityUid uid, LightBulbComponent bulb, LandEvent args) + private void HandleLand(EntityUid uid, LightBulbComponent bulb, ref LandEvent args) { PlayBreakSound(uid, bulb); SetState(uid, LightBulbState.Broken, bulb); diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs index 1681d351b4..8db1bee123 100644 --- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs @@ -154,7 +154,7 @@ namespace Content.Server.Nutrition.EntitySystems args.Handled = TryDrink(args.User, args.User, component); } - private void HandleLand(EntityUid uid, DrinkComponent component, LandEvent args) + private void HandleLand(EntityUid uid, DrinkComponent component, ref LandEvent args) { if (component.Pressurized && !component.Opened && diff --git a/Content.Server/Tiles/LavaComponent.cs b/Content.Server/Tiles/LavaComponent.cs new file mode 100644 index 0000000000..0b1df9b139 --- /dev/null +++ b/Content.Server/Tiles/LavaComponent.cs @@ -0,0 +1,23 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Server.Tiles; + +/// +/// Applies flammable and damage while vaulting. +/// +[RegisterComponent, Access(typeof(LavaSystem))] +public sealed class LavaComponent : Component +{ + /// + /// Sound played if something disintegrates in lava. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("soundDisintegration")] + public SoundSpecifier DisintegrationSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg"); + + /// + /// How many fire stacks are applied per second. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("fireStacks")] + public float FireStacks = 2f; +} diff --git a/Content.Server/Tiles/LavaSystem.cs b/Content.Server/Tiles/LavaSystem.cs new file mode 100644 index 0000000000..e484b62a39 --- /dev/null +++ b/Content.Server/Tiles/LavaSystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Shared.StepTrigger.Systems; + +namespace Content.Server.Tiles; + +public sealed class LavaSystem : EntitySystem +{ + [Dependency] private readonly FlammableSystem _flammable = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnLavaStepTriggered); + SubscribeLocalEvent(OnLavaStepTriggerAttempt); + } + + + private void OnLavaStepTriggerAttempt(EntityUid uid, LavaComponent component, ref StepTriggerAttemptEvent args) + { + if (!HasComp(args.Tripper)) + return; + + args.Continue = true; + } + + private void OnLavaStepTriggered(EntityUid uid, LavaComponent component, ref StepTriggeredEvent args) + { + var otherUid = args.Tripper; + + if (TryComp(otherUid, out var flammable)) + { + // Apply the fury of a thousand suns + var multiplier = flammable.FireStacks == 0f ? 5f : 1f; + _flammable.AdjustFireStacks(otherUid, component.FireStacks * multiplier, flammable); + _flammable.Ignite(otherUid, flammable); + } + } +} diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactLandSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactLandSystem.cs index 1183250ac9..f92e4f8e30 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactLandSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactLandSystem.cs @@ -14,7 +14,7 @@ public sealed class ArtifactLandSystem : EntitySystem SubscribeLocalEvent(OnLand); } - private void OnLand(EntityUid uid, ArtifactLandTriggerComponent component, LandEvent args) + private void OnLand(EntityUid uid, ArtifactLandTriggerComponent component, ref LandEvent args) { _artifact.TryActivateArtifact(uid, args.User); } diff --git a/Content.Shared/Climbing/Events/EndClimbEvent.cs b/Content.Shared/Climbing/Events/EndClimbEvent.cs new file mode 100644 index 0000000000..12eaac236d --- /dev/null +++ b/Content.Shared/Climbing/Events/EndClimbEvent.cs @@ -0,0 +1,10 @@ +namespace Content.Shared.Climbing.Events; + +/// +/// Raised on an entity when it ends climbing. +/// +[ByRefEvent] +public readonly record struct EndClimbEvent +{ + +} diff --git a/Content.Shared/Nutrition/EntitySystems/SharedCreamPieSystem.cs b/Content.Shared/Nutrition/EntitySystems/SharedCreamPieSystem.cs index 933d755d2e..a7e191eabf 100644 --- a/Content.Shared/Nutrition/EntitySystems/SharedCreamPieSystem.cs +++ b/Content.Shared/Nutrition/EntitySystems/SharedCreamPieSystem.cs @@ -45,7 +45,7 @@ namespace Content.Shared.Nutrition.EntitySystems } } - private void OnCreamPieLand(EntityUid uid, CreamPieComponent component, LandEvent args) + private void OnCreamPieLand(EntityUid uid, CreamPieComponent component, ref LandEvent args) { SplatCreamPie(uid, component); } diff --git a/Content.Shared/Sound/SharedEmitSoundSystem.cs b/Content.Shared/Sound/SharedEmitSoundSystem.cs index b34ff65b60..c50951f73e 100644 --- a/Content.Shared/Sound/SharedEmitSoundSystem.cs +++ b/Content.Shared/Sound/SharedEmitSoundSystem.cs @@ -29,7 +29,7 @@ namespace Content.Shared.Sound { base.Initialize(); SubscribeLocalEvent(HandleEmitSpawnOnInit); - SubscribeLocalEvent(HandleEmitSoundOnLand); + SubscribeLocalEvent(OnEmitSoundOnLand); SubscribeLocalEvent(HandleEmitSoundOnUseInHand); SubscribeLocalEvent(HandleEmitSoundOnThrown); SubscribeLocalEvent(HandleEmitSoundOnActivateInWorld); @@ -42,7 +42,7 @@ namespace Content.Shared.Sound TryEmitSound(component, predict: false); } - private void HandleEmitSoundOnLand(EntityUid uid, BaseEmitSoundComponent component, LandEvent args) + private void OnEmitSoundOnLand(EntityUid uid, BaseEmitSoundComponent component, ref LandEvent args) { if (!TryComp(uid, out var xform) || !_mapManager.TryGetGrid(xform.GridUid, out var grid)) diff --git a/Content.Shared/Throwing/LandEvent.cs b/Content.Shared/Throwing/LandEvent.cs index 5384cfff99..def0278816 100644 --- a/Content.Shared/Throwing/LandEvent.cs +++ b/Content.Shared/Throwing/LandEvent.cs @@ -5,11 +5,8 @@ namespace Content.Shared.Throwing /// /// Raised when an entity that was thrown lands. This occurs before they stop moving and is when their tile-friction is reapplied. /// - [PublicAPI] - public sealed class LandEvent : EntityEventArgs - { - public EntityUid? User; - } + [ByRefEvent] + public readonly record struct LandEvent(EntityUid? User); /// /// Raised when a thrown entity is no longer moving. diff --git a/Content.Shared/Throwing/ThrowingSystem.cs b/Content.Shared/Throwing/ThrowingSystem.cs index 53d6341aff..331c98feeb 100644 --- a/Content.Shared/Throwing/ThrowingSystem.cs +++ b/Content.Shared/Throwing/ThrowingSystem.cs @@ -82,8 +82,7 @@ public sealed class ThrowingSystem : EntitySystem if (time < FlyTime) { - _physics.SetBodyStatus(physics, BodyStatus.OnGround); - _thrownSystem.LandComponent(comp); + _thrownSystem.LandComponent(comp, physics); } else { @@ -94,8 +93,7 @@ public sealed class ThrowingSystem : EntitySystem if (physics.Deleted) return; - _physics.SetBodyStatus(physics, BodyStatus.OnGround); - _thrownSystem.LandComponent(comp); + _thrownSystem.LandComponent(comp, physics); }); } diff --git a/Content.Shared/Throwing/ThrownItemSystem.cs b/Content.Shared/Throwing/ThrownItemSystem.cs index fa29a03e45..e497b2ec19 100644 --- a/Content.Shared/Throwing/ThrownItemSystem.cs +++ b/Content.Shared/Throwing/ThrownItemSystem.cs @@ -19,9 +19,11 @@ namespace Content.Shared.Throwing /// public sealed class ThrownItemSystem : EntitySystem { - [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; + [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly FixtureSystem _fixtures = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; private const string ThrowingFixture = "throw-fixture"; @@ -115,8 +117,10 @@ namespace Content.Shared.Throwing EntityManager.RemoveComponent(uid); } - public void LandComponent(ThrownItemComponent thrownItem) + public void LandComponent(ThrownItemComponent thrownItem, PhysicsComponent physics) { + _physics.SetBodyStatus(physics, BodyStatus.OnGround); + if (thrownItem.Deleted || Deleted(thrownItem.Owner) || _containerSystem.IsEntityInContainer(thrownItem.Owner)) return; var landing = thrownItem.Owner; @@ -133,8 +137,9 @@ namespace Content.Shared.Throwing if (thrownItem.Thrower is not null) _adminLogger.Add(LogType.Landed, LogImpact.Low, $"{ToPrettyString(landing):entity} thrown by {ToPrettyString(thrownItem.Thrower.Value):thrower} landed."); - var landMsg = new LandEvent {User = thrownItem.Thrower}; - RaiseLocalEvent(landing, landMsg, false); + _broadphase.RegenerateContacts(physics); + var landEvent = new LandEvent(thrownItem.Thrower); + RaiseLocalEvent(landing, ref landEvent); } /// diff --git a/Resources/Prototypes/Entities/Tiles/lava.yml b/Resources/Prototypes/Entities/Tiles/lava.yml new file mode 100644 index 0000000000..c2129fb143 --- /dev/null +++ b/Resources/Prototypes/Entities/Tiles/lava.yml @@ -0,0 +1,43 @@ +- type: entity + id: FloorLavaEntity + name: lava floor + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: StepTrigger + requiredTriggeredSpeed: 0 + intersectRatio: 0.1 + - type: Lava + - type: Transform + anchored: true + - type: Sprite + sprite: Tiles/Planet/lava.rsi + netsync: false + drawdepth: BelowFloor + layers: + - state: lava + shader: unshaded + - type: Icon + sprite: Tiles/Planet/lava.rsi + state: full + - type: IconSmooth + key: floor + base: lava + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + layer: + - SlipLayer + mask: + - ItemMask + density: 1000 + hard: false + - type: Tag + tags: + - HideContextMenu diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/full.png b/Resources/Textures/Tiles/Planet/lava.rsi/full.png new file mode 100644 index 0000000000..b3585d8b22 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava.png new file mode 100644 index 0000000000..a534947981 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava0.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava0.png new file mode 100644 index 0000000000..94acdee620 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava0.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava1.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava1.png new file mode 100644 index 0000000000..3d13abcf4a Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava1.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava2.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava2.png new file mode 100644 index 0000000000..7d0f3b94e2 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava2.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava3.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava3.png new file mode 100644 index 0000000000..0bc58a875f Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava3.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava4.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava4.png new file mode 100644 index 0000000000..3069bea5d2 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava4.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava5.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava5.png new file mode 100644 index 0000000000..6fa1ba427c Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava5.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava6.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava6.png new file mode 100644 index 0000000000..c97ebefb33 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava6.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/lava7.png b/Resources/Textures/Tiles/Planet/lava.rsi/lava7.png new file mode 100644 index 0000000000..a090bed1d1 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/lava.rsi/lava7.png differ diff --git a/Resources/Textures/Tiles/Planet/lava.rsi/meta.json b/Resources/Textures/Tiles/Planet/lava.rsi/meta.json new file mode 100644 index 0000000000..d4d7e14afc --- /dev/null +++ b/Resources/Textures/Tiles/Planet/lava.rsi/meta.json @@ -0,0 +1,265 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation/tree/f116442e34fe3e941a1df474bb57bb410dd177a3/icons/turf and modified", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "lava0", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava1", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava2", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava3", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava4", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava5", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava6", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava7", + "directions": 4, + "delays": [ + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ], + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "lava", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + } + ] +} \ No newline at end of file