Premium masodikbela 1359 Posted July 14, 2015 Premium Share Posted July 14, 2015 M2 Download Center This is the hidden content, please Sign In or Sign Up ( Internal ) Hi there Devs, I have published a tutorial yesterday on a Hungarian forum, and I decided to share it here, too. So... I chose int type for the level variables (originally its unsigned char) because: its more than enough maximum level 2147483647 the damage done by the characters (and much more thing) is calculated via they levels, and the type of this variables is int This is why I recommend to use int type game/src char.cpp Search this: void CHARACTER::SetLevel(BYTE level) Then replace to this: void CHARACTER::SetLevel(int level) char.h Search this: void SetLevel(BYTE level); Then replace to this: void SetLevel(int level); Then search: BYTE level; (its under this: typedef struct character_point) And replace to this: int level; party.cpp Search this one: void CParty::P2PSetMemberLevel(DWORD pid, BYTE level) Then replace to this: void CParty::P2PSetMemberLevel(DWORD pid, int level) Then replace this: BYTE CParty::GetMemberMaxLevel() { BYTE bMax = 0; To this: int CParty::GetMemberMaxLevel() { int bMax = 0; Find this one: BYTE CParty::GetMemberMinLevel() { BYTE bMin = PLAYER_MAX_LEVEL_CONST; And replace to this: int CParty::GetMemberMinLevel() { int bMin = PLAYER_MAX_LEVEL_CONST; And then this: void CParty::RequestSetMemberLevel(DWORD pid, BYTE level) To this: void CParty::RequestSetMemberLevel(DWORD pid, int level) party.h Search this: BYTE bLevel; (its under typedef struct SMember) And replace to this: int bLevel; Then this ones: BYTE GetMemberMaxLevel(); BYTE GetMemberMinLevel(); To this: int GetMemberMaxLevel(); int GetMemberMinLevel(); And these: void RequestSetMemberLevel(DWORD pid, BYTE level); void P2PSetMemberLevel(DWORD pid, BYTE level); To: void RequestSetMemberLevel(DWORD pid, int level); void P2PSetMemberLevel(DWORD pid, int level); char_battle.cpp Find: struct FPartyTotaler { int total; And replace to: struct FPartyTotaler { long total; And this: struct FPartyDistributor { int total; LPCHARACTER c; int x, y; DWORD _iExp; int m_iMode; int m_iMemberCount; FPartyDistributor(LPCHARACTER center, int member_count, int total, DWORD iExp, int iMode) To this: struct FPartyDistributor { long total; LPCHARACTER c; int x, y; DWORD _iExp; int m_iMode; int m_iMemberCount; FPartyDistributor(LPCHARACTER center, int member_count, long total, DWORD iExp, int iMode) config.h Find this: extern BYTE PK_PROTECT_LEVEL; And replace to this: extern int PK_PROTECT_LEVEL; locale_service.cpp Change: BYTE PK_PROTECT_LEVEL To this: int PK_PROTECT_LEVEL constants.cpp Well, here you should decide how much is the maximum level you want. You should fill these tables with as much records, as the maximum level. (e.g if you want to have maximum level 300, you need to put 300 records to these tables) const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] const DWORD party_exp_distribute_table[PLAYER_MAX_LEVEL_CONST + 1] const int aiExpLossPercents[PLAYER_EXP_TABLE_MAX + 1] log.h Edit this: void LoginLog(bool isLogin, DWORD dwAccountID, DWORD dwPID, BYTE bLevel, BYTE bJob, DWORD dwPlayTime); To this: void LoginLog(bool isLogin, DWORD dwAccountID, DWORD dwPID, int bLevel, BYTE bJob, DWORD dwPlayTime); log.cpp Replace this: void LogManager::LoginLog(bool isLogin, DWORD dwAccountID, DWORD dwPID, BYTE bLevel, BYTE bJob, DWORD dwPlayTime) To this: void LogManager::LoginLog(bool isLogin, DWORD dwAccountID, DWORD dwPID, int bLevel, BYTE bJob, DWORD dwPlayTime) guild.h Replace this: typedef struct SGuildMemberPacketData { DWORD pid; BYTE grade; BYTE is_general; BYTE job; BYTE level; DWORD offer; BYTE name_flag; char name[CHARACTER_NAME_MAX_LEN+1]; } TGuildMemberPacketData; To this: typedef struct SGuildMemberPacketData { DWORD pid; BYTE byGrade; BYTE byIsGeneral; BYTE byJob; int byLevel; DWORD dwOffer; BYTE byNameFlag; } TGuildMemberPacketData; Then this: void ChangeMemberData(DWORD pid, DWORD offer, BYTE level, BYTE grade); To this: void ChangeMemberData(DWORD pid, DWORD offer, int level, BYTE grade); Then SGuildMember(DWORD pid, BYTE grade, BYTE is_general, BYTE job, BYTE level, DWORD offer_exp, char* name); To this: SGuildMember(DWORD pid, BYTE grade, BYTE is_general, BYTE job, int level, DWORD offer_exp, char* name); And this: DWORD pid; // player Ĺ×ŔĚşíŔÇ id; primary key BYTE grade; // ±ćµĺ»óŔÇ ÇĂ·ąŔĚľîŔÇ °č±Ţ 1 to 15 (1ŔĚ ÂŻ) BYTE is_general; BYTE job; BYTE level; DWORD offer_exp; // °řÇĺÇŃ °ćÇčġ BYTE _dummy; To this: DWORD pid; // player Ĺ×ŔĚşíŔÇ id; primary key BYTE grade; // ±ćµĺ»óŔÇ ÇĂ·ąŔĚľîŔÇ °č±Ţ 1 to 15 (1ŔĚ ÂŻ) BYTE is_general; BYTE job; int level; DWORD offer_exp; // °řÇĺÇŃ °ćÇčġ BYTE _dummy; And then this: void LevelChange(DWORD pid, BYTE level); To this: void LevelChange(DWORD pid, int level); guild.cpp Find this: BYTE level = (BYTE)strtoul(row[4], (char**) NULL, 10); Replace to this: int level = (int)strtoul(row[4], (char**) NULL, 10); Then this: sys_log(0, "GUILD: AddMember PID %u, grade %u, job %u, level %u, offer %u, name %s ptr %p", To this: sys_log(0, "GUILD: AddMember PID %u, grade %u, job %u, level %d, offer %u, name %s ptr %p", Then replace the whole function: void CGuild::ChangeMemberData(DWORD pid, DWORD offer, BYTE level, BYTE grade) To this: void CGuild::ChangeMemberData(DWORD pid, DWORD offer, int level, BYTE grade) { TGuildMemberContainer::iterator cit = m_member.find(pid); if (cit == m_member.end()) return; cit->second.offer_exp = offer; cit->second.level = level; cit->second.grade = grade; cit->second._dummy = 0; TPacketGCGuild pack; TGuildMemberPacketData mbData; pack.header = HEADER_GC_GUILD; pack.subheader = GUILD_SUBHEADER_GC_LIST; pack.size = sizeof(TPacketGCGuild); pack.size += sizeof(TGuildMemberPacketData); for (TGuildMemberOnlineContainer::iterator it = m_memberOnline.begin(); it != m_memberOnline.end(); ++it) { LPDESC d = (*it)->GetDesc(); if (d) { TEMP_BUFFER buf; buf.write(&pack, sizeof(pack)); mbData.byNameFlag = 0; mbData.byGrade = cit->second.grade; mbData.byIsGeneral = cit->second.is_general; mbData.byJob = cit->second.job; mbData.byLevel = cit->second.level; mbData.dwOffer = cit->second.offer_exp; mbData.pid = cit->second.pid; buf.write(&mbData, sizeof(TGuildMemberPacketData)); d->Packet(buf.read_peek(), buf.size()); } } } And replace this function too: void CGuild::LevelChange(DWORD pid, BYTE level) To this: void CGuild::LevelChange(DWORD pid, int level) { TGuildMemberContainer::iterator cit = m_member.find(pid); if (cit == m_member.end()) return; cit->second.level = level; TPacketGuildChangeMemberData gd_guild; gd_guild.guild_id = GetID(); gd_guild.pid = pid; gd_guild.offer = cit->second.offer_exp; gd_guild.grade = cit->second.grade; gd_guild.level = level; db_clientdesc->DBPacket(HEADER_GD_GUILD_CHANGE_MEMBER_DATA, 0, &gd_guild, sizeof(gd_guild)); TPacketGCGuild pack; TGuildMemberPacketData mbData; pack.header = HEADER_GC_GUILD; pack.subheader = GUILD_SUBHEADER_GC_LIST; pack.size = sizeof(TPacketGCGuild); pack.size += sizeof(TGuildMemberPacketData); cit->second._dummy = 0; for (TGuildMemberOnlineContainer::iterator it = m_memberOnline.begin(); it != m_memberOnline.end(); ++it) { LPDESC d = (*it)->GetDesc(); if (d) { TEMP_BUFFER buf; buf.write(&pack, sizeof(pack)); mbData.byNameFlag = 0; mbData.byGrade = cit->second.grade; mbData.byIsGeneral = cit->second.is_general; mbData.byJob = cit->second.job; mbData.byLevel = cit->second.level; mbData.dwOffer = cit->second.offer_exp; mbData.pid = cit->second.pid; buf.write(&mbData, sizeof(TGuildMemberPacketData)); d->Packet(buf.read_peek(), buf.size()); } } } Then this function: bool CGuild::OfferExp(LPCHARACTER ch, int amount) To this: bool CGuild::OfferExp(LPCHARACTER ch, int amount) { TGuildMemberContainer::iterator cit = m_member.find(ch->GetPlayerID()); if (cit == m_member.end()) return false; if (m_data.exp+amount < m_data.exp) return false; if (amount < 0) return false; if (ch->GetExp() < (DWORD) amount) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±ćµĺ> Á¦°řÇĎ°íŔÚ ÇĎ´Â °ćÇčġ°ˇ ł˛Ŕş °ćÇčġş¸´Ů ¸ą˝Ŕ´Ď´Ů.")); return false; } if (ch->GetExp() - (DWORD) amount > ch->GetExp()) { sys_err("Wrong guild offer amount %d by %s[%u]", amount, ch->GetName(), ch->GetPlayerID()); return false; } ch->PointChange(POINT_EXP, -amount); TPacketGuildExpUpdate guild_exp; guild_exp.guild_id = GetID(); guild_exp.amount = amount / 100; db_clientdesc->DBPacket(HEADER_GD_GUILD_EXP_UPDATE, 0, &guild_exp, sizeof(guild_exp)); GuildPointChange(POINT_EXP, amount / 100, true); cit->second.offer_exp += amount / 100; cit->second._dummy = 0; TPacketGCGuild pack; TGuildMemberPacketData mbData; pack.header = HEADER_GC_GUILD; pack.subheader = GUILD_SUBHEADER_GC_LIST; pack.size = sizeof(TPacketGCGuild); pack.size += sizeof(TGuildMemberPacketData); for (TGuildMemberOnlineContainer::iterator it = m_memberOnline.begin(); it != m_memberOnline.end(); ++it) { LPDESC d = (*it)->GetDesc(); if (d) { TEMP_BUFFER buf; buf.write(&pack, sizeof(pack)); mbData.byNameFlag = 0; mbData.byGrade = cit->second.grade; mbData.byIsGeneral = cit->second.is_general; mbData.byJob = cit->second.job; mbData.byLevel = cit->second.level; mbData.dwOffer = cit->second.offer_exp; mbData.pid = cit->second.pid; buf.write(&mbData, sizeof(TGuildMemberPacketData)); d->Packet(buf.read_peek(), buf.size()); } } SaveMember(ch->GetPlayerID()); TPacketGuildChangeMemberData gd_guild; gd_guild.guild_id = GetID(); gd_guild.pid = ch->GetPlayerID(); gd_guild.offer = cit->second.offer_exp; gd_guild.level = ch->GetLevel(); gd_guild.grade = cit->second.grade; db_clientdesc->DBPacket(HEADER_GD_GUILD_CHANGE_MEMBER_DATA, 0, &gd_guild, sizeof(gd_guild)); return true; } And this function: void CGuild::SendListPacket(LPCHARACTER ch) To this: void CGuild::SendListPacket(LPCHARACTER ch) { /* List Packet Header Count (byte) [ ... name_flag 1 - Ŕ̸§Ŕ» ş¸ł»´ŔłÄ ľČş¸ł»´ŔłÄ name CHARACTER_NAME_MAX_LEN+1 ] * Count */ LPDESC d; if (!(d=ch->GetDesc())) return; TPacketGCGuild pack; pack.header = HEADER_GC_GUILD; pack.size = sizeof(TPacketGCGuild); pack.subheader = GUILD_SUBHEADER_GC_LIST; pack.size += sizeof(TGuildMemberPacketData) * m_member.size(); pack.size += (CHARACTER_NAME_MAX_LEN + 1) * m_member.size(); TEMP_BUFFER buf; TGuildMemberPacketData mbData; buf.write(&pack,sizeof(pack)); char c[CHARACTER_NAME_MAX_LEN+1]; for (TGuildMemberContainer::iterator it = m_member.begin(); it != m_member.end(); ++it) { it->second._dummy = 1; mbData.byNameFlag = 1; mbData.byGrade = it->second.grade; mbData.byIsGeneral = it->second.is_general; mbData.byJob = it->second.job; mbData.byLevel = it->second.level; mbData.dwOffer = it->second.offer_exp; mbData.pid = it->second.pid; buf.write(&mbData, sizeof(TGuildMemberPacketData)); strlcpy(c, it->second.name.c_str(), MIN(sizeof(c), it->second.name.length() + 1)); buf.write(c, CHARACTER_NAME_MAX_LEN+1 ); if ( test_server ) sys_log(0 ,"name %s job %d ", it->second.name.c_str(), it->second.job ); } d->Packet(buf.read_peek(), buf.size()); for (TGuildMemberOnlineContainer::iterator it = m_memberOnline.begin(); it != m_memberOnline.end(); ++it) { SendLoginPacket(ch, *it); } for (TGuildMemberP2POnlineContainer::iterator it = m_memberP2POnline.begin(); it != m_memberP2POnline.end(); ++it) { SendLoginPacket(ch, *it); } } Then this function: void CGuild::SendListOneToAll(DWORD pid) To this: void CGuild::SendListOneToAll(DWORD pid) { TPacketGCGuild pack; pack.header = HEADER_GC_GUILD; pack.size = sizeof(TPacketGCGuild); pack.subheader = GUILD_SUBHEADER_GC_LIST; pack.size += sizeof(TGuildMemberPacketData); TGuildMemberPacketData mbData; char c[CHARACTER_NAME_MAX_LEN+1]; memset(c, 0, sizeof(c)); TGuildMemberContainer::iterator cit = m_member.find(pid); if (cit == m_member.end()) return; for (TGuildMemberOnlineContainer::iterator it = m_memberOnline.begin(); it!= m_memberOnline.end(); ++it) { LPDESC d = (*it)->GetDesc(); if (!d) continue; TEMP_BUFFER buf; buf.write(&pack, sizeof(pack)); cit->second._dummy = 1; mbData.byNameFlag = 1; mbData.byGrade = cit->second.grade; mbData.byIsGeneral = cit->second.is_general; mbData.byJob = cit->second.job; mbData.byLevel = cit->second.level; mbData.dwOffer = cit->second.offer_exp; mbData.pid = cit->second.pid; //buf.write(&(cit->second), sizeof(DWORD) * 3 +1); buf.write(&mbData, sizeof(TGuildMemberPacketData)); buf.write(cit->second.name.c_str(), cit->second.name.length()); buf.write(c, CHARACTER_NAME_MAX_LEN + 1 - cit->second.name.length()); d->Packet(buf.read_peek(), buf.size()); } } Then find this: SGuildMember::SGuildMember(DWORD pid, BYTE grade, BYTE is_general, BYTE job, BYTE level, DWORD offer_exp, char* name) And replace to this: SGuildMember::SGuildMember(DWORD pid, BYTE grade, BYTE is_general, BYTE job, int level, DWORD offer_exp, char* name) common tables.h Find this: BYTE byLevel; Replace to this: int byLevel; Then this: BYTE level; To this: int level; And this: BYTE level; To this: int level; Then this: BYTE bLevel; (under typedef struct SPacketPartySetMemberLevel) To this: int bLevel; And then this: BYTE bLevel; (under typedef struct SPacketDGGuildMember) To this: int bLevel; lenght.h Then here set the maximum level: PLAYER_EXP_TABLE_MAX = 120, PLAYER_MAX_LEVEL_CONST = 120, db/src ClientManager.h Find this: struct TPartyInfo { BYTE bRole; BYTE bLevel; Replace to this: struct TPartyInfo { BYTE bRole; int bLevel; ClientManager.cpp Search this: pkPeer->Encode(&it_member->second.bLevel, sizeof(BYTE)); (its in the void CClientManager::SendPartyOnSetup(CPeer* pkPeer) function) and replace with this: pkPeer->Encode(&it_member->second.bLevel, sizeof(int)); ClientManagerPlayer.cpp Find this: "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d" Then replace to this: "PLAYER_DELETE FAILED LEVEL %d >= DELETE LIMIT %d" And find this: "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d" You will find it 2 times, replace both to this: "PLAYER_DELETE FAILED LEVEL %d >= DELETE LIMIT %d" client packet.h Find this: BYTE byLevel; Then replace to this: int byLevel; And this: BYTE byLevel; To this: int byLevel; PythonGuild.h Find this: BYTE byLevel; And replace to this: int byLevel; And finally, edit the level colum in the player table in the player database. Set its type from tinyint to smallint (or int, it depends how high is the maximum level) and expand its size to 3 (or higher). And then, here you are I also made a video while I made this, if you have free 42 minute, maybe worth to watch it (if you do, you are my guest for a beer (or something liquid :D)) https://www.youtube.com/embed/NTN5mwEeEv8 If you have question(s)/problem(s)/remark(s), feel free to post it here, or send me a PM. Have a nice day, ~masodikbela 54 2 2 1 20 78 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
TheMt2 11 Posted July 14, 2015 Share Posted July 14, 2015 Good, thx. Link to comment Share on other sites More sharing options...
Premium Galet 510 Posted July 14, 2015 Premium Share Posted July 14, 2015 Thanks Link to comment Share on other sites More sharing options...
Premium V0iĐ 114 Posted July 14, 2015 Premium Share Posted July 14, 2015 Thank you dude! Link to comment Share on other sites More sharing options...
ScreamMyName 100 Posted July 14, 2015 Share Posted July 14, 2015 It looks like everything is here. I already had it done but good job. Link to comment Share on other sites More sharing options...
TheMt2 11 Posted July 14, 2015 Share Posted July 14, 2015 (edited) 1 problem of compilation. https://metin2.download/picture/RilQLpShBg5L68nSUk1yt91SG2PnmCJB/.png Edited August 30, 2022 by Metin2 Dev Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
Premium masodikbela 1359 Posted July 14, 2015 Author Premium Share Posted July 14, 2015 I think you forgot to do this: guild.hReplace this: typedef struct SGuildMemberPacketData { DWORD pid; BYTE grade; BYTE is_general; BYTE job; BYTE level; DWORD offer; BYTE name_flag; char name[CHARACTER_NAME_MAX_LEN+1]; } TGuildMemberPacketData; To this: typedef struct SGuildMemberPacketData { DWORD pid; BYTE byGrade; BYTE byIsGeneral; BYTE byJob; int byLevel; DWORD dwOffer; BYTE byNameFlag; } TGuildMemberPacketData; 2 1 1 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
TheMt2 11 Posted July 14, 2015 Share Posted July 14, 2015 Ok uderstand. thx Link to comment Share on other sites More sharing options...
Shiver 4 Posted July 14, 2015 Share Posted July 14, 2015 (edited) constants.cppWell, here you should decide how much is the maximum level you want. You should fill these tables with as much records, as the maximum level. (e.g if you want to have maximum level 300, you need to put 300 records to these tables) const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] const DWORD party_exp_distribute_table[PLAYER_MAX_LEVEL_CONST + 1] const int aiExpLossPercents[PLAYER_EXP_TABLE_MAX + 1] I don't understand.Where i fill these tables ?, Where i put 300 records ? And, my tables.. How i do that ? https://metin2.download/picture/yofIaf6wgTjq1LpRaIn4Th1X18mNdscL/.png Edited August 30, 2022 by Metin2 Dev Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
TheMt2 11 Posted July 14, 2015 Share Posted July 14, 2015 (edited) Work https://metin2.download/picture/qNyWjX77SdOB5U35r9XeGlUa3a883i1h/.jpg Edited August 30, 2022 by Metin2 Dev Core X - External 2 Internal 1 1 Link to comment Share on other sites More sharing options...
Premium masodikbela 1359 Posted July 14, 2015 Author Premium Share Posted July 14, 2015 (edited) constants.cppWell, here you should decide how much is the maximum level you want. You should fill these tables with as much records, as the maximum level. (e.g if you want to have maximum level 300, you need to put 300 records to these tables) const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] const DWORD party_exp_distribute_table[PLAYER_MAX_LEVEL_CONST + 1] const int aiExpLossPercents[PLAYER_EXP_TABLE_MAX + 1] I don't understand.Where i fill these tables ?, Where i put 300 records ? And, my tables.. How i do that ? https://metin2.download/picture/yofIaf6wgTjq1LpRaIn4Th1X18mNdscL/.png Soo... These tables contains the exp, that you have to get to reach a levelup. Each table must contain as much record, as much your max level. E.g. this is one of my table: const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] = { 0, // 0 300, 800, 1500, 2500, 4300, 7200, 11000, 17000, 24000, 33000, // 10 43000, 58000, 76000, 100000, 130000, 169000, 219000, 283000, 365000, 472000, // 20 610000, 705000, 813000, 937000, 1077000, 1237000, 1418000, 1624000, 1857000, 2122000, // 30 2421000, 2761000, 3145000, 3580000, 4073000, 4632000, 5194000, 5717000, 6264000, 6837000, // 40 7600000, 8274000, 8990000, 9753000, 10560000, 11410000, 12320000, 13270000, 14280000, 15340000, // 50 16870000, 18960000, 19980000, 21420000, 22930000, 24530000, 26200000, 27960000, 29800000, 32780000, // 60 36060000, 39670000, 43640000, 48000000, 52800000, 58080000, 63890000, 70280000, 77310000, 85040000, // 70 93540000, 102900000, 113200000, 124500000, 137000000, 150700000, 165700000, 236990000, 260650000, 286780000, // 80 315380000, 346970000, 381680000, 419770000, 461760000, 508040000, 558740000, 614640000, 676130000, 743730000, // 90 1041222000, 1145344200, 1259878620, 1385866482, 1524453130, 1676898443, 1844588288, 2029047116, 2029047116, // 99·ąş§ ŔĎ ¶§ ÇĘżä°ćÇčġ (100·ąş§ŔĚ µÇ±â Ŕ§ÇŃ) 2000000000, // 100 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 105 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 110 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 115 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 120 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 125 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 130 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 135 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 140 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 145 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 150 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 155 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 160 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 165 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 170 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 175 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 180 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 185 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 190 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 195 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 200 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 205 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 210 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 215 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 220 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 225 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 230 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 235 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 240 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 245 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 250 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 255 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 260 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 255 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 260 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 265 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 270 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 275 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 280 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 295 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 300 }; Edited August 30, 2022 by Metin2 Dev Core X - External 2 Internal 1 3 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
Shiver 4 Posted July 14, 2015 Share Posted July 14, 2015 (edited) constants.cppWell, here you should decide how much is the maximum level you want. You should fill these tables with as much records, as the maximum level. (e.g if you want to have maximum level 300, you need to put 300 records to these tables) const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1] const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] const DWORD party_exp_distribute_table[PLAYER_MAX_LEVEL_CONST + 1] const int aiExpLossPercents[PLAYER_EXP_TABLE_MAX + 1] I don't understand.Where i fill these tables ?, Where i put 300 records ? And, my tables.. How i do that ? https://metin2.download/picture/yofIaf6wgTjq1LpRaIn4Th1X18mNdscL/.png Soo... These tables contains the exp, that you have to get to reach a levelup. Each table must contain as much record, as much your max level. E.g. this is one of my table: const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] = { 0, // 0 300, 800, 1500, 2500, 4300, 7200, 11000, 17000, 24000, 33000, // 10 43000, 58000, 76000, 100000, 130000, 169000, 219000, 283000, 365000, 472000, // 20 610000, 705000, 813000, 937000, 1077000, 1237000, 1418000, 1624000, 1857000, 2122000, // 30 2421000, 2761000, 3145000, 3580000, 4073000, 4632000, 5194000, 5717000, 6264000, 6837000, // 40 7600000, 8274000, 8990000, 9753000, 10560000, 11410000, 12320000, 13270000, 14280000, 15340000, // 50 16870000, 18960000, 19980000, 21420000, 22930000, 24530000, 26200000, 27960000, 29800000, 32780000, // 60 36060000, 39670000, 43640000, 48000000, 52800000, 58080000, 63890000, 70280000, 77310000, 85040000, // 70 93540000, 102900000, 113200000, 124500000, 137000000, 150700000, 165700000, 236990000, 260650000, 286780000, // 80 315380000, 346970000, 381680000, 419770000, 461760000, 508040000, 558740000, 614640000, 676130000, 743730000, // 90 1041222000, 1145344200, 1259878620, 1385866482, 1524453130, 1676898443, 1844588288, 2029047116, 2029047116, // 99·ąş§ ŔĎ ¶§ ÇĘżä°ćÇčġ (100·ąş§ŔĚ µÇ±â Ŕ§ÇŃ) 2000000000, // 100 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 105 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 110 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 115 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 120 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 125 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 130 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 135 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 140 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 145 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 150 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 155 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 160 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 165 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 170 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 175 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 180 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 185 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 190 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 195 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 200 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 205 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 210 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 215 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 220 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 225 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 230 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 235 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 240 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 245 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 250 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 255 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 260 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 255 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 260 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 265 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 270 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 275 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 280 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 295 2000000000, 2000000000, 2000000000, 2000000000, 2000000000, // 300 }; Thanks dude, so can i do this others table ?like,copy paste your table ? Edited August 30, 2022 by Metin2 Dev Core X - External 2 Internal 1 1 1 Link to comment Share on other sites More sharing options...
Premium masodikbela 1359 Posted July 14, 2015 Author Premium Share Posted July 14, 2015 Well, I not recommend to rewrite all of the tables with this one. Its better to select the last 10 record, then paste at the end of the table, and do it until you reach the number of your maximum level. Btw, I started to edit these exp tables here: (7m, 58s and 11m 10s) 1 2 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
smutnazaba.jpg 3 Posted July 14, 2015 Share Posted July 14, 2015 (edited) Good Job Edited August 19, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
veilles 0 Posted July 14, 2015 Share Posted July 14, 2015 Can you do tutorial how to increase stack limit ? Link to comment Share on other sites More sharing options...
Premium masodikbela 1359 Posted July 14, 2015 Author Premium Share Posted July 14, 2015 Can you do tutorial how to increase stack limit ? I can't promise this, but I will see 1 The one and only UI programming guideline Link to comment Share on other sites More sharing options...
veilles 0 Posted July 14, 2015 Share Posted July 14, 2015 Can you do tutorial how to increase stack limit ? I can't promise this, but I will see It would be great Link to comment Share on other sites More sharing options...
Tacticus 73 Posted July 18, 2015 Share Posted July 18, 2015 (edited) when i try login my client crash and get this syser: Unknown packet header: 103, last: 48 43 what can be problem?? btw when try make with new char login my server crash...did i need edit anything in player.sql? Edited July 18, 2015 by Tacticus Link to comment Share on other sites More sharing options...
Night 366 Posted July 18, 2015 Share Posted July 18, 2015 don't you think that using "int" as a type is going a bit too far? for two reason : the first is that the range of an int is way too big for the level , after all who is going to have the max level 1kk for ex? well it can always be used. but be logical this is a bit too far. you can if it is for the player rank you can always do what ymir has done (the ability to get exp even on the max level (in this case you will have to change the exp var type)). the secound reason is why are you using a type that accept negative value? that can cause some problems at least use DWORD or unsigned short. and you did forget all of the quest functions that uses the level var. good luck. 1 Link to comment Share on other sites More sharing options...
Premium masodikbela 1359 Posted July 18, 2015 Author Premium Share Posted July 18, 2015 Well, you are right, int is really too big, and I will try out this with unsigned short, and then I will edit the topic. But I'm almost sure there isn't any problem between signed and unsigned int in this case, because I take care about it when I did this.I have searched for quest functions what uses unsigned char level var, but I couldn't find anyone. Maybe if you find one, please tell me. The one and only UI programming guideline Link to comment Share on other sites More sharing options...
Tacticus 73 Posted July 18, 2015 Share Posted July 18, 2015 (edited) thanks to masodikbela for fix problems...work perfect Edited August 19, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Cilindro 14 Posted July 19, 2015 Share Posted July 19, 2015 i have every timy the same error on compile need help pleass will break strict-aliasing rulescompile gm.cppgm.cpp: In function 'BYTE gm_new_get_level(const char*, const char*, const char*)':gm.cpp:69: warning: suggest parentheses around && within ||compile guild.cppguild.cpp: In member function 'void CGuild::SendListOneToAll(DWORD)':guild.cpp:407: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:408: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:409: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:410: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:412: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::SendListPacket(CHARACTER*)':guild.cpp:459: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:460: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:461: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:462: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:464: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'bool CGuild::OfferExp(CHARACTER*, int)':guild.cpp:983: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:984: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:985: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:986: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:988: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::LevelChange(DWORD, int)':guild.cpp:1664: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:1665: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:1666: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:1667: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:1669: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::ChangeMemberData(DWORD, DWORD, int, BYTE)':guild.cpp:1706: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:1707: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:1708: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:1709: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:1711: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'../../../Extern/include/cryptopp/cryptlib.h: In member function 'bool CryptoPP::NameValuePairs::GetValue(const char*, T&) const [with T = std::string]':../../../Extern/include/cryptopp/cryptlib.h:277: instantiated from here../../../Extern/include/cryptopp/cryptlib.h:264: warning: dereferencing type-punned pointer will break strict-aliasing rules../../../Extern/include/cryptopp/cryptlib.h: In member function 'bool CryptoPP::NameValuePairs::GetValue(const char*, T&) const [with T = int]':../../../Extern/include/cryptopp/cryptlib.h:283: instantiated from here../../../Extern/include/cryptopp/cryptlib.h:264: warning: dereferencing type-punned pointer will break strict-aliasing rulesMakefile:119: recipe for target 'OBJDIR/guild.o' failedgmake[1]: *** [OBJDIR/guild.o] Error 1gmake[1]: Leaving directory '/root/workspace/Server/game/src'Makefile:60: recipe for target 'all' failedgmake: *** [all] Error 2root@root:~/workspace/Server # Link to comment Share on other sites More sharing options...
Former Staff flygun 304 Posted July 20, 2015 Former Staff Share Posted July 20, 2015 i have every timy the same error on compile need help pleass will break strict-aliasing rulescompile gm.cppgm.cpp: In function 'BYTE gm_new_get_level(const char*, const char*, const char*)':gm.cpp:69: warning: suggest parentheses around && within ||compile guild.cppguild.cpp: In member function 'void CGuild::SendListOneToAll(DWORD)':guild.cpp:407: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:408: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:409: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:410: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:412: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::SendListPacket(CHARACTER*)':guild.cpp:459: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:460: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:461: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:462: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:464: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'bool CGuild::OfferExp(CHARACTER*, int)':guild.cpp:983: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:984: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:985: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:986: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:988: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::LevelChange(DWORD, int)':guild.cpp:1664: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:1665: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:1666: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:1667: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:1669: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::ChangeMemberData(DWORD, DWORD, int, BYTE)':guild.cpp:1706: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:1707: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:1708: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:1709: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:1711: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'../../../Extern/include/cryptopp/cryptlib.h: In member function 'bool CryptoPP::NameValuePairs::GetValue(const char*, T&) const [with T = std::string]':../../../Extern/include/cryptopp/cryptlib.h:277: instantiated from here../../../Extern/include/cryptopp/cryptlib.h:264: warning: dereferencing type-punned pointer will break strict-aliasing rules../../../Extern/include/cryptopp/cryptlib.h: In member function 'bool CryptoPP::NameValuePairs::GetValue(const char*, T&) const [with T = int]':../../../Extern/include/cryptopp/cryptlib.h:283: instantiated from here../../../Extern/include/cryptopp/cryptlib.h:264: warning: dereferencing type-punned pointer will break strict-aliasing rulesMakefile:119: recipe for target 'OBJDIR/guild.o' failedgmake[1]: *** [OBJDIR/guild.o] Error 1gmake[1]: Leaving directory '/root/workspace/Server/game/src'Makefile:60: recipe for target 'all' failedgmake: *** [all] Error 2root@root:~/workspace/Server # re do the server guild part Link to comment Share on other sites More sharing options...
Premium masodikbela 1359 Posted July 20, 2015 Author Premium Share Posted July 20, 2015 i have every timy the same error on compile need help pleass will break strict-aliasing rulescompile gm.cppgm.cpp: In function 'BYTE gm_new_get_level(const char*, const char*, const char*)':gm.cpp:69: warning: suggest parentheses around && within ||compile guild.cppguild.cpp: In member function 'void CGuild::SendListOneToAll(DWORD)':guild.cpp:407: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:408: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:409: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:410: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:412: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::SendListPacket(CHARACTER*)':guild.cpp:459: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:460: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:461: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:462: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:464: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'bool CGuild::OfferExp(CHARACTER*, int)':guild.cpp:983: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:984: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:985: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:986: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:988: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::LevelChange(DWORD, int)':guild.cpp:1664: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:1665: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:1666: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:1667: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:1669: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'guild.cpp: In member function 'void CGuild::ChangeMemberData(DWORD, DWORD, int, BYTE)':guild.cpp:1706: error: 'struct TGuildMemberPacketData' has no member named 'byNameFlag'guild.cpp:1707: error: 'struct TGuildMemberPacketData' has no member named 'byGrade'guild.cpp:1708: error: 'struct TGuildMemberPacketData' has no member named 'byIsGeneral'guild.cpp:1709: error: 'struct TGuildMemberPacketData' has no member named 'byJob'guild.cpp:1711: error: 'struct TGuildMemberPacketData' has no member named 'dwOffer'../../../Extern/include/cryptopp/cryptlib.h: In member function 'bool CryptoPP::NameValuePairs::GetValue(const char*, T&) const [with T = std::string]':../../../Extern/include/cryptopp/cryptlib.h:277: instantiated from here../../../Extern/include/cryptopp/cryptlib.h:264: warning: dereferencing type-punned pointer will break strict-aliasing rules../../../Extern/include/cryptopp/cryptlib.h: In member function 'bool CryptoPP::NameValuePairs::GetValue(const char*, T&) const [with T = int]':../../../Extern/include/cryptopp/cryptlib.h:283: instantiated from here../../../Extern/include/cryptopp/cryptlib.h:264: warning: dereferencing type-punned pointer will break strict-aliasing rulesMakefile:119: recipe for target 'OBJDIR/guild.o' failedgmake[1]: *** [OBJDIR/guild.o] Error 1gmake[1]: Leaving directory '/root/workspace/Server/game/src'Makefile:60: recipe for target 'all' failedgmake: *** [all] Error 2root@root:~/workspace/Server # I think you forgot to do this: Replace this: typedef struct SGuildMemberPacketData { DWORD pid; BYTE grade; BYTE is_general; BYTE job; BYTE level; DWORD offer; BYTE name_flag; char name[CHARACTER_NAME_MAX_LEN+1]; } TGuildMemberPacketData; To this: typedef struct SGuildMemberPacketData { DWORD pid; BYTE byGrade; BYTE byIsGeneral; BYTE byJob; int byLevel; DWORD dwOffer; BYTE byNameFlag; } TGuildMemberPacketData; The one and only UI programming guideline Link to comment Share on other sites More sharing options...
Premium tierrilopes 452 Posted July 20, 2015 Premium Share Posted July 20, 2015 Didnt tested but from topic feedback seems all is working just fine. I will surelly use this. Thank you for the tutorial Link to comment Share on other sites More sharing options...
Recommended Posts