From c3fde1d5ba7e0e0c4e2be8d8b63e82667b27d3c1 Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Sun, 23 Feb 2025 13:37:45 +0400 Subject: [PATCH 1/7] Update Loenn plugin to make particleColors a list of colors --- Loenn/entities/wind_tunnel.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Loenn/entities/wind_tunnel.lua b/Loenn/entities/wind_tunnel.lua index 7beec08..c2b65fd 100644 --- a/Loenn/entities/wind_tunnel.lua +++ b/Loenn/entities/wind_tunnel.lua @@ -8,6 +8,13 @@ windTunnel.fieldInformation = { direction = { editable = false, options = directions + }, + particleColors = { + fieldType = "list", + elementOptions = { + fieldType = "color" + }, + elementDefault = "ffffff" } } @@ -22,7 +29,7 @@ for _, direction in ipairs(directions) do activationId = "", strength = 100.0, startActive = true, - particleColors = "808080,545151,ada5a5", + particleColors = "808080,545151,ada5a5", showParticles = true } } From c5b2257fe31cfd3779c88d5924b4d460c35037be Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Sun, 23 Feb 2025 15:12:35 +0400 Subject: [PATCH 2/7] Add reskinnability for Throw Boxes + an option to allow Boxes to pass through Spinners --- Code/Entities/ThrowBox.cs | 23 ++++++++++++++----- Code/Entities/ThrowBoxSpawner.cs | 24 +++++++++++++++++--- Loenn/entities/crate.lua | 39 +++++++++++++++++++++++++++++--- Loenn/entities/crate_spawner.lua | 14 ++++++++++-- Loenn/lang/en_gb.lang | 8 +++++++ 5 files changed, 94 insertions(+), 14 deletions(-) diff --git a/Code/Entities/ThrowBox.cs b/Code/Entities/ThrowBox.cs index 0153560..ec201f0 100644 --- a/Code/Entities/ThrowBox.cs +++ b/Code/Entities/ThrowBox.cs @@ -39,6 +39,8 @@ public class ThrowBox : Actor { private readonly string _levelName; private readonly bool _tutorial; private readonly TransitionListener _transitionListener; + private readonly bool _canPassThroughSpinners; + private readonly ParticleType _p_Impact; private Vector2 _prevLiftSpeed; private Level _level; @@ -55,7 +57,8 @@ public class ThrowBox : Actor { private BirdTutorialGui _tutorialPutDown; private bool _isCrucial; - public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSpecial = false, bool isCrucial = false) + public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSpecial = false, bool isCrucial = false, + bool canPassThroughSpinners = false, string textureDirectory = "", bool overrideParticles = false, Color impactParticlesColor = default) : base(position) { Position -= DISPLACEMENT; _starterPosition = Position; @@ -64,14 +67,18 @@ public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSp _isMetal = isMetal; IsSpecial = isSpecial; _isCrucial = isCrucial; + _canPassThroughSpinners = canPassThroughSpinners; _tutorial = tutorial; + + textureDirectory = textureDirectory.Trim().TrimEnd('/'); + string textureDir = string.IsNullOrEmpty(textureDirectory) ? "objects/FactoryHelper/crate" : textureDirectory; string pathString = isMetal ? "crate_metal0" : "crate0"; - Add(_image = new Image(GFX.Game[$"objects/FactoryHelper/crate/{pathString}"])); + Add(_image = new Image(GFX.Game[$"{textureDir}/{pathString}"])); _image.Position += DISPLACEMENT; if (_isCrucial) { - Add(_warningImage = new Image(GFX.Game["objects/FactoryHelper/crate/crucial"])); + Add(_warningImage = new Image(GFX.Game[$"{textureDir}/crucial"])); _warningImage.Position += DISPLACEMENT; } @@ -98,10 +105,13 @@ public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSp Add(new LightOcclude(0.2f)); Add(new MirrorReflection()); + + _p_Impact = overrideParticles ? new(P_Impact) { Color = impactParticlesColor } : P_Impact; } public ThrowBox(EntityData data, Vector2 offset) - : this(data.Position + offset, data.Bool("isMetal", false), data.Bool("tutorial", false), data.Bool("isSpecial", false), data.Bool("isCrucial", false)) { + : this(data.Position + offset, data.Bool("isMetal", false), data.Bool("tutorial", false), data.Bool("isSpecial", false), data.Bool("isCrucial", false), + data.Bool("canPassThroughSpinners", false), data.Attr("textureDirectory", ""), data.Bool("overrideParticles", false), data.HexColor("impactParticlesColor", default)) { _levelName = data.Level.Name; } @@ -110,7 +120,8 @@ private void OnSteamWall(SteamWall steamWall) { } private void OnHitSpinner(Entity spinner) { - Shatter(); + if (!_canPassThroughSpinners) + Shatter(); } public override void Added(Scene scene) { @@ -419,7 +430,7 @@ private void ImpactParticles(Vector2 dir) { positionRange = Vector2.UnitX * 6f; } - (Scene as Level).Particles.Emit(P_Impact, 12, position, positionRange, direction); + (Scene as Level).Particles.Emit(_p_Impact, 12, position, positionRange, direction); } private void Shatter() { diff --git a/Code/Entities/ThrowBoxSpawner.cs b/Code/Entities/ThrowBoxSpawner.cs index a8003d8..89e5457 100644 --- a/Code/Entities/ThrowBoxSpawner.cs +++ b/Code/Entities/ThrowBoxSpawner.cs @@ -20,7 +20,14 @@ public class ThrowBoxSpawner : Entity { private readonly bool _fromTop; private readonly bool _tutorial; - public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activationId, bool isMetal, bool isRandom, bool fromTop, bool tutorial, bool startActive) : base(position) { + private readonly bool _canPassThroughSpinners; + private readonly string _textureDirectory; + private readonly bool _overrideParticles; + private readonly Color _impactParticlesColor; + + public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activationId, bool isMetal, bool isRandom, bool fromTop, bool tutorial, bool startActive, + bool canPassThroughSpinners = false, string textureDirectory = "", bool overrideParticles = false, Color impactParticlesColor = default) + : base(position) { Add(Activator = new FactoryActivator()); Activator.ActivationId = activationId == string.Empty ? null : activationId; Activator.StartOn = startActive; @@ -33,13 +40,20 @@ public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activa _isRandom = isRandom; _fromTop = fromTop; _tutorial = tutorial; + + _canPassThroughSpinners = canPassThroughSpinners; + _textureDirectory = textureDirectory; + _overrideParticles = overrideParticles; + _impactParticlesColor = impactParticlesColor; + Add(new Coroutine(SpawnSequence())); Add(new SteamCollider(OnSteamWall)); } public ThrowBoxSpawner(EntityData data, Vector2 offset) : this(data.Position + offset, data.Float("delay", 5f), data.Int("maximum", 0), data.Attr("activationId"), data.Bool("isMetal", false), - data.Bool("isRandom", false), data.Bool("fromTop", true), data.Bool("tutorial", false), data.Bool("startActive", true)) { + data.Bool("isRandom", false), data.Bool("fromTop", true), data.Bool("tutorial", false), data.Bool("startActive", true), + data.Bool("canPassThroughSpinners", false), data.Attr("textureDirectory", ""), data.Bool("overrideParticles", false), data.HexColor("impactParticlesColor", default)) { } private void OnSteamWall(SteamWall steamWall) { @@ -69,7 +83,11 @@ private void TrySpawnThrowBox() { ThrowBox crate = new( position: new Vector2(posX, posY), isMetal: _isRandom ? Calc.Random.Chance(0.5f) : _isMetal, - tutorial: _tutorial + tutorial: _tutorial, + canPassThroughSpinners: _canPassThroughSpinners, + textureDirectory: _textureDirectory, + overrideParticles: _overrideParticles, + impactParticlesColor: _impactParticlesColor ); Scene.Add(crate); _boxes.Add(crate); diff --git a/Loenn/entities/crate.lua b/Loenn/entities/crate.lua index 540bd30..1b46679 100644 --- a/Loenn/entities/crate.lua +++ b/Loenn/entities/crate.lua @@ -1,7 +1,15 @@ +local drawableSprite = require("structs.drawable_sprite") + local crate = {} crate.name = "FactoryHelper/ThrowBox" +crate.fieldInformation = { + impactParticlesColor = { + fieldType = "color" + } +} + crate.placements = { { name = "wood", @@ -9,7 +17,11 @@ crate.placements = { isMetal = false, tutorial = false, isSpecial = false, - isCrucial = false + isCrucial = false, + canPassThroughSpinners = false, + textureDirectory = "objects/FactoryHelper/crate", + overrideParticles = false, + impactParticlesColor = "9c8d7b" } }, { @@ -18,13 +30,34 @@ crate.placements = { isMetal = true, tutorial = false, isSpecial = false, - isCrucial = false + isCrucial = false, + canPassThroughSpinners = false, + textureDirectory = "objects/FactoryHelper/crate", + overrideParticles = false, + impactParticlesColor = "9c8d7b" } } } -function crate.texture(sprite, entity) +--[[function crate.texture(sprite, entity) return entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0" +end]] + +function crate.sprite(room, entity) + local sprites = {} + + local textureDirData = entity.textureDirectory + local textureDir = (textureDirData == nil or textureDirData == "") and "objects/FactoryHelper/crate" or textureDirData + + local texture = textureDir .. (entity.isMetal and "/crate_metal0" or "/crate0") + table.insert(sprites, drawableSprite.fromTexture(texture, entity)) + + if (entity.isCrucial) then + local crucialTexture = textureDir .. "/crucial" + table.insert(sprites, drawableSprite.fromTexture(crucialTexture, entity)) + end + + return sprites end crate.justification = {0.0, 0.0} diff --git a/Loenn/entities/crate_spawner.lua b/Loenn/entities/crate_spawner.lua index 51bb22b..94bc47c 100644 --- a/Loenn/entities/crate_spawner.lua +++ b/Loenn/entities/crate_spawner.lua @@ -12,6 +12,9 @@ crateSpawner.fieldInformation = { maximum = { fieldType = "integer", minimumValue = 0 + }, + impactParticlesColor = { + fieldType = "color" } } @@ -26,7 +29,11 @@ crateSpawner.placements = { isRandom = false, fromTop = true, tutorial = false, - startActive = true + startActive = true, + canPassThroughSpinners = false, + textureDirectory = "objects/FactoryHelper/crate", + overrideParticles = false, + impactParticlesColor = "9c8d7b" } } } @@ -37,7 +44,10 @@ local randomColor = {1.0, 0.5, 1.0, 0.2} function crateSpawner.sprite(room, entity) local sprites = {} - local texture = entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0" + local textureDirData = entity.textureDirectory + local textureDir = (textureDirData == nil or textureDirData == "") and "objects/FactoryHelper/crate" or textureDirData + + local texture = textureDir .. (entity.isMetal and "/crate_metal0" or "/crate0") local crateSprite = drawableSprite.fromTexture(texture, entity) crateSprite.color = {1.0, 1.0, 1.0, 0.5} diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index 4b94f82..9b37a91 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -33,6 +33,10 @@ entities.FactoryHelper/ThrowBox.attributes.description.isMetal=Whether the crate entities.FactoryHelper/ThrowBox.attributes.description.tutorial=Whether the tutorial messsages should show up. entities.FactoryHelper/ThrowBox.attributes.description.isSpecial=Whether the crate should kill the player and return them to the crate's origin upon destruction or player death. entities.FactoryHelper/ThrowBox.attributes.description.isCrucial=Whether the crate should kill the player upon destruction. +entities.FactoryHelper/ThrowBox.attributes.description.canPassThroughSpinners=Whether the crate should not break in collision with Spinners. +entities.FactoryHelper/ThrowBox.attributes.description.textureDirectory=Which directory in the Gameplay atlas that the crate should use for its textures.\nIf changed, the directory should be a copy of the default "objects/FactoryHelper/crate", containing the following textures:\n- "crate0" for wooden crates\n- "crate_metal0" for metal crates\n- "crucial" for the frame added if `Is Crucial` is `true` +entities.FactoryHelper/ThrowBox.attributes.description.overrideParticles=If `true`, a new impact particle type will be created for the crate.\nThis is required in order to modify the color of the particles. +entities.FactoryHelper/ThrowBox.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when the crate hits a solid. Default value: "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. # Crate Spawner entities.FactoryHelper/ThrowBoxSpawner.placements.name.crate_spawner=Crate Spawner @@ -44,6 +48,10 @@ entities.FactoryHelper/ThrowBoxSpawner.attributes.description.isRandom=Whether t entities.FactoryHelper/ThrowBoxSpawner.attributes.description.fromTop=If `true` they will spawn on top, otherwise they will spawn at the nearest side. Defaults to `true`. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.tutorial=Whether the tutorial messsages should show up. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.maximum=The maximum number of crate this spawner can spawn. Destroyed crates do not count towards the maximum. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.canPassThroughSpinners=Whether the spawned crates should not break in collision with Spinners. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.textureDirectory=Which directory in the Gameplay atlas that spawned crates should use for their textures.\nIf changed, the directory should be a copy of the default "objects/FactoryHelper/crate", containing the following textures:\n- "crate0" for wooden crates\n- "crate_metal0" for metal crates\n- "crucial" for the frame added if `Is Crucial` is `true` +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.overrideParticles=If `true`, a new impact particle type will be created for spawned crates.\nThis is required in order to modify the color of the particles. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when spawned crates hit a solid. Default value: "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. # Dash Fuse Box entities.FactoryHelper/DashFuseBox.placements.name.left=Dash Fuse Box (Left) From 6b16d8ac624617024a100c35550a332eb47ec126 Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Mon, 24 Feb 2025 13:30:31 +0400 Subject: [PATCH 3/7] Refactor texture customisation, and add debris customisation --- Code/Entities/ThrowBox.cs | 52 ++++++++++++++++++------ Code/Entities/ThrowBoxSpawner.cs | 68 ++++++++++++++++++++++++-------- Loenn/entities/crate.lua | 56 +++++++++++++++++--------- Loenn/entities/crate_spawner.lua | 51 ++++++++++++++++-------- Loenn/lang/en_gb.lang | 4 +- 5 files changed, 165 insertions(+), 66 deletions(-) diff --git a/Code/Entities/ThrowBox.cs b/Code/Entities/ThrowBox.cs index ec201f0..ccdff83 100644 --- a/Code/Entities/ThrowBox.cs +++ b/Code/Entities/ThrowBox.cs @@ -41,6 +41,7 @@ public class ThrowBox : Actor { private readonly TransitionListener _transitionListener; private readonly bool _canPassThroughSpinners; private readonly ParticleType _p_Impact; + private readonly char _debrisTypeOverride; private Vector2 _prevLiftSpeed; private Level _level; @@ -57,8 +58,8 @@ public class ThrowBox : Actor { private BirdTutorialGui _tutorialPutDown; private bool _isCrucial; - public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSpecial = false, bool isCrucial = false, - bool canPassThroughSpinners = false, string textureDirectory = "", bool overrideParticles = false, Color impactParticlesColor = default) + public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSpecial = false, bool isCrucial = false, bool canPassThroughSpinners = false, + string crateTextureOverride = null, string crucialTextureOverride = null, ParticleType impactParticlesOverride = null, char debrisTypeOverride = '\0') : base(position) { Position -= DISPLACEMENT; _starterPosition = Position; @@ -67,18 +68,22 @@ public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSp _isMetal = isMetal; IsSpecial = isSpecial; _isCrucial = isCrucial; - _canPassThroughSpinners = canPassThroughSpinners; _tutorial = tutorial; + _canPassThroughSpinners = canPassThroughSpinners; - textureDirectory = textureDirectory.Trim().TrimEnd('/'); - string textureDir = string.IsNullOrEmpty(textureDirectory) ? "objects/FactoryHelper/crate" : textureDirectory; - string pathString = isMetal ? "crate_metal0" : "crate0"; - - Add(_image = new Image(GFX.Game[$"{textureDir}/{pathString}"])); + string crateTexture; + if (string.IsNullOrEmpty(crateTextureOverride)) { + string pathString = isMetal ? "crate_metal0" : "crate0"; + crateTexture = $"objects/FactoryHelper/crate/{pathString}"; + } else { + crateTexture = crateTextureOverride; + } + Add(_image = new Image(GFX.Game[crateTexture])); _image.Position += DISPLACEMENT; if (_isCrucial) { - Add(_warningImage = new Image(GFX.Game[$"{textureDir}/crucial"])); + string crucialTexture = string.IsNullOrEmpty(crucialTextureOverride) ? "objects/FactoryHelper/crate/crucial" : crucialTextureOverride; + Add(_warningImage = new Image(GFX.Game[crucialTexture])); _warningImage.Position += DISPLACEMENT; } @@ -106,15 +111,34 @@ public ThrowBox(Vector2 position, bool isMetal, bool tutorial = false, bool isSp Add(new LightOcclude(0.2f)); Add(new MirrorReflection()); - _p_Impact = overrideParticles ? new(P_Impact) { Color = impactParticlesColor } : P_Impact; + _p_Impact = impactParticlesOverride ?? P_Impact; + _debrisTypeOverride = debrisTypeOverride; } public ThrowBox(EntityData data, Vector2 offset) - : this(data.Position + offset, data.Bool("isMetal", false), data.Bool("tutorial", false), data.Bool("isSpecial", false), data.Bool("isCrucial", false), - data.Bool("canPassThroughSpinners", false), data.Attr("textureDirectory", ""), data.Bool("overrideParticles", false), data.HexColor("impactParticlesColor", default)) { + : this(data.Position + offset, data.Bool("isMetal", false), data.Bool("tutorial", false), data.Bool("isSpecial", false), data.Bool("isCrucial", false), data.Bool("canPassThroughSpinners", false), + GetCrateTextureOverride(data), GetCrucialTextureOverride(data), GetImpactParticlesOverride(data), GetDebrisTypeOverride(data)) { _levelName = data.Level.Name; } + private static string GetCrateTextureOverride(EntityData data) { + return data.Bool("overrideTextures", false) ? data.Attr("crateTexturePath") : null; + } + + private static string GetCrucialTextureOverride(EntityData data) { + return data.Bool("overrideTextures", false) ? data.Attr("crucialTexturePath") : null; + } + + private static ParticleType GetImpactParticlesOverride(EntityData data) { + return data.Bool("overrideParticles", false) ? new ParticleType(P_Impact) { + Color = data.HexColor("impactParticlesColor") + } : null; + } + + private static char GetDebrisTypeOverride(EntityData data) { + return data.Bool("overrideDebris", false) ? data.Char("debrisFromTiletype") : '\0'; + } + private void OnSteamWall(SteamWall steamWall) { Shatter(); } @@ -445,7 +469,9 @@ private void Shatter() { for (int i = 0; i < Width / 8f; i++) { for (int j = 0; j < Height / 8f; j++) { - if (_isMetal) { + if (_debrisTypeOverride != '\0') { + Scene.Add(Engine.Pooler.Create().Init(Position + new Vector2(4 + (i * 8), 4 + (j * 8)) + DISPLACEMENT, _debrisTypeOverride, false).BlastFrom(Center)); + } else if (_isMetal) { Scene.Add(Engine.Pooler.Create().Init(Position + new Vector2(4 + (i * 8), 4 + (j * 8)) + DISPLACEMENT, '8', false).BlastFrom(Center)); } else { Scene.Add(Engine.Pooler.Create().Init(Position + new Vector2(4 + (i * 8), 4 + (j * 8)) + DISPLACEMENT, '9', false).BlastFrom(Center)); diff --git a/Code/Entities/ThrowBoxSpawner.cs b/Code/Entities/ThrowBoxSpawner.cs index 89e5457..0bad080 100644 --- a/Code/Entities/ThrowBoxSpawner.cs +++ b/Code/Entities/ThrowBoxSpawner.cs @@ -19,14 +19,16 @@ public class ThrowBoxSpawner : Entity { private readonly HashSet _boxes = new(); private readonly bool _fromTop; private readonly bool _tutorial; - private readonly bool _canPassThroughSpinners; - private readonly string _textureDirectory; - private readonly bool _overrideParticles; - private readonly Color _impactParticlesColor; - public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activationId, bool isMetal, bool isRandom, bool fromTop, bool tutorial, bool startActive, - bool canPassThroughSpinners = false, string textureDirectory = "", bool overrideParticles = false, Color impactParticlesColor = default) + private readonly string _woodenCrateTextureOverride; + private readonly string _metalCrateTextureOverride; + private readonly ParticleType _impactParticlesOverride; + private readonly char _woodenDebrisTypeOverride; + private readonly char _metalDebrisTypeOverride; + + public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activationId, bool isMetal, bool isRandom, bool fromTop, bool tutorial, bool startActive, bool canPassThroughSpinners = false, + string woodenCrateTextureOverride = null, string metalCrateTextureOverride = null, ParticleType impactParticlesOverride = null, char woodenDebrisTypeOverride = '\0', char metalDebrisTypeOverride = '\0') : base(position) { Add(Activator = new FactoryActivator()); Activator.ActivationId = activationId == string.Empty ? null : activationId; @@ -40,11 +42,13 @@ public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activa _isRandom = isRandom; _fromTop = fromTop; _tutorial = tutorial; - _canPassThroughSpinners = canPassThroughSpinners; - _textureDirectory = textureDirectory; - _overrideParticles = overrideParticles; - _impactParticlesColor = impactParticlesColor; + + _woodenCrateTextureOverride = woodenCrateTextureOverride; + _metalCrateTextureOverride = metalCrateTextureOverride; + _impactParticlesOverride = impactParticlesOverride; + _woodenDebrisTypeOverride = woodenDebrisTypeOverride; + _metalDebrisTypeOverride = metalDebrisTypeOverride; Add(new Coroutine(SpawnSequence())); Add(new SteamCollider(OnSteamWall)); @@ -52,8 +56,30 @@ public ThrowBoxSpawner(Vector2 position, float delay, int maximum, string activa public ThrowBoxSpawner(EntityData data, Vector2 offset) : this(data.Position + offset, data.Float("delay", 5f), data.Int("maximum", 0), data.Attr("activationId"), data.Bool("isMetal", false), - data.Bool("isRandom", false), data.Bool("fromTop", true), data.Bool("tutorial", false), data.Bool("startActive", true), - data.Bool("canPassThroughSpinners", false), data.Attr("textureDirectory", ""), data.Bool("overrideParticles", false), data.HexColor("impactParticlesColor", default)) { + data.Bool("isRandom", false), data.Bool("fromTop", true), data.Bool("tutorial", false), data.Bool("startActive", true), data.Bool("canPassThroughSpinners", false), + GetWoodenCrateTextureOverride(data), GetMetalCrateTextureOverride(data), GetImpactParticlesOverride(data), GetWoodenDebrisTypeOverride(data), GetMetalDebrisTypeOverride(data)) { + } + + private static string GetWoodenCrateTextureOverride(EntityData data) { + return data.Bool("overrideTextures", false) ? data.Attr("woodenCrateTexturePath") : null; + } + + private static string GetMetalCrateTextureOverride(EntityData data) { + return data.Bool("overrideTextures", false) ? data.Attr("metalCrateTexturePath") : null; + } + + private static ParticleType GetImpactParticlesOverride(EntityData data) { + return data.Bool("overrideParticles", false) ? new ParticleType(ThrowBox.P_Impact) { + Color = data.HexColor("impactParticlesColor") + } : null; + } + + private static char GetWoodenDebrisTypeOverride(EntityData data) { + return data.Bool("overrideDebris", false) ? data.Char("woodenDebrisFromTiletype") : '\0'; + } + + private static char GetMetalDebrisTypeOverride(EntityData data) { + return data.Bool("overrideDebris", false) ? data.Char("metalDebrisFromTiletype") : '\0'; } private void OnSteamWall(SteamWall steamWall) { @@ -80,14 +106,24 @@ private void TrySpawnThrowBox() { if (_maximum <= 0 || _boxes.Count < _maximum) { float posY = _fromTop ? SceneAs().Bounds.Top - 15 : Position.Y; float posX = _fromTop ? Position.X : GetClosestPositionH(); + bool isMetal = _isRandom ? Calc.Random.Chance(0.5f) : _isMetal; + string crateTextureOverride; + char debrisTypeOverride; + if (isMetal) { + crateTextureOverride = _metalCrateTextureOverride; + debrisTypeOverride = _metalDebrisTypeOverride; + } else { + crateTextureOverride = _woodenCrateTextureOverride; + debrisTypeOverride = _woodenDebrisTypeOverride; + } ThrowBox crate = new( position: new Vector2(posX, posY), - isMetal: _isRandom ? Calc.Random.Chance(0.5f) : _isMetal, + isMetal: isMetal, tutorial: _tutorial, canPassThroughSpinners: _canPassThroughSpinners, - textureDirectory: _textureDirectory, - overrideParticles: _overrideParticles, - impactParticlesColor: _impactParticlesColor + crateTextureOverride: crateTextureOverride, + impactParticlesOverride: _impactParticlesOverride, + debrisTypeOverride: debrisTypeOverride ); Scene.Add(crate); _boxes.Add(crate); diff --git a/Loenn/entities/crate.lua b/Loenn/entities/crate.lua index 1b46679..55c1167 100644 --- a/Loenn/entities/crate.lua +++ b/Loenn/entities/crate.lua @@ -1,14 +1,21 @@ local drawableSprite = require("structs.drawable_sprite") +local fakeTilesHelper = require("helpers.fake_tiles") local crate = {} crate.name = "FactoryHelper/ThrowBox" -crate.fieldInformation = { - impactParticlesColor = { - fieldType = "color" +crate.fieldInformation = function() + return { + impactParticlesColor = { + fieldType = "color" + }, + debrisFromTiletype = { + options = fakeTilesHelper.getTilesOptions(), + editable = false + } } -} +end crate.placements = { { @@ -19,9 +26,13 @@ crate.placements = { isSpecial = false, isCrucial = false, canPassThroughSpinners = false, - textureDirectory = "objects/FactoryHelper/crate", + overrideTextures = false, + crateTexturePath = "objects/FactoryHelper/crate/crate0", + crucialTexturePath = "objects/FactoryHelper/crate/crucial", overrideParticles = false, - impactParticlesColor = "9c8d7b" + impactParticlesColor = "9c8d7b", + overrideDebris = false, + debrisFromTiletype = '9' } }, { @@ -32,29 +43,36 @@ crate.placements = { isSpecial = false, isCrucial = false, canPassThroughSpinners = false, - textureDirectory = "objects/FactoryHelper/crate", + overrideTextures = false, + crateTexturePath = "objects/FactoryHelper/crate/crate_metal0", + crucialTexturePath = "objects/FactoryHelper/crate/crucial", overrideParticles = false, - impactParticlesColor = "9c8d7b" + impactParticlesColor = "9c8d7b", + overrideDebris = false, + debrisFromTiletype = '8' } } } ---[[function crate.texture(sprite, entity) - return entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0" -end]] - function crate.sprite(room, entity) local sprites = {} - local textureDirData = entity.textureDirectory - local textureDir = (textureDirData == nil or textureDirData == "") and "objects/FactoryHelper/crate" or textureDirData + if (entity.overrideTextures) then + local crateSprite = entity.crateTexturePath or "" + table.insert(sprites, drawableSprite.fromTexture(crateSprite, entity)) - local texture = textureDir .. (entity.isMetal and "/crate_metal0" or "/crate0") - table.insert(sprites, drawableSprite.fromTexture(texture, entity)) + if (entity.isCrucial) then + local crucialTexture = entity.crucialTexturePath or "" + table.insert(sprites, drawableSprite.fromTexture(crucialTexture, entity)) + end + else + local crateSprite = entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0" + table.insert(sprites, drawableSprite.fromTexture(crateSprite, entity)) - if (entity.isCrucial) then - local crucialTexture = textureDir .. "/crucial" - table.insert(sprites, drawableSprite.fromTexture(crucialTexture, entity)) + if (entity.isCrucial) then + local crucialTexture = "objects/FactoryHelper/crate/crucial" + table.insert(sprites, drawableSprite.fromTexture(crucialTexture, entity)) + end end return sprites diff --git a/Loenn/entities/crate_spawner.lua b/Loenn/entities/crate_spawner.lua index 94bc47c..e8f8bff 100644 --- a/Loenn/entities/crate_spawner.lua +++ b/Loenn/entities/crate_spawner.lua @@ -1,22 +1,33 @@ local drawableRectangle = require("structs.drawable_rectangle") local drawableSprite = require("structs.drawable_sprite") +local fakeTilesHelper = require("helpers.fake_tiles") local crateSpawner = {} crateSpawner.name = "FactoryHelper/ThrowBoxSpawner" -crateSpawner.fieldInformation = { - delay = { - minimumValue = 0.0 - }, - maximum = { - fieldType = "integer", - minimumValue = 0 - }, - impactParticlesColor = { - fieldType = "color" +crateSpawner.fieldInformation = function() + return { + delay = { + minimumValue = 0.0 + }, + maximum = { + fieldType = "integer", + minimumValue = 0 + }, + impactParticlesColor = { + fieldType = "color" + }, + debrisFromTiletype = { + options = fakeTilesHelper.getTilesOptions(), + editable = false + }, + metalDebrisFromTiletype = { + options = fakeTilesHelper.getTilesOptions(), + editable = false + } } -} +end crateSpawner.placements = { { @@ -31,9 +42,14 @@ crateSpawner.placements = { tutorial = false, startActive = true, canPassThroughSpinners = false, - textureDirectory = "objects/FactoryHelper/crate", + overrideTextures = false, + woodenCrateTexturePath = "objects/FactoryHelper/crate/crate0", + metalCrateTexturePath = "objects/FactoryHelper/crate/crate_metal0", overrideParticles = false, - impactParticlesColor = "9c8d7b" + impactParticlesColor = "9c8d7b", + overrideDebris = false, + woodenDebrisFromTiletype = '9', + metalDebrisFromTiletype = '8' } } } @@ -44,10 +60,13 @@ local randomColor = {1.0, 0.5, 1.0, 0.2} function crateSpawner.sprite(room, entity) local sprites = {} - local textureDirData = entity.textureDirectory - local textureDir = (textureDirData == nil or textureDirData == "") and "objects/FactoryHelper/crate" or textureDirData + local texture = "" + if (entity.overrideTextures) then + texture = entity.isMetal and (entity.metalCrateTexturePath or "") or (entity.woodenCrateTexturePath or "") + else + texture = entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0" + end - local texture = textureDir .. (entity.isMetal and "/crate_metal0" or "/crate0") local crateSprite = drawableSprite.fromTexture(texture, entity) crateSprite.color = {1.0, 1.0, 1.0, 0.5} diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index 9b37a91..4ad53ce 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -34,7 +34,7 @@ entities.FactoryHelper/ThrowBox.attributes.description.tutorial=Whether the tuto entities.FactoryHelper/ThrowBox.attributes.description.isSpecial=Whether the crate should kill the player and return them to the crate's origin upon destruction or player death. entities.FactoryHelper/ThrowBox.attributes.description.isCrucial=Whether the crate should kill the player upon destruction. entities.FactoryHelper/ThrowBox.attributes.description.canPassThroughSpinners=Whether the crate should not break in collision with Spinners. -entities.FactoryHelper/ThrowBox.attributes.description.textureDirectory=Which directory in the Gameplay atlas that the crate should use for its textures.\nIf changed, the directory should be a copy of the default "objects/FactoryHelper/crate", containing the following textures:\n- "crate0" for wooden crates\n- "crate_metal0" for metal crates\n- "crucial" for the frame added if `Is Crucial` is `true` + entities.FactoryHelper/ThrowBox.attributes.description.overrideParticles=If `true`, a new impact particle type will be created for the crate.\nThis is required in order to modify the color of the particles. entities.FactoryHelper/ThrowBox.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when the crate hits a solid. Default value: "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. @@ -49,7 +49,7 @@ entities.FactoryHelper/ThrowBoxSpawner.attributes.description.fromTop=If `true` entities.FactoryHelper/ThrowBoxSpawner.attributes.description.tutorial=Whether the tutorial messsages should show up. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.maximum=The maximum number of crate this spawner can spawn. Destroyed crates do not count towards the maximum. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.canPassThroughSpinners=Whether the spawned crates should not break in collision with Spinners. -entities.FactoryHelper/ThrowBoxSpawner.attributes.description.textureDirectory=Which directory in the Gameplay atlas that spawned crates should use for their textures.\nIf changed, the directory should be a copy of the default "objects/FactoryHelper/crate", containing the following textures:\n- "crate0" for wooden crates\n- "crate_metal0" for metal crates\n- "crucial" for the frame added if `Is Crucial` is `true` + entities.FactoryHelper/ThrowBoxSpawner.attributes.description.overrideParticles=If `true`, a new impact particle type will be created for spawned crates.\nThis is required in order to modify the color of the particles. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when spawned crates hit a solid. Default value: "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. From ceff4635a0296c136d6de337aa096f8ada5a6da2 Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:57:20 +0400 Subject: [PATCH 4/7] Fix sprite justification --- Loenn/entities/crate.lua | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Loenn/entities/crate.lua b/Loenn/entities/crate.lua index 55c1167..1e906ab 100644 --- a/Loenn/entities/crate.lua +++ b/Loenn/entities/crate.lua @@ -54,30 +54,34 @@ crate.placements = { } } +local justification = {0.0, 0.0} + function crate.sprite(room, entity) local sprites = {} if (entity.overrideTextures) then - local crateSprite = entity.crateTexturePath or "" - table.insert(sprites, drawableSprite.fromTexture(crateSprite, entity)) + local crateSprite = drawableSprite.fromTexture(entity.crateTexturePath or "", entity) + crateSprite:setJustification(justification) + table.insert(sprites, crateSprite) if (entity.isCrucial) then - local crucialTexture = entity.crucialTexturePath or "" - table.insert(sprites, drawableSprite.fromTexture(crucialTexture, entity)) + local crucialSprite = drawableSprite.fromTexture(entity.crucialTexturePath or "", entity) + crucialSprite:setJustification(justification) + table.insert(sprites, crucialSprite) end else - local crateSprite = entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0" - table.insert(sprites, drawableSprite.fromTexture(crateSprite, entity)) + local crateSprite = drawableSprite.fromTexture(entity.isMetal and "objects/FactoryHelper/crate/crate_metal0" or "objects/FactoryHelper/crate/crate0", entity) + crateSprite:setJustification(justification) + table.insert(sprites, crateSprite) if (entity.isCrucial) then - local crucialTexture = "objects/FactoryHelper/crate/crucial" - table.insert(sprites, drawableSprite.fromTexture(crucialTexture, entity)) + local crucialSprite = drawableSprite.fromTexture("objects/FactoryHelper/crate/crucial", entity) + crucialSprite:setJustification(justification) + table.insert(sprites, crucialSprite) end end return sprites end -crate.justification = {0.0, 0.0} - return crate From 56bfcfbc61dc2851432c7cc9be6ea27c3ea9f07e Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:59:46 +0400 Subject: [PATCH 5/7] Update lang file --- Loenn/lang/en_gb.lang | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index 4ad53ce..6433f8f 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -34,9 +34,13 @@ entities.FactoryHelper/ThrowBox.attributes.description.tutorial=Whether the tuto entities.FactoryHelper/ThrowBox.attributes.description.isSpecial=Whether the crate should kill the player and return them to the crate's origin upon destruction or player death. entities.FactoryHelper/ThrowBox.attributes.description.isCrucial=Whether the crate should kill the player upon destruction. entities.FactoryHelper/ThrowBox.attributes.description.canPassThroughSpinners=Whether the crate should not break in collision with Spinners. - -entities.FactoryHelper/ThrowBox.attributes.description.overrideParticles=If `true`, a new impact particle type will be created for the crate.\nThis is required in order to modify the color of the particles. -entities.FactoryHelper/ThrowBox.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when the crate hits a solid. Default value: "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. +entities.FactoryHelper/ThrowBox.attributes.description.overrideTextures=Whether to use custom texture paths instead of the default ones, regardless of the type of the crate. +entities.FactoryHelper/ThrowBox.attributes.description.crateTexturePath=What texture to use for the crate.\nDefault value is "objects/FactoryHelper/crate/crate0" if wooden, or "objects/FactoryHelper/crate/crate_metal0" if metal.\nChanging this has no effect if `Override Textures` is `false`. +entities.FactoryHelper/ThrowBox.attributes.description.crucialTexturePath=What texture to add to the crate if `Is Crucial` is `true`.\nDefault value is "objects/FactoryHelper/crate/crucial".\nChanging this has no effect if `Override Textures` is `false`. +entities.FactoryHelper/ThrowBox.attributes.description.overrideParticles=Whether to create a new impact particle type for the crate, to be used instead of the default. +entities.FactoryHelper/ThrowBox.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when the crate hits a solid. Default value is "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. +entities.FactoryHelper/ThrowBox.attributes.description.overrideDebris=Whether to use a different type of debris that will appear when the crate breaks regardless of its type. +entities.FactoryHelper/ThrowBox.attributes.description.debrisFromTiletype=From which tiletype to use the debris that will appear when the crate breaks.\nDefault value is '9' (Wood) if wooden, or '8' (Rock) if metal.\nChanging this has no effect if `Override Debris` is `false`.\nYou can create new debris types by adding the `debris` attribute to modded tilesets in your `ForegroundTiles.xml`.\nSee https://github.com/EverestAPI/Resources/wiki/Custom-Tilesets#adding-custom-debris for details. # Crate Spawner entities.FactoryHelper/ThrowBoxSpawner.placements.name.crate_spawner=Crate Spawner @@ -49,9 +53,14 @@ entities.FactoryHelper/ThrowBoxSpawner.attributes.description.fromTop=If `true` entities.FactoryHelper/ThrowBoxSpawner.attributes.description.tutorial=Whether the tutorial messsages should show up. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.maximum=The maximum number of crate this spawner can spawn. Destroyed crates do not count towards the maximum. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.canPassThroughSpinners=Whether the spawned crates should not break in collision with Spinners. - -entities.FactoryHelper/ThrowBoxSpawner.attributes.description.overrideParticles=If `true`, a new impact particle type will be created for spawned crates.\nThis is required in order to modify the color of the particles. -entities.FactoryHelper/ThrowBoxSpawner.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when spawned crates hit a solid. Default value: "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.overrideTextures=Whether to use custom texture paths instead of the default ones for spawned crates depending on their type. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.woodenCrateTexturePath=What texture to use for spawned crates if they are wooden.\nDefault value is "objects/FactoryHelper/crate/crate0".\nChanging this has no effect if `Override Textures` is `false`. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.metalCrateTexturePath=What texture to use for spawned crates if they are metal.\nDefault value is "objects/FactoryHelper/crate/crate_metal0".\nChanging this has no effect if `Override Textures` is `false`. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.overrideParticles=Whether to create a new impact particle type for spawned crates, to be used instead of the default. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.impactParticlesColor=The color in hexadecimal for the particles emitted when spawned crates hit a solid. Default value is "9c8d7b".\nChanging this has no effect if `Override Particles` is `false`. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.overrideDebris=Whether to use a different type of debris that will appear when spawned crates break depending on their type. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.woodenDebrisFromTiletype=From which tiletype to use the debris that will appear when spawned crates break if they are wooden.\nDefault value is '9' (Wood).\nChanging this has no effect if `Override Debris` is `false`.\nYou can create new debris types by adding the `debris` attribute to modded tilesets in your `ForegroundTiles.xml`.\nSee https://github.com/EverestAPI/Resources/wiki/Custom-Tilesets#adding-custom-debris for details. +entities.FactoryHelper/ThrowBoxSpawner.attributes.description.metalDebrisFromTiletype=From which tiletype to use the debris that will appear when spawned crates break if they are metal.\nDefault value is '8' (Rock).\nChanging this has no effect if `Override Debris` is `false`.\nYou can create new debris types by adding the `debris` attribute to modded tilesets in your `ForegroundTiles.xml`.\nSee https://github.com/EverestAPI/Resources/wiki/Custom-Tilesets#adding-custom-debris for details. # Dash Fuse Box entities.FactoryHelper/DashFuseBox.placements.name.left=Dash Fuse Box (Left) From c3d098e17be3530092330015c7e9c1e5111ac4fc Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:23:58 +0400 Subject: [PATCH 6/7] Unload hooks on Unload --- Code/FactoryHelperHooks.cs | 12 ++++++++++++ Code/FactoryHelperModule.cs | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Code/FactoryHelperHooks.cs b/Code/FactoryHelperHooks.cs index 34ba0ae..06f9be6 100644 --- a/Code/FactoryHelperHooks.cs +++ b/Code/FactoryHelperHooks.cs @@ -20,6 +20,18 @@ public static void Load() { On.Celeste.DashBlock.RemoveAndFlagAsGone += DashBlockRemoveAndFlagAsGone; } + public static void Unload() { + On.Celeste.Player.ctor -= ctor; + On.Celeste.Level.LoadLevel -= LoadLevel; + On.Celeste.Player.Die -= PlayerDie; + On.Celeste.LevelExit.Routine -= RespawnRoutine; + On.Celeste.Player.Pickup -= Pickup; + On.Celeste.Lookout.LookRoutine -= LookRoutine; + On.Celeste.LevelEnter.Go -= LevelEnterGo; + On.Celeste.DashBlock.Break_Vector2_Vector2_bool_bool -= DashBlockBreak; + On.Celeste.DashBlock.RemoveAndFlagAsGone -= DashBlockRemoveAndFlagAsGone; + } + private static void DashBlockRemoveAndFlagAsGone(On.Celeste.DashBlock.orig_RemoveAndFlagAsGone orig, DashBlock self) { if (self is FactoryActivatorDashBlock) { self.RemoveSelf(); diff --git a/Code/FactoryHelperModule.cs b/Code/FactoryHelperModule.cs index b1dca14..059292f 100644 --- a/Code/FactoryHelperModule.cs +++ b/Code/FactoryHelperModule.cs @@ -28,6 +28,8 @@ public override void Load() { FactoryHelperHooks.Load(); } - public override void Unload() { } + public override void Unload() { + FactoryHelperHooks.Unload(); + } } } From 0883a9635d059030b898ec14103ad8b0115b6f69 Mon Sep 17 00:00:00 2001 From: SilverDorian46 <86711559+SilverDorian46@users.noreply.github.com> Date: Sun, 2 Mar 2025 22:08:09 +0400 Subject: [PATCH 7/7] Separate normal and reskinnable placements --- Loenn/entities/crate.lua | 26 +++++++++++++++++++++++--- Loenn/entities/crate_spawner.lua | 16 +++++++++++++++- Loenn/lang/en_gb.lang | 3 +++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Loenn/entities/crate.lua b/Loenn/entities/crate.lua index 1e906ab..0227fb6 100644 --- a/Loenn/entities/crate.lua +++ b/Loenn/entities/crate.lua @@ -20,13 +20,33 @@ end crate.placements = { { name = "wood", + data = { + isMetal = false, + tutorial = false, + isSpecial = false, + isCrucial = false, + canPassThroughSpinners = false + } + }, + { + name = "metal", + data = { + isMetal = true, + tutorial = false, + isSpecial = false, + isCrucial = false, + canPassThroughSpinners = false + } + }, + { + name = "reskin_wood", data = { isMetal = false, tutorial = false, isSpecial = false, isCrucial = false, canPassThroughSpinners = false, - overrideTextures = false, + overrideTextures = true, crateTexturePath = "objects/FactoryHelper/crate/crate0", crucialTexturePath = "objects/FactoryHelper/crate/crucial", overrideParticles = false, @@ -36,14 +56,14 @@ crate.placements = { } }, { - name = "metal", + name = "reskin_metal", data = { isMetal = true, tutorial = false, isSpecial = false, isCrucial = false, canPassThroughSpinners = false, - overrideTextures = false, + overrideTextures = true, crateTexturePath = "objects/FactoryHelper/crate/crate_metal0", crucialTexturePath = "objects/FactoryHelper/crate/crucial", overrideParticles = false, diff --git a/Loenn/entities/crate_spawner.lua b/Loenn/entities/crate_spawner.lua index e8f8bff..07a74e7 100644 --- a/Loenn/entities/crate_spawner.lua +++ b/Loenn/entities/crate_spawner.lua @@ -32,6 +32,20 @@ end crateSpawner.placements = { { name = "crate_spawner", + data = { + delay = 1.0, + maximum = 0, + activationId = "", + isMetal = false, + isRandom = false, + fromTop = true, + tutorial = false, + startActive = true, + canPassThroughSpinners = false + } + }, + { + name = "crate_spawner_reskin", data = { delay = 1.0, maximum = 0, @@ -42,7 +56,7 @@ crateSpawner.placements = { tutorial = false, startActive = true, canPassThroughSpinners = false, - overrideTextures = false, + overrideTextures = true, woodenCrateTexturePath = "objects/FactoryHelper/crate/crate0", metalCrateTexturePath = "objects/FactoryHelper/crate/crate_metal0", overrideParticles = false, diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index 6433f8f..dca5d0e 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -29,6 +29,8 @@ entities.FactoryHelper/Conveyor.attributes.description.startLeft=If `true` the c # Crate entities.FactoryHelper/ThrowBox.placements.name.wood=Crate (Wood) entities.FactoryHelper/ThrowBox.placements.name.metal=Crate (Metal) +entities.FactoryHelper/ThrowBox.placements.name.reskin_wood=Crate (Reskinnable, Wood) +entities.FactoryHelper/ThrowBox.placements.name.reskin_metal=Crate (Reskinnable, Metal) entities.FactoryHelper/ThrowBox.attributes.description.isMetal=Whether the crate is metallic or not. If `false` it will be wooden.\nWooden crates will break on high-speed impacts. entities.FactoryHelper/ThrowBox.attributes.description.tutorial=Whether the tutorial messsages should show up. entities.FactoryHelper/ThrowBox.attributes.description.isSpecial=Whether the crate should kill the player and return them to the crate's origin upon destruction or player death. @@ -44,6 +46,7 @@ entities.FactoryHelper/ThrowBox.attributes.description.debrisFromTiletype=From w # Crate Spawner entities.FactoryHelper/ThrowBoxSpawner.placements.name.crate_spawner=Crate Spawner +entities.FactoryHelper/ThrowBoxSpawner.placements.name.crate_spawner_reskin=Crate Spawner (Reskinnable) entities.FactoryHelper/ThrowBoxSpawner.attributes.description.activationId=String value of the entity's activator ID. When a factory activator with this ID is turned on, the entity will toggle state. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.startActive=If `true` the entity will initially be active. entities.FactoryHelper/ThrowBoxSpawner.attributes.description.delay=The amount of time before a new crate is spawned after the previous one in seconds.