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!

[Arcturus - how to] No level restriction on drops

Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Dear all,
We have several projects for our server + we found very few good tutorials/how to on Arcturus.

Therefore we decided to create a new topic named [Arcturus - how to] for our current project. Our goal is:
- if someone knows how to do this, he can explain it here. This will help us a lot and at least a tuto page (this one!) will be finally available on this topic
- if no one knows, I guess after some time we will figure how to do and we will update this thread.

ROSE, for us, is an old game full of childhood dreams. We see no point in keeping secret in its development. The more you share a dream, the more you live it.

Cheers,

Numenor



The goal:
At the moment: when the difference in the monster level and the player level is too high, the loots will be affected.
Project: we would like to remove this limit

Notes:
This thread focus on [Arcturus], so please answer for Arcturus only or specify in your answer if you are speaking of an other version.

Why?
In our opinion, a monster is a monster. He should always drop the same thing "like in real live".
Furthermore our server will have a really small population. This will help a lot grinding (no need to loose lvl etc)
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Since we didn't get any answer, we assume no one knows how to do. Therefore here is what we've already looked at in case some people are interested.

So, we looked into all the STB, AIP and other 3DData stuffs without success (at least we learned a lot, Laurenzzo should soon release some info on the clan STL for example).
We will now look into TRose.exe and the .dll

Maybe it will be obvious to you that this information could not be in the STB etc. If it is the case, then you should have posted something, saying that "we should look there, or there".

We'll keep you informed and we hope to one day close this subject with the answer :)
Cheers!
 
Newbie Spellweaver
Joined
May 29, 2014
Messages
81
Reaction score
5
The drop level restriction isn't in any client files.

It is server sided, and hardcoded. You either need a worhty source code to work with, or a hell long time to spend on reverse engineering to find the offset(s) responsible for it.

It works this way:

The server compares player and monster levels. If the difference is < X, then we drop. Else we don't.

Hope it helped.




Hij.
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Thank you very (very!) much for your help Hijakob ! Thanks to you we know that:
- it is not specific to each monster, but a more general rule
- it is on the server side.
By the way, when you say it is on the server side, do you know in which file? In SHO_GS.dll ?

And about the drops, if there is this limit, is there also a difference in the drop you earn if you are close to the monster level or not ?
I mean, do you get better drop if the monster is yellow than blue or purple? And if yes, how to change this?

And yes, we tried to ask for the sources, but only receive negative answers. I hope one day we'll find someone who would like to share them because a lot of our projects look like they are related to the sources.

Thanks again!
 
Experienced Elementalist
Joined
Aug 19, 2007
Messages
294
Reaction score
26
It would be SHO_GS. That handles all of the ingame stuff. LS is for logging in and WS handles character select, clan chat, and some other stuff like whispers and such
 
Newbie Spellweaver
Joined
May 29, 2014
Messages
81
Reaction score
5
Like raven said, SHO_GS.dll handles this.

For the drop row picking it is a random formula. Steps are like this:

- Get monster ID in list_npc
- Find the linked drop row in drop row
- get a random rows from the drops.

the random calc takes the level difference in account. So yes it all depends on the monster color name as it is also based on monster/player level diff.




Hij.
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Ok, thank you very much both of you.
I guess that, to achieve what we want (i.e. always the same and the best drop at any level on a monster), we will have to change those two formula:
- no level limit
- no influence of the level in the drop rate

I started playing with the titanmods of ExJam (but have trouble to find what are the ExLib\Array.hpp, List.hpp, etc he's speaking about. I tried the std ones and the boost ones but without success... will try again this evening) and also try to reverse the dll myself (long process but at least I got more control). I will share with you what works :)

Again, thank you for your help!
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Hi guys,
Just a small update to share our progresses and in case you would have suggestion.

We had a look at the SHO_GS.exe in assembly (and started to learn assembly in the meantime ^^).
We searched for conditions* like :
CMP R8, 10
JA ...
And we found one !
We changed the comparison to 19, made some tests and... nothing changed ^^'

Well, a lot of similar conditions could exist, like
CMP R8, 9
JAE ...

We will continue searching that way since it could be a nice and simple way to change the files without the sources/reverse engineering for the Arcturus people.
By the way, if anyone with the source code could tell us what it the exact conditions, it would help us a lot while looking in the asm.

And this is just the first (easy) step: changing the limit. Then we'll have to find where is the random number generation you spoke about (also in SHO_GS if I understand well?)


*This idea came from the fact that we notice that: if level_monster-level_player > 10 then drop; else don't drop;
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Dear all,
It is with great pleasure that I can tell we did the first step!
Using ollydbg, we set (a lot of !) breakpoints to analyse what was happening when a monster was killed.
Eventually, we found those lines:
1005C56C 837D 08 0A CMP DWORD PTR SS:[EBP+8],0A
1005C570 7C 07 JL SHORT SHO_GS_1.1005C579


This is the test between your level difference with the monster and ... 10, but in hexadecimal! We are stupid ^^' So our first guess was not that bad, just we should have looked for 0xA instead of 10.


What we would have like to do, is to change this 0x0A into a 0xD2 (210).
However, when putting a too big number, it creates a new line (SHR CL, 0EC). And this makes things crash.
I think it has something to do with the size of the stack ? I don't know, started learning assembly only a few days ago ^^

Does any of you with greater knowledge of assembly could help us telling what we should do to be able to compare with a bigger number?


Also I'd like to thank you, once again :)
Without the precious information you shared, we would have probably taken ten times more times (knowing the logic and that is in SHO_GS.DLL; you did 99% of the work ^^)

Next step is to remove the level difference in the computation of your drop chances... and of course to learn more assembly to be able to put D2 :)


NB: For the moment, we have changed the JL by a JMP. As a temporary fix. But we don't really like it since it breaks the mechanics.



Final update:

This is the whole piece of code we are interesting in:

1005C55D 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
1005C561 7D 09 JGE SHORT SHO_GS_1.1005C56C
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A EB 0D JMP SHORT SHO_GS_1.1005C579
1005C56C 837D 08 0A CMP DWORD PTR SS:[EBP+8],0A
1005C570 7C 07 JL SHORT SHO_GS_1.1005C579

DWORD PTR SS:[EBP+8] is apparently the level difference with the monster.
Therefore, we see that it could be read like the following:


//we assume the level difference definition is: level_diff = level_player - level_monster; else it doesn't match what we observe in-game.

if (level_diff >= 0){
if (level_diff < 10){
//go to the drop computation with this level_diff
}
else{
//no drop
}
}
else{
level_diff = 0;
//and go to the drop computation with this level_diff
}


So, if I understand well what is done at the moment:

If lvl_player < lvl_monster, it means the lvl_diff < 0 -->so we have a drop with the best possible chance (we drop and level_diff is force to 0)
if lvl_player > lvl_monster, it means we will drop until the difference is >= 10; and the closer we are to the monster lvl, the best drops we have.
Correct?

And so, if I want to change this to be able to always have the best chance to drop, all I have to do is the following change :

1) The "let's erase everything"

In assembly:
1005C55D 90 NOP
1005C55E 90 NOP
1005C55F 90 NOP
1005C560 90 NOP
1005C561 90 NOP
1005C562 90 NOP
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A 90 NOP
1005C56B 90 NOP
1005C56C 90 NOP
1005C56D 90 NOP
1005C56E 90 NOP
1005C56F 90 NOP
1005C570 EB 07 JMP SHORT SHO_GS_1.1005C579




And if we translate this in C:

level_diff = 0;
//and go to the drop computation with this level_diff





2) The more soft version

In assembly:
1005C55D 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
1005C561 7D 09 JGE SHORT SHO_GS_1.1005C56C
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A EB 0D JMP SHORT SHO_GS_1.1005C579
1005C56C C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C570 EB 07 JMP SHORT SHO_GS_1.1005C579


And if we translate this in C:
if (level_diff >= 0){
level_diff = 0;
//go to the drop computation with this level_diff
}
else{
level_diff = 0;
//and go to the drop computation with this level_diff
}



I don't know if you have something more clever to suggest.

For us, this topic is close and is a first great success !!!
Thanks again all :)
 
Last edited:
Experienced Elementalist
Joined
Aug 19, 2007
Messages
294
Reaction score
26
Dear all,
It is with great pleasure that I can tell we did the first step!
Using ollydbg, we set (a lot of !) breakpoints to analyse what was happening when a monster was killed.
Eventually, we found those lines:
1005C56C 837D 08 0A CMP DWORD PTR SS:[EBP+8],0A
1005C570 7C 07 JL SHORT SHO_GS_1.1005C579


This is the test between your level difference with the monster and ... 10, but in hexadecimal! We are stupid ^^' So our first guess was not that bad, just we should have looked for 0xA instead of 10.


What we would have like to do, is to change this 0x0A into a 0xD2 (210).
However, when putting a too big number, it creates a new line (SHR CL, 0EC). And this makes things crash.
I think it has something to do with the size of the stack ? I don't know, started learning assembly only a few days ago ^^

Does any of you with greater knowledge of assembly could help us telling what we should do to be able to compare with a bigger number?


Also I'd like to thank you, once again :)
Without the precious information you shared, we would have probably taken ten times more times (knowing the logic and that is in SHO_GS.DLL; you did 99% of the work ^^)

Next step is to remove the level difference in the computation of your drop chances... and of course to learn more assembly to be able to put D2 :)


NB: For the moment, we have changed the JL by a JMP. As a temporary fix. But we don't really like it since it breaks the mechanics.



Final update:

This is the whole piece of code we are interesting in:

1005C55D 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
1005C561 7D 09 JGE SHORT SHO_GS_1.1005C56C
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A EB 0D JMP SHORT SHO_GS_1.1005C579
1005C56C 837D 08 0A CMP DWORD PTR SS:[EBP+8],0A
1005C570 7C 07 JL SHORT SHO_GS_1.1005C579

DWORD PTR SS:[EBP+8] is apparently the level difference with the monster.
Therefore, we see that it could be read like the following:


//we assume the level difference definition is: level_diff = level_player - level_monster; else it doesn't match what we observe in-game.

if (level_diff >= 0){
if (level_diff < 10){
//go to the drop computation with this level_diff
}
else{
//no drop
}
}
else{
level_diff = 0;
//and go to the drop computation with this level_diff
}


So, if I understand well what is done at the moment:

If lvl_player < lvl_monster, it means the lvl_diff < 0 -->so we have a drop with the best possible chance (we drop and level_diff is force to 0)
if lvl_player > lvl_monster, it means we will drop until the difference is >= 10; and the closer we are to the monster lvl, the best drops we have.
Correct?

And so, if I want to change this to be able to always have the best chance to drop, all I have to do is the following change :

1) The "let's erase everything"

In assembly:
1005C55D 90 NOP
1005C55E 90 NOP
1005C55F 90 NOP
1005C560 90 NOP
1005C561 90 NOP
1005C562 90 NOP
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A 90 NOP
1005C56B 90 NOP
1005C56C 90 NOP
1005C56D 90 NOP
1005C56E 90 NOP
1005C56F 90 NOP
1005C570 EB 07 JMP SHORT SHO_GS_1.1005C579




And if we translate this in C:

level_diff = 0;
//and go to the drop computation with this level_diff





2) The more soft version

In assembly:
1005C55D 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
1005C561 7D 09 JGE SHORT SHO_GS_1.1005C56C
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A EB 0D JMP SHORT SHO_GS_1.1005C579
1005C56C C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C570 EB 07 JMP SHORT SHO_GS_1.1005C579


And if we translate this in C:
if (level_diff >= 0){
level_diff = 0;
//go to the drop computation with this level_diff
}
else{
level_diff = 0;
//and go to the drop computation with this level_diff
}



I don't know if you have something more clever to suggest.

For us, this topic is close and is a first great success !!!
Thanks again all :)


What you want to do is :

1005C55D 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
1005C561 7D 09 JGE SHORT SHO_GS_1.1005C56C
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A EB 0D JMP SHORT SHO_GS_1.1005C579
1005C56C 90 NOP
1005C570 90 NOP


You might want to NOP
1005C563 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0
1005C56A EB 0D JMP SHORT SHO_GS_1.1005C579

as well but that may be a null pointer check so that way the server doesn't crash.


Don't forget you could always make a C++ dll and inject it into the server and do all of your programming work in C/C++ instead of having to do ASM. You would still have to do asm so you can find out other stuff.
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Thanks Raven. However what you suggest is not what we want.
In your case, if you hit a monster lvl 5 while being lvl 120, you won't drop anything since the level difference will be too high for your drop chance formula.
What we are using at the moment just force the "level_difference" used for the drop computation to be equal to 0. This without looking at the player and monster levels.


About dll injection, it is a good idea. I never played with that, I should learn. However I can see how it can be used to add new stuff, but to fix new stuff... it's a bit of a mystery for me. I'm trying to understand what titan did.

Honestly, I hope I will find someone who would agree to share the sources before I have to make too much asm ^^ But new knowledges are never lost :)
 
Newbie Spellweaver
Joined
May 29, 2014
Messages
81
Reaction score
5
If you want to stick to assembly, have you tried to simply get ridd of the CMP ?

You don't wish to have comparisons done (those will check level difference in our case), if you do it with caution you might be able to get the result you are aiming for.

about DLL hooking, this is what we used at RISE before having a hand on the source code.

If you wish to have more informations about it, here are a few handy links:

-
-

these two examples will give you a brief idea of what you want to do, and if you wish to study a rose specific example, the public repository publied by exjam called "titan-modmaster" you should have a look at their code and especially around TRose project that has the most explicit hooks examples.




Hij.
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Thanks a lot Hijakob!
I didn't try to just remove the CMP, I will give it a shot (even if, it's working as we wish for the moment :) )

Thanks also for the DLL injection links ! I didn't know where to start and your links look really useful! Will read them this evening.

About ExJam's titanmods, I tried to use them, but was stuck by all the headers in ExLib (ExLib/*.h). If by any chance you manage to make them work or find those headers, we would be really interested and grateful :)
The only thing I never understood is how they did to find all of this. I have the feeling that you have to know the sources to be able to do such things. But maybe it's because I don't know anything of reverse engineering ^^

Haha, one of my motivation to work on iROSE was because I felt confident enough in my programming skills (C, python, ...) and wanted to sharpen them but... eventually I landed in a world of asm and reverse engineering. It's unexpected, harder but fun :)

Best,


NB: Sorry for the late answer, for some reason I wasn't warned of your answer.
 
Newbie Spellweaver
Joined
Dec 30, 2015
Messages
35
Reaction score
0
Dear all,

Sorry the project has not advanced a lot on this side (was busy with real work :) ).
Looking at the difficulty to do our next project directly in assembly, I will try to redo this (very simple) project through DLL injection.

However, even with the links you sent it is still not obvious how to do DLL injection into ROSE for me. Therefore I was wondering if someone would be fine with sharing just a small example for ROSE ? Something that compiles and runs (not like exjam's titanmods) and gives a good basis to start.

Let's hope this will be at least easier to get than iROSE sources ^^'

Thanks again,

Num
 
Back
Top