/// Sprite layer that will have its visibility toggled when this item is toggled.
/// </summary>
[DataField("spriteLayer")]
- public string SpriteLayer = "light";
+ public string? SpriteLayer = "light";
/// <summary>
/// Layers to add to the sprite of the player that is holding this entity (while the component is toggled on).
var modulate = AppearanceSystem.TryGetData<Color>(uid, ToggleableLightVisuals.Color, out var color, args.Component);
// Update the item's sprite
- if (args.Sprite != null && args.Sprite.LayerMapTryGet(component.SpriteLayer, out var layer))
+ if (args.Sprite != null && component.SpriteLayer != null && args.Sprite.LayerMapTryGet(component.SpriteLayer, out var layer))
{
args.Sprite.LayerSetVisible(layer, enabled);
if (modulate)
[ViewVariables(VVAccess.ReadWrite)]
[DataField("firestacksOnIgnite")]
public float FirestacksOnIgnite = 2.0f;
+
+ /// <summary>
+ /// Determines how quickly the object will fade out. With positive values, the object will flare up instead of going out.
+ /// </summary>
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public float FirestackFade = -0.1f;
}
}
using Content.Server.Administration.Logs;
using Content.Server.Atmos.Components;
+using Content.Server.Explosion.EntitySystems;
using Content.Server.Stunnable;
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared.ActionBlocker;
using Content.Shared.Alert;
using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
using Content.Shared.Physics;
using Content.Shared.Popups;
using Content.Shared.Rejuvenate;
using Content.Shared.Temperature;
using Content.Shared.Throwing;
+using Content.Shared.Timing;
+using Content.Shared.Toggleable;
using Content.Shared.Weapons.Melee.Events;
using Robust.Server.GameObjects;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
+using Robust.Shared.Random;
namespace Content.Server.Atmos.EntitySystems
{
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
+ [Dependency] private readonly UseDelaySystem _useDelay = default!;
+ [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
public const float MinimumFireStacks = -10f;
public const float MaximumFireStacks = 20f;
SubscribeLocalEvent<IgniteOnCollideComponent, LandEvent>(OnIgniteLand);
SubscribeLocalEvent<IgniteOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit);
+
+ SubscribeLocalEvent<ExtinguishOnInteractComponent, UseInHandEvent>(OnExtinguishUsingInHand);
+ SubscribeLocalEvent<ExtinguishOnInteractComponent, ActivateInWorldEvent>(OnExtinguishActivateInWorld);
}
private void OnMeleeHit(EntityUid uid, IgniteOnMeleeHitComponent component, MeleeHitEvent args)
args.Handled = true;
}
+ private void OnExtinguishActivateInWorld(EntityUid uid, ExtinguishOnInteractComponent component, ActivateInWorldEvent args)
+ {
+ TryHandExtinguish(uid, component);
+ }
+
+ private void OnExtinguishUsingInHand(EntityUid uid, ExtinguishOnInteractComponent component, UseInHandEvent args)
+ {
+ TryHandExtinguish(uid, component);
+ }
+
+ private void TryHandExtinguish(EntityUid uid, ExtinguishOnInteractComponent component)
+ {
+ if (!TryComp(uid, out FlammableComponent? flammable))
+ return;
+ if (!flammable.OnFire)
+ return;
+ if (TryComp(uid, out UseDelayComponent? useDelay) && _useDelay.ActiveDelay(uid, useDelay))
+ return;
+
+ _useDelay.BeginDelay(uid);
+ _audio.PlayPvs(component.ExtinguishAttemptSound, uid);
+ if (_random.Prob(component.Probability))
+ {
+ AdjustFireStacks(uid, component.StackDelta, flammable);
+ } else
+ {
+ _popup.PopupEntity(Loc.GetString(component.ExtinguishFailed), uid);
+ }
+ }
private void OnCollide(EntityUid uid, FlammableComponent flammable, ref StartCollideEvent args)
{
var otherUid = args.OtherEntity;
_appearance.SetData(uid, FireVisuals.OnFire, flammable.OnFire, appearance);
_appearance.SetData(uid, FireVisuals.FireStacks, flammable.FireStacks, appearance);
+
+ // Also enable toggleable-light visuals
+ // This is intended so that matches & candles can re-use code for un-shaded layers on in-hand sprites.
+ // However, this could cause conflicts if something is ACTUALLY both a toggleable light and flammable.
+ // if that ever happens, then fire visuals will need to implement their own in-hand sprite management.
+ _appearance.SetData(uid, ToggleableLightVisuals.Enabled, true, appearance);
}
public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null)
_damageableSystem.TryChangeDamage(uid, flammable.Damage * damageScale);
- AdjustFireStacks(uid, -0.1f * (flammable.Resisting ? 10f : 1f), flammable);
+ AdjustFireStacks(uid, flammable.FirestackFade * (flammable.Resisting ? 10f : 1f), flammable);
}
else
{
--- /dev/null
+using Robust.Shared.Audio;
+
+namespace Content.Shared.Atmos.Components;
+/// <summary>
+/// Allows you to extinguish an object by interacting with it
+/// </summary>
+[RegisterComponent]
+public sealed partial class ExtinguishOnInteractComponent : Component
+{
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public SoundSpecifier? ExtinguishAttemptSound = new SoundPathSpecifier("/Audio/Items/candle_blowing.ogg");
+
+ /// <summary>
+ /// Extinguishing chance
+ /// </summary>
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public float Probability = 0.9f;
+
+ /// <summary>
+ /// Number of fire stacks to be changed on successful interaction.
+ /// </summary>
+ // With positive values, the interaction will conversely fan the fire,
+ // which is useful for any blacksmithing mechs
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public float StackDelta = -5.0f;
+
+ [DataField]
+ public LocId ExtinguishFailed = "candle-extinguish-failed";
+}
- files: ["bow_pull.ogg"]
license: "CC-BY-3.0"
copyright: "User jzdnvdoosj on freesound.org. Converted to ogg by mirrorcult"
- source: "https://freesound.org/people/jzdnvdoosj/sounds/626262/"
\ No newline at end of file
+ source: "https://freesound.org/people/jzdnvdoosj/sounds/626262/"
+
+- files: ["candle_blowing.ogg"]
+ license: "CC-BY-NC-3.0"
+ copyright: "Created by Bee09, converted to OGG, cropped and converted to mono by TheShuEd"
+ source: "https://freesound.org/people/Bee09/sounds/326561/"
\ No newline at end of file
--- /dev/null
+candle-extinguish-failed = The flame flickers, but it doesn't go out
\ No newline at end of file
expendable-light-spent-purple-glowstick-name = spent purple glowstick
expendable-light-spent-yellow-glowstick-name = spent purple glowstick
expendable-light-spent-blue-glowstick-name = spent blue glowstick
-expendable-light-spent-glowstick-desc = It looks like this glowstick has stopped glowing. How tragic.
+expendable-light-spent-glowstick-desc = It looks like this glowstick has stopped glowing. How tragic.
\ No newline at end of file
- type: RadiationBlockingContainer
resistance: 2
+- type: entity
+ name: candle box
+ parent: BoxCardboard
+ id: BoxCandle
+ components:
+ - type: Item
+ size: 30
+ - type: Sprite
+ layers:
+ - state: box
+ - state: candle
+ - type: Storage
+ maxTotalWeight: 30
+ - type: StorageFill
+ contents:
+ - id: Candle
+ amount: 3
+ - id: CandleBlue
+ amount: 3
+ - id: CandleRed
+ amount: 3
+ - id: CandleGreen
+ amount: 3
+ - id: CandlePurple
+ amount: 3
+
+- type: entity
+ name: small candle box
+ parent: BoxCardboard
+ id: BoxCandleSmall
+ components:
+ - type: Item
+ size: 30
+ - type: Sprite
+ layers:
+ - state: box
+ - state: candle
+ - type: Storage
+ maxTotalWeight: 30
+ - type: StorageFill
+ contents:
+ - id: CandleSmall
+ amount: 5
+ - id: CandleBlueSmall
+ amount: 5
+ - id: CandleRedSmall
+ amount: 5
+ - id: CandleGreenSmall
+ amount: 5
+ - id: CandlePurpleSmall
+ amount: 5
+
- type: entity
name: darts box
parent: BoxCardboard
ClothingOuterPlagueSuit: 1
ClothingMaskPlague: 1
ClothingHeadsetService: 2
+ BoxCandle: 2
+ BoxCandleSmall: 2
emaggedInventory:
ClothingOuterArmorCult: 1
ClothingHeadHelmetCult: 1
--- /dev/null
+- type: entity
+ name: candle
+ parent: BaseItem
+ id: Candle
+ description: A thin wick threaded through fat.
+ components:
+ - type: Sprite
+ noRot: true
+ sprite: Objects/Misc/candles.rsi
+ layers:
+ - state: candle-big
+ color: "#decb8e"
+ - type: Item
+ size: 2
+ - type: Appearance
+ - type: Reactive
+ groups:
+ Flammable: [ Touch ]
+ Extinguish: [ Touch ]
+ - type: ExtinguishOnInteract
+ extinguishAttemptSound:
+ path: /Audio/Items/candle_blowing.ogg
+ params:
+ variation: 0.05
+ volume: 10
+ - type: UseDelay
+ - type: Flammable
+ fireSpread: false
+ canResistFire: false
+ alwaysCombustible: true
+ canExtinguish: true
+ firestacksOnIgnite: 3.0
+ firestackFade: -0.01
+ damage:
+ types:
+ Heat: 0.1
+ - type: FireVisuals
+ sprite: Objects/Misc/candles.rsi
+ normalState: fire-big
+ - type: ToggleableLightVisuals
+ spriteLayer: null
+ inhandVisuals:
+ left:
+ - state: inhand-left-flame
+ shader: unshaded
+ right:
+ - state: inhand-right-flame
+ shader: unshaded
+ - type: Damageable
+ damageModifierSet: Wood
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 100
+ behaviors:
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+
+- type: entity
+ name: red candle
+ parent: Candle
+ id: CandleRed
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#a12349"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#a12349"
+ - state: inhand-left-flame
+ right:
+ - state: inhand-right
+ color: "#a12349"
+
+- type: entity
+ name: blue candle
+ parent: Candle
+ id: CandleBlue
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#425d7d"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#425d7d"
+ right:
+ - state: inhand-right
+ color: "#425d7d"
+
+- type: entity
+ name: black candle
+ parent: Candle
+ id: CandleBlack
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#1b1724"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#1b1724"
+ right:
+ - state: inhand-right
+ color: "#1b1724"
+
+- type: entity
+ name: green candle
+ parent: Candle
+ id: CandleGreen
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#5d997e"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#5d997e"
+ right:
+ - state: inhand-right
+ color: "#5d997e"
+
+- type: entity
+ name: purple candle
+ parent: Candle
+ id: CandlePurple
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#984aa1"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#984aa1"
+ right:
+ - state: inhand-right
+ color: "#984aa1"
+
+
+- type: entity
+ name: small candle
+ parent: Candle
+ id: CandleSmall
+ components:
+ - type: Item
+ size: 1
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#e2ca90"
+ - type: FireVisuals
+ normalState: fire-small
+ - type: Flammable
+ firestacksOnIgnite: 2.0
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 60
+ behaviors:
+ - !type:SpawnEntitiesBehavior
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+
+- type: entity
+ name: small red candle
+ parent: CandleSmall
+ id: CandleRedSmall
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#a12349"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#a12349"
+ right:
+ - state: inhand-right
+ color: "#a12349"
+
+- type: entity
+ name: small blue candle
+ parent: CandleSmall
+ id: CandleBlueSmall
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#425d7d"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#425d7d"
+ right:
+ - state: inhand-right
+ color: "#425d7d"
+
+- type: entity
+ name: small black candle
+ parent: CandleSmall
+ id: CandleBlackSmall
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#1b1724"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#1b1724"
+ right:
+ - state: inhand-right
+ color: "#1b1724"
+
+- type: entity
+ name: small green candle
+ parent: CandleSmall
+ id: CandleGreenSmall
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#5d997e"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#5d997e"
+ right:
+ - state: inhand-right
+ color: "#5d997e"
+
+- type: entity
+ name: small purple candle
+ parent: CandleSmall
+ id: CandlePurpleSmall
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#984aa1"
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#984aa1"
+ right:
+ - state: inhand-right
+ color: "#984aa1"
+
+#Purely decorative candles for mappers. Do not have any functionality.
+
+- type: entity
+ name: magic candle
+ description: It's either magic or high tech, but this candle never goes out. On the other hand, its flame is quite cold.
+ parent: BaseItem
+ suffix: Decorative
+ id: CandleInfinite
+ components:
+ - type: Sprite
+ noRot: true
+ sprite: Objects/Misc/candles.rsi
+ layers:
+ - state: candle-big
+ color: "#decb8e"
+ - state: fire-big
+ shader: unshaded
+ - type: PointLight
+ color: "#e39c40"
+ radius: 2.5
+ power: 10
+
+- type: entity
+ name: magic red candle
+ parent: CandleInfinite
+ id: CandleRedInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#a12349"
+ - state: fire-big
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#a12349"
+ right:
+ - state: inhand-right
+ color: "#a12349"
+
+- type: entity
+ name: magic blue candle
+ parent: CandleInfinite
+ id: CandleBlueInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#425d7d"
+ - state: fire-big
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#425d7d"
+ right:
+ - state: inhand-right
+ color: "#425d7d"
+
+- type: entity
+ name: magic black candle
+ parent: CandleInfinite
+ id: CandleBlackInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#1b1724"
+ - state: fire-big
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#1b1724"
+ right:
+ - state: inhand-right
+ color: "#1b1724"
+
+- type: entity
+ name: magic green candle
+ parent: CandleInfinite
+ id: CandleGreenInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#5d997e"
+ - state: fire-big
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#5d997e"
+ right:
+ - state: inhand-right
+ color: "#5d997e"
+
+- type: entity
+ name: magic purple candle
+ parent: CandleInfinite
+ id: CandlePurpleInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-big
+ color: "#984aa1"
+ - state: fire-big
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#984aa1"
+ right:
+ - state: inhand-right
+ color: "#984aa1"
+
+- type: entity
+ name: small magic red candle
+ parent: CandleInfinite
+ id: CandleRedSmallInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#a12349"
+ - state: fire-small
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#a12349"
+ right:
+ - state: inhand-right
+ color: "#a12349"
+
+- type: entity
+ name: small magic blue candle
+ parent: CandleInfinite
+ id: CandleBlueSmallInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#425d7d"
+ - state: fire-small
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#425d7d"
+ right:
+ - state: inhand-right
+ color: "#425d7d"
+
+- type: entity
+ name: small magic black candle
+ parent: CandleInfinite
+ id: CandleBlackSmallInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#1b1724"
+ - state: fire-small
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#1b1724"
+ right:
+ - state: inhand-right
+ color: "#1b1724"
+
+- type: entity
+ name: small magic green candle
+ parent: CandleInfinite
+ id: CandleGreenSmallInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#5d997e"
+ - state: fire-small
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#5d997e"
+ right:
+ - state: inhand-right
+ color: "#5d997e"
+
+- type: entity
+ name: small magic purple candle
+ parent: CandleInfinite
+ id: CandlePurpleSmallInfinite
+ components:
+ - type: Sprite
+ layers:
+ - state: candle-small
+ color: "#984aa1"
+ - state: fire-small
+ shader: unshaded
+ - type: Item
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ color: "#984aa1"
+ right:
+ - state: inhand-right
+ color: "#984aa1"
endValue: 1.0
- type: Tag
tags:
- - Torch
\ No newline at end of file
+ - Torch
--- /dev/null
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by TheShuEd (github) for ss14",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "stand-small"
+ },
+ {
+ "name": "stand-big"
+ },
+ {
+ "name": "candle-small"
+ },
+ {
+ "name": "candle-big"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "fire-small",
+ "delays": [
+ [
+ 0.15,
+ 0.15,
+ 0.15,
+ 0.15
+ ]
+ ]
+ },
+ {
+ "name": "fire-big",
+ "delays": [
+ [
+ 0.15,
+ 0.15,
+ 0.15,
+ 0.15
+ ]
+ ]
+ },
+ {
+ "name": "inhand-left-flame",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "inhand-right-flame",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ }
+ ]
+}
{
"version": 1,
"license": "CC-BY-SA-3.0",
- "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/cc65477c04f7403ca8a457bd5bae69a01abadbf0, encryptokey was taken from Baystation12 at https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi and modified by lapatison. boxwidetoy, shelltoy, swab, flare, inflatable, trashbag, magazine, holo and forensic created by potato1234x (github) for ss14 based on toys.rsi, mouth_swab.rsi, flare.rsi, inflatable_wall.rsi, trashbag.rsi, caseless_pistol_mag.rsi, guardians.rsi and bureaucracy.rsi respectively, darts made by TheShuEd (github) for ss14",
+ "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/cc65477c04f7403ca8a457bd5bae69a01abadbf0, encryptokey was taken from Baystation12 at https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi and modified by lapatison. boxwidetoy, shelltoy, swab, flare, inflatable, trashbag, magazine, holo and forensic created by potato1234x (github) for ss14 based on toys.rsi, mouth_swab.rsi, flare.rsi, inflatable_wall.rsi, trashbag.rsi, caseless_pistol_mag.rsi, guardians.rsi and bureaucracy.rsi respectively, candle and darts created by TheShuEd for ss14",
"size": {
"x": 32,
"y": 32
{
"name": "ziptie"
},
+ {
+ "name": "candle"
+ },
{
"name": "darts"
}