From 346aa845c22ff32835cd335b9d02d1edbd8e6562 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Fri, 23 Feb 2018 04:28:38 -0700 Subject: [PATCH] zoom plugin: Add option to relax the camera's upper pitch limit. --- .../main/java/net/runelite/api/Client.java | 2 + .../client/plugins/zoom/ZoomConfig.java | 10 ++ .../client/plugins/zoom/ZoomPlugin.java | 19 +++ .../java/net/runelite/mixins/CameraMixin.java | 109 ++++++++++++++++++ .../java/net/runelite/rs/api/RSClient.java | 3 + 5 files changed, 143 insertions(+) create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/CameraMixin.java diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index af3e6d5aa2..9ea4aedb54 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -286,4 +286,6 @@ public interface Client extends GameEngine boolean isClanMember(String name); Preferences getPreferences(); + + void setCameraPitchRelaxerEnabled(boolean enabled); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java index 06f57e73d6..1d95abb316 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java @@ -54,4 +54,14 @@ public interface ZoomConfig extends Config { return false; } + + @ConfigItem( + keyName = "relaxCameraPitch", + name = "Vertical camera", + description = "Relax the camera's upper pitch limit" + ) + default boolean relaxCameraPitch() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java index e22ea3773e..8c47c09e29 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java @@ -30,6 +30,7 @@ import com.google.inject.Inject; import com.google.inject.Provides; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ScriptEvent; import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; @@ -107,4 +108,22 @@ public class ZoomPlugin extends Plugin } } } + + @Override + protected void startUp() + { + client.setCameraPitchRelaxerEnabled(zoomConfig.relaxCameraPitch()); + } + + @Override + protected void shutDown() + { + client.setCameraPitchRelaxerEnabled(false); + } + + @Subscribe + public void onConfigChanged(ConfigChanged ev) + { + client.setCameraPitchRelaxerEnabled(zoomConfig.relaxCameraPitch()); + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/CameraMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/CameraMixin.java new file mode 100644 index 0000000000..c3bf1df189 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/CameraMixin.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.mixins; + +import net.runelite.api.mixins.FieldHook; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClient; + +@Mixin(RSClient.class) +public abstract class CameraMixin implements RSClient +{ + private static final int STANDARD_PITCH_MAX = 383; + private static final int NEW_PITCH_MAX = 512; + + @Shadow("clientInstance") + static RSClient client; + + @Inject + static boolean pitchRelaxEnabled = false; + + @Shadow("visibilityMaps") + static boolean[][][][] visibilityMaps; + + @Inject + static int lastPitch = 128; + + static + { + // The first index is pitch. In the default client it is 9, here it is 13 because we increase the pitch limit + visibilityMaps = new boolean[13][35][53][53]; + for (boolean[][][] z : visibilityMaps) + { + for (boolean[][] y : z) + { + for (boolean[] x : y) + { + for (int i = 0; i < x.length; i++) + { + x[i] = true; + } + } + } + } + } + + @FieldHook("cameraPitch") + @Inject + static void onCameraPitchChanged(int idx) + { + int newPitch = client.getCameraPitch(); + int pitch = newPitch; + if (pitchRelaxEnabled) + { + // This works because the vanilla camera movement code only moves %2 + if (lastPitch > STANDARD_PITCH_MAX && newPitch == STANDARD_PITCH_MAX) + { + pitch = lastPitch; + if (pitch > NEW_PITCH_MAX) + { + pitch = NEW_PITCH_MAX; + } + client.setCameraPitch(pitch); + } + } + lastPitch = pitch; + } + + @Inject + public void setCameraPitchRelaxerEnabled(boolean enabled) + { + if (pitchRelaxEnabled == enabled) + { + return; + } + pitchRelaxEnabled = enabled; + if (!enabled) + { + int pitch = client.getCameraPitch(); + if (pitch > STANDARD_PITCH_MAX) + { + client.setCameraPitch(STANDARD_PITCH_MAX); + } + } + } +} \ No newline at end of file diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 928c84b537..53835bc481 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -472,4 +472,7 @@ public interface RSClient extends RSGameEngine, Client @Import("preferences") @Override RSPreferences getPreferences(); + + @Import("cameraPitch") + void setCameraPitch(int pitch); }