Skip to content

Commit

Permalink
add(): Sensitivity dampen
Browse files Browse the repository at this point in the history
update(): Update to 1.20.71.1
  • Loading branch information
ATXLtheAxolotl committed Apr 2, 2024
1 parent 08acda6 commit 9c30c00
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 97 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.12)
project(VidereLonge)
set(MOD_VERSION "1.1.1")
set(MOD_VERSION "1.2.0")

set(CMAKE_CXX_STANDARD 23)

Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
[![MIT License](https://img.shields.io/github/license/ATXLtheAxolotl/VidereLonge.svg?style=for-the-badge)](https://github.com/ATXLtheAxolotl/VidereLonge/blob/main/License.md)
</div>

## VidēreLongē v1.0.0
Currently stable on Minecraft Bedrock Edition 1.20.51 with Amethyst Runtime 1.1.0
## VidēreLongē v1.2.0
Currently stable on Minecraft Bedrock Edition 1.20.71 with Amethyst Runtime 1.2.1

<video controls>
<source src="./assets/VidereLongeExample.mp4" type="video/mp4">
Expand All @@ -33,7 +33,7 @@ Currently stable on Minecraft Bedrock Edition 1.20.51 with Amethyst Runtime 1.1.

2. Use a Minecraft version manager, for example [Bedrock Launcher](https://bedrocklauncher.github.io/) or [MCLauncher](https://github.com/MCMrARM/mc-w10-version-launcher) (most require your PC user account to have administrator level premissions).

3. Download, play, and close Minecraft Bedrock 1.20.51
3. Download, play, and close Minecraft Bedrock 1.20.71

4. Find and install the latest Amethyst Launcher and Runtime release in [Amethyst's releases page](https://github.com/FrederoxDev/Amethyst/releases/latest).

Expand All @@ -51,7 +51,7 @@ Currently stable on Minecraft Bedrock Edition 1.20.51 with Amethyst Runtime 1.1.

<img src="assets/movedFolders.png" width="400"/>

10. Relaunch AmethystLauncher, select `AmethystRuntime@1.0.2` under `Runtime Mod`, and click `VidereLonge@1.0.0` under `Inactive Mods` to activate it. The end result should look like this.
10. Relaunch AmethystLauncher, select `AmethystRuntime@1.2.1` under `Runtime Mod`, and click `VidereLonge@1.2.0` under `Inactive Mods` to activate it. The end result should look like this.

11. Click `Launch Game`, and enjoy VidēreLongē.

Expand Down Expand Up @@ -89,18 +89,18 @@ Join the [Amethyst modding Discord guild](https://discord.gg/DcCksKssfD), we'll
> A default config.json should be made automatically once you start the game however you can still manually make it if you like.
> ````json
> {
> "zoomType": "gradual",
> "targetFov": 10.0,
> "zoomRate": 1.5
> "zoomType": "gradual",
> "sensitivityDampen": 90.0,
> "targetFov": 10.0,
> "duration": 0.2
> }
> ````
4. The config format is the following:
* `zoomType` can either be `instant` or `gradual`. Instant sets your FOV to the `targetFov` the *intstant* you press the zoom key and `gradual` zooms in slowly.
* `targetFov` is the FOV the mod will stop at when you press the zoomKey.
* `zoomRate` is for the `gradual` mode. For every tick your FOV will decrease by this amount.
<img src="assets/editConfig.png" width="400"/>
* `sensitivityDampen` is the percentage you want your sensitivity to decrease by when zoomed.
* `targetFov` is the FOV the mod will stop at when you press the zoom key.
* `duration` is for the `gradual` mode. In this amount of time (seconds) you will reach the `targetFov`.
## How was the banner made?
* This was made with Blender using two assets from Sketchfab.
Expand Down
Binary file removed assets/editConfig.png
Binary file not shown.
2 changes: 2 additions & 0 deletions mod.json.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"meta": {
"name": "VidēreLongē",
"version": "@MOD_VERSION@",
"description": "An Amethyst mod that changes the in-game FOV.",
"author": "ATXL (566770844286844953)",
"is_runtime": false
Expand Down
28 changes: 10 additions & 18 deletions src/ConfigManager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "ConfigManager.h"
#include "ConfigManager.hpp"

// If anyone knows a better way to do this and make it look cleaner please help me.
ConfigManager::ConfigManager() {
std::string configPath = GetAmethystFolder() + "mods/VidereLonge@" + MOD_VERSION + "/config.json";

Expand Down Expand Up @@ -32,32 +33,23 @@ ConfigManager::ConfigManager() {
throw error;
}

json sensitivityDampen = data["sensitivityDampen"];
json targetFov = data["targetFov"];
json zoomType = data["zoomType"];
json zoomRate = data["zoomRate"];
json duration = data["duration"];

if (!sensitivityDampen.is_number_float())
throw std::exception("[VidereLonge] Field \"sensitivityDampen\" should be of type \"float\" in config.json");
if (!targetFov.is_number_float())
throw std::exception("[VidereLonge] Field \"targetFov\" should be of type \"float\" in config.json");
if (!zoomType.is_string())
throw std::exception("[VidereLonge] Field \"zoomType\" should be of type \"string\" in config.json");
if (!data["zoomRate"].is_number_float())
throw std::exception("[VidereLonge] Field \"zoomRate\" should be of type \"float\" in config.json");

if (!data["duration"].is_number_float())
throw std::exception("[VidereLonge] Field \"duration\" should be of type \"float\" in config.json");

this->sensitivityDampen = sensitivityDampen;
this->targetFov = targetFov;
this->zoomType = zoomType;
this->zoomRate = zoomRate;
this->duration = duration;
Log::Info("[VidereLonge] Successfully loaded config.json from \"{}\"", configPath);
}

std::string ConfigManager::getZoomType() {
return zoomType;
}

float ConfigManager::getTargetFov() {
return targetFov;
}

float ConfigManager::getZoomRate() {
return zoomRate;
}
20 changes: 13 additions & 7 deletions src/ConfigManager.h → src/ConfigManager.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "amethyst/Log.h"
#pragma once
#include "amethyst/Log.hpp"
#include "Json.hpp"

#include "amethyst/Utility.h"
Expand All @@ -16,18 +17,23 @@ class ConfigManager {
std::string defaultConfig =
"{\n" \
" \"zoomType\": \"gradual\",\n" \
" \"sensitivityDampen\": 90.0,\n" \
" \"targetFov\": 10.0,\n" \
" \"zoomRate\": 1.5\n" \
" \"duration\": 0.2\n" \
"}";

std::string zoomType;
float sensitivityDampen;
float targetFov;
float zoomRate;
float duration;

std::string zoomType;

public:
ConfigManager();

std::string getZoomType();
float getTargetFov();
float getZoomRate();
inline float getSensitivityDampen() { return sensitivityDampen; }
inline float getTargetFov() { return targetFov; }
inline float getDuration() { return duration; }

std::string getZoomType() { return zoomType; }
};
71 changes: 71 additions & 0 deletions src/ZoomManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "ZoomManager.hpp"

static ZoomManager* mInstance;
ZoomManager::ZoomManager(AmethystContext* context, ConfigManager* config) {
mConfig = config;

context->mHookManager.CreateHook<&BaseOptions::getSensitivity>(ZoomManager::mGetSensitivity, ZoomManager::sensitivityHook);
context->mHookManager.CreateHook<&LevelRendererPlayer::getFov>(ZoomManager::mGetFov, ZoomManager::fovHook);

mInstance = this;
}

ZoomManager* ZoomManager::getInstance() {
return mInstance;
}

void ZoomManager::setEnabled(bool value) {
mEnabledStart = std::chrono::system_clock::now();
mEnabled = value;
}

float ZoomManager::fovHook(LevelRendererPlayer* self, float a, bool a2) {
static ZoomManager* instance = ZoomManager::getInstance();

static std::string zoomType = instance->mConfig->getZoomType();
static float targetFov = instance->mConfig->getTargetFov();
static float duration = instance->mConfig->getDuration();

float currentFov = instance->mGetFov.thiscall<float>(self, a, a2);
if(currentFov == 70.0f) return currentFov;

if(zoomType == "gradual") {
auto currentTime = std::chrono::system_clock::now();
std::chrono::duration<float> elapsedTime = currentTime - instance->mEnabledStart;

float time = std::clamp(elapsedTime.count(), 0.0f, duration);
float rate = (currentFov - targetFov) / duration;

if(instance->mEnabled)
return (time * -rate) + currentFov;
else return time * rate;
} else if(zoomType == "instant" && instance->mEnabled) return targetFov;

return currentFov;
}

float ZoomManager::sensitivityHook(BaseOptions* self, unsigned int inputMode) {
static ZoomManager* instance = ZoomManager::getInstance();

static float dampen = (100.0f - instance->mConfig->getSensitivityDampen()) / 100.0f;

static std::string zoomType = instance->mConfig->getZoomType();
static float duration = instance->mConfig->getDuration();

float currentSensitivity = instance->mGetSensitivity.thiscall<float>(self, inputMode);
float targetSensitivity = currentSensitivity * dampen;

if(zoomType == "gradual") {
auto currentTime = std::chrono::system_clock::now();
std::chrono::duration<float> elapsedTime = currentTime - instance->mEnabledStart;

float time = std::clamp(elapsedTime.count(), 0.0f, duration);
float rate = (currentSensitivity - targetSensitivity) / duration;

if(instance->mEnabled)
return (time * -rate) + currentSensitivity;
else return time * rate;
} else if(zoomType == "instant" && instance->mEnabled) return targetSensitivity;

return currentSensitivity;
}
26 changes: 26 additions & 0 deletions src/ZoomManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once
#include "minecraft/src-client/common/client/renderer/game/LevelRendererPlayer.hpp"
#include "minecraft/src-client/common/client/options/BaseOptions.hpp"

#include "amethyst/runtime/AmethystContext.hpp"
#include "amethyst/runtime/HookManager.hpp"

#include "ConfigManager.hpp"
#include <chrono>

class ZoomManager {
public:
ZoomManager(AmethystContext*, ConfigManager*);
static ZoomManager* getInstance();
void setEnabled(bool);

private:
static float sensitivityHook(BaseOptions*, unsigned int);
static float fovHook(LevelRendererPlayer*, float, bool);
SafetyHookInline mGetSensitivity;
SafetyHookInline mGetFov;

std::chrono::system_clock::time_point mEnabledStart;
ConfigManager* mConfig;
bool mEnabled;
};
97 changes: 37 additions & 60 deletions src/dllmain.cpp
Original file line number Diff line number Diff line change
@@ -1,78 +1,55 @@
#include "minecraft/src-client/common/client/renderer/game/LevelRendererPlayer.h"
#include "amethyst/events/EventManager.h"
#include "amethyst/InputManager.h"
#include "amethyst/HookManager.h"
#include "amethyst/Log.h"
#pragma once
#include "minecraft/src-client/common/client/renderer/game/LevelRendererPlayer.hpp"
#include "minecraft/src-client/common/client/options/BaseOptions.hpp"

#include "ConfigManager.h"
#include "amethyst/runtime/events/EventManager.hpp"
#include "amethyst/runtime/AmethystContext.hpp"
#include "amethyst/runtime/HookManager.hpp"
#include "amethyst/Log.hpp"

#define ModFunction extern "C" __declspec(dllexport)
#include "ConfigManager.hpp"
#include "ZoomManager.hpp"

ConfigManager configManager;
SafetyHookInline getFov;
HookManager hookManager;
float initialFov;
bool releasing;
bool pressed;
float fov;
ConfigManager* configManager;
ZoomManager* zoomManager;

AmethystContext* context;

static float LevelRendererPlayer_getFov(LevelRendererPlayer* self, float a, bool applyEffects) {
if(pressed || releasing) return fov;
else {
initialFov = getFov.thiscall<float>(self, a, applyEffects);
return fov = initialFov;
}
}
void RegisterInputs(Amethyst::InputManager* input) { input->RegisterNewInput("zoom", { 0x43 }); }
void OnStartJoinGame(ClientInstance* ci) {
context->mInputManager.AddButtonDownHandler("zoom", [](FocusImpact focus, ClientInstance& client) {
zoomManager->setEnabled(true);
}, false);

inline void gradualPress() {
static float targetFov = configManager.getTargetFov();
static float zoomRate = configManager.getZoomRate();

if(fov <= targetFov) fov = targetFov;
else fov -= zoomRate;
context->mInputManager.AddButtonUpHandler("zoom", [](FocusImpact focus, ClientInstance& client) {
zoomManager->setEnabled(false);
}, false);
}

inline void gradualRelease() {
static float zoomRate = configManager.getZoomRate();

if(fov >= initialFov) {
releasing = false;
fov = initialFov;
} else fov += zoomRate;
}
void BeforeModShutdown() {
if(zoomManager != nullptr) {
delete zoomManager;
zoomManager = nullptr;
}

void OnTick() {
static std::string type = configManager.getZoomType();
static float targetFov = configManager.getTargetFov();

if(type == "gradual") {
if(pressed) gradualPress();
else if(releasing) gradualRelease();
} else if(type == "instant") {
if(pressed) fov = targetFov;
else if(releasing) fov = initialFov;
if(configManager != nullptr) {
delete configManager;
configManager = nullptr;
}
}

ModFunction void RegisterInputs(InputManager* inputManager) { inputManager->RegisterInput("zoom", 0x56); }
ModFunction void Initialize(HookManager* hookManager, Amethyst::EventManager* eventManager, InputManager* inputManager) {
hookManager->RegisterFunction(&LevelRendererPlayer::getFov, "48 8B C4 48 89 58 ? 48 89 70 ? 57 48 81 EC ? ? ? ? 0F 29 70 ? 0F 29 78 ? 44 0F 29 40 ? 44 0F 29 48 ? 48 8B 05");
hookManager->CreateHook(&LevelRendererPlayer::getFov, getFov, &LevelRendererPlayer_getFov);

inputManager->AddButtonDownHandler("zoom", [](FocusImpact f, ClientInstance c) {
releasing = false;
pressed = true;
});
extern "C" __declspec(dllexport) void Initialize(AmethystContext* ctx) {
context = ctx;

inputManager->AddButtonUpHandler("zoom", [](FocusImpact f, ClientInstance c) {
static std::string type = configManager.getZoomType();
context->mHookManager.RegisterFunction<&LevelRendererPlayer::getFov>("48 8B C4 48 89 58 ? 48 89 70 ? 57 48 81 EC ? ? ? ? 0F 29 70 ? 0F 29 78 ? 44 0F 29 40 ? 44 0F 29 48 ? 48 8B 05");
context->mHookManager.RegisterFunction<&BaseOptions::getSensitivity>("40 53 48 83 EC ? 80 B9 ? ? ? ? ? 8B DA");

if(type == "gradual") releasing = true;
pressed = false;
});
configManager = new ConfigManager();
zoomManager = new ZoomManager(context, configManager);

eventManager->beforeTick.AddListener(OnTick);
context->mEventManager.beforeModShutdown.AddListener(BeforeModShutdown);
context->mEventManager.onStartJoinGame.AddListener(OnStartJoinGame);
context->mEventManager.registerInputs.AddListener(RegisterInputs);

Log::Info("[VidereLonge] Mod successfully initialized!");
}
Expand Down

0 comments on commit 9c30c00

Please sign in to comment.