From: B_Kirill <153602297+B-Kirill@users.noreply.github.com> Date: Fri, 9 Jan 2026 04:00:36 +0000 (+1000) Subject: Add craft for bonfire and bonfire with stake (#42211) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=386aca70c73d1f1f6d340f520696819fab4b8950;p=space-station-14.git Add craft for bonfire and bonfire with stake (#42211) * Add craft for bonfire and bonfire with stake * review * review * nullable MaxFireStacks * retry * retry * review * I will change it and hope that they will agree with me * Revert "I will change it and hope that they will agree with me" This reverts commit 83823692d0116bf9aa9eceb85a10e95c88b51fb9. * construction Merged the graphs Changed the bonfire stake ID to follow the proper naming scheme * add destroy sound * planks Instead of logs * of course I forgot about ftl * Slarti review + Princess review Yes I sneaked an admeme abuse change here * a small fix * clamp firestacks * This was on purpose, leave as is This reverts commit 7d63e38b66cb63e5e50b7fac5030013e2ef508b5. * irrelevant * Fixtures * cleanup --------- Co-authored-by: ScarKy0 Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> --- diff --git a/Content.Server/Buckle/Systems/IgniteOnBuckleSystem.cs b/Content.Server/Buckle/Systems/IgniteOnBuckleSystem.cs new file mode 100644 index 0000000000..e7d088df7f --- /dev/null +++ b/Content.Server/Buckle/Systems/IgniteOnBuckleSystem.cs @@ -0,0 +1,70 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos.Components; +using Content.Shared.Buckle.Components; +using Robust.Shared.Timing; + +namespace Content.Server.Buckle.Systems; + +public sealed class IgniteOnBuckleSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly FlammableSystem _flammable = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStrapped); + SubscribeLocalEvent(OnUnstrapped); + + SubscribeLocalEvent(ActiveOnInit); + } + + private void OnStrapped(Entity ent, ref StrappedEvent args) + { + // We cache the values here to the other component. + // This is done so we have to do less lookups + var comp = EnsureComp(args.Buckle); + comp.FireStacks = ent.Comp.FireStacks; + comp.MaxFireStacks = ent.Comp.MaxFireStacks; + comp.IgniteTime = ent.Comp.IgniteTime; + } + + private void ActiveOnInit(Entity ent, ref MapInitEvent args) + { + // Handle this via a separate MapInit so the component can be added by itself if need be. + ent.Comp.NextIgniteTime = _timing.CurTime + ent.Comp.NextIgniteTime; + Dirty(ent); + } + + private void OnUnstrapped(Entity ent, ref UnstrappedEvent args) + { + RemCompDeferred(args.Buckle); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var curTime = _timing.CurTime; + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var igniteComponent, out var flammableComponent)) + { + if (curTime < igniteComponent.NextIgniteTime) + continue; + + igniteComponent.NextIgniteTime += TimeSpan.FromSeconds(igniteComponent.IgniteTime); + Dirty(uid, igniteComponent); + + if (flammableComponent.FireStacks > igniteComponent.MaxFireStacks) + continue; + + var stacks = flammableComponent.FireStacks + igniteComponent.FireStacks; + if (igniteComponent.MaxFireStacks.HasValue) + stacks = Math.Min(stacks, igniteComponent.MaxFireStacks.Value); + + _flammable.SetFireStacks(uid, stacks, flammableComponent, true); + } + } +} diff --git a/Content.Shared/Buckle/Components/ActiveIgniteOnBuckleComponent.cs b/Content.Shared/Buckle/Components/ActiveIgniteOnBuckleComponent.cs new file mode 100644 index 0000000000..f4fd4f59a4 --- /dev/null +++ b/Content.Shared/Buckle/Components/ActiveIgniteOnBuckleComponent.cs @@ -0,0 +1,41 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Buckle.Components; + +/// +/// Component for entities that are currently being ignited by +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentPause, AutoGenerateComponentState] +public sealed partial class ActiveIgniteOnBuckleComponent : Component +{ + // We cache data in this component and apply it to those who get buckled to have to do less lookups. + + /// + /// How many fire stacks to add per cycle. + /// + [DataField] + public float FireStacks = 0.5f; + + /// + /// How frequently the ignition should be applied, in seconds. + /// + [DataField] + public float IgniteTime = 1f; + + /// + /// Maximum fire stacks that can be added by this source. + /// If target already has this many or more fire stacks, no additional stacks will be added. + /// Null means unlimited. + /// + [DataField] + public float? MaxFireStacks = 2.5f; + + /// + /// Next time that fire stacks will be applied. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField, AutoNetworkedField] + public TimeSpan NextIgniteTime = TimeSpan.Zero; +} diff --git a/Content.Shared/Buckle/Components/IgniteOnBuckleComponent.cs b/Content.Shared/Buckle/Components/IgniteOnBuckleComponent.cs new file mode 100644 index 0000000000..61af16f792 --- /dev/null +++ b/Content.Shared/Buckle/Components/IgniteOnBuckleComponent.cs @@ -0,0 +1,31 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Buckle.Components; + +/// +/// Component that makes an entity ignite entities that are buckled to it. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class IgniteOnBuckleComponent : Component +{ + /// + /// How many fire stacks to add per cycle. + /// + [DataField] + public float FireStacks = 0.5f; + + /// + /// How frequently the ignition should be applied, in seconds. + /// + [DataField] + public float IgniteTime = 1f; + + /// + /// Maximum fire stacks that can be added by this source. + /// If target already has this many or more fire stacks, no additional stacks will be added. + /// Null means unlimited. + /// + [DataField] + public float? MaxFireStacks = 2.5f; +} diff --git a/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml b/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml index b60b2bd943..d28abb2b63 100644 --- a/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml +++ b/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml @@ -1,15 +1,22 @@ - type: entity - id: Bonfire + abstract: true parent: BaseStructure - name: bonfire - description: What can be better than a late evening under the sky with guitar and friends? + id: BaseBonfire components: + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.4 + mask: + - Impassable + layer: + - Opaque + - BulletImpassable - type: Sprite noRot: true sprite: Structures/Decoration/bonfire.rsi - layers: - - state: bonfire - - state: burning - type: PointLight radius: 5 energy: 3 @@ -23,6 +30,9 @@ !type:DamageTrigger damage: 50 behaviors: + - !type:PlaySoundBehavior + sound: + collection: WoodDestroy - !type:DoActsBehavior acts: [ "Destruction" ] - type: AmbientSound @@ -31,15 +41,51 @@ sound: path: /Audio/Ambience/Objects/fireplace.ogg - type: AlwaysHot + - type: IgnitionSource + temperature: 700 + ignited: true + +- type: entity + parent: BaseBonfire + id: Bonfire + name: bonfire + description: What can be better than a late evening under the sky with guitar and friends? + components: + - type: Sprite + layers: + - state: burning + - type: Construction + graph: Bonfire + node: bonfire + +- type: entity + parent: BaseBonfire + id: BonfireStake + name: bonfire with stake + description: A sinister bonfire with a stake for... ceremonial purposes. Best not to ask. + components: + - type: Sprite + sprite: Structures/Decoration/bonfire_stake.rsi + layers: + - state: burning + offset: "0, 0.5" + - type: Strap + position: Stand + buckleOffset: "0, 0.5" + buckleDoafterTime: 5 + - type: IgniteOnBuckle + - type: Construction + graph: Bonfire + node: bonfireStake - type: entity + parent: BaseBonfire id: LegionnaireBonfire - parent: Bonfire name: legionnaire bonfire description: There, in the land of lava and ash, place to to cook marshmallow and potato. components: - type: Sprite layers: - - state: legionnaire_bonfire + - state: legionnaire_bonfire - type: PointLight color: "#FF5601" diff --git a/Resources/Prototypes/Recipes/Construction/structures.yml b/Resources/Prototypes/Recipes/Construction/structures.yml index 1f568a1629..5d60a5fc04 100644 --- a/Resources/Prototypes/Recipes/Construction/structures.yml +++ b/Resources/Prototypes/Recipes/Construction/structures.yml @@ -1327,4 +1327,30 @@ canRotate: false canBuildInImpassable: false conditions: - - !type:TileNotBlocked \ No newline at end of file + - !type:TileNotBlocked + +- type: construction + id: Bonfire + graph: Bonfire + startNode: start + targetNode: bonfire + category: construction-category-structures + objectType: Structure + placementMode: SnapgridCenter + canRotate: false + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + +- type: construction + id: BonfireStake + graph: Bonfire + startNode: start + targetNode: bonfireStake + category: construction-category-structures + objectType: Structure + placementMode: SnapgridCenter + canRotate: false + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/bonfire.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/bonfire.yml new file mode 100644 index 0000000000..98ec98d46e --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/bonfire.yml @@ -0,0 +1,42 @@ +- type: constructionGraph + id: Bonfire + start: start + graph: + + - node: start + edges: + - to: bonfire + steps: + - material: WoodPlank + amount: 10 + doAfter: 4 + + - node: bonfire + entity: Bonfire + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: MaterialWoodPlank1 + amount: 10 + - !type:DeleteEntity { } + steps: + - tool: Prying + doAfter: 4 + - to: bonfireStake + steps: + - material: WoodPlank + amount: 2 + doAfter: 2 + + - node: bonfireStake + entity: BonfireStake + edges: + - to: bonfire + completed: + - !type:SpawnPrototype + prototype: MaterialWoodPlank1 + amount: 2 + steps: + - tool: Prying + doAfter: 1 diff --git a/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/bonfire.png b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/bonfire.png new file mode 100644 index 0000000000..f197142c74 Binary files /dev/null and b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/bonfire.png differ diff --git a/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/bonfire_extinguished.png b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/bonfire_extinguished.png new file mode 100644 index 0000000000..c2e629e1a6 Binary files /dev/null and b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/bonfire_extinguished.png differ diff --git a/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/burning.png b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/burning.png new file mode 100644 index 0000000000..cd5ccf1f10 Binary files /dev/null and b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/burning.png differ diff --git a/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/legionnaire_bonfire.png b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/legionnaire_bonfire.png new file mode 100644 index 0000000000..d130f96252 Binary files /dev/null and b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/legionnaire_bonfire.png differ diff --git a/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/meta.json b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/meta.json new file mode 100644 index 0000000000..666b40dba9 --- /dev/null +++ b/Resources/Textures/Structures/Decoration/bonfire_stake.rsi/meta.json @@ -0,0 +1,37 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from /tg/station at commit 28b476ab6d17014e6f9e18a748d7c96be28de9a1, modified by B_Kirill", + "size": { + "x": 32, + "y": 64 + }, + "states": [ + { + "name": "bonfire" + }, + { + "name": "bonfire_extinguished" + }, + { + "name": "burning", + "delays": [ + [ + 0.3, + 0.3, + 0.3 + ] + ] + }, + { + "name": "legionnaire_bonfire", + "delays": [ + [ + 0.3, + 0.3, + 0.3 + ] + ] + } + ] +}