Jump to content
metin2dev

Leaderboard


Popular Content

Showing most liked content since 08/19/2017 in all areas

  1. 11 points
    Hi devs, today I will release the fix I made for the skill cooldown, already fixed on official servers, this is the bug it self: And this is the fix: Regards! Fix skill cooldown ~ Shang.rar ### root/ui.py ### Search: def SetSlotCoolTimeColor(self, slotIndex, r, g, b, a): wndMgr.SetSlotCoolTimeColor(self.hWnd, slotIndex, r, g, b, a) ### Add after: def StoreSlotCoolTime(self, key, slotIndex, coolTime, elapsedTime = 0.0): wndMgr.StoreSlotCoolTime(self.hWnd, key, slotIndex, coolTime, elapsedTime) def RestoreSlotCoolTime(self, key): wndMgr.RestoreSlotCoolTime(self.hWnd, key)
  2. 11 points
    v17.4 Beta new packs (Nothing special) https://mega.nz/#!uVIjQDoY!kukBR-pFoxQqMzgt7cbVIAmYnTnepcXu6-_op1CDKVI
  3. 8 points
    New class used in official servers for minigameokey (move cards). Code can be improved, who have a better code please make a new topic. No one is forced to use my code. https://mega.nz/#!NpMR2AYI!2xgiiBn3dGLvxcnTv2oVH2RnqvL8DRZGAEtY_tdYJNY Screen (Shang) :
  4. 6 points
    9 New Tree's (Giant) Datei anzeigen Hi guys, i have download the tree's from this thread: thank you very much Nevisor for that beautiful pack. i just convert 4-5 Tree's and Change the size of them for big map's they are really nice. But, do not use to much of your map's cause it's .spt and will lag if you place 1.000.000.000.000.000 file Passwort: Profizockers.com here some screen's: Hochgeladen von Ace Hochgeladen 27.08.2017 Kategorie 3d Models
  5. 6 points
  6. 5 points
    This item type is the new type from official servers used for battle boxes and recently for boss chest and fish event boxes. You can open boxes few times (set in item_proto). 1. You can use macro ENABLE_BATTLE_FIELD because was added with battle zone. 2. Number of openings is in item_proto -> LimitValue1 (Like official) Let's start: Server Source Part: #db\src\ProtoReader.cpp (same steps in ItemCSVReader.cpp) //Search: "ITEM_BELT", //Add after: "ITEM_GACHA" //Search: in array string* arSubType 0, //34 //Add after: 0, //37 //Search: in array int arNumberOfSubtype 0, //34 //Add after: 0, //37 #common\item_length.h //Search: ITEM_BELT, //Add after: ITEM_GACHA, #game\src\item_manager.cpp //Search: if (id == 0) //Add before: (be careful , before) if(item->GetType() == ITEM_GACHA) item->SetSocket(0, item->GetLimitValue(1)); #game\src\char_item.cpp //Search: (CHARACTER::UseItemEx) case ITEM_EXTRACT: ... break; //Add after: case ITEM_GACHA: { DWORD dwBoxVnum = item->GetVnum(); std::vector <DWORD> dwVnums; std::vector <DWORD> dwCounts; std::vector <LPITEM> item_gets(0); int count = 0; if (GiveItemFromSpecialItemGroup(dwBoxVnum, dwVnums, dwCounts, item_gets, count)) { if(item->GetSocket(0) > 1) item->SetSocket(0, item->GetSocket(0) - 1); else ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (ITEM_GACHA)"); } } break; Client Source Part: #GameLib\ItemData.h //Search: ITEM_TYPE_BELT, //Add after: ITEM_TYPE_GACHA, #UserInterface\PythonItemModule.cpp //Search: PyModule_AddIntConstant(poModule, "ITEM_TYPE_BELT", CItemData::ITEM_TYPE_BELT); //Add after: PyModule_AddIntConstant(poModule, "ITEM_TYPE_GACHA", CItemData::ITEM_TYPE_GACHA); Client root part: #root\uitooltip.py #Search: elif item.ITEM_TYPE_FISH == itemType: if 0 != metinSlot: self.__AppendFishInfo(metinSlot[0]) #Add after: ### Gacha = Battle Shop Chest ### elif item.ITEM_TYPE_GACHA == itemType: if 0 != metinSlot: if self.isShopItem: restUsableCount = int(item.GetLimit(1)[1]) else: restUsableCount = int(metinSlot[0]) self.AppendSpace(5) self.AppendTextLine(localeInfo.TOOLTIP_REST_USABLE_COUNT % (restUsableCount), grp.GenerateColor(0.5, 1.0, 0.3, 1.0)) Client locale part: #locale_game.txt #Add: TOOLTIP_REST_USABLE_COUNT Left: %d Server Item_proto example: 25111 fish 보상상자 ITEM_GACHA 0 1 NONE NONE NONE NONE 0 0 0 0 0 LIMIT_NONE 0 LIMIT_NONE 1 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0 12 25112 fish 보상상자 ITEM_GACHA 0 1 NONE NONE NONE NONE 0 0 0 0 0 LIMIT_NONE 0 LIMIT_NONE 2 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0 12 25113 fish 보상상자 ITEM_GACHA 0 1 NONE NONE NONE NONE 0 0 0 0 0 LIMIT_NONE 0 LIMIT_NONE 3 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0 12
  7. 5 points
    Are you tired of write [ENTER] in all your text or use 20 says for write a simple text? Me, yes. So I coded a funcion wich solve this problem. The difference between this function and the normal "say" is that this search for the last word of the line, and dont cut this word like the normal "say" do. Add to your questlib.lua function say2(msg) msg_size = string.len(msg) if msg_size > 59 then local i = 59 last_word = nil while last_word == nil and i > 0 do if string.sub(msg,i,i) == " " or string.sub(msg,i,i) == "." or string.sub(msg,i,i) == "," then last_word = i end i = i-1 end if i == 0 then last_word = 59 end say(string.sub(msg,0,last_word)) say2(string.sub(msg,last_word+1)) else say(msg) end end Add to your quest_functions: say2 And now use say2 instead of say in your quests!
  8. 5 points
    The textures of this water are ideally joined by no visible textures (seams). Colors are well matched to the climate of the metin. Download: http://www.mediafire.com/file/ig1cwm93zmlc4i3/Metin2+-+nowa+tekstura+wody.rar Scan virustotal: https://www.virustotal.com/pl/url/7d7bf9aa3daffe7e1c4418a3050f9ae2270ec1233d03cbd9f9eecd7c9087ef66/analysis/1503531780/
  9. 4 points
    Advanced Regen Editor I have worked in the past week on a new regen tool(made in C#-WPF) to make the life easier for the mappers/server owner between us. It is an advanced regen tool that includes all the basic functions + new ones such as: mob/group file viewer. Importing regen file. Remember information - Remember the last data entered such as direction, respawn time,count etc. Color Character by color(Mob-Red, Stone-Blue, Boss-turquoise, NPC-Belge, Group-Black). Add a character - Left click. Remove a character - right click on a character dot. Load MOB/Group information - select mob_names.txt/group.txt to view information on a data grid(shown on screen shots below). When choosing a group.txt make sure you have type field set on group. Ctrl Z Feature - Reverse action, that means that if you added a character it will be deleted and if you removed a character it will be added back. Separation of exported files - Files will be exported upon the type of the map character, if you had stone,boss and npc character then stone.txt,boss.txt and npc.txt will be generated. This is not the final version, more cool features will be added within a matter of days/weeks(such as map zoom-in/out and few more). If you find any bugs, please reply here with the bug information in specific details. Please Like this thread if you find my tool useful! Ⓒ Metin2 Guild Wars. Version 1.0 Download Link: https://mega.nz/#!bM8Hmbgb!emV186zxV8fBNqVq6QWMTdWN4GIo0ss590QFh-p8lcM Virus total: https://www.virustotal.com/#/file/876d21f140e3be617c0587377b4e7cdfc3fb50cbe6a7d14d70c69b61cd183924/detection Enjoy!!
  10. 4 points
  11. 3 points
    Link:https://mega.nz/#!nh1lzTYQ!Sg3bqSR5rAiLAFNDikqBPnowz1WVWrWy78gc_r-QQ1Q Auto Block Chat (Insult).rar
  12. 3 points
    Hi there! Here you can see my all modifications about this codes, what I showed in my video, when you split or stack the same items the opening count will be correct always. <!> Carefully, it could be different name of variables, and different types what you have to fix by yourself <!>
  13. 3 points
    Hello, the time has come to withdraw from this area. You will have a cloud of helpful resources! http://xsag.esy.es/ I ask a moderator if she can put this topic sticky
  14. 3 points
    Hi there devs, Probably the most of us know the problem when an image contains alpha/fully transparent parts but you can't click trough them and it would be very necessary to do so. This problem is very common with the taskbars, for example with the ilumina taskbar (you know when it looks like you are clicking the ground, but the image is still there but that part is transparent). Video: How to: EterPythonLib\PythonWindow.h EterPythonLib\PythonWindowManagerModule.cpp EterPythonLib\PythonWindow.cpp EterLib\GrpImageTexture.cpp EterLib\GrpImageInstance.h EterLib\GrpImageInstance.cpp By default it won't check the alpha value, so it means that you have to add manually the "alpha_sensitive" flag to the preferred windows/objects (also note that its only effective with an expandedImageBox object and it has some interference with the "float" flag (if both added to the same object)). For the usage check the video. If you have any question, remark, or anything that you like to ask or suggest, feel free to post it here, or send it in PM. Have a nice day, ~masodikbela
  15. 3 points
    This weekend I'll release the next rev. Expect some great additions like I mentioned before. Also thanks to the community this new build will have a lot of minor bugs fixed. Going open source was the best decision in my opinion, I'd never have found them since some of them require a special setup which I'd never do. So yeah, I'd like to thank the community for it's suggestions and fixes. Even though I have very limited spare time to work with the core these days I was able to make big steps with the core and that's all thanks to the community. So yep: Thank you.
  16. 3 points
    Hey tutorial created for someone who requested. We will talk about the differences of this platforms and them how to setup it on the PC (i won't do a freebsd tutorial, there are 3000 of them Advantages: - Debugger more Intuitive than GDB - Memory Leak dump without using external programs - Easy start and stop - Console Output more detailed than FreeBSD - No Virtualizzation - Great speed in Release mode - Configuration and Gesture more easier (in my opition) Disadvantages: - Microsoft typedefs (CHAR,BYTE) - fopen,sprintf,swprintf,etc... are insecure , use newer and other stupid warnings because the compiler is special - Windows dosen't have peer redirect (USE_SELECT), other cores won't work - Maybe it wouldn't be easy to create a stop script - Missing some features like HackShield Step 1: Installing MySQL/MariaDB Download MySQL Installer here (you should do that even if you use MariaDB, it have some usefull tools) If you want to use MariaDB click here MySQL Installer: Installation method: Custom Don't install MySQL Server if you want to use MariaDB only Setting up MySQL Server: Standalone MySQL (Do not enable INNODB Cluster) Config Type: Development Machine (on your PC), Server Machine (if you want to use Windows Server) WARNING: on the service page the name must begin with MySQL You could uncheck "Start at Windows" if you want to start the server manually Then move into Execute and finish the install MariaDB Configuration You MUST change the name to something like this or anything else that won't be MySQL else you will die before starting the server (XD), seriusilly change it else there will be service mismatch If you want to install MariaDB with MySQL change the TCP Port If you want to remove MariaDB at System bootup you had to open the services (Run... -> services.msc) Find the name of the service (we setted that before), right click -> Property, Bootup type: Manual (No.. i don't have an English Windows) press apply and then ok Now you will see an icon rappresenting a dolphin (MySQL logo) let's right click them and we will se this If you have installed MariaDB go to Options -> Manage Monitored Items press Add --> Windows Service, select the service of MariaDB, press OK and close. Here, we could easly start, stop and restart out Databases, othen that use MySQL Workbench for run querys and show the server status If you want to launch MySQL Notifier at system startup, close any existing instance (Actions -> Close MySQL Notifier) go to this folder: C:\Program Files (x86)\MySQL\MySQL Notifier 1.1 and launch MySQLNotifier.exe with admin rights, them from the notifier clickActions -> Options, check "Run at Windows Startup" and click Accept Step 2: Database setup Go to C:\ProgramData\MySQL\MySQL Server 5.7\Data (if you use MySQL) or C:\Program Files\MariaDB 10.2\data (if you use MariaDB) and copy the database files here (or take them from /var/db/mysql if you have a VM) We need this folder (for the basic SF setup) account common hotbackup log player Step 3: Creating our SF in local Create a folder where we put our Windows server files (ex: Desktop\metin2_Server) This folder will be the same as we use for FreeBSD, then if must follow the same links and structure as the FreeBSD SF For create a symbolic link open a CMD with admin rights and type this command mklink <source file> <destination file> for the folder mklink /D For who want a (not tested) script in MS-BATCH Starting the server Open db.exe in db folder After you see "[async] 0/0/" or something similar it means that db has been started Launch in the older that you want game.exe and auth.exe making double-click Stopping the server Select the console window (of the core you want to stop) and press ESC button. Remeber that db.exe must be the last core that need to be stopped Notes - The only thing that need to be fixed (if you are using ymir source) is the ip check of "5.x" and "10.x" (easily fixing in Config.cpp) - The folder were we put the files (share_data,etc...) it's the same folder that we use in WinSCP. - All the implementations\tutorials written for FreeBSD are the same. - For building with Windows, you must install Visual Studio, open the file m2server.2008.sln (or copy the vcxproj into your source folder) and build - For building, you must create a compatible Extern, link is here
  17. 3 points
    Author: (c) Metin2 Factory/Guild Wars This implementation includes a new ingame GM command: /reload_regen which reloads ingame current map regen(regen.txt,boss.txt,stones.txt,etc) including server_attr Please follow the following steps: Open cmd.cpp look for: ACMD(do_purge); Add below: ACMD(reload_regen); Look for: { "nowar", do_nowar, 0, POS_DEAD, GM_PLAYER }, Add below: { "reload_regen", reload_regen , 0, POS_DEAD, GM_GOD }, Open cmd_gm.cpp look for the end of ACMD(do_purge) function and add below: ACMD(reload_regen) { std::vector<LPEVENT> regenEvent = SECTREE_MANAGER::instance().GetRegenEvent(ch->GetMapIndex()); for (std::vector<LPEVENT>::iterator it = regenEvent.begin(); it != regenEvent.end(); ++it) { event_cancel(&(*it)); } FuncPurge func(ch); func.m_bAll = true; LPSECTREE_MAP lm = SECTREE_MANAGER::instance().GetMap(ch->GetMapIndex()); lm->for_each(func); char * mapIndex; mapIndex = number_to_str(ch->GetMapIndex(), 10); SECTREE_MANAGER::instance().BuildMap(mapIndex, LocaleService_GetMapPath().c_str()); } Open sectree_manager.cpp Look for the end of int SECTREE_MANAGER::Build(const char * c_pszListFileName, const char* c_pszMapBasePath) function Add below: int SECTREE_MANAGER::BuildMap(const char * c_pszMapID, const char* c_pszMapBasePath) { std::string mapIndexPath = c_pszMapBasePath; mapIndexPath += "/index"; int test; FILE* fp = fopen(mapIndexPath.c_str(), "rb"); if (fp == NULL) { return 0; } std::string line; char buf[256 + 1]; while (fgets(buf, 256, fp)) { std::string tmp = buf; if (tmp.find(c_pszMapID) != std::string::npos) { printf("found!!"); break; } } char szFilename[256]; char szMapName[256]; int iIndex; *strrchr(buf, '\n') = '\0'; if (!strncmp(buf, "//", 2) || *buf == '#') return 0; sscanf(buf, " %d %s ", &iIndex, szMapName); snprintf(szFilename, sizeof(szFilename), "%s/%s/Setting.txt", c_pszMapBasePath, szMapName); TMapSetting setting; setting.iIndex = iIndex; if (!LoadSettingFile(iIndex, szFilename, setting)) { sys_err("can't load file %s in LoadSettingFile", szFilename); return 0; } snprintf(szFilename, sizeof(szFilename), "%s/%s/Town.txt", c_pszMapBasePath, szMapName); if (!LoadMapRegion(szFilename, setting, szMapName)) { sys_err("can't load file %s in LoadMapRegion", szFilename); return 0; } if (true == test_server) sys_log(0, "[BUILD] Build %s %s %d ", c_pszMapBasePath, szMapName, iIndex); // ¸ÕÀú ÀÌ ¼­¹ö¿¡¼­ ÀÌ ¸ÊÀÇ ¸ó½ºÅ͸¦ ½ºÆùÇØ¾ß Çϴ°¡ È®ÀÎ ÇÑ´Ù. if (map_allow_find(iIndex)) { LPSECTREE_MAP pkMapSectree = BuildSectreeFromSetting(setting); m_map_pkSectree.insert(std::map<DWORD, LPSECTREE_MAP>::value_type(iIndex, pkMapSectree)); snprintf(szFilename, sizeof(szFilename), "%s/%s/server_attr", c_pszMapBasePath, szMapName); LoadAttribute(pkMapSectree, szFilename, setting); snprintf(szFilename, sizeof(szFilename), "%s/%s/regen.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/npc.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/boss.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/stone.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/dungeon.txt", c_pszMapBasePath, szMapName); LoadDungeon(iIndex, szFilename); pkMapSectree->Build(); } return 1; } Open regen.cpp Look for: regen->event = event_create(regen_event, info, PASSES_PER_SEC(number(0, 16)) + PASSES_PER_SEC(regen->time)); add below: SECTREE_MANAGER::instance().AddRegenEventToMap(lMapIndex, regen->event); Open sectree_manager.h Look for: std::map<DWORD, std::vector<npc_info> > m_mapNPCPosition; Add below: std::map<long, std::vector<LPEVENT>> m_mapRegen; Look for: bool GetRandomLocation(long lMapIndex, PIXEL_POSITION & r_pos, DWORD dwCurrentX = 0, DWORD dwCurrentY = 0, int iMaxDistance = 0); Add below: void AddRegenEventToMap(long lMapIndex, LPEVENT event) { m_mapRegen[lMapIndex].push_back(event); } std::vector<LPEVENT> GetRegenEvent(long lMapIndex) { return m_mapRegen[lMapIndex]; } Open utils.h from common folder Look for: /*----atoi function-----*/ Add below: /*----itoa function-----*/ inline char* number_to_str(int val, int base) { static char buf[32] = { 0 }; int i = 30; for (; val && i; --i, val /= base) buf[i] = "0123456789abcdef"[val % base]; return &buf[i + 1]; } /*----itoa function-----*/ Recompile the source and enjoy.
  18. 3 points
    Story: Over time I learned that the SetEvent function can cause weird problems in Metin2, maybe you have this bug or maybe not, I actually encountered this problem and found the fix. How to trigger the bug: 1. Use this quest for a test: quest test begin state start begin when 9003.chat."quest test" begin say("Hey we are doing a test here") local o = select("option 1","option 2") if o == 1 then return elseif o == 2 then return end end end end 2. Now you click on the NPC, choose "quest test" option and don't click on any option(1,2) 3. /transfer your_character with another GM account 4. The character who clicked on "quest test" option and didn't choose any of the sub-options (1 or 2 ) will now have an invisible stucked window on the center and can't click on the ground or click the area in the center of the screen(where the quest ui was before teleportation) How to fix it: 1. Go to uiQuest.py 2. In def MakeQuestion find the SetEvent functions and edit them as below: def MakeQuestion(self, n): global entire_questbutton_number global entire_questpage_number global cur_questpage_number entire_questpage_number = ((n-2)/7)+1 entire_questbutton_number = n if not self.board: return self.btnAnswer = [self.MakeEachButton(i) for i in xrange (n)] import localeInfo self.prevbutton = self.MakeNextPrevPageButton() self.prevbutton.SetPosition(self.sx+self.board.GetWidth()/2-164, self.board.GetHeight()/2-16) self.prevbutton.SetText(localeInfo.UI_PREVPAGE) #self.prevbutton.SetEvent(self.PrevQuestPageEvent, 1, n) # buggy self.prevbutton.SAFE_SetEvent(self.PrevQuestPageEvent, 1, n) # unbuggy self.nextbutton = self.MakeNextPrevPageButton() self.nextbutton.SetPosition(self.sx+self.board.GetWidth()/2+112, self.board.GetHeight()/2-16) self.nextbutton.SetText(localeInfo.UI_NEXTPAGE) #self.nextbutton.SetEvent(self.NextQuestPageEvent, 1, n) # buggy self.nextbutton.SAFE_SetEvent(self.NextQuestPageEvent, 1, n) # unbuggy if cur_questpage_number != 1: cur_questpage_number = 1 Note: After that you should check for other SetEvent functions (comment them and see if the bug still happens) Info: The bug has something to do with the function arguments Other locations where this bug caused problems: intrologin.py - can cause the arrow keys,enter,esc to not work in the select character phase
  19. 3 points
  20. 3 points
    Hello guys. I'm here with the v17.2 and the v17.3 patches. 17.3 New gaya gui files + npcs New fish event gui files New changelook gui file (I've got this 3 weeks ago :P) New party match gui files New ranking gui files Unpacked protos: DE, CZ and HU (XML + TXT) Dumped root files + builtins <!> INFORMATIONS ONLY <!> https://mega.nz/#!aNgABRjS!SUCh-DVHxvc5LWbTMow9VOcGKPAvZmtQjeiEDz6ynmg
  21. 2 points
  22. 2 points
  23. 2 points
  24. 2 points
    Game Of Thrones The 100 The Originals The Vampire Diaries Teen Wolf 13 Reasons Why
  25. 2 points
    Hello everyone, Today I'm gonna share with you the clientside root from the end of the year 2015 by Webzen. Include codes of new interfaces(charselect, charcreate, selectempire), wolfman, acce, pet, costume and skillbook combination, selectattr, pshop search and a lots of modification. These codes are using a lot of new and expanded functions, constant variables which require the source modification. https://mega.nz/#!zcICCARZ!HZl-MVyeWukXb676qs9KCUV2q6S-wL_WXn_DedaPNiI #nosupport #no-no&no
  26. 2 points
    Hey there, so I got very good responds due to my last video, so I made the full package Login + Select + Empire + Create. Hope you like it and for more information contact me at skype: geo.geani94 . Special thanks to: @VegaS - for some advice @.Kori - for making a clean client and Serverfiles @All of you for the feedback from the other topic.
  27. 2 points
    Hi everyone, This is a funny project, the player can swim, fly, jump , and more with improvement in the future: Let's see video: Cordialy
  28. 2 points
    Just continue like this doesnt exists.
  29. 2 points
    Seems like no trans are allowed here
  30. 2 points
    That "bug" is because the quest window is not destroyed properly. In interfaceModule.py search: eachQuestWindow.CloseSelf() Replace with: eachQuestWindow.OnPressEscapeKey() How to test that "bug". Press logout button and in those 3 seconds open a quest, when you login again you can't click in quest area but quest is not there.
  31. 2 points
    Ask Gameforge to sell
  32. 2 points
    metin2_patch_user_situation https://mega.nz/#!6JgW0LYZ!m9g3GGhGFbiA4Z9VssPVu6kSeB48uEFXSwcl2AXBm-U metin2.sg eterPacks 2017.04.29. https://mega.nz/#!mFhU0CzY!9L6OC-cH6rSrVZi1npqkRCwW_TXGaJGkfBUJRJhDuRA
  33. 1 point
    The site with metin2 icons. If bad department is sorry. http://icometin2.eu
  34. 1 point
  35. 1 point
    No problem High Level Developer:
  36. 1 point
    if killing_enemy == 0 or killing_enemy == pc.get_vid() then return end o boi btw, the bug is source-sided, it's known that kill triggers trigger twice for players. Solution: Search this line in the questmanager.cpp file: m_mapNPC[npc].OnKill(*pPC); Substitute with: if (npc > 0) { m_mapNPC[npc].OnKill(*pPC); }
  37. 1 point
    Hello, like the old topic ( >here< ) this topic is reserved for SHARES ONLY. If you're searching some specific files use our file request topic >here<. Additionally to this you can search for your files in the latest fully unpacked client: 17.0.7 whole unpacked client: https://metin2dev.org/board/index.php?/topic/3541-official-unpacked-updates-metin2de/&do=findComment&comment=84202 17.0.12 whole unpacked client: https://metin2dev.org/board/index.php?/topic/3541-official-unpacked-updates-metin2de/&do=findComment&comment=86090 17.1 updates only: https://metin2dev.org/board/index.php?/topic/3541-official-unpacked-updates-metin2de/&do=findComment&comment=86516 If you spam in here (which includes asking for files) you will get an infraction! Sincerly, .PolluX
  38. 1 point
  39. 1 point
    24/08/2017: Polished up other functions. Added party_get_member_count, Added party.get_member_pids Added clear_dungeon, Added table.get_keyword_index Added table_is_any_subarray_containing_keyword, Added table_get_subarray_keyword_index,
  40. 1 point
    Animation Pipeline by PhiLL Hello guys... I don't know if someone of you knows me, I was working on InfinityMetin, 2 years ago... I left it for work and study on the 3D VFX field.. Now in my spare time I would like to work on the 3D stuffs for metin2 again but just for myself. The videos you are going to watch, are my pipeline for a new animation inside Metin2. Animation created by the user and not taken from other games like everyone does, where the skeleton has other positions and the character is going to be squashed and stretched in the wrong way... For now this pipeline is on alpha test, I've got to finish my rig setup in all the 8 characters. The skeletons are completely done and fixed (as you did see in my previous posts, I got some skeleton issues to resolve, and I did resolve 'em all). Information about the Pipeline: You can see everything from the video, is not difficult to understand. Software used: Maya 2016 Knowledge for this project: Rigging/Skinning/Animation on Autodesk Maya Video Animation System: Video in game: UPDATE 14/05/15 of the animation system: Request from you: Just want to know from you, what you think about this process and if it is usefull for metin2 developers or there are already "tools" like that one. And if you have ideas, just write 'em.
  41. 1 point
    to know how much work and time such a map need ill show you a littel Pictures, i hope any one understand what i want to say. you can see a point of the littel Picture and this point is one of more then 10 grases on the map. we have more then 4 textures and very much stones to place. to know how much time you Need just have a littel Fantasy. Why should I release it? i have much of reasons to not do it. 1. all mappers who use my things give 0 credits 2. Many people did not indicate that it is free and have it already bought. And earning money with my my work which I provide free of charge 3. I am supported by the least and get the people who have not earned it. 4. I am written to get only the map or my resources, after that I will still hate 5. more reasons? My english is very weak, but I hope you understand what I want to say. Ungrateful people who earn money with it / dont give credits: Ace,
  42. 1 point
    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 2147483647the damage done by the characters (and much more thing) is calculated via they levels, and the type of this variables is intThis 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_LEVELTo this: int PK_PROTECT_LEVELconstants.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
  43. 1 point
    To clarify a few things: - If someone spammed, a report is enough. Please do not write an extra post for this. - Double- (or even more) posts are allowed for shares in this topic.
  44. 1 point
    Today i release a code which you can walk through safezone without block Enjoy. Download: Here
  45. 1 point
    InstanceBase.h find NAMECOLOR_WAYPOINT, add NAMECOLOR_METIN, PythonCharacterManagerModule.cpp find PyModule_AddIntConstant(poModule, "NAMECOLOR_MOB", CInstanceBase::NAMECOLOR_NORMAL_MOB);add PyModule_AddIntConstant(poModule, "NAMECOLOR_METIN", CInstanceBase::NAMECOLOR_METIN); InstanceBaseEffect.cpp find else if (IsPoly()) { return NAMECOLOR_MOB; }add else if (IsStone()) { return NAMECOLOR_METIN; } PythonMiniMap.cpp find m_NPCPositionVector.clear(); add m_MetinPositionVector.clear(); find else if (pkInstEach->IsNPC()) { aMarkPosition.m_fX = ( m_fWidth - (float)m_WhiteMark.GetWidth() ) / 2.0f + fDistanceFromCenterX + m_fScreenX; aMarkPosition.m_fY = ( m_fHeight - (float)m_WhiteMark.GetHeight() ) / 2.0f + fDistanceFromCenterY + m_fScreenY; m_NPCPositionVector.push_back(aMarkPosition); }add else if (pkInstEach->IsStone()) { aMarkPosition.m_fX = ( m_fWidth - (float)m_WhiteMark.GetWidth() ) / 2.0f + fDistanceFromCenterX + m_fScreenX; aMarkPosition.m_fY = ( m_fHeight - (float)m_WhiteMark.GetHeight() ) / 2.0f + fDistanceFromCenterY + m_fScreenY; m_MetinPositionVector.push_back(aMarkPosition); } find // NPC STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, CInstanceBase::GetIndexedNameColor(CInstanceBase::NAMECOLOR_NPC)); aIterator = m_NPCPositionVector.begin(); while (aIterator != m_NPCPositionVector.end()) { TMarkPosition & rPosition = *aIterator; m_WhiteMark.SetPosition(rPosition.m_fX, rPosition.m_fY); m_WhiteMark.Render(); ++aIterator; }add // Metin STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, CInstanceBase::GetIndexedNameColor(CInstanceBase::NAMECOLOR_METIN)); aIterator = m_MetinPositionVector.begin(); while (aIterator != m_MetinPositionVector.end()) { TMarkPosition & rPosition = *aIterator; m_WhiteMark.SetPosition(rPosition.m_fX, rPosition.m_fY); m_WhiteMark.Render(); ++aIterator; } PythonMiniMap.h find TInstanceMarkPositionVector m_NPCPositionVector; add TInstanceMarkPositionVector m_MetinPositionVector; root/colorinfo.py find CHR_NAME_RGB_WARP = (136, 218, 241)add CHR_NAME_RGB_METIN = (240, 255, 255)You can select another color from here root/introloading.py find chrmgr.NAMECOLOR_WAYPOINT : colorInfo.CHR_NAME_RGB_WAYPOINT,add chrmgr.NAMECOLOR_METIN : colorInfo.CHR_NAME_RGB_METIN, Ingame Screen
  46. 1 point
    I mention that all these functions are shit, we just did in a hurry, we have not tested, they are just tools to check code that do not have very bright but functional. Someone wanted this and even more people from a certain conference, so I made this little tutorial. These features give you the chance to check the following: - To introduce reading a game DLL source automatically. - To check the size of the DLL in question. - To check more files in the client if that which corresponds md5 version of the file. ffd:h -> http://pastebin.com/1TXW32Qu Src/Client/UserInterface/Locale_inc.h #define __ENABLE_DLL_CHECK__ // enable #define __ENABLE_CHECK_SIZE__ // check size of files #define __ENABLE_CHECK_MD5__ // check md5 of files #define __SIZE_DLL__ 54200 // size in kb Src/Client/UserInterface/UserInterface.cpp #include "ffd.h" // Put file ffd.h in Extern/include/ #ifdef __ENABLE_DLL_CHECK__ int FunctionGetFileSize(char* FileName) { HANDLE pFile_done = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return FunctionGetFileSize(pFile_done, NULL); } #endif #ifdef __ENABLE_CHECK_MD5__ void FunctionGetFileMD5(char* cFile, char* hash) { MD5 ffd; if (strcmp(ffd.digestFile(cFile), hash)) { MessageBoxA(NULL, "It was detected a change to a file. Please do update the autopatcher!", "#System Error", NULL); exit(0); } } #endif You can check this function in : int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) #ifdef __ENABLE_DLL_CHECK__ const char* keyName = "name_your_dll"; HINSTANCE hGetProcIDDLL = LoadLibrary(keyName + ".dll"); if (hGetProcIDDLL == NULL) { MessageBox(NULL, "The customer name can not start without dll_vegas.dll, please update your autopatcher.", "#System Error", MB_ICONSTOP); return 0; } #endif #ifdef __ENABLE_CHECK_SIZE__ if (FunctionGetFileSize(keyName + ".dll") != __SIZE_DLL__) //kb { MessageBox(NULL, "DLL has been changed, please update.", "#System Error", MB_ICONSTOP); return 0; } #endif #ifdef __ENABLE_CHECK_MD5__ const char* MILES_key_MD5_Index_0 = "miles/mssdsp.flt"; const char* MILES_key_MD5_Index_0 = "miles/msssoft.m3d"; const char* MILES_key_MD5_Index_0 = "miles/mssa3d.m3d"; const char* MILES_key_MD5_Index_0 = "miles/mss32.dll"; const char* DLL_key_MD5_Index_0 = "python27.dll"; const char* DLL_key_MD5_Index_1 = "mss32.dll"; const char* LIB_key_MD5_Index_0 = "ib/__future__.pyc"; const char* LIB_key_MD5_Index_1 = "lib/copy_reg.pyc"; const char* LIB_key_MD5_Index_2 = "lib/linecache.pyc"; const char* LIB_key_MD5_Index_3 = "lib/ntpath.pyc"; const char* LIB_key_MD5_Index_4 = "lib/os.pyc"; const char* LIB_key_MD5_Index_5 = "lib/site.pyc"; const char* LIB_key_MD5_Index_6 = "lib/stat.pyc"; const char* LIB_key_MD5_Index_7 = "lib/string.pyc"; const char* LIB_key_MD5_Index_8 = "lib/traceback.pyc"; const char* LIB_key_MD5_Index_9 = "lib/types.pyc"; const char* LIB_key_MD5_Index_10 = "lib/UserDict.pyc"; const char* Index_key_md5_ = "pack/Index"; const char* PACK_key_MD5_Index_0 = "pack/root.eix"; const char* PACK_key_MD5_Index_1 = "pack/ETC.eix"; const char* PACK_key_MD5_Index_2 = "pack/locale_en.eix"; ///////////// VERIFICATION PATCH MILES /////////////////// FunctionGetFileMD5(MILES_key_MD5_Index_0,"cb71b1791009eca618e9b1ad4baa4fa9"); FunctionGetFileMD5(MILES_key_MD5_Index_1,"bdc9ad58ade17dbd939522eee447416f"); FunctionGetFileMD5(MILES_key_MD5_Index_2,"e089ce52b0617a6530069f22e0bdba2a"); FunctionGetFileMD5(MILES_key_MD5_Index_3,"6400e224b8b44ece59a992e6d8233719"); ///////////// VERIFICATION PATCH DLL /////////////////// FunctionGetFileMD5(DLL_key_MD5_Index_0,"d219c0a8aff2c771946d73554916bd9a"); FunctionGetFileMD5(DLL_key_MD5_Index_1,"6400e224b8b44ece59a992e6d8233719"); ///////////// VERIFICATION PATCH LIB /////////////////// FunctionGetFileMD5(LIB_key_MD5_Index_0,"d2505c6e64dc44a1745dda0905f4e787"); FunctionGetFileMD5(LIB_key_MD5_Index_1,"5e996d35b598676b253dd25fa3809ef2"); FunctionGetFileMD5(LIB_key_MD5_Index_2,"c4c28529b05b4093f629fb7b23603cd2"); FunctionGetFileMD5(LIB_key_MD5_Index_3,"966048f390a65bebf60f912845441110"); FunctionGetFileMD5(LIB_key_MD5_Index_4,"9e1e72faaafcde16dfd0e643a31f0b74"); FunctionGetFileMD5(LIB_key_MD5_Index_5,"8336371539a459e72d7110f0cb1ed84f"); FunctionGetFileMD5(LIB_key_MD5_Index_6,"3dc2d3d11ba4c668a0097fbd631c7be6"); FunctionGetFileMD5(LIB_key_MD5_Index_7,"39c29074226b2196e7f13ce93560d3d0"); FunctionGetFileMD5(LIB_key_MD5_Index_8,"009e6647dfac211b6e69c6b3f1ed5600"); FunctionGetFileMD5(LIB_key_MD5_Index_9,"2bff75340aa1d94b88bfc7915a291564"); FunctionGetFileMD5(LIB_key_MD5_Index_10,"aabdd94dfe3a1b0092f0a414a935c091"); ///////////// VERIFICATION INDEX /////////////////// FunctionGetFileMD5(Index_key_md5_,"8823ca827dfc980798856e97f3568cef"); ///////////// VERIFICATION FILES PACK /////////////////// FunctionGetFileMD5(PACK_key_MD5_Index_0,"ce13b7c96f725b7d7c39cbe1ae2f8b4d"); FunctionGetFileMD5(PACK_key_MD5_Index_1,"7c0b756d079a9c76a220a724b9594eeb"); FunctionGetFileMD5(PACK_key_MD5_Index_2,"5b1aea18b89330481e16eca94673951c"); #endif
  47. 1 point
    https://metin2dev.org/board/index.php?/topic/12505-block-rank-map/ I saw this guy looking hasta .. it provides money for shit, so I wanted to paint a small tutorial sucks these functions. [File: Src/game/src/service.h] #define ENABLE_PROTECT_ALIGNMENT #ifdef ENABLE_PROTECT_ALIGNMENT #define IS_MAPINDEX_PROTECT_ALIGN(map) (200==(map)||201==(map)||(202)==(map)) #endif [File: Src/game/src/char_battle.cpp] //1.) Search: if (g_iUseLocale && pkKiller->GetParty()) { FPartyAlignmentCompute f(-20000, pkKiller->GetX(), pkKiller->GetY()); pkKiller->GetParty()->ForEachOnlineMember(f); if (f.m_iCount == 0) pkKiller->UpdateAlignment(-20000); //2.) Delete and replaced with this: if (g_iUseLocale && pkKiller->GetParty()) { #ifdef ENABLE_PROTECT_ALIGNMENT if (IS_MAPINDEX_PROTECT_ALIGN(GetMapIndex())) { return; } #endif FPartyAlignmentCompute f(-20000, pkKiller->GetX(), pkKiller->GetY()); pkKiller->GetParty()->ForEachOnlineMember(f); if (f.m_iCount == 0) pkKiller->UpdateAlignment(-20000); [File: Src/game/src/char.cpp] //1.) Search: UpdateAlignment(5 * (dwPlayedTime / 60000)); //2.) Delete and replaced with this: #ifdef ENABLE_PROTECT_ALIGNMENT if (IS_MAPINDEX_PROTECT_ALIGN(GetMapIndex())) { return; } #endif UpdateAlignment(5 * (dwPlayedTime / 60000)); PS: I have not tested this, I just wrote. But in principle it should work. ------------------- EDIT: Fcking shit or you can make that easy: [File: Src/game/src/char_battle.cpp] void CHARACTER::UpdateAlignment(int iAmount) { #ifdef ENABLE_PROTECT_ALIGNMENT if (IS_MAPINDEX_PROTECT_ALIGN(GetMapIndex())) { return; } #endif bool bShow = false; if (m_iAlignment == m_iRealAlignment) bShow = true; int i = m_iAlignment / 10; m_iRealAlignment = MINMAX(-200000, m_iRealAlignment + iAmount, 200000); if (bShow) { m_iAlignment = m_iRealAlignment; if (i != m_iAlignment / 10) UpdatePacket(); } }
  48. 1 point
    Hallo all In The Fitst This Is A Beginner Tut in this tut we going to use table insted of if elseif else ipairs insted of table.getn ( Thanks To Marty <3 ) In What This Will help ? I am Seening To many pepole who want make quest and it's have too many if + elseif and they dont know when they put else or when they put end in the end u have atleast 20 elseif and quest maybe 300 line so i will show u how to write it in maybe 20 line and easy to understnad also easy to add new item to it i will take a e.g for a item trade ( player give items for npc and he take a new item ) e.g For Quest quest table_test begin state start begin when xxx.click begin say("chose what u want to give") local data01 = { -- Name vnum count give_vnum count {"Enargy", 51001, 200, 71159, 1}, {"Drink", 71054, 1, 71160, 1}, } local menu01 = {} for num1,str1 in ipairs(data01) do table.insert(menu01, str1[1]) end local seltab01 = select_table(menu01, " Close ") local count_check = pc.count_item(data01[seltab01][2]) if seltab01 == table.getn(menu01) then return end say(" Are u Sure U want Give ".. data01[seltab01][1] .." To Get "..item_name(data01[seltab01][4]).." ") if select("Yes Sure","No I Dont Want It") == 2 then return end if count_check < 1 then syschat("Not possess the required number") return end say_reward("You Get : "..item_name(data01[seltab01][3]+1).."") pc.removeitem(data01[seltab01][2],data01[seltab01][3]) pc.give_item2(data01[seltab01][4], data01[seltab01][5]) end -- when end -- state end -- quest Let's Start local data01 = { Thos for Start The Table Items {"Enargy", 51001, 200, 71159, 1}, Name vnum count give_vnum count if u want add Other Item Just Add New Line {"Name", vnum, count, give_vnum, count}, Now To The Part That It's Show The Items in game: local menu01 = {} for num1,str1 in ipairs(data01) do table.insert(menu01, str1[1]) end Here As U Can See We Make New Local And It's empty and we give him name menu01 then for num1,str1 in ipairs(data01) do < we here load the first tab from the data01 table.insert(menu01, str1[1]) we here insert the first tab from data01 to the menu01 and now the part from quest to show tab for the player : local seltab01 = select_table(menu01, " Close ") the check count for the selected item local count_check = pc.count_item(data01[seltab01][2]) pc.count_item = count function data01 = the table seltab01 = the selected item tab [2] = second tab from the selected item ( the item vnum tab ) and i think The rest code is clear sry for my bed Engish I Hope This Help Some Pepole
  49. 1 point
    The only two errors you could get when you compile your root are:"Decoding error, missing or incorrect coding"Since all the .py files are processed as korean strings, all of them written with a different charset (arabic) will trigger this issue. It's explained in the .txt file, and you can simply bypass this just writing the text in the locale_game.txt file. "Expected an increase in indentation level"This happens when the .py file has a bad tabulation, so bad written: It's clear that you won't be able to compile unworkable/unrunnable/broken .py files.
  50. 1 point
    Are your map2 and arena on the same gamecore? (because they must be)
×