diff --git a/Ahorn/lang/en_gb.lang b/Ahorn/lang/en_gb.lang index 8e45fab..374a55c 100644 --- a/Ahorn/lang/en_gb.lang +++ b/Ahorn/lang/en_gb.lang @@ -273,3 +273,6 @@ placements.entities.SpringCollab2020/SeekerStatueCustomColors.tooltips.trailColo # Custom Respawn Time Refill placements.entities.SpringCollab2020/CustomRespawnTimeRefill.tooltips.twoDash=Whether the refill should give two dashes. placements.entities.SpringCollab2020/CustomRespawnTimeRefill.tooltips.respawnTime=The delay (in seconds) before the refill respawns after being collected. + +# Camera Catchup Speed Trigger +placements.triggers.SpringCollab2020/CameraCatchupSpeedTrigger.tooltips.catchupSpeed=Raise this value to have the camera scroll quicker to its target. Vanilla values are 8 during the temple fall cutscene, and 1 everywhere else. diff --git a/Ahorn/triggers/cameraCatchupSpeed.jl b/Ahorn/triggers/cameraCatchupSpeed.jl new file mode 100644 index 0000000..1b343b1 --- /dev/null +++ b/Ahorn/triggers/cameraCatchupSpeed.jl @@ -0,0 +1,15 @@ +module SpringCollab2020CameraCatchupSpeedTrigger + +using ..Ahorn, Maple + +@mapdef Trigger "SpringCollab2020/CameraCatchupSpeedTrigger" CameraCatchupSpeedTrigger(x::Integer, y::Integer, width::Integer=Maple.defaultTriggerWidth, height::Integer=Maple.defaultTriggerHeight, + catchupSpeed::Number=1.0) + +const placements = Ahorn.PlacementDict( + "Camera Catchup Speed (Spring Collab 2020)" => Ahorn.EntityPlacement( + CameraCatchupSpeedTrigger, + "rectangle" + ) +) + +end diff --git a/SpringCollab2020Module.cs b/SpringCollab2020Module.cs index 3c7de53..3610489 100644 --- a/SpringCollab2020Module.cs +++ b/SpringCollab2020Module.cs @@ -32,6 +32,7 @@ public override void Load() { BlockJellySpawnTrigger.Load(); StrawberryIgnoringLighting.Load(); SeekerCustomColors.Load(); + CameraCatchupSpeedTrigger.Load(); } public override void LoadContent(bool firstLoad) { @@ -59,6 +60,7 @@ public override void Unload() { BlockJellySpawnTrigger.Unload(); StrawberryIgnoringLighting.Unload(); SeekerCustomColors.Unload(); + CameraCatchupSpeedTrigger.Unload(); } public override void PrepareMapDataProcessors(MapDataFixup context) { diff --git a/Triggers/CameraCatchupSpeedTrigger.cs b/Triggers/CameraCatchupSpeedTrigger.cs new file mode 100644 index 0000000..e7300c6 --- /dev/null +++ b/Triggers/CameraCatchupSpeedTrigger.cs @@ -0,0 +1,56 @@ +using Celeste.Mod.Entities; +using Microsoft.Xna.Framework; +using Mono.Cecil.Cil; +using Monocle; +using MonoMod.Cil; +using MonoMod.RuntimeDetour; +using System; + +namespace Celeste.Mod.SpringCollab2020.Triggers { + [CustomEntity("SpringCollab2020/CameraCatchupSpeedTrigger")] + [Tracked] + class CameraCatchupSpeedTrigger : Trigger { + private static ILHook playerOrigUpdateHook; + + public static void Load() { + playerOrigUpdateHook = new ILHook(typeof(Player).GetMethod("orig_Update"), modPlayerOrigUpdate); + } + + public static void Unload() { + playerOrigUpdateHook?.Dispose(); + } + + private static void modPlayerOrigUpdate(ILContext il) { + ILCursor cursor = new ILCursor(il); + + // we're looking for: 1f - (float)Math.Pow(0.01f / num2, Engine.DeltaTime) + if (cursor.TryGotoNext( + instr => instr.MatchLdcR4(0.01f), + instr => instr.OpCode == OpCodes.Ldloc_S, + instr => instr.MatchDiv())) { + + // and we want to position the cursor just after loading num2 + cursor.Index += 2; + + Logger.Log("SpringCollab2020/CameraCatchupSpeedTrigger", $"Inserting code to mod camera catchup speed at {cursor.Index} in IL for Player.orig_Update()"); + + // this delegate will allow us to turn num2 into something else. + cursor.Emit(OpCodes.Ldarg_0); + cursor.EmitDelegate>((orig, self) => { + CameraCatchupSpeedTrigger trigger = self.CollideFirst(); + if (trigger != null) { + return trigger.catchupSpeed; + } + return orig; + }); + } + } + + + private float catchupSpeed; + + public CameraCatchupSpeedTrigger(EntityData data, Vector2 offset) : base(data, offset) { + catchupSpeed = data.Float("catchupSpeed", 1f); + } + } +}