|
1 | 1 | using Celeste.Mod.CommunalHelper.Components; |
| 2 | +using Celeste.Mod.CommunalHelper.Entities; |
2 | 3 | using Celeste.Mod.CommunalHelper.States; |
3 | 4 | using Mono.Cecil.Cil; |
4 | 5 | using MonoMod.Cil; |
5 | 6 | using MonoMod.RuntimeDetour; |
6 | 7 | using MonoMod.Utils; |
| 8 | +using System.Collections.Generic; |
7 | 9 | using System.Linq; |
8 | 10 | using System.Reflection; |
9 | 11 |
|
@@ -50,6 +52,8 @@ public static bool NextDashFeather |
50 | 52 | public static Color[] DreamTrailColors; |
51 | 53 | public static int DreamTrailColorIndex = 0; |
52 | 54 |
|
| 55 | + // Keep a List<Entity> around to not allocate a new one every CollideAll<T>() call |
| 56 | + private static List<Entity> dreamTunnelBlockers = new(); |
53 | 57 |
|
54 | 58 | private static IDetour hook_Player_DashCoroutine; |
55 | 59 | private static IDetour hook_Player_orig_Update; |
@@ -348,7 +352,14 @@ private static void Player_OnCollideV(ILContext il) { |
348 | 352 |
|
349 | 353 | private static bool Player_DreamDashCheck(On.Celeste.Player.orig_DreamDashCheck orig, Player self, Vector2 dir) |
350 | 354 | { |
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); |
352 | 363 | } |
353 | 364 |
|
354 | 365 | // Fixes bug with dreamSfx soundsource not being stopped |
@@ -659,6 +670,10 @@ private static bool DreamTunnelDashCheck(this Player player, Vector2 dir) |
659 | 670 | 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) |
660 | 671 | return false; |
661 | 672 |
|
| 673 | + // Check if we're colliding with a DreamTunnelBlocker |
| 674 | + if (player.IsDreamTunnelDashBlocked(player.Position + dir)) |
| 675 | + return false; |
| 676 | + |
662 | 677 | Solid solid = null; |
663 | 678 |
|
664 | 679 | // Check for dream blocks first, then for solids |
@@ -740,6 +755,37 @@ private static bool DreamTunnelDashCheck(this Player player, Vector2 dir) |
740 | 755 | return false; |
741 | 756 | } |
742 | 757 |
|
| 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 | + |
743 | 789 | #endregion |
744 | 790 |
|
745 | 791 | } |
0 commit comments