[Source] Fix the old exp bar - by writing code!

03/12/2017 18:09 florian0#1
Hello beloved, dead community,

its time for another release. Its more of a proof of concept and I hope it might inspire people to continue working on it. You don't need the source to accomplish cool things. Just write your own source.

[Only registered and activated users can see links. Click Here To Register...]

Ye, its super ugly looking. I choose to be a coder, not a designer. I'd be happy, if someone supplies me a proper version of the 2dt and ddj files so I can update this embarrassing screenshot.

Anyway. It allows you to write code and access GUI-Elements of SRO like you got the original source. It results in an injectable Dll.
This allows you to change the weird scaling of the new Expbar:

Code:
#include "CNIFUnderMenuBar.h"

#include "CICPlayer.h"

#include <stdio.h>
#include "CGlobalDataManager.h"

#include <cmath>

void CNIFUnderMenuBar::Update() {
	// Skip, if player object is not loaded yet (KEEP!)
	if (!g_CICPlayer) {
		return;
	}

	// Some other call that is important (KEEP!)
	((void (__thiscall * )(CNIFUnderMenuBar*))0x46CD80)(this);

	// Retrieve LevelData for current Level
	// (this is one line of Media\server_dep\silkroad\textdata\leveldata.txt)
	CLevelData* data = g_CGlobalDataManager->GetLevelData(g_CICPlayer->level);

	// Calculate EXP as percentage value
	double exp_percentage = g_CICPlayer->exp_current * 100.0 / data->Exp_C;

	// Limit maximum percentage to 99.99%
	if (exp_percentage > 99.99)
		exp_percentage = 99.99;

	// Calculate the number of bars that are full
	int barnum = floor(exp_percentage / 10.0);

	for (int i = 0; i < 10; i++) {

		// Fill or empty bars
		if (barnum <= i) {
			gauges[i]->background_value = 0.0;
			gauges[i]->foreground_value = 0.0;
		} else {
			gauges[i]->background_value = 1.0;
			gauges[i]->foreground_value = 1.0;
		}
	}

	// Fill the bar that is neither full or empty with the remaining percentage
	double exp_remain = (exp_percentage - (barnum * 10.0)) / 10.0;

	gauges[barnum]->background_value = exp_remain;
	gauges[barnum]->foreground_value = exp_remain;


	// Assign more texts
	this->lbl_level->SetText(L"Level: %d", g_CICPlayer->level);
	this->lbl_percentage->SetText(L"%.2lf %%", exp_percentage);

	// Skillpoints
	this->lbl_spcount->SetText(L"%d", g_CICPlayer->skillpoints);
	this->gauge_skillexp->background_value = g_CICPlayer->skill_exp / 400.0;
	this->gauge_skillexp->foreground_value = g_CICPlayer->skill_exp / 400.0;

	// You can also draw text directly at the gauge. It will be centered automatically
	// this->gauge_skillexp->SetText(L"%d", g_CICPlayer->skill_exp);
	

	this->lbl_exp_bar_scaler->SetText(L""); // Prescaler is disabled
	
	// This label is right in the middle of the EXP-Bar
	//this->lbl_360->SetText(L"lbl_360");
};
Important checklist:
  1. Compile using Visual Studio 2005
  2. Compile on RELEASE
  3. Never compile on DEBUG
  4. IF and only IF you know how to make the 2005 compiler work in other VS versions, dare to use other VS versions. If not, simply don't even think about it. I have supplied my v2010 project-file :).
  5. Wanna try newer compilers? Go for it! But don't cry <3

Have fun :)
03/12/2017 18:23 XxGhostSpiriTxX#2
thanks
03/12/2017 18:48 KingDollar#3
That's what you can do when you got sro srcs xD
kk nice keep it up :"D
03/12/2017 18:55 Devsome#4
Quote:
Originally Posted by Alexiuns* View Post
That's what you can do when you got sro srcs xD
kk nice keep it up :"D
he does not have the source, but okay.
@florian0 nice release :+1:
03/12/2017 18:57 KingDollar#5
Quote:
Originally Posted by Devsome View Post
he does not have the source, but okay.
@florian0 nice release :+1:
no he has
03/12/2017 19:08 florian0#6
Sadly no, I don't. I've never seen a single line of the source. And, TBH, that would be pretty boring xD.

All that stuff is guessed from runtime type info, error messages and a good portion of luck.
03/12/2017 19:12 KingDollar#7
Quote:
Originally Posted by florian0 View Post
Sadly no, I don't. I've never seen a single line of the source. And, TBH, that would be pretty boring xD.

All that stuff is guessed from runtime type info, error messages and a good portion of luck.
i thought that you are painkiller because of your github account description and as fair as i know painkiller has sro src he has showed me them before
03/12/2017 19:33 devtekve#8
Quote:
Originally Posted by Alexiuns* View Post
i thought that you are painkiller because of your github account description and as fair as i know painkiller has sro src he has showed me them before
You would think that Florian0 has the source, but indeed what he has is a big brain:
[Only registered and activated users can see links. Click Here To Register...]
03/12/2017 19:41 florian0#9
Nah, i'm not pain. I got in touch with him last year. This is where this text on my github originates. It's just a random chat-quote of pain and qqdev describing my social-life precisely xD.
03/12/2017 19:45 KingDollar#10
Quote:
Originally Posted by florian0 View Post
Nah, i'm not pain. I got in touch with him last year. This is where this text on my github originates. It's just a random chat-quote of pain and qqdev describing my social-life precisely xD.
aha i got it! xD sorry for understood wrong
03/12/2017 20:11 ZeonNETWORK#11
not bad, unfortunately don't have vs2005 at the moment to try messing with it
OFF Topic: i saw your wordpress you've shared a lot of good documentations
have you investigated about the max slots that item mall (client side) can handle?
i figured out that client completely crashes after slot No.381 and between 371~381 random crashes
like Megamax said to me it's a freaking bug in the GUI itself
but there must be a work around to expand it like in Metin2 src
03/13/2017 00:00 florian0#12
Quote:
Originally Posted by ZeonNETWORK View Post
not bad, unfortunately don't have vs2005 at the moment to try messing with it
Yeah. I had a little trouble finding it.

Quote:
Originally Posted by ZeonNETWORK View Post
OFF Topic: i saw your wordpress you've shared a lot of good documentations
have you investigated about the max slots that item mall (client side) can handle?
Never dealt with it. Sounds interesting. I will stumble upon this sooner or later on my way through the interface ...
03/13/2017 22:20 VEssence#13
Nicely done. Thank you for your time and effort, nice reverse engineering skills btw. :)
03/14/2017 08:30 Gooby.#14
Quote:
Originally Posted by Alexiuns* View Post
aha i got it! xD sorry for understood wrong
Jumping to conclusions are never good.
04/23/2017 20:49 florian0#15
Ace notified me of a weird, random crash in my implementation.

It took me some time, but I found two bugs:

1. When the current exp gets close to the max exp, the percentage will round to 100%
I guessed this would only have visual effects, but i was taught other xD.

Having a percentage of 100 will cause this line
Code:
	int barnum = floor(exp_percentage / 10.0);
to return 10 as the highest bar-index to be filled, but there are only 0-9 bars available causing this line:
Code:
	gauges[barnum]->background_value = exp_remain;
	gauges[barnum]->foreground_value = exp_remain;
to crash the application.

Luckily, there is a simple fix for this:

Code:
	// Calculate EXP as percentage value
	double exp_percentage = g_CICPlayer->exp_current * 100.0 / data->Exp_C;

	if (exp_percentage > 99.99)
		exp_percentage = 99.99;
2. GetLevelData sometimes returns nullptr
I actually noticed that during testing, but considered it being a bug of my own. When i fixed several offset-issues regarding g_CICPlayer->level, it did not occur again so i considered it fixed.

It still seems to appear, so ... wtf?

Definitely needs more research, but there is a quick fix that will solve it for now.
Code:
	// Retrieve LevelData for current Level
	// (this is one line of Media\server_dep\silkroad\textdata\leveldata.txt)
	CLevelData* data = g_CGlobalDataManager->GetLevelData(g_CICPlayer->level);

	if (data == 0)
		return;
Edit: Many months later, I seem to have finally figured out whats wrong. The level of the player is stored as a byte, while I am interpreting it as an int (4 byte). While the other 3 bytes are null, there is no problem. If the other bytes are not null, they are interpreted as the level, too, resulting in levels greater than 1000 or even a couple of million. As a result, GetLevelData(1 Million) will return crap, causing my code to do crap and eventually crash.

Long story short: Make level a char instead of int. Problem solved

Thanks to $Wegs for debugging this out with me and supplying helpful crashdumps.