Skip to content

Commit aae6141

Browse files
authored
Merge pull request CommunalHelper#242 from SnipUndercover/dream-tunnel-blocker
Implement Dream Tunnel Blockers
2 parents c4a185d + 4922833 commit aae6141

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
local triggers = require("triggers")
2+
local depths = require("consts.object_depths")
3+
local drawableRectangle = require("structs.drawable_rectangle")
4+
local drawableText = require("structs.drawable_text")
5+
local colors = require("consts.colors")
6+
7+
local dreamTunnelBlocker = {}
8+
9+
dreamTunnelBlocker.name = "CommunalHelper/DreamTunnelBlocker"
10+
dreamTunnelBlocker.depth = depths.fakeWalls + 2000;
11+
12+
dreamTunnelBlocker.placements = {
13+
name = "normal",
14+
data = {
15+
width = 16,
16+
height = 16,
17+
blockDreamTunnelDashes = true,
18+
blockDreamDashes = false
19+
}
20+
}
21+
22+
-- adapted from triggers.getDrawable
23+
function dreamTunnelBlocker.sprite(room, entity)
24+
local displayName = triggers.triggerText(room, entity)
25+
26+
local x = entity.x or 0
27+
local y = entity.y or 0
28+
29+
local width = entity.width or 16
30+
local height = entity.height or 16
31+
32+
local borderedRectangle = drawableRectangle.fromRectangle("bordered", x, y, width, height, colors.triggerColor, colors.triggerBorderColor)
33+
local textDrawable = drawableText.fromText(displayName, x, y, width, height, nil, triggers.triggerFontSize, colors.triggerTextColor)
34+
35+
local drawables = borderedRectangle:getDrawableSprite()
36+
table.insert(drawables, textDrawable)
37+
38+
textDrawable.depth = dreamTunnelBlocker.depth - 1
39+
40+
return drawables
41+
end
42+
43+
return dreamTunnelBlocker

Loenn/lang/en_gb.lang

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,10 @@ entities.CommunalHelper/SJ/PelletEmitter.attributes.description.wiggleFrequency=
981981
entities.CommunalHelper/SJ/PelletEmitter.attributes.description.wiggleAmount=The amplitude of the wiggle. Defaults to 2. Set to 0 to disable wiggling, causing pellets to travel in a straight line.
982982
entities.CommunalHelper/SJ/PelletEmitter.attributes.description.wiggleHitbox=Whether or not the pellet hitbox should move following the wiggle.
983983

984+
entities.CommunalHelper/DreamTunnelBlocker.placements.name.normal=Dream Tunnel Blocker
985+
entities.CommunalHelper/DreamTunnelBlocker.attributes.description.blockDreamTunnelDashes=Whether to prevent dream tunneling when dashing into a solid covered by this entity.
986+
entities.CommunalHelper/DreamTunnelBlocker.attributes.description.blockDreamDashes=Whether to prevent dream dashing when dashing into a dream block covered by this entity.
987+
984988
# ---------------------- TRIGGERS --------------------------
985989

986990
# [Strawberry Jam] Show Hitbox Trigger

src/DashStates/DreamTunnelDash/DreamTunnelDash.cs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using Celeste.Mod.CommunalHelper.Components;
2+
using Celeste.Mod.CommunalHelper.Entities;
23
using Celeste.Mod.CommunalHelper.States;
34
using Mono.Cecil.Cil;
45
using MonoMod.Cil;
56
using MonoMod.RuntimeDetour;
67
using MonoMod.Utils;
8+
using System.Collections.Generic;
79
using System.Linq;
810
using System.Reflection;
911

@@ -50,6 +52,8 @@ public static bool NextDashFeather
5052
public static Color[] DreamTrailColors;
5153
public static int DreamTrailColorIndex = 0;
5254

55+
// Keep a List<Entity> around to not allocate a new one every CollideAll<T>() call
56+
private static List<Entity> dreamTunnelBlockers = new();
5357

5458
private static IDetour hook_Player_DashCoroutine;
5559
private static IDetour hook_Player_orig_Update;
@@ -348,7 +352,14 @@ private static void Player_OnCollideV(ILContext il) {
348352

349353
private static bool Player_DreamDashCheck(On.Celeste.Player.orig_DreamDashCheck orig, Player self, Vector2 dir)
350354
{
351-
return overrideDreamDashCheck ? (overrideDreamDashCheck = false) : orig(self, dir);
355+
if (overrideDreamDashCheck)
356+
return overrideDreamDashCheck = false;
357+
358+
// Don't enter StDreamDash if there's a blocker
359+
if (self.IsDreamDashBlocked(self.Position + dir))
360+
return false;
361+
362+
return orig(self, dir);
352363
}
353364

354365
// Fixes bug with dreamSfx soundsource not being stopped
@@ -659,6 +670,10 @@ private static bool DreamTunnelDashCheck(this Player player, Vector2 dir)
659670
if (player.Left + dir.X < bounds.Left || player.Right + dir.X > bounds.Right || player.Top + dir.Y < bounds.Top || player.Bottom + dir.Y > bounds.Bottom)
660671
return false;
661672

673+
// Check if we're colliding with a DreamTunnelBlocker
674+
if (player.IsDreamTunnelDashBlocked(player.Position + dir))
675+
return false;
676+
662677
Solid solid = null;
663678

664679
// Check for dream blocks first, then for solids
@@ -740,6 +755,37 @@ private static bool DreamTunnelDashCheck(this Player player, Vector2 dir)
740755
return false;
741756
}
742757

758+
private static (bool blockDreamTunnelDashes, bool blockDreamDashes) GetBlockerConfiguration(this Player player, Vector2 position)
759+
{
760+
bool blockDreamTunnelDashes = false;
761+
bool blockDreamDashes = false;
762+
763+
foreach (Entity e in player.CollideAll<DreamTunnelBlocker>(position, dreamTunnelBlockers))
764+
{
765+
if (e is DreamTunnelBlocker { BlockDreamTunnelDashes: true })
766+
blockDreamTunnelDashes = true;
767+
if (e is DreamTunnelBlocker { BlockDreamDashes: true })
768+
blockDreamDashes = true;
769+
770+
if (blockDreamTunnelDashes && blockDreamDashes)
771+
break;
772+
}
773+
774+
return (blockDreamTunnelDashes, blockDreamDashes);
775+
}
776+
777+
private static bool IsDreamTunnelDashBlocked(this Player player, Vector2 position)
778+
{
779+
return player.CollideAll<DreamTunnelBlocker>(position, dreamTunnelBlockers)
780+
.Any(e => e is DreamTunnelBlocker { BlockDreamTunnelDashes: true });
781+
}
782+
783+
private static bool IsDreamDashBlocked(this Player player, Vector2 position)
784+
{
785+
return player.CollideAll<DreamTunnelBlocker>(position, dreamTunnelBlockers)
786+
.Any(e => e is DreamTunnelBlocker { BlockDreamDashes: true });
787+
}
788+
743789
#endregion
744790

745791
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace Celeste.Mod.CommunalHelper.Entities;
2+
3+
[Tracked]
4+
[CustomEntity("CommunalHelper/DreamTunnelBlocker")]
5+
public class DreamTunnelBlocker : Entity
6+
{
7+
public bool BlockDreamTunnelDashes;
8+
public bool BlockDreamDashes;
9+
10+
/// Blocking behavior handled in <see cref="DashStates.DreamTunnelDash.DreamTunnelDashCheck" />
11+
/// and <see cref="DashStates.DreamTunnelDash.Player_DreamDashCheck"/>
12+
public DreamTunnelBlocker(EntityData data, Vector2 offset) : base(data.Position + offset)
13+
{
14+
Collider = new Hitbox(data.Width, data.Height);
15+
Depth = Depths.FakeWalls + 2000;
16+
17+
BlockDreamTunnelDashes = data.Bool("blockDreamTunnelDashes", true);
18+
BlockDreamDashes = data.Bool("blockDreamDashes", false);
19+
}
20+
}

0 commit comments

Comments
 (0)