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!

C++ Get Monster ID

Newbie Spellweaver
Joined
May 12, 2016
Messages
8
Reaction score
2
Hello everyone,
I'm coding some addons and I'm stuck on something.
I'm using MadKnight spawn mob snippet :
PHP:
int getX = *(_DWORD *)((int)pPlayer + 332);    
int getY = *(_DWORD *)((int)pPlayer + 336);    
int getZ = *(_DWORD *)((int)pPlayer + 340);    
int getMap = *(_DWORD *)((int)pPlayer + 316);    
int Monsterindex = 47;    
int spawntime = 20;    
int amount = 20;

Dereference((DWORD)0x0044402B,(DWORD)Monsterindex);   
Dereference((DWORD)0x004440A6,(DWORD)getX);    
Dereference((DWORD)0x004440AD,(DWORD)getY);    
Dereference((DWORD)0x004440BA,(DWORD)getMap);    
Dereference((DWORD)0x00444129,(DWORD)spawntime);

for (int i = 0; i < amount; i++){        
__asm push 0        
__asm mov edx, 0x00443FD0        
__asm call edx        
__asm add esp, 4     
}
I don't know how you can get monster's ID or pointer, someone can give me a tip or the way you found it, thank you.
 
Joined
Jul 2, 2007
Messages
646
Reaction score
291
Monster ID -> cchar object(monster) offset + 28 (you can use also CBase::Id(Object) in order to get the ID for any object, it's just returns + 28)
Monster Index -> cchar object (monster) offset + 512

As I see he call CMonsterBigBirdMaster::Create() which means he just edit the index of monster as it referred here: Index = 318; (44402B)

You don't need to get monster index nor pointer, also this function type is void which means it get no value, if you willing to get the monster offset you should rewrite the whole function and then return to the monster offset.
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
May 12, 2016
Messages
8
Reaction score
2
Oh sorry I think I misspoke, I want to creat a monster then get his pointer (or his Mainserver ID, with the function to get the pointer with ID) to add some script on it.
Thank for the reply
 
Upvote 0
Joined
Jul 2, 2007
Messages
646
Reaction score
291
Oh sorry I think I misspoke, I want to creat a monster then get his pointer (or his Mainserver ID, with the function to get the pointer with ID) to add some script on it.
Thank for the reply

void __cdecl CMonsterBigBirdMaster::Create -> return no value. (void)

pointer-> what you seek:
nMonster = CMonsterBigBirdMaster::CMonsterBigBirdMaster(malloc(0x2B0));
Rewrite the whole function and then return to nMonster, don't forget to use the arguments to your needs.

then it should look like this:
int MyMonster = MySummonFunction(Index, map, x, y, z)

MyMonster -> pointer.
 
Upvote 0
Skilled Illusionist
Joined
Mar 20, 2009
Messages
374
Reaction score
378
You also could simply call Server::CMonster::Create(&gen, 0); with a strukt as Input.
And a hook at CChar::Unlock() inside the CMonster::Create() function to get the pointer.
Not the best way but it is working.

Code:
Memory->Hook(0x0043A1E9, SaveMonsterPtr);

void __fastcall SaveMonsterPtr(void *Monsterptr, void*_edx){
	UNREFERENCED_PARAMETER(_edx);
	Server::CChar::Unlock(Monsterptr);
	MonsterSummonPtr = (int*)Monsterptr;
}

struct GenMonster{
	int s_gen[22];
	int dummy[4];
};

GenMonster SetGenMonster(int index, int x1, int y1, int x2, int y2, int map){
	GenMonster myMonster;
	ZeroMemory(&myMonster, sizeof myMonster);
	myMonster.s_gen[0] = 0x4B7DC8;
	myMonster.s_gen[8] = index;
	myMonster.s_gen[9] = map;
	myMonster.s_gen[10] = rand() % 1000000 + 1000000;
	myMonster.s_gen[11] = 1;
	myMonster.s_gen[13] = 1;
	myMonster.s_gen[14] = x1;
	myMonster.s_gen[15] = y1;
	myMonster.s_gen[16] = x2;
	myMonster.s_gen[17] = y2;
	myMonster.s_gen[18] = *(DWORD*)0x4E2738;
	myMonster.s_gen[19] = GetTickCount();
	myMonster.s_gen[20] = 1000;
	return myMonster;
}


int* KSummon::Spawn(int index, int x, int y, int map){
	GenMonster gen;
	gen = SetGenMonster(index, x, y, x, y, map);
	Server::CMonster::Create(&gen, 0);
	return MonsterSummonPtr;
}


void KSummon::Monster(int index, int x, int y, int map, int amount, int casterid, bool DeSpawn, unsigned int endtick){
	int* Mobptr;
	Summon_Base summon_base;
	unsigned int SummonTick = GetTickCount();
	for (int i = 0; i < amount; i++)
	{
		Mobptr = this->Spawn(index, x, y, map);
		KMonster Mob(Mobptr);
		summon_base.CasterID = casterid;
		summon_base.MobID = Mob.GetBaseID();
		summon_base.Type = SummonType::Normal;
		summon_base.Despawn = DeSpawn;
		summon_base.endtick = SummonTick + (endtick * 1000);
		summon_base.ParentID = 0;
		SummonVec.push_back(summon_base);		
	}
}
 
Last edited:
Upvote 0
Joined
Jul 2, 2007
Messages
646
Reaction score
291
Well I thought no one has found genmonster summon before but seems you did.
I found it a while ago while checking the CMonster::Create function.
If you want to play with summon then it will be necessary to return to monster offset, but I made a simple way of summoning with gen monster and since you shared I'll show as well.

Code:
int CreateGenMonster(int Index, int map, int max, int cycle, int X, int Y, int nX, int nY)
{
    int Object = 0, CompareObject = 0, CreateCompareObject = 0, GenOffset = 0;


    Unnamed::nGetObject(0x004E1870, (int)&Object);
    CompareObject = Unnamed::CompareObjectValue(0x004E1870, (int)&CreateCompareObject);
    
    if (!Unnamed::CompareValues((int)&Object, (int)&CreateCompareObject))
        return 0;
    
    GenOffset = *(DWORD*)(Unnamed::GetOffset((int)&Object) + 4);


    if (GenOffset)
    {
        *(DWORD *)(GenOffset + 32) = Index;
        *(DWORD *)(GenOffset + 36) = map;
        *(DWORD *)(GenOffset + 40) = -1;
        *(DWORD *)(GenOffset + 44) = max;
        *(DWORD *)(GenOffset + 56) = X;
        *(DWORD *)(GenOffset + 60) = Y;
        *(DWORD *)(GenOffset + 64) = nX;
        *(DWORD *)(GenOffset + 68) = nY;
        *(DWORD *)(GenOffset + 80) = cycle;


        for (int i = 0; i < max; i++)
        {
            if (CMonster::Create(GenOffset, 0))
                InterlockedIncrement((volatile LONG *)(GenOffset + 48));
        }
        return 1;
    }


    return 0;
}

Also @Darn, *(DWORD *)(GenOffset + 40) -> Area ([10]), not monster ID.
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
May 12, 2016
Messages
8
Reaction score
2
Thank you guys for your contributions.
Very nice Darn, that's a good idea why I did not think about it.
Here my "dirty way" functions inspired by Darn :

Code:
Tools->DetourFunction((PBYTE)0x00444222, (PBYTE)GetpMonster, 5);

int pSummonMonster = 0;
void _declspec (naked) GetpMonster(){   
    __asm {           
         push  edx            
         mov   ecx, [ebp-8]            
         mov   pSummonMonster, ecx            
         mov   eax, 0x0043A200            
         call  eax    
   }    
   JumpTo(0x0044422B);
}

int SummonMonster(int Monsterindex, int getX, int getY, int getMap, int spawntime){    
    Tools->Dereference((DWORD)0x0044402B,(DWORD)Monsterindex);    
    Tools->Dereference((DWORD)0x004440A6,(DWORD)getX);    
    Tools->Dereference((DWORD)0x004440AD,(DWORD)getY);    
    Tools->Dereference((DWORD)0x004440BA,(DWORD)getMap);    
    Tools->Dereference((DWORD)0x00444129,(DWORD)spawntime);    
    __asm{            
         push 0            
         mov edx, 0x00443FD0            
         call edx    
    }    
    if(pSummonMonster)    return pSummonMonster;    
    else return 0;
}
 
Upvote 0
Newbie Spellweaver
Joined
May 12, 2016
Messages
8
Reaction score
2
Thank you guys for your contributions.
Very nice Darn, that's a good idea why I did not think about it.
Here my "dirty way" functions inspired by Darn :

Code:
Tools->DetourFunction((PBYTE)0x00444222, (PBYTE)GetpMonster, 5);

int pSummonMonster = 0;
void _declspec (naked) GetpMonster(){
    __asm {
       push edx
       mov ecx, [ebp-8]
       mov pSummonMonster, ecx
       mov eax, 0x0043A200
       call eax
    }
    JumpTo(0x0044422B);
}

int SummonMonster(int Monsterindex, int getX, int getY, int getMap, int spawntime){
    Tools->Dereference((DWORD)0x0044402B,(DWORD)Monsterindex);
    Tools->Dereference((DWORD)0x004440A6,(DWORD)getX);
    Tools->Dereference((DWORD)0x004440AD,(DWORD)getY);
    Tools->Dereference((DWORD)0x004440BA,(DWORD)getMap);
    Tools->Dereference((DWORD)0x00444129,(DWORD)spawntime);   
    __asm{            
       push 0
       mov edx, 0x00443FD0
       call edx    
    }    
    if(pSummonMonster)    return pSummonMonster;    
    else return 0;
}
 
Upvote 0
Newbie Spellweaver
Joined
May 12, 2016
Messages
8
Reaction score
2
Thank you guys for your contributions.
Very nice Darn this is a good idea why I didn't think of this.
Here my "dirty way" functions inspired by Darn :

Code:
Tools->DetourFunction((PBYTE)0x00444222, (PBYTE)GetpMonster, 5);
int pSummonMonster = 0;
void _declspec (naked) GetpMonster(){   
 __asm {            
      push edx            
      mov ecx, [ebp-8]            
      mov pSummonMonster, ecx            
      mov eax, 0x0043A200            
      call eax    
   }    
   JumpTo(0x0044422B);
}
int SummonMonster(int Monsterindex, int getX, int getY, int getMap, int spawntime){    
   Tools->Dereference((DWORD)0x0044402B,(DWORD)Monsterindex);    
   Tools->Dereference((DWORD)0x004440A6,(DWORD)getX);    
   Tools->Dereference((DWORD)0x004440AD,(DWORD)getY);    
   Tools->Dereference((DWORD)0x004440BA,(DWORD)getMap);    
   Tools->Dereference((DWORD)0x00444129,(DWORD)spawntime);    
   __asm{           
      push 0            
      mov edx, 0x00443FD0            
      call edx    
   }    
   if(pSummonMonster)    return pSummonMonster;    
   else return 0;
}

I'm still using CMonsterBigBirdMaster::Create, should I use instead CMonster::Create ?
 
Upvote 0
Joined
Jul 2, 2007
Messages
646
Reaction score
291
When you use CMonsterBigBirdMaster your monster will have the type of a boss all the time, that means AI will be default 3 and some other things, also summoning boxes and few other kind of monster will not work correctly.

While using CMonster::Create you will have the advantage of summoning any kind of monster (CORRECTLY!) beside doggebi lord if I am not mistaken.
 
Upvote 0
Skilled Illusionist
Joined
Mar 20, 2009
Messages
374
Reaction score
378
Yes you should use CMonster::Create just call it or rewrite the function.
And by the way CMonsterBigBirdMaster::Create is used for the queen if im not mistaken.
if you edit it without changing it back the queen summon won't work correctly.
 
Upvote 0
Newbie Spellweaver
Joined
May 12, 2016
Messages
8
Reaction score
2
You're right guys, the IA boss type also prevents the monster from being beheaded, I'll go with CMonster::Create for now, thanks for your infos. :)

I find the gameplay of kal outdated so I rewriting everything (skills, buffs, etc..).
I created a new thread with a loop on mainsrv, it seems to be unstable and make mainsrv crash sometime when I use some mainsrv functions.

Do you know some mainsrv loop functions or adresses that I could hook? I tried with Tick functions but I find the 1sec iteration too slow.
 
Upvote 0
Skilled Illusionist
Joined
Mar 20, 2009
Messages
374
Reaction score
378
You might have to enter critical section to prevent it from crashing depending on what you trying to do.
The tick functions are all i know, not sure if there is anything faster as the 1 sec tick.
 
Upvote 0
Back
Top