Jump to content


Popular Content

Showing content with the highest reputation since 02/01/2014 in all areas

  1. 150 points
    Hello metin2dev, Vanilla project is a project where I'm going to modify the source code just to enhance the capabilities of the gamecore, add small new stuff, bugfixing and making it more comfortable to use. Some of the goals are more performance and lesser dependencies on dif-files. This project reached a level where it's easy to use and offers tons of new features. Many bugs and exploits are fixed. Additionally, this gamefile is the only one released for everyone that's having so much features and still allows you to customize them to your needs! There are a lot of CONFIG-options where you can enable/disable systems and even tune them to your needs. You won't need difs anymore, you can just configure the gamefile as you want! It's the only gamefile released that's compiled with newer libraries and gcc 4.9.1 with even more optimization to enhance the speed and lower the file size of the gamefile. Also this game has the package-system disabled by default and lets you run the dbcache from mysql tables by default instead of txt-files! That allows you to easily upgrade your current gamefile without the need to create new directories or convert your proto's to txt! You just have to download the package I provided, extract it and to read the install instructions! I promise you there isn't much to read! Since the source code is written by YMIR and I respect their work I won't release the source code or give any peeks into it. current version: 2.4.1 Developed version: 2.5 Download: See second post! *FEATURE LIST* + removed the license functions so the server won't connect to a license server nor check if your server is valid + removed the time limitation so it won't even check the time limit. This crash issue is completely fixed. + merged all the exp tables to the "exp_table_common" which will be used by ANY locale. You can change the needed exp for 200 levels there. + Max_level can be raised in the CONFIG file to a maximum of 255. + status points will be given at any level. It depends now on Max_level so if you set max_level to 120 you'll get status points until level 120! + fixed vampirism effects so you won't loose hp when you make an overkill (suras may embrace this change) + exp bonus now works comulutative instead of just making a chance to get double exp. If you have 20% exp bonus in your items you'll get 20% more exp at any time. + Rewrote the version check. You can now set your server version in your CONFIG-file and let it check with the client version. If serverversion != clientversion the server will print a message and kick the player out + Raised the gold limit up to 999.999.999.999 + membuf-errors fixed! Now you have a optimized buffer length so it won't consume much RAM but still have enough to not kick players out. + you can now give priv_empire (or other priv's) up to 2000% at any time. + a lot of new quest functions, when triggers and CONFIG-options + more stability and performance especially since it's compiled with a newer gcc version + Optimization flags and linker optimization enabled + ip's beginning with 5. and 25. are now allowed by the internal ip-check + Items can now be sold for 0 gold + 6/7 bonus are now working + name-change works with every locale + gold overflow: Now resets the gold to the maximum value to fight against gold overflow + horse-table has new entries for up to level 51. Raising the level extends the horse-stats. + New error handling for bonus overflow. Now the bonus will be set to the maximum generating a warning in your syserr + player movement speed will be observerd by the server now and set down to the maximum value if it's too high. + Skills can now apply new bonuses! You can e. g. raise your int-attribute + Dbcache can now start without txt-files + If you're warped into a non-existing map or non-existing coordinates your coordinates will be resetted to map1 of your village; You won't need unstuckers anymore + adminpage_ip set to localhost by default so it'll only listen to itself to prevent attackings from API tool. Additionally it's disabled by default and you can enable it with a CONFIG-option. Say good bye to the API tool! + Tons of bug fixes even YMIR had! + Completely rebuild of the source with gcc4.9, cryptopp 5.6.2 and boost 1.55; new optimizations flags and C++11 are enabled to make the core much more faster and more stable! + Advanced spam protection installed! + Unknown packet headers will no longer lead to a disconnect though they'll get dropped + Second binary compiled with 4 inventory pages! + Added the new skill flags so they can use FIRE, ICE, ELEC and DARK + Anti-Exp in the game source + reload q corrected. Note! Still not recommended. But if it's crashing, it'll now notice you. *Gameplay changes* + HP/MP overflow fixed + yang limit raised to unsigned long long int! + Fixed a huge load of format errors that'd actually crash the core! + Speedhack limit fixed so you won't get teleported back when riding + item.remove() won't remove stacks anymore! It'll just reduce the amount of the stack by 1. It there's only one left, the item will be removed. + Bypass to createa guild under level 40 fixed! + Guild wars won't crash the core anymore! + immune bug fixed (completely!!!) + Anti-Overflow mechanism prevents people from receiving too much gold + prisma glass system enabled and fixed + 6/7 bonuses work + polymorph bug fixed + invisibility bug fixed + empire exploit fixed + belt system and dragon soul system enabled + level size raised up to a normal int + You can put items for 0 gold in a shop + Exp can go higher than long int. It's now unsigned long long int (which makes higher exp requirements possible) *New CONFIG-options* MAX_LEVEL_STATUS: unsigned int Forces a maximum level. If you level up higher than this, you'll receive no status points anymore. MAX_STATUS: unsigned int Sets a maximum of distributed status points. If you e. g. set it to 20, you can only raise your stat's by 20 each status. SERVER_CHECK: 1/0 Checks if the client version and the server version are the same. If not, the server will send a message to the client and kick him out after a few seconds. SERVER_VERSION: unsigned int There you can set the version of your server for the SERVER_CHECK. MAX_HT: unsigned int It's the same option than MAX_STATUS but only for the con-attribute. MAX_IQ: unsigned int It's the same option than MAX_STATUS but only for the int-attribute. MAX_ST: unsigned int It's the same option than MAX_STATUS but only for the str-attribute. MAX_DX: unsigned int It's the same option than MAX_STATUS but only for the dex-attribute. ATTR_ALWAYS_ADD: 1/0 If enabled you'll get 100% chance to add new attributes to you equipment. ATTR_ALWAYS_5_ADD: 1/0 If enabled you'll get 100% chance to add new attributes to you equipment. Counts only for 5th Bonus (blessing marble). ATTR_CHANGE_LIMIT: int You can set a limit time to change your attributes again. It's changed to seconds (set it to 1 to let the users switch only once per second their attributes). GUILD_MAX_LEVEL: int Sets the maximum guild level. You can raise it up to 50 since the exp-table is extended to handle up to 50. ITEM_OWNERSHIP_TIME: int If you drop an item, this option sets how long the item will be flagged as yours. MIN_ADDON_FKS: int Sets the minimum ability bonus dmg you can have. MAX_ADDON_FKS: int Sets the maximum ability bonus dmg you can have. MIN_ADDON_DSS: int Sets the minimum normal hit bonus dmg you can have. MIN_ADDON_DSS: int Sets the maximum normal hit bonus dmg you can have. SKILLBOOK_DELAY: int Sets the time limit for reading a book (e. g. if you read skill books you'll have to wait x seconds until you can read the same skill book again). SKILLBOOK_NEED_EXP: int Sets the exp you need for reading a book. SKILLBOOK_ALWAYS_BOOK: 1/0 Sets if every book will be handled as you'd have used a skillbook chance amplifier. GOLD_DROP_TIME_INTERVAL: int Sets how long you have to wait until you can drop gold again. SEQUENCE_CHECK: 1/0 Enables a check if the sequence table is the same than the client's one. SKILLBOOK_STEP_LEVELING: 1/0 Enables the need of more books for raising a skill (e. g. you need 2 books from m2 to m3). RAISE_EMPIRE_PRICES: 1/0 Enables the raise of prices if you buy items in another empire. HORSE_MAX_LEVEL: int Sets the maximum level of your horse (you still need to write quests or something like that to allow players to achieve the higher horse-levels). MARRIAGE_MAX_PERCENT: int Sets the maximum allowed percent of love points. Warning! If love points > 100 it'd lead into bugs with breaking the marriage. PC_MAX_MOVEMENT_SPEED: int Sets the maximum movement speed for players. PC_MAX_ATTACK_SPEED: int Sets the maximum attack speed for players. MOB_MAX_MOVEMENT_SPEED: int Sets the maximum movement speed for mobs. MOB_MAX_ATTACK_SPEED: int Sets the maximum attack speed for mobs. TAXES: int From 0 to 100. Sets the % how much taxes you have to pay while shopping. DYE_LEVEL: int Sets how many levels you have to get after you can change your hair color again. YANG_MAX: long long Sets the maximum gold you can carry. You can change it up to 999.999.999.999 gold. package_enable: 0/1 1 = enabled. Disabled by default. Enable to use the package-feature. log_level: 0/1/2 Sets the logging level. 0 means to logs will be entered in your database. 1 means that the most important tables (hack-logs for example) will be used 2 means that all logging tables will be used new_test_server: 0/1 Protects your test-server so the gamecore will check if accounts are written into gmlist before granting them implementor-privileges. new_gm_host_check: 1/0 Checks the gmhost and gmlist for the right ip before granting privileges. Disabled by default. adminpage_enable: 1/0 Enables the adminpage-features. Disabled by default (say bye bye to API tools) adminpage_no_localhost: 1/0 Disables the security feature which inserts localhost into your adminpage_ip so it'll only listen to localhost. item_floor_time: int Set the time how long a dropped item will be lying on the ground (by monsters) max_rank_points: long int Set the maximum rank points movement_speed: int Set the initial movement speed for players. belt_all_allow_items: 0/1 Allow Players to store every item in their belt inventory attr_rare_enable: 0/1 Allow the using of rare attributes (6th and 7th attributes). Default: ON. GOLD_DROP_TIME: int Sets the time how long dropped gold will lay on the ground until it's purged. ITEM_DROP_TIME: int Sets how long dropped items will lay on the ground intil it's purged. BELT_FORCE_SLOTS: int Forces to open up the given amount of slots in your belt inventory. If this value is higher than the grade of your belt, it'll open the given amount of slots. If it's lower, the amount your belt provides will be used. For example: You set 10. You've got a belt that opens 5 slots. 10 will be opened. Now you set 4 and still have the same belt. This time 5 slots will be opened. This does also work when no belts are weared. But be careful: Since there's also a clientside part the slots may appear to be locked but you can still put items into them trade_effect: 1/0 Enables a effect that'll occur when people are traing stuff. Enabled by default. ban_force_reason: 1/0 This lets the ban-command only work when you're giving a reason. Disabled by default. start_gold: long int Let's players start with a custom amount of gold. Default: 0. view_equip_for_all: 1/0 Let's player view equip of others! Disabled by default. view_equip_sp_cost: int Sets the cost of using view_equip. This is in % so if you type in 30 then it'll cost 30% of the players maximum sp. Default: 0. glass_enable: 1/0 Enables the prisma glass-system to print your items in the chat. Disabled by default. glass_needed: 1/0 Sets if you need a glass for using the prisma glass-system or not. Enabled by default. trade_effect_exchange_threshold: int Sets the threshold to create another effect when making an exchange. Default: 500000. This means, that every 500000 gold traded away there'll be another fly effect created trade_effect_shop_threshold: int Same as trade_effect_exchange_threshold; This points to buying items in shops. Default: 100000000. VERSIONCHECK_KICK_DELAY: int Default is 10. Sets the time until the player is kicked when a version mismatch is occured. Takes only effect if the versioncheck is enabled. EMOTION_WITHOUT_MASK: 1/0 Default is 0. Lets you define if you won't need a mask to use emotions. EMOTION_SAME_GENDER: 1/0 Default is 0. Lets you define if people will be able to use emotions on the same gender. Notice: This'd possibly look awkward because the animations doesn't match CHECK_SPEEDHACK_ENABLE: 1/0 Default is 1. Lets you define if you want to use the speedhack/synchack check. Warning! Make sure you only use this for debugging purpose! You can fine-tune the variables for the speedhack in your CONFIG, so this should normally not be touched! QUEST_TRIGGER_ENABLE: 1/0 Default is 1. Lets you define if you want to use the new execute-trigger. EXP_NEED_THRESHOLD: unsigned long long int Allows you to set the exp needed if your level is higher than the maximum level of the exp table SKILL_MASTER_UPGRADE: int Sets the minimum level when your skill can jump to master. If it's set to 1 for example, then it'd happen that your skill jumps to m1 at any level. SKILL_FORCE_MASTER: 1/0 Lets you define if your skill will definitely raise to m1 if it hits the minimum level for jumping. So if you're enabling this, then your skill will definitely (unless you set SKILL_MASTER_UPGRADE) raise to m1 when hitting 17. BUGFIX_SURA_MANASHIELD: 1/0 Default is disabled. Fixes the sura manashield so it'll now scale with the proper value instead of always removing a third of the damage. Warning! When activating, you'd nerf the skill! Otherwise people with over 100 iq could prevent every incoming damage and even heal themselves or cause crashes! *New questfunctions* item.get_attr_type(int index) item.get_attr_value(int index) item.set_attr(int ApplyType, int ApplyValue[, int index]) npc.get_level() game.mysql_real_escape_string(string query) game.mysql_query(string query) game.mysql_update_query(string query) pc.delayed_disconnect(int zeit) pc.get_mount_vnum() pc.set_level(int level) pc.send_effect(int id) pc.block_exp() pc.unblock_exp() item.equip() npc.select() pet.is_mine() pc.get_id() *New conf.txt options* TXT_STARTUP = 0/1 1 = enabled. Disabled by default. Enable to boot with txt-files instead of sql *New quest trigger* OnBuy (triggers on buying a item from players or npc's) OnDie (triggers on dying) *commands* /ban playername reason /unban playername full list of all allowed bonuses for skills: MAX_HP MAX_SP HP_REGEN SP_REGEN BLOCK HP SP ATT_GRADE DEF_GRADE MAGIC_ATT_GRADE MAGIC_DEF_GRADE BOW_DISTANCE MOV_SPEED ATT_SPEED POISON_PCT RESIST_RANGE CASTING_SPEED REFLECT_MELEE ATT_BONUS DEF_BONUS RESIST_NORMAL DODGE KILL_HP_RECOVER KILL_SP_RECOVER HIT_HP_RECOVER HIT_SP_RECOVER CRITICAL MANASHIELD SKILL_DAMAGE_BONUS NORMAL_HIT_DAMAGE_BONUS HT IQ ST DX STUN_PCT SLOW_PCT PENETRATE_PCT ATTBONUS_HUMAN STEAL_HP STEAL_SP MANA_BURN_PCT DAMAGE_SP_RECOVER RESIST_SWORD RESIST_TWOHAND RESIST_DAGGER RESIST_BELL RESIST_FAN RESIST_BOW RESIST_FIRE RESIST_ELEC RESIST_MAGIC RESIST_WIND REFLECT_CURSE POISON_REDUCE EXP_DOUBLE_BONUS GOLD_DOUBLE_BONUS ITEM_DROP_BONUS POTION_BONUS IMMUNE_STUN IMMUNE_SLOW IMMUNE_FALL CURSE_PCT STA ATTBONUS_WARRIOR ATTBONUS_ASSASSIN ATTBONUS_SURA ATTBONUS_SHAMAN ATTBONUS_MONSTER MAX_HP_PCT MAX_SP_PCT SKILL_DEFEND_BONUS NORMAL_HIT_DEFEND_BONUS RESIST_WARRIOR RESIST_ASSASSIN RESIST_SURA RESIST_SHAMAN ENERGY RESIST_CRITICAL RESIST_PENETRATE Thanks to: xP3NG3Rx for some quest functions Sphinx² & lollo_9_1 for the mysql-functions Lefloyd for the 2 new quest triggers .InyaProduction for some new quest functions Tim for the suggestion to include libs from a special path MartPwnS for helping with the src code on gcc48/gcc49 And especially thanks to you!
  2. 77 points
    Hi, As requested by some users i have you a VM with FreeBSD 9.2 32bit, novaline source and pre installed Ports so you can compile the game. It was like 10 minutes of work to enter the commands so no thanks needed. Link: HerpDerp Login: root Pw: dev To compile the game: 1 2 3 cd /usr/src/novaline/Srcs/Server/game/src gmake clean gmake -j20 If there are any Problems or questsions you can add me in Skype(l337-5p34k) or Message me here i'll always give you support. Kind regards TheGame €: There are no Serverfiles on this VM because i dont have test serverfiles. If someone have Serverfiles for me i'll implement them and upload an updated version of this VM. €€: Updated Link: Thanks to Da'Real Pain
  3. 75 points
    This post is made for changelogs and for the download link! ### Changelog vanilla version 2.2 (without rev system) ### ~> See here ### Changelog vanilla revision rev52410 ### Also known as version 2.3 ~> See here ### Changelog vanilla revision 54180 ### Also known as version 2.4 ~> See here ### Changelog vanilla revision 54250 ### Also known as version 2.4.1 ~> See here ~> Hotfix see here ~> Second hotfix see here Download (v2.4.1): here password: vanilla note! Please always test newer versions of vanilla first in a test environment!! Only download the vanilla core from valid sources (this thread!!) If you want to donate then you can simply donate via paypal or other payment methods. Just write me a private message I appreciate every help I can get! Installation: Read readme.txt! You are allowed to freely distribute the vanilla core but be sure you mark the right authors! The main source code is from YMIR, the modifications are made by me (vanilla)! And if you release it somewhere else please make sure you create a reference to this thread and that it's allowed to be posted there.
  4. 61 points
    Hi, In this thread I'm going to show you how to make a game-client or client-game communication with packets, instead of using the old quest-client, client-quest communication. Lets start with the game-client, in this example I will send 1 variable to the client. First start with the HEADER, open your binary source and navigate to UserInterface/Packet.h. Now you will see many headers, create a new one, but search for an empty number. I will use 57, because its not used. GC means it's used for Game -> Client packet, it's just a prefix. HEADER_GC_METIN2DEV Now add the structure for the packet, this is most important part. Structure is the "body" of the packet, it contains the HEADER as BYTE and the other optional variables. As I said I just want to send one int type to the client, so add it. typedef struct command_metin2dev_packet { BYTE bHeader; int M2int; } TPacketGCMetin2Dev; Now navigate to UserInterface/PythonNetworkStream.cpp and add your header to the CMainPacketHeaderMap class. The first parameter of the Set is the HEADER, second is the size of the structure. We will use just static size packets in this tutorial, but the third argument can be dynamic size too. Set(HEADER_GC_METIN2DEV, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCMetin2Dev), STATIC_SIZE_PACKET)); Now navigate to UserInterface/PythonNtworkStreamPhaseGame.cpp and add the function to the switch. case HEADER_GC_METIN2DEV: ret = RecvM2DevPacket(); break; The name of the function will be RecvM2DevPacket: Now declarate the function, navigate to UserInterface/PythonNetworkStream.h and add it as public: bool RecvM2DevPacket(); Now add the receiver part of the code. Recv "picks" out xy bytes from the buffer and the return type of it is false if there was no data in the buffer by that size otherwise true, which means it was successful. xy = size of the structure bool CPythonNetworkStream::RecvM2DevPacket() { TPacketGCMetin2Dev Metin2DevGC; if (!Recv(sizeof(TPacketGCMetin2Dev), &Metin2DevGC)) { Tracen("Recv Metin2DevGC Packet Error"); return false; } } Now we are calling the BINARY_M2DEV_Test function in game.py and passing the received data. PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_M2DEV_Test", Py_BuildValue("(i)", Metin2DevGC.M2int)); This was the client-side of the game-client communication, lets start the server-side: First of all we need to add the header again, navigate to game/packet.h and add this: And the structure: typedef struct packet_metin2dev_packet { BYTE byHeader; int M2int; } TPacketGCMetin2Dev; Now navigate to game/char.cpp and create a function which sends the packet. void CHARACTER::SendMetin2DevPacket() { } Declare it in the game/char.h: void SendMetin2DevPacket(); Now lets add the content of the function. Create a new instance of the structure, set the values of it and send it to the client. void CHARACTER::SendMetin2DevPacket() { if (!GetDesc()) { return; } TPacketGCMetin2Dev Metin2DevGC; Metin2DevGC.byHeader = HEADER_GC_METIN2DEV; Metin2DevGC.M2int = GetPlayerID(); GetDesc()->Packet(&Metin2DevGC, sizeof(TPacketGCMetin2Dev)); } Now add the last function to game.py, this will be called by the binary: def BINARY_M2DEV_Test(self, M2int): import dbg dbg.LogBox(str(M2int)) Finally, lets check how it works: If you have any question or suggestion, please just reply to this topic. Kind Regards, Sanchez
  5. 60 points
    Today I'm gonna show you how to compile the mainline_released client binary. Tools we will need: VS2008,Visual Studio 2008 SP1 We will need to make two folders on our hard drive for example include_stuff and lib_stuff after that we go to srcnovalineSrcsToolsWorldEditorexterninclude and copy all that things into include_stuff next go to srcnovalineSrcsToolsWorldEditorexternlib and copy all that things into lib_stuff next open srcnovalineSrcsToolsRAD Game Toolsgrannycommongranny_common_2_9_12_0_release.zip go to lib then win32 and copy all that into lib_stuff next go to srcnovalineSrcsExternlib and copy all into lib_stuff after this go to srcnovalineSrcsExterninclude and copy all into include_stuff In VS 2008 go to Tools->Options->Project and Solutions->VC++ Directories=>Select Include files and include there your include_stuff folder then select Library files and include there your lib_stuff files. Finally we did it Select to release mode and press ctrl+shift+b Kind Regards, Denic
  6. 47 points
    Hi guys Someone wondered how to make 4 inventory page with source. I will share how to make 4 inventory page today I hope you are like it First which you are use to source files open it. I will use to mainline_released(SG) log in mainline_released/mainline_sg/Srcs/Server/common after open length.h after search this INVENTORY_MAX_NUM = 90, Replace to INVENTORY_MAX_NUM = 180, Open char_item.cpp and search this BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2); Replace to BYTE bPage = bCell / (INVENTORY_MAX_NUM / 4); search this if (p / (INVENTORY_MAX_NUM / 2) != bPage) Replace to if (p / (INVENTORY_MAX_NUM / 4) != bPage) open exchange.cpp. Search this after add under this. static CGrid s_grid2(5, INVENTORY_MAX_NUM/5 / 2); // inven page 2 will be like this. static CGrid s_grid1(5, INVENTORY_MAX_NUM/5 / 2); // inven page 1 static CGrid s_grid2(5, INVENTORY_MAX_NUM/5 / 2); // inven page 2 static CGrid s_grid3(5, INVENTORY_MAX_NUM/5 / 2); // inven page 3 static CGrid s_grid4(5, INVENTORY_MAX_NUM/5 / 2); // inven page 4 s_grid1.Clear(); s_grid2.Clear(); s_grid3.Clear(); s_grid4.Clear(); and replace to your self.. for (i = 0; i < INVENTORY_MAX_NUM / 4; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid1.Put(i, 1, item->GetSize()); } for (i = INVENTORY_MAX_NUM / 4; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid2.Put(i - INVENTORY_MAX_NUM / 4, 1, item->GetSize()); } for (i = INVENTORY_MAX_NUM / 4; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid3.Put(i - INVENTORY_MAX_NUM / 4, 1, item->GetSize()); } for (i = INVENTORY_MAX_NUM / 4; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid4.Put(i - INVENTORY_MAX_NUM / 4, 1, item->GetSize()); } After client.. Log in mainline_released/mainline_sg/Srcs/Client/Userinterface after open GameType.h after search this const DWORD c_Inventory_Page_Count = 2; Replace to const DWORD c_Inventory_Page_Count = 4; open inventorywindow.py and search this EQUIPMENT_START_INDEX = 90 Replace to EQUIPMENT_START_INDEX = 180 open uiinventory.py and search this after add under this self.inventoryTab.append(self.GetChild("Inventory_Tab_02")) self.inventoryTab.append(self.GetChild("Inventory_Tab_03")) self.inventoryTab.append(self.GetChild("Inventory_Tab_04")) search this after add under this self.inventoryTab[1].SetEvent(lambda arg=1: self.SetInventoryPage(arg)) self.inventoryTab[2].SetEvent(lambda arg=2: self.SetInventoryPage(arg)) self.inventoryTab[3].SetEvent(lambda arg=3: self.SetInventoryPage(arg)) Search SetInventoryPage function and replace with this. def SetInventoryPage(self, page): self.inventoryTab[self.inventoryPageIndex].SetUp() self.inventoryPageIndex = page self.inventoryTab[self.inventoryPageIndex].Down() self.RefreshBagSlotWindow() Thanks for @Zardon,Deniec Cikiec comment. i will share my inventorywindow.py import uiScriptLocale import item EQUIPMENT_START_INDEX = 180 window = { "name" : "InventoryWindow", ## 600 - (width + 오른쪽으로 부터 띄우기 24 px) "x" : SCREEN_WIDTH - 176, "y" : SCREEN_HEIGHT - 37 - 565, "style" : ("movable", "float",), "width" : 176, "height" : 585, "children" : ( ## Inventory, Equipment Slots { "name" : "board", "type" : "board", "style" : ("attach",), "x" : 0, "y" : 0, "width" : 176, "height" : 585, "children" : ( ## Title { "name" : "TitleBar", "type" : "titlebar", "style" : ("attach",), "x" : 8, "y" : 7, "width" : 161, "color" : "yellow", "children" : ( { "name":"TitleName", "type":"text", "x":77, "y":3, "text":uiScriptLocale.INVENTORY_TITLE, "text_horizontal_align":"center" }, ), }, ## Equipment Slot { "name" : "Equipment_Base", "type" : "image", "x" : 10, "y" : 33, "image" : "d:/ymir work/ui/equipment_bg_without_ring.tga", "children" : ( { "name" : "EquipmentSlot", "type" : "slot", "x" : 3, "y" : 3, "width" : 150, "height" : 182, "slot" : ( {"index":EQUIPMENT_START_INDEX+0, "x":39, "y":37, "width":32, "height":64}, {"index":EQUIPMENT_START_INDEX+1, "x":39, "y":2, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+2, "x":39, "y":145, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+3, "x":75, "y":67, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+4, "x":3, "y":3, "width":32, "height":96}, {"index":EQUIPMENT_START_INDEX+5, "x":114, "y":67, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+6, "x":114, "y":35, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+7, "x":2, "y":145, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+8, "x":75, "y":145, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+9, "x":114, "y":2, "width":32, "height":32}, {"index":EQUIPMENT_START_INDEX+10, "x":75, "y":35, "width":32, "height":32}, ## 새 반지1 ##{"index":item.EQUIPMENT_RING1, "x":2, "y":106, "width":32, "height":32}, ## 새 반지2 ##{"index":item.EQUIPMENT_RING2, "x":75, "y":106, "width":32, "height":32}, ## 새 벨트 {"index":item.EQUIPMENT_BELT, "x":39, "y":106, "width":32, "height":32}, ), }, ## Dragon Soul Button { "name" : "DSSButton", "type" : "button", "x" : 114, "y" : 107, "tooltip_text" : uiScriptLocale.TASKBAR_DRAGON_SOUL, "default_image" : "d:/ymir work/ui/dragonsoul/dss_inventory_button_01.tga", "over_image" : "d:/ymir work/ui/dragonsoul/dss_inventory_button_02.tga", "down_image" : "d:/ymir work/ui/dragonsoul/dss_inventory_button_03.tga", }, ## MallButton { "name" : "MallButton", "type" : "button", "x" : 118, "y" : 148, "tooltip_text" : uiScriptLocale.MALL_TITLE, "default_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_01.tga", "over_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_02.tga", "down_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_03.tga", }, ## CostumeButton { "name" : "CostumeButton", "type" : "button", "x" : 78, "y" : 5, "tooltip_text" : uiScriptLocale.COSTUME_TITLE, "default_image" : "d:/ymir work/ui/game/taskbar/costume_Button_01.tga", "over_image" : "d:/ymir work/ui/game/taskbar/costume_Button_02.tga", "down_image" : "d:/ymir work/ui/game/taskbar/costume_Button_03.tga", }, { "name" : "Equipment_Tab_01", "type" : "radio_button", "x" : 86, "y" : 161, "default_image" : "d:/ymir work/ui/game/windows/tab_button_small_01.sub", "over_image" : "d:/ymir work/ui/game/windows/tab_button_small_02.sub", "down_image" : "d:/ymir work/ui/game/windows/tab_button_small_03.sub", "children" : ( { "name" : "Equipment_Tab_01_Print", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "I", }, ), }, { "name" : "Equipment_Tab_02", "type" : "radio_button", "x" : 86 + 32, "y" : 161, "default_image" : "d:/ymir work/ui/game/windows/tab_button_small_01.sub", "over_image" : "d:/ymir work/ui/game/windows/tab_button_small_02.sub", "down_image" : "d:/ymir work/ui/game/windows/tab_button_small_03.sub", "children" : ( { "name" : "Equipment_Tab_02_Print", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "II", }, ), }, ), }, { "name" : "Inventory_Tab_01", "type" : "radio_button", "x" : 10, "y" : 33 + 189, "default_image" : "d:/ymir work/ui/game/windows/tab_button_large_01.sub", "over_image" : "d:/ymir work/ui/game/windows/tab_button_large_02.sub", "down_image" : "d:/ymir work/ui/game/windows/tab_button_large_03.sub", "tooltip_text" : uiScriptLocale.INVENTORY_PAGE_BUTTON_TOOLTIP_1, "children" : ( { "name" : "Inventory_Tab_01_Print", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "I", }, ), }, { "name" : "Inventory_Tab_02", "type" : "radio_button", "x" : 10 + 78, "y" : 33 + 189, "default_image" : "d:/ymir work/ui/game/windows/tab_button_large_01.sub", "over_image" : "d:/ymir work/ui/game/windows/tab_button_large_02.sub", "down_image" : "d:/ymir work/ui/game/windows/tab_button_large_03.sub", "tooltip_text" : uiScriptLocale.INVENTORY_PAGE_BUTTON_TOOLTIP_2, "children" : ( { "name" : "Inventory_Tab_02_Print", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "II", }, ), }, { "name" : "Inventory_Tab_03", "type" : "radio_button", "x" : 10, "y" : 33 + 210, "default_image" : "d:/ymir work/ui/game/windows/tab_button_large_01.sub", "over_image" : "d:/ymir work/ui/game/windows/tab_button_large_02.sub", "down_image" : "d:/ymir work/ui/game/windows/tab_button_large_03.sub", "tooltip_text" : uiScriptLocale.INVENTORY_PAGE_BUTTON_TOOLTIP_2, "children" : ( { "name" : "Inventory_Tab_03_Print", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "III", }, ), }, { "name" : "Inventory_Tab_04", "type" : "radio_button", "x" : 10 + 78, "y" : 33 + 210, "default_image" : "d:/ymir work/ui/game/windows/tab_button_large_01.sub", "over_image" : "d:/ymir work/ui/game/windows/tab_button_large_02.sub", "down_image" : "d:/ymir work/ui/game/windows/tab_button_large_03.sub", "tooltip_text" : uiScriptLocale.INVENTORY_PAGE_BUTTON_TOOLTIP_2, "children" : ( { "name" : "Inventory_Tab_04_Print", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "IV", }, ), }, ## Item Slot { "name" : "ItemSlot", "type" : "grid_table", "x" : 8, "y" : 264, "start_index" : 0, "x_count" : 5, "y_count" : 9, "x_step" : 32, "y_step" : 32, "image" : "d:/ymir work/ui/public/Slot_Base.sub" }, ## Print { "name":"Money_Slot", "type":"button", "x":8, "y":28, "horizontal_align":"center", "vertical_align":"bottom", "default_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "over_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "down_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "children" : ( { "name":"Money_Icon", "type":"image", "x":-18, "y":2, "image":"d:/ymir work/ui/game/windows/money_icon.sub", }, { "name" : "Money", "type" : "text", "x" : 3, "y" : 3, "horizontal_align" : "right", "text_horizontal_align" : "right", "text" : "123456789", }, ), }, ), }, ), } open beltinventorywindow.py after search this EQUIPMENT_START_INDEX = 90 replace to EQUIPMENT_START_INDEX = 180 I think someone don't make part of client-side. I share binary file (original file) with your. https://mega.co.nz/#!TxpUzL6Y!9vC4ip61k_El6Ew6POIF53_PApd29a4CFSqIMdzb4XQ Kind Regards HaveBeen
  7. 43 points
    Hi, In this thread I will show you how you can implement an advanced spam protection to your server. The player can write the same message just after 5 seconds. The player will receive 1 minute of chat ban if he is trying to send the same message more than 3 times in 5 seconds. You can specify a blockspamlist.lst file which contains words. If the user sending a message which contains a words from the list, the player will receive 5 minutes of chat ban. (You can specify the time of the chat ban) You can specify a bannspamlist.lst file which contains words. If the user sending a message which contains a words from the list, the player will receive a ban. (You can specify the time of the ban) Open game/input_main.cpp and search for this: if (ch->IncreaseChatCounter() >= 10) Add this over that: if (!strcmp(ch->LastPlayerMessage, buf) && (thecore_pulse() < (ch->LastMessageAt + SPAM_WAIT_SEC * 25)) && !ch->SpamAllowBuf(buf) && ch->GetGMLevel() < GM_LOW_WIZARD) { if (ch->BlockChatAfter < 2) { ch->ChatPacket(CHAT_TYPE_INFO, ("You must wait 5 seconds to repeat your message")); ch->BlockChatAfter++; return iExtraLen; } else { ch->BlockChatAfter = 0; ch->PlayerPunish(false, SPAM_CHAT_BAN_TIME); return iExtraLen; } } else { if (!ch->BannListCheck(buf) && ch->GetGMLevel() < GM_LOW_WIZARD) { ch->PlayerPunish(true, SPAM_BAN_TIME); return iExtraLen; } if (!ch->SpamListCheck(buf) && ch->GetGMLevel() < GM_LOW_WIZARD) { ch->ChatPacket(CHAT_TYPE_INFO, ("You wrote a not allowed words!")); ch->PlayerPunish(false, SPAM_CHAT_BAN_TIME); return iExtraLen; } } Still in input_main.cpp search for this: ch->GetMapIndex(), strlen(ch->GetName()))); Add this under that: strcpy(ch->LastPlayerMessage, buf); ch->LastMessageAt = thecore_pulse(); ch->BlockChatAfter = 0; Open game/char.h and search for this: BYTE GetChatCounter() const; Add this under that: int LastMessageAt; int BlockChatAfter; char LastPlayerMessage[CHAT_MAX_LEN + 1]; void PlayerPunish(bool PowerPunish, int Duration); bool SpamListCheck(const char *Message); bool BannListCheck(const char *Message); bool SpamAllowBuf(const char *Message); Open game/char.cpp and add these events: void CHARACTER::PlayerPunish(bool PowerPunish, int Duration) { if (!PowerPunish) { AddAffect(AFFECT_BLOCK_CHAT, POINT_NONE, 0, AFF_NONE, Duration, 0, true); sys_log(0, "%s[%d] has been chatbanned because of spamming/writing words which are in the spamlist.txt", GetName(), GetPlayerID()); } else { std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery("UPDATE account.account SET availDt = FROM_UNIXTIME(UNIX_TIMESTAMP(CURRENT_TIMESTAMP()) + %i) WHERE id = %d", Duration, GetAID())); sys_log(0, "%s[%d] has been banned because of saying blacklisted word", GetName(), GetPlayerID()); GetDesc()->DelayedDisconnect(5); } } bool CHARACTER::SpamAllowBuf(const char *Message) { if (!strcmp(Message, "(Ȳ´ç)") || !strcmp(Message, "(µ·)") || !strcmp(Message, "(±â»Ý)") || !strcmp(Message, "(ÁÁľĆ)") || !strcmp(Message, "(»ç¶ű)") || !strcmp(Message, "(şĐłë)") || !strcmp(Message, "(ľĆÇĎ)") || !strcmp(Message, "(żěżď)") || !strcmp(Message, "(ÁËĽŰ)")) { return true; } return false; } bool CHARACTER::SpamListCheck(const char *Message) { for (int i = 0; i < SpamBlockListArray.size(); i++) { if (!strcmp(Message, SpamBlockListArray[i].c_str())) { return false; } } return true; } bool CHARACTER::BannListCheck(const char *Message) { for (int i = 0; i < SpamBannListArray.size(); i++) { if (!strcmp(Message, SpamBannListArray[i].c_str())) { return false; } } return true; } Add 2 new files to your project: spamblock.cpp spamblock.h Add these to the spamblock.cpp #include "fstream" #include "string" #include "sstream" #include "stdafx.h" #include "../../common/length.h" std::vector<std::string> SpamBlockListArray; std::vector<std::string> SpamBannListArray; void LoadBlockSpamList() { std::string TempBlockList; std::ifstream File("chat/blockspamlist.lst"); if (!File.is_open()) { sys_log(0, "WARNING: cannot open chat/blockspamlist.lst"); return; } SpamBlockListArray.clear(); while (!File.eof()) { File >> TempBlockList; SpamBlockListArray.push_back(TempBlockList); } File.close(); } void LoadBannSpamList() { std::string TempBannList; std::ifstream File("chat/bannspamlist.lst"); if (!File.is_open()) { sys_log(0, "WARNING: cannot open chat/bannspamlist.lst"); return; } SpamBannListArray.clear(); while (!File.eof()) { File >> TempBannList; SpamBannListArray.push_back(TempBannList); } File.close(); } Add these to the spamblock.h #include "string" #include "../../common/length.h" extern void LoadBlockSpamList(); extern void LoadBannSpamList(); extern std::vector<std::string> SpamBlockListArray; extern std::vector<std::string> SpamBannListArray; Add this to game/char.cpp #include "spamblock.h" Add this to game/main.cpp #include "spamblock.h" Search for this in game/main.cpp: PanamaLoad(); Add these under that: LoadBlockSpamList(); LoadBannSpamList(); Open common/length.h and add these: SPAM_WAIT_SEC = 5, // The player can duplicate his message after 5 sec SPAM_CHAT_BAN_TIME = 60, // The player will receive 60 seconds chat ban, if he is saying a spamlist word SPAM_BAN_TIME = 3600, // The player will receive 1 hour ban, if he is saying a banlist word Open game/cmd_gm.cpp and search for this event: ACMD(do_reload) Add this to the switch function: case 'b': ch->ChatPacket(CHAT_TYPE_INFO, "Reloading bann/spam list infomations."); LoadBlockSpamList(); LoadBannSpamList(); sys_log(0, "Reloading bann/spam list infomations."); break; Add this to the top of the file: #include "spamblock.h" How to set up: Make sure you added everything to your game Create a new folder called chat in your channels Create 2 files, blockspamlist.lst and bannspamlist.lst Upload the words to these files Restart your server blockspamlist.lst example: obsceneword1 obsceneword2 obsceneword3 obsceneword4 bannspamlist.lst example: WWW.CHEAP-FARM-SERVICE.COM WWW.CHEAP-GOLD.COM WWW.EASY-HACKS.COM WWW.FREE-YANG.COM If you have any question or suggestion, please just reply to this topic. Kind Regards, Sanchez
  8. 41 points
    Hello guys today i'm gonna show u how to compile the source in freebsd. First of all you need and dns or a dedicated server because in hamachi server we can not use the fetch command We will install Gmake,Makedepend,Svn(subversion),Devil,G++ 1)gmake: cd /usr/ports/devel/gmake && make install clean 2)makedepend: cd /usr/ports/devel/makedepend && make install clean 3)svn: cd /usr/ports/devel/subversion && make install clean 4)devil: cd /usr/ports/graphics/devil && make install clean 5)G++: cd /usr/ports/lang/gcc48/ && make install clean NOTE: if you have already installed some of this step just skip the step and follow the other Then you do this: From libdevil/ copy all .a files into /usr/lib From libgame/From lib copy the From libgame.a file into /usr/lib From libhackshield/From lib copy the From libanticpxsvr.a file into /usr/lib From liblua/From lib copy the .a files into /usr/lib From libpoly/ copy the .o files into /usr/lib From libserverkey/ copy the .o files into /usr/lib From libthecore/From lib copy the From libthecore.a files into /usr/lib After copying the files into the /usr/lib do this: go to Extern folder of the novaline and open the include folder and copy everything into /usr/include go to Extern/Lib folder of the novaline branch and copy everything from there to /usr/lib go to Extern folder of the novaline branch and drag the cryptopp and openssl folders into /usr/include So we have installed everything then we have to upload the branch novaline into /usr/src then u give this command in freebsd: cd /usr/src/novaline/Server cd /usr/src/novaline/Server/ gmake To build db: cd /usr/src/novaline/Server/db/src gmake clean gmake -j20 To build game: cd /usr/src/novaline/Server/game/src gmake clean gmake -j20 Fixing the error: g++ directory": No such file or directory Solution: here
  9. 41 points
    Hey all, Today I will explain to you how to use different designs for your quest scrolls like WoM. Setting up the system 1) Copy your scroll designs to ui/game/quest/questicon in the client. I have attached the WoM scrolls as example. 2) Open uiCharacter.py and insert the code that appears between comments: if questCount > quest.QUEST_MAX_NUM: self.questScrollBar.Show() else: self.questScrollBar.Hide() for i in questRange[:questCount]: (questName, questIcon, questCounterName, questCounterValue) = quest.GetQuestData(self.questShowingStartIndex+i) # start colored scrolls if questName[0] == '*': questName = questName[1:] elif questName[0] == '&': questName = questName[1:] elif questName[0] == '~': questName = questName[1:] elif questName[0] == '+': questName = questName[1:] # end colored scrolls self.questNameList[i].SetText(questName) self.questNameList[i].Show() self.questLastCountList[i].Show() self.questLastTimeList[i].Show()3) Open interfaceModule.py Replace this part: if locale.IsEUROPE(): btn.SetUpVisual(locale.GetLetterCloseImageName()) btn.SetOverVisual(locale.GetLetterOpenImageName()) btn.SetDownVisual(locale.GetLetterOpenImageName()) else: btn.SetUpVisual(buttonImageFileName) btn.SetOverVisual(buttonImageFileName) btn.SetDownVisual(buttonImageFileName) btn.Flash() # END_OF_QUEST_LETTER_IMAGE with this: if locale.IsSINGAPORE() or locale.IsEUROPE(): if name[0] == '*': btn.SetUpVisual("d:/ymir work/ui/game/quest/questicon/scroll_close_blue.tga") btn.SetOverVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_blue.tga") btn.SetDownVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_blue.tga") name = name[1:] elif name[0] == '~': btn.SetUpVisual("d:/ymir work/ui/game/quest/questicon/scroll_close_golden.tga") btn.SetOverVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_golden.tga") btn.SetDownVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_golden.tga") name = name[1:] elif name[0] == '&': btn.SetUpVisual("d:/ymir work/ui/game/quest/questicon/scroll_close_green.tga") btn.SetOverVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_green.tga") btn.SetDownVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_green.tga") name = name[1:] elif name[0] == '+': btn.SetUpVisual("d:/ymir work/ui/game/quest/questicon/scroll_close_purple.tga") btn.SetOverVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_purple.tga") btn.SetDownVisual("d:/ymir work/ui/game/quest/questicon/scroll_open_purple.tga") name = name[1:] else: btn.SetUpVisual(locale.GetLetterCloseImageName()) btn.SetOverVisual(locale.GetLetterOpenImageName()) btn.SetDownVisual(locale.GetLetterOpenImageName()) else: btn.SetUpVisual(buttonImageFileName) btn.SetOverVisual(buttonImageFileName) btn.SetDownVisual(buttonImageFileName) btn.Flash() # END_OF_QUEST_LETTER_IMAGEUsage After you modified your client, there will be 4 color codes that you can use at the start of your quest's title to enable the colored scroll: Blue (*), Golden (~), Green (&) and Purple (+). You also have to add the q.set_icon function containing the filename of the scroll picture. Here is an example of how to make a quest scroll blue: when login with game.get_event_flag("worldbookday") == 1 begin send_letter("*World Book Day") q.set_icon("scroll_open_blue.tga") local v=find_npc_by_vnum(20023) if v!=0 then target.vid("__TARGET__", v, "Soon") end endAnd it looks like this: That's all you can also add new codes easily or use your own quest scroll designs. Enjoy! questicon.zip
  10. 40 points
    Dear community, this is my first guide for you in which I will show you how you change the older Granny 2.4 version which is the client using to the newer Granny 2.9 version. For this tutorial I'm using the mainline_released client source (all client sources are the same as I heard). DO NOT FORGET TO CREATE BACKUPS! 1. Step: Navigate to novalineSrcsToolsRAD Game Toolsgrannycommon and unzip the file granny_common_2_9_12_0_release.zip. You will receive some folders. Now you navigate into the folder include and copy the granny.h file to the include folder of your client (for me it's mainline_releasedSrcsExterninclude). Then you go into the libwin32 folder and copy all the *.lib and *.pdb files into your lib folder of your client. 2. Step: Open your client source and navigate to the project EterGrnLib. Open Mesh.cpp. Search for this: int * boneIndices = GrannyGetMeshBindingToBoneIndices(pgrnMeshBinding); Replace with this: int * boneIndices = (int*)GrannyGetMeshBindingToBoneIndices(pgrnMeshBinding); Search for this: return GrannyGetMeshBindingToBoneIndices(m_pgrnMeshBindingTemp); Replace with this: return (int*)GrannyGetMeshBindingToBoneIndices(m_pgrnMeshBindingTemp); Search for this: m_pgrnMeshDeformer = GrannyNewMeshDeformer(pgrnInputType, pgrnOutputType, GrannyDeformPositionNormal); Replace with this: m_pgrnMeshDeformer = GrannyNewMeshDeformer(pgrnInputType, pgrnOutputType, GrannyDeformPositionNormal, GrannyAllowUncopiedTail); ----- Open ModelInstanceUpdate.cpp. Search for this: GrannyUpdateModelMatrix(m_pgrnModelInstance, fSecondsElapsed, (const float *) pMatrix, (float *) pMatrix); Replace with this: GrannyUpdateModelMatrix(m_pgrnModelInstance, fSecondsElapsed, (const float *) pMatrix, (float *) pMatrix, false); ----- Open Material.cpp. Search for this: granny_variant twoSideResult = GrannyFindMatchingMember(pgrnMaterial->ExtendedData.Type, pgrnMaterial->ExtendedData.Object, "Two-sided"); if (NULL != twoSideResult.Type) GrannyConvertSingleObject(twoSideResult.Type, twoSideResult.Object, TwoSidedFieldType, &twoSided); Replace with this: granny_variant twoSideResult; if (GrannyFindMatchingMember(pgrnMaterial->ExtendedData.Type, pgrnMaterial->ExtendedData.Object, "Two-sided", &twoSideResult) && NULL != twoSideResult.Type) GrannyConvertSingleObject(twoSideResult.Type, twoSideResult.Object, TwoSidedFieldType, &twoSided, NULL); ----- Open ModelInstanceModel.cpp Search for this: return GrannyGetMeshBindingToBoneIndices(m_vct_pgrnMeshBinding[iMeshBinding]); Replace with this: return (int*)GrannyGetMeshBindingToBoneIndices(m_vct_pgrnMeshBinding[iMeshBinding]); ----- Navigate to the UserInterface project. Open UserInterface.cpp. Search for this (it's at the end of the file): static void GrannyError(granny_log_message_type Type, granny_log_message_origin Origin, char const *Error, void *UserData) { TraceError("GRANNY: %s", Error); } Replace with this: static void GrannyError(granny_log_message_type Type, granny_log_message_origin Origin, char const* File, granny_int32x Line, char const *Error, void *UserData) { TraceError("GRANNY: %s", Error); } Now rebuild the whole project! 3. Step: Go to the folder where we unziped the things of the first step and go to the lib folder. Copy the granny2.dll into your main client directory. Now you're finished and you have Granny 2.9. I hope this guide helped you! Special Thanks to Cryfact! Regards
  11. 39 points
    Hi, In this thread I will show you how to do an in-game ban for your GMs. First of all, you need to make a new column in the account.account. The name of the field should be reason and select varchar as type. Or just use this in your console to create the field: ALTER TABLE account ADD reason VARCHAR(256); Now open game/cmd.cpp and search for this: ACMD(do_block_chat); Add this under that: ACMD(do_ban); Search for this still in the game/cmd.cpp: { "block_chat_list",do_block_chat_list, 0, POS_DEAD, GM_PLAYER }, Make a new line and add this under that: { "ban", do_ban, 0, POS_DEAD, GM_IMPLEMENTOR }, At this point you can change the rights for the command: GM_PLAYER - do NOT choose this! GM_LOW_WIZARD GM_WIZARD GM_HIGH_WIZARD GM_GOD GM_IMPLEMENTOR Search for this event in game/cmd_gm.cpp: ACMD(do_block_chat) Add this under that: ACMD(do_ban) Now time to add the complete code to ACMD(do_ban): // Args char arg1[256], arg2[256], arg3[256]; // Local variables const char* szName; const char* szReason; int iDuration; one_argument(two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2)), arg3, sizeof(arg3)); // Invalid syntax if (!*arg1 || !*arg2 || !*arg3) { ch->ChatPacket(CHAT_TYPE_INFO, "Invalid Syntax, usage: <player name> <time in hours> <reason> tip: don't use spaces in the reason, use _"); return; } szName = arg1; iDuration = atoi(arg2); szReason = arg3; if (iDuration <= 0) { ch->ChatPacket(CHAT_TYPE_INFO, "Duration can't be 0 or minus."); return; } LPCHARACTER tch = CHARACTER_MANAGER::instance().FindPC(szName); if (!tch) { ch->ChatPacket(CHAT_TYPE_INFO, "%s is not playing", szName); return; } if (!tch->GetDesc()) { ch->ChatPacket(CHAT_TYPE_INFO, "%s don't have desc", szName); return; } if (tch == ch) { ch->ChatPacket(CHAT_TYPE_INFO, "What's wrong with you? Don't ban yourself"); return; } if (tch->GetGMLevel() > GM_PLAYER) { ch->ChatPacket(CHAT_TYPE_INFO, "Do not ban GMs"); return; } std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery("UPDATE account.account SET availDt = FROM_UNIXTIME(UNIX_TIMESTAMP(CURRENT_TIMESTAMP()) + %i), reason = '%s' WHERE id = %d", iDuration * 3600, szReason, tch->GetDesc()->GetAccountTable().id)); tch->GetDesc()->DelayedDisconnect(5); sys_log(0, "%s[%d] banned %s for %i hours with reason: %s", ch->GetName(), ch->GetPlayerID(), szName, iDuration, szReason); ch->ChatPacket(CHAT_TYPE_INFO, "%s has been banned for %i hours with reason: %s", szName, iDuration, szReason); Check how it works: /ban <player name> <duration in hours> <reason> Example: /ban Doe 24 Hacking In-game: Database, account table: syslog: Feb 10 03:30:15.890000 :: Sanchez[57735] banned Doe for 24 hours with reason: Hacking If you have any question or suggestion, please just reply to this topic. Kind Regards, Sanchez
  12. 37 points
    This guide will walk you through each step of installing the necessary daemons for a Metin2 server on FreeBSD. Asking for help setting up Metin2 on the official FreeBSD forums is not permitted, I suggest if you have issues to ask in this forum only. You may not need to install cURL, it depends on whether or not you'll host your website on the same server and use things that require cURL (such as automatic paypal transactions). It's recommended to host your website on a separate web server and not share the IP with anyone then run it through CloudFlare. A guide will be posted soon in these forums on how to run your website through CloudFlare while preventing CloudFlare IP resolvers from functioning. However, if you do run your website on another server I would recommend hosting it in the same datacenter because you'll need to use Remote MYSQL to access your database. - For sake of simplicity I'll be using "ee editor" for this guide. Most new people don't like vi anyway. If you're already familiar with vi, feel free to use that to edit text inside files instead. - To transfer files to and from your server, use WinSCP. - To enter commands into your server, use PuTTy. Please note that when the system asks you for a password in PuTTy you won't see it as you type it on the screen, be precise! - Pressing the TAB key in PuTTy will auto-complete as much as possible in the directory you're in. Downloads Libs: https://mega.co.nz/#!rExCyBba!dho0EjPjjHLzARsaQ3XU2yY38mpRBrf0YpilLo3aC4c 1. Updating Ports portsnap fetch extract portsnap update 2. Installing Python 2.7 cd /usr/ports/lang/python27 make -DBATCH install clean pro tip: Use the "-DBATCH" flag for a default installation of the port. Skip all those annoying prompts during installation. 3. Standard C++ Libraries fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/9.1-RELEASE/lib32.txz tar Jxpvf lib32.txz -C / rm lib32.txz Unrar "Libs.rar" and put the files in the "/usr/lib32" directory. 4. Compat7x Because Metin2 was originally meant to be run on FreeBSD 7, we need this so that it's compatible with FreeBSD 9. cd /usr/ports/misc/compat7x && make -DBATCH install clean pkg_add -r compat7x-amd64 5. Install & Configure MySQL 5.6 server cd /usr/ports/databases/mysql56-server make BUILD_OPTIMIZED=yes BUILD_STATIC=yes make WITH_XCHARSET=all install clean Now we make it start on each startup of the system. ee /etc/rc.conf Add a new line: mysql_enable="YES" Press ESC then save and close the file. service mysql-server start /usr/local/bin/mysqladmin -uroot password 'enterpassword' pro tip: "enterpassword" should be the password you choose, don't use "enterpassword" as your password. A long string of lower case and capital letters and numbers is the safest bet. Don't use words that can be found in a dictionary. Don't use passwords which are the same as other passwords of yours. You may not need to do this, but when I got an OVH server it messed up the installation of mysql (on 9.2). If you get an error about the mysql user account with the step above, just do this: pwd_mkdb -p /etc/master.passwd chown -R mysql /var/db/mysql && chgrp -R mysql /var/db/mysql Then repeat the step. 6. Adding your server files and Metin2 Database Extract your game.tar.gz containing all the Metin2 server files somewhere in your server. This is all you have to do to extract a .tar.gz file: tar -zxvf filename.tar.gz You should have your metin2 database inside of a tarball (.tar.gz file). For structure, it doesn't really matter as long as once you extract your tarball on your server it follows this file hierarchy: Now you should change the group and ownership of some files for your database: service mysql-server stop chown -R mysql /var/db/mysql && chgrp -R mysql /var/db/mysql service mysql-server start Setup an account for you to login to the database via Navicat and an account for your game cores to interact with your database using. For this example I'll use the username "rumor" for my account and "metin2" for the game core's account. Every password in this example will be "password" but please DO NOT use this as your password! If you have a static IP address and wish to restrict access to the database only to your IP, change the "%" sign to your IP. The "%" sign indicates that any IP address is allowed to connect to the database using the specified credentials. mysql -p Now enter the password you set with mysqladmin earlier... and you will see this prompt: mysql> This is where we set the actual permissions for the accounts up. GRANT ALL PRIVILEGES ON *.* TO 'rumor'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION; GRANT ALL PRIVILEGES ON *.* TO 'metin2'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION; quit pro tip: remember (or write down) this information because you will need it later. Setup your CONFIG files under each channel folder and the "auth" folder. All of these are found inside the Metin2 server files. PLAYER_SQL: localhost metin2 password player COMMON_SQL: localhost metin2 password common LOG_SQL: localhost metin2 password log The conf.txt file looks a little bit different and it's found in the "db" folder of your Metin2 server files. SQL_ACCOUNT = "localhost account metin2 password 0" SQL_PLAYER = "localhost player metin2 password 0" SQL_COMMON = "localhost common metin2 password 0" SQL_HOTBACKUP = "localhost hotbackup metin2 password 0" ~~~~ STOP HERE IF YOU'RE RUNNING YOUR WEB SERVER SOMEWHERE ELSE ~~~~ 7. Setting up web server for website and/or patcher Install nginx: cd /usr/ports/www/nginx make install clean Make sure these are selected with space bar: [X] HTTP_MODULE Enable HTTP module [X] HTTP_ADDITION_MODULE Enable http_addition module [X] HTTP_CACHE_MODULE Enable http_cache module [X] HTTP_GEOIP_MODULE Enable http_geoip module [X] HTTP_GZIP_STATIC_MODULE Enable http_gzip_static module [X] HTTP_IMAGE_FILTER_MODULE Enable http_image_filter module [x] HTTP_PERL_MODULE Enable http_perl module [X] HTTP_REALIP_MODULE Enable http_realip module [X] HTTP_REWRITE_MODULE Enable http_rewrite module [X] HTTP_STATUS_MODULE Enable http_stub_status module Press "Enter" when ready to continue. Install libtool cd /usr/ports/devel/libtool make install clean Install php5 cd /usr/ports/lang/php5 make config Make sure the following is selected with space bar then press "Enter": [X] FPM Build FPM version (experimental) Leave everything else default. then do this: make install clean ~~~~ If you need cURL support then do this, if not then skip this step: cd /usr/ports/lang/php5-extensions make config Make sure that the "CURL Support" is selected then press "Enter". Then do the installation and clean the directory: make -DBATCH install clean ~~~~ Time to configure your php.ini file... cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini Edit /usr/local/etc/php.ini in WinSCP using Notepad++. Firstly, set your "date.timezone" to the appropriate one. Choose from this list: http://php.net/manual/en/timezones.php Next, if you have something that needs to run large MYSQL queries you may run into some issues. Some website packages also can cause these problems. The issue is with memory usage. For security reasons there are limitations set on how much memory php is allowed to use. I suggest only modifying this IF you have problems loading memory-intensive pages. Just try to raise it a bit until it works, don't raise it to an excessively high number. I had to set mine to "512M" to make my queries work in my patcher. It can be set by just inputting numbers and they will be recognized as bytes, or you could use K, M, or G. memory_limit = 512M Installation of php-mysql5: cd /usr/ports/databases/php5-mysql make -DBATCH install clean If you've gotten this far, congratulations.. you're almost done! You need to create a folder for your website like this: mkdir /usr/local/www/nginx/domain.com Set the owner and permissions: chown www:www /usr/local/www/nginx/domain.com chmod 755 /usr/local/www/nginx/domain.com Customize this file to your needs and upload it to /usr/local/etc/nginx: If you're using cloudflare, uncomment the lines 38-57 by removing the "#". The reason for this is to ensure you get the real user IP in your logs rather than cloudflare's IP. If you want to allow directory listing.. ie: [url=http://domain.com/files]http://domain.com/files to present a visitor with a list of files they can access/download then uncomment lines 63 and 73. You MUST change the domain name to your own! Now you need to enable startup of php-fpm and nginx whenever your server is booted: ee /etc/rc.conf Add these lines: php_fpm_enable="YES" nginx_enable="YES" Start your services: service php-fpm start service nginx start Upload your website files to /usr/local/www/nginx/domain.com
  13. 35 points
    Hi guys, Since people are asking for a 34k client I have decided to release the World of Metin2 beta client from early last year. Many people have contributed to this release, namely the whole WoM team which as you may know is pretty big, but particularly Tim who created most of the scripts and the compiling stuff. Contents The package includes: bin folder: this is where you actually run the client. The client includes tim's granny 2.8 DLL and a .mix file that allows attacking on mounts made by Paylasici (DynamicPatcher.mix). Warning: metin2.bin may be identified by your antivirus as a threat. It's just packed with Themida. Why packed? because otherwise Tim's dll doesn't work. You will need to create the epk files first. A patch maker/uploader script is also included in this folder. data folder: the contents of the Eterpack archives, unpacked. Includes batch files to create the packs, an automatic XML generator (make_xml.py, configurable through make_xml.xml) and root/uiscript/locale pyc compiler. The data folders contain every official file (costumes pets etc) up to March 2013, and a few of our own. tools: includes FileArchiver, Tim's lz, and python22 (used by the compiling scripts). launcher: includes everything necessary to create your own official launcher Installation Unpack wherever you want Install Python2.7(if you don't have it already) and add your Python27 installation folder to the System Path Add the tools folder to the System Path Usage Edit the client to your liking and then run the appropiate make_*.bat file to compile the pack into the bin/pack folder. When done, make a copy of metin2.bin called metin2client.exe so you can test the client locally. Patch maker There is an official patch maker included under bin/make_patch.py configurable through Patch_config.txt, it will read an online crclist and a list of files / archives and create a zip file containing the updated archives (lz'ed) and the updated crclist. Syntax make_patch.py [-f filename] [-a packname] [-p patch (see PatchConfig.txt)] Example python make_patch.py -f pack/Index -a root -a uiscript -p patch_test Then you just need to upload this zip file to your patch root and unzip it. Regards World of Metin2 Client for metin2dev.org - Base.7z 95.9 MB https://mega.co.nz/#!WhpiVDBI!ipa7YoFKoo5Qnft7calTquWczM_WCScnyC3VQctUhNk World of Metin2 Client for metin2dev.org - Extra.7z 486.2 MB https://mega.co.nz/#!nhAV3RjY!e8ACrA-IwgwNk49vBAMBqa0ULf2tOZl5v8vcdLEpYZU
  14. 34 points
    June 17 2014 - I rewrote the whole the source. FAQ: How can I open the project, which version of Visual Studio do I need? I used Visual Studio 2013, but I'm sure you can open in 2012 too. What is CRC? You can learn more about Cyclic redundancy check here. How can I make a list for the patcher? You can use the lister tool, it's in the source. HOW TO MAKE IT WORKS: 1. Change the ServerURL variable in Globals.cs to your url 2. Build the project 3. Create a list with the lister tool (Example of the list) 4. Upload the files and the patchlist to your server (Example of the folder structure) Downloads: MEGA.CO.NZ If you have any question or suggestion please just reply to this topic. Kind Regards, Sanchez
  15. 33 points
    I go to release a simple system , to see the coins in the inventory. http://youtu.be/93aufcRE_4s REMEMBER: localeInfo is from binary r28k locale is from binary r36k First, go to uiinventory.py and now search: self.wndMoneySlot = self.GetChild("Money_Slot") And down put: self.wndMds = self.GetChild("Mds") self.wndMdsSlot = self.GetChild("Mds_Slot") Now, search def Destroy(self): self.ClearDictionary() .... .... self.wndMoney = 0 self.wndMoneySlot = 0 And down put: self.wndMds = 0 self.wndMdsSlot = 0 Now, Search: def RefreshStatus(self): And change to: def RefreshStatus(self): money = player.GetElk() self.wndMoney.SetText(localeInfo.NumberToMoneyString(money)) import constInfo self.wndMds.SetText(str(constInfo.mds) + " Md's") And down Put: def OnUpdate(self): import constInfo self.wndMds.SetText(str(constInfo.mds) + " Md's") The uiinventory is finished, save and close, now go to locale/xx/ui/inventorywindow.py. Search: ## Print { "name":"Money_Slot", "type":"button", "x":-68, "y":28, "horizontal_align":"center", "vertical_align":"bottom", "default_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "over_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "down_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "children" : ( { "name":"Money_Icon", "type":"image", "x":-21, "y":2, "image":"d:/ymir work/ui/game/windows/money_icon.sub", }, { "name" : "Money", "type" : "text", "x" : 5, "y" : 3, "horizontal_align" : "right", "text_horizontal_align" : "right", "text" : "123456789", }, ), }, And Down Put: { "name":"Mds_Slot", "type":"button", "x":-68, "y":48, "horizontal_align":"center", "vertical_align":"bottom", "default_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "over_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "down_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "children" : ( { "name":"Mds_Icon", "type":"image", "x":-21, "y":2, "image":"d:/ymir work/ui/game/windows/money_icon.sub", }, { "name" : "Mds", "type" : "text", "x" : 5, "y" : 3, "horizontal_align" : "right", "text_horizontal_align" : "right", "text" : "123456789 Md's", }, ), }, Remember change the "x" and "y". Now, go to game.py in root. Search: def __ServerCommand_Build(self): serverCommandList={ And down put: #Carga Mds Start "Mds" : self.__Mds, #Carga Mds End and now, go to the end and put: def __Mds(self, coins): import constInfo constInfo.mds = int(coins) Save and close. Now go to constinfo.py and put mds = 0 And Here the quest: quest mds begin state start begin when login begin loop_timer("carga_mds", 10) end when carga_mds.timer begin local coins = mysql_query("SELECT coins from account.account WHERE id="..pc.get_account_id().." LIMIT 1;")[1][1] cmdchat("Mds "..coins) end end end This is my release in this forum. Sorry my bad english.. I'm Spanish. If you don't know how put, upload my archives uiinventory and inventorywindow.py https://mega.co.nz/#!R9A3SD6Q!IFZ38BXrwGOt0Z8N3qT9g5vr5XAa4DdKdeAf2KRlPEY
  16. 33 points
    For years now we've relied on various file leaks which were usually in some Asian language, up until 2010 when someone (nico_w?) released the SG database. Even after this date, we continued to use our old file structures and methods, and old bash scripts to manage our servers. In 2013, some files were released which came from a private server that was based off the SG files. This isn't a thread to talk about who's right or wrong, or who did what work or anything like that... just a place to release files. The reason this release is beneficial is we've never really had a full release of "clean" and "untouched" files. Every time someone releases files they have some stupid backdoor added or are heavily modified from the original. The goal of this release is to get the files to be as close as possible to an official server, and remove things like Xtrap which none of us are using anyway. Official files is what all the pservers are based off of, so having the official structure just makes sense. There are several threads online with files that have been modified by some person but I never see threads with the files the way they originally came. These files in the game folder are from July, 2013 and the game/db cores are fully unmodified and straight from YMIR. That includes lack of modification to make them compatible with certain clients or anything like that. Garbage files like old logs are removed and ready to be generated when you launch your server. These are meant to be a "base server" for the one you want to create. For this reason, there are no customized quests or new items and stuff like that. It's only what SG had in 2013 of July. The database structure is the one from this thread: http://metin2dev.org/board/topic/174-complete-34k-db-structure/#entry950 The item_proto and mob_proto is the one from SG in July 2013. I've included a tool in the download as well used to dump the server proto to the client. Since the goal is purity of files, but some files had to be slightly modified for simplicity (and so they run at all) here's the list of things changed/removed: - Removed panama folder. - Removed old log files and pid files, etc.. - Removed Xcrap stuff - Removed all traces to the above (Symlinks) from install.sh. - Removed cshybridcrypt files. - Modified CONFIG file to guide you into configuration for your own usage. - The quests are from the leak of pserver files based off SG. Some of these may or may not work fully. - Timebomb fix applied (Updated: March 13th, 2014) Now in order to use these files: 1. Upload and untar the database and server files. "untouched_34083_db.tar.gz" goes in "/var/db". 2. Navigate with PuTTy to the game folder as a root user and run this command: "chown -R metin2 .". 3. Navigate to the game folder as the metin2 user and run install.sh. This will setup all the permissions and symlinks correctly. 4. Restart your database with the command "service mysql-server restart". The server can be started and stopped by executing "run.sh" and "shutdown.sh" and logs can be cleared by executing "clear.sh". All of these are found in the game folder. Make sure to "/shutdown" ingame before using "shutdown.sh" or you may have data loss. Don't be alarmed when running the shutdown script, it's normal for PuTTy to not give you a prompt for a while (you haven't disconnected from SSH). How to convert the database proto to a perfect client-side proto: 1. Grab the following files from the conf folder in the server files: mob_proto.txt mob_names.txt item_proto.txt item_names.txt 2. Put those files in a folder with the "dump_proto.exe" tool and run it. It will automatically generate the protos for your client assuming you have followed the correct structure of the txt files. Download: https://mega.co.nz/#!aNp3CJCa!UYpjfJvzWPDejhOTysXTqa-o0bQ_JsC5Q6emudCCQc4 (Updated: March 13th, 2014) - No password (I don't believe in putting passwords on archives released to the public).
  17. 32 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
  18. 32 points
    I've been using this method since August 1st, 2013 and it's been working great. Most cheats are automatically blocked, just make sure you check sites that post metin2 cheats frequently to make sure there aren't any new ones that actually work. Those ones will need to be manually added. I'll begin by listing the features of using this method: - DLL files can normally be renamed to .mix, .dll, or .flt and inserted into the client before launching and they would inject the dll into the client. With this protection those files are deleted on client launch, there's no way around this. - MSS32.dll is an important file for protecting against cheats, and it's being checked by the client to ensure it's not tampered with. - There are exploits out there (and possibly more to be found or more which aren't yet released publicly) which this protection method can help detour. It hides the revision of the binary from the Details tab in Windows Properties for this reason. If they don't know which version you're using it's a good start already to protect against exploiting the binary. - This will prevent cheats from loading whether the player sets them up to automatically inject them on startup or while the game is already on. - This DOES block m2Pythonloader and Kernel Detective. - This DOES block the new ProDamage hack by lalaker1 with randomized window classes as well as switchbotv3. - I don't know of any cheats that actually work with this setup active... - Works even on lower end computers without a problem. - It restricts debugging the client. Caveats: - About 25% of Windows 8 users can't run the client. I'm not entirely sure what the problem is but it appears to be an issue from Windows 8 (thanks again Microshit). The user is warned upon running the client of a "FATAL ERROR" in which the Index file located in the pack folder is missing. It isn't missing. So far, the only workaround known for this issue is to run the game using Razer Game Booster. I feel that it's worth it because it stops cheaters from playing. It's up to you if you want to lose some of your Windows 8 users. UPDATE 2/11/2014: If you purchase the latest version of the software it WILL work with Windows 8! - Virtual Box: Bug fixed loading virtual dll files under Windows 8 x64 - Virtual Box: Bug fixed running some virtual exe files on Windows 8 - It may be detected by antivirus software as a virus because it's encrypted, it has no way of knowing what the file is really doing or really contains. Currently it's only detected by 2/50 scanners on Virustotal.com and it's not a definitive sign of a virus, only a warning that the virus scanner can't read the file. https://www.virustotal.com/en/file/f15ffd6c32d13ce7ac013c535f7abec22531093505609d082c9afa97db8f0009/analysis/1391644127/ - You can't run the command prompt while the game is open, nor can you have one open when attempting to launch the game. Setup Instructions: Open the file "prototype.py" in the root archive and find this: def RunApp(): musicInfo.LoadLastPlayFieldMusic() app.SetHairColorEnable(constInfo.HAIR_COLOR_ENABLE) app.SetArmorSpecularEnable(constInfo.ARMOR_SPECULAR_ENABLE) app.SetWeaponSpecularEnable(constInfo.WEAPON_SPECULAR_ENABLE) app.SetMouseHandler(mouseModule.mouseController) wndMgr.SetMouseHandler(mouseModule.mouseController) wndMgr.SetScreenSize(systemSetting.GetWidth(), systemSetting.GetHeight())On a new line enter this: injectionprotection = os.listdir('.') injectionprotection.sort() for Data in injectionprotection: if Data.find('.mix') != -1 or Data.find('.m3d') != -1 or Data.find('.flt') != -1 or Data.find('.asi') != -1: os.remove(Data)Add the following to the imports: import osSave and close the file. Now we'll block the introLogin.py bug allowing users to run client extractors or python cheats on client launch. Open "intrologin.py" from the same archive and find this: self.__LoadLoginInfo("loginInfo.py")Replace the entire line with this, edit the message to your liking: if not os.path.exists('logininfo.py') and not os.path.isfile('logininfo.py'): self.__LoadLoginInfo("loginInfo.py") else: dbg.LogBox('Ah so you want to try to extract the client?n' 'Or maybe you want to run your favorite cheat?n' 'Not gonna happen...n' 'It seems I have already thought of this.n' 'I am ATLEAST one step ahead of you...n' '------------------------------------------------n' 'n' "TRY HARDER BRO") exception.Abort("Unsupported file, please delete it. (TRY HARDER BRO)") # Syserr.txt returnAdd the following to the imports: import osSave and close the file. Now you need Enigma protector. You can purchase it here: http://www.enigmaprotector.com/en/order.html or download an older cracked version here: https://mega.co.nz/#!fBY1zRia!ib0eiy6Tq9FLFOphKJrceX2fMIlL_KiDjOlRCfuIhW4 You will also need a plugin created by my friend Anfidya: https://mega.co.nz/#!vVgxwI4Q!1GQ5GgfbvBHlkYc5O23IJ_Woy0OBJyIlh_bqNh0dDhM Place the .dll file in the "Plugins" directory of your installation of The Enigma Protector. Here's the Enigma settings file already ready-to-go minus some minor changes you need to make: https://mega.co.nz/#!LVJ1wIYa!cO9C2Vim_Gk8Lklh86mxK5FKTqOug8FltQOkPYYT-NE Now you will need to maintain two versions of your client, one for the public and one private one. Copy your client to another hard drive or directory on your computer. You should have two identical copies of the same game but you're going to do all your work on the private client from now on. You will keep your eix and epk archives in the pack folder of the private client and do your work there. You need to keep a client binary in your private client which isn't encrypted by Enigma so that you can create a new one whenever necessary. When you release a patch you will need to re-pack the binary even if you didn't change anything there or in Enigma. All it takes is a change of any of the archive files for the binary to need a re-encryption by Enigma. This is because the eIndex files are going to be hidden inside the binary. The miles folder can be used to inject cheats too, so we're going to hide that and all it's contents in the binary as well. The binary is protected from debuggers and people can't just unpack it with WinRAR or something to get files out of it. Despite Enigma offering messages displayed before client closing, I don't use them because they allow the client to stay open until the user clicks the OK button. This means they can just sit there with the cheat running and move the popup window. I've included my settings file for Enigma. You need to customize the Settings in the INPUT tab: - Modify the "file to protect" and "output protected file name" using the Browse buttons. - Modify the "Name" - Modify the "Version" (hint: don't put it the same as your binary version) You also have to edit the file name if you aren't going to call your client metin2.bin (note that on some newer binaries it has to begin with "metin2" or it doesn't work. I'm sure there's a way to edit this but it isn't so important. It's alright to show a message before termination, to assist the player with the reason why it won't work. This is only going to check during launch of the application and the file name can't be changed while the application is already running. You should go to "External Files" and delete my MSS32.dll file by clicking the red "X" and add your own MSS32.dll file to make sure it's the correct one. If you skip this step and your MSS32.dll doesn't match mine EXACTLY then the client will fail to run. Now you need to add some custom rules for cheat detection: You can see here I've already setup the miles folder for you. You need to click "pack" so that it's highlighted like in the image then click "Add" then "Add File(s)" and select all your .eix files as well as your Index file from the pack folder. An easy way to do this is set your Windows Explorer to detailed view and organize by File Type then use SHIFT + click to select a beginning and ending file. This next part is mostly preference, and to avoid letting anyone know which version you use for a binary. It adds customization to your client, it's a fancy thing that isn't too necessary but if you want to change this stuff go for it! An example of what that does: Now you just press "Protect". You need to copy your new protected bin to your Public Client and go delete the entire "miles" folder as well as the contents of the folder from your Public Client folder. Also go into the "pack" folder of your Public Client and delete "Index" and ALL of your ".eix" files (sort with detailed view again). In the end you should have a Public Client like this or very similar: Your Private Client should look something like this:
  19. 31 points
    Hi everyone, It's finally time to open a topic for the small tutorials, it's better than flooding the board with one sentence topics. 1. Binary name check: Sure, it's possible to do it on client-side, but if we can do it on server-side, theres no reason to do it on client-side. 1. Search for this function in game/input.cpp: void CInputProcessor::Version(LPCHARACTER ch, const char* c_pData) 2. Replace the entire function with this: if (!ch) { return; } TPacketCGClientVersion * p = (TPacketCGClientVersion *) c_pData; // If the file name is not metin2client.exe and the GM level is not equal with GM_IMPLEMENTOR kick the player if (strcmp(p->filename, "metin2client.exe") && ch->GetGMLevel() != GM_IMPLEMENTOR) { // immediately close the connection with the player sys_err("%s[%d] has been disconnected: %s", ch->GetName(), ch->GetPlayerID(), p->filename); ch->GetDesc()->SetPhase(PHASE_CLOSE); return; } sys_log(0, "VERSION: %s %s %s", ch->GetName(), p->timestamp, p->filename); ch->GetDesc()->SetClientVersion(p->timestamp); 2. Block the drop hacks: This issue is surely known by everybody, the server gets overloaded when dropping too many items in short time. 1. Open game/char_item.cpp and search for this: if (pkItemToDrop->AddToGround(GetMapIndex(), pxPos)) 2. Add this under that: // Clear the variable, it looks the player does not dropped any item in the past second. if (thecore_pulse() > LastDropTime + 25) CountDrops = 0; // It looks the player dropped min. 4 items in the past 1 second if (thecore_pulse() < LastDropTime + 25 && CountDrops >= 4) { // Set it to 0 CountDrops = 0; sys_err("%s[%d] has been disconnected because of drophack using", GetName(), GetPlayerID()); // Disconnect the player GetDesc()->SetPhase(PHASE_CLOSE); return false; } 3. Search for this still in game/char_item.cpp: LogManager::instance().ItemLog(this, pkItemToDrop, "DROP", szHint); 4. Add this under that: LastDropTime = thecore_pulse(); CountDrops++; 5. Open game/char.h and add these: int LastDropTime; int CountDrops; 6. Open game/char.cpp and search for this: void CHARACTER::Initialize() 7. Add these to the function: CountDrops = 0; LastDropTime = 0;
  20. 31 points
    Hey guy :3 Well... here you will find all my graphics i released till now, i really hope you like some of it ^-^ [#1] Download --------------------------------------------------------------------- [#2] Download --------------------------------------------------------------------- [#3] Download --------------------------------------------------------------------- [#4] Download --------------------------------------------------------------------- [#5] Download --------------------------------------------------------------------- [#6] Download --------------------------------------------------------------------- [#7] Download --------------------------------------------------------------------- [#8] Download --------------------------------------------------------------------- [#9] Download --------------------------------------------------------------------- [#10] Download --------------------------------------------------------------------- [#11] Download --------------------------------------------------------------------- [#12] Download --------------------------------------------------------------------- [#13] Download --------------------------------------------------------------------- [#14] Download --------------------------------------------------------------------- [#15] Download --------------------------------------------------------------------- [#16] Download --------------------------------------------------------------------- [#17] Download --------------------------------------------------------------------- [#18] Download --------------------------------------------------------------------- [#19] Download --------------------------------------------------------------------- [#20] Download --------------------------------------------------------------------- [#21] Download --------------------------------------------------------------------- [#22] Download --------------------------------------------------------------------- [#23] Download --------------------------------------------------------------------- [#24] Download ---------------------------------------------------------------------
  21. 31 points
    Since many people may need it, here's my complete official db structure for game 34k, including: - All Indexes and Options included - All auto increment values are set to 1 (except player that is set to 100 to avoid some issues) - Some non-fatal errors caused by original YMIR table structure are fixed 34k_official_db_structure.zip 69 KB https://mega.co.nz/#!SB1CzYyI!T8c_wILefEJBpYjNJXKW2BVaPzp2SRMjNuVDh2WEXkU Tables refine_proto (official, valid for all game revisions) object_proto (modified from official with smaller limits for buildings so they actually fit in your land) skill_proto (SG, has a couple of small differences in regards to GF) shop_item (SG)
  22. 31 points
    The World of Metin2 Monarch System is composed of two parts. For the system to work fully you need to use db core 33820 or a compiled db where this bug is solved (look dif part at the end. If anybody wants to create difs for other revisions, you are welcome to do so.) Monarch Election Authors: Musicinstructor and me (Shogun) Usage: the election has 3 stages: Candidacy, Election and Crowning. All the stages can be started sucessively from the Archer Guardian NPC in town. - During Candidacy phase, all players over level 65 can apply for election by paying some Yang. Up to 8 players can apply per kingdom. - During Election phase, players will drop an item called Certificate of Loyalty (60004) which allows them to cast a vote. - Finally, you can finish the election, which will announce the winners automatically. The new King / Queen will receive a new Hwang Armor on login and the Angel's Blessing item. For the quest to work you need the following preparation: 1) Create an empty file share/data/monarch_election in your server with the touch command. 2) Fill the table player.monarch with some random values (use the PID of your GM for example). You can also use this table: DROP TABLE IF EXISTS `monarch`; CREATE TABLE `monarch` ( `empire` int(10) unsigned NOT NULL DEFAULT '0', `pid` int(10) unsigned DEFAULT NULL, `windate` datetime DEFAULT NULL, `money` bigint(20) unsigned DEFAULT NULL, PRIMARY KEY (`empire`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -- ---------------------------- -- Records of monarch -- ---------------------------- INSERT INTO `monarch` VALUES ('1', '266', '2014-02-04 04:36:55', '0'); INSERT INTO `monarch` VALUES ('2', '188', '2013-11-07 20:10:00', '0'); INSERT INTO `monarch` VALUES ('3', '170', '2013-09-16 22:12:06', '0');3) Make sure 60004 exists in item proto and has a suitable icon for it. The quest Add this to locale.lua Add this also to questlib.lua Items for item_list.txt 60004 ETC icon/item/60002.tgaitem_proto.txt entries for the certificate, blessing and armors 60004 loyalty_certificate ITEM_UNIQUE UNIQUE_NONE 1 ANTI_GET | ANTI_DROP | ANTI_SELL | ANTI_SAVE | ANTI_GIVE | ANTI_PKDROP | ANTI_STACK | ANTI_MYSHOP | ANTI_SAFEBOX LOG NONE NONE 0 0 0 0 0 LIMIT_NONE 0 LIMIT_NONE 0 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 604800 0 1 0 0 0 0 0 0 70021 ±ºÁÖÀÇ ÁõÇ¥ ITEM_QUEST 0 1 ANTI_DROP | ANTI_SELL | ANTI_GIVE | ANTI_STACK | ANTI_MYSHOP | ANTI_SAFEBOX NONE NONE NONE 0 0 0 0 0 LIMIT_NONE 0 LIMIT_NONE 0 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0 11971 Ȳ»óÀü°© ITEM_ARMOR ARMOR_BODY 2 ANTI_ASSASSIN | ANTI_SURA | ANTI_MUDANG | ANTI_DROP | ANTI_SELL | ANTI_GIVE | ANTI_STACK | ANTI_MYSHOP ITEM_TUNABLE WEAR_BODY NONE 0 0 0 0 0 LEVEL 50 LIMIT_NONE 0 APPLY_MOV_SPEED 10 APPLY_RESIST_MAGIC 20 APPLY_ATTBONUS_HUMAN 15 0 350 0 24 0 100 100 3 0 11972 ȲÀÇ ITEM_ARMOR ARMOR_BODY 2 ANTI_MUSA | ANTI_SURA | ANTI_MUDANG | ANTI_DROP | ANTI_SELL | ANTI_GIVE | ANTI_STACK | ANTI_MYSHOP | ANTI_SAFEBOX ITEM_TUNABLE WEAR_BODY NONE 0 0 0 0 0 LEVEL 50 LIMIT_NONE 0 APPLY_MOV_SPEED 10 APPLY_RESIST_MAGIC 20 APPLY_ATTBONUS_HUMAN 15 0 350 0 24 0 100 100 3 0 11973 ÁøȲ»ó°© ITEM_ARMOR ARMOR_BODY 2 ANTI_MUSA | ANTI_ASSASSIN | ANTI_MUDANG | ANTI_DROP | ANTI_SELL | ANTI_GIVE | ANTI_STACK | ANTI_MYSHOP | ANTI_SAFEBOX ITEM_TUNABLE WEAR_BODY NONE 0 0 0 0 0 LEVEL 50 LIMIT_NONE 0 APPLY_MOV_SPEED 10 APPLY_RESIST_MAGIC 20 APPLY_ATTBONUS_HUMAN 15 0 350 0 24 0 100 100 3 0 11974 Ȳ»óÀÇ ITEM_ARMOR ARMOR_BODY 2 ANTI_MUSA | ANTI_ASSASSIN | ANTI_SURA | ANTI_DROP | ANTI_SELL | ANTI_GIVE | ANTI_STACK | ANTI_MYSHOP | ANTI_SAFEBOX ITEM_TUNABLE WEAR_BODY NONE 0 0 0 0 0 LEVEL 50 LIMIT_NONE 0 APPLY_MOV_SPEED 10 APPLY_RESIST_MAGIC 20 APPLY_ATTBONUS_HUMAN 15 0 350 0 24 0 100 100 3 0 Angel's Blessing Quest written by me and loosely based in the official quest used by Metin2 US. This is the item the Monarch can use to cast his powers, such as healing and attacking buffs which affect all the players from his kingdom in the same map; or summoning of different bosses and Guardians which only attack players from enemy kingdoms. It's an original YMIR item and the vnum is 70021. Instructions are included in the quest for the rookie kings/queens. Preparation: 1) Set MonarchHealGold event flag to an appropiate value (this is the cost of a monarch buff that heals everyone on the map) 2) Edit the list of bosses and their cost to your desires The quest: The function oh.takemonarchmoney() used in the angel's blessing quest is bugged on all official db cores. This is fixed in Vanilla Core 2.2+. For db 33820 here is a dif made by Paylasici: [UNSTRIPPED] db_r33820_32 000A30DD: 3B 20For db 40146 here's another dif made by PACIFICADOR db_r40146 000A5015: 3B 20 It is possible that something is missing in that case let me know here your answers are appreciated
  23. 30 points
    Put the content that the exe is in this path D:/ymir work/WorldEditor_en.exe Download
  24. 28 points
    Welcome to the second part of my guide series. This time I'll tell you how you can compile with gcc48 or even gcc49 like it's the case in vanilla and how you can use c++11 which will allow much more and faster instructions than the old one. At first we need to have a look at our Makefile. Make sure you edited the Line SVN_VERSION so you won't receive any errors. Try it e. g. to SVN_VERSION = mt2 Next, you'll have to declare what compiler you want to use. Of course you first need to install the compiler, but I guess it's clear (if you haven't done so, just use cd /usr/ports/lang/gcc49 or even 48 and use make install clean). The line normally say: CC = g++ This is the standard compiler. You may want to change this line to: CC = g++49 Or if you're using 48, change it to CC = g++48 Now before you compile it, you'd recompile all needed libs with gcc48/gcc49 too! So change the compiler in the makefile and recompile the sources in the following directories: libgame/src libpoly libserverkey libsql libthecore/src And then you need to recmopile cryptopp with the newer gcc version too! It's located in the Extern/cryptopp-directory. Now you can compile your game and even your db source with the newer gcc version. You may experience a much smaller file size. The newer compilers will produce an even more faster and smaller gamefile than before. Oh and if you want to carry out the lib-files you're using on your compiling machine (to make sure everything runs smoothly) you may use the following CFLAG: -Wl,-rpath,/usr/local/lib32/metin2 You can change the path to whatever you want! If you specify this, you instruct the linker to use this path so whenever you start your game/dbcache it'll first look in the given directory for the right libs and then, if it can't find the libs there, it'll look elsewhere. Using c++11 is a must-have if you want to make new statements. The source code how to load the database without txt-files needs the newer c++ version, so you'll have to upgrade at least the dbcache for it. But you'll experience even more smaller file sizes with this change so it keeps up with more and more advantages. First you may want to specify the new CFLAG. It's called: -std=c++11 This tells the compiler to use c++11. Keep in mind that not every compiler can use c++11! The newer gcc version can deal with it without any problems. If you compile your source then, you may find a new error occuring! Open every .cpp and .h-file in Notepad++ and do the following things (you can use the mass replacement of Notepad++): replace typeof with __typeof replace auto_ptr with unique_ptr Watch out for the common-directory too! Then you can recompile the source and it's done! Oh and for this you don't need to compile every other sourcecode with c++11. You can e. g. only compile the dbcache with it. Last small hint: You can play with the tuning flags to get even more optimization. -O2 can sometimes be good, but sometimes it's better to use others flags. You can even use -O3 or -Ofast. But be careful with this and consider using -fstrict-aliasing so the compiler won't optimize instructions that'd lead into a crash if it'd optimize them. And always: Pay attention to the warnings your compiler throws at you! They aren't there to just "hang out". They'd lead into crashes, so care about them. Lastly I hope you enjoyed the guide. As in the last one, please tell me if it's good or not and if you have any questions: Feel free to ask.
  25. 26 points
    Today I release a high-level map made by YMIR and used only in the now closed Korean server. It includes some unique mobs. Everything is in the package, except the regen which is buggy (the groups in regen.txt don't seem to have an entry in groups.txt), if someone wants to create a regen (With BlackYuko's Map Converter for example) I will add it to the package Some screens Included: Map (client & server) , textureset and terrainmaps Mobs (client & server) and mob_proto Minimap https://mega.co.nz/#!LRF2hA5D!WgEpQAxJQBVuY3_whtH-BSDbi_WSJnf67Eoedali__Q