Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Black Desert
You last visited: Today at 13:36

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[Free Source] BDO Market Bot/Animation Speedhack

Discussion on [Free Source] BDO Market Bot/Animation Speedhack within the Black Desert forum part of the MMORPGs category.

Reply
 
Old   #1
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
[Free Source] BDO Market Bot/Animation Speedhack

Since I got all the items I needed with this bot (about 10k meme frags, all boss gears and enough value packs) I decided to release the source.

It is a single file (exclusive MinHook dep.) and is fully internal.
I coded it mainly as a marketplace bot but also added some animation speedhack capabilities.

Code:
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <map>
#include <iostream>
#include <ctime>

#include "third_party/minhook/source/minhook.h"

#define APPLICATION_NAME									"Mark"

#define ATA_LUA_GETTOP										0x0000000141566270 // 795 0x00000001414FE620
#define ATA_REQUEST_ITEM_MARKET_SELL_INFO					0x000000014043A040 // 795 0x0000000140434640
#define ATA_GET_ITEM_MARKET_SELL_INFO_IN_CLIENT_COUNT		0x0000000140439EB0 // 795 0x00000001404344B0
#define ATA_GET_ITEM_MARKET_SELL_INFO_IN_CLIENT_BY_INDEX	0x0000000140439EE0 // 795 0x00000001404344E0
#define ATA_REQUEST_BUY_ITEM_FOR_ITEM_MARKET				0x000000014043A410 // 795 0x0000000140434A10
#define ATA_IS_BIDDING_ITEM									0x0000000140397D40 // 795 0x0000000140392420
#define ATA_IS_BIDDING_JOIN_TIME							0x0000000140397D80 // 795 0x0000000140392460
#define ATA_GET_ITEM_MARKET_NO								0x00000001401BCA10 // 795 0x00000001401BB5A0
#define ATA_IS_BIDDING_JOIN_ITEM							0x000000014043B0F0 // 795 0x00000001404356F0
#define ATA_GET_ONE_PRICE									0x00000001402CD020 // 795 0x00000001402C78E0
#define ATA_WAREHOUSE_MONEY_FROM_NPC_SHOP					0x0000000140645E40 // 795 0x000000014063F9C0

#define ADA_LOCAL_PLAYER									0x00000001421BB768 // 795 0x0000000142108158

#define EXECUTION_INTERVAL									250

#define DEFAULT_TERRITORY_KEY								1 // Heidel
#define DEFAULT_WALLET_TYPE									2 // Warehouse
#define DEFAULT_ANIMATION_SPEED_MODIFIER					0.25f

typedef uint64_t(__fastcall* ft_lua_gettop)(void* lua_state);
typedef void(__fastcall* ft_request_item_market_sell_info)(uint32_t territory_key, uint32_t item_key, bool unk_1);
typedef int32_t(__fastcall* ft_get_item_market_sell_info_in_client_count)(uint32_t territory_key, uint32_t item_key);
typedef uint64_t(__fastcall* ft_get_item_market_sell_info_in_client_by_index)(uint32_t territory_key, uint32_t item_key, uint32_t slot_index);
typedef void(__fastcall* ft_request_buy_item_for_item_market)(uint32_t wallet_type, uint32_t item_key, uint32_t slot_index, uint32_t amount, uint64_t unk_1);
typedef bool(__fastcall* ft_is_bidding_item)(uint64_t sell_info_address);
typedef bool(__fastcall* ft_is_bidding_join_time)(uint64_t sell_info_address);
typedef uint64_t(__fastcall* ft_get_item_market_no)(uint64_t sell_info_address);
typedef bool(__fastcall* ft_is_bidding_join_item)(uint64_t item_market_no);
typedef uint64_t(__fastcall* ft_get_one_price)(uint64_t sell_info_address);
typedef uint64_t(__fastcall* ft_warehouse_money_from_npc_shop)();

static ft_lua_gettop g_fp_lua_gettop = nullptr;
static ft_request_item_market_sell_info g_fp_request_item_market_sell_info = reinterpret_cast<ft_request_item_market_sell_info>(ATA_REQUEST_ITEM_MARKET_SELL_INFO);
static ft_get_item_market_sell_info_in_client_count g_fp_get_item_market_sell_info_in_client_count = reinterpret_cast<ft_get_item_market_sell_info_in_client_count>(ATA_GET_ITEM_MARKET_SELL_INFO_IN_CLIENT_COUNT);
static ft_get_item_market_sell_info_in_client_by_index g_fp_get_item_market_sell_info_in_client_by_index = reinterpret_cast<ft_get_item_market_sell_info_in_client_by_index>(ATA_GET_ITEM_MARKET_SELL_INFO_IN_CLIENT_BY_INDEX);
static ft_request_buy_item_for_item_market g_fp_request_buy_item_for_item_market = reinterpret_cast<ft_request_buy_item_for_item_market>(ATA_REQUEST_BUY_ITEM_FOR_ITEM_MARKET);
static ft_is_bidding_item g_fp_is_bidding_item = reinterpret_cast<ft_is_bidding_item>(ATA_IS_BIDDING_ITEM);
static ft_is_bidding_join_time g_fp_is_bidding_join_time = reinterpret_cast<ft_is_bidding_join_time>(ATA_IS_BIDDING_JOIN_TIME);
static ft_get_item_market_no g_fp_get_item_market_no = reinterpret_cast<ft_get_item_market_no>(ATA_GET_ITEM_MARKET_NO);
static ft_is_bidding_join_item g_fp_is_bidding_join_item = reinterpret_cast<ft_is_bidding_join_item>(ATA_IS_BIDDING_JOIN_ITEM);
static ft_get_one_price g_fp_get_one_price = reinterpret_cast<ft_get_one_price>(ATA_GET_ONE_PRICE);
static ft_warehouse_money_from_npc_shop g_fp_warehouse_money_from_npc_shop = reinterpret_cast<ft_warehouse_money_from_npc_shop>(ATA_WAREHOUSE_MONEY_FROM_NPC_SHOP);

static bool g_market_activated = false;
static bool g_hacks_activated = false;
static std::map<std::string, uint32_t> g_targets = {
	// { "Memory Fragment", 44195 },
	{ "Value Pack (30 Days)", 17354 },
	{ "Blessing of Kamasylve (15 Days)", 17081 },
	{ "Sealed Book of Combat (15 Days)", 17646 },
	{ "Equipment Tailoring Coupon", 17611 },
	{ "Young Griffon", 18429 },
	{ "Shaggy Dog", 17939 },
	{ "Calpheon Chubby Dog", 17966 },
	{ "Desert Fox", 17976 },
	{ "Red Panda", 18098 },
	{ "Snowball Rosefinch", 18426 },
	{ "Crow", 18439 },
	{ "Snowflake Reindeer Box", 290006 },
	{ "Winter Snowflake Box", 18946 },
	{ "Horse Flute Box (Permanent)", 17973 },
	{ "Trina Knight Horse Gear Set", 21012 },
	{ "Silver Embroidered Cook's Clothes +3", 50345667 },
	{ "[Musa] Western Frontiers Premium Set", 21257 },
	{ "[Musa] Palgong Premium Set", 21359 },
	{ "[Musa] Nouse's Shard Premium Set", 29147 },
	{ "[Musa] Western Frontiers Classic Set", 21256 },
	{ "Nouver Horn Bow +0", 13138 },
	{ "Kutum Horn Bow +0", 13140 },
	{ "Dandelion Crescent Blade +0", 14762 },
	{ "Griffon's Helmet +0", 11101 },
	{ "Dim Tree Spirit's Armor +0", 11017 }
};
static uint64_t g_last_execution = 0;
static float g_animation_speed = 1.0f;

std::string get_formatted_datetime()
{
	std::time_t raw_time;
	std::tm* time;
	char time_buffer[20] = { 0 };

	std::time(&raw_time);
	time = std::localtime(&raw_time);
	std::strftime(time_buffer, sizeof(time_buffer), "%d.%m.%Y %H:%M:%S", time);

	return std::string(::_strdup(time_buffer));
}

uint64_t __fastcall hf_lua_gettop(void* lua_state)
{
	if (::GetAsyncKeyState(VK_NUMPAD6) & 0x01)
	{
		g_market_activated = !g_market_activated;

		if (g_market_activated)
		{
			std::ostringstream warehouse_money_string_stream;

			warehouse_money_string_stream.imbue(std::locale("de"));
			warehouse_money_string_stream << g_fp_warehouse_money_from_npc_shop();

			std::cout << "Warehouse Money: " << warehouse_money_string_stream.str() << std::endl;
		}

		std::cout << APPLICATION_NAME " Market state is now `" << g_market_activated << "`." << std::endl;
	}

	if (::GetAsyncKeyState(VK_NUMPAD7) & 0x01)
	{
		g_animation_speed -= DEFAULT_ANIMATION_SPEED_MODIFIER;

		std::cout << "<< Animation Speed Modifier decreased to `" << g_animation_speed << "`." << std::endl;
	}

	if (::GetAsyncKeyState(VK_NUMPAD8) & 0x01)
	{
		g_animation_speed += DEFAULT_ANIMATION_SPEED_MODIFIER;

		std::cout << ">> Animation Speed Modifier increased to `" << g_animation_speed << "`." << std::endl;
	}

	if (::GetAsyncKeyState(VK_NUMPAD9) & 0x01)
	{
		g_hacks_activated = !g_hacks_activated;

		if (!g_hacks_activated)
		{
			uint64_t local_player_address = *((uint64_t*) ADA_LOCAL_PLAYER);
			uint64_t character_control_address = *((uint64_t*) (local_player_address + 0x0380));
			uint64_t character_scene_address = *((uint64_t*) (character_control_address + 0x10));

			*((float*) (character_scene_address + 0x04BC)) = 1.0f;
		}

		std::cout << APPLICATION_NAME " Hack state is now `" << g_hacks_activated << "`." << std::endl;
	}

	if (g_hacks_activated)
	{
		uint64_t local_player_address = *((uint64_t*) ADA_LOCAL_PLAYER);
		uint64_t character_control_address = *((uint64_t*) (local_player_address + 0x0380));
		uint64_t character_scene_address = *((uint64_t*) (character_control_address + 0x10));

		*((float*) (character_scene_address + 0x04BC)) = g_animation_speed;
	}

	if (g_market_activated && ((g_last_execution + EXECUTION_INTERVAL) <= ::GetTickCount64()))
	{
		g_last_execution = ::GetTickCount64();

		for (auto const& target : g_targets)
		{
			g_fp_request_item_market_sell_info(DEFAULT_TERRITORY_KEY, target.second, false);

			int32_t target_slot_count = g_fp_get_item_market_sell_info_in_client_count(DEFAULT_TERRITORY_KEY, target.second);

			if (target_slot_count == 0)
				continue;

			for (int32_t slot_index = 0; slot_index < target_slot_count; slot_index++)
			{
				uint64_t sell_info = g_fp_get_item_market_sell_info_in_client_by_index(DEFAULT_TERRITORY_KEY, target.second, slot_index);

				if (sell_info == 0x00)
					continue;

				uint64_t sell_info_count = *((uint64_t*) (sell_info + 0x18));

				if (sell_info_count > 0)
				{
					bool is_bidding_item = g_fp_is_bidding_item(sell_info);
					bool is_bidding_join_time = g_fp_is_bidding_join_time(sell_info);
					uint64_t item_market_no = g_fp_get_item_market_no(sell_info);
					bool is_bidding_join_item = g_fp_is_bidding_join_item(item_market_no);

					uint64_t one_price = g_fp_get_one_price(sell_info);
					uint64_t total_price = (one_price * sell_info_count);

					if (g_fp_warehouse_money_from_npc_shop() < total_price)
						continue;

					std::ostringstream one_price_string_stream;
					std::ostringstream total_price_string_stream;

					one_price_string_stream.imbue(std::locale("de"));
					one_price_string_stream << one_price;

					total_price_string_stream.imbue(std::locale("de"));
					total_price_string_stream << total_price;

					if (is_bidding_item)
					{
						if (is_bidding_join_time)
						{
							if (!is_bidding_join_item)
							{
								std::cout << "[" << get_formatted_datetime() << "] Bidding on " << target.first << " (" << slot_index << "." << sell_info_count << "-" <<  item_market_no << ") [T " << total_price_string_stream.str() << " | U " << one_price_string_stream.str() << "]" << std::endl;

								g_fp_request_buy_item_for_item_market(DEFAULT_WALLET_TYPE, target.second, slot_index, sell_info_count, 0);
							}
						}
						else if (is_bidding_join_item)
						{
							std::cout << "[" << get_formatted_datetime() << "] Confirming bid on " << target.first << " (" << slot_index << "." << sell_info_count << "-" << item_market_no << ") [T " << total_price_string_stream.str() << " | U " << one_price_string_stream.str() << "]" << std::endl;

							g_fp_request_buy_item_for_item_market(DEFAULT_WALLET_TYPE, target.second, slot_index, sell_info_count, 0);
						}
					}
					else
					{
						std::cout << "[" << get_formatted_datetime() << "] Buying " << target.first << " (" << slot_index << "." << sell_info_count << "-" << item_market_no << ") [T " << total_price_string_stream.str() << " | U " << one_price_string_stream.str() << "]" << std::endl;

						g_fp_request_buy_item_for_item_market(DEFAULT_WALLET_TYPE, target.second, slot_index, sell_info_count, 0);
					}
				}
			}
		}
	}

	return g_fp_lua_gettop(lua_state);
}

BOOL APIENTRY DllMain(HMODULE module, DWORD reason, void* reserved)
{
	if (reason != DLL_PROCESS_ATTACH)
		return FALSE;

	FILE* console_stream = nullptr;

	::AllocConsole();
	::SetConsoleTitle(APPLICATION_NAME);
	::freopen_s(&console_stream, "conout$", "w", stdout);

	std::cout << "Hello, world!" << std::endl;

	if (::MH_Initialize() != MH_OK)
	{
		std::cout << "Failed to initialize hook library." << std::endl;

		return 0;
	}

	if (::MH_CreateHook(((void*) ATA_LUA_GETTOP), &hf_lua_gettop, reinterpret_cast<void**>(&g_fp_lua_gettop)) != MH_OK)
	{
		std::cout << "Failed to create `lua_gettop` hook." << std::endl;

		return 0;
	}

	if (::MH_EnableHook(MH_ALL_HOOKS) != MH_OK)
	{
		std::cout << "Failed to enable hooks." << std::endl;

		return 0;
	}

	return TRUE;
}
Small Usage Guide

Modify the g_targets variable and add the items you want to be purchased. Go to the Heidel (important, I've hardcoded the territory key cuz lazy) Marketplace and press NUMPAD 6. You should see "Mark Market state is now `1`." in the console. It will now buy all the items possible (uses the warehouse money, also hardcoded). Take care, don't let it buy meme frags overnight as you will go bankrupt (I got about 1k meme frags per hour).

The only big thing that is not implemented is a way to check if a purchase was successful or not. I didn't want to bother with the shitty lua stuff so I decided to leave it out.

The speedhack is pretty simple, use NUMPAD 7 and NUMPAD8 to de/increase your animation speed in 0.25-steps and NUMPAD 9 to toggle the hack.

Don't forget to disable the hack (NUMPAD 9) before switching channels/characters/joining RBF or the client will crash.

I've also attached a binary version, if you don't want to compile it yourself.
Inject it with your favourite DLL injector during the Xigncode Splash.
(Or use Xenos with 750 ms delay to automatically do it for you).

Have fun.

Edit: I've also attached the whole source folder (Mark-Source.rar).
Should have all dependencies included. Open Solution with Visual Studio 2017 and hit compile.

Edit 2: Cause I was asked in Discord: Yes, you can do other stuff on your computer while using the bot. And you shouldn't hit NUMPAD 6 during that time as this will toggle the market bot even when the game is not focused (again, I'm lazy).
Attached Files
File Type: rar Mark.rar (41.7 KB, 943 views)
File Type: rar Mark-Source.rar (19.0 KB, 722 views)
Ustonovic is offline  
Thanks
17 Users
Old 06/28/2018, 14:23   #2

 
R3p's Avatar
 
elite*gold: 1988
The Black Market: 325/15/3
Join Date: Apr 2010
Posts: 532
Received Thanks: 962
Interesting attempt. Calling the functions which are bound to their Lua. But why not just let them load a Lua code chunk which does the same job?
R3p is offline  
Thanks
1 User
Old 06/28/2018, 14:30   #3
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
Quote:
Originally Posted by R3p View Post
Interesting attempt. Calling the functions which are bound to their Lua. But why not just let them load a Lua code chunk which does the same job?
Actually I had a project before, which did exactly that.
But when I added more than 2 items to the target array the code was somehow not able to bid on every sell_info there is and felt like it was "lagging behind" the real data. Hard to explain.
I decided to ditch lua (also I'm not good in lua) and used the bindings directly.
Ustonovic is offline  
Thanks
1 User
Old 06/28/2018, 15:20   #4
 
elite*gold: 0
Join Date: May 2013
Posts: 339
Received Thanks: 160
Quote:
Originally Posted by Ustonovic View Post
Don't forget to disable the hack (NUMPAD 9) before switching channels/characters/joining RBF or the client will crash.
This is easy to fix..

Code:
#define ADA_LOCAL_PLAYER 0x1421BB768

DWORD *ingame = (DWORD*)0x1421BB768;

if (g_hacks_activated)
{
	if (*ingame) //check if null or not.. prevent crashes
	{
		uint64_t local_player_address = *((uint64_t*) ADA_LOCAL_PLAYER);
		uint64_t character_control_address = *((uint64_t*) (local_player_address + 0x0380));
		uint64_t character_scene_address = *((uint64_t*) (character_control_address + 0x10));

		*((float*) (character_scene_address + 0x04BC)) = g_animation_speed;
	}
}
meymeygila is offline  
Old 06/28/2018, 16:43   #5
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
Quote:
Originally Posted by meymeygila View Post
This is easy to fix..

Code:
#define ADA_LOCAL_PLAYER 0x1421BB768

DWORD *ingame = (DWORD*)0x1421BB768;

if (g_hacks_activated)
{
	if (*ingame) //check if null or not.. prevent crashes
	{
		uint64_t local_player_address = *((uint64_t*) ADA_LOCAL_PLAYER);
		uint64_t character_control_address = *((uint64_t*) (local_player_address + 0x0380));
		uint64_t character_scene_address = *((uint64_t*) (character_control_address + 0x10));

		*((float*) (character_scene_address + 0x04BC)) = g_animation_speed;
	}
}
yeah ik, but you should use DWORD64/uint64_t ^^
Ustonovic is offline  
Old 06/28/2018, 17:10   #6
 
elite*gold: 0
Join Date: May 2013
Posts: 339
Received Thanks: 160
Quote:
Originally Posted by Ustonovic View Post
yeah ik, but you should use DWORD64/uint64_t ^^
It doesnt matter. I rather use DWORD and compile it in x64 and still working just fine in 64bit BDO, don't forget some people are still playing BDO in 32bit.
meymeygila is offline  
Old 06/28/2018, 17:16   #7
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
Quote:
Originally Posted by meymeygila View Post
It doesnt matter. I rather use DWORD and compile it in x64 and still working just fine in 64bit BDO, don't forget some people are still playing BDO in 32bit.
Yeah true, some are.
But in x64 you def. need to use a 8 byte type, DWORD will only work when the address is 32 bits or fewer.
Ustonovic is offline  
Old 06/28/2018, 17:48   #8
 
elite*gold: 0
Join Date: Aug 2008
Posts: 8
Received Thanks: 0
Quote:
Originally Posted by Ustonovic View Post
Yeah true, some are.
But in x64 you def. need to use a 8 byte type, DWORD will only work when the address is 32 bits or fewer.
Some stupid question, will we need new offset as for SEA server. Just wondering. Thank you in advance
141193 is offline  
Old 06/28/2018, 18:10   #9
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
Quote:
Originally Posted by 141193 View Post
Some stupid question, will we need new offset as for SEA server. Just wondering. Thank you in advance
yup, this is for EU/NA 802.
Ustonovic is offline  
Old 06/29/2018, 15:37   #10
 
elite*gold: 0
Join Date: Sep 2012
Posts: 115
Received Thanks: 69
Quote:
Originally Posted by Ustonovic View Post
yeah ik, but you should use DWORD64/uint64_t ^^
In that case it's a DWORD* so it's fine as it's not actually a DWORD holding the pointer.
Also stop using DWORD64/uint64_t for storing pointer, uintptr_t is here for a reason
JuJuBoSc1 is offline  
Old 06/29/2018, 16:23   #11
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
Quote:
Originally Posted by JuJuBoSc1 View Post
In that case it's a DWORD* so it's fine as it's not actually a DWORD holding the pointer.
Also stop using DWORD64/uint64_t for storing pointer, uintptr_t is here for a reason
My bad, you are right.
Ustonovic is offline  
Old 06/29/2018, 16:29   #12

 
Trixie Mattel's Avatar
 
elite*gold: 941
Join Date: Nov 2012
Posts: 216
Received Thanks: 54
Quote:
Originally Posted by JuJuBoSc1 View Post
In that case it's a DWORD* so it's fine as it's not actually a DWORD holding the pointer.
Also stop using DWORD64/uint64_t for storing pointer, uintptr_t is here for a reason
@ , on the side note, what's the remaining balance you still need to pay DAUM ?
Trixie Mattel is offline  
Old 06/29/2018, 16:52   #13
 
elite*gold: 0
Join Date: Sep 2012
Posts: 115
Received Thanks: 69
Quote:
Originally Posted by Lady Integra View Post
@ , on the side note, what's the remaining balance you still need to pay DAUM ?
We had an agreement, not sure what can / cannot be made to public to be honest, but I legally can't work on BDO now .

Even tho I have almost not played the game since the last 2 years, I still like to come here and see what others people are working on.
JuJuBoSc1 is offline  
Thanks
4 Users
Old 06/29/2018, 21:14   #14
 
elite*gold: 0
Join Date: Jan 2016
Posts: 290
Received Thanks: 33
disclaimer: Im still learning

how do you find the addresses? like, how do you know which address is correspond to which function? do you have an sdk dump?

I can find the addresses im looking for with IDA, like I know what im looking for but I dont know how they correspond to the addresses if you can pm me your discord to help me that would be great.

just to prove that I know how to find the addresses,
addresses for 805 are
localplayer: 1421BA7C8
vehicle: 142BE5880
gettop: 141564F60

I know some addresses are super obvious like the dobuffer which is just getting the function address of aLua_tinkerDobu but for other addresses like guildquest (which is 14219E168 for 805) I dont know how to find that without checking the sig
ruikangzhu1990 is offline  
Old 06/29/2018, 21:17   #15
 
Ustonovic's Avatar
 
elite*gold: 0
Join Date: Mar 2008
Posts: 89
Received Thanks: 48
Quote:
Originally Posted by ruikangzhu1990 View Post
how do you find the addresses? like, how do you know which address is correspond to which function? do you have an sdk dump?

I can find the addresses im looking for with IDA, like I know what im looking for but I dont know how they correspond to the addresses if you can pm me your discord to help me that would be great.

just to prove that I know how to find the addresses,
addresses for 805 are
localplayer: 1421BA7C8
vehicle: 142BE5880
gettop: 141564F60

I know some addresses are super obvious like the dobuffer which is just getting the function address of aLua_tinkerDobu but for other addresses like guildquest (which is 14219E168 for 805) I dont know how to find that without checking the sig
There are many ways to get the address of functions. Personally I just unpacked the content of the game (the PAZ files) and looked through the lua files how the scripts interact with the native code.
There are some lua functions exported by the game like "requestBuyItemForItemMarket" which you can easily find in IDA using the string section (Shift + F12, Ctrl + F to search for a string).

Looks like this:
Ustonovic is offline  
Thanks
1 User
Reply


Similar Threads Similar Threads
BDO-PSERVER incls. Ninja/Kuno OgreFest BDO
07/16/2016 - Black Desert - 5 Replies
BDO Pserver Stats idk? exp is pretty damn High... Starter pack incl. etc ? im not the owner just found it and wanted to share by the way post if the server works for u :) if not i may help yah :)



All times are GMT +1. The time now is 13:36.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.