Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/28/20 in all areas

  1. Did I ever said it will be legal to host a private server using this? No, I'm not a lawyer But I know that writing server emulators is legal, and making them available to the public too. The main goal of this project was and still is for me to learn more about how to write a stable and more or less solid game server, with the limitations we have. Like not being able to replace the network protocol. So I could also kept this project for me, but I wanted to make it available to all, so everybody can profit from it. No matter how.
    6 points
  2. M2 Download Center Download Here ( Internal ) Hi. This small release save our sent and received private messages till we change the character. If you close by mistake PM with somebody and after you'll open the converastion with that player the old messages will be loaded from dictionary. All changes are in root. Let's begin. constInfo.py Add: WHISPER_MESSAGES = {} game.py Replace these methods: def OnRecvWhisper(self, mode, name, line): if mode == chat.WHISPER_TYPE_GM: self.interface.RegisterGameMasterName(name) line.replace(" : ", ": ") if not self.interface.FindWhisperButton(name) and constInfo.WHISPER_MESSAGES.has_key(name) and not self.interface.whisperDialogDict.has_key(name): self.interface.RecvWhisper(mode, name, line, True) else: self.interface.RecvWhisper(mode, name, line, False) if not constInfo.WHISPER_MESSAGES.has_key(name): constInfo.WHISPER_MESSAGES.update({name : [(mode, line)]}) else: constInfo.WHISPER_MESSAGES[name].append((mode, line)) chat.AppendWhisper(mode, name, line) def OnRecvWhisperSystemMessage(self, mode, name, line): chat.AppendWhisper(chat.WHISPER_TYPE_SYSTEM, name, line) self.interface.RecvWhisper(mode, name, line, False) def OnRecvWhisperError(self, mode, name, line): if localeInfo.WHISPER_ERROR.has_key(mode): chat.AppendWhisper(chat.WHISPER_TYPE_SYSTEM, name, localeInfo.WHISPER_ERROR[mode](name)) else: chat.AppendWhisper(chat.WHISPER_TYPE_SYSTEM, name, "Whisper Unknown Error(mode=%d, name=%s)" % (mode, name)) self.interface.RecvWhisper(mode, name, line, False) interfaceModule.py Replace this method: def RecvWhisper(self, mode, name, line, loadMsg): if loadMsg: for text in constInfo.WHISPER_MESSAGES[name]: chat.AppendWhisper(text[0], name, text[1]) if not self.whisperDialogDict.has_key(name): btn = self.FindWhisperButton(name) if 0 == btn: btn = self.__MakeWhisperButton(name) btn.Flash() chat.AppendChat(chat.CHAT_TYPE_NOTICE, localeInfo.RECEIVE_MESSAGE % (name)) else: btn.Flash() elif self.IsGameMasterName(name): dlg = self.whisperDialogDict[name] dlg.SetGameMasterLook() introSelect.py In def Open(self): add: WHISPER_MESSAGES = {} uiWhisper.py Add: import constInfo Replace this method: def OpenWithTarget(self, targetName="", loadMessages=False): chat.CreateWhisper(targetName) chat.SetWhisperBoxSize(targetName, self.GetWidth() - 60, self.GetHeight() - 90) self.chatLine.SetFocus() self.titleName.SetText(targetName) self.targetName = targetName self.textRenderer.SetTargetName(targetName) self.titleNameEdit.Hide() self.ignoreButton.Hide() if app.IsDevStage(): self.reportViolentWhisperButton.Show() else: self.reportViolentWhisperButton.Hide() self.acceptButton.Hide() self.gamemasterMark.Hide() self.minimizeButton.Show() if loadMessages: if constInfo.WHISPER_MESSAGES.has_key(targetName): for text in constInfo.WHISPER_MESSAGES[targetName]: chat.AppendWhisper(text[0], targetName, text[1]) in def AcceptTarget(self): at botton add: if constInfo.WHISPER_MESSAGES.has_key(name): for text in constInfo.WHISPER_MESSAGES[name]: chat.AppendWhisper(text[0], name, text[1]) And replace this method: def SendWhisper(self): text = self.chatLine.GetText() textLength = len(text) if textLength > 0: if net.IsInsultIn(text): chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.CHAT_INSULT_STRING) return net.SendWhisperPacket(self.targetName, text) self.chatLine.SetText("") if not constInfo.WHISPER_MESSAGES.has_key(self.targetName): constInfo.WHISPER_MESSAGES.update({self.targetName : [(1, ("{}: {}".format(player.GetName(), text)))]}) else: constInfo.WHISPER_MESSAGES[self.targetName].append([1, "{}: {}".format(player.GetName(), text)]) chat.AppendWhisper(chat.WHISPER_TYPE_CHAT, self.targetName, player.GetName() + ": " + text) That's all If you will find any bugs just give me some feedback.
    3 points
  3. Welcome to QuantumCore, most people always told you me you are crazy, that's a waste of time don't do that. But I don't care and still started this project, mostly as a learning process. So what is QuantumCore you ask? QuantumCore is basically a server emulator for Metin2. In comparison to what we currently mostly use this doesn't use any source code by Ymir/Webzen and is a full reimplementation of the 40k server. This project is still in work and far from being completed. So why do you already create a thread for this? First of all we need feedback from you guys of what the features are and what we could improve even more. In addition to a normal rewrite of the core this project is using more modern technology. The code base is based on C++17 and will include features of C++20 as soon as it's officially released. Also we only test 64bit builds, no more 32bit builds. In addition to this we are automated building the core against the current LLVM toolchain and automatically creating Docker images. We have started to implement Unit Testing for some core features, and we will extend this to more code we write. Also we are working on embedding AngelScript (and maybe even more languages in the future) to not only write quests but also to extend the core. The main goal is that you can create most of the new systems in AngelScript with a resonable performance instead of modifying the core source code. For example if you want to create a new command you could write the following plugin: void main() { command::RegisterCommand("test", TestCommand); } void TestCommand(game::Player@ player, string[] arguments) { if(arguments.length() < 2) { player.SendChatMessage(1, "/test [name]"); return; } player.SendChatMessage(1, "Hello from " + player.name + "(" + player.level + ") to " + arguments[1]); } We also using redis for caching fast changing fields, like player position, items etc. The source code of this project will be licensed under the GPLv3 license. So you are free to modify the source code and use it for your project. We would be also very happy if you contribute back your improvements to the core. So what is the main goal? - Providing a compatible game server to the clean 40k client - Writing a modern, stable and scalable game server - Keep the core extensible Main repository: https://gitlab.com/quantum-core/core Documentation: https://docs.quantum-core.io/index.html With best regards, QuantumCore Team @arves100, @DevChuckNorris
    3 points
  4. M2 Download Center Download Here ( Internal ) Videos Download
    3 points
  5. M2 Download Center Download Here ( Internal ) Hi everyone! So, after serveral days of searching a tool that could change the texture path of a .gr2 file, I found the tool(probably all of you know it, the texture changer by marv). After that I tried to change the texture paths of some gr2 models of a weapon, and guess what, it didn't work. I'm gonna reupload the file, because I didn't seen it on metin2dev, and I'm gonna teach you how to use it. First of all, I don't know about others, but for me it didn't work to change anything with this (I'm running windows 7 x64 bit). Some of guys told me that this "texture changer" works only on windows 7 x86 bit, so I reinstalled my windows(I really needed that tool), of course, it didn't work either way. So, go in Start and search cmd, and run it. After the cmd started you'll see a path right there C:\Users\Name (Instead of Name you'll have your username of computer administrator, or the account you're logged in), now that's the path where we can work with the tool. PAY ATTENTION!!! IF YOU START THE TOOL IN OTHER FOLDER INSTEAD OF C:\Users\Name THE TOOL WILL NOT WORK, AND YOU WILL NOT BE ABLE TO SAVE THE NEW MODEL. Exctract all the files from the archive(I'll post it below), and start Metin2TextureChanger.exe. Now click "Load" to choose a gr2 file you want to change texture path, BUT, the model name can't have spaces in name(devil sword.gr2 for example, it's wrong, the tool won't read it, and you'll not be able to save your new gr2 model), so if you want to change for example devil sword.gr2 you need to rename it into devil_sword.gr2 or devilsword.gr2 or any other name without spaces betwen. Where is "Neuer Texturpfad" we will chose the new path for texture, for example d:\ymir work\test\devil_sword_blue.dds , there you can choose any other path, but you can't modify "d:\ymir work" or you won't be able to see the weapon/armour in-game. Now we save the file wherever we want, it doesn't matter, this way must work for everybody. AGAIN, THIS TOOL WASN'T MADE BY ME. And I made this post because I've searched many days a tool that would work, but neither didn't work, and this tool didn't work for me either just when I used this method. So, this post is for guys who had the same problem like me (they had the tool, but couldn't save the new model) that's why I wanted to help them, and any other people who weren't been able to use it. And about the other tool I've found on this forum, the tool "made" by thunder-core, I didn't find that tool satisfying, it worked, but after the new model was made, I wasn't been able to import it in 3d max, or to convert the model from file format revision 7 to 6. So you were basicaly forced to upgrade your client to granny 2.9, and I found that inconvenient, because, I don't know about others, but I don't use source for binary, and because of that it's imposible to see the model in-game. And of course, the new model you've created, with the tool in attachement, is revision 7, so you need the new granny if you want to see it in-game, but you can use the converter from archive to convert from revision 7, to revision 6 (old), and you'll be able to see it in-game. If you already see it in-game, you don't need to use the converter. If you found this post helpful I'm glad I could help you.
    2 points
  6. Here's the .mse files for each version. Make sure to use the .tga files of ymirred, not .jpg ones because you'll get that white background if you're using .jpg. gm2004.mse gm2008.mse
    2 points
  7. M2 Download Center Download Here ( Internal ) Download Here ( Latest Version ) This WE is a version compiled directly by me which includes infinite fixes and features. It's certain that you won't longer use the worldeditor_en! To make it simple, I wrote all the details about this feature and the common WE inside the relative config file: (called WorldEditorRemix.ini) ; Info: ; -) 100% translated ; -) granny2.11 ; -) F6 as Insert alternative ; -) many default features not present inside the worldeditor_en (probably, that binary was taken out from an SVN long time ago and resource hacked) such as Ins for all regions and skyboxes ; -) WASD UPLEFTDOWNRIGHT to move around (+asynchronous diagonally movements) ; -) UP-LEFT-DOWN-RIGHT to move around*10 (+asynchronous diagonally movements) ; -) config file for few things ; Output options by default ; few others such as default WASD movement ; whether or not Insert should let you go where you were before the press ; no MAI dump when saving atlas ; whether or not DevIL should compress and remove alpha from minimap.dds ; whether or not loading .mdatr building heights ; default textureset when creating maps ; overlapped tabs ; other stuff ; -) several bugfixes ; default title app name ; attempting to write to an empty textureset name when creating new maps ; ViewRadius doubled every load&save ; shadowmap.dds creation ; assert when saving atlas ; crash when adjusting height ; many buffer under/overflows ; *.mdc collision data saving (for game_test) ; not checking output options when loading maps ; water brush waterid bug (the id was increased until 256 each time the function was called; now it's based on the water height just like it should be) ; init texture map reload map crash and last 2px always blank ; square shape even for up/down height brushes ; add textureset texture button (+multiselection) ; remove textureset texture feature (just selecting a texture from the list and pressing DELETE) ; creation of empty textureset with index -1 (changed to 0) ; change baseposition button ; misspelled stuff ; skybox bottom image (nb: you also need a fixed launcher for this) ; removed boring CTRL requirement (to move the camera) when editing daylight/attr ; fixed refresh texture imagebox onKey pressing the down/up keys (like when onClicking them) ; fixed TextureSet file creation if not existing ; fixed new wolfman motion event handling ; fixed crash when editing animation attack bones and 00010.gr2 was missing ; fixed locale/ymir/mob_proto load (it autodetects the most common structures) and <map>/regen.txt load/save ; fixed ./group.txt load ; fixed load/save/edit <map>/regen.txt (very nice for "m" regens, untested for "g") ; load from PACK is available if pack/property is present! Be sure pack/Index exists! ; fixed multi-object selection crash ; fixed crash when previewing a missing texture ; fixed not clearing of old environment (e.g. skybox) when switching maps ; fixed not creating property folders in root tree (object tab) ; fixed object attachment in Model Tab ; fixed newly particles names in Effect Tab ; fixed crash when saving a .mse script with no mesh model ; fixed crash when inserting a lower gradient ; -) created new TextureSet field when creating new maps ; -) created new Change/Delete Texture buttons when double-clicking a texture ; -) created Background Music playback and Shadow Recalculate buttons ; -) created water height "set 0z", "+1z", "-1z" buttons ; -) server_attr generator ; -) every crash will generate a logs/WorldEditorRemix_{target}_{date}.dmp file useful for debugging ; -) implemented a "water path" mapsettings option (the launcher requires additional code) ; -) implemented a "wind strength" msenv option (the launcher requires additional code) ; -) the "encrypt data" feature does nothing (unimplemented) ; Note: ; 0) there are no regressions in this version! a bug here means it'd also be present in older WE versions too! ; 1) the shadow output option is tricky: when UpdateUI is called, shadows are hidden although the check is pressed (i implemented the shadow recalculate function for that) #fixed since v11 ; 2) the bgm player requires /miles and the fadein/out doesn't work until you load the map ; 3) the adjusting height button works only if mdatr height is detected ; 4) the Debug version is laggy when working on maps such as n_flame_dungeon and n_ice_dungeon (by default, because SphereRadius are intensively checked in SphereLib\spherepack.h) ; 5) if you load a map, the script panels (where you load .msa et similia) will have the camera perspective a little fucked up (0z instead of -32767z or 0x 0y -163,94z) ; 6) few tree objects are not movable and/or highlightable after placed on the ground and their selection is invisible (you can still delete 'em) ; trick: draw a square selecting a normal building and 'em, then move the building and you'll see all of 'em will be moved! ; 7) the server_attr generator will clean all the unused flags! attr[idx]&=~0xFFFFFFF8; ; 8) you can read files from pack/Index 'n stuff but be aware that Property will not be considered! #fixed since v15 ; 9) the MonsterAreaInfo features are laggy and buggy as fuck ; 10) even though you can select many textures at once (using ctrl+click on textureset list; for brushing or initializing a base texture), you can't delete more than one at the same time ; 11) the .mdatr height is tricky; if you move a building, the height will not be refreshed until you put a new building or whatever you want to trigger the update event ; 12) by default, the worldeditor tries to render only the first 8 terrain textures of a 32x32px region (nb: a 1x1 map is a 256x256 px region) ; 13) the minimap rendering cannot catch the buildings/trees inside the first 2x2 regions due a ymir cache fault and you need to set the camera to "see" them ; 14) when the textureset, environment, etc load fails, the old filename still remains loaded ; 15) the attr flag "3" (three) has no implementation, so don't use it! ; 16) load from PACK doesn't load texturesets from files for first (if they are already in pack/), and the object placer's object list will remain empty because it takes the list from property/ (and not from pack/property) ; 17) to save the regen.txt you press CTRL+S ; 18) if you enable the wireframe (f4) when on Attr Tab, you see the terrain all white ; 19) the water brush disappears when the camera renders the waterwheel small/big effect ; 20) the monster area info goes under ground if you're outside the relative sectree ; 21) the full skybox may be displayed only after the top picture has been added (if the other textures have already been inserted) ; 22) the slider in the Attr Tab is something like "16 photoshop layers" in which you can split your attrs; not so helpful and quite confusing sometimes ; 23) the fixed model - object attachment attaches static objects (hairs'skeleton will not mirror the playing animation) ; 24) in environment tab, if you insert lower gradients, you may end up with an out of range crash #fixed since v30 ; 25) brushes working out-of-screen/map-range may affect random terrain places ; TODO: ; A) look at more than 8 textures for region -> DONE ; B) create a shortcut to fix the #5 note -> DONE ; C) disable the radius <= GetRadius()+0.0001f check to fix the #4 note -> REJECTED ; the worldeditor_en calls this assert and, if ignored, the lag ceases to exist (this will not occur in source version) ; at least, if the release version is not a problem for you, use that in those few cases when .mse are abused and try to kill the debug one ; D) translation in more languages other than english -> REJECTED ; english should be enough! ; E) alternative path for d: -> REJECTED ; you can mount d as a subpath of c like this: ; subst d: "c:\mt2stuff" ; F) need to fix note #19 #25 -> TODO [shortcuts] ; ### SHORTCUTS ; # ESC(ape) Clean cursor ; # Canc(el|Delete) Delete stuff such as selected buildings ; # Ctrl+S Save map ; # Ins(ert) or F6 Save shadowmap|minimap.dds ; # F3 BoundGrid Show/Hide ; # F4 Render UI Show/Hide ; # F11 WireFrame Show/Hide ; # R Reload Texture ; # Z and X Decrease/Increase Texture Splat by 0.1 ; # CapsLock Show GaussianCubic effect if shadows are displayed ; # L-Shift+1-6 Show TextureCountThreshold flags (&2-7) as colors on the ground ; # L-Shift+8 Set Max Showable texture to 8 (de-fix note 12) ; # L-Shift+0 Set Max Showable texture to 255 (fix note 12) ; # H Refresh MDATR Heights (useful when you move an object) (fix note 11) ; # Y Set Perspective as default (fix note 5) ; # T Set the Camera to catch all the object on the screen (w/a note 13) then you'll be ready to press Insert/F6 ; # DO NOT HAVE AN OBJECT SELECTED WHEN USING THOSE SHORTCUTS (MW1-7) ; # MouseWheel+1 move cursor x rotation ; # MouseWheel+2 move cursor y rotation ; # MouseWheel+3 move cursor z rotation ; # MouseWheel+4 move cursor height base (1x) ; # MouseWheel+5 move cursor height base (0.5x) ; # MouseWheel+6 move cursor height base (0.05x) ; # MouseWheel+7 move cursor ambience scale (1x) ; # MouseWheel+Q move selected object height base (1x) ; # MouseWheel+9 move selected object x position (1x) (+asyncronous) ; # MouseWheel+0 move selected object y position (1x) (+asyncronous) ; # MW+RSHIFT+9|0 as above but *10x (+asyncronous) ; # MW+RCONTROL+9|0 as above but *100x (+asyncronous) ; # MouseLeft Insert Objects ; # MouseRight Move camera (it could require CTRL too) ; # SPACE Start move/selected animation in Object/Effect/Fly CB ; # ESC Stop animation in Effect/Fly CB [config] ; ### CONFIG OPTIONS VIEW_CHAR_OUTPUT_BY_DEFAULT = 1 VIEW_SHADOW_OUTPUT_BY_DEFAULT = 1 VIEW_WATER_OUTPUT_BY_DEFAULT = 1 ; WINDOW_HEIGHT_SIZE = 1080 ; WINDOW_WIDTH_SIZE = 1920 WINDOW_FOV_SIZE = 45 ; #100 = 1px (minimal px movement when pressing WASD) WASD_MINIMAL_MOVE = 100 ; came back from where you were before pressing Insert/F6 NO_GOTO_AFTER_INSERT = 1 ; disable MAI dumps when saving atlas and/or pressing Insert/F6 NOMAI_ATLAS_DUMP = 1 ; disable minimap.dds alpha saving and enable compression NOMINIMAP_RAWALPHA = 1 ; enable .mdatr height collision loading when moving on buildings or adjusting terrain DETECT_MDATR_HEIGHT = 1 ; disable fog when loading maps NOFOG_ONMAPLOAD = 1 ; refresh all checkbox configurations when loading maps 'n stuff REFRESHALL_ONUPDATEUI = 0 ; set a default mapname prefix when creating new maps ("" to disable) NEW_MAP_MAPNAME_PREFIX = "metin2_map_" ; display a default textureset when creating new maps ("" to disable) ; note: it loads the filepath if exists, otherwise it will create an empty textureset file NEWMAP_TEXTURESETLOADPATH = "textureset\metin2_a1.txt" ; create a default textureset as "textureset/{mapname}.txt" ; note: this option is not considered if NEWMAP_TEXTURESETLOADPATH is not empty. [before v24] ; note: this option is not considered if the TextureSet path input is not empty when creating a new map [since v24] NEWMAP_TEXTURESETSAVEASMAPNAME = 1 ; remove the weird attr flags from the generated server_attr SERVERATTR_REMOVE_WEIRD_FLAGS = 1 ; show diffuse lighting to object VIEW_OBJECT_LIGHTING = 1 ; path of mob_proto used for regen MOB_PROTO_PATH = "locale/ymir/mob_proto" ; select monster area info checkbox at startup VIEW_MONSTER_AREA_INFO = 0 ; brush cursor / object selection color RGB float between 0.0 to 1.0 (default: green -> 0 1 0) RENDER_CURSOR_COLOR_R = 0.0 RENDER_CURSOR_COLOR_G = 1.0 RENDER_CURSOR_COLOR_B = 0.0 Download: [Hidden Content] How To Map: This release will not cover this part. Look at CryPrime`s tutorials to understand how to do it. About the ServerAttr Generator: (since v14) This is a beta function but it should work fine. I tested it on gm_guild_build (1x1), metin2_map_a1 (4x5), metin2_map_trent (2x2), metin2_n_snowm_01 (6x6) and the result was the same as the blackyuko map editor. (I use a different lzo version and I clean deprecated and useless flags, so the size is different from this last one but the "final image" will be the same; using game_test to fix his server_attr will let mine and his perfectly equal byte per byte) I also give you the source code of my server_attr generator function. CLICK A server_attr file is based on all the attr.atr files merged into a one raw RGBA image and each one scaled from 256x256 to 512x512. After that, the image will be splitted into sectors of 128x128 px and each one compressed using lzo compression. The server_attr header is composed by the size of the map*4. (e.g. a 4x4 will have a 16x16 size with 256 sectors inside) (gj ymir CLICK) An uncompressed server_attr sector is just like this: CLICK (the sub 4 byte header is the size returned by the LzoCompress which indicates how much the compressed sector data are large) Each attr.atr is just like this: CLICK (the header is composed of 6 byte in total: 3 WORDs respectively for version, width and height; they are always 2634, 1, 1 so don't bother about it) A single attr.atr scaled from 256x256 to 512x512 will be just like this: CLICK You can use the game_test (from source) to perform few tasks like: Create a server_attr from a .mcd file (I won't suggest it) a <collision data filename> <map directory> Regenerate an old server_attr to server_attr.new using the current lzo compression and cleaning useless flag CLICK c <filename> Other stuff such as b to create a character instance or q to quit About the SkyBox Bottom pic fix: (since v21) Both metin2launch.exe and worldeditor.exe should be edited to see the bottom pic of the skybox. Ymir messed up the code wrongly flipping the bottom image. Open ./Srcs/Client/EterLib/SkyBox.cpp and replace: ////// Face 5: BOTTOM v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f); v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f); v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f); with: ////// Face 5: BOTTOM v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, -1.0f); v3QuadPoints[1] = D3DXVECTOR3(1.0f, -1.0f, -1.0f); v3QuadPoints[2] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f); v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); then recompile. Credits:
    1 point
  8. M2 Download Center Download Here ( Internal ) Download
    1 point
  9. M2 Download Center Download Here ( Internal )
    1 point
  10. M2 Download Center Download Here ( Internal ) 3dsMax 2011 + Activator: Here Plugins GR2 for 3dsmax 2011: Here
    1 point
  11. When you are changing attributes in your item for every-single attribute server sends update packet to client, which is up to 4 unnecessary packets per one change. You must agree this is pointless. If you use bonus switcher and, let's say, with 500ms delay for 7 items it is 5 * 7 * 2 update packets per second. Going lower with delay you will get absurd amount of those packets. Another issue is you are not able to read attributes, I mean, avarage human cannot. After digging in code I got rid of redundant packets and received smoother in-game experience This how it looks for 150ms switch delay: gif With my fix: gif Download: link
    1 point
  12. 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!
    1 point
  13. Hi there devs, Its been a while since my last release and probably this will not change, but I had this guide in my head for like a year now. In my last ~2 years while I was working in the AE team various devs came and go, and this kind of guideline would have been a huge help and could prevent lots of errors. I have been in the dev scene for more than 10 years now and (as some of you may already noticed) one of my main interest has always been making more and more user friendly and complex UI objects/interfaces and along the road gathered tons of experience. You won't end up with another shiny system that you can use in your server this time by reading this article, but instead maybe I can prevent you from making windows that stays in the memory forever, opens infinite times, prevents other window's destruction, and many more. Who knows, maybe you will leave with some brand new never ever seen tricks that you can use in your future UIs. But first of all lets talk about some good2know stuff. UI layers Layers are root "windows", their purpose to hold all kind of interface windows while managing the z order of the windows (z order = depth level of the windows, which one is "above" the other). By default there are 5 layers (from bottom to top): "GAME": this is only used for the game window (game.py), and when you click on it the game will translate the click position to the map "UI_BOTTOM": this is used for shop titles "UI": this is the default layer, we would like to put most of our windows into this layer, like inventory, character window, messenger, pms, etc, so they can overlap each other "TOP_MOST": every window, that should always be in front of the player, so other windows would not overlap them from the lower layers, so for example the taskbar is placed in this layer "CURTAIN": this is for the curtain window, which is actually a black as a pit window, that is used to smooth the change from different introXX windows (like between login and charselect) This is the outest layer and goes before the other 4. So when the render happens, the 1st layer and its childs will be rendered first, then the 2nd layer, then the 3rd, etc, so by this we will get our comfy usual client layout. In the other hand, when we click, everything goes in reverse order, first the client will try to "pick" from the curtain layer's child windows (also in reverse order), then the top_most layer, etc. Ofc there is no layers beyond the game layer, so usually the "pick" will succeed there, and we will end up clicking on the map. UI windows Now lets talk a little bit about the parts of an UI window. It has a python object part and a c++ object part. When you create a basic Window (from the ui.py) basically 2 things happen: a python Window object is created first, then through the wndMgr.Register call a c++ CWindow object is created. These 2 objects are linked, in python the handle for the CWindow is saved in the self.hWnd variable, while in the CWindow the python object handle would be stored in the m_poHandler. What are these handles for? If you want to call a method on a window from python, you have to specify which window you want to perform that action on. Remember, the python part is just a "frontend" for the UI, the actual magic happens in the cpp part. Without python, its possible to create windows, but without the cpp part there is no windows at all. On the cpp part, we need the python object handle to perform callbacks, like notifying the python class when we press a key, or pressing our left mouse button. By default the newly created window will take a seat in one of the layers (if provided through the register method, otherwise it goes to the UI layer). In a healthy client we only put useful windows directly into a layer. For example you want to put your brand new won exchange window into the UI layer, but you don't want to put all parts of a window into the UI layer (for example putting the base window into the root layer then putting the buttons on it to the root layer too, then somehow using global coordinates to make it work). Instead, you want to "group" your objects, using the SetParent function. You may say that "yeah yeah who doesn't know this?", but do you know what actually happens in the background? The current window will be removed from its current parent's child list (which is almost never null, cus when you create it its in the UI layer, so the parent is the UI layer) and will be put into the end of the new parent window's child list. Why is it important, that it will be put into the end? Because it will determine the Z order of the childs of the window. For example if I create 2 ImageBox with the same size of image on the same position and then I set ImageBox1's parent before ImageBox2's parent, then I will only see ImageBox2, because that will be rendered after ImageBox1, because its position in the childList is lower than ImageBox2's. For normal window elements (like buttons) its very important, because after you set the parent of a window, you can't alter the z order (or rather the position in the childList) unless you use the SetParent again. No, you can't use SetTop, because its only for windows with "float" flags on it, which you only want to use on the base of your window (the root window that you put your stuff on it and use it as parent for most of the time). Window picking "Picking" is performed when we move the cursor. This is an important method, because this will determine the result of various events, for example the OnMouseOverIn, OnMouseOverOut, OnMouseRightButtonDown, etc. To fully understand it, you must keep in mind that every window is a square. Do you have a perfect circle image for a button? No you don't, its a square. Do you have the most abstract future window board design with full star wars going on the background? No, you DON'T. ITS A SQUARE. By default, a window is picked if: the mouse is over the window AND the window is visible (Shown) AND the window doesn't have "not_pick" flag set AND the window is "inside its parent's square" on the current mouse position, which means if the parent's position is 0,0 and it has a size of 10x10 and the window's position is 11, 0, the window is outside of its parent's square. This is really important to understand, lots of UI has fully bugged part because of ignoring this fact. I think every one of you already experienced it on some bad illumina design implementation, when you click on a picture, and your character will start to run around like a madman, because the game says that A-a-aaaaa! There is NO WINDOW ON THAT POSITION It is useful to use the not_pick flag whenever you can, for example on pure design elements, like lines and flowers and ofc the spaceships on the background. Lets say you have a size of 10x10 image that has a tooltip, and you have a window on it that has a size of 5x5. When the mouse is over the image, the tooltip will be shown, but if its over the 5x5 window, the tooltip won't appear, unless you set it to the 5x5 window too. But if you use the not_pick flag on the 5x5 window, the 5x5 window won't be picked and the tooltip would be shown even if the mouse is over the 5x5 window. Window deletion, reference counting, garbage collector, proxying The window deletion procedure starts on the python side, first the destructor of the python object will be called, then it will call the wndMgr.Destroy that deletes the c++ object. By default, we have to store our python object, or this time our python window, to make sour it doesn't vanish. Usually we do this via the interface module, like "self.wndRandomThing = myModule.RandomWindow()". But what is this? What is in the background? Python objects has reference count. Let me present it with the following example: a = ui.Window() # a new python object is created, and its reference count is 1 b = a # no new python object is created, but now b is refering to the same object as 'a', so that object has a refence count of 2 del b # b is no longer exists, so its no longer referencing to the newly created window object, so its reference count will be 1 del a # the newly created window object's reference count now 0, so it will be deleted, calling the __del__ method To be more accurate, del-ing something doesn't mean that it will be deleted immediately. If the reference count hits 0 the garbage collector (btw there is garbage collector in python if you didn't know) will delete it, and that moment the __del__ will be called. It sounds very handy isn't it? Yeeeeah its easyyyy the coder don't have to manage object deletion its sooo simple.... Yeah... But lets do the following: class stuff(object): def __del__(self): print "del" def doStuff(self): self.something = self.__del__ # here we could just simply do self.something = self too, doesnt matter a = stuff() a.doStuff() # and now you just cut your leg del a #you are expecting the "del" print, but that will never happen You may say " ? oh please who tf does something stupid like this? It SO OBVIOUS that its wrong whaaaaaaat????" But in reality, I could count on only one of my hand how many devs don't make this mistake. Even my codes from the past decade are bad according to this aspect, since I only realized this problem about a year ago, when I was working on the AE wiki. Even the yimir codes contain tons of this kind of errors, however there was definitely a smart man, who implemented the __mem_func__. Okay, I see that you still don't understand how is this possible to make this kind of mistake, so let me show you a real example: class myBoard(ui.Board): def __init__(self): super(myBoard, self).__init__() self.makeItRain() def __del__(self): super(myBoard, self).__del__() print "I want to break free. I want to breeaaaaaak freeeeeeeeeeee" def doNothing(self): pass def makeItRain(self): self.btn = ui.Button() self.btn.SetParent(self) self.btn.SetEvent(self.doNothing) #boom a = myBoard() del a # but where is the print? Thats not that obvious now right? What happens here? We create a myBoard object, which in the __init__ calls to the makeItRain func, which stores an ui.Button object, and sets the button to call for the myBoard class's doNothing function with the self object pointer in the OnLeftMouseButtonDown function, which means that the reference count will never be zero, because the btn referenced in the myBoard but myBoard is referenced in the btn but the btn is referenced in the.... so you know, its a spiral of death, that our best friend garbage collector can't resolve. Okay, but how to do it correctly? Lets talk about proxying. In python, proxies are weak references, which means that they don't increase reference count of an object, which is exactly what we need. #let me show this time the console output too class stuff(object): def __del__(self): print "del" >>> from weakref import proxy >>> a = stuff() #newly created object >>> b = proxy(a) #create weak reference to the new object (note that the weak reference object is also an object that stores the weak reference) >>> b #what is b? <weakproxy at 02DB0F60 to stuff at 02DBFB50> # b is a weakproxy object that refers to a which is a "stuff object" >>> del b # what if we delete b? # no "del" message, the stuff object is not deleted, because its reference count is still 1, because its stored in a >>> b = proxy(a) # lets recreate b >>> del a # now we delete the only one reference of the stuff object del # and here we go, we got the del message from __del__ >>> b # okay but whats up with b? <weakproxy at 02DB0F60 to NoneType at 7C2DFB7C> # because b is a weakproxy object, it won't be deleted out of nowhere, but it refers to a NoneType right now, because the stuff object is deleted (also note here that NoneType is also a python object :D) >>> if b: #what if I want to use b? ... print "a" ... Traceback (most recent call last): File "<stdin>", line 1, in <module> ReferenceError: weakly-referenced object no longer exists # in normal cases no need to trycatch this exception, because if we do everything right, we will never run into a deleted weakly-referenced object But how do we proxy something like self.doNothing? Actually, what is self.doNothing? self.doNothing has 3 parts: The first part is not that obvious, it has a base class pointer, which is points to myBoard. It has a class object pointer, that is basically "self". It refers to the current instance of myBoard. It has a function object pointer, called doNothing, which is located inside the myBoard class. And now we can understand ymir's ui.__mem_func__ class, which is exactly meant to be used for proxying class member functions: # allow me to reverse the order of the definitions inside the __mem_func__ so it will be more understandable class __mem_func__: def __init__(self, mfunc): #this happens when we write ui.__mem_func__(self.doSomething) if mfunc.im_func.func_code.co_argcount>1: # if the doSomething takes more than one argument (which is not the case right now, because it only needs the class obj pointer (which is the 'self' in the 'self.doSomething')) self.call=__mem_func__.__arg_call__(mfunc.im_class, mfunc.im_self, mfunc.im_func) #lets unfold the python object to the mentioned 3 parts else: self.call=__mem_func__.__noarg_call__(mfunc.im_class, mfunc.im_self, mfunc.im_func) #this will be called for the 'self.doSomething' def __call__(self, *arg): # this line runs whenever we call apply(storedfunc, args) or storedfunc() return self.call(*arg) class __noarg_call__: # this class is used whever the python object we want to proxy only takes one argument def __init__(self, cls, obj, func): self.cls=cls # this one I don't really get, we won't need the class object later also its not proxied, so its probably here to prevent delete the base class in rare cases self.obj=proxy(obj) # here we proxy the object pointer which is what really matters self.func=proxy(func) # and then we proxy the class func pointer def __call__(self, *arg): return self.func(self.obj) # here we just simply call the class function with the object pointer class __arg_call__: def __init__(self, cls, obj, func): self.cls=cls self.obj=proxy(obj) self.func=proxy(func) def __call__(self, *arg): return self.func(self.obj, *arg) # here we just simply call the class function with the object pointer and additional arguments Pros, cons, when to, when not to, why? Now you may ask that "Okay okay that sounds good, but why? What can this cause, how big the impact could be, is it worth to even bother with it?" First of all, you must understand that this is kinda equal to a memory leak. I would actually call these non-deleted windows as "leaking windows". Every time you warp, new and new instances will be generated from those objects, and ofc, one instance of a window means like about +50/100 instances, depending on the window complexity, how much childs it has. Usually these windows are at least remain in a Hide state, and hidden windows don't affect update and render time, but they will remain in the root layer, and may stack up depending on how much time the player warp. Still, the number of leaking root windows / warp is around 50-100, which is really not much for a linked list (the type of the childList). However, the memory consumption is much greater. One year ago AE had 10k leaking windows growth / warp. One base class (CWindow)'s size is 140 bytes, which means the memory growth is at least 1,3MB/warp and it does not contain the size of the python objects size for those windows, the linked_list headers and other necessary stuffs. After some hour of playing this can easily reach 100+MB of leaking memory. On worse cases the old windows are not even hidden, and on rewarp players may see multiple instances of the mentioned windows, like double inventory, double messenger window, etc. In this cases those windows can affect the render and update times too. Pros: your code will now work correctly regarding to this topic you may gain some performance boost you may find stuff in your client that even you don't know about you may find enough kebab for a whole week you can save kittens by removing leaking windows and proxying objects you can build my respect towards you and your code and you can even calculate the actual number using the following formula: totalRespect = proxysUsed * 2 + ui.__mem_func__sUsed - proxysMisused * 3.511769 - ui.__mem_func__sMisused * pi - 666 * ui.__mem_func__sNotUsed Cons: depending on how bad the situation is and how skilled you are, the time needed to find and fix everything could be vary, from few hours to several days if you are satisfied with your client as it is right now there is not that huge benefit regarding how much time it could take to fix all the windows Detecting leaking windows DON'T BLOCK THE BACKEND!! At first glance python code looks like you are invincible, you can do whatever you want, you are not responsible for the performance because python has a bottomless bucket full of update/render time and if the game freeze sometimes its definitely not your fault, the game is just BAD. Lets talk about OnUpdate and OnRender, whats the difference, when they are called, what to and what not to put in there. So as their name implies, they are called from the binary every time it performs an Update or Render action. In Update, the binary performs non-rendering actions, like updating the positions of walking characters, updating window positions, and every kind of calculation that is necessary for a render action, to make every kind of data up to date, reducing the cpu operations required for render as much as possible while keeping track of the time. In Render, the binary performs non-updating actions, calling only directx device rendering methods that builds up a picture of the current world, including the UI, using the current, up to date positions. If you try to count the number of stars in our galaxy to accurately simulate your star wars going on in the background of your inventory window, no matter where you do it, (render or update) you will start hurting the game. For example if you have an ui with tons of elements, generating all the elements under one tick can cause HUGE client lag. In my AE wiki, I only load one or two entity for the current page under an update tick, so it will still load quickly, but won't block the game. Notice that doing something like this is an UPDATE operation. Lets be nice and don't interrupt our rendering whit this kind of stuff. You should only use calls to render functions inside the OnRender, for example like in the ui.ListBox class, where we actually ask the binary to render a bar into our screen. Around 20% of time spent in an Update tick was consumed by the UI update (calling to a python object through the api is kinda slow by default) in the AE client one year ago. Removing the rendering and updating of the gui for testing purposes actually gave a huge boost to the client, so who knows, maybe one day someone will make a great client that runs smooth on low end pcs too. Answer the api calls if expected! Some calls from the binary like OnPressEscapeKey expects a return value. Of course if no return value is provided the binary won't crash, but can lead to weird problems and malfunctions. For example, the OnPressEscapeKey expects non-false (non-null) if the call was successful on the window, so it will stop the iteration from calling to lower level windows. So if you expect from the game to close only one window per esc push, you have to return True (or at least not False or nothing). There was a crash problem related to this in one of my friend's client recently. In his ui.EditLine class the OnPressEscapeKey looked something like this: def OnPressEscapeKey(self): if self.eventEscape(): return True return False In the original version it just return True unrelated to the eventEscape's return value. This looks fine at first glance, but if for some reason the self.eventEscape doesn't return anything and if (like the garbage collector decides to run or its disabled) the layer's or the parent's child lists changes in the binary because one or more windows are destroyed under the OnPressEscapeKey procedure and the iteration trough the child list is not interrupted, the binary will start to call invalid addresses thinking that they are existing windows, calling OnPressEscapeKey on them, resulting hardly backtraceable crashes. Closing words I can't highlight out enough times how much I like and enjoy creating new kind of UI stuff, (like animating windows that you may saw on my profile recently (click for the gif)) and because of this if you want to discuss a theory about new UI stuffs or mechanics of already existing UI stuffs feel free to do it in the comment section instead of writing me a pm to help others. Also this time (unlike for my other topics) I would like to keep this guideline up to date and maybe adding new paragraphs if I find out another common mistake/misunderstanding. DEATH TO ALL LEAKING WINDOW!!!!!4444four
    1 point
  14. M2 Download Center Download Here ( Internal ) VirusTotal: [Hidden Content] Hi ! Today ThunderCore Society will offer you a special tool for Granny3D Models. Note: That tool isn't for begginers and we don't offer suport for that. We hereby inform you that we take the copyrights file and his contents because ThunderCore Society has paid to perform this work. Attention: NonCommercial — You may not use the material for commercial purposes. NoDerivatives — If you transform, or build upon the material, you may not distribute the modified material. No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. Kind Regards - Johnny White
    1 point
  15. M2 Download Center Download Here ( Internal ) Hey, Today i will share how can you change the Whitemark in Minimap with a new one. I saw that there is a topic in Questions & Answers but seems not complete so. Minimap Whitemark - New Download:
    1 point
  16. This quest was made by when the only server that got it was karma2. Anyways it got leaked so i might release it full. It works on any game versions. Regens , group and quest in attachment. The only problem is , it`s in romanian language, but in 15 min u can translate it. MOB PROTO ( For shaman only damage) ITEM PROTO Snow.zip
    1 point
  17. and this: chrmgr.RegisterEffect(chrmgr.EFFECT_AFFECT + XX, "Bip01", "d:/ymir work/ob_work/shinnings/armor/black_dragon_light/black_dragon_light_v3.mse") [Hidden Content]
    1 point
  18. Topic updated - removed bug with double messages.
    1 point
  19. Here are all the update texts regarding the beta [Hidden Content] Unfortunately these files seem long lost; [Hidden Content] [Hidden Content]
    1 point
  20. The repository and part of the documentation is now available to the public. Repository: https://gitlab.com/quantum-core/core Documentation: https://docs.quantum-core.io/index.html
    1 point
  21. M2 Download Center Download Here ( Internal ) Hi ! Today ThunderCore Society will offer you a special tool for 3d MAX Software. Note: That tool isn't for begginers and we don't offer suport for that. We hereby inform you that we take the copyrights file and his contents because ThunderCore Society has paid to perform this work. There exists an "readme" file that contains some informations about how to install the script. Attention: These files are under copyright and licensed by ThunderCore Society. Any violation of the license may result in suing. Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. NonCommercial — You may not use the material for commercial purposes. NoDerivatives — If you transform, or build upon the material, you may not distribute the modified material. No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
    1 point
  22. Not bad I have searched this last days but now I have without extra image
    1 point
  23. When it comes to working with source code files (C++, LUA, Python) you will encounter a situation where you want to compare files. To help you comparing files there are two tools which we can recommend for that: Beyond Compare With Beyond Compare you are able to compare files and folders and easily find any mismatches. But you have to install another program to use it. Notepad++ Compare Plugin If you already have notepad++ installed, the compare plugin comes in handy. (Thanks to @Johnny69 for this recommendation.)
    1 point
  24. There are a bunch of tools you need to work on your private server. This is only an overview. If you want to know how to work with these programs please use google. There are a lot of tutorials out there. Please notice: Some of these programs do need a valid license which you have to buy. Yes, there are cracks on the internet but sometimes it's worth the money. You decide! Filetransfer (FTP / SFTP) Managing your server (console, ssh) Managing your database (MySQL / MariaDB) Working on text files (there are a lot of them in your sever) Working on image files (there are a lot of them in your client) Oh, one advice at the end: If you want an easy solution on how to install all these programs you just should have a look on [Hidden Content].
    1 point
  25. This is a list of 680 functions you can use in your quests. And you can create your own if you have knowledge of C++ and the sourcecode. addimage addmapsignal add_bgm_info add_goto_info add_ox_quiz affecr.remove_all_collect affect.add affect.add_collect affect.add_collect_point affect.add_hair affect.remove affect.remove_bad affect.remove_collect affect.remove_good affect.remove_hair arena.add_map arena.add_observer arena.get_duel_list arena.is_in_arena arena.start_duel ba.start block_chat bool_to_str building.get_land_id building.get_land_info building.has_land building.reconstruct building.set_land_owner BuildSkillList CancelTimerEvent char_log chat clearmapsignal cleartimer clear_letter clear_named_timer clear_server_timer cmdchat color command complete_quest complete_quest_state confirm d.check_eliminated d.clear_regen d.count_monster d.exit d.exit_all d.exit_all_to_start_position d.getf d.get_kill_mob_count d.get_kill_stone_count d.get_map_index d.is_unique_dead d.is_use_potion d.join d.jump_all d.jump_all_local d.kill_all d.kill_unique d.new_jump d.new_jump_all d.notice d.purge d.purge_unique d.regen_file d.revived d.select d.setf d.setqf d.set_dest d.set_exit_all_at_eliminate d.set_regen_file d.set_unique d.set_warp_at_eliminate d.spawn d.spawn_goto_mob d.spawn_group d.spawn_mob d.spawn_move_group d.spawn_move_unique d.spawn_name_mob d.spawn_stone_door d.spawn_unique d.spawn_wooden_door d.unique_get_hp_perc d.unique_set_def_grade d.unique_set_hp d.unique_set_maxhp dance.event_go_home delay dl.startRaid dragonlair.startRaid dungeon-set_quest_flag dungeon.all_near_to dungeon.check_eliminated dungeon.clear_regen dungeon.count_monster dungeon.exit dungeon.exit_all dungeon.get_flag dungeon.get_kill_mob_count dungeon.get_kill_stone_count dungeon.get_map_index dungeon.is_unique_dead dungeon.is_use_potion dungeon.join dungeon.jump_all dungeon.kill_all dungeon.kill_unique dungeon.new_jump dungeon.new_jump_all dungeon.notice dungeon.purge dungeon.purge_unique dungeon.regen_file dungeon.revived dungeon.select dungeon.set_dest dungeon.set_exit_all_at_eliminate dungeon.set_flag dungeon.set_regen_file dungeon.set_unique dungeon.set_warp_at_eliminate dungeon.spawn dungeon.spawn_goto_mob dungeon.spawn_group dungeon.spawn_mob dungeon.spawn_move_group dungeon.spawn_move_unique dungeon.spawn_stone_door dungeon.spawn_unique dungeon.spawn_wooden_door dungeon.unique_get_hp_perc dungeon.unique_set_def_grade dungeon.unique_set_hp dungeon.unique_set_maxhp empire.info enable_over9refine end.oxevent find_npc_by_vnum find_pc find_pc_by_name find_pc_cond fish_real_refine_rod forked.getbosskillcount forked.getdeadcount forked.getlevellimit forked.getpassmapindex forked.getpassmapindexbyempire forked.getpasspath forked.getpasspathbyempire forked.getpassstartposx forked.getpassstartposy forked.getsungzimapindex forked.getsungziposx forked.getsungziposy forked.get_dead_count forked.get_pass_path_by_empire forked.get_pass_start_pos forked.get_sungzi_start_pos forked.incbosskillcount forked.init forked.initforked forked.initkillcount forked.initmobkillcount forked.init_kill_count_per_empire forked.isforkedmapindex forked.issungzimapindex forked.is_forked_mapindex forked.is_registered_user forked.is_sungzi_mapindex forked.pass_mapindex_by_empire forked.pass_mapindex_by_empire forked.purge_all_monsters forked.register_user forked.setdeadcount forked.set_dead_count forked.sungzi_mapindex forked.sungzi_start_pos forked.warp_all_in_map frog.to_empire_money game.drop_item game.drop_item_with_ownership game.get_event_flag game.get_guild_name game.get_safebox_level game.get_warp_guild_war_list game.open_mall game.open_safebox game.request_make_guild game.set_event_flag game.set_safebox_level game.web_mall getnpcid get_empire_privilege get_empire_privilege_string get_global_time get_guildid_byname get_guild_privilege get_guild_privilege_string get_locale get_locale_base_path get_quest_state get_server_timer_arg get_time give_char_privilege give_empire_privilege give_guild_privilege goldbar.quest guild.around_ranking_string guild.change_master guild.change_master_with_limit guild.get_any_war guild.get_ladder_point guild.get_member_count guild.get_name guild.get_rank guild.get_reserve_war_table guild.get_warp_war_list guild.high_ranking_string guild.is_bet guild.is_war guild.level guild.name guild.war_bet guild.war_enter highscore.register highscore.show horse.advance horse.feed horse.get_grade horse.get_health horse.get_health_pct horse.get_hp horse.get_level horse.get_name horse.get_stamina horse.get_stamina_pct horse.is_dead horse.is_mine horse.is_riding horse.revive horse.ride horse.set_level horse.set_name horse.summon horse.unride horse.unsummon input is_test_server item.can_over9refine item.change_to_over9 item.get_cell item.get_count item.get_id item.get_level item.get_name item.get_over9_material_vnum item.get_refine_vnum item.get_size item.get_socket item.get_sub_type item.get_type item.get_value item.get_vnum item.has_flag item.next_refine_vnum item.over9refine item.remove item.select item.select_cell item.set_socket item_log item_name kill_all_in_map left_image loop_timer makequestbutton marriage.divorce_time_check marriage.end_wedding marriage.engage_to marriage.find_married_vid marriage.get_married_time marriage.get_wedding_list marriage.in_my_wedding marriage.join_wedding marriage.marry_to marriage.remove marriage.set_to_marriage marriage.warp_to_my_marriage_map marriage.wedding_client_command marriage.wedding_dark marriage.wedding_is_playing_music marriage.wedding_music marriage.wedding_snow math.ceil math.floor math.max math.min math.mod math.random member.chat member.clear_ready member.set_ready mgmt.monarch_change_lord mgmt.monarch_state mob.spawn mob.spawn_group mob_name mob_vnum monarch.bless monarch.defenseup monarch.defenseup_event monarch.notice monarch.powerup monarch.powerup_event monarch.transfer monarch.transfer2 monarch.transfer2_event monarch.warp next_time_is_now next_time_set notice notice_all notice_in_map npc.dec_remain_hairdye_count npc.dec_remain_skill_book_count npc.getrace npc.get_empire npc.get_guild npc.get_race npc.get_remain_hairdye_count npc.get_remain_skill_book_count npc.is_near npc.is_near_vid npc.is_pc npc.is_quest npc.kill npc.lock npc.open_shop npc.purge npc.unlock npc_get_job npc_is_same_empire npc_is_same_job number oh.candidacy oh.candidacycount oh.candidacy_list oh.candidacy_name oh.election oh.frog_to_empire_money oh.isguildmaster oh.ismonarch oh.monarchbless oh.monarchdefenseup oh.monarchpowerup oh.notice oh.spawnguard oh.spawnmob oh.takemonarchmoney os.date os.execute os.time oxevent.close oxevent.end_event oxevent.end_event_force oxevent.get_attender oxevent.get_status oxevent.give_item oxevent.open oxevent.quiz party.chat party.clear_ready party.getf party.get_flag party.get_max_level party.get_near_count party.is_leader party.is_party party.run_cinematic party.setf party.setqf party.set_flag party.set_quest_flag party.show_cinematic party.syschat pc.aggregate_monster pc.can_warp pc.changealignment pc.changegold pc.changemoney pc.change_alignment pc.change_empire pc.change_gold pc.change_money pc.change_name pc.change_sex pc.change_sp pc.clear_one_skill pc.clear_skill pc.clear_sub_skill pc.countitem pc.count_item pc.dec_skill_point pc.delqf pc.del_quest_flag pc.destroy_guild pc.diamond_refine pc.enough_inventory pc.forget_my_attacker pc.getarmor pc.getcurrentmapindex pc.getempire pc.getf pc.getgold pc.getguild pc.gethp pc.getleadership pc.getmaxhp pc.getmaxsp pc.getmoney pc.getname pc.getplaytime pc.getqf pc.getsp pc.getweapon pc.getx pc.gety pc.get_account pc.get_account_id pc.get_alignment pc.get_another_quest_flag pc.get_armor pc.get_change_empire_count pc.get_channel_id pc.get_dx pc.get_empire pc.get_empty_inventory_count pc.get_equip_refine_level pc.get_exp pc.get_flag pc.get_gm_level pc.get_gold pc.get_guild pc.get_horse_hp pc.get_horse_level pc.get_horse_stamina pc.get_hp pc.get_ht pc.get_iq pc.get_job pc.get_leadership pc.get_level pc.get_local_x pc.get_local_y pc.get_logoff_interval pc.get_map_index pc.get_max_hp pc.get_max_sp pc.get_money pc.get_name pc.get_next_exp pc.get_part pc.get_player_id pc.get_playtime pc.get_premium_remain_sec pc.get_quest_flag pc.get_race pc.get_real_alignment pc.get_sex pc.get_skill_group pc.get_skill_level pc.get_skill_point pc.get_socket_items pc.get_sp pc.get_special_ride_vnum pc.get_st pc.get_start_location pc.get_vid pc.get_war_map pc.get_weapon pc.get_x pc.get_y pc.give_exp pc.give_exp2 pc.give_exp_perc pc.give_gold pc.give_item pc.give_item2 pc.give_item_from_special_item_group pc.give_lotto pc.give_or_drop_item pc.give_polymorph_book pc.give_poly_marble pc.hasguild pc.has_guild pc.has_master_skill pc.have_map_scroll pc.have_pos_scroll pc.in_dungeon pc.isguildmaster pc.is_clear_skill_group pc.is_dead pc.is_engaged pc.is_engaged_or_married pc.is_gm pc.is_guild_master pc.is_horse_alive pc.is_married pc.is_monarch pc.is_mount pc.is_near_vid pc.is_polymorphed pc.is_riding pc.is_skill_book_no_delay pc.learn_grand_master_skill pc.mining pc.mount pc.mount_bonus pc.ore_refine pc.pc_attract_ranger pc.polymorph pc.refine_equip pc.removeitem pc.remove_from_guild pc.remove_item pc.remove_polymorph pc.remove_skill_book_no_delay pc.reset_point pc.reset_status pc.revive_horse pc.save_exit_location pc.select pc.select_pid pc.select_vid pc.send_block_mode pc.set.skill_level pc.setf pc.setqf pc.set_another_quest_flag pc.set_change_empire_count pc.set_flag pc.set_part pc.set_quest_flag pc.set_skillgroup pc.set_skill_group pc.set_skill_level pc.set_warp_location pc.set_warp_location_local pc.teleport pc.unmount pc.upgrade_polymorph_book pc.warp pc.warp_exit pc.warp_local pc.warp_to_guild_war_observer_position pc_find_skill_teacher_vid pc_find_square_guard_vid pc_get_exp_bonus pc_get_village_map_index pc_is_novice purge_area q.done q.getcurrentquestindex q.no_send q.setstate q.set_clock q.set_clock_name q.set_clock_value q.set_counter q.set_counter_name q.set_counter_value q.set_icon q.set_quest_state q.set_state q.set_title q.set_title2 q.start q.yield quest.done quest.no_send quest.setstate quest.set_another_title quest.set_clock_name quest.set_clock_value quest.set_counter_name quest.set_counter_value quest.set_icon_file quest.set_title quest.start quest_create_server_timer_event quest_create_timer_event quest_server_timer_event quest_timer_event raw_script refine_pick regen_in_map RegisterMonarchFunctionTable resetdelay restart_quest say ScriptToString select select_item select_table send_letter send_letter_ex server_loop_timer server_timer setbgimage setcolor say_color setdelay setleftimage setmapcenterposition say_size setskin setstate set_named_loop_timer set_named_timer set_quest_state set_server_loop_timer set_server_timer set_skin set_state set_timer show_horse_menu skill_group_dialog spawn.guard spawn.mob spawn_mob string.format string.len syschat syserr syslog sys_log table.foreach table.foreachi table.getn table.insert table.remove table_get_random_item takemonarchmoney target.clear target.delete target.id target.npc target.pc target.pos target.vid test_chat timer time_hour_to_sec time_min_to_sec time_to_str tonumber top_image tostring type under_han wait warp_all_in_area_to_area warp_all_in_map warp_all_to_map_event warp_all_to_map_my_empire_event warp_all_to_village warp_all_to_village_event warp_all_to_village_except_my_empire warp_to_village __fish_real_refine_rod __get_empire_priv_string __get_guildid_byname __get_guild_priv_string __give_char_priv __give_empire_priv __give_guild_priv __refine_pick
    1 point
  26. You must rebuild all solution. (Microsoft Visual Studio -> Build -> Rebuild Solution. @topic Thanks. XD
    1 point
  27. Well .. i've made it for 40k to work perfect... uicharacter.py and interfacemodule.py made for r40k Client is attached to this reply.. Have fun test.zip
    1 point
  28. I'm still looking for that 3 lines
    0 points
  29. M2 Download Center Download Here ( Internal )
    0 points
×
×
  • 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.