Skip to content
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ To run a mod, you must perform the following steps:
### Installing the Mod Loader
When Haggle mods are used with Peggle, they are loaded into the Peggle executable code on startup.
The Mod Loader performs this operation. Follow these steps to install the Mod Loader.
1. Obtain the Mod Loader `dsound.dll` file:
1. Obtain the Mod Loader `ddraw.dll` file:
1. Download from the [Haggle Github releases page](https://github.com/PeggleCommunity/haggle/releases) or
2. Compile from the [`mod-loader` project files](src/mod-loader/). Refer to the [Compiling](#compiling) section for details.
2. Copy the `dsound.dll` file into the directory that the Peggle executable is run from.
2. Copy the `ddraw.dll` file into the directory that the Peggle executable is run from.
1. For **Steam**, Peggle executes from a location like `C:\ProgramData\PopCap Games\Peggle` (drive letter may vary).
Note that the install location for Steam games is not the same as this ProgramData location.
The Mod Loader must be placed inside this ProgramData location due to Steam's DRM check.
Expand Down Expand Up @@ -59,7 +59,7 @@ The Mod Loader performs this operation. Follow these steps to install the Mod Lo
At this point, the Mod Loader will complain about not finding a mod folder if no mods have been installed yet.
Refer to the section on [installing mods into the mod folder](#installing-mods-into-the-mods-folder).

*Note: you can temporarily disable mods by renaming the `dsound.dll` file (e.g. rename it to `_dsound.dll`).*
*Note: you can temporarily disable mods by renaming the `ddraw.dll` file (e.g. rename it to `_ddraw.dll`).*

### Installing mods into the mods folder
1. Create a folder called "mods" in the Peggle installation directory.
Expand All @@ -72,8 +72,9 @@ The Mod Loader performs this operation. Follow these steps to install the Mod Lo
</p>
</details>
2. For the **EA launcher**, you can find this location by following the same steps in the [Installing the Mod Loader](#installing-the-mod-loader) section for the EA launcher.
2. Place the mod's file(s) into the created folder. A mod file will usually have a `.dll` or `.asi` extension.
3. Test that the mod has been installed correctly.
2. Place the Haggle SDK's file into the mods folder. The file is called `haggle-sdk.dll`.
3. Place the mod's file(s) into the mods folder. A mod file will usually have a `.dll` or `.asi` extension.
4. Test that the mod has been installed correctly.
1. Launch Peggle, having already completed the [Installing the Mod Loader](#installing-the-mod-loader) step.
2. In the Haggle Mod Loader window, the Mod Loader identifies which mods it loads.
Ensure that all of the mod files that were placed into the "mods" folder in the previous step have been loaded.
Expand Down
14 changes: 11 additions & 3 deletions src/example-mod/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <random>
#include <cstdio>
#include "sdk/SexySDK.hpp"
#include "callbacks/callbacks.hpp"

Expand Down Expand Up @@ -55,18 +56,20 @@ void Example_Callbacks(void)
*/
void Example_AutoShoot(void)
{
std::printf("[ EXAMPLE MOD ]: Starting Example_AutoShoot\n");
callbacks::on(callbacks::type::main_loop, []()
{
// std::printf("[ EXAMPLE MOD ]: Main Loop Callback triggered\n");
static float angleIncrement = 8.0f;
static constexpr int MOVE_DELAY_MS = 1000 / 60;
static constexpr int MOVE_DELAY_MS = 1000 / 60; // Update at a rate of 60 FPS.
static constexpr float ANGLE_BOUNDS[] = { -93.0f, 93.0f };
static bool isMovingLeft = false;

static std::random_device rd; //Will be used to obtain a seed for the random number engine
static std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
static std::uniform_int_distribution<> distribDelayMs(1000, 2000);
static unsigned int firstShotDelayCounter = 0;
static unsigned int firstShotDelayMs = distribDelayMs(gen);
static unsigned int firstShotDelayMs = distribDelayMs(gen); // Randomize the time at which the first shot is fired off.

Sexy::LogicMgr::State logicState = Sexy::LogicMgr::GetState();
switch (logicState)
Expand All @@ -84,6 +87,8 @@ void Example_AutoShoot(void)
return;
}

// std::printf("[ EXAMPLE MOD ]: Running the auto-move behavior.\n");

float currentGunAngleDegrees = Sexy::LogicMgr::GetGunAngleDegrees();
if (isMovingLeft)
{
Expand Down Expand Up @@ -115,6 +120,8 @@ void Example_AutoShoot(void)
{
if (firstShotDelayCounter >= firstShotDelayMs)
{
/// @TODO: Fix for Nights 1.01 - Fix calling convention for MouseDown.
std::printf("[ EXAMPLE MOD ]: Shooting!\n");
Sexy::LogicMgr::MouseDown(100, 100, 1, false, false);
}
else
Expand All @@ -123,6 +130,7 @@ void Example_AutoShoot(void)
}
}
});
std::printf("[ EXAMPLE MOD ]: Done with startup work.\n");
}

DWORD WINAPI OnAttachImpl(LPVOID lpParameter)
Expand All @@ -137,7 +145,7 @@ DWORD WINAPI OnAttach(LPVOID lpParameter)
{
return OnAttachImpl(lpParameter);
}
__except (0)
__except (EXCEPTION_EXECUTE_HANDLER)
{
FreeLibraryAndExitThread((HMODULE)lpParameter, 0xDECEA5ED);
}
Expand Down
44 changes: 40 additions & 4 deletions src/haggle/callbacks/callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ void __declspec(naked) main_loop()
retn;
}
} break;

case PeggleVersion::NightsDeluxe10:
case PeggleVersion::NightsDeluxe100:
{
__asm
{
Expand Down Expand Up @@ -89,6 +88,40 @@ void __declspec(naked) main_loop()
retn;
}
} break;
case PeggleVersion::NightsDeluxe101:
{
__asm
{
push esi;
mov esi, ecx;
cmp byte ptr[esi + 341h], 0;
jnz short loc_4FA1A5;

loc_4FA180:
cmp byte ptr[esi + 342h], 0;
jz short loc_4FA190;
mov byte ptr[esi + 342h], 0;

loc_4FA190:
mov eax, [esi];
mov edx, [eax + 188h];
mov ecx, esi;

pushad;
push hook_type;
call callbacks::run_basic_callbacks;
add esp, 0x04;
popad;

call edx;
cmp byte ptr[esi + 341h], 0;
jz short loc_4FA180;

loc_4FA1A5:
pop esi;
retn;
}
} break;
}
}

Expand All @@ -100,11 +133,14 @@ void callbacks::init()
{
jump(0x0052A5F0, main_loop);
} break;

case PeggleVersion::NightsDeluxe10:
case PeggleVersion::NightsDeluxe100:
{
jump(0x0054CBD0, main_loop);
} break;
case PeggleVersion::NightsDeluxe101:
{
jump(0x004FA170, main_loop);
} break;
}

callbacks::on(type::main_loop, []() -> void
Expand Down
9 changes: 7 additions & 2 deletions src/haggle/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ void init()
}
else if (!strcmp(reinterpret_cast<char*>(0x006851D0), "Peggle Nights"))
{
version = PeggleVersion::NightsDeluxe10;
std::printf("[ HAGGLE ]: Detected Peggle Nights Deluxe 1.0\n");
version = PeggleVersion::NightsDeluxe100;
std::printf("[ HAGGLE ]: Detected Peggle Nights Deluxe 1.00\n");
}
else if (!strcmp(reinterpret_cast<char*>(0x006873F0), "Peggle Nights Deluxe"))
{
version = PeggleVersion::NightsDeluxe101;
std::printf("[ HAGGLE ]: Detected Peggle Nights Deluxe 1.01\n");
}
else
{
Expand Down
Loading