-
Notifications
You must be signed in to change notification settings - Fork 18
Displaying Messages In Game
This guide shows how to display in-game messages like the ones shown below.
To follow this guide you should know/understand
- how to write a plugin
- very basic C/C++
In this guide you will learn how to call one of the game's functions to display in-game messages. To do so, we will be calling the game's ShowGameMessage
function (unofficial name).
The function itself is located at 0x141a671f0
, in game version 15.11. The prototype for the function looks something like so:
void ShowGameMessage(sChat* this, const char* msg, float unk0, int unk1, bool unk2);
The last 3 parameters are labelled as unkN
because we don't know what they do. However parameters 3 and 4 don't seem to be used at all. However we can simply pass -1, -1, false
for those last parameters.
You might have also noticed the first parameter of type sChat*
. This is simply the actual type. However we can replace this with any pointer type, even a 64bit integer will do, as long as it points to the sChat
singleton instance. (More on that later)
With this we can now declare a function pointer to this function. A function pointer is, as the name implies, a pointer to a function, and as such, acts as an indirect call. We cannot execute direct calls to non-exported functions in another exe. (Not without quite a bit of effort)
However instead of declaring the function pointer as a variable, let's declare a proper type first:
typedef void(*ShowGameMessageFunc)(void*, const char*, float, int, bool);
This will let us cast any address to this type and call that address.
The first parameter this
of the function is the instance of the sChat
class. Luckily we can always find that instance at 0x14506d340
. To get the instance we simply dereference that address like so:
void* instance = *(void**)0x14506d340;
instance
will now hold the sChat
instance.
Now that we have this information, we can throw together a function that will print game-messages for us.
void ShowGameMessage(const std::string& message)
{
((ShowGameMessageFunc)0x141a671f0)(*(void**)0x14506d340, message.c_str(), -1, -1, false);
}
Now if you are not used to function pointer syntax this might look weird. So let me break it down.
void ShowGameMessage(const std::string& message)
{
// First we declare the function pointer using the type we defined above
ShowGameMessageFunc displayMessage = (ShowGameMessageFunc)0x141a671f0;
// Next we get the sChat instance
void* instance = *(void**)0x14506d340;
// Finally we get a const char* out of our std::string
const char* str = message.c_str();
// Now we call the function
displayMessage(instance, str, -1, -1, false);
}
Already looks a lot less complicated right? These 2 functions do the exact same thing.
Now all we have to do is call the function:
ShowGameMessage("Hello World!");
All done! You can use this function in any plugin to show messages in-game. However keep in mind that you will crash your game if you call this before entering a session.
To call this function externally, we need to start a thread in the game's context and call it from there. To do so we use the function CreateRemoteThread
.
To make things a little easier, we can restructure our function like so:
DWORD WINAPI ShowGameMessage(void* message)
{
((ShowGameMessageFunc)0x141a671f0)(*(void**)0x14506d340, (const char*)message, -1, -1, false);
}
Doing so will let us do this:
HANDLE hProc = ...; // Get process handle as usual
CreateRemoteThread(hProc, nullptr, 0, ShowGameMessage, "Hello World!", 0, nullptr);
Here we create a thread in the context of the game. This is necessary since we cannot call functions in the address space of another process. Now we can of course create another wrapper around this. However keep in mind that launching a remote thread is quite "slow".
General Tutorials
Animation Tutorials
Audio Tutorials
File & In Game IDs
- Accessory and Specialized Tool IDs (Asset)
- Armor IDs (Asset)
- Decorations IDs
- EFX IDs
- Endemic Critter IDs (Asset)
- Face IDs (Asset)
- Furniture IDs (Asset)
- Gimmick IDs (Asset)
- Hairstyle IDs (Asset)
- Item IDs
- LMT IDs
- Material IDs
- Medal IDs
- Model Bone Function IDs
- Monster IDs
- Monster Shell IDs (A-P)
- Monster Shell IDs (Q-Z)
- NPC IDs (Asset)
- NPC Base Model (Asset)
- Palico Equipment IDs (Asset)
- Pendant IDs (Asset)
- Poogie Clothes IDs
- Quest IDs
- Skill IDs
- Stage IDs (Asset)
- Player Weapon Action IDs
- Weapon IDs (Asset)
- Weapon ID Dump (GS,SnS,DB)
- Weapon ID Dump (LS,Ham,HH)
- Weapon ID Dump (Lan,GL)
- Weapon ID Dump (SA,CB)
- Weapon ID Dump (Bow,HBG,LBG)
Model Tutorials
- Quick Guide to Importing Models (Blender 2.79)
- Walkthrough of a Weapon Import
- Basics of Exporting Into the .mod3 Format
- How To Fix UVs Sharing a Seam
- How To Separate Mesh Parts in Blender
- Rotating, Moving and Resizing in Blender
- How to Split a Single Mesh Outfit into Player Equippable Parts
- Jigglebone Chains (.ctc) and Colliders (.ccl)
- Axial CTC Rotations
- Editing Hair Models and Materials
- Useful Blender Scripts
- [external page] How to Make All Polygons Into Triangles (Required for MHW models)
- [external page] How to Convert Triangles Back Into Quads
- [external page] How to Change The View-port clipping Parameters For Large Models
- [external page] How to Set Origin to Vertex in Edit Mode
- [external page] Shortcut to repeat the last operation in Blender
- [external page] Transferring Rig Weights From One Mesh To Another
- [external page] How to Copy Paint Weights From One Object to Another
- [external page] How to Remove All Zero-Weight Vertex Groups
- [external page] How to Weight Paint Against Current Pose
- [external page] Making a Hair Rig
- [external page] Physics Transfer
EFX Tutorials
FSM Editing
MRL3 Tutorials
NPC Editing
Plugins and Memory Editing
Monster AI Editing
General Texture Tutorials
- Obtaining, Converting and Replacing Textures
- Textures with Paint NET
- How To Open DDS Files
- Editing Textures
- Understanding Alpha Channels
- Exporting Textures with Transparency
- How To Achieve Glass Texture
- How to create Crystal materials with Alpha Textures
- Working Around the Mip Map Loading Bug
- [external page] Extracting a UV Layout
Specific Texture Tutorials
Asterisk's Plugin Notes
Miscellaneous Tutorials
Outdated Tutorials
- How to Make an NPC Skin Material Support Skin Color Customization
- Plugin Comparison
- A Theoretical Proposal on Skeleton Extension
- Monster Hunter World Save Editor Tutorial
- Making Copies of a Save Slot
- Making a Green Screen
- Notes on CTC Physics Jiggle Files
- Opening MRL3 file with a template
- Transferring MRL3 Files Between Models
- Expanding mrl3 Reference List
- How to Edit Eye Color in mrl3 Files