generated from YimMenu/YimMenuV2
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature Wrappers and Hotkey System (#20)
* UI control block and some small features * Fixed scripts unload * FeatureCommand & HotkeySystem * Remove useless header file * Formatting * Added non-looped command * Changed commands location * Added description field * test commit to test permissions * Added descriptions to existing commands * feat(commands): improve commands * Reintegrated hotkey system * Changed CommandLink to host the hotkey vector * Added UI cue on hover for hotkeys * Added check for hotkey changing Commands should not execute with their respective hotkeys if the said hotkey is in process of being modified. --------- Co-authored-by: maybegreat48 <email@hostname>
- Loading branch information
Showing
20 changed files
with
1,673 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#include "BoolCommand.hpp" | ||
|
||
namespace YimMenu | ||
{ | ||
BoolCommand::BoolCommand(std::string name, std::string label, std::string description) : | ||
Command(name, label, description, 0) | ||
{ | ||
} | ||
|
||
void BoolCommand::OnCall() | ||
{ | ||
SetState(!m_State); | ||
} | ||
|
||
bool BoolCommand::GetState() | ||
{ | ||
return m_State; | ||
} | ||
|
||
void BoolCommand::SetState(bool state) | ||
{ | ||
if (state && !m_State) | ||
OnEnable(); | ||
else if (!state && m_State) | ||
OnDisable(); | ||
|
||
m_State = state; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#pragma once | ||
#include "Command.hpp" | ||
|
||
namespace YimMenu | ||
{ | ||
class BoolCommand : public Command | ||
{ | ||
protected: | ||
virtual void OnEnable(){}; | ||
virtual void OnDisable(){}; | ||
virtual void OnCall() override; | ||
|
||
bool m_State = false; | ||
|
||
public: | ||
BoolCommand(std::string name, std::string label, std::string description); | ||
bool GetState(); | ||
void SetState(bool state); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#include "util/Joaat.hpp" | ||
#include "Command.hpp" | ||
#include "Commands.hpp" | ||
|
||
namespace YimMenu | ||
{ | ||
Command::Command(std::string name, std::string label, std::string description, int num_args) : | ||
m_Name(name), | ||
m_Label(label), | ||
m_Description(description), | ||
m_NumArgs(num_args), | ||
m_Hash(Joaat(name)) | ||
{ | ||
Commands::AddCommand(this); | ||
} | ||
|
||
void Command::Call() | ||
{ | ||
OnCall(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
#include "util/Joaat.hpp" | ||
#include <nlohmann/json.hpp> | ||
|
||
namespace YimMenu | ||
{ | ||
class Command | ||
{ | ||
private: | ||
std::string m_Name; | ||
std::string m_Label; | ||
std::string m_Description; | ||
joaat_t m_Hash; | ||
|
||
int m_NumArgs = 0; // TODO: currently unused | ||
|
||
protected: | ||
virtual void OnCall() = 0; | ||
|
||
|
||
public: | ||
Command(std::string name, std::string label, std::string description, int num_args = 0); | ||
void Call(); | ||
|
||
const std::string& GetName() | ||
{ | ||
return m_Name; | ||
} | ||
|
||
const std::string& GetLabel() | ||
{ | ||
return m_Label; | ||
} | ||
|
||
const std::string& GetDescription() | ||
{ | ||
return m_Description; | ||
} | ||
|
||
joaat_t GetHash() | ||
{ | ||
return m_Hash; | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include "Commands.hpp" | ||
#include "Command.hpp" | ||
#include "LoopedCommand.hpp" | ||
|
||
namespace YimMenu | ||
{ | ||
void Commands::AddCommandImpl(Command* command) | ||
{ | ||
m_Commands.insert({command->GetHash(), command}); | ||
} | ||
|
||
void Commands::AddLoopedCommandImpl(LoopedCommand* command) | ||
{ | ||
m_LoopedCommands.push_back(command); | ||
} | ||
|
||
void Commands::RunLoopedCommandsImpl() | ||
{ | ||
for (auto& command : m_LoopedCommands) | ||
if (command->GetState()) | ||
command->Tick(); | ||
} | ||
|
||
Command* Commands::GetCommandImpl(joaat_t hash) | ||
{ | ||
if (auto it = m_Commands.find(hash); it != m_Commands.end()) | ||
return it->second; | ||
return nullptr; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#pragma once | ||
#include "util/Joaat.hpp" | ||
|
||
namespace YimMenu | ||
{ | ||
class Command; | ||
class LoopedCommand; | ||
|
||
class Commands | ||
{ | ||
private: | ||
std::unordered_map<joaat_t, Command*> m_Commands; | ||
std::vector<LoopedCommand*> m_LoopedCommands; | ||
Commands(){}; | ||
|
||
public: | ||
static void AddCommand(Command* command) | ||
{ | ||
GetInstance().AddCommandImpl(command); | ||
} | ||
|
||
static void AddLoopedCommand(LoopedCommand* command) | ||
{ | ||
GetInstance().AddLoopedCommandImpl(command); | ||
|
||
} | ||
|
||
static void RunLoopedCommands() | ||
{ | ||
GetInstance().RunLoopedCommandsImpl(); | ||
} | ||
|
||
template<typename T = Command> | ||
static T* GetCommand(joaat_t hash) | ||
{ | ||
return reinterpret_cast<T*>(GetInstance().GetCommandImpl(hash)); | ||
} | ||
|
||
static std::unordered_map<joaat_t, Command*> GetCommands() | ||
{ | ||
return GetInstance().m_Commands; | ||
}; | ||
|
||
static std::vector<LoopedCommand*> GetLoopedCommands() | ||
{ | ||
return GetInstance().m_LoopedCommands; | ||
} | ||
|
||
private: | ||
void AddCommandImpl(Command* command); | ||
void AddLoopedCommandImpl(LoopedCommand* command); | ||
void RunLoopedCommandsImpl(); | ||
Command* GetCommandImpl(joaat_t hash); | ||
|
||
static Commands& GetInstance() | ||
{ | ||
static Commands instance{}; | ||
return instance; | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
#include "HotkeySystem.hpp" | ||
|
||
#include "game/rdr/Natives.hpp" | ||
#include "game/backend/ScriptMgr.hpp" | ||
#include "Commands.hpp" | ||
#include "LoopedCommand.hpp" | ||
|
||
// TODO: hotkeys | ||
|
||
|
||
namespace YimMenu | ||
{ | ||
|
||
void HotkeySystem::RegisterCommands() | ||
{ | ||
auto commands = Commands::GetCommands(); | ||
auto looped_commands = Commands::GetLoopedCommands(); | ||
|
||
for (auto [hash, command] : commands) | ||
{ | ||
CommandLink link(false); | ||
m_CommandHotkeys.insert(std::make_pair(command->GetHash(), link)); | ||
} | ||
|
||
for (auto looped_command : looped_commands) | ||
{ | ||
CommandLink link(true); | ||
m_CommandHotkeys.insert(std::make_pair(looped_command->GetHash(), link)); | ||
} | ||
|
||
LOG(INFO) << "Registered " << m_CommandHotkeys.size() << " commands"; | ||
} | ||
|
||
bool HotkeySystem::ListenAndApply(int& Hotkey, std::vector<int> blacklist) | ||
{ | ||
static auto is_key_blacklisted = [blacklist](int key) -> bool { | ||
for (auto key_ : blacklist) | ||
if (key_ == key) | ||
return true; | ||
|
||
return false; | ||
}; | ||
|
||
//VK_OEM_CLEAR Is about the limit in terms of virtual key codes | ||
for (int i = 0; i < VK_OEM_CLEAR; i++) | ||
{ | ||
if ((GetKeyState(i) & 0x8000) && i != 1 && !is_key_blacklisted(i)) | ||
{ | ||
Hotkey = i; | ||
|
||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
//Will return the keycode if there are no labels | ||
std::string HotkeySystem::GetHotkeyLabel(int hotkey_modifier) | ||
{ | ||
char key_name[32]; | ||
GetKeyNameTextA(MapVirtualKey(hotkey_modifier, MAPVK_VK_TO_VSC) << 16, key_name, 32); | ||
|
||
if (std::string(key_name).empty()) | ||
strcpy(key_name, std::to_string(hotkey_modifier).data()); | ||
|
||
return key_name; | ||
} | ||
|
||
//Meant to be called in a loop | ||
void HotkeySystem::CreateHotkey(std::vector<int>& Hotkey) | ||
{ | ||
static auto is_key_unique = [this](int key, std::vector<int> list) -> bool { | ||
for (auto& key_ : list) | ||
if (GetHotkeyLabel(key_) == GetHotkeyLabel(key)) | ||
return false; | ||
|
||
return true; | ||
}; | ||
|
||
int pressed_key = 0; | ||
ListenAndApply(pressed_key, Hotkey); | ||
|
||
|
||
if (pressed_key > 1) | ||
{ | ||
if (is_key_unique(pressed_key, Hotkey)) | ||
{ | ||
Hotkey.push_back(pressed_key); | ||
} | ||
} | ||
} | ||
|
||
void HotkeySystem::FeatureCommandsHotkeyLoop() | ||
{ | ||
for (auto& [hash, link] : m_CommandHotkeys) | ||
{ | ||
if (link.Hotkey.empty() || link.Listening) | ||
continue; | ||
|
||
bool allkeyspressed = true; | ||
|
||
for (auto hotkey_modifier : link.Hotkey) | ||
{ | ||
if (!(GetAsyncKeyState(hotkey_modifier) & 0x8000)) | ||
{ | ||
allkeyspressed = false; | ||
} | ||
} | ||
|
||
if (allkeyspressed) | ||
{ | ||
if (link.Looped) | ||
{ | ||
auto looped_command = Commands::GetCommand<LoopedCommand>(hash); | ||
|
||
if (looped_command) | ||
looped_command->SetState(!looped_command->GetState()); | ||
|
||
LOG(INFO) << "Hotkey detected for looped command " << looped_command->GetName(); | ||
} | ||
else | ||
{ | ||
auto command = Commands::GetCommand(hash); | ||
if (command) | ||
{ | ||
command->Call(); | ||
LOG(INFO) << "Hotkey detected for command " << command->GetName(); | ||
} | ||
} | ||
|
||
ScriptMgr::Yield(100ms); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#pragma once | ||
#include "../../common.hpp" | ||
|
||
namespace YimMenu | ||
{ | ||
struct CommandLink | ||
{ | ||
public: | ||
bool Looped; | ||
std::vector<int> Hotkey{}; | ||
|
||
CommandLink(bool looped) : | ||
Looped(looped) | ||
{ | ||
} | ||
|
||
bool Listening; | ||
}; | ||
|
||
class HotkeySystem | ||
{ | ||
public: | ||
std::map<uint32_t, CommandLink> m_CommandHotkeys; | ||
void RegisterCommands(); | ||
bool ListenAndApply(int& Hotkey, std::vector<int> blacklist = {0}); | ||
std::string GetHotkeyLabel(int hotkey_modifiers); | ||
void CreateHotkey(std::vector<int>& Hotkey); | ||
|
||
void FeatureCommandsHotkeyLoop(); | ||
}; | ||
|
||
inline HotkeySystem g_HotkeySystem; | ||
} |
Oops, something went wrong.