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 0000000000..3dbaa124ed Binary files /dev/null and b/Resources/Textures/_White/Objects/Misc/snowball.rsi/snowball.png differ 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 0000000000..8968f8c0df Binary files /dev/null and b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-left.png differ diff --git a/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-right.png b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-right.png new file mode 100644 index 0000000000..b5ebad8516 Binary files /dev/null and b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/inhand-right.png differ diff --git a/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/meta.json b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/meta.json new file mode 100644 index 0000000000..95da8eb1fc --- /dev/null +++ b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by RedTerror (Discord, id 748161739056611428)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "snowball-maker" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/snowball-maker.png b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/snowball-maker.png new file mode 100644 index 0000000000..860db89b90 Binary files /dev/null and b/Resources/Textures/_White/Objects/Misc/snowball_maker.rsi/snowball-maker.png differ