Jump to content


Popular Content

Showing content with the highest reputation since 05/21/2020 in all areas

  1. 21 points
    Hello. Demo: Mega.nz
  2. 20 points
    https://github.com/blackdragonx61/Metin2-CHANNEL-STATUS-UPDATE --------------------------------- ---------------------------------
  3. 17 points
    Hello everybody. I was not planned to offer this for sale neither to release it, but couple of persons were asking for it and since it seems to be stable for a month now it is on a live server, so here it is. As you all know there are some visual problems with the sashes on tall mounts or with the motion of die, with this they are gone forever. Some examples: I am offering the sash scaling+positioning together with character/mob/npc/pet aka world-scaling for 50€ If you need the scaling expanded onto effects too, that is +20€. Implementation + 10€. Discord: dotpngr#3873 Be specific with your message you are sending to me, and at least if you don't speak english well let me know at the beginning, usually I don't reply to the "i need system i pay" kind of messages. Also, my laptop is online 24/7, even when I am not in front of it I am online, this doesn't mean that I am available too.
  4. 9 points
    Hello togehter, today i want to share a small, but in my opinion, usefull security upgrade for your player password-hashes. The current default hash, which is used by the most of you (some exeptions might be out there) is the MD5 Hash. This hash might be not the best choice for hashing passwords in this modern days. This is why i thought about something to change there. And my solution for this is Argon2. This Method had won the Password Hashing Competition and this is why i had choosen this over bcrypt or scrypt. This tutorial isn't a 100% beginner firendly guide! Just follow my instructions if you got a little bit of c++ knowledge and know how to work with the source! Create the libargon2 Change the hash inner the game-core source (DEFAULT PASSWORD() MYSQL FUNC TUTORIAL) For now you just need to edit the account.account table and set the size for the password to 128 (Why 128? Db.h EArgon2::HASH_LENGTH = 64. 64 * 2 = 128) And you need to replace your hashes with the argon2 once. For this follow the link to the generation: https://argon2.online Example config for the tutorial setup: Have fun
  5. 6 points
    Its finally out!! Full dungeon info is here: https://plechito.com/ancient-pyramid/
  6. 4 points
    Hi, Here i publish my edit of the public Render Target System. I hate it, when people earn money with public systems. https://mega.nz/file/TREH0KQD#3wx1zo5pSxLPQ0tmU41cJjpGzuKsN3bLBKQCawBv250 Original Thread https://metin2.dev/board/index.php?/topic/20550-rlsrendertarget/&tab=comments#comment-111384 https://gyazo.com/f1529844682e872a6c580c27b2daa289 have a look at my comments at UiToolTip.py Bug Fix: UiToolTip-Fix.txt
  7. 4 points
    EterNexus File Archiver View File File archiver for Metin2 with GUI made by Crysus Technologies. Please note, you will need Microsoft Visual C++ 2010 Redistributable Package installed to use this software. 32-bit download: http://www.microsoft.com/en-us/download/details.aspx?id=5555 64-bit download: http://www.microsoft.com/en-us/download/details.aspx?id=14632 Screenshots: EterNexus_1.0.3.1a.rar Submitter Rumor Submitted 02/03/14 Category Tools
  8. 3 points
    File Name: WorldEditor ReMIX File Submitter: martysama0134 File Submitted: 27 Aug 2014 File Category: Tools Intro: 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: https://www.mediafire.com/folder/g0r2rlnfewwv4/WE 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: old_map_tools__20140718-0420.rar we_remix_v24__20150621-0154.rar
  9. 3 points
    Hello everyone. Let me share these with you here. This post contains everything for the recent[v20.1.5.1 05.05.2020] item and mob proto structure. About the mob_proto it might be some false data, but it's okay , it is impossible to figure out totally from clientside only. I am going to explain my thoughts about the new AI Flags as well as about everything I know, or think. enum EMisc { CHARACTER_NAME_MAX_LEN = 24, MOB_SKILL_MAX_NUM = 5, ITEM_NAME_MAX_LEN = 24, ITEM_LIMIT_MAX_NUM = 2, ITEM_VALUES_MAX_NUM = 6, ITEM_APPLY_MAX_NUM = 4, ITEM_SOCKET_MAX_NUM = 3, CHARACTER_FOLDER_MAX_LEN = 64, }; Fist stop, this enum contains some basic informations which mostly the same, except one. ITEM_APPLY_MAX_NUM has been increased to 4 from 3. Why? Because of the new mounting system what they have done. The seal items of the mounts control everything about the mounting and its bonuses; - New APPLY_MOUNT bonus, its value is the vnum of the mount, stored into POINT_MOUNT. - The bonuses what the mount gives are in the rest of the applies. This why they had to add an extra apply because some mounts gives up to 3 bonuses. typedef struct SItemLimit { BYTE bType; long lValue; } TItemLimit; typedef struct SItemApply { WORD wType; long lValue; } TItemApply; Ho-ho-ho another stop here for a sentence. Might be you cannot see any new values, but if you check the datatypes in the TItemApply, you will see they have changed the datatype of the ApplyType from BYTE(unsigned char) to WORD(unsigned short). Why? The answer is easy; because of their number of the bonuses reached the 255 limit of the BYTE, above of 255 the data will overflow. This modification they made with the 6th 7th bonuses. They added lots of worthless bonuses to be different from the private section and to squeeze out the money of the players with the 6th 7th bonuses. enum EItemAntiFlag { ITEM_ANTIFLAG_FEMALE = (1 << 0), ITEM_ANTIFLAG_MALE = (1 << 1), ITEM_ANTIFLAG_WARRIOR = (1 << 2), ITEM_ANTIFLAG_ASSASSIN = (1 << 3), ITEM_ANTIFLAG_SURA = (1 << 4), ITEM_ANTIFLAG_SHAMAN = (1 << 5), ITEM_ANTIFLAG_GET = (1 << 6), ITEM_ANTIFLAG_DROP = (1 << 7), ITEM_ANTIFLAG_SELL = (1 << 8), ITEM_ANTIFLAG_EMPIRE_A = (1 << 9), ITEM_ANTIFLAG_EMPIRE_B = (1 << 10) ITEM_ANTIFLAG_EMPIRE_R = (1 << 11) ITEM_ANTIFLAG_SAVE = (1 << 12) ITEM_ANTIFLAG_GIVE = (1 << 13) ITEM_ANTIFLAG_PKDROP = (1 << 14) ITEM_ANTIFLAG_STACK = (1 << 15) ITEM_ANTIFLAG_MYSHOP = (1 << 16) ITEM_ANTIFLAG_SAFEBOX = (1 << 17) ITEM_ANTIFLAG_WOLFMAN = (1 << 18) ITEM_ANTIFLAG_RT_REMOVE = (1 << 19) ITEM_ANTIFLAG_QUICKSLOT = (1 << 20) ITEM_ANTIFLAG_CHANGELOOK = (1 << 21) ITEM_ANTIFLAG_REINFORCE = (1 << 22) ITEM_ANTIFLAG_ENCHANT = (1 << 23) ITEM_ANTIFLAG_ENERGY = (1 << 24) ITEM_ANTIFLAG_PETFEED = (1 << 25) ITEM_ANTIFLAG_APPLY = (1 << 26) ITEM_ANTIFLAG_ACCE = (1 << 27) ITEM_ANTIFLAG_MAIL = (1 << 28) }; Okay, here also there are many of new antiflags and I am going the explain the new flags only: ITEM_ANTIFLAG_RT_REMOVE : This one kind of funny, because this doesn't have any reference at clientside, but it should be ANTIFLAG_REAL_TIME_REMOVE. Which blocks the destroyitem function when the real_time_expire_event is executed. It is about 98% sure. Only the new pet system seals have this flag, and their transport box. Isn't it funny that I've just figured this out now when I wrote this? haha ITEM_ANTIFLAG_QUICKSLOT : Obviously blocks to attach the item with this flag to the quickslots. ITEM_ANTIFLAG_CHANGELOOK : This one will block the changelook process. That item which has this flag cannot be used for appearance for another. ITEM_ANTIFLAG_REINFORCE : Blocks to add new bonuses to an item. ITEM_ANTIFLAG_ENCHANT : Blocks to change the attributes of an item. ITEM_ANTIFLAG_ENERGY : Blocks to use the item for making Energy Fragment from it. ITEM_ANTIFLAG_PETFEED : This flag blocks the pet, to eat the item which has it. ITEM_ANTIFLAG_APPLY : This flag will make the item unstonable, you will not be able to put any stones into it. Or It blocks every applicable item to use on it, can be both too, dunno. ITEM_ANTIFLAG_ACCE : This flag will block theowadan to absorb the bonuses from the item which has this flag. ITEM_ANTIFLAG_MAIL : The flag will make the item unsendable via mail. enum EItemFlag { ITEM_FLAG_REFINEABLE = (1 << 0), ITEM_FLAG_SAVE = (1 << 1), ITEM_FLAG_STACKABLE = (1 << 2), ITEM_FLAG_COUNT_PER_1GOLD = (1 << 3), ITEM_FLAG_SLOW_QUERY = (1 << 4), ITEM_FLAG_RARE = (1 << 5), ITEM_FLAG_UNIQUE = (1 << 6), ITEM_FLAG_MAKECOUNT = (1 << 7), ITEM_FLAG_IRREMOVABLE = (1 << 8), ITEM_FLAG_CONFIRM_WHEN_USE = (1 << 9), ITEM_FLAG_QUEST_USE = (1 << 10), ITEM_FLAG_QUEST_USE_MULTIPLE= (1 << 11), ITEM_FLAG_QUEST_GIVE = (1 << 12), ITEM_FLAG_LOG = (1 << 13), ITEM_FLAG_APPLICABLE = (1 << 14), }; Small confess about the normal Flags, I'm too lazy to explain everything so I just put here the list of them Anyway they didn't add any new, just removed some unused from 2003 devphase. enum EItemWearFlag { WEARABLE_BODY = (1 << 0), WEARABLE_HEAD = (1 << 1), WEARABLE_FOOTS = (1 << 2), WEARABLE_WRIST = (1 << 3), WEARABLE_WEAPON = (1 << 4), WEARABLE_NECK = (1 << 5), WEARABLE_EAR = (1 << 6), WEARABLE_UNIQUE = (1 << 7), WEARABLE_SHIELD = (1 << 8), WEARABLE_ARROW = (1 << 9), WEARABLE_HAIR = (1 << 10), WEARABLE_ABILITY = (1 << 11), WEARABLE_PENDANT = (1 << 12), }; Here for a comment, they have just added the pendant as new, and changed the index of the unique with the shield. Also wondering when they are going to remove the unused wear ability flag, and its I dont know how many slots from the equipments .. Those were back in time couple of hidden items, for the collection quests bonus holder of the results, or whatever, stupid thing, unused, supposed to be removed. Done. The Immune flag is untouched, pf obviously because it is used for nothing at all rofl. About the LimitTypes, they removed the PC_BANG value, and its items, codes completely. typedef struct SItemTable { DWORD dwVnum; DWORD dwVnumRange; char szName[ITEM_NAME_MAX_LEN + 1]; char szLocaleName[ITEM_NAME_MAX_LEN + 1]; BYTE bType; BYTE bSubType; BYTE bWeight; BYTE bSize; DWORD dwAntiFlags; DWORD dwFlags; DWORD dwWearFlags; DWORD dwImmuneFlag; DWORD dwBuyItemPrice; DWORD dwSellItemPrice; TItemLimit aLimits[ITEM_LIMIT_MAX_NUM]; TItemApply aApplies[ITEM_APPLY_MAX_NUM]; long alValues[ITEM_VALUES_MAX_NUM]; long alSockets[ITEM_SOCKET_MAX_NUM]; DWORD dwRefinedVnum; WORD wRefineSet; DWORD dw67Material; BYTE bAlterToMagicItemPct; BYTE bSpecular; BYTE bGainSocketPct; BYTE bMaskType; BYTE bMaskSubType; } TItemTable; Okay, lets do this one too. So, as you can see here are couple of new values, compared to the old one from 2013. Let's roll over on the new values. dw67Material : This one will be the vnum for the 6th 7th bonus adder, which material is necessary to add the bonus to the item. You can read about this on the official wiki. bMaskType : This is used for the private shop search to categorize the items. bMaskSubType : This is also used for the private shop search to categorize the items. Last word about the item_proto: I will not put the types, subtypes, and their mask version and describe them because none of you will use it . Coming up the mob_proto. enum EMobEnchants { MOB_ENCHANT_CURSE, MOB_ENCHANT_SLOW, MOB_ENCHANT_POISON, MOB_ENCHANT_STUN, MOB_ENCHANT_CRITICAL, MOB_ENCHANT_PENETRATE, MOB_ENCHANTS_MAX_NUM, }; Yes this is untoucheed. No, they didn't add bleeding as enchant to the mobs. It is an effect of some skills of the monsters in the zodiac temple. enum EMobResists { MOB_RESIST_FIST, MOB_RESIST_SWORD, MOB_RESIST_TWOHAND, MOB_RESIST_DAGGER, MOB_RESIST_BELL, MOB_RESIST_FAN, MOB_RESIST_BOW, MOB_RESIST_CLAW, MOB_RESIST_FIRE, MOB_RESIST_ELECT, MOB_RESIST_MAGIC, MOB_RESIST_WIND, MOB_RESIST_POISON, MOB_RESIST_BLEEDING, MOB_RESISTS_MAX_NUM, }; Here you can see couple of new values, all of them obvious, and readable to understand. But if it isn't... MOB_RESIST_FIST: Resist to fist, so when you hit the monster without weapon equipped and it has this defence value, the damage will be reduced. MOB_RESIST_CLAW: Resist against claw attacks, come on, I don't want to do this. MOB_RESIST_BLEEDING: Same as resist_poison just against of the bleeding. enum EMobElementaryWhatevers { MOB_ELEMENTAL_ELEC, MOB_ELEMENTAL_FIRE, MOB_ELEMENTAL_ICE, MOB_ELEMENTAL_WIND, MOB_ELEMENTAL_EARTH, MOB_ELEMENTAL_DARK, MOB_ELEMENTAL_MAX_NUM }; Without serverside these values are not understandable properly. Naturaly those monsters which has elemental resists they have this values as well on the same elemental. Forexample: Lets see the Death reaper(1093). He has UNDEAD and ATT_DARK as RaceFlag, 50% resist fist(just telling ;]), ElemDark=1 and resist dark "-20%" But some monsters are having these values 100+ which is.... no idea why. Zodiac monsters only if I'm not wrong. enum EMobAIFlags { AIFLAG_AGGRESSIVE = (1 << 0), AIFLAG_NOMOVE = (1 << 1), AIFLAG_COWARD = (1 << 2), AIFLAG_NOATTACKSHINSU = (1 << 3), AIFLAG_NOATTACKJINNO = (1 << 4), AIFLAG_NOATTACKCHUNJO = (1 << 5), AIFLAG_ATTACKMOB = (1 << 6), AIFLAG_BERSERK = (1 << 7), AIFLAG_STONESKIN = (1 << 8), AIFLAG_GODSPEED = (1 << 9), AIFLAG_DEATHBLOW = (1 << 10), AIFLAG_REVIVE = (1 << 11), AIFLAG_HEALER = (1 << 12), AIFLAG_COUNT = (1 << 13), AIFLAG_NORECOVERY = (1 << 14), AIFLAG_REFLECT = (1 << 15), AIFLAG_FALL = (1 << 16), AIFLAG_VIT = (1 << 17), AIFLAG_RATTSPEED = (1 << 18), AIFLAG_RCASTSPEED = (1 << 19), AIFLAG_RHP_REGEN = (1 << 20), AIFLAG_TIMEVIT = (1 << 21), }; Here you can see many of new AIFlag values. I am not 100% sure about them, but here is what I think about these new values: AIFLAG_HEALER : This one is the healer, who will heal all members in its group. AIFLAG_COUNT : Who has this flag, you can make just 1 damage on it. AIFLAG_NORECOVERY : This will blocks the monster to recover its health. AIFLAG_REFLECT : <vice> With this flag the monster will be able to transform you into a monster, npc, or statue. AIFLAG_FALL : Ability to force you to fall off your mount. AIFLAG_VIT : <versa> Make your attack damage half, for 10 minutes, until the zodiac floor expires. AIFLAG_RATTSPEED : Reduces the speed of your attack. AIFLAG_RCASTSPEED : Reduces the speed of your skills, it means the cooldown of your skills will be increased. AIFLAG_RHP_REGEN : Reduces the regeneration of your health. AIFLAG_TIMEVIT : <versa> Make your attack damage half, for x seconds. About the vice-versa, those values are imaginable in switched description too. If the reflect is removing your attack damage with the half of it for x seconds then the VIT flags are the transformations. Forexample: the timevit is for tranforming you into monster, or mount for couple of seconds. the vit is for transforming you into a statue until the zodiac floor runs, or until one of your mate hits you. typedef struct SMobSkillLevel { DWORD dwVnum; BYTE bLevel; } TMobSkillLevel; typedef struct SMobTable { DWORD dwVnum; char szName[CHARACTER_NAME_MAX_LEN + 1]; char szLocaleName[CHARACTER_NAME_MAX_LEN + 1]; BYTE bType; BYTE bRank; BYTE bBattleType; BYTE bLevel; BYTE bScale; BYTE bSize; DWORD dwGoldMin; DWORD dwGoldMax; DWORD dwExp; DWORD dwMaxHP; BYTE bRegenCycle; BYTE bRegenPercent; WORD wDef; DWORD dwAIFlag; DWORD dwRaceFlag; DWORD dwImmuneFlag; BYTE bStr, bDex, bCon, bInt; DWORD dwDamageRange[2]; short sAttackSpeed; short sMovingSpeed; BYTE bAggresiveHPPct; WORD wAggressiveSight; WORD wAttackRange; char cEnchants[MOB_ENCHANTS_MAX_NUM]; char cResists[MOB_RESISTS_MAX_NUM]; char cElementalFlags[MOB_ELEMENTAL_MAX_NUM]; char cResistDark, cResistIce, cResistEarth; DWORD dwResurrectionVnum; DWORD dwDropItemVnum; BYTE bMountCapacity; BYTE bOnClickType; BYTE bEmpire; char szFolder[CHARACTER_FOLDER_MAX_LEN + 1]; float fDamMultiply; DWORD dwSummonVnum; DWORD dwDrainSP; DWORD dwMonsterColor; DWORD dwPolymorphItemVnum; TMobSkillLevel Skills[MOB_SKILL_MAX_NUM]; BYTE bBerserkPoint; BYTE bStoneSkinPoint; BYTE bGodSpeedPoint; BYTE bDeathBlowPoint; BYTE bRevivePoint; BYTE bHealPoint; BYTE bRAttSpeedPoint; BYTE bRCastSpeedPoint; BYTE bRHPRegenPoint; FLOAT fHitRange; } TMobTable; bScale: : Scale value between 50 and 200. It will resize the monster. cElementalFlags : So I've told you some info about this, I don't know more. cResistDark : This is a missing elemental resist, they have added it, I just don't really know why even there, not into the resists array, stupid. cResistIce : This is a missing elemental resist, they have added it, I just don't really know why even there, not into the resists array, stupid. cResistEarth : This is a missing elemental resist, they have added it, I just don't really know why even there, not into the resists array, stupid. bHealPoint : Healing percent for the healers. bRAttSpeedPoint : These can be used for what I've named them or the REFLECT or the VIT and TIMEVIT flags too, to give them special value, so it is still a questionmark. bRCastSpeedPoint : These can be used for what I've named them or the REFLECT or the VIT and TIMEVIT flags too, to give them special value, so it is still a questionmark. bRHPRegenPoint : These can be used for what I've named them or the REFLECT or the VIT and TIMEVIT flags too, to give them special value, so it is still a questionmark. fHitRange : Because the client is using its default value to make the checks, this one for sure is on serverside, to check the distance between the character and the monster to validate the attack, skill or the movement of the monsters. But still not 100% I hope it is understandable, my english isn't the best sorry for that. If I missed something let me know in PM.
  10. 3 points
    Write me on Discord: Volvox#7662 Bug-Fix for all others. Preview is now only on Items in Inventory UiToolTip-Fix.txt
  11. 2 points
    Introduction Hey, since I'm often asked if I can make an example for this or that in Python, I just post some of these examples in this thread from time to time. Usually they just end up in my trash (that's why the collection is small for now) but maybe it will help some of you to learn something. You are also welcome to post examples here and I will add them to the startpost. You have a wish for a certain example? Then write it in here. PS: These examples are designed very simple, so that they can be understood. Examples ui.ComoBox() ui.ScrollBar() with text ui.AniImageBox() as loading bar ui.ListBox() ui.ToggleButton() ui.RadioButtonGroup() ui.DragButton() ui.Bar(), ui.Box(), ui.Line() ui.Gauge(), ui.SliderBar() ui.TextLine(), ui.EditLine() Pagination Tabs DropDown Tree Category Navigation ListBox Search TextLineScrollable Class Collapsible window
  12. 2 points
    I'm very sorry for this topic, since it's offtopic, I just wanted to share this individual, so disrespectful to me... What kind of behavior from a customer is this? This is spam, insults, talking spanish, all hell with his profile picutre...
  13. 2 points
    https://github.com/blackdragonx61/Metin2-Skill-CoolTime-Update Based idea: https://puu.sh/FMqJb/715b86e1b3.png https://streamable.com/1g6nz7 You can add control for specific skill ids ----------- Not tested very well. Let me know, if you found a bug.
  14. 2 points
  15. 2 points
    Hello, this type of system was already released on TurkMMO today, I thought I will post a in my opinion better implementation of this system. Download: https://mega.nz/#!BehnlQ4C!0ME6NcbK-O_7gFyZQLkMGcM2p90cH79umtECZiTIP2E Thanks to VegaS for the re-edit. Kind regards, CHMarvin.
  16. 2 points
    Hey guys! I'd like to introduce my anti-cheat system which has been running for some time with a few customers - now I'd like to expand it to different countries as well The codebase is pretty clean, it's regulary tested for performance and stability, so it's guaranteed you won't have issues with the system after integrating it. The most important things to mention: I'm constantly updating the anticheat, so every time a hack updates, I'll take care of it. The monthly price obviously includes every update. I'm also updating my detection methods if cheat authors aren't yet active If someone finds a method to bypass my anticheat, I'll take care of the update. Nothing external website dependecy, it's completely independent from any of my domain. Even licensing works in a way which does NOT require my confirmal, but still very secure. This is why it's a monthly paid service. I'm taking support & update tasks very seriously. [TLDR;] What does HackTrap provide? Protection against all current major cheat providers, obviously including m2bob & lalaker (continously updating detection methods!) SDK to integrate server-client communication between the anticheat and the server, so it's ensured that anticheat MUST be running. Some generic protection against unknown cheats & unwanted hacktools. Forbid launching the game directly without using patcher. Advanced logging in case if any issue happens, so I'm able to investigate any case. Independent from ANY EXTERNAL website. Advanced licensing system, which prevents other servers from stealing your anticheat/license. Completely anonymous telemetry data about your players (OS version, country, most often tried hacks) (GDPR-Wise, NOTHING personal is stored!) Considering to add any customer-requested features What isn't HackTrap trying to be? A world-grade perfect anticheat protection against literally every hacker and more. If you want so, try to buy EAC, HackShield and others. Pricing: Each server is priced individually, if you're interested, please DM me. Price is paid MONTHLY, but you can obviously choose to pay more than a single month, so you have to pay less frequently. If requested, a trial month is available. Why the monthly price? Because as I mentioned - I'm constantly updating the anticheat. As soon as there's any public method which is able to bypass my anticheat, I'll take care of it. So, you're actually paying for the support & updates, which I'm monthly spending on my product. Where to contact me? If you're looking for a price estimation, I'll need you to fill a form first, so I know a few important details. You can find it here: https://forms.gle/FWcsCjXN4moXGceh7 Discord: Unc3nZureD#9313 Or you can just PM me here, on forum. Feel free to ask any question. Thanks for reading!
  17. 2 points
    Yep ... there really is a problem :-s https://gyazo.com/69965fee9b78244e3d7b92de97b0db55 Edit: Even with a 100% chance of reading is still not working. https://gyazo.com/f914a7496af1481ded2fa4a954c71848 At least we know the problem doesn't come from char_item.cpp.
  18. 2 points
    https://i.epvpimg.com/fFtMcab.png https://i.epvpimg.com/0o3Zfab.jpg https://i.epvpimg.com/hy7Baab.jpg https://i.epvpimg.com/96gfcab.jpg https://i.epvpimg.com/TdDxcab.jpg https://i.epvpimg.com/f5B5cab.jpg https://i.imgur.com/cii0YBw.jpg https://www.youtube.com/watch?v=bVI4zBnPMHs https://www.youtube.com/watch?v=_T44fR23Cts https://www.youtube.com/watch?v=-YzrFcmDnzk Includes: - PSD login - Cuttet PNGs login - Background animation login - PSD ingame - Cuttet PNGs ingame - Animation HP and MP - Skill Icons Code is not included! Download: https://mega.nz/#!cPhWBIrb!J9ydnNNqucGfIe91W7ADvlQOkiwWfvCsLbGrw-VccAI Id love to see this one coded and on an actual server. If you use it please let me see so i can take a look!
  19. 2 points
    @boloca Topic closed + you won a warning. (2.5) Questions & Answers specific rules Don't modify your thread (or reply to it) to mark it solved, and not explain the solution to the issue.
  20. 2 points
    Hello, Working on some new stuff I found out that current implementation of event looks a bit tricky. Due to this fact I basically deciced to re-implement it in C++11 providing up to date tech. Don`t forget to take a look at this topic before you start: https://metin2dev.org/board/index.php?/topic/305-src-compile-with-gcc48-c11-and-optimized-flags/ So lets begin. Add include into the main.cpp: #ifdef __NEW_EVENT_HANDLER__ #include "EventFunctionHandler.h" #endif And add this into main function before: while (idle()); #ifdef __NEW_EVENT_HANDLER__ CEventFunctionHandler EventFunctionHandler; #endif Now add this at the end of idle: #ifdef __NEW_EVENT_HANDLER__ CEventFunctionHandler::instance().Process(); #endif Now search for: sys_log(0, "<shutdown> Destroying CArenaManager..."); And add before: #ifdef __NEW_EVENT_HANDLER__ sys_log(0, "<shutdown> Destroying CEventFunctionHandler..."); CEventFunctionHandler::instance().Destroy(); #endif Now open service.h and add this define: #define __NEW_EVENT_HANDLER__ That`s all. Now just download attachment and add included files to your source. Enjoy. EventFunctionHandler.zip http://www71.zippyshare.com/v/XQNjXSKn/file.html
  21. 2 points
    The archive contains: The icons The models Textures Before : After : Download
  22. 2 points
    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). Client files: element_image_client_files.rar 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! element_image_client_files.rar
  23. 2 points
    Today I bring you another exclusive release from Tim. This time is the granny.dll compatible with Granny 2.8 models and new binaries. Included for completeness is the already public granny DLL for the old binaries, and the bulkconverter.exe tool. What can I do with this? You can use granny models from any Granny version up to 2.8 in your client. How do I use this? Just replace the original dll in your client. Please note, it only works on original, packed client binaries. A tool (bulkconverter.exe) is provided so you can easily convert your current models to 2.8 for best performance. Usage: bulkconverter foldername Will convert all the gr2 files found inside foldername to v2.8 Granny format. Regards granny28.zip
  24. 2 points
    M2 Download Center Download Here ( Latest Version ) Dear M2Dev Community, I did not find a share with the Sources of Metin2... I share the sources with you today ! Kraizy sources with all branches of development. External Link : Mega Go Best Regards, ASIKOO
  25. 2 points
    Hello everyone ! I've been away from metin2 for about 6 months and i've get back from less then a month and made thoes systems , i've start selling them but i didn't sell it to anyone and i got bored from metin2 again so i'm going to release it and go off from metin2 for ever . about the Advance Refine System here some info: so download and have fun Advance Refine System.rar Soul Bind System.rar Cheque System.rar
  26. 2 points
    I would do it like this, in a simple way, without useless code, as i said in another forum too. [hide] def AppendAntiflagInformation(self): antiFlagDict = { localeInfo.TOOLTIP_ANTIFLAG_DROP : item.ITEM_ANTIFLAG_DROP, localeInfo.TOOLTIP_ANTIFLAG_SELL : item.ITEM_ANTIFLAG_SELL, localeInfo.TOOLTIP_ANTIFLAG_GIVE : item.ITEM_ANTIFLAG_GIVE, localeInfo.TOOLTIP_ANTIFLAG_PKDROP : item.ITEM_ANTIFLAG_PKDROP, localeInfo.TOOLTIP_ANTIFLAG_STACK : item.ITEM_ANTIFLAG_STACK, localeInfo.TOOLTIP_ANTIFLAG_MYSHOP : item.ITEM_ANTIFLAG_MYSHOP, localeInfo.TOOLTIP_ANTIFLAG_SAFEBOX : item.ITEM_ANTIFLAG_SAFEBOX, } antiFlagNames = [name for name, flag in antiFlagDict.iteritems() if item.IsAntiFlag(flag)] if antiFlagNames: self.AppendSpace(5) textLine = self.AppendTextLine('{} {}'.format(', '.join(antiFlagNames), localeInfo.NOT_POSSIBLE), self.CONDITION_COLOR) textLine.SetFeather() [/hide]
  27. 2 points
    Hi there everyone, I'd like to share a small function which will give you a random name whilst creating a new character. This will only include the function and a list of names, so you will have to set the event on your own. Preview: The function which will most likely be put in introCreate.py import os import app #import the above lines if you don't have them already def __randomizeName(self): dir = os.path.dirname(os.path.abspath("introCreate.py")) list = open("%s\\names.list" % dir, "r").read().split("\n") rng = app.GetRandom(0, len(list)-1) randomName = list[rng] self.heroName.SetText("%s" % randomName) ## change variable 'heroName' with your editline's name Also place the attached file to this thread in the main directory of the client. (i.e: where the launcher is) names.list contains 150 names, if you ever need more names let me know so I can up the number or you can add more yourself, but do note you need to put each name as a new line so you won't mess up the function. That's all for now, hope you all have a great day! Cheers. names.list
  28. 2 points
    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. VirusTotal: Link Download: texturechanger_thc.zip Archive Password: http://www.thunder-core.com How to use: Kind Regards - Johnny White
  29. 1 point
    That is what Penger said just above. It’s not a scale.
  30. 1 point
    decided to purchase their services. your code is clean. It responds fast and I can say that its support is good. I will certainly acquire more services in the future. recommended!
  31. 1 point
    Honestly not, but also on my srv they use this shit to anger other users in pvp. I think also clearing the target they can still do the skills after unride causing a sync lag to the opponent. ps. Maybe is better to lock the skills for some second after unride. No buff skills to take clean pvm.
  32. 1 point
  33. 1 point
    I think you still use code under "tr1" namespace and this causes crash. Additionally do not use old libraries from extern. You dont need anything from extern to do game server working. libstdc++.so.6, libcxxrt.so.1 libc++.so.1 mixing of these libraries is not coool
  34. 1 point
    Wow! This was on my endless TODO List, now it's done, so cool, thank you!
  35. 1 point
    https://github.com/blackdragonx61/Compare-Item-Tooltip Video:
  36. 1 point
    Warrior Strange visual bug Hi, I have a problem, as you well know, there is this problem on all servers, including the official one. The problem is as follows. If a warrior gives magic to another player, and immediately standing still gives another skill, the second skill is not seen. Okay, no more theory, I've made a little video. Thanks, Sincerly, r00t3r
  37. 1 point
    Hello, first of all this not a release, it's just 1-5 second work. Today I found a problem on my server, it was lagging when we were in map in small distance and attacking a lot of monsters. There was like 1-3s delay and it was horrible. I know a lot of you know about it, dont write it here please. Open: PythonNetworkStreamPhaseGame.cpp Search for: const DWORD MAX_RECV_COUNT = You have different value there, I recommend edit it to 32 It will look like this: const DWORD MAX_RECV_COUNT = 32; Save it, build it, enjoy. Result for me: No delay when mount/unmount, no delay when adding new status points etc.
  38. 1 point
    Hey @Tatsumaru! Can you correct this? I would be grateful!
  39. 1 point
    Download https://i.imgur.com/XvtuWyy.gif[/img] Video: https://i.imgur.com/XvtuWyy.mp4
  40. 1 point
    Hi there. While cleaning out "my closet", I found this thing I developed between 2014-2015 - maybe(?) - for my, at that moment, server. Since it's now closed, and I won't use it, I'm sharing it with you guys. Note: Didn't do the scrollbar, wasn't needed for me, so yeah. Now, let's start with opening your locale_game.txt and adding these lines: QUESTCATEGORY_0 Main Quests QUESTCATEGORY_1 Sub Quests QUESTCATEGORY_2 Collect Quests QUESTCATEGORY_3 Levelup Quests QUESTCATEGORY_4 Scroll Quests QUESTCATEGORY_5 System Quests Alright, now find your characterwindow.py (uiscript?) and you can either comment Quest_Page children or simply remove them all. Moving on to your interfaceModule.py find this line self.BINARY_RecvQuest(index, name, "file", localeInfo.GetLetterImageName()) and replace it with self.wndCharacter.questCategory.RecvQuest(self.BINARY_RecvQuest, index, name) Ok, then we are at the most, let's say, difficult part of this. Open your uiCharacter.py and just as you did in your characterwindow.py, remove or simply comment any single line related to quests. You can just search for these vars: self.questShowingStartIndex self.questScrollBar self.questSlot self.questNameList self.questLastTimeList self.questLastCountList Once you did that, you just: # Find these lines self.soloEmotionSlot = self.GetChild("SoloEmotionSlot") self.dualEmotionSlot = self.GetChild("DualEmotionSlot") self.__SetEmotionSlot() # And add the following import uiQuestCategory self.questCategory = uiQuestCategory.QuestCategoryWindow(self.pageDict["QUEST"]) # Find this def OnUpdate(self): self.__UpdateQuestClock() # Replace it with def OnUpdate(self): self.questCategory.OnUpdate() And we're done with the client-side. I attached some extra elements needed (such as the main python file (uiQuestCategory.py) and some image resources). Remember to edit the path linked to these images in that file. For the server-side... Well, screw it, uploaded it too. Too lazy to write. It has only a new quest function (q.getcurrentquestname()) and a few things to add in your questlib.lua. Btw, not sure if you have it, but if not, just add this extra function in ui.Button() (ui.py - class Button). def SetTextAlignLeft(self, text, height = 4): if not self.ButtonText: textLine = TextLine() textLine.SetParent(self) textLine.SetPosition(27, self.GetHeight()/2) textLine.SetVerticalAlignCenter() textLine.SetHorizontalAlignLeft() textLine.Show() self.ButtonText = textLine #Äù½ºÆ® ¸®½ºÆ® UI¿¡ ¸ÂÃç À§Ä¡ ÀâÀ½ self.ButtonText.SetText(text) self.ButtonText.SetPosition(27, self.GetHeight()/2) self.ButtonText.SetVerticalAlignCenter() self.ButtonText.SetHorizontalAlignLeft() Forgot the source part, fml, here it is. Add it to your questlua_quest.cpp. int quest_get_current_quest_name(lua_State* L) { CQuestManager& q = CQuestManager::instance(); PC* pPC = q.GetCurrentPC(); lua_pushstring(L, pPC->GetCurrentQuestName().c_str()); return 1; } void RegisterQuestFunctionTable() { luaL_reg quest_functions[] = { { "getcurrentquestname", quest_get_current_quest_name}, { NULL, NULL } }; CQuestManager::instance().AddLuaFunctionTable("q", quest_functions); } Now, finally, have fun and bye! questcategory.7z server-side.7z
  41. 1 point
  42. 1 point
    This is the post with number 100.000 Congrats for 100.000 POSTS
  43. 1 point
    When item materials are removed from the refinment process the source item that is beeing refined also get's removed since it's apart of the required item list and this is what causes the game core to crash after any instance like warping. In order to fix this, we can check the source item beeing refined by position, simply by creating a new argument for the function RemoveSpecifyItem with the source item's cell position. char_item.cpp char.h Preview of fix: https://i.imgur.com/9xgfhK8.gifv
  44. 1 point
    Hi m2dev, I release my modifications of game core. 0x01.) Here are "some" new questfunctions to you ^^ If either of them is already public I'm sorry :> but these works perfectly. A short list of them: * Item module: - get_flag | Return: Integer | Args: None - get_wearflag | Return: Integer | Args: None - get_antiflag | Return: Integer | Args: None - has_antiflag | Return: Boolean | Args: int Antiflag - get_refine_set | Return: Integer | Args: None - get_limit | Return: Table1 | Args: byte LimitIndex[0..1] - get_apply | Return: Table1 | Args: byte ApplyIndex[0..2] - get_applies | Return: Table2 | Args: None - get_refine_materials | Return: Table3 | Args: None - get_addon_type | Return: Integer | Args: None - dec | Return: Nil | Args: None or byte Count - inc | Return: Nil | Args: None or byte Count - add_attribute | Return: Boolean | Args: None - get_attribute | Return: Table1 | Args: byte AttrIndex[0..4] - set_attribute | Return: Boolean | Args: byte AttrIndex[0..4], byte AttrType[1..94], short AttrValue[-32768..32767] - change_attribute | Return: Boolean | Args: None - add_rare_attribute | Return: Boolean | Args: None - get_rare_attribute | Return: Table1 | Args: byte AttrIndex[0..1] - set_rare_attribute | Return: Boolean | Args: byte AttrIndex[0..1], byte AttrType[1..94], short AttrValue[-32768..32767] - change_rare_attribute | Return: Boolean | Args: None - equip | Return: Boolean | Args: byte EquipCell[0..32] - set_count | Return: Nil | Args: byte/short Count(short with increased item stack number) Returning item table-structures: Table1 = { -- Type, Value 1, 2000 } Table2 = { -- [idx] = {Type, Value} -- Triton sword+9: [0] = { 7, 30 }, [1] = { 22, 12 }, [2] = { 17, 12 } } Table3 = { -- Poison sword+8(refineSet:27): material_count = 2, materials = { -- { Vnum, Count } { 30091, 2 }, { 27994, 1 } }, cost = 150000, prob = 10, } * NPC module: - get_level | Return: Integer | Args: None - get_name | Return: String | Args: None - get_type | Return: Byte | Args: None - get_rank | Return: Byte | Args: None - is_metin | Return: Boolean | Args: None - is_boss | Return: Boolean | Args: None - show_effect_on_target | Return: Boolean | Args: string EffectRealPath - get_ip | Return: String | Args: None - get_client_version | Return: String | Args: None - get_job | Return: Byte | Args: None - get_pid | Return: Integer | Args: None - get_exp | Return: Long | Args: None * PC module: - get_mount_vnum | Return: Integer | Args: None - get_point | Return: Integer | Args: byte PointNumber - get_real_point | Return: Integer | Args: byte PointNumber - show_effect | Return: Boolean | Args: string EffectRealPath - disconnect_with_delay | Return: Nil | Args: int Delay - get_max_level | Return: Integer | Args: None - get_ip | Return: String | Args: None - get_client_version | Return: String | Args: None - kill | Return: Nil | Args: None * Game module: - drop_item_and_select | Return: Nil | Args: int Vnum, byte/short Count=1, bool HasOwnership=false, short OwnershipTime=180 Example call: game.drop_item_and_select(19, 1, true, 30); item.set_attribute(0, apply.CRITICAL_PCT, 10) * Pet module: - is_mine | Return: Boolean | Args: None * Global: - purge_vid | Return: Nil | Args: int Vid Here are the codes: questlua_item.cpp questlua_npc.cpp questlua_pc.cpp questlua_game.cpp questlua_pet.cpp questlua_global.cpp 0x02.) Two GM commands: - "/kill_all" -> Kill all players inside your view-range/horizon - "/drop_item" -> Drop an item from arg1, or drop all items from range(arg1, arg2) Commands: Clientside version of kill_all: 0x03.) refine_proto reloading without server restart. Extend your "/reload Proto" command with the refine_proto reloading with this code parts: - Open your db/src/ClientManager.cpp file and replace your "void CClientManager::QUERY_RELOAD_PROTO()" function to this: void CClientManager::QUERY_RELOAD_PROTO() { if (!InitializeTables()) { sys_err("QUERY_RELOAD_PROTO: cannot load tables"); return; } for (TPeerList::iterator i = m_peerList.begin(); i != m_peerList.end(); ++i) { CPeer * tmp = *i; if (!tmp->GetChannel()) continue; tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0, sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() + sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() + sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() + sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size() + sizeof(WORD) + sizeof(TRefineTable) * m_iRefineTableSize); tmp->EncodeWORD(m_vec_skillTable.size()); tmp->Encode(&m_vec_skillTable[0], sizeof(TSkillTable) * m_vec_skillTable.size()); tmp->EncodeWORD(m_vec_banwordTable.size()); tmp->Encode(&m_vec_banwordTable[0], sizeof(TBanwordTable) * m_vec_banwordTable.size()); tmp->EncodeWORD(m_vec_itemTable.size()); tmp->Encode(&m_vec_itemTable[0], sizeof(TItemTable) * m_vec_itemTable.size()); tmp->EncodeWORD(m_vec_mobTable.size()); tmp->Encode(&m_vec_mobTable[0], sizeof(TMobTable) * m_vec_mobTable.size()); tmp->EncodeWORD(m_iRefineTableSize); tmp->Encode(m_pRefineTable, sizeof(TRefineTable) * m_iRefineTableSize); } } - Then open game/src/refine.cpp and replace this function: "bool CRefineManager::Initialize(TRefineTable * table, int size)" to this: bool CRefineManager::Initialize(TRefineTable * table, int size) { if (!m_map_RefineRecipe.empty()) m_map_RefineRecipe.clear(); for (int i = 0; i < size; ++i, ++table) { sys_log(0, "REFINE %d prob %d cost %d", table->id, table->prob, table->cost); m_map_RefineRecipe.insert(std::make_pair(table->id, *table)); } sys_log(0, "REFINE: COUNT %d", m_map_RefineRecipe.size()); return true; } - If you are done with these, open game/src/input_db.cpp and extend this event "void CInputDB::ReloadProto(const char * c_pData)" with this: /* * REFINE */ wSize = decode_2bytes(c_pData); c_pData += 2; sys_log(0, "RELOAD: REFINE: %d", wSize); if (wSize) { CRefineManager::instance().Initialize((TRefineTable *) c_pData, wSize); c_pData += wSize * sizeof(TRefineTable); } - Done. 0x04.) kill quest trigger fix (when kill / when race.kill) With this change you can use every kill methods with mobs and players and runs by once per kills. Examples: when 101.kill begin -> Works when you are killing Wild dogs. when kill begin -> Works with mobs and players too. when kill with npc.is_pc() begin -> Works with players only. when kill with npc.is_pc() == false begin -> Works with monsters only. when kill with npc.get_race() == 102 begin -> Works when you hunt Wolf. I tested with these codes: when kill begin if npc.is_pc() then chat("kill pc") end if npc.get_race() > 100 then chat("kill by race: "..tostring(npc.race)) end end when kill with npc.is_pc() begin chat("kill with npc.is_pc") end when kill with npc.get_race() == 102 begin chat("kill with npc.get_race 102") end when 101.kill begin chat("101.kill") end Follow these steps to fix it: - Open game/src/questmanager.h and search for this: "void Kill(unsigned int pc, unsigned int npc);" replace to: "void Kill(unsigned int pc, unsigned int npc, unsigned int pc2 = 0);" - Save&Close, open game/src/questmanager.cpp and search this function: "void CQuestManager::Kill(unsigned int pc, unsigned int npc)" - and replace to this: void CQuestManager::Kill(unsigned int pc, unsigned int npc, unsigned int pc2) { //m_CurrentNPCRace = npc; PC * pPC; sys_log(0, "CQuestManager::Kill QUEST_KILL_EVENT (pc=%d, npc=%d, pc2=%d)", pc, npc, pc2); if ((pPC = GetPC(pc))) { if (!CheckQuestLoaded(pPC)) return; /* [hyo] ¸÷ kill˝Ă Áßşą Ä«żîĆĂ ŔĚ˝´ °ü·ĂÇŃ ĽöÁ¤»çÇ× quest scriptżˇ when 171.kill begin ... µîŔÇ ÄÚµĺ·Î ŔÎÇĎż© ˝şĹ©¸łĆ®°ˇ Ăł¸®µÇľú´ő¶óµµ ąŮ·Î returnÇĎÁö ľĘ°í ´Ů¸Ą °Ë»çµµ ĽöÇŕÇϵµ·Ď şŻ°ćÇÔ. (2011/07/21) */ // call script if (npc > 0 && pc2 == 0) m_mapNPC[npc].OnKill(*pPC); LPCHARACTER ch = GetCurrentCharacterPtr(); LPPARTY pParty = ch->GetParty(); LPCHARACTER leader = pParty ? pParty->GetLeaderCharacter() : ch; if (leader) { m_pCurrentPartyMember = ch; if (m_mapNPC[npc].OnPartyKill(*GetPC(leader->GetPlayerID()))) return; pPC = GetPC(pc); } LPCHARACTER victim = CHARACTER_MANAGER::instance().FindByPID(pc2); if (victim && victim->IsPC() && m_mapNPC[QUEST_NO_NPC].OnKill(*pPC)) return; else if (m_mapNPC[QUEST_NO_NPC].OnKill(*pPC)) return; if (leader) { m_pCurrentPartyMember = ch; m_mapNPC[QUEST_NO_NPC].OnPartyKill(*GetPC(leader->GetPlayerID())); } } else sys_err("QUEST: no such pc id : %d", pc); } - Save&Close, open game/src/char_battle.cpp and search this call: "quest::CQuestManager::instance().Kill(pkKiller->GetPlayerID(), quest::QUEST_NO_NPC)" - and replace to this: "quest::CQuestManager::instance().Kill(pkKiller->GetPlayerID(), quest::QUEST_NO_NPC, GetPlayerID());" - Done. 0x05.) ImmuneBug fix. I know there are some fixes but this is a working solution.. Everything inside two functions into item.cpp file by names: "CItem::EquipTo" and "CItem::Unequip". Every two functions are containing this sh*!&t: DWORD dwImmuneFlag = 0; for (int i = 0; i < WEAR_MAX_NUM; ++i) if (m_pOwner->GetWear(i)) SET_BIT(dwImmuneFlag, m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag); m_pOwner->SetImmuneFlag(dwImmuneFlag); Hm, you have to replace those to this: DWORD dwImmuneFlag = 0; LPITEM item = NULL; for (int i = 0; i < WEAR_MAX_NUM; ++i) { if (item=m_pOwner->GetWear(i)) { if (item->GetImmuneFlag() != 0) SET_BIT(dwImmuneFlag, item->GetImmuneFlag()); if (item->GetAttributeCount() > 0) { if (item->HasAttr(APPLY_IMMUNE_STUN)) SET_BIT(dwImmuneFlag, IMMUNE_STUN); if (item->HasAttr(APPLY_IMMUNE_SLOW)) SET_BIT(dwImmuneFlag, IMMUNE_SLOW); if (item->HasAttr(APPLY_IMMUNE_FALL)) SET_BIT(dwImmuneFlag, IMMUNE_FALL); } } } m_pOwner->SetImmuneFlag(dwImmuneFlag); - Done. 0x06.) Finished uiQuest.py selection by keyboard-usage with "Next" and "Prev" buttons. Test-example: when 9010.chat."TEST selection pages" begin local sTab = { "01","02","03","04","05","06","07","08","09","10", "11","12","13","14","15","16","17","18","19","20", "Exit"--to make exit by Escape key } local s=select_table(sTab) if s==table.getn(sTab) then return end chat("You'r choice: sTab["..tostring(s).."] -> "..sTab[s]) end Here you can download the full uiquest.py file from my client: Download 0x07.) Little SQL-Script: SELECT log.log.time AS "When", player.player.`name` AS Who, log.log.how AS WhatDid, log.log.what AS ItemID, log.log.vnum AS ItemVnum, player.item_proto.locale_name AS ItemName, player.item.count AS Count, player.item.Socket0, player.item.Socket1, player.item.Socket2, player.item.AttrType0, player.item.AttrValue0, player.item.AttrType1, player.item.AttrValue1, player.item.AttrType2, player.item.AttrValue2, player.item.AttrType3, player.item.AttrValue3, player.item.AttrType4, player.item.AttrValue4, player.item.AttrType5, player.item.AttrValue5, player.item.AttrType6, player.item.AttrValue6 FROM log.log INNER JOIN player.player ON log.log.who = player.player.id INNER JOIN player.item ON log.log.what = player.item.id INNER JOIN player.item_proto ON log.log.vnum = player.item_proto.vnum WHERE log.how in ("EXCHANGE_GIVE", "EXCHANGE_TAKE", "DROP", "SAFEBOX PUT", "SAFEBOX GET", "DEAD_DROP") AND player.`name` = "Xeriesey"; * You have to give a name where you can see Xeriesey ^-^ Result of query: I hope you like it. If you have any questions or find an error/mistake, just post a message into this thread and I will try to make answer when I'll be online. ps.: Sorry for my bad English. "(" + "c" + ")" == © -> F**k Changelog: - 2014.09.22. 16:29 / 04:29 PM ~ Added forgotten include to questlua_npc.cpp. - 2014.09.22. 16:48 / 04:48 PM ~ Added more forgotten things :S - 2014.09.27. 13:08 / 01:08 PM ~ SQL syntax fix With Regards, P3NG3R
  45. 1 point
    #Update V2(You need Emoji Textline) Custom Sort:Change item.h
  46. 1 point
    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
  47. 1 point
    English: Hello, today I want to share with you my quest. What it does? It changes your attributes on an item if you place it on a certain NPC (in this case "Handu-Up") and puts best in slot PVP attributes. What this quest can't do (yet): Differentiate between Average Damage, Skill damage - type weapons like Poison Sword (If someone could show me how to exit a FOR-Loop in LUA I might be ablte to do it) #added Change attributes on other items than your "standard" equipement like costumes etc. Keep in mind that I just wanted to look back into quest scripting so I it's not perfect written by any means but it works and I think some people will have a use for it. Here is the Code (Downloadable as attachement down below): German: auto_boni_easy.quest
  48. 1 point
    Webzen started to code new functions for everything. (They're refreshing the stuff slowly too). Today I'll give an update about SendQuestInputStringPacket. This packet is often used by r34083 to make new systems with communication. This function is only work when the string size is big than 64. New function; net.SendQuestInputLongStringPacket I explained everything in the rar file (NewFunction.rar) Kind Regards ~ Ken
  49. 1 point
    input_main.cpp CInputMain::AnswerMakeGuild if (ch->GetGold() < 200000) return; Replace if (ch->GetGold() < 200000) ch->ChatPacket(CHAT_TYPE_INFO, "You don't have 200000 yang"); return; if (ch->GetLevel() < 40) ch->ChatPacket(CHAT_TYPE_INFO, "You don't have 40lv+ "); return;
  50. 1 point
    Hi all, i did some changes to the official blazingpurgatory quest to fix the errors of the mob count and timers. quest flame_dungeon begin state start begin when 20394.click with pc.get_level() >= 90 begin pc.give_item2(71175, 1) set_state(run) end end state run begin function setting() return { ["bossroom_entry_pos"] = {8109,6867}, ["boss_pos"] = {686,637}, ["doors_pos"] = { {320,394}, {293,359}, {333,321}, {378,320}, {400,355}, {394,401} }, ["idoors_pos"] = { {268,447}, {234,359}, {300,264}, {454,217}, {470,355}, {467,469} }, ["doors_dir"] = {135,90,210,152,90,223}, ["idoors_dir"] = {135,90,210,135,90,239}, ["dungeon_entry_pos"] = {7766, 6719},-- ??? ?? ???? ? ["DUNGEON_MAN_bpos"] = {690,722}, ["DUNGEON_MAN_pos"] = {354,362}, ["LEVEL2_STONE_pos"] = {195,352}, ["LEVEL4_TARGET_pos"] = {470,175}, ["LEVEL5_STONE_pos"] = { {486, 345}, {511, 336}, {525, 349}, {521, 365}, {503, 372}, {486, 365}, {500, 354} }, ["LEVEL6_TARGET_pos"] = {511,480}, ["outside_entry_pos"] = {5980,7075}, --??????? ??? ? } end function is_flamed(idx) -- ???? ??? ?? return idx >= 351 * 10000 and idx < (351 + 1) *10000 end function make_dungeon() -- ?? ??? local setting = flame_dungeon.setting() d.new_jump_party(351, setting.dungeon_entry_pos[1], setting.dungeon_entry_pos[2]) d.regen_file("data/dungeon/flame_dungeon/npc.txt") d.setf("level",0) for i=1,6 do d.set_unique("door"..i, d.spawn_mob_ac_dir(20387, setting.doors_pos[i][1], setting.doors_pos[i][2],setting.doors_dir[i])) end for i=1,6 do d.set_unique("idoor"..i, d.spawn_mob_ac_dir(20388, setting.idoors_pos[i][1], setting.idoors_pos[i][2],setting.idoors_dir[i])) end d.setf("clear_count",0) d.setf("started",0) d.setf("dungeon_enter",0) -- ????? ?????? // ??? : 0 ?? : 1 // ??? ??????? ?? ?? d.setf("counter_11", 180) d.setf("counter_13", 180) end function go_boss() -- ??? ?? local setting = flame_dungeon.setting() if pc.get_level() < 104 then --???? say("Seu nível não é suficiente para continuar.[ENTER]Volte, quando tiver atingido pelo menos nível 104.") return else --if pc.getf("main_quest_flame_lv103", "__status")==main_quest_flame_lv103.__COMPLETE__ then -- ????? ?? say("Será que você quer avançar[ENTER]para conhecer o seu destino?") local warp = select("Avançar","Talvez mais tarde") if warp == 1 then d.setf("level",17) d.jump_all(setting.bossroom_entry_pos[1],setting.bossroom_entry_pos[2]) d.set_regen_file ("data/dungeon/flame_dungeon/".."fd_fild_boss.txt") d.spawn_mob(6091,setting.boss_pos[1],setting.boss_pos[2]) end --else -- say("Pode apenas avançar quando tiver[ENTER]concluído a missão de nível 103.") -- return --end end end function level_clear() -- ?? ???, ?????, ????? d.setf("level",0) d.clear_regen() d.purge_area(750000,620000,817400,689400) -- ??? -- d.purge() ???? end function clear_timer(inx) -- ??? ???? clear_server_timer ("flame_dungeon_0m_left_timer", inx) clear_server_timer ("flame_dungeon_1m_left_timer", inx) clear_server_timer ("flame_dungeon_5m_left_timer", inx) clear_server_timer ("flame_dungeon_10m_left_timer", inx) clear_server_timer ("flame_dungeon_15m_left_timer", inx) clear_server_timer ("flame_dungeon_30m_left_timer", inx) clear_server_timer ("flame_dungeon_45m_left_timer", inx) clear_server_timer ("flame_dungeon_ticket_remove", inx) end when login begin local idx = pc.get_map_index() local setting = flame_dungeon.setting() if idx == 351 then --pc.warp(setting.outside_entry_pos[1]*100, setting.outside_entry_pos[2] * 100, 62) elseif flame_dungeon.is_flamed(idx) then -- ?? ??, ??? ?? ?? ------------------------------------------------------------------------------------------------------------------------------------------------------ --??? ??? ???? ???? ???? ?????? ?? ?? ??? ????. ???? ??? ?? ???? ???? ?? ?? ??? ??? ??. --???? ???? ?? ?? ?? ??? ??? ??, ???? ??? ??? ????? ?? ??? ????? ???? ??? ??? ??? ??. ------------------------------------------------------------------------------------------------------------------------------------------------------ --pc.set_warp_location(62, setting.outside_entry_pos[1] , setting.outside_entry_pos[2]) -- ?? ??? ? ??? ???? local ticketGroup = {get_special_item_group (10033)} if d.getf("dungeon_enter") == 0 then -- ???? ??? local canPass = false for i=1, table.getn(ticketGroup),2 do if pc.count_item(ticketGroup[i]) >= ticketGroup[i+1] then canPass = true break end end if get_global_time() - pc.getf("flame_dungeon","exit_time") < 30 * 60 then -- ??????? ???? notice_multiline("O período de espera para re-entrada na[ENTER]Fortaleza Dragão Vermelho ainda não expirou.",d.notice) say("O período de espera para re-entrada na[ENTER]Fortaleza Dragão Vermelho ainda não expirou.") timer("flame_dungeon_warp_timer", 5) elseif not canPass then notice_multiline("Apenas um grupo pode invadir a Fortaleza Dragão[ENTER]Vermelho. Além disso, é necessário uma[ENTER]autorização para entrar.",d.notice) say("Eu posso deixar você entrar se[ENTER]você tiver em posse de um passe.") timer("flame_dungeon_warp_timer", 5) elseif pc.get_level() < 100 then notice_multiline("O nível de todos os membros do grupo deve ser[ENTER]pelo menos 100. Caso contrário, eu não posso[ENTER]deixar continuar.",d.notice) say("Eu vou deixar passar se todos os membros do grupo,[ENTER]tiverem no mínimo nível 100.") timer("flame_dungeon_warp_timer", 5) end elseif pc.getf("flame_dungeon","ticket_delete") == 0 then -- ????? ??? ??????? for i=1, table.getn(ticketGroup),2 do if pc.count_item(ticketGroup[i]) >= ticketGroup[i+1] then pc.remove_item(ticketGroup[i], ticketGroup[i+1]) break end end pc.setf("flame_dungeon","ticket_delete",1) end else pc.setf("flame_dungeon","ticket_delete",0) end end when flame_dungeon_warp_timer.timer begin local setting = flame_dungeon.setting() pc.warp(setting.outside_entry_pos[1]*100, setting.outside_entry_pos[2] * 100, 62) end when logout begin local idx = pc.get_map_index() if flame_dungeon.is_flamed(idx) then if d.getf("dungeon_enter") == 1 then -- ???? ?? ?? ? ???? pc.setf("flame_dungeon","exit_time",get_global_time()) -- ???? ???? ??? ??? ??, ?? ???? ??? or ?? ???? ??? end end end when 20394.chat."Fortaleza Dragão Vermelho" begin local setting = flame_dungeon.setting() if party.is_party() then local party_check = 0 if d.find(party.getf("dungeon_index")) then party_check = (d.getf_from_map_index("party_leader_pid", party.getf("dungeon_index")) == party.get_leader_pid()) end if d.find(party.getf("dungeon_index")) and party_check then if get_global_time() - pc.getf("flame_dungeon","exit_time") < 5 * 60 then -- ?? ?? 5? ?? local dungeon_level = d.getf_from_map_index("level", party.getf("dungeon_index")) if dungeon_level == 17 then -- ?? pc.warp(setting.bossroom_entry_pos[1] * 100, setting.bossroom_entry_pos[2] * 100, party.getf("dungeon_index")) else pc.warp(setting.dungeon_entry_pos[1] * 100, setting.dungeon_entry_pos[2] * 100, party.getf("dungeon_index")) end else -- 5? ???? ? ?? ?? say_title(mob_name(20394)) say("Você esteve mais de cinco minutos fora da[ENTER]Fortaleza Dragão Vermelho e[ENTER]agora não pode entrar.") end else local pids = {party.get_member_pids()} local noTicketMembers = {} local notEnoughLevelMembers = {} local ticketCheck = true local levelCheck = true local ticketGroup = {get_special_item_group (10033)} for i, pid in next, pids, nil do q.begin_other_pc_block(pid) local canPass = false for idx=1, table.getn(ticketGroup),2 do if pc.count_item(ticketGroup[idx]) >= ticketGroup[idx+1] then canPass = true break end end if not canPass then table.insert(noTicketMembers, pc.get_name()) ticketCheck = false end if pc.level < 100 then table.insert(notEnoughLevelMembers, pc.get_name()) levelCheck = false end q.end_other_pc_block() end if not ticketCheck then say_title(mob_name(20394)) say("Atenção! Para entrar na Fortaleza Dragão[ENTER]Vermelho, exige-se que cada membro do grupo[ENTER]tenha um passe para entrar. Os membros que não[ENTER]têem passe são:") for i, name in next, noTicketMembers, nil do say(color(1,1,0), " "..name) end if levelCheck then return else wait() end end if not levelCheck then say_title(mob_name(20394)) say("Atenção! Para entrar na Fortaleza Dragão[ENTER]Vermelho, todos os membros do grupo devem ter[ENTER]nível 100, os jogadores que actualmente não[ENTER]atingiram o nível são:") for i, name in next, notEnoughLevelMembers, nil do say(color(1,1,0), " "..name) end return end if party.is_leader() then say("Você quer entrar na Fortaleza Dragão Vermelho?") local warp = select("Entrar","Talvez mais tarde") if warp == 1 then if party.is_map_member_flag_lt("exit_time", get_global_time() - 30 * 60 ) then flame_dungeon.make_dungeon() else say("O período de espera para re-entrada na[ENTER]Fortaleza Dragão Vermelho ainda não expirou.") end end party.setf("flame_dungeon_boss_kill_count", 0) else say("Apenas o líder do grupo pode solicitar a entrada.") end end else say("Eu aprecio a sua coragem, mas só você[ENTER]não pode entrar na Fortaleza Dragão Vermelho.[ENTER]Defina um grupo forte e eu vou conceder a entrada.") end end when 20394.chat."Test : Teleporte para instancia" with pc.is_gm() begin -- ???? local setting = flame_dungeon.setting() pc.setf("flame_dungeon","fdRtest",1) pc.warp( setting.dungeon_entry_pos[1]*100, setting.dungeon_entry_pos[2]*100, 351) end when 20394.chat."TEST : Init time limit init" with pc.is_gm() begin -- ???? pc.setf("flame_dungeon","exit_time",get_global_time()-1800) say("Done") end when 20385.chat."Test : Informação" with pc.is_gm() begin -- ???? say("monstros_11 : "..d.getf("counter_11")) say("monstros_13 : "..d.getf("counter_13")) say("server time : "..get_server_timer_arg()) say("número de monstros : "..d.count_monster()) say("level : "..d.getf("level")) say("Dmap index : "..d.get_map_index()) say("Pmap index : "..pc.get_map_index()) say("access limit : "..pc.getf("flame_dungeon","exit_time")) say("global time : "..get_global_time()) if flame_dungeon.is_flamed(d.get_map_index()) then say("in dungeon") -- is_flamed ?? ?? end if d.is_unique_dead("stone1") then say("stone1 is dead") else say("stone1 is not dead") end end when 20385.chat."ativar instancia" with pc.is_gm() begin -- ???? say("??? ???") flame_dungeon.clear_timer(d.get_map_index()) flame_dungeon.make_dungeon() end when 20385.chat."Test : Boss Room" with pc.is_gm() begin -- ???? flame_dungeon.go_boss() end when 20385.chat."testar sair" with pc.is_gm() begin -- ???? ??? ?? ? ?? ??? local setting = flame_dungeon.setting() say("??? ????????") local warp = select("Sim","Não") if warp == 1 then pc.warp(setting.outside_entry_pos[1]*100, setting.outside_entry_pos[2] * 100, 62) end end when flame_dungeon_45m_left_timer.timer begin notice_multiline(string.format("Tempo restante: %d minuto(s)", 45),d.notice) notice_multiline("Depois do tempo, o grupo é teleportado[ENTER]para fora da fortaleza.",d.notice) timer("flame_dungeon_30m_left_timer", 15*60) end when flame_dungeon_30m_left_timer.timer begin notice_multiline(string.format("Tempo restante: %d minuto(s)", 30),d.notice) notice_multiline("Depois do tempo, o grupo é teleportado[ENTER]para fora da fortaleza.",d.notice) timer("flame_dungeon_15m_left_timer", 15*60) end when flame_dungeon_15m_left_timer.timer begin notice_multiline(string.format("Tempo restante: %d minuto(s)", 15),d.notice) notice_multiline("Depois do tempo, o grupo é teleportado[ENTER]para fora da fortaleza.",d.notice) timer("flame_dungeon_5m_left_timer", 10*60) end when flame_dungeon_5m_left_timer.timer begin notice_multiline(string.format("Tempo restante: %d minuto(s)", 5),d.notice) notice_multiline("Depois do tempo, o grupo é teleportado[ENTER]para fora da fortaleza.",d.notice) timer("flame_dungeon_1m_left_timer", 4*60) end when flame_dungeon_1m_left_timer.timer begin notice_multiline(string.format("Tempo restante: %d minuto(s)", 1),d.notice) notice_multiline("Depois do tempo, o grupo é teleportado[ENTER]para fora da fortaleza.",d.notice) timer("flame_dungeon_0m_left_timer", 60) end when flame_dungeon_0m_left_timer.timer begin local setting = flame_dungeon.setting() notice_multiline("Seu tempo expirou. Dentro de 10 segundos você[ENTER]será teleportado para os portões da fortaleza.",d.notice) notice_multiline("Em dez segundos, o grupo é teleportado[ENTER]da Fortaleza Dragão Vermelho.",d.notice) timer("exit_dungeon",10) end when 20385.chat."O despertar do Am-heh" with npc.lock() begin -- '0x'? x?? ?? ??? ?? ? ?? ?? , '1x'? x?? ?? ??? ??? local setting = flame_dungeon.setting() if d.getf("started") == 0 then say("O Am-heh foi despertado.") say("Os portões da Fortaleza Dragão Vermelho[ENTER]seram fechados dentro de uma hora.") wait() d.setf("started",1) timer("flame_dungeon_45m_left_timer",15*60) notice_multiline("Tempo restante: 60 Minuto(s) ",d.notice) notice_multiline("Depois do tempo, o grupo é teleportado[ENTER]para fora da fortaleza.",d.notice) local pids = {party.get_member_pids()} local ticketGroup = {get_special_item_group (10033)} for i, pid in next, pids, nil do q.begin_other_pc_block(pid) local canPass = false for idx=1, table.getn(ticketGroup),2 do if pc.count_item(ticketGroup[idx]) >= ticketGroup[idx+1] then canPass = true pc.remove_item(ticketGroup[idx], ticketGroup[idx+1]) break end end if not canPass then pc.warp(setting.outside_entry_pos[1]*100, setting.outside_entry_pos[2] * 100, 62) end q.end_other_pc_block() end d.setqf2("flame_dungeon","ticket_delete",1) d.setf("dungeon_enter",1) party.setf("dungeon_index", d.get_map_index()) d.setf("party_leader_pid", party.get_leader_pid()) end if d.getf("level") < 7 then --???? ??? if d.getf("clear_count") == 6 then -- ? ??? ??? ??? d.setf("level",7) else local rand = number(1,6)--???? ????? ?? ???? ?? ?? ?????? ??? local setlev = 0 d.setf("level",7) -- ?? ?? ??? ?? ??? ?????? ??? ????? ???? for i=1,50 do setlev = setlev + 1 if setlev > 6 then setlev = 1 end if not d.is_unique_dead("door"..setlev) then rand = rand - 1 if rand == 0 then d.setf("level",setlev) d.setf("clear_count",d.getf("clear_count")+1) break end end end end end if d.getf("level") == 1 then say("Missão: Aventure-se no anel de demônios[ENTER]e surja como vencedor.") notice_multiline("Missão: Aventure-se no anel de demônios[ENTER]e surja como vencedor.",d.notice) d.kill_unique("door1") d.kill_unique("idoor1") d.setf("level",11) local counter_11 = 180 d.regen_file ("data/dungeon/flame_dungeon/".."fd_a.txt") elseif d.getf("level") == 11 then say("Não foram derrotados todos os demônios.") say_title("Restantes: ", counter_11) elseif d.getf("level") == 2 then say("Tarefa: Encontre a engrenagem de ouro,[ENTER]substituindo o mecanismo oculto[ENTER]na estela de Isfet.") notice_multiline("Tarefa: Encontre a engrenagem de ouro, substituindo [ENTER] o mecanismo oculto na estela de Isfet.",d.notice) d.spawn_mob(20386, setting.LEVEL2_STONE_pos[1], setting.LEVEL2_STONE_pos[2]) -- ??? ?? d.kill_unique("door2") d.kill_unique("idoor2") d.set_regen_file ("data/dungeon/flame_dungeon/".."fd_b.txt") d.setf("level",12) elseif d.getf("level") == 12 then say("O mecanismo na estela de Isfet só pode ser[ENTER]acionado com a roda de engrenagem de ouro.[ENTER]Volta quando a tarefa foi cumprida.") elseif d.getf("level") == 3 then say("Missão: Aventure-se no anel de demônios e[ENTER]surja como vencedor.") notice_multiline("Missão: Aventure-se no anel de demônios e[ENTER]surja como vencedor.",d.notice) d.kill_unique("door3") d.kill_unique("idoor3") d.setf("level",13) local counter_13 = 180 d.regen_file ("data/dungeon/flame_dungeon/".."fd_c.txt") elseif d.getf("level") == 13 then say("Não foram derrotados todos os demônios.") say_title("Restantes: ", counter_13) elseif d.getf("level") == 4 then -- 474 178 say("Tarefa: Derrote Ignator, guarda das brasas.") notice_multiline("Tarefa: Derrote Ignator, guarda das brasas.",d.notice) d.setf("level",14) d.kill_unique("door4") d.kill_unique("idoor4") d.set_regen_file ("data/dungeon/flame_dungeon/".."fd_d.txt") d.spawn_mob(6051,setting.LEVEL4_TARGET_pos[1],setting.LEVEL4_TARGET_pos[2] ) -- ????? ?? elseif d.getf("level") == 14 then say("Ignator ainda não foi derrotado.[ENTER]Fortaleça-se ou receberá a condenação eterna.[ENTER]Volte se a tarefa for cumprida.") elseif d.getf("level") == 5 then -- 510 355 say("Missão: Procurar as Pedras de Maat e coloca-as[ENTER]na ordem correta nas 7 estelas de Isfet.") say("Se usares a Pedra de Maat na estela errada,[ENTER]a pedra irá partir-se.") notice_multiline("Missão: Procurar as Pedras de Maat e coloca-as[ENTER]na ordem correta nas 7 estelas de Isfet.",d.notice) notice_multiline("Se usares a Pedra de Maat na estela errada,[ENTER]a pedra irá partir-se.",d.notice) d.kill_unique("door5") d.kill_unique("idoor5") d.setf("level",15) d.set_regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") local vis = { 0,0,0,0,0,0,0} for i=1,7 do vis[i] = 0 end for i = 1, 7 do -- ???? ??? local ran = number(1,7) local st = 0 for j = 1, 50 do st = st + 1 if st > 7 then st = 1 end if vis[st] == 0 then ran = ran - 1 if ran == 0 then vis[st] = 1 d.set_unique("stone5_"..st, d.spawn_mob(20386, setting.LEVEL5_STONE_pos[i][1], setting.LEVEL5_STONE_pos[i][2])) break end end end end elseif d.getf("level") == 15 then say("Errar é humano! Portanto, escolha com sabedoria[ENTER]para resolver o mistério. Volte se a tarefa[ENTER]for cumprida.") elseif d.getf("level") == 6 then -- 507 490 say("Tarefa: Só quem não tem medo do calor abrasador,[ENTER]irá destruir a Metin do purgatório.") notice_multiline("Tarefa: Só quem não tem medo do calor abrasador,[ENTER]irá destruir a Metin do purgatório.",d.notice) d.setf("level",16) d.kill_unique("door6") d.kill_unique("idoor6") d.set_regen_file ("data/dungeon/flame_dungeon/".."fd_f.txt") d.spawn_mob(8057, setting.LEVEL6_TARGET_pos[1],setting.LEVEL6_TARGET_pos[2]) -- ?????? ?? elseif d.getf("level") == 16 then say(" ") say("Vamos colocar a Metin do purgatório em cinzas.[ENTER]Volta se a tarefa for cumprida.") elseif d.getf("level") == 7 then flame_dungeon.go_boss() else say(" ") end npc.unlock() end when kill with flame_dungeon.is_flamed(pc.get_map_index()) and d.getf("level") == 11 begin -- 2?? ??? ?? ?? if d.getf("counter_11") == 0 then -- 1?? ??? ??? notice_multiline("Todos os demônios foram derrotados.",d.notice) notice_multiline("Fala com Am-heh para abrir um novo destino.",d.notice) flame_dungeon.level_clear() else d.setf("counter_11",d.getf("counter_11")-1) end end when kill with flame_dungeon.is_flamed(pc.get_map_index()) and d.getf("level") == 13 begin -- 2?? ??? ?? ?? if d.getf("counter_13") == 0 then -- 1?? ??? ??? notice_multiline("Todos os demônios foram derrotados.",d.notice) notice_multiline("Fala com Am-heh para abrir um novo destino.",d.notice) flame_dungeon.level_clear() else d.setf("counter_13",d.getf("counter_13")-1) end end when kill with flame_dungeon.is_flamed(pc.get_map_index()) and d.getf("level") == 12 begin -- 2?? ??? ?? ?? local i = number(1, 100) -- 100?? 1 ??? ???? if i == 1 then game.drop_item (30329, 1) end end when 20386.take with flame_dungeon.is_flamed(pc.get_map_index()) and item.vnum == 30329 and d.getf("level") == 12 begin -- 2?? ?? ???? local i = number(1, 5) -- 5?? 1 ??? ?? ?? if i == 1 then npc.purge() item.remove() notice_multiline("A estela de Isfet foi destruída.",d.notice) notice_multiline("Fala com Am-heh para abrir um novo destino.",d.notice) flame_dungeon.level_clear() else item.remove() say("Esta peça é falsa e foi destruida.[ENTER]Procura a original.") end end when 6051.kill with flame_dungeon.is_flamed(pc.get_map_index()) and d.getf("level") == 14 begin notice_multiline("Ignator, guarda das brasas, foi destruído.",d.notice) notice_multiline("Fala com Am-heh para abrir um novo destino.",d.notice) flame_dungeon.level_clear() end when kill with flame_dungeon.is_flamed(pc.get_map_index()) and d.getf("level") == 15 begin -- 5?? ??? ?? ?? local i = number(1, 30) -- 30?? 1 ??? ???? if i == 1 then game.drop_item (30330, 1) end end when 20386.take with flame_dungeon.is_flamed(d.get_map_index()) and item.vnum == 30330 and d.getf("level") == 15 begin -- 5?? ???? ???? local setting = flame_dungeon.setting() if npc.get_vid() == d.get_unique_vid("stone5_1") then -- ??? ?? ????? ? ?? ????? ???? ???? npc.purge() item.remove() say("Essa foi uma escolha sábia.[ENTER]Destrua agora a próxima estela.") d.setf("stonekill",2) -- 2? ?? ??? if d.count_monster() < 100 then d.regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") end elseif npc.get_vid() == d.get_unique_vid("stone5_2") then if d.getf("stonekill") == 2 then -- 2??? ?? ??? 2???? ??? ??? ? npc.purge() item.remove() say("Essa foi uma escolha sábia.[ENTER]Destrua agora a próxima estela.") d.setf("stonekill",3) if d.count_monster() < 100 then d.regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") end else item.remove() say("Ordem errada. A Pedra de Maat foi destruída.") end elseif npc.get_vid() == d.get_unique_vid("stone5_3") then if d.getf("stonekill") == 3 then npc.purge() item.remove() say("Essa foi uma escolha sábia.[ENTER]Destrua agora a próxima estela.") d.setf("stonekill",4) if d.count_monster() < 100 then d.regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") end else item.remove() say("Ordem errada. A Pedra de Maat foi destruída.") end elseif npc.get_vid() == d.get_unique_vid("stone5_4") then if d.getf("stonekill") == 4 then npc.purge() item.remove() say("Essa foi uma escolha sábia.[ENTER]Destrua agora a próxima estela.") d.setf("stonekill",5) if d.count_monster() < 100 then d.regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") end else item.remove() say("Ordem errada. A Pedra de Maat foi destruída.") end elseif npc.get_vid() == d.get_unique_vid("stone5_5") then if d.getf("stonekill") == 5 then npc.purge() item.remove() say("Essa foi uma escolha sábia.[ENTER]Destrua agora a próxima estela.") d.setf("stonekill",6) if d.count_monster() < 100 then d.regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") end else item.remove() say("Ordem errada. A Pedra de Maat foi destruída.") end elseif npc.get_vid() == d.get_unique_vid("stone5_6") then if d.getf("stonekill") == 6 then npc.purge() item.remove() say("Essa foi uma escolha sábia. Destrua agora a última[ENTER]estela e Maat triunfará sobre Isfet.") d.setf("stonekill",7) if d.count_monster() < 100 then d.regen_file ("data/dungeon/flame_dungeon/".."fd_e.txt") end else item.remove() say("Ordem errada. A Pedra de Maat foi destruída.") end else if d.getf("stonekill") == 7 then npc.purge() item.remove() notice_multiline("A estela de Isfet foi destruída.",d.notice) notice_multiline("Fala com Am-heh para abrir um novo destino.",d.notice) flame_dungeon.level_clear() else item.remove() say("Ordem errada. A Pedra de Maat foi destruída.") end end end when 8057.kill with flame_dungeon.is_flamed(d.get_map_index()) and d.getf("level") ==16 begin -- ??? ???? ? notice_multiline("A Metin do purgatório foi destruída.",d.notice) notice_multiline("Fala com Am-heh para abrir um novo destino.",d.notice) flame_dungeon.level_clear() end when 6091.kill with flame_dungeon.is_flamed(d.get_map_index()) and d.getf("level") ==17 begin -- ?? ???? notice_multiline("Razador foi destruído.",d.notice) notice_multiline("Todos os lutadores seram teleportados[ENTER]em um minuto do Templo do Dragão.",d.notice) timer("exit_dungeon", 60) flame_dungeon.level_clear() if party.is_party() then party.setf("flame_dungeon_boss_kill_count", 1) end end when exit_dungeon.timer begin local setting = flame_dungeon.setting() flame_dungeon.clear_timer(d.get_map_index()) d.set_warp_location(62, setting.outside_entry_pos[1] , setting.outside_entry_pos[2]) d.exit_all() d.setf("party_leader_pid", 0) end end end Also attached the mob spawn files to implement on server side. Since the official quest doesn't have an option to leave the instance if you are logged out if the Razador dies i made a quest to fix that part. quest flame_dungeon_leave begin state start begin when login or enter begin set_state(leave) end end state leave begin when letter begin if pc.get_map_index() == 351 then send_letter("Sair da Fortaleza do Dragão Vermelho") end end when button or info begin say_title("Fortaleza do Dragão Vermelho") say("Deseja sair da instância?") local warp = select("Sim","Não") if warp == 1 then clear_letter() q.done() pc.warp(5980*100, 7075*100, 62) else say("Boa Sorte!") end end when logout begin clear_letter() q.done() end end end flame_dungeon.zip
  • 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.