-
Posts
199 -
Joined
-
Last visited
-
Days Won
1 -
Feedback
100%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Amun
-
-
It looks like the vip is acting like a GM. What system did you use ?
-
If the db doesn't start, then nothing will, so open ClientManagerBoot and check what tables should be loaded from mysql at boot time(if you don't have logs, add logs as well so you can see what's loaded and what isn't).
There's a lot of stuff that can cause the db/cores to shut down without any syserr but let's start with that and we'll see what's to be done later.
Also, you can find me on discord at: Amun#3808
-
You can use Epack32 to pack/unpack your protos(assuming you know the keys).
Or just download dump_proto source and compile it..
- 1
-
Open char_skill.cpp and look for
bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
Replace the whole function with:
Spoilerbool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb) { const CSkillProto *pkSk = CSkillManager::instance().Get(dwSkillVnum); if (!pkSk) return false; if (!IsLearnableSkill(dwSkillVnum)) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("수련할 수 없는 스킬입니다.")); return false; } DWORD need_exp = 0; if (FN_should_check_exp(this)) { need_exp = 20000; if (GetExp() < need_exp) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("경험치가 부족하여 책을 읽을 수 없습니다.")); return false; } } if (pkSk->dwType != 0) { if (GetSkillMasterType(dwSkillVnum) != SKILL_MASTER) { if (GetSkillMasterType(dwSkillVnum) > SKILL_MASTER) ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 스킬은 책으로 더이상 수련할 수 없습니다.")); else ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 스킬은 아직 책으로 수련할 경지에 이르지 않았습니다.")); return false; } } if (get_global_time() < GetSkillNextReadTime(dwSkillVnum)) { if (!(test_server && quest::CQuestManager::instance().GetEventFlag("no_read_delay"))) { if (FindAffect(AFFECT_SKILL_NO_BOOK_DELAY)) { RemoveAffect(AFFECT_SKILL_NO_BOOK_DELAY); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("주안술서를 통해 주화입마에서 빠져나왔습니다.")); } else { SkillLearnWaitMoreTimeMessage(static_cast<DWORD>(GetSkillNextReadTime(dwSkillVnum) - get_global_time())); return false; } } } BYTE bLastLevel = GetSkillLevel(dwSkillVnum); if (bProb != 0) { if (FindAffect(AFFECT_SKILL_BOOK_BONUS)) { bProb += bProb / 2; RemoveAffect(AFFECT_SKILL_BOOK_BONUS); } sys_log(0, "LearnSkillByBook Pct %u prob %d", dwSkillVnum, bProb); if (number(1, 100) <= bProb) { if (test_server) sys_log(0, "LearnSkillByBook %u SUCC", dwSkillVnum); SkillLevelUp(dwSkillVnum, SKILL_UP_BY_BOOK); } else { if (test_server) sys_log(0, "LearnSkillByBook %u FAIL", dwSkillVnum); } } else { int idx = MIN(9, GetSkillLevel(dwSkillVnum) - 20); sys_log(0, "LearnSkillByBook %s table idx %d value %d", GetName(), idx, aiSkillBookCountForLevelUp[idx]); { int need_bookcount = GetSkillLevel(dwSkillVnum) - 20; PointChange(POINT_EXP, -static_cast<int>(need_exp)); quest::CQuestManager &q = quest::CQuestManager::instance(); quest::PC *pPC = q.GetPC(GetPlayerID()); if (pPC) { char flag[128 + 1]; memset(flag, 0, sizeof(flag)); snprintf(flag, sizeof(flag), "traning_master_skill.%u.read_count", dwSkillVnum); int read_count = pPC->GetFlag(flag); int percent = 65; if (FindAffect(AFFECT_SKILL_BOOK_BONUS)) { percent = 0; RemoveAffect(AFFECT_SKILL_BOOK_BONUS); } if (number(1, 100) > percent) { if (read_count >= need_bookcount) { SkillLevelUp(dwSkillVnum, SKILL_UP_BY_BOOK); pPC->SetFlag(flag, 0); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("책으로 더 높은 경지의 수련을 성공적으로 끝내셨습니다.")); LogManager::instance().CharLog(this, dwSkillVnum, "READ_SUCCESS", ""); return true; } else { pPC->SetFlag(flag, read_count + 1); switch (number(1, 3)) { case 1: ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("어느정도 이 기술에 대해 이해가 되었지만 조금 부족한듯 한데..")); break; case 2: ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("드디어 끝이 보이는 건가... 이 기술은 이해하기가 너무 힘들어..")); break; case 3: default: ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("열심히 하는 배움을 가지는 것만이 기술을 배울수 있는 유일한 길이다..")); break; } ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d 권을 더 읽어야 수련을 완료 할 수 있습니다."), need_bookcount - read_count); return true; } } } else { } } } if (bLastLevel != GetSkillLevel(dwSkillVnum)) { ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("몸에서 뭔가 힘이 터져 나오는 기분이야!")); ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("뜨거운 무엇이 계속 용솟음치고 있어! 이건, 이것은!")); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("책으로 더 높은 경지의 수련을 성공적으로 끝내셨습니다.")); LogManager::instance().CharLog(this, dwSkillVnum, "READ_SUCCESS", ""); } else { ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("크윽, 기가 역류하고 있어! 이거 설마 주화입마인가!? 젠장!")); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("수련이 실패로 끝났습니다. 다시 도전해주시기 바랍니다.")); LogManager::instance().CharLog(this, dwSkillVnum, "READ_FAIL", ""); } return true; }
Good Luck
If you have problems, discord: Amun#3808
- 1
-
Hi mate,
I've never used the system but I found an image trying to find it, so open ui.py and look for something like:
wndMgr.SetSlotLevelImage
If you still can't find it, let me know on Discord: Amun#3808 and I'll remove it for you..
Good Luck !
Edit: I forgot to tell you to also follow the code into your source(should be in eterPythonLib/PythonWIndowManagerModule.cpp) and get rid of the function from there as well. It doesn't affect keeping the function there but what's the point if you never use it, right ?
-
Have you ever started the server before or is it the first time ?
-
Client source, ActorInstanceCollisionDetection.cpp
Search for:
BOOL CActorInstance::TestActorCollision(CActorInstance& rVictim)
Write your conditions inside that function.
Example:
Disable collision with pets:
if (rVictim.GetRace() >= 34001 && rVictim.GetRace() <= 34099) return FALSE;
To disable collision with stones, just add another condition with the vnum range of the stones or individually if you only want it disabled for specific stones. NOTE: You should add a check to see if the player is attacking or not. I have never disabled the collision with metin stones so I am unsure if you'll be able to attack them anymore without a check.
Untested Example for all metin stones(at least I think that's all of them):
if (!isAttacking() && rVictim.GetRace() >= 8001 && rVictim.GetRace() <= 8206) return false;
I advise you against disabling collision with houses and other objects since you'll just go right through them so they become useless.
That can be done from __TestObjectCollision
If you have any questions, let me know here or on Discord: Amun#3808
Good luck !
-
It looks like your server is live. The problem's from root. Most likely serverinfo.py or wherever you declared your connection settings.
-
I guess you're one of those guys who tried to implement it, f*cked up and then assumed there's a problem with the system
-
That's pretty much impossible :))
Did you restart you pc as well ?(I had to ask, sorry)
Try something else: download the dll and put it in the folder with dump_proto
-
Install VC++ for VS2013 and it should be fine.
https://www.microsoft.com/en-us/download/details.aspx?id=40784
A simple search on google would've brought you the solution: https://stackoverflow.com/questions/23114427/vs2012-msvcr120d-dll-is-missing
- 1
-
I don't get it.. mine's working just fine.
Here's the code, I've also commented to see what's what:
char_change_empire.cpp
Spoilerint CHARACTER::ChangeEmpire(BYTE empire)
{
if (GetEmpire() == empire)
return 1;//return 1 means you're trying to change to the same empire. Aka: you're already there..char szQuery[1024 + 1];
DWORD dwAID;
DWORD dwPID[4];
memset(dwPID, 0, sizeof(dwPID));{//get all the players on this account
snprintf(szQuery, sizeof(szQuery), //pid5 after pid4 if you have lykan //pid5=%u if you have lykan
"SELECT id, pid1, pid2, pid3, pid4 FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u",
//add one more GetPlayerID() if you have lykan
get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());std::unique_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));
if (msg->Get()->uiNumRows == 0)
{
return 0;//return 0 is unknown or query error
}MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
str_to_number(dwAID, row[0]);
str_to_number(dwPID[0], row[1]);
str_to_number(dwPID[1], row[2]);
str_to_number(dwPID[2], row[3]);
str_to_number(dwPID[3], row[4]);
// str_to_number(dwPID[4], row[5]);//if you have lykan.
}const int loop = 4;//number of characters available(should be 5 if you have lykan)
{
DWORD dwGuildID[4];
CGuild *pGuild[4];
SQLMsg *pMsg = NULL;for (int i = 0; i < loop; ++i)
{snprintf(szQuery, sizeof(szQuery), "SELECT guild_id FROM guild_member%s WHERE pid=%u", get_table_postfix(), dwPID[i]);
pMsg = DBManager::instance().DirectQuery(szQuery);
if (pMsg != NULL)//query failed
{
if (pMsg->Get()->uiNumRows > 0)//query didn't fail, we've got some results.
{
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
str_to_number(dwGuildID[i], row[0]);pGuild[i] = CGuildManager::instance().FindGuild(dwGuildID[i]);//look for a guild
if (pGuild[i] != NULL)//we found a guild on one of the accounts
{
M2_DELETE(pMsg);
return 2;
}
}
else // we didn't get any results
{
dwGuildID[i] = 0;
pGuild[i] = NULL;
}
M2_DELETE(pMsg);
}
}
}{//return 3 means one of the characters is married.
for (int i = 0; i < loop; ++i)
{
if (marriage::CManager::instance().IsEngagedOrMarried(dwPID[i]) == true)
return 3;
}
}{
//don't forget to add your 5th pid if you have lykan.
snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u",
get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());std::unique_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));
if (msg->Get()->uiAffectedRows > 0)
{
SetChangeEmpireCount();
SetEmpire(empire);
UpdatePacket();
return 999;//it means everything ran as expected.
}
}return 0;//unexpectedly, we've reached the final destination. How did this happen ?
}This should do the trick.
Good luck !
- 1
-
Welcome, mate ! You'll like it here xD
- 1
-
Does your db start ? Have you ever started the server with the current quests ? Do you have the config files properly set up ?
I don't know what source you're using, but also check your mob_drop_item, common_drop, dragon_soul, etc from locale/xx. And don't forget to check the syslog as well.
Cheers !
-
Any syserr when this happens ?
Tmp4's source moved to windows
in Binaries
Posted · Edited by Metin2 Dev
Core X - External 2 Internal
Metin2 Download
Hi
I noticed quite a bit of people have problems opening a dev server on Tmp4's source.
I moved the server source to windows hoping it'd be easier for any beginners to get started. If anyone wants to give it a try, here it is:
I've also removed matrix card, auction, udp port, etc.. Not all of them, but quite a few.
NOTE: If you don't have the Client from Tmp4, go to his topic and download it(maybe give him a thanks while you're there).
Here's the topic:
OK, let's get started.
How to:
Download the files and move them in a folder.
Open a terminal (CMD/PowerShell/GitBash, etc..) and cd into the folder where you downloaded the files.
Now run:
If you get any errors from tar, you might need to install Git Bash(or just use WinRar or something).
I wanted to give you the server already compiled, just to get started faster, but I cleaned up the objects and forgot to make a backup of the game and db.exe..
So, you'll have to compile them yourself, unfortunately.
Go to server_src and open m2_server.2008.sln(I didn't rename it, do it yourself) then select Debug(or release, whatever you want) and Win32.
After the game and db files are compiled, go back and open `winsf` folder.
Now run `make_test_env.bat` with admin rights(it needs them to create the shortcuts(links)).
After each compilation you just run `refresh.bat` to remove the old exe files and replace them with the new ones(Or just change the out directory in VS to winsf.. your choice).
To start in debug mode, just run `run_d.bat`.
If you don't have mysql server installed on your PC, get it from here:
https://downloads.mysql.com/archives/installer/?version=5.6.26
And click the second button(294.4MB).
After it's installed, connect to the mysql server with either MySql WorkBench or with Navicat and import the sql scripts found in sql.rar.
The tables are taken from some old serverfiles(from Marty, if I'm not mistaken). The tables are fucked, but it should work fine to get started.
I'll fix them up later if I have time.. but not now.. Also, don't forget to change the user and password in the configs.(You'll find them in share/cores_config).
Also. If your PC slows down while compiling, you might want to disable Multi-processor Compilation(I don't know if it's user specific or if it's saved in the solution's config, but I wanted to mention it just in case it's saved).
The last step is to copy the exe files from client_src/binary into your client, pack the root folder with Eternexus(or whatever you use) and replace them in Client/pack.
Here's two pictures:
If I forgot anything, just let me know and I'll update the post as soon as I can. Also, please report whatever bugs/errors you find. It would be greatly appreciated.
Cheers!
Virus total found BitDefenderTheta in server_extern, but Antivirus found none, so you decide if you want to use them or just compile the libs yourself:
root
server_src
sql
winsf
client_src
server_extern