Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/10/18 in all areas

  1. Hello everybody, since I've heard that a lot of servers (and even the most recent vanilla source release) have no fix for this hack I decided to release this. It's not too big, but I really would like to make it visible for everybody. I highly dislike hacks in every form and I'll gladly develop such fixes. So, the fix is quite easy. It's a bug from metin2. They decided to add a check if the target is too far away to be attacked and yeah, that works. Targets only receive damage once they're within range. But the problem is that modern moblock tools do that a different way. They send attack packets to every mob in the near surrounding which triggers aggr towards the player. You may ask: Why does it trigger aggr and let the mobs move to the player? Well, as mentioned, the source has a fix for that - but it's implemented too late. 1. Open char_battle.cpp and search for this function: CHARACTER::Attack First you may notice that there's literally no check for distance. The distance check is implemented in battle.cpp in the function battle_melee_attack. That's fine and we don't need to modify anything about this. 2. If you scroll down you'll see the following lines: pkVictim->SetSyncOwner(this); if (pkVictim->CanBeginFight()) pkVictim->BeginFight(this); Noticed something? Yeah, the check is - as mentioned before - in the function battle_melee_attack. The problem is, that these lines are executed before the check happens. So hackers will be visible in logfiles (syslog should spam distance errors) but they're still free to hack like they want to. 3. Move the lines below the battle type segment So, how do we fix this? We'd simply move it down below the battle type functions. So you'd move it just before the line "if (iRet == BATTLE_DAMAGE || iRet == BATTLE_DEAD)". But still that won't be enough since these lines would still be executed. We don't want them to be executed. So we wrap a condition around it. 4. modify these lines so they look like this: if(iRet != BATTLE_NONE) { pkVictim->SetSyncOwner(this); if (pkVictim->CanBeginFight()) pkVictim->BeginFight(this); } If we take a look on the battle type functions we'll notice that they return the BATTLE_NONE if something goes wrong - for example the distance is invalid. 5. you're done! The fix pretty much solves this issue. If you still know hacks that work feel free to write in this topic, I'll gladly share solutions once I've developed them. Enjoy!
    5 points
  2. Speedhacks are already somewhat fixed. In battle.cpp look for the function IS_SPEED_HACK and replace it with this one: bool IS_SPEED_HACK(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time) { if (ch->m_kAttackLog.dwVID == victim->GetVID()) { if (current_time - ch->m_kAttackLog.dwTime < GET_ATTACK_SPEED(ch)) { INCREASE_SPEED_HACK_COUNT(ch); sys_log(0, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d", ch->GetName(), current_time - ch->m_kAttackLog.dwTime, GET_ATTACK_SPEED(ch), ch->m_speed_hack_count); if (test_server) { ch->ChatPacket(CHAT_TYPE_INFO, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d", ch->GetName(), current_time - ch->m_kAttackLog.dwTime, GET_ATTACK_SPEED(ch), ch->m_speed_hack_count); } SET_ATTACK_TIME(ch, victim, current_time); SET_ATTACKED_TIME(ch, victim, current_time); if (ch->m_speed_hack_count >= 10) ch->GetDesc()->DelayedDisconnect(3); return true; } } SET_ATTACK_TIME(ch, victim, current_time); if (victim->m_AttackedLog.dwPID == ch->GetPlayerID()) { if (current_time - victim->m_AttackedLog.dwAttackedTime < GET_ATTACK_SPEED(ch)) { INCREASE_SPEED_HACK_COUNT(ch); sys_log(0, "%s Attack Speed HACK! time (delta, limit)=(%u, %u), hack_count = %d", ch->GetName(), current_time - victim->m_AttackedLog.dwAttackedTime, GET_ATTACK_SPEED(ch), ch->m_speed_hack_count); if (test_server) { ch->ChatPacket(CHAT_TYPE_INFO, "Attack Speed Hack(%s), (delta, limit)=(%u, %u)", ch->GetName(), current_time - victim->m_AttackedLog.dwAttackedTime, GET_ATTACK_SPEED(ch)); } SET_ATTACKED_TIME(ch, victim, current_time); if (ch->m_speed_hack_count >= 10) ch->GetDesc()->DelayedDisconnect(3); return true; } } SET_ATTACKED_TIME(ch, victim, current_time); return false; } Note that the only thing I've changed is that the loggin always happens and that you get disconnected if the speedhack detection is triggered too often. The "10" is subject to change. Also make sure that you visit the function GET_ATTACK_SPEED which is also in battle.cpp. Remove these two lines: if (item && item->GetSubType() == WEAPON_DAGGER) real_speed /= 2; and set the variable "default_bonus" to something like 70 (which is a quite good value in test environments). You can fine-tune this value. Make sure you also remove the * 3. You may just want to have a simple value like 70 (default: 80 which is too much in some conditions, depending on your server). This should trigger all those hacks and still make your game playable without false-positives. But this indeed needs further testing, for live servers I recommend choosing a higher threshold (at least 80) until it's confirmed to be working on your server.
    3 points
  3. Cut the shit you can't even answer your own questions !
    2 points
  4. Hi there devs, Okay, so after reading the title you may (or may not) have some thougts/questions like "Hollllllllly sh..", "Oooookay..." or just "?". About one or two years ago a mapper questioned me: "Is this possible, to make the whole map visible? Like in normal games? This fog is sooo disgusting, I've could create more beautiful view with a normal fog..." I've tried to do it many ways until finally after some sleepless night I've made it about a year ago. Once it was done I didn't know what to do with it. It was pretty good (I think) but since I'm not a mapper I can't do anything with it. I could have sell it, but since there is no way to protect this code its not an option for me, so I've decided to share it with the public. This TuT gonna be a bit long and there are several things to discuss but FIRST lets watch this video (in the first part I disabled the fog). "Wow, thats actually not bad" this was my first reaction when I first saw this view. BUT enough from me, lets talk about more important things... So I decided to create stages for this tutorial (4 stages actually). Its a normal down-top thing, so it means that you can do stage 1, 2 and then you can stop, but can't do stage 2 without 1, 3 without 2 and 4 without 3... it will help you to customize these modifications. Also I may write some "interesting" (at least for me) notes/thoughts for each stages. However, as you will see the last 2 stages are not ready at the moment, so I would rather say its an experimental release... Anyway, before we start to implement this lets talk about the tests, performance and other more or less important things. Table of content: Stage 1: Removing garbage collectors, loading all map related things into memory ("chunks", objects, etc...) Stage 2: Rendering full terrain Stage 3: Rendering all objects on map [NOT READY YET] Stage 4: Create config for players [NOT READY YET] Performance One of the most important questions about a game: will I be able to play it with my spec? Well of course this depends on much things. Using high poly objects, large maps, HD textures, lots of trees, effects can highly impact the performance/rendering time. So all I can say about it in a nutshell: its really depends on your maps (and of course the player's machine). Until now this old buddy could be ran on almost every computer but with this could change things so this is why I created config for it, enabling or disabling this feature. About my experiences/tests Well the memory usage increased, from the default ~270 MB to ~300 MB (see the explanations later), the processor usage didn't change (~5-10%). About my video card usage I can't tell nothing since I can't monitor it, but I'm sure its usage (both video memory and processing) increased too... You maybe noticed some lag in the video but its not the case, its only because of my recorder, the game is still runs smoothly (remember, its depends on the computer and the map...) If it helps I have a Lenovo U41-70 notebook (Intel i7 5500U, 8GB DDR3 and GeForce 920M) and I used the "(old) wom2 maps". However, I noticed some fps drop with all shadows enabled, and also couldn't test it with many characters (cus the character render consumes so much processing time without this too), so I recommend to disable it by default and if the player decides to use it, he will be able to turn it on. Stage 1 Stage 2 Stage 3 Stage 4 So yeah this is it so far, if you have problem with the code (not compiling, etc) is probably because you did something wrong, I made these steps too on a full untouched client source so it should work for you too... (So pls don't ask me to help with this ) However, if something is not clear in the tutorial you can ask me for pictures or clarification. I didn't test it in dungeons (indoor maps) so there could be problems... Also if you made this and you have some nice maps or you find some great spots for some ingame pictures or videos, feel free to post them here
    1 point
  5. M2 Download Center Download Here ( Internal ) A small model, nothing ambitious, but it may be useful to someone (designer mapper). I made 3 sizes of this model to choose. Download: [Hidden Content]
    1 point
  6. M2 Download Center Download Here ( Internal ) //Find in PythonNetworkStreamModule.cpp: PyObject* netGetBettingGuildWarValue(PyObject* poSelf, PyObject* poArgs) { char* szName; if (!PyTuple_GetString(poArgs, 0, &szName)) return Py_BuildException(); CPythonNetworkStream& rkNetStream=CPythonNetworkStream::Instance(); return Py_BuildValue("i", rkNetStream.EXPORT_GetBettingGuildWarValue(szName)); } ///Add; static const char* ServerIPVName[4][2] = { {"192.168.0.100", "BETA-1"}, {"76.342.12.12", "BETA-2"}, {"145.12.231.12", "BETA-3"}, {"192.31.52.69", "BETA-4"} }; static unsigned int ServerPORT[] = {{13000},{1600},{1900},{21000},{11002},{13000}}; PyObject* netGetServer_IPNAME(PyObject* poSelf, PyObject* poArgs) { return Py_BuildValue("ssssssss", ServerIPVName[0][0], ServerIPVName[0][1], ServerIPVName[1][0], ServerIPVName[1][1], ServerIPVName[2][0], ServerIPVName[2][1], ServerIPVName[3][0], ServerIPVName[3][1] ); } PyObject* netGetServer_PORT(PyObject* poSelf, PyObject* poArgs) { return Py_BuildValue("iiiiii", ServerPORT[0],ServerPORT[1],ServerPORT[2],ServerPORT[3],ServerPORT[4],ServerPORT[5]); } //Find: { "SendOnClickPacket", netOnClickPacket, METH_VARARGS }, ///Add; { "GetServer_IPNAME", netGetServer_IPNAME, METH_VARARGS }, { "GetServer_PORT", netGetServer_PORT, METH_VARARGS }, Example ServerInfo.py import net (sv1_ip, sv1_name, sv2_ip, sv2_name, sv3_ip, sv3_name, sv4_ip, sv4_name) = net.GetServer_IPNAME() (ch1_port, ch2_port, ch3_port, ch4_port, auth_port, mark_port) = net.GetServer_PORT() CH_1_NAME = "|cFF00FFFF|hCH1" CH_2_NAME = "|cFF00FFFF|hCH2" CH_3_NAME = "|cFF00FFFF|hCH3" CH_4_NAME = "|cFF00FFFF|hCH4" STATE_NONE = "|cFFFF0000|hKAPALI" STATE_DICT = { 0 : "|cFFFF0000|hKAPALI", 1 : "|cff00ff00|hNORMAL", 2 : "|cff00ff00|hYOGUN", 3 : "|cff00ff00|hDOLU" } SERVER01_CHANNEL_DICT = { 1:{"key":11,"name":CH_1_NAME,"ip":sv1_ip,"tcp_port":ch1_port,"udp_port":ch1_port,"state":STATE_NONE,}, 2:{"key":12,"name":CH_2_NAME,"ip":sv1_ip,"tcp_port":ch2_port,"udp_port":ch2_port,"state":STATE_NONE,}, 3:{"key":13,"name":CH_3_NAME,"ip":sv1_ip,"tcp_port":ch3_port,"udp_port":ch3_port,"state":STATE_NONE,}, 4:{"key":14,"name":CH_4_NAME,"ip":sv1_ip,"tcp_port":ch4_port,"udp_port":ch4_port,"state":STATE_NONE,}, } SERVER02_CHANNEL_DICT = { 1:{"key":11,"name":CH_1_NAME,"ip":sv2_ip,"tcp_port":ch1_port,"udp_port":ch1_port,"state":STATE_NONE,}, 2:{"key":12,"name":CH_2_NAME,"ip":sv2_ip,"tcp_port":ch2_port,"udp_port":ch2_port,"state":STATE_NONE,}, 3:{"key":13,"name":CH_3_NAME,"ip":sv2_ip,"tcp_port":ch3_port,"udp_port":ch3_port,"state":STATE_NONE,}, 4:{"key":14,"name":CH_4_NAME,"ip":sv2_ip,"tcp_port":ch4_port,"udp_port":ch4_port,"state":STATE_NONE,}, } SERVER03_CHANNEL_DICT = { 1:{"key":11,"name":CH_1_NAME,"ip":sv3_ip,"tcp_port":ch1_port,"udp_port":ch1_port,"state":STATE_NONE,}, 2:{"key":12,"name":CH_2_NAME,"ip":sv3_ip,"tcp_port":ch2_port,"udp_port":ch2_port,"state":STATE_NONE,}, 3:{"key":13,"name":CH_3_NAME,"ip":sv3_ip,"tcp_port":ch3_port,"udp_port":ch3_port,"state":STATE_NONE,}, 4:{"key":14,"name":CH_4_NAME,"ip":sv3_ip,"tcp_port":ch4_port,"udp_port":ch4_port,"state":STATE_NONE,}, } SERVER04_CHANNEL_DICT = { 1:{"key":11,"name":CH_1_NAME,"ip":sv4_ip,"tcp_port":ch1_port,"udp_port":ch1_port,"state":STATE_NONE,}, 2:{"key":12,"name":CH_2_NAME,"ip":sv4_ip,"tcp_port":ch2_port,"udp_port":ch2_port,"state":STATE_NONE,}, 3:{"key":13,"name":CH_3_NAME,"ip":sv4_ip,"tcp_port":ch3_port,"udp_port":ch3_port,"state":STATE_NONE,}, 4:{"key":14,"name":CH_4_NAME,"ip":sv4_ip,"tcp_port":ch4_port,"udp_port":ch4_port,"state":STATE_NONE,}, } REGION_NAME_DICT = { 0 : "", } REGION_AUTH_SERVER_DICT = { 0 : { 1 : { "ip":sv1_ip, "port":auth_port, }, 2 : { "ip":sv2_ip, "port":auth_port, }, 3 : { "ip":sv3_ip, "port":auth_port, }, 4 : { "ip":sv4_ip, "port":auth_port, }, } } REGION_DICT = { 0 : { 1 : { "name" :sv1_name, "channel" : SERVER01_CHANNEL_DICT, }, 2 : { "name" :sv2_name, "channel" : SERVER02_CHANNEL_DICT, }, 3 : { "name" :sv3_name, "channel" : SERVER03_CHANNEL_DICT, }, 4 : { "name" :sv4_name, "channel" : SERVER04_CHANNEL_DICT, }, }, } MARKADDR_DICT = { 10 : { "ip" : sv1_ip, "tcp_port" : mark_port, "mark" : "10.tga", "symbol_path" : "10", }, 20 : { "ip" : sv2_ip, "tcp_port" : mark_port, "mark" : "20.tga", "symbol_path" : "20", }, 30 : { "ip" : sv3_ip, "tcp_port" : mark_port, "mark" : "30.tga", "symbol_path" : "30", }, 40 : { "ip" : sv4_ip, "tcp_port" : mark_port, "mark" : "40.tga", "symbol_path" : "40", }, }
    1 point
  7. M2 Download Center Download Here ( Internal ) This is the edited texture of the initial outfit for assassin, made by me. Download: [Hidden Content]
    1 point
  8. M2 Download Center Download Here ( Internal ) Hey, I'd like to release the following modification for monsters targetboards: How to add: open uiTarget.py search for def __init__(self): and add under hpGauge = ui.Gauge() hpGauge.SetParent(self) hpGauge.MakeGauge(130, "red") hpGauge.Hide() hpPercenttxt = ui.TextLine() hpPercenttxt.SetParent(self) hpPercenttxt.SetPosition(160, 13) hpPercenttxt.SetText("") hpPercenttxt.Hide() Search for self.name = name self.hpGauge = hpGauge and add under this self.hpPercenttxt = hpPercenttxt Search def Destroy(self): add it under self.hpPercenttxt = None Search def ResetTargetBoard(self): Find self.hpGauge.Hide() add it under self.hpPercenttxt.Hide() Now search for def SetHP(self, hpPercentage): and add under self.UpdatePosition() self.hpPercenttxt.SetPosition(200 + 7*self.nameLength-205, 13) self.hpPercenttxt.Show() and under self.hpGauge.SetPercentage(hpPercentage, 100) self.hpPercenttxt.SetText("%d%%" % (hpPercentage)) Have fun!
    1 point
  9. in item_proto change the ITEM_GIFTBOX to ITEM_USE with USE_SPECIAL as subtype .
    1 point
  10. Your item_proto sql is not equal to client side. To able the papyrus upp, must have refined_vnum there too.
    1 point
  11. Very useful, we shouldn't need many anticheat measures if we would apply corrections in the source itself, thank you for this contribution.
    1 point
  12. Latest update. item and mob protos are dumped, in more or less readable xml format. Mob proto got a new value by name ResistFist (xD). Every texts of the quests are in the locale files from now in the locale/XX/locale_quest.txt file. Some gui elements for the quest category. Correction of the dark temple map, probably they discovered that the minimap wasn't show some bridges /emoticons/default_biggrin.png (Mega) (Metin2 Download)
    1 point
  13. Sending it like that isn't a bit pointless? Why not make the connections really in the binary instead of sending to python?
    1 point
  14. The well coded c++ codes are more safety than pylua connections, in my opinion.
    1 point
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.