Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/11/20 in all areas

  1. The problem is the m_Victim, each LPCHARACTERS stores the target and, even if ChangeVictimByAggro(args) won't be executed since type = DAMAGE_TYPE_POISON, the monster will keep the target pointer to their last victim, you need to also remove the resurrected LPCHARACTER as victim of nearby monsters. To do so you can use some simple structs, I already posted this solution for Invisibility skill. in char.cpp find void CHARACTER::ReviveInvisible(int iDur) and replace whole function struct RemoveInvisibleVictim { RemoveInvisibleVictim(LPCHARACTER pkOldVictim) { m_pkOldVictim = pkOldVictim; } void operator () (LPENTITY ent) { if (ent->IsType(ENTITY_CHARACTER)) { LPCHARACTER pkChr = (LPCHARACTER) ent; if (pkChr && pkChr->IsMonster()) { LPCHARACTER pkVictim = pkChr->GetVictim(); if (pkVictim && pkVictim == m_pkOldVictim) { LPCHARACTER new_victim = pkChr->GetNewNearestVictim(pkChr, m_pkOldVictim); pkChr->SetVictim(new_victim); } } } } LPCHARACTER m_pkOldVictim; }; void CHARACTER::ReviveInvisible(int iDur) { if (GetSectree()) { RemoveInvisibleVictim f(this); GetSectree()->ForEachAround(f); } AddAffect(AFFECT_REVIVE_INVISIBLE, POINT_NONE, 0, AFF_REVIVE_INVISIBLE, iDur, 0, true); } in char_battle.cpp add (and define it in char.h: LPCHARACTER GetNewNearestVictim(LPCHARACTER pkChr, LPCHARACTER pkVictimOld); ) LPCHARACTER CHARACTER::GetNewNearestVictim(LPCHARACTER pkChr, LPCHARACTER pkVictimOld) { if (NULL == pkChr) pkChr = this; float fMinDist = 99999.0f; LPCHARACTER pkVictim = NULL; TDamageMap::iterator it = m_map_kDamage.begin(); while (it != m_map_kDamage.end()) { const VID & c_VID = it->first; ++it; LPCHARACTER pAttacker = CHARACTER_MANAGER::instance().Find(c_VID); if (!pAttacker) continue; if (pAttacker->IsAffectFlag(AFF_EUNHYUNG) || pAttacker->IsAffectFlag(AFF_INVISIBILITY) || pAttacker->IsAffectFlag(AFF_REVIVE_INVISIBLE)) continue; float fDist = DISTANCE_APPROX(pAttacker->GetX() - pkChr->GetX(), pAttacker->GetY() - pkChr->GetY()); if (fDist < fMinDist && !pAttacker->IsDead() && pAttacker != pkVictimOld) { pkVictim = pAttacker; fMinDist = fDist; } } return pkVictim; } And then clean some miscoding: In char_affect.cpp at CHARACTER::AddAffect(args...) if bool bOverride (one of the function arguments) is true it will first reset a said flag calling if (pkAff && bOverride) { ComputeAffect(pkAff, false); // if (GetDesc()) SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn); } WE change it as follows if (pkAff && bOverride) { ComputeAffect(pkAff, false, true); // ComputeAffect(Affect, !bOvveride, bOverride); if (GetDesc()) SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn); } But we do not need to reset said flag early in the function if we are going to set it back few moments later so we can change CHARACTER::ComputeAffect(args..) as follows: find void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd) if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END) { if (!GetGuild()) return; if (!GetGuild()->UnderAnyWar()) return; } if (pkAff->dwFlag) { if (!bAdd) m_afAffectFlag.Reset(pkAff->dwFlag); else m_afAffectFlag.Set(pkAff->dwFlag); } replace with void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd, bool bTemp) { if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END) { if (!GetGuild()) return; if (!GetGuild()->UnderAnyWar()) return; } if (pkAff->dwFlag) { if (!bAdd && !bTemp) m_afAffectFlag.Reset(pkAff->dwFlag); else if (bAdd) m_afAffectFlag.Set(pkAff->dwFlag); } //HEADER char.h find void ComputeAffect(CAffect * pkAff, bool bAdd); replace with void ComputeAffect(CAffect * pkAff, bool bAdd, bool bTemp = false); tested and working.
    2 points
  2. M2 Download Center Download Here ( Internal ) Download Here ( GitHub )
    1 point
  3. M2 Download Center Download Here ( Internal ) 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: [Hidden Content] 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: [Hidden Content] 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=[Hidden Content] 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
    1 point
  4. Thank you guys! I found this too on char_affect.cpp if (GetPoint(POINT_HP_RECOVERY) > 0) { if (GetMaxHP() <= GetHP()) { PointChange(POINT_HP_RECOVERY, -GetPoint(POINT_HP_RECOVERY)); } else { int iVal = MIN(GetPoint(POINT_HP_RECOVERY), GetMaxHP() * 7 / 100); PointChange(POINT_HP, iVal); PointChange(POINT_HP_RECOVERY, -iVal); } } I changed the " * 7 / 100 " part with 2 / 100 so now i should get 2% of hp with automatic potion with each tick of heal
    1 point
  5. I don't know how this 'petsystem' works, but i think the condition what he had is to check if the skill slot value isn't -1 or 0 like. You replace the condition for no reason, i think you didn't understand the boolean conditions. -1 to -2147483647 - True 1 to 2147483647 - True 0 - False 1 - True So, with your condition the loop will count the -1 skill slot value too.
    1 point
  6. Metin2Rage sf is the evil. Find other files trust me.
    1 point
  7. in char_skill.cpp //in: int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel) //bellow: if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY)) pkVictim = this; // #ifdef ENABLE_WOLFMAN_CHARACTER // else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY)) // pkVictim = this; // #endif //1-add: if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY2) && !GetParty() && !pkVictim) pkVictim = this; //in bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaster) //below if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY)) pkVictim = this; #ifdef ENABLE_WOLFMAN_CHARACTER else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY)) pkVictim = this; #endif //2-add if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY2) && !GetParty() && !pkVictim) pkVictim = this; //below if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY)) ComputeSkill(dwVnum, this); #ifdef ENABLE_WOLFMAN_CHARACTER else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY)) ComputeSkillParty(dwVnum, this); #endif //3-add else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY2) && !GetParty() && !pkVictim) ComputeSkill(dwVnum, this); else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY2) && GetParty()) { FPartyPIDCollector f; GetParty()->ForEachOnMapMember(f, GetMapIndex()); for (std::vector <DWORD>::iterator it = f.vecPIDs.begin(); it != f.vecPIDs.end(); it++) { LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(*it); ComputeSkill(dwVnum, ch); } } and then you have to add the flag " SKILL_FLAG_PARTY2 " after that go to your skill proto add new flag "party2 ", then set the skills that you want to be used with and without a group the reason why i added new flag is that there are some skills like lycan buff and shaman healing cannot be used to other people without group hopefully it fix your problem
    1 point
  8. The idea is good, but the code is bugged and unreadable, here're the bugs: text = '1kks' ValueError: invalid literal for int() with base 10: '1000000s' text = '1kk500' 1000000500 text = '1abcd' '1abcd' If I'm the one who do this, i would do it more extendable and using a proficient way. [Hidden Content] At least, keep the copyright.
    1 point
  9. I know what they mean.We are talking about wrong codes, not efficient
    1 point
  10. Kimetsu no Yaiba ( Demon Slayer) Trailer: Ever since the death of his father, the burden of supporting the family has fallen upon Tanjirou Kamado's shoulders. Though living impoverished on a remote mountain, the Kamado family are able to enjoy a relatively peaceful and happy life. One day, Tanjirou decides to go down to the local village to make a little money selling charcoal. On his way back, night falls, forcing Tanjirou to take shelter in the house of a strange man, who warns him of the existence of flesh-eating demons that lurk in the woods at night. When he finally arrives back home the next day, he is met with a horrifying sight—his whole family has been slaughtered. Worse still, the sole survivor is his sister Nezuko, who has been turned into a bloodthirsty demon. Consumed by rage and hatred, Tanjirou swears to avenge his family and stay by his only remaining sibling. Alongside the mysterious group calling themselves the Demon Slayer Corps, Tanjirou will do whatever it takes to slay the demons and protect the remnants of his beloved sister's humanity.
    1 point
  11. Very thanks @Mark for help with modeling <3 Best regards oncemoron
    1 point
  12. M2 Download Center Download Here ( Internal ) Download Here ( GitHub ) Hello, came by to share something simple yet helpful for players, someone requested me this feature that allows you to input money with k format on the pick money dialog window, this will enable you to input “1kk” instead of “1000000” Hope it comes in handy for who is planning to use it.
    0 points
  13. Hello, Corrections of some syntax error made by Ymir; cmd_general.cpp Find: ACMD(do_shutdown) { if (NULL == ch) { sys_err("Accept shutdown command from %s.", ch->GetName()); } TPacketGGShutdown p; p.bHeader = HEADER_GG_SHUTDOWN; P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShutdown)); Shutdown(10); } Replace: ACMD(do_shutdown) { if (!ch) return; sys_err("Accept shutdown command from %s.", ch->GetName()); TPacketGGShutdown p; p.bHeader = HEADER_GG_SHUTDOWN; P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShutdown)); Shutdown(10); } Dungeon.cpp Find: float CDungeon::GetUniqueHpPerc(const std::string& key) { TUniqueMobMap::iterator it = m_map_UniqueMob.find(key); if (it == m_map_UniqueMob.end()) { sys_err("Unknown Key : %s", key.c_str()); return false; } return (100.f*it->second->GetHP())/it->second->GetMaxHP(); } Replace: float CDungeon::GetUniqueHpPerc(const std::string& key) { TUniqueMobMap::iterator it = m_map_UniqueMob.find(key); if (it == m_map_UniqueMob.end()) { sys_err("Unknown Key : %s", key.c_str()); return 0.0f; } return (100.f*it->second->GetHP())/it->second->GetMaxHP(); } ClientManager.cpp Find: if (!dwSkillVnum > 120) Replace: if (dwSkillVnum > 120) Special Thanks @Moț;
    0 points
  14. Official server send locale string like this: [LS;6969] where 6969 is the number of text in locale_string.txt from locale pack. They send a number and parse it in binary very easy.
    0 points
  15. I've done this by sending the client an information what kind of datatypes in which order got send. So i modified my ChatPacket function to some kind of this: Also then i reversed this on the client-side to get the arguments and got myself a StringModifier to push args step by step. And this is almost everything you need. Here is how i call the strings on the Server: ch->ChatPacket(CHAT_TYPE_INFO, 934, "dd"); I hope this few hints will help you out for a bit.
    0 points
  16. Client sources are files which compile into your ".exe" application, they manage physics, graphics, incoming and outgoing data transfers, and use the resources contained in your client's pack folder, such as textures, 3d models (.gr2), python files and plain text files. Server sources are files which compile into your "game" and "db" (no extension since they're elf32) files hosted on the remote server. They manage incoming and outgoing data transfers, and use the resources contained in your database to evaluate formulas for pretty much anything. The only way to actually "use" them is compiling into the respective files, but you can change how they work on datas, or datas they work with.
    0 points
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.