From e55275dcebe9e12e7507ee38d1cbb29263ef3e00 Mon Sep 17 00:00:00 2001 From: PuroSlavKing <103608145+PuroSlavKing@users.noreply.github.com> Date: Wed, 25 Dec 2024 14:53:43 +0300 Subject: [PATCH] [Port] Snowball (#199) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Снежки (#179) * snowballs * nah * reviewe * oops + better offset * a * migrate * fixiki * namespaces * edit flavors --------- Co-authored-by: csqrb <56765288+CaptainSqrBeard@users.noreply.github.com> --- .../Thresholds/Behaviors/SpillBehavior.cs | 7 +- .../Components/FromTileCrafterComponent.cs | 54 +++++++++++ .../Systems/FromTileCrafterSystem.cs | 85 ++++++++++++++++++ .../Locale/ru-RU/_white/flavors/flavors.ftl | 1 + .../entities/objects/misc/snowball.ftl | 5 ++ .../Entities/Structures/Machines/lathe.yml | 1 + .../_White/Entities/Fun/snowball.yml | 77 ++++++++++++++++ .../Prototypes/_White/Flavors/flavors.yml | 3 + .../Prototypes/_White/Recipes/Lathes/Misc.yml | 6 ++ .../Objects/Misc/snowball.rsi/meta.json | 14 +++ .../Objects/Misc/snowball.rsi/snowball.png | Bin 0 -> 361 bytes .../Misc/snowball_maker.rsi/inhand-left.png | Bin 0 -> 344 bytes .../Misc/snowball_maker.rsi/inhand-right.png | Bin 0 -> 349 bytes .../Objects/Misc/snowball_maker.rsi/meta.json | 22 +++++ .../snowball_maker.rsi/snowball-maker.png | Bin 0 -> 420 bytes 15 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 Content.Shared/_White/FromTileCrafter/Components/FromTileCrafterComponent.cs create mode 100644 Content.Shared/_White/FromTileCrafter/Systems/FromTileCrafterSystem.cs create mode 100644 Resources/Locale/ru-RU/_white/flavors/flavors.ftl create mode 100644 Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/snowball.ftl create mode 100644 Resources/Prototypes/_White/Entities/Fun/snowball.yml create mode 100644 Resources/Prototypes/_White/Flavors/flavors.yml create mode 100644 Resources/Prototypes/_White/Recipes/Lathes/Misc.yml create mode 100644 Resources/Textures/_White/Objects/Misc/snowball.rsi/meta.json create mode 100644 Resources/Textures/_White/Objects/Misc/snowball.rsi/snowball.png create mode 100644 Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-left.png create mode 100644 Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-right.png create mode 100644 Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/meta.json create mode 100644 Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/snowball-maker.png diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs index 38564380c0..b422aaa37f 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs @@ -12,6 +12,11 @@ public sealed partial class SpillBehavior : IThresholdBehavior [DataField] public string? Solution; + // WWDP-Start + [DataField] + public bool SpillSound = true; + // WWDP-End + /// /// If there is a SpillableComponent on EntityUidowner use it to create a puddle/smear. /// Or whatever solution is specified in the behavior itself. @@ -35,7 +40,7 @@ public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause else if (Solution != null && solutionContainerSystem.TryGetSolution(owner, Solution, out _, out var behaviorSolution)) { - spillableSystem.TrySplashSpillAt(owner, coordinates, behaviorSolution, out _, user: cause); + spillableSystem.TrySplashSpillAt(owner, coordinates, behaviorSolution, out _, SpillSound, user: cause); // WWDP-Edit } } } diff --git a/Content.Shared/_White/FromTileCrafter/Components/FromTileCrafterComponent.cs b/Content.Shared/_White/FromTileCrafter/Components/FromTileCrafterComponent.cs new file mode 100644 index 0000000000..7973e02355 --- /dev/null +++ b/Content.Shared/_White/FromTileCrafter/Components/FromTileCrafterComponent.cs @@ -0,0 +1,54 @@ +using Content.Shared.DoAfter; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._White.FromTileCrafter.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class FromTileCrafterComponent : Component +{ + /// + /// Object that will be created + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + [ValidatePrototypeId] + public string EntityToSpawn; + + /// + /// Tiles that allowed to use to craft an object + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public HashSet AllowedTileIds = new(); + + /// + /// The time it takes to craft. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Delay = 1f; + + /// + /// How far spawned item can offset from tile center + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Spread = 0.3f; +} + +[Serializable, NetSerializable] +public sealed partial class FromTileCraftDoAfterEvent : DoAfterEvent +{ + public NetEntity Grid; + public Vector2i GridTile; + + public FromTileCraftDoAfterEvent(NetEntity grid, Vector2i gridTile) + { + Grid = grid; + GridTile = gridTile; + } + + public override DoAfterEvent Clone() + { + return new FromTileCraftDoAfterEvent(Grid, GridTile); + } + +} diff --git a/Content.Shared/_White/FromTileCrafter/Systems/FromTileCrafterSystem.cs b/Content.Shared/_White/FromTileCrafter/Systems/FromTileCrafterSystem.cs new file mode 100644 index 0000000000..3898b95a30 --- /dev/null +++ b/Content.Shared/_White/FromTileCrafter/Systems/FromTileCrafterSystem.cs @@ -0,0 +1,85 @@ +using System.Numerics; +using Content.Shared._White.FromTileCrafter.Components; +using Content.Shared.DoAfter; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Network; +using Robust.Shared.Random; + + +namespace Content.Shared._White.FromTileCrafter.Systems; + +public sealed class FromTileCrafterSystem : EntitySystem +{ + [Dependency] private readonly SharedHandsSystem _handsSystem = default!; + [Dependency] private readonly SharedMapSystem _maps = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; + [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly INetManager _netManager = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnFromTileCraftComplete); + SubscribeLocalEvent(OnAfterInteract); + } + + private void OnFromTileCraftComplete(Entity ent, ref FromTileCraftDoAfterEvent args) + { + if (_netManager.IsClient) + return; + + if (args.Handled || args.Cancelled) + return; + + var comp = ent.Comp; + + var gridUid = GetEntity(args.Grid); + if (!TryComp(gridUid, out var grid)) + return; + + var tileRef = _maps.GetTileRef(gridUid, grid, args.GridTile); + var coords = _maps.ToCoordinates(tileRef, grid); + + var offset = new Vector2( + ((_robustRandom.NextFloat() - 0.5f) * comp.Spread + 0.5f) * grid.TileSize, + ((_robustRandom.NextFloat() - 0.5f) * comp.Spread + 0.5f) * grid.TileSize); + + Spawn(ent.Comp.EntityToSpawn, coords.Offset(offset)); + } + + private void OnAfterInteract(Entity ent, ref AfterInteractEvent args) + { + if (args.Handled || args.Target != null) + return; + + var comp = ent.Comp; + + if (!_mapManager.TryFindGridAt(_transformSystem.ToMapCoordinates(args.ClickLocation), out var gridUid, out var mapGrid)) + return; + + var tileRef = _maps.GetTileRef(gridUid, mapGrid, args.ClickLocation); + var tileId = _tileDefManager[tileRef.Tile.TypeId].ID; + + if (!comp.AllowedTileIds.Contains(tileId)) + return; + + var coordinates = _maps.GridTileToLocal(gridUid, mapGrid, tileRef.GridIndices); + if (!_interactionSystem.InRangeUnobstructed(args.User, coordinates, popup: false)) + return; + + var doAfterEvent = new FromTileCraftDoAfterEvent(GetNetEntity(gridUid), tileRef.GridIndices); + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, comp.Delay, doAfterEvent, ent, used: ent) + { + BreakOnUserMove = true, + BlockDuplicate = true, + DuplicateCondition = DuplicateConditions.SameTool, + }; + _doAfterSystem.TryStartDoAfter(doAfterArgs, out _); + } +} diff --git a/Resources/Locale/ru-RU/_white/flavors/flavors.ftl b/Resources/Locale/ru-RU/_white/flavors/flavors.ftl new file mode 100644 index 0000000000..a1bf0e1a03 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/flavors/flavors.ftl @@ -0,0 +1 @@ +flavor-base-snow = как снег diff --git a/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/snowball.ftl b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/snowball.ftl new file mode 100644 index 0000000000..15b001c6ab --- /dev/null +++ b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/snowball.ftl @@ -0,0 +1,5 @@ +ent-ItemSnowballMaker = снежколеп + .desc = Позволяет быстро лепить снежки из снега (или из астро-снега, когда сезон не тот). + +ent-ItemSnowball = снежок + .desc = Небольшой комочек снега, что можно бросить в кого-то. diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 69dd85c155..dbb7e386ab 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -196,6 +196,7 @@ - WeaponCapacitorRechargerCircuitboard - HandheldStationMap - ClothingHeadHatWelding + - SnowballMaker # WWDP - type: EmagLatheRecipes emagStaticRecipes: - BoxLethalshot diff --git a/Resources/Prototypes/_White/Entities/Fun/snowball.yml b/Resources/Prototypes/_White/Entities/Fun/snowball.yml new file mode 100644 index 0000000000..68360ac678 --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Fun/snowball.yml @@ -0,0 +1,77 @@ +- type: entity + parent: BaseItem + id: ItemSnowballMaker + name: snowball maker + description: Makes snowballs. + components: + - type: Sprite + sprite: _White/Objects/Misc/snowball_maker.rsi + layers: + - state: snowball-maker + - type: Item + - type: PhysicalComposition + materialComposition: + Plastic: 200 + - type: FromTileCrafter + delay: 0.5 + entityToSpawn: ItemSnowball + allowedTileIds: + - FloorAstroSnow + - FloorSnow + - FloorSnowDug + - PlatingSnow + +- type: entity + parent: [BaseItem, FoodBase] + id: ItemSnowball + name: snowball + description: Iced. + components: + - type: Damageable + damageContainer: Inorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 1 + behaviors: + - !type:SpillBehavior + solution: snowball + spillSound: False + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/chop.ogg + - !type:DoActsBehavior + acts: ["Destruction"] + - type: DamageOnLand + damage: + types: + Blunt: 3 + - type: StaminaDamageOnCollide + damage: 8.1 + - type: Sprite + sprite: _White/Objects/Misc/snowball.rsi + state: snowball + - type: Item + size: Tiny + - type: SolutionContainerManager + solutions: + snowball: + maxVol: 10 + reagents: + - ReagentId: Water + Quantity: 5 + - type: FlavorProfile + flavors: + - snow + ignoreReagents: + - Water + - type: Food + solution: snowball + - type: MixableSolution + solution: snowball + - type: InjectableSolution + solution: snowball + - type: RefillableSolution + solution: snowball +# - type: LandAtCursor diff --git a/Resources/Prototypes/_White/Flavors/flavors.yml b/Resources/Prototypes/_White/Flavors/flavors.yml new file mode 100644 index 0000000000..5a999068a3 --- /dev/null +++ b/Resources/Prototypes/_White/Flavors/flavors.yml @@ -0,0 +1,3 @@ +- type: flavor + id: snow + description: flavor-base-snow diff --git a/Resources/Prototypes/_White/Recipes/Lathes/Misc.yml b/Resources/Prototypes/_White/Recipes/Lathes/Misc.yml new file mode 100644 index 0000000000..d1f91c10d9 --- /dev/null +++ b/Resources/Prototypes/_White/Recipes/Lathes/Misc.yml @@ -0,0 +1,6 @@ +- type: latheRecipe + id: SnowballMaker + result: ItemSnowballMaker + completetime: 2 + materials: + Plastic: 200 diff --git a/Resources/Textures/_White/Objects/Misc/snowball.rsi/meta.json b/Resources/Textures/_White/Objects/Misc/snowball.rsi/meta.json new file mode 100644 index 0000000000..c1346e5802 --- /dev/null +++ b/Resources/Textures/_White/Objects/Misc/snowball.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by RedTerror (Discord, id 748161739056611428)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "snowball" + } + ] +} diff --git a/Resources/Textures/_White/Objects/Misc/snowball.rsi/snowball.png b/Resources/Textures/_White/Objects/Misc/snowball.rsi/snowball.png new file mode 100644 index 0000000000000000000000000000000000000000..3dbaa124ed2257d17ebf117434cf2fd6a6df1405 GIT binary patch literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^ThgKNpD0f^_us^{bd~nbHOyfq2NO!( z+gyIFAE7V)ZRxzbEfa6oTS**PFTTewp~r)D;_pXynI8-7QvaTNbb;Cw>2;@GDu~M6 zYx&;P(xE)j>FVdQ&MBb@ E0FQo^^#A|> literal 0 HcmV?d00001 diff --git a/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-left.png b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..8968f8c0dfc496e7c609653f56b95f5f61f20e39 GIT binary patch literal 344 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|et5b#hE&XX zd&`io*?_0@VSwgw1?M!sLyeZ6X>1m3&Q=Q+bSxA)>m7CLfAp@KeVnNqdKrP*fFR&Z zyGHMI|63JTpYm30|8ZN^YI>KxtxL0-%_`S#ic+snB}HsMzVb$gpPZq7ne6Gus~^vO zk>_B4^zq&8e&KJd%8r`9WQ}EBW1JTKt!caKchwJya)sI#Ocx|g{J!|#9=W7uKah~DBW(>eh=%jXWM6FF0<#qCG&E@&&m2T zyj~x_Y3E|hA3ODIU-6kKuUCu29QStF?fiAxl7CU%t!&fO7+Te@7-yvEsRm9r*y!iG_g?CxC#K8Rlxn< iAiuYU*GM$yqTp(!mx>HrH)Hx^Xo-hCTQ(>caT|g$3=&*7RyLRiC(vfCz<5p4?JBo z_1IIU8D|!4?-f><`gBh6{@-PizfS2)efsEbVZ#fpBb)}m&eXBZi(CI$;Q0^Ht+{&| z-cEXZeRbF^)!(1Z?{cmPIKL+D(XSa3Y<&-uotz+gAoKCFuX!tuE$@|fPn*vc80BNX zw|&B;y1QLFlr7%!d}%0I?~MB+>WAPgqm*%gxX0*>gW38ri7wFswz8i;Q z#g?$kui>8cuKH25f^Wk`hSQDre{Oy9nqO?s5-V{7jU`!iMO)WaJFIpH{U;FNx9y>P zWWnt!-#u}1OKlaq(~ecmzR=bDh(Fz^?aKPbkGjCXzopr00Hl@ApigX literal 0 HcmV?d00001