Skip to content

Commit

Permalink
Afterbirth support!
Browse files Browse the repository at this point in the history
Added Preferences menu for people to have a little choice on how detailed their HUD is.
  • Loading branch information
networkMe committed Oct 31, 2015
1 parent 6ce2ee5 commit ff54f1c
Show file tree
Hide file tree
Showing 30 changed files with 748 additions and 110 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set(DLL_SOURCE_FILES
src/dll/TextRenderer.h src/dll/TextRenderer.cpp
src/dll/ShaderProgram.h src/dll/ShaderProgram.cpp
src/dll/ResourceLoader.h src/dll/ResourceLoader.cpp
src/dll/DLLPreferences.h src/dll/DLLPreferences.cpp
res/DllResources.h res/DllResources.rc
)
add_library(MissingHUD2Hook MODULE ${DLL_SOURCE_FILES} ${PROTO_SRCS} ${PROTO_HDRS})
Expand Down Expand Up @@ -94,6 +95,7 @@ set(SOURCE_FILES
src/BoIInjector.h src/BoIInjector.cpp
src/BoIProcess.h src/BoIProcess.cpp
src/MHUD_MsgQueue.h src/MHUD_MsgQueue.cpp
src/MHUD_Options.h src/MHUD_Options.cpp
src/mhud2_version.h

res/MissingHUD2.qrc
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
## Overview
Missing HUD 2 is an Open-GL powered informational overlay for the Binding of Isaac: Rebirth.
Missing HUD 2 is an OpenGL powered informational overlay for the Binding of Isaac: Rebirth + Afterbirth.

The developers of Rebirth (Edmund McMillen, Nicalis) decided that one of their design decisions for the game would be to hide raw player statistics from the player as to not to overwhelm them.
This project gives the player the choice to see their raw statistics if they choose to.
The developers of the Binding of Isaac (Edmund McMillen, Nicalis) decided that one of their design decisions for the game would be to hide raw player statistics from the player as to not to overwhelm them. This project gives the player the choice to see their raw statistics if they choose to.

It is a transparent mod that **DOES NOT** disable achievements nor alter your Isaac game files in any way. As a result, it can be enabled and disabled at any point, during any run, with no lasting consequences. One can run other mods side-by-side with Missing HUD 2 with no issues.
It is a transparent mod that **DOES NOT** disable achievements nor alter your Isaac game files in any way. **Note:** It can be used in Afterbirth daily runs with no repercussions.

Unlike other mods, it uses your live character statistics during a run. This translates to Missing HUD 2 remaining 100% accurate even after picking up items like [Experimental Treatment](http://bindingofisaacrebirth.gamepedia.com/Experimental_Treatment) and [Libra](http://bindingofisaacrebirth.gamepedia.com/Libra).
It can be enabled and disabled at any point, during any run, with no lasting consequences. One can run other mods side-by-side with Missing HUD 2 with no issues.

Unlike other statistic based mods, it uses your live character statistics during a run. This translates to Missing HUD 2 remaining 100% accurate even after picking up items like [Experimental Treatment](http://bindingofisaacrebirth.gamepedia.com/Experimental_Treatment) and [Libra](http://bindingofisaacrebirth.gamepedia.com/Libra).

![Image of MissingHUD2](https://raw.githubusercontent.com/networkMe/missinghud2/master/doc/isaac-mhud2-example-124.jpg)

Expand All @@ -27,11 +28,14 @@ https://github.com/networkMe/missinghud2/releases/latest
## Current features
* Works in fullscreen and windowed mode (as it's a direct OpenGL implementation)
* Shows how your raw statistics change as you pick up items and use pills, real-time
* Allows you to choose at what precision you see the raw statistics (default is 1 decimal place)
* Statistics HUD on the left of the Rebirth viewport shows:
* Total tears fired in run (optional)
* Speed
* Range
* Tear firerate (Tear delay, lower is faster)
* Shot speed
* Shot height (optional)
* Damage
* Luck
* Deal with the Devil % chance
Expand Down
4 changes: 2 additions & 2 deletions res/DllResources.rc
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ MHUD2_ISAAC_FONT_CHARMAP RCDATA "files/MHUD2FontCharmap.texmap"
OPENGL_HUD_SPRITE_VERTEX_SHADER RCDATA "shaders/hud_icon_vert.glsl"
OPENGL_HUD_SPRITE_FRAG_SHADER RCDATA "shaders/hud_icon_frag.glsl"

#define PRODUCT_VER 1,2,4,0
#define PRODUCT_VER_STR "1.2.4"
#define PRODUCT_VER 1,3,0,0
#define PRODUCT_VER_STR "1.3.0"

#ifdef NDEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/WinResource.rc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

APP_ICON ICON "files/MissingHUD2_Ico.ico"

#define PRODUCT_VER 1,2,4,0
#define PRODUCT_VER_STR "1.2.4"
#define PRODUCT_VER 1,3,0,0
#define PRODUCT_VER_STR "1.3.0"

#ifdef NDEBUG
#define VER_DEBUG 0
Expand Down
2 changes: 1 addition & 1 deletion res/files/MHUD2StatIcons.texmap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
speed range firerate shotspeed damage luck deal_with_devil
speed range firerate shotspeed shotheight damage luck deal_with_devil tears_fired
Binary file modified res/files/MUD2StatIcons.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified res/files/MissingHUD2Banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified res/files/psds/MUD2StatIcons.psd
Binary file not shown.
Binary file modified res/files/psds/Missing HUD2 Banner.psd
Binary file not shown.
23 changes: 19 additions & 4 deletions src/BoIInjector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,16 @@ void BoIInjector::InjectorThread()
LOG(INFO) << "BoI process found, time to inject...";

// Set-up the DLL message queue (for IPC)
MHUD::MsgQueue::Remove();
dll_msg_queue_ = MHUD::MsgQueue::GetInstance();
MHUD::MsgQueue::Remove(MSG_QUEUE_APP_TO_DLL);
MHUD::MsgQueue::Remove(MSG_QUEUE_DLL_TO_APP);
app_msg_queue_ = MHUD::MsgQueue::GetInstance(MSG_QUEUE_APP_TO_DLL);
dll_msg_queue_ = MHUD::MsgQueue::GetInstance(MSG_QUEUE_DLL_TO_APP);
std::thread handle_dll_msgs = std::thread(&BoIInjector::HandleDllMsgs, this);
handle_dll_msgs.detach();

// Send the preferences message ready for the DLL
SendNewPrefs(MHUD::Options::ReadCfgFile(CFG_FILENAME));

// Inject DLL
isaac_process_ = BoIProcess::GetInstance();
isaac_process_->HookBoIProcess();
Expand All @@ -75,8 +80,10 @@ void BoIInjector::InjectorThread()
BoIProcess::Close();

// Clean-up DLL message queue
app_msg_queue_ = nullptr;
dll_msg_queue_ = nullptr;
MHUD::MsgQueue::Remove();
MHUD::MsgQueue::Remove(MSG_QUEUE_APP_TO_DLL);
MHUD::MsgQueue::Remove(MSG_QUEUE_DLL_TO_APP);
}
else
{
Expand All @@ -103,6 +110,14 @@ void BoIInjector::InjectorThread()
}
}

void BoIInjector::SendNewPrefs(MHUD::Prefs new_prefs)
{
if (app_msg_queue_)
{
app_msg_queue_->SendPrefs(new_prefs);
}
}

bool BoIInjector::IsBoIRunning()
{
bool isaac_running = false;
Expand Down Expand Up @@ -134,7 +149,7 @@ void BoIInjector::HandleDllMsgs()
while (dll_msg_queue_ != nullptr)
{
MHUD::MHUDMsg mhud_msg;
while(MHUD::MsgQueue::GetInstance()->TryRecieve(&mhud_msg))
while(MHUD::MsgQueue::GetInstance(MSG_QUEUE_DLL_TO_APP)->TryRecieve(&mhud_msg))
{
switch(mhud_msg.msg_type)
{
Expand Down
5 changes: 5 additions & 0 deletions src/BoIInjector.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class BoIInjector : public QObject
void InjectionStatus(InjectStatus s);
void FatalError(std::string err_msg);

private slots:
void SendNewPrefs(MHUD::Prefs new_prefs);

private:
void InjectorThread();

Expand All @@ -72,6 +75,8 @@ class BoIInjector : public QObject
bool stop_injector_ = false;
std::thread inject_thread_;
BoIProcess *isaac_process_ = nullptr;

MHUD::MsgQueue *app_msg_queue_ = nullptr;
MHUD::MsgQueue *dll_msg_queue_ = nullptr;
};

Expand Down
70 changes: 53 additions & 17 deletions src/LoaderGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,30 @@ LoaderGUI::LoaderGUI(QWidget *parent) :
qRegisterMetaType<std::string>();

// Connect GUI signals/slots
QObject::connect(ui_.UpdateCheck, SIGNAL(clicked(bool)),
QObject::connect(ui_.btn_UpdateCheck, SIGNAL(clicked(bool)),
this, SLOT(CheckForUpdates(bool)));
QObject::connect(ui_.btn_ApplyPrefs, SIGNAL(clicked(bool)),
this, SLOT(SavePreferences(bool)));
QObject::connect(ui_.btn_ResetPrefs, SIGNAL(clicked(bool)),
this, SLOT(ResetPreferences(bool)));
}

void LoaderGUI::ConnectSlots(BoIInjector &injector)
{
QObject::connect(this, SIGNAL(NewPrefs(MHUD::Prefs)),
&injector, SLOT(SendNewPrefs(MHUD::Prefs)));

QObject::connect(&injector, SIGNAL(InjectionStatus(InjectStatus)),
this, SLOT(OnInjectionStatusChange(InjectStatus)));
QObject::connect(&injector, SIGNAL(FatalError(std::wstring)),
this, SLOT(OnFatalError(std::wstring)));
QObject::connect(&injector, SIGNAL(FatalError(std::string)),
this, SLOT(OnFatalError(std::string)));
}

void LoaderGUI::UpdatePrefs(MHUD::Prefs mhud_prefs)
{
ui_.cb_ShowNumTears->setChecked(mhud_prefs.show_tears_fired);
ui_.cb_ShowShotHeight->setChecked(mhud_prefs.show_shot_height);
ui_.spinbox_Precision->setValue(mhud_prefs.stat_precision);
}

void LoaderGUI::showEvent(QShowEvent *event)
Expand All @@ -51,25 +65,47 @@ void LoaderGUI::showEvent(QShowEvent *event)

void LoaderGUI::CheckForUpdates(bool checked)
{
if (ui_.UpdateCheck->text().toStdWString() == L"New version available!")
if (ui_.btn_UpdateCheck->text().toStdString() == "New version available!")
{
QDesktopServices::openUrl(QUrl(QString::fromStdWString(L"https://github.com/networkMe/missinghud2/releases")));
QDesktopServices::openUrl(QUrl(QString::fromStdString("https://github.com/networkMe/missinghud2/releases")));
return;
}

ui_.UpdateCheck->setText(QString::fromStdWString(L"Checking for updates..."));
ui_.UpdateCheck->setDisabled(true);
ui_.btn_UpdateCheck->setText(QString::fromStdString("Checking for updates..."));
ui_.btn_UpdateCheck->setDisabled(true);

QNetworkAccessManager *network_mgr = new QNetworkAccessManager(this);
QObject::connect(network_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(OnUpdateResponse(QNetworkReply*)));
QObject::connect(network_mgr, SIGNAL(finished(QNetworkReply*)),
network_mgr, SLOT(deleteLater()));

QNetworkRequest github_req(QUrl(QString::fromStdWString(L"https://api.github.com/repos/networkMe/missinghud2/releases/latest")));
QNetworkRequest github_req(QUrl(QString::fromStdString("https://api.github.com/repos/networkMe/missinghud2/releases/latest")));
network_mgr->get(github_req);
}

void LoaderGUI::SavePreferences(bool checked)
{
MHUD::Prefs new_mhud2_prefs;
new_mhud2_prefs.show_tears_fired = ui_.cb_ShowNumTears->isChecked();
new_mhud2_prefs.show_shot_height = ui_.cb_ShowShotHeight->isChecked();
new_mhud2_prefs.stat_precision = ui_.spinbox_Precision->value();
MHUD::Options::SaveCfgFile(CFG_FILENAME, new_mhud2_prefs);

// Send the new prefs to the injected DLL
emit NewPrefs(new_mhud2_prefs);

QMessageBox prefs_saved(this);
prefs_saved.setText("Updated preferences!");
prefs_saved.setStandardButtons(QMessageBox::Ok);
prefs_saved.exec();
}

void LoaderGUI::ResetPreferences(bool checked)
{
UpdatePrefs(MHUD::Prefs());
}

void LoaderGUI::OnUpdateResponse(QNetworkReply *response)
{
try
Expand All @@ -85,7 +121,7 @@ void LoaderGUI::OnUpdateResponse(QNetworkReply *response)
throw std::runtime_error("Unable to parse the JSON GitHub replied with.");

QJsonObject json_obj = json_response.object();
QJsonObject::iterator tag_member = json_obj.find(QString::fromStdWString(L"tag_name"));
QJsonObject::iterator tag_member = json_obj.find(QString::fromStdString("tag_name"));
if (tag_member == json_obj.end())
throw std::runtime_error("Unable to find the latest version number in GitHub's API.");

Expand All @@ -94,22 +130,22 @@ void LoaderGUI::OnUpdateResponse(QNetworkReply *response)
{
LOG(INFO) << "GitHub reported latest version is " << latest_version <<
" whilst running version is " << MHUD2_VERSION;
ui_.UpdateCheck->setText(QString::fromStdString("New version available!"));
ui_.UpdateCheck->setStyleSheet(QString::fromStdString("color: rgb(200, 0, 0);"));
ui_.btn_UpdateCheck->setText(QString::fromStdString("New version available! (" + latest_version + ")"));
ui_.btn_UpdateCheck->setStyleSheet(QString::fromStdString("color: rgb(200, 0, 0);"));
}
else
{
LOG(INFO) << "GitHub reported no updates available.";
ui_.UpdateCheck->setText(QString::fromStdString("No update available"));
ui_.btn_UpdateCheck->setText(QString::fromStdString("No update available"));
}
}
catch(std::runtime_error &e)
{
LOG(ERROR) << "Error occured during update check: " << e.what();
ui_.UpdateCheck->setText(QString::fromStdString("Update check failed"));
ui_.btn_UpdateCheck->setText(QString::fromStdString("Update check failed"));
}

ui_.UpdateCheck->setEnabled(true);
ui_.btn_UpdateCheck->setEnabled(true);
response->deleteLater();
}

Expand All @@ -119,17 +155,17 @@ void LoaderGUI::OnInjectionStatusChange(InjectStatus inject_status)
{
case InjectStatus::Result::OK:
{
ui_.InjectionStatus->setText(QString::fromStdString("Injected Missing HUD 2 into active BoI Process."));
ui_.lbl_InjectStatus->setText(QString::fromStdString("Injected Missing HUD 2 into active BoI Process."));
} break;

case InjectStatus::Result::FAIL:
{
ui_.InjectionStatus->setText(QString::fromStdString("Error injecting Missing HUD 2 into active BoI process."));
ui_.lbl_InjectStatus->setText(QString::fromStdString("Error injecting Missing HUD 2 into active BoI process."));
} break;

case InjectStatus::Result::NOT_FOUND:
{
ui_.InjectionStatus->setText(QString::fromStdString("No active Binding of Isaac: Rebirth process found."));
ui_.lbl_InjectStatus->setText(QString::fromStdString("No active Binding of Isaac process found."));
} break;
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/LoaderGUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "ui_LoaderGUI.h"
#include "BoIInjector.h"
#include "MHUD_Options.h"
#include "mhud2_version.h"

Q_DECLARE_METATYPE(std::string);
Expand All @@ -39,12 +40,18 @@ class LoaderGUI : public QMainWindow
LoaderGUI(QWidget *parent = 0);

void ConnectSlots(BoIInjector &injector);
void UpdatePrefs(MHUD::Prefs mhud_prefs);

signals:
void NewPrefs(MHUD::Prefs mhud_prefs);

protected:
void showEvent(QShowEvent *event);

private slots:
void CheckForUpdates(bool checked = false);
void SavePreferences(bool checked = false);
void ResetPreferences(bool checked = false);
void OnInjectionStatusChange(InjectStatus s);
void OnFatalError(std::string err_msg);
void OnUpdateResponse(QNetworkReply* response);
Expand Down
Loading

0 comments on commit ff54f1c

Please sign in to comment.