Jump to content

metin2-factory

Inactive Member
  • Posts

    174
  • Joined

  • Last visited

  • Days Won

    13
  • Feedback

    0%

Everything posted by metin2-factory

  1. At first i tried only client side but there were 2 down sides. first, the flags are declared only in server side that means you'd have to add a new enum in client side which is pointless. and second, for some reason a few raceflag do not show properly on client side. also, i prefer the logic to remain in server side. It doesn't matter much and i rather keep the code clean and easier to work with. also, server side check is required for the element icon over player target which ill add later on.
  2. Small update: Added tool tip to make it more clear for players, follow the steps below to have it. Like this post if you find it useful Screens: in _init_ and in Destroy methods look for: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None replace with: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None self.elementId = None self.elementImageToolTip = None search for: def Close(self): add inside the method: if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage.Hide() Search for: ELEMENT_IMAGE_DIC = {1: "elect", 2: "fire", 3: "ice", 4: "wind", 5: "earth", 6: "dark"} add above: import uiToolTip inside ResetTargetBoard method look for: if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None replace with: if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None self.elementId = None if self.elementImageToolTip: self.elementImageToolTip.Hide() Look for: def SetElementImage(self, elementId): replace the whole method with: def SetElementImage(self, elementId): try: if elementId > 0 and elementId in ELEMENT_IMAGE_DIC.keys(): self.elementId = elementId self.elementImage = ui.ImageBox() self.elementImage.SAFE_SetStringEvent("MOUSE_OVER_IN", self.OnElementImageOverIn) self.elementImage.SAFE_SetStringEvent("MOUSE_OVER_OUT", self.OnElementImageOverOut) self.elementImage.SetPosition(self.GetLeft() - 40, self.GetTop()) self.elementImage.LoadImage( "d:/ymir work/ui/game/12zi/element/%s.sub" % (ELEMENT_IMAGE_DIC[elementId])) self.elementImage.Show() except: pass def OnElementImageOverIn(self): if not self.elementImageToolTip: self.elementImageToolTip = uiToolTip.ToolTip() self.elementImageToolTip.ClearToolTip() self.elementImageToolTip.AppendTextLine(ELEMENT_IMAGE_DIC[self.elementId] + " element") self.elementImageToolTip.SetToolTipPosition(self.GetLeft() - 40, self.GetTop() + 70) self.elementImageToolTip.Show() def OnElementImageOverOut(self): if self.elementImageToolTip: self.elementImageToolTip.Hide() That's it. Enjoy!
  3. use sys_err function server side(char.cpp) and print in python(game.py) to find bElement value. it should be between 1 and 6 for elemental mobs. if it's not in this range then you did something wrong. Also, make sure in mob_proto server side the mobs race is with ATT_ for example: ATT_ICE, ATT_FIRE, ATT_WIND etc etc
  4. Thanks, i'v updated my post. If you have the error below: 1028 16:37:29247 :: TypeError 1028 16:37:29247 :: : 1028 16:37:29247 :: SetHPTargetBoard() takes exactly 4 arguments (6 given) 1028 16:37:29247 :: open PythonNetworkPhaseGame and modify as above
  5. M2 Download Center Download Here ( Internal ) Hey there, I have an Halloween gift for you all. i have been working for a few hours on official like element image on target window(See screenshots below). When you click on a mob if it is defined as elemental, it will open an element image in addition to the target window. Don't forget to hit the like button! (C) Metin2 guild wars - coded by [GA]Ruin - 27/10/2017 (I create custom metin2 systems in c++/python. if you want a custom system send me a pm and we can talk over skype). Let's begin! Server Side: Open service.h, add in the end: #define ELEMENT_TARGET Open char.cpp, search for else { p.dwVID = 0; p.bHPPercent = 0; } add below: #ifdef ELEMENT_TARGET const int ELEMENT_BASE = 11; DWORD curElementBase = ELEMENT_BASE; DWORD raceFlag; if (m_pkChrTarget && m_pkChrTarget->IsMonster() && (raceFlag = m_pkChrTarget->GetMobTable().dwRaceFlag) >= RACE_FLAG_ATT_ELEC) { for (int i = RACE_FLAG_ATT_ELEC; i <= RACE_FLAG_ATT_DARK; i *= 2) { curElementBase++; int diff = raceFlag - i; if (abs(diff) <= 1024) break; } p.bElement = curElementBase - ELEMENT_BASE; } else { p.bElement = 0; } #endif open packet.h, search for: } TPacketGCTarget; add above: #ifdef ELEMENT_TARGET BYTE bElement; #endif Client side: open locale_inc.h, add in the end: #define ELEMENT_TARGET open packet.h, search for } TPacketGCTarget; add above: #ifdef ELEMENT_TARGET BYTE bElement; #endif open PythonNetworkPhaseGame.cpp, look for: else if (pInstPlayer->CanViewTargetHP(*pInstTarget)) replace below with the following: #ifdef ELEMENT_TARGET PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(iii)", TargetPacket.dwVID, TargetPacket.bHPPercent, TargetPacket.bElement)); #else PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(ii)", TargetPacket.dwVID, TargetPacket.bHPPercent)); #endif open PythonApplicationModule.cpp, look for #ifdef ENABLE_ENERGY_SYSTEM add above: #ifdef ELEMENT_TARGET PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 0); #endif open game.py, look for def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show() replace with: if app.ENABLE_VIEW_ELEMENT: def SetHPTargetBoard(self, vid, hpPercentage,bElement): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.SetElementImage(bElement) self.targetBoard.Show() else: def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show() open uitarget.py, look for import background add below: if app.ENABLE_VIEW_ELEMENT: ELEMENT_IMAGE_DIC = {1: "elect", 2: "fire", 3: "ice", 4: "wind", 5: "earth", 6 : "dark"} look for: self.isShowButton = False add below: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None inside Destroy method, look for: self.__Initialize() add below: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None inside ResetTargetBoard method, look for: self.hpGauge.Hide() add below: if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None look for : def SetElementImage(self,elementId): add above: if app.ENABLE_VIEW_ELEMENT: def SetElementImage(self,elementId): try: if elementId > 0 and elementId in ELEMENT_IMAGE_DIC.keys(): self.elementImage = ui.ImageBox() self.elementImage.SetParent(self.name) self.elementImage.SetPosition(-60,-12) self.elementImage.LoadImage("d:/ymir work/ui/game/12zi/element/%s.sub" % (ELEMENT_IMAGE_DIC[elementId])) self.elementImage.Show() except: pass Compile server, client source and root pack and that's it! Enjoy! Happy halloween!
  6. well, since iRet is just for debug, this will be better. BOOL CPythonChat::IsChatModeEnabled(DWORD dwID) { TChatSet * pChatSet = GetChatSetPtr(dwID); if (!pChatSet) return FALSE; for (BYTE i = 0; i < CHAT_TYPE_MAX_NUM; i++) { if (pChatSet->CheckMode(i)) return TRUE; } return FALSE; } isModeEnabled = chat.IsChatModeEnabled(self.chatID) if not isModeEnabled: self.btnAll.Down() self.ToggleAllChatMode() But anyway, it's not a big deal. everyone has its own style
  7. ison, modeflag = chat.GetChatMode(self.chatID) what is the modeflag variable used for? is it needed anywhere or you added it just for debugging your code? because i can't see it being used anywhere
  8. Every time you're using direct query it allocates new object of SQLMSg and it returns the pointer to this object. it'd be preffered to be handled by an auto_ptr so it would deallocate all of the containing dynamic objects inside of SQLMsg automatically when SQLMsg destructor is called. The reason they used a delete in this call is because they probably knew for certian they wouldn't use this pointer to the object anymore and it can potentially cause a memory leak. My advice is to always use an auto_ptr as it saves you the trouble to remember where and when to delete this pointer. *Incase you know for sure that you won't use the SQLMsg pointer object anymore(mostly for actions such as UPDATE / DELETE / INSERT) then you should add delete before the directquery as you mentioned above(Although, you are still in risk that the dynamically allocated objects inside SQLMsg will not be free'd). Hope i made it clear.
  9. Mate, So far i'm the one with 100+ rank/likes. i have contributed to this forum much more than you that's for sure. Surf around the C++ code release section and find for yourself how many useful guides i made. all of my stuff worked and working today 100%. I have never posted any leeched code/tool and i have no intention to do so. So take your lame ass some where else/keep your thoughts to yourself. Thanks. P.S Here's a proof for the efficient difference between my tool and the old italian tool. If you have a little bit of programming knowledge you'll easily realize which one is better. My code: Italian tool code:
  10. What a load of crap. there is a similar tool made long time ago(in Italian language) but i took nothing out of this tool code except a few layout design ideas. the italian tool is poorly coded with unefficient & un-maintainable code, without seperation of UI and Logic,No containers, and the list goes on and on. Here, i have made it fully english + coded the tool from scratch(in an efficient,maintainable way) + coded new features that no tool existing today has. and i have obfuscated it so leecher dumbass like yourself can't steal the code. You don't have to trust me but it's a fact that this tool has features that no other tool has today. And yes, the tool was built with wpf. P.S About 90% of these features do not exist in the old italian tool.
  11. M2 Download Center Download Here ( Internal ) 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. 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: [Hidden Content] Update 06/10/2017: Zoom in/out feature has been added. View entities seperately feature has been added. Import regen bug has been fixed. Enjoy! Version 1.1 Download Link: [Hidden Content] Virustotal: [Hidden Content] Enjoy!!
  12. Well, i didn't see someone published it before until now. and if you look at the implementations of his and mine, you could easily notice the difference. Anyway, it doesn't hurt
  13. This feature was created custom made by me. but a similar version may be included in other servers. and np It should work, you have an issue with your server files/src. I can help you and fix it(not for free), send me a pm.
  14. M2 Download Center Download Here ( Internal ) 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.
  15. If you want a seperate dungeon for each different player you should use d.join instead of pc.warp d.joim(mapindex) Or, recode d.new_jump_party to work also for single players.
  16. I'm working on a big project, looking for proffesional animator that has previous knowledge with 3dmax. Paying well. Send me a forum PM for more info.
  17. Hi, i'm searching Professional web developer. Paying well, for more info send me a forum PM and we will talk on skype.
  18. Look at the client/server source code. learn the classes/functions hierarchy. Add/Modify slowly the source and experience the changes in game. Learn the Client/Server packet structure and try adding your own packets to transmit data from client to server and vice versa. Take a look at some released systems from known people and study what they did. GL.
  19. Hey, Today i will make a small guide how to enable refinement scroll to be stackable. This will enable you to stack any refinement scroll such as blessing scroll, magic metal etc. Before we start diving into the source code, make sure to look into item_proto and check that there isn't any ANTI_STACK flag and the item is defined as ITEM_STACKABLE. Client side: Open uiinventory.py Search for: def __DropSrcItemToDestItemInInventory(self, srcItemVID, srcItemSlotPos, dstItemSlotPos): if srcItemSlotPos == dstItemSlotPos: return if item.IsRefineScroll(srcItemVID): Replace with: def __DropSrcItemToDestItemInInventory(self, srcItemVID, srcItemSlotPos, dstItemSlotPos): if srcItemSlotPos == dstItemSlotPos: return if item.IsRefineScroll(srcItemVID): if player.GetItemIndex(srcItemSlotPos) == player.GetItemIndex(dstItemSlotPos): self.__SendMoveItemPacket(srcItemSlotPos, dstItemSlotPos,0) else: self.RefineItem(srcItemSlotPos, dstItemSlotPos) self.wndItem.SetUseMode(FALSE) Search for: if item.IsRefineScroll(srcItemVNum): if player.REFINE_OK == player.CanRefine(srcItemVNum, dstSlotPos) Replace with: if item.IsRefineScroll(srcItemVNum): if player.REFINE_OK == player.CanRefine(srcItemVNum, dstSlotPos) or player.GetItemIndex(dstSlotPos) == srcItemVNum: That's all, Enjoy!
  20. Hey, I have made a small function that will enable you to use an unlimited amount of arguments in server source code. For example look at the function do_item in cmd_gm.cpp, it gets 2 arguments : arg1 and arg2. Using my function you will be able to have as many arguments easier and in more convenient way. That means you can have 5,7 or even 20 arguments. Let's begin: Open utils.cpp and look for #include "stdafx.h" add below the following: #include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of #include <boost/algorithm/string/split.hpp> look for const char *first_cmd add above: void split_argument(const char *argument, std::vector<std::string> & vecArgs) { std::string arg = argument; boost::split(vecArgs, arg, boost::is_any_of(" "), boost::token_compress_on); } open utils.h and look for const char * first_cmd add above: extern void split_argument(const char *argument, std::vector<std::string> & vecArgs); That's all. How to use? Let's look for example in ACMD(do_item) method: Instead of char arg1[256], arg2[256]; two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2)); you can replace with: std::vector<std::string> vecArgs; split_argument(argument,vecArgs); And now you can access any of the arguments starting from index of 1. so for example if you type ingame the command /item 6001 10 vecArgs[1] is 6001 vecArgs[2] is 10 if you need to convert it to number, you can use as example: int iCount = 0; str_to_number(iCount, vecArgs[2].c_str()); If you need any assistance, write here a reply and ill do my best in helping you. Enjoy
  21. Looking for working server/client side protection against hacks such m2 bob or similar hacks. Paying via paypal/pay safe card. Send me a pm with your skype info.
×
×
  • 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.