Just a quick tut on how to set up a new project for vindictus.
What you need
1) A steam account with Half Life 2: Deathmatch on it(might work with other games that use the old source engine) //edit: got told it doesn't work with just HL2M, you'll need another source engine game to get access to the source SDK
2) Microsoft Visual Studio(or MS Visual C++ Express edition), preferably 2005 or 2008(I use 2008)
3) A brain(Can't help with that, sorry)
Creating the mod project
Launch the Source SDK and create a new project using the following settings:
I've set my path to C:\VindictusHax for easy access
Cleaning up
Go to C:\VindictusHax(or whatever location you extracted to) and open Game_HL2-2005.sln, if you're using 2008 just click no on the backup part before conversion and have it converted.
Now on the left in the solution explorer you'll see 2 projects: client_hl2 and server_hl2, we won't need the server part, so just delete it from the solution.
Expand client_hl2, then expand Source Files, select ALL of the contents and delete it(you can do the same for the header files map, but I recommend leaving those there for easier access)
Now you should only have this left:
Configuring the project
Renaming the output dll
Removing precompiled headers:
Removing additional build steps:
Adding code
Right click source files, add new file, name it VindictusHack.cpp and do the same thing for sdk.h
VindictusHack.cpp:
Code:
#include <windows.h> //windows header
#include "sdk.h" //contains the sdk headers that we'll be using.
/**************************
** Forward Declarations **
** and global variables **
**************************/
void HackThread(void);
bool IsGameReady(void);
IBaseClientDLL *pBaseClient = NULL; //a pointer to the IBaseClientDLL interface, initialized as NULL
IVEngineClient *pEngineClient = NULL; //a pointer to the IVEngineClient interface, initialized as NULL
IClientEntityList *pClientEntityList = NULL; //a pointer to the IClientEntityList interface, initialized as NULL
ICvar *pCvar = NULL; //a pointer to the ICvar interface, initialized as NULL
/*
Function: BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
Purpose: Handles events for the current DLL(process/thread attach/detach events)
Arguments:
HMODULE hModule - A handle to this module
DWORD dwReason - The event that occured(DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH)
LPVOID lpReserved - Reserved
Returns:
TRUE on success
FALSE on failure
*/
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason) //'switch' to dwReason, could use if's instead
{
case DLL_PROCESS_ATTACH: //we 'attached' to the process
DisableThreadLibraryCalls(hModule); //Disable calls to dllmain for DLL_THREAD_ATTACH and DLL_THREAD_DETACH
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)HackThread, 0, 0, 0); //Create a thread that runs our HackThread function
break; //break out of the switch statement
}
return TRUE; //success
}
/*
Function: void HackThread(void)
Purpose: The main function for our hack, here is where we have our code
Arguments:
-
Returns:
-
*/
void HackThread(void)
{
HMODULE hEngineModule, hClientModule; //module handles
CreateInterfaceFn pEngineFactory, pClientFactory; //CreateInterface function pointers
while(!IsGameReady()) //while the game isn't ready
Sleep(1000); //wait for a second before checking again
//Here the game is ready, so we get handles to the dlls
hEngineModule = GetModuleHandle("engine.dll"); //Get a handle to the engine dll
hClientModule = GetModuleHandle("client.dll"); //Get a handle to the client dll
//Get the function pointers to the CreateInterface functions
pEngineFactory = (CreateInterfaceFn)GetProcAddress(hEngineModule, "CreateInterface"); //Get the address of the CreateInterface function in engine.dll
pClientFactory = (CreateInterfaceFn)GetProcAddress(hClientModule, "CreateInterface"); //Get the address of the CreateInterface function in client.dll
//Nullpointer checks
if(pEngineFactory == NULL || pClientFactory == NULL) //if any of the two function pointers is NULL
{
MessageBox(0, "A CreateInterface pointer was NULL, shutting down!", "Failure", MB_OK); //Warn us about it
exit(0); //and exit the game
}
//Get pointers to the existing interfaces in client.dll
pBaseClient = (IBaseClientDLL*)pClientFactory(CLIENT_DLL_INTERFACE_VERSION, 0); //CLIENT_DLL_INTERFACE_VERSION is defined as "VClient013"
pClientEntityList = (IClientEntityList*)pClientFactory(VCLIENTENTITYLIST_INTERFACE_VERSION, 0); //VCLIENTENTITYLIST_INTERFACE_VERSION is defined as "VClientEntityList003"
//Get pointers to the existing interfaces in engine.dll
pEngineClient = (IVEngineClient*)pEngineFactory(VENGINE_CLIENT_INTERFACE_VERSION, 0); //VENGINE_CLIENT_INTERFACE_VERSION is defined as "VEngineClient012"
pCvar = (ICvar*)pEngineFactory(VENGINE_CVAR_INTERFACE_VERSION, 0); //VENGINE_CVAR_INTERFACE_VERSION is defined as "VEngineCvar003"
if(pBaseClient == NULL || pClientEntityList == NULL || pEngineClient == NULL || pCvar == NULL) //if any of the pointers is NULL
{
MessageBox(0, "One of the interface pointers is NULL, shutting down!", "Failure", MB_OK); //Warn us about it
exit(0); //and exit the game
}
while(1) //We passed all the checks, so we can enter an infinite loop
{
if(GetAsyncKeyState(VK_NUMPAD1)&1) //if the first bit for numpad1 is set(initial press & repeats)
{
pEngineClient->ClientCmd("monster_attack_bonus_ratio -80"); //enable godmode using ClientCmd
}
if(GetAsyncKeyState(VK_NUMPAD3)&1) //if the first bit for numpad3 is set(initial press & repeats)
{
//Disable godmode using ConVars
ConVar *pGodmode = pCvar->FindVar("monster_attack_bonus_ratio"); //get a pointer to the ConVar
if(pGodmode != NULL) //make sure it isn't a NULL pointer!
pGodmode->SetValue(pGodmode->GetDefault()); //Set the convar back to the default value
}
Sleep(100); //Sleep(pause) the thread for 100 miliseconds
}
}
/*
Function: bool IsGameReady(void)
Purpose: Checks if the game has loaded the required dll's
Arguments:
-
Returns:
true if the required dlls are loaded
false if they aren't
*/
bool IsGameReady(void)
{
if( GetModuleHandle("client.dll") && //Can we get a handle to client.dll
GetModuleHandle("engine.dll") //and engine.dll?
)
{
return true; //we can get handles, so the game is ready
}
return false; //we missed 1 or more handles, so the game isn't ready yet!
}
sdk.h:
Code:
#pragma once //prevent the compiler from regenerating symbols for this file(important when included in multiple .cpp files)
#include "cdll_int.h" //IVEngineClient and IBaseClientDLL interfaces
#include "icliententitylist.h" //IClientEntityList interface
#include "icvar.h" //ICvar interface
#include "icliententity.h" //IClientEntity class
#include "convar.h" //ConVar and ConCommand classes
//The source engine makes some funny defines, so we have to undefine them or we won't be able to use windows' functions with those names
#undef CreateThread
#undef GetAsyncKeyState
I hope this will get some of you interested in starting your own projects(and releasing them of course =))
~ Hell_Demon