Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[Release] HP Bar Source 99.6XT (Main 1.00.13)

Newbie Spellweaver
Joined
Mar 9, 2010
Messages
46
Reaction score
71
Hello,
I finally found some spare time to finish this small project. As i promised i'm releasing it after it's finished. The release includes source code without compiled binaries, everyone who wanna use it can compile it, so i leave this part to you guys.

Client Side

HealthBar.h
Code:
#pragma once

#include "stdafx.h"
#include <gl\GL.h>

#pragma comment(lib,"Opengl32.lib")

#define MAX_MAIN_VIEWPORT 400

struct NEW_HEALTH_BAR
{
	WORD index;
	BYTE type;
	BYTE rate;
};


struct VAngle
{
	float X;
	float Y;
	float Z;
};

void ClearNewHealthBar();
void InsertNewHealthBar(WORD index, BYTE type, BYTE rate);
NEW_HEALTH_BAR* GetNewHealthBar(WORD index, BYTE type);
void DrawNewHealthBar();

#define pCursorX					*(DWORD *)0x7CBAF14
#define pCursorY					*(DWORD *)0x7CBAF10
#define pProtocolCall				0x004CDA7D
#define pGLSwitch					((void(*)()) 0x005F10B0)
#define pDrawBarForm				((void(*)(float PosX, float PosY, float Width, float Height)) 0x005F21D0)
#define pGetPosFromAngle			((void(*)(int a1, int a2, int a3)) 0x005F0CE0) 
#define pSetBlend					((char(*)(BYTE Mode)) 0x005F1130)
#define pDrawText					((int(*)(int posX, int posY, LPCSTR lpString, int a4, char a5, int a6))  0x00534350 )
#define DrawText					((char(*)(int a1, int a2, LPCSTR lpString))0x005343A0)
#define DrawText2					((int(*)(int a1, int a2, LPCSTR lpString, int a4, char a5, int a6))0x005342A0)
#define pSetTextColor				((void(__thiscall*)(HDC hdc, COLORREF h)) 0x00661030) // OK

#define MU_CDC_GET_THIS_POINTER		0x00643470		//99.6XT
#define MU_CDC_TABBEDTEXTOUT		0x00454500		//99.6XT

HealthBar.cpp

Code:
#include "stdafx.h"

NEW_HEALTH_BAR gNewHealthBar[MAX_MAIN_VIEWPORT];


void ClearNewHealthBar() // OK
{
	for (int n = 0; n < MAX_MAIN_VIEWPORT; n++)
	{
		gNewHealthBar[n].index = 0xFFFF;
		gNewHealthBar[n].type = 0;
		gNewHealthBar[n].rate = 0;
	}
}


void InsertNewHealthBar(WORD index, BYTE type, BYTE rate) // OK
{
	for (int n = 0; n < MAX_MAIN_VIEWPORT; n++)
	{
		if (gNewHealthBar[n].index == 0xFFFF)
		{
			gNewHealthBar[n].index = index;
			gNewHealthBar[n].type = type;
			gNewHealthBar[n].rate = rate;
			return;
		}
	}
}


NEW_HEALTH_BAR* GetNewHealthBar(WORD index, BYTE type) // OK
{
	for (int n = 0; n < MAX_MAIN_VIEWPORT; n++)
	{
		if (gNewHealthBar[n].index != 0xFFFF)
		{
			if (gNewHealthBar[n].index == index && gNewHealthBar[n].type == type)
			{
				return &gNewHealthBar[n];
			}
		}
	}

	return 0;
}


void DrawNewHealthBar() // OK
{
	((void(*)())0x00581D30)();

	int PosX, PosY, LifeProgress;
	float LifeBarWidth = 38.0f;
	char LifeDisplay[20];
	VAngle Angle;

	for (int n = 0; n < MAX_MAIN_VIEWPORT; n++)
	{
		int ViewportAddress = *(DWORD*)(0x73C8174) + 1068 * n;

		int mIndex = *(WORD*)(ViewportAddress + 492);
		int MonsterType = *(BYTE*)(ViewportAddress + 132);

		if (!ViewportAddress)
		{
			continue;
		}

		NEW_HEALTH_BAR* lpNewHealthBar = GetNewHealthBar(mIndex, MonsterType);

		if (lpNewHealthBar == 0)
		{
			continue;
		}

		int LifePercent = lpNewHealthBar->rate / 10;

		Angle.X = *(float*)(ViewportAddress + 0x10);
		Angle.Y = *(float*)(ViewportAddress + 0x14);
		Angle.Z = *(float *)(ViewportAddress + 308) + *(float *)(ViewportAddress + 24) + 100.0f;

		pGetPosFromAngle((int)&Angle, (int)&PosX, (int)&PosY);

		PosX -= (int)floor(LifeBarWidth / (double)2.0);

		if ((pCursorX >= PosX) && ((float)pCursorX <= (float)PosX + LifeBarWidth) && (pCursorY >= PosY - 2) && (pCursorY < PosY + 6))
		{
			sprintf_s(LifeDisplay, "HP : %d0%%", LifePercent);
			pDrawText(PosX, PosY - 6, LifeDisplay, 0, 0, 1);
		}

		pSetBlend(true);

		glColor4f(0.0, 0.0, 0.0, 0.5);
		pDrawBarForm((float)(PosX + 1), (float)(PosY + 1), LifeBarWidth + 4.0f, 5.0f);

		pSetBlend(true);

		glColor3f(0.2f, 0.0, 0.0);
		pDrawBarForm((float)PosX, (float)PosY, LifeBarWidth + 4.0f, 5.0f);

		glColor3f(0.19607843f, 0.039215688f, 0.0);
		pDrawBarForm((float)(PosX + 2), (float)(PosY + 2), LifeBarWidth, 1.0f);

		if (LifePercent > 10)
		{
			LifeProgress = 10;
		}
		else
		{
			LifeProgress = LifePercent;
		}

		glColor3f(0.98039216f, 0.039215688f, 0.0);

		for (int i = 0; i < LifeProgress; i++)
		{
			pDrawBarForm((float)(i * 4 + PosX + 2), (float)(PosY + 2), 3.0, 2.0);
		}

		pGLSwitch();
	}

	pGLSwitch();
	glColor3f(1.0, 1.0, 1.0);
}

Protocol.h

Code:
#ifndef _Protocol_H
#define _Protocol_H

#include "StdAfx.h"
#include "Packets.h"

#define ProtocolCore				((BOOL(*)(DWORD,BYTE*,DWORD,DWORD))0x004CDB60)

extern DWORD *GameIndex;

int cMU_ProtocolCore(int index, PBYTE lpMsg, int len, int flags);
void GCNewHealthBarRecv(PMSG_NEW_HEALTH_BAR_RECV* lpMsg);

#endif

Protocol.cpp

Code:
#include "StdAfx.h"

DWORD *GameIndex = (DWORD*)0x78305B4;

int cMU_ProtocolCore(int index, PBYTE lpMsg, int len, int flags)
{
	switch (index)
	{
	case 0xF3:
	{
		switch(((lpMsg[0]==0xC1)?lpMsg[3]:lpMsg[4]))
		{
		case 0xE2:
			GCNewHealthBarRecv((PMSG_NEW_HEALTH_BAR_RECV*)lpMsg);
			return 1;
		}

		break;
	}
	}

	return ProtocolCore(index, lpMsg, len, flags);
}

void GCNewHealthBarRecv(PMSG_NEW_HEALTH_BAR_RECV* lpMsg) // OK
{
	ClearNewHealthBar();

	for (int n = 0; n < lpMsg->count; n++)
	{
		PMSG_NEW_HEALTH_RECV* lpInfo = (PMSG_NEW_HEALTH_RECV*)(((BYTE*)lpMsg) + sizeof(PMSG_NEW_HEALTH_BAR_RECV) + (sizeof(PMSG_NEW_HEALTH_RECV)*n));

		InsertNewHealthBar(lpInfo->index, lpInfo->type, lpInfo->rate);
	}
}

dllmain.cpp

Code:
#include "stdafx.h"

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

extern "C" _declspec(dllexport) void TheLast()
{
	DWORD OldProtect;
	if (VirtualProtect(LPVOID(0x401000), 2490366, PAGE_EXECUTE_READWRITE, &OldProtect))
	{
		ToolKit.SetCompleteHook(0xFF, MU_PROTOCOL_CORE, &cMU_ProtocolCore);
		ToolKit.SetCompleteHook(0xE8, 0x00580806, &DrawNewHealthBar);
	}
}

GameServer Side

Health packet info worker

Code:
void Start(){
_beginthread(TimerWorker, 0, NULL);
}

void TimerWorker(void * ignored) {

	while (true)
	{
		for (int n = 0; n < OBJECT_MAX; n++)
		{
			LPOBJ lpObj = gObj(n);

			if (lpObj->Type == OBJECT_USER && lpObj->Connected == 3)
			{
				GCNewHealthBarSend(lpObj);
			}
		}

		Sleep(500);
	}
}

void __cdecl GCNewHealthBarSend(LPOBJ lpObj) // OK
{
	BYTE send[4096];

	PMSG_NEW_HEALTH_BAR_SEND pMsg;

	pMsg.header.set(0xF3, 0xE2, 0);

	int size = sizeof(pMsg);

	pMsg.count = 0;

	PMSG_NEW_HEALTH_BAR info;

	for (int n = 0; n < MAX_VIEWPORT; n++)
	{
		if (lpObj->VpPlayer[n].state != VIEWPORT_SEND && lpObj->VpPlayer[n].state != VIEWPORT_WAIT)
		{
			continue;
		}

		if (lpObj->VpPlayer[n].type != OBJECT_MONSTER)
		{
			continue;
		}

		if (OBJECT_RANGE(lpObj->VpPlayer[n].index) == 0)
		{
			continue;
		}

		LPOBJ lpTarget = gObj(lpObj->VpPlayer[n].index);

		if (lpTarget->Live == 0)
		{
			continue;
		}

		info.index = lpTarget->m_Index;

		info.type = (BYTE)lpTarget->Type;

		info.rate = (BYTE)((lpTarget->Life * 100) / (lpTarget->MaxLife + lpTarget->AddLife));

		memcpy(&send[size], &info, sizeof(info));
		size += sizeof(info);

		pMsg.count++;
	}

	pMsg.header.size[0] = SET_NUMBERHB(size);

	pMsg.header.size[1] = SET_NUMBERLB(size);

	memcpy(send, &pMsg, sizeof(pMsg));

	DataSend(lpObj->m_Index, send, size);
}

Packet.h

Code:
struct PSWMSG_HEAD
{
	void set(BYTE head, BYTE subh, WORD size) // OK
	{
		this->type = 0xC2;
		this->size[0] = HIBYTE(size);
		this->size[1] = LOBYTE(size);
		this->head = head;
		this->subh = subh;
	}

	void setE(BYTE head, BYTE subh, WORD size) // OK
	{
		this->type = 0xC4;
		this->size[0] = HIBYTE(size);
		this->size[1] = LOBYTE(size);
		this->head = head;
		this->subh = subh;
	}

	BYTE type;
	BYTE size[2];
	BYTE head;
	BYTE subh;
};

struct PMSG_NEW_HEALTH_BAR_RECV
{
	PSWMSG_HEAD header; // C2:F3:E2
	BYTE count;
};

struct PMSG_NEW_HEALTH_RECV
{
	WORD index;
	BYTE type;
	BYTE rate;
};

Misc

Code:
#define MU_PROTOCOL_CORE	0x004CDA7D

enum eViewportState
{
	VIEWPORT_NONE = 0,
	VIEWPORT_SEND = 1,
	VIEWPORT_WAIT = 2,
	VIEWPORT_DESTROY = 3,
};

#define OBJECT_RANGE(x) (((x)<0)?0:((x)>=OBJECT_MAX)?0:1)
#define OBJECT_MONSTER_RANGE(x) (((x)<0)?0:((x)>=OBJ_MAXMONSTER)?0:1)

#define SET_NUMBERHB(x) ((BYTE)((DWORD)(x)>>(DWORD)8))
#define SET_NUMBERLB(x) ((BYTE)((DWORD)(x)&0xFF))
#define SET_NUMBERHW(x) ((WORD)((DWORD)(x)>>(DWORD)16))
#define SET_NUMBERLW(x) ((WORD)((DWORD)(x)&0xFFFF))
#define SET_NUMBERHDW(x) ((DWORD)((QWORD)(x)>>(QWORD)32))
#define SET_NUMBERLDW(x) ((DWORD)((QWORD)(x)&0xFFFFFFFF))

Code:
void ToolKitEx::SetCompleteHook(BYTE head, DWORD offset, ...) // OK
{
	DWORD OldProtect;

	VirtualProtect((void*)offset, 5, PAGE_EXECUTE_READWRITE, &OldProtect);

	if (head != 0xFF)
	{
		*(BYTE*)(offset) = head;
	}

	DWORD* function = &offset + 1;

	*(DWORD*)(offset + 1) = (*function) - (offset + 5);

	VirtualProtect((void*)offset, 5, OldProtect, &OldProtect);
}

Main.exe Link :

pz7QKT - [Release] HP Bar Source 99.6XT (Main 1.00.13) - RaGEZONE Forums


 

Attachments

You must be registered for see attachments list
Last edited:
Newbie Spellweaver
Joined
Oct 1, 2015
Messages
98
Reaction score
2
You can build a dll file , Thank you for your interest
 
Newbie Spellweaver
Joined
Mar 9, 2010
Messages
46
Reaction score
71
Mmm ya but down below it checks does the Monsters are in the view port so it just need to be checked are there any visible at the moment. So the packet must not be sent if no monsters are in the viewport currently. We must simply avoid sending when no monsters are in viewport or hook the ViewportAdd func and send packet per monster. There are tons of ways to implement this, the source code is just a bare example of what can be done and how, that's why is not released as compiled .dll (everyone is free to use/change do whatever he want). To goal was to find the offsets and render the bars, i won't focus on the server side because this isn't a server side project, ofc you are right about the CPU usage.
 
Joined
Nov 4, 2012
Messages
928
Reaction score
544
The problem is not really send or not, but the loop itself.
If this gameservers is look a bit of mine (Even if you use dll), did you will have a game loop that already do this, you need only to send at this loop;

i recommend to do call GCNewHealthBarSend(lpObj); at void MonsterAndMsgProc() function, before

Code:
			if ( lpObj->Type == OBJ_USER )
			{
				gDarkSpirit[n].Run();
			}

check, since MonsterAndMsgProc is already done for this type of loop on viewport.
Also you need to verify if life is -1 (Or simple if it is above of maxlife of monster), since can bug in some situations.

Ps. I will try to put my code here to help when i go to home

This function is like a muemu function :p
 
Newbie Spellweaver
Joined
Mar 9, 2010
Messages
46
Reaction score
71
Ya good call about MonsterAndMsgProc().
As i don't have time to implement it right now will share some dummy code.

Code:
SetCompleteHook(0xE9, 0x004C4869, &TimerTick); // Hook at CDarkSpirit::Run((CDarkSpirit *)&gDarkSpirit + n); position

__declspec(naked) void TimerTick(){

_asm {
		push EAX //lpObj instance
		call &GCNewHealthBarSend
		MOV ECX, DWORD PTR SS : [EBP - 0x8]
		IMUL ECX, ECX, 0x28
		ADD ECX, 0x3A77ED8 //CDarkSpirit class
		CALL 00402478 // CDarkSpirit::Run func
	}
}

That's the code of the original MonsterAndMsgProc() function

Code:
for ( n = 0; n < 4000; ++n )
  {
    lpObj = &gObj + n;
    if ( *(&gObj.Connected + 1379 * n) == 3 )
    {
      if ( lpObj->Type != 2 && lpObj->Type != 3 )
      {
        gObjSkillUseProcTime500(lpObj);
        gObjMsgProc(lpObj);
        CreateFrustrum(lpObj->X, lpObj->Y, n);
      }
      else
      {
        gObjMonsterProcess(lpObj);
      }
      if ( lpObj->Type == 1 )
        CDarkSpirit::Run((CDarkSpirit *)&gDarkSpirit + n);
    }
    else if ( lpObj->Connected >= 2 && lpObj->Type == 1 )
    {
      gObjMsgProc(lpObj);
      if ( lpObj->Connected == 3 )
        CreateFrustrum(lpObj->X, lpObj->Y, n);
    }
  }

And the ASM of the 'if'

Code:
004C4864    83F9 01         CMP ECX,0x1
004C4867    75 11           JNZ SHORT 004C487A                       ; 004C487A
004C4869    8B4D F8         MOV ECX,DWORD PTR SS:[EBP-0x8]
004C486C    6BC9 28         IMUL ECX,ECX,0x28
004C486F    81C1 D87EA703   ADD ECX,0x3A77ED8
004C4875    E8 FEDBF3FF     CALL 00402478                            ; 00402478
 
Junior Spellweaver
Joined
Dec 25, 2014
Messages
143
Reaction score
3
you can post fixed ?

+ packet.h ?
or full source plz in visual ?
 
Newbie Spellweaver
Joined
Mar 9, 2010
Messages
46
Reaction score
71
you can post fixed ?

+ packet.h ?
or full source plz in visual ?

Sorry i missed that...

Packet.h

Code:
struct PSWMSG_HEAD
{
	void set(BYTE head, BYTE subh, WORD size) // OK
	{
		this->type = 0xC2;
		this->size[0] = HIBYTE(size);
		this->size[1] = LOBYTE(size);
		this->head = head;
		this->subh = subh;
	}

	void setE(BYTE head, BYTE subh, WORD size) // OK
	{
		this->type = 0xC4;
		this->size[0] = HIBYTE(size);
		this->size[1] = LOBYTE(size);
		this->head = head;
		this->subh = subh;
	}

	BYTE type;
	BYTE size[2];
	BYTE head;
	BYTE subh;
};

struct PMSG_NEW_HEALTH_BAR_RECV
{
	PSWMSG_HEAD header; // C2:F3:E2
	BYTE count;
};

struct PMSG_NEW_HEALTH_RECV
{
	WORD index;
	BYTE type;
	BYTE rate;
};
 
Junior Spellweaver
Joined
May 1, 2009
Messages
192
Reaction score
17
in this
ToolKit.SetCompleteHook(0xFF, MU_PROTOCOL_CORE, &cMU_ProtocolCore);

MU_PROTOCOL_CORE is missing define, what is MU_PROTOCOL_CORE ?
 
Junior Spellweaver
Joined
Dec 25, 2014
Messages
143
Reaction score
3
Sorry i missed that...

Packet.h

Code:
struct PSWMSG_HEAD
{
    void set(BYTE head, BYTE subh, WORD size) // OK
    {
        this->type = 0xC2;
        this->size[0] = HIBYTE(size);
        this->size[1] = LOBYTE(size);
        this->head = head;
        this->subh = subh;
    }

    void setE(BYTE head, BYTE subh, WORD size) // OK
    {
        this->type = 0xC4;
        this->size[0] = HIBYTE(size);
        this->size[1] = LOBYTE(size);
        this->head = head;
        this->subh = subh;
    }

    BYTE type;
    BYTE size[2];
    BYTE head;
    BYTE subh;
};

struct PMSG_NEW_HEALTH_BAR_RECV
{
    PSWMSG_HEAD header; // C2:F3:E2
    BYTE count;
};

struct PMSG_NEW_HEALTH_RECV
{
    WORD index;
    BYTE type;
    BYTE rate;
};

ToolKit.SetCompleteHook(0xFF, MU_PROTOCOL_CORE, &cMU_ProtocolCore); ToolKit.SetCompleteHook(0xE8, 0x00580806, &DrawNewHealthBar);

You can give me
code : ToolKit
and MU_PROTOCOL_CORE?
 
Junior Spellweaver
Joined
May 1, 2009
Messages
192
Reaction score
17
you can change ToolKit.SetCompleteHook -> HookOffset

and I think 0x004CDB60 = MU_PROTOCOL_CORE

void HookOffset(DWORD my, DWORD tohook, BYTE type)
{
*(BYTE*)tohook = type;
*(DWORD*)(tohook+1) = my - (tohook+5);
};

vankyy26 I said true or false ?...... :wink:
 
Junior Spellweaver
Joined
Dec 25, 2014
Messages
143
Reaction score
3
PMSG_NEW_HEALTH_BAR_SEND = code ?
PMSG_NEW_HEALTH_BAR = code ?
VIEWPORT_SEND = ?
VIEWPORT_WAIT = ?
OBJECT_RANGE = ?
SET_NUMBERHB = ?
SET_NUMBERLB = ?
 
Newbie Spellweaver
Joined
Mar 9, 2010
Messages
46
Reaction score
71
Code:
#define MU_PROTOCOL_CORE	0x004CDA7D

enum eViewportState
{
	VIEWPORT_NONE = 0,
	VIEWPORT_SEND = 1,
	VIEWPORT_WAIT = 2,
	VIEWPORT_DESTROY = 3,
};

#define OBJECT_RANGE(x) (((x)<0)?0:((x)>=OBJECT_MAX)?0:1)
#define OBJECT_MONSTER_RANGE(x) (((x)<0)?0:((x)>=OBJ_MAXMONSTER)?0:1)

#define SET_NUMBERHB(x) ((BYTE)((DWORD)(x)>>(DWORD)8))
#define SET_NUMBERLB(x) ((BYTE)((DWORD)(x)&0xFF))
#define SET_NUMBERHW(x) ((WORD)((DWORD)(x)>>(DWORD)16))
#define SET_NUMBERLW(x) ((WORD)((DWORD)(x)&0xFFFF))
#define SET_NUMBERHDW(x) ((DWORD)((QWORD)(x)>>(QWORD)32))
#define SET_NUMBERLDW(x) ((DWORD)((QWORD)(x)&0xFFFFFFFF))

Code:
void ToolKitEx::SetCompleteHook(BYTE head, DWORD offset, ...) // OK
{
	DWORD OldProtect;

	VirtualProtect((void*)offset, 5, PAGE_EXECUTE_READWRITE, &OldProtect);

	if (head != 0xFF)
	{
		*(BYTE*)(offset) = head;
	}

	DWORD* function = &offset + 1;

	*(DWORD*)(offset + 1) = (*function) - (offset + 5);

	VirtualProtect((void*)offset, 5, OldProtect, &OldProtect);
}
 
Junior Spellweaver
Joined
Dec 25, 2014
Messages
143
Reaction score
3
PMSG_NEW_HEALTH_BAR_SEND
PMSG_NEW_HEALTH_BAR

You can give me code ?
 
Newbie Spellweaver
Joined
Mar 9, 2010
Messages
46
Reaction score
71
PMSG_NEW_HEALTH_BAR_SEND
PMSG_NEW_HEALTH_BAR

You can give me code ?

It's the same as RCV lol ...

Code:
struct PMSG_NEW_HEALTH_BAR_SEND
{
	PSWMSG_HEAD header; // C2:F3:E2
	BYTE count;
};

struct PMSG_NEW_HEALTH_BAR
{
	WORD index;
	BYTE type;
	BYTE rate;
};

P.S.: Think over it, if you are trying to run it with copy/paste it won't work.
 

cMu

Elite Diviner
Joined
Jan 8, 2017
Messages
427
Reaction score
133
It's the same as RCV lol ...

Code:
struct PMSG_NEW_HEALTH_BAR_SEND
{
    PSWMSG_HEAD header; // C2:F3:E2
    BYTE count;
};

struct PMSG_NEW_HEALTH_BAR
{
    WORD index;
    BYTE type;
    BYTE rate;
};

P.S.: Think over it, if you are trying to run it with copy/paste it won't work.

Lol, you're so right bro!
 
Newbie Spellweaver
Joined
Jan 6, 2013
Messages
47
Reaction score
4
Someones know is visual studio for mac can be used or need to be some specific visual studio version?
 
Newbie Spellweaver
Joined
Jan 6, 2013
Messages
47
Reaction score
4
I'm not able to run Visual Studio on VM for MAC. can someone share me the dlls please?.
 
Back
Top