minigutza
P-Server Owner-
Posts
85 -
Joined
-
Last visited
-
Feedback
0%
About minigutza

Metin2 Dev
Informations
-
Gender
Male
-
Country
Romania
-
Nationality
Romanian
Recent Profile Visitors
2650 profile views
minigutza's Achievements
-
Description This fix addresses a quest-system problem that occurs when multiple quests are registered for the take event of the same NPC. Example: object/9009/take/fisher.start object/9009/take/eveniment_pescar.start Each quest may work correctly on its own. However, when both handlers are installed, the client can sometimes remain stuck with the cinematic black bars after choosing an option. No additional message appears, the action is not completed correctly, and the player may need to relog. The server usually reports: QUEST ScriptAnswer pid 11475 answer 0 Select: wrong QUEST_SELECT request! : 11475 Please note that answer 0 means the player selected the first option. It does not represent a failed upgrade result. Cause NPC::HandleEvent() executes all quest handlers registered for the same NPC event. For example, when an item is given to NPC 9009, both of these handlers may be executed: fisher.start eveniment_pescar.start If the first handler reaches select(), it is suspended while waiting for the player's answer. However, the original event loop continues and executes the next take handler. If the second handler finishes, it can replace or clear the currently running quest state. The client still displays the selection created by the first quest, but when the player answers, the server is no longer suspended in the QUEST_SELECT state. This results in: Select: wrong QUEST_SELECT request! A when ... with ... condition alone does not fully prevent this issue. The condition is evaluated inside the compiled quest handler, but the handler itself is still called by NPC::HandleEvent(). Source fix Open: game/src/questnpc.cpp Find the following function: bool NPC::HandleEvent(PC& pc, int EventIndex) Inside this function, there are two loops that call: CQuestManager::ExecuteQuestScript(...) Both calls must be modified. 1. Existing-state handler loop Find the call that uses the fMatch structure and replace the bare function call like: CQuestManager::ExecuteQuestScript(pc, fMatch.vdwQuesIndices[i], fMatch.viPCStates[i], fMatch.vcodes[i], fMatch.vcode_sizes[i]); with: if (CQuestManager::ExecuteQuestScript( pc, fMatch.vdwQuesIndices[i], fMatch.viPCStates[i], fMatch.vcodes[i], fMatch.vcode_sizes[i])) { return true; } 2. New-start handler loop Find the call that uses the fMiss structure and replace the bare function call like: CQuestManager::ExecuteQuestScript( pc, fMiss.vdwNewStartQuestIndices[i], 0, script.GetCode(), script.GetSize()); with: if (CQuestManager::ExecuteQuestScript( pc, fMiss.vdwNewStartQuestIndices[i], 0, script.GetCode(), script.GetSize())) { return true; } Do not use an unconditional return. The return value of ExecuteQuestScript() must be checked. How the fix works ExecuteQuestScript() returns true when the quest coroutine is suspended and waiting for player interaction, for example: select wait input confirm select_item When this happens, NPC::HandleEvent() must stop executing additional handlers for the same event. If the quest finishes without being suspended, ExecuteQuestScript() returns false, allowing the loop to continue and giving another handler the opportunity to process the item. In simplified form: if (quest_is_waiting_for_player_input) { stop_processing_other_handlers; } else { continue_to_the_next_handler; } What this fix allows This modification allows multiple take handlers to coexist on the same NPC. For example: object/9009/take/fisher.start object/9009/take/eveniment_pescar.start It does not allow two select() dialogs to run simultaneously. The first handler that suspends and waits for player input owns that event. The remaining handlers will not be executed during the same invocation. Quest conditions should therefore remain mutually exclusive whenever possible. If two handlers intentionally process the same item and both need to display a selection, they should be combined into a single quest flow. Recompile the game source and that's it. Good luck.
-
- 2
-
-
-
I have this one too
-
it is possible items picked up by group member to stack as well? because they are not automatically stacking. Or maybe to block them to pick them up
-
I have this error. I already checked for DAMAGE_BLOCK inside of enum DamageFlag from char_battle.cpp. What's missing or what i did wrong? Thank you.
-
Sometimes, the blacksmith from Demon Tower is not spawned. There is anyone with this issue too? I thinks it is related somehow with your party. If you have a party and the others are not in the same channel/core (he is like offline), sometimes the blacksmith is not spawned. If they are with you in a party or you don t have a party, everything's fine. How it could be fixed?
-
Automatic Dungeon Rejoin DT Issue
minigutza replied to minigutza's topic in Community Support - Questions & Answers
This is not so easy as you said, changing some coords and that's all. I figured out to reach the dungeon but the quest is not working anymore. You need to update all the coords in it, and still other problems happen. E.G. even if i am 66 index map inside the dungeon, the metin stone is not teleporting me anymore. -
Great Offline Shop issue
minigutza replied to minigutza's topic in Community Support - Questions & Answers
I solved the second error but still i get I tried to change the binary with this tutorial but the error is not adding a file name.... I tried the debug binary and it is crashing after loading, exactly when that error comes up even on distribute binary. Any ideas please? -
Hello guys, I try to add the great shop offline, it is working with some minor bugs, related to the client side i guess but i can t figure out the problem. First of all, when i log in i have this error: After that, this error shows up when i create an offline shop. The offline shop is working perfectly but is generating those logs. When i select the normal shop option (without expiring time - no offline shop, just regular one) the name of the shop remains above my character until relog like this if i close the shop. [Hidden Content] Probably because of that error. Thanks
-
thelittlemarkus started following minigutza
-
Something is not added right. Maybe a binary part is missing or wrong placed. Or tabs in game.py? What do you have on 2069 from game.py? I would recommend to revert the sash and cheque system. Try to add one system by time so you can figure it out where the problem is. Let just title, see if everything works then go to another one.
-
You must have TITLE_1 [Beginner] and so on in locale_game.txt. I did not added a DE version since i don t have a german locale. For ClientManagerLogin.cpp you should adjust the syntax for your server not just copy/paste. Probably there are some columns in tables like "mobile" that you don t have or maybe you had and now there are gone. I did it wrong first time too If you use TMP4 files it should be ok with mine #include "stdafx.h" #include "ClientManager.h" #include "Main.h" #include "Config.h" #include "QID.h" #include "Cache.h" extern std::string g_stLocale; extern bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab); extern int g_test_server; extern int g_log; bool CClientManager::InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP) { char szLogin[LOGIN_MAX_LEN + 1]; trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin)); itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin); if (m_map_kLogonAccount.end() != it) return false; CLoginData * pkLD = GetLoginDataByLogin(c_pszLogin); if (!pkLD) return false; pkLD->SetConnectedPeerHandle(dwHandle); pkLD->SetIP(c_pszIP); m_map_kLogonAccount.insert(TLogonAccountMap::value_type(szLogin, pkLD)); return true; } bool CClientManager::DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle) { char szLogin[LOGIN_MAX_LEN + 1]; trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin)); itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin); if (it == m_map_kLogonAccount.end()) return false; CLoginData * pkLD = it->second; if (pkLD->GetConnectedPeerHandle() != dwHandle) { sys_err("%s tried to logout in other peer handle %lu, current handle %lu", szLogin, dwHandle, pkLD->GetConnectedPeerHandle()); return false; } if (pkLD->IsPlay()) { pkLD->SetPlay(false); SendLoginToBilling(pkLD, false); } if (pkLD->IsDeleted()) { delete pkLD; } m_map_kLogonAccount.erase(it); return true; } bool CClientManager::FindLogonAccount(const char * c_pszLogin) { char szLogin[LOGIN_MAX_LEN + 1]; trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin)); if (m_map_kLogonAccount.end() == m_map_kLogonAccount.find(szLogin)) return false; return true; } void CClientManager::QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p) { #ifdef ENABLE_LIMIT_TIME static int s_updateCount = 0; static int s_curTime = time(0); if (s_updateCount > 100) { s_curTime = time(0); s_updateCount = 0; } ++s_updateCount; if (s_curTime >= GLOBAL_LIMIT_TIME) { sys_err("Server life time expired."); exit(0); return; } #endif CLoginData * pkLoginData = GetLoginData(p->dwLoginKey); char szLogin[LOGIN_MAX_LEN + 1]; trim_and_lower(p->szLogin, szLogin, sizeof(szLogin)); if (!pkLoginData) { sys_log(0, "LOGIN_BY_KEY key not exist %s %lu", szLogin, p->dwLoginKey); pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle); return; } TAccountTable & r = pkLoginData->GetAccountRef(); if (FindLogonAccount(r.login)) { sys_log(0, "LOGIN_BY_KEY already login %s %lu", r.login, p->dwLoginKey); TPacketDGLoginAlready ptog; strlcpy(ptog.szLogin, szLogin, sizeof(ptog.szLogin)); pkPeer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, dwHandle, sizeof(TPacketDGLoginAlready)); pkPeer->Encode(&ptog, sizeof(TPacketDGLoginAlready)); return; } if (strcasecmp(r.login, szLogin)) { sys_log(0, "LOGIN_BY_KEY login differ %s %lu input %s", r.login, p->dwLoginKey, szLogin); pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle); return; } if (memcmp(pkLoginData->GetClientKey(), p->adwClientKey, sizeof(DWORD) * 4)) { const DWORD * pdwClientKey = pkLoginData->GetClientKey(); sys_log(0, "LOGIN_BY_KEY client key differ %s %lu %lu %lu %lu, %lu %lu %lu %lu", r.login, p->adwClientKey[0], p->adwClientKey[1], p->adwClientKey[2], p->adwClientKey[3], pdwClientKey[0], pdwClientKey[1], pdwClientKey[2], pdwClientKey[3]); pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle); return; } TAccountTable * pkTab = new TAccountTable; memset(pkTab, 0, sizeof(TAccountTable)); pkTab->id = r.id; trim_and_lower(r.login, pkTab->login, sizeof(pkTab->login)); strlcpy(pkTab->passwd, r.passwd, sizeof(pkTab->passwd)); strlcpy(pkTab->social_id, r.social_id, sizeof(pkTab->social_id)); strlcpy(pkTab->status, "OK", sizeof(pkTab->status)); ClientHandleInfo * info = new ClientHandleInfo(dwHandle); info->pAccountTable = pkTab; strlcpy(info->ip, p->szIP, sizeof(info->ip)); sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip); char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id); CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info); } void CClientManager::RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg) { CQueryInfo * qi = (CQueryInfo *) msg->pvUserData; ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData; if (msg->uiSQLErrno != 0) { peer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle); delete info; return; } char szQuery[QUERY_MAX_LEN]; if (msg->Get()->uiNumRows == 0) { DWORD account_id = info->pAccountTable->id; char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id); std::unique_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER)); sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id); if (pMsg->Get()->uiNumRows == 0) { sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id); // PLAYER_INDEX_CREATE_BUG_FIX //snprintf(szQuery, sizeof(szQuery), "INSERT IGNORE INTO player_index%s (id) VALUES(%lu)", GetTablePostfix(), info->pAccountTable->id); snprintf(szQuery, sizeof(szQuery), "INSERT INTO player_index%s (id) VALUES(%u)", GetTablePostfix(), info->pAccountTable->id); CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_INDEX_CREATE, peer->GetHandle(), info); // END_PLAYER_INDEX_CREATE_BUF_FIX } return; } MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult); int col = 0; for (; col < PLAYER_PER_ACCOUNT; ++col) str_to_number(info->pAccountTable->players[col].dwID, row[col]); str_to_number(info->pAccountTable->bEmpire, row[col++]); info->account_index = 1; extern std::string g_stLocale; if (g_stLocale == "gb2312") #ifdef ENABLE_TITLE_SYSTEM { snprintf(szQuery, sizeof(szQuery), "SELECT id, name, job, level, alignment, prestige, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u", GetTablePostfix(), info->pAccountTable->id); } else { snprintf(szQuery, sizeof(szQuery), "SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u", GetTablePostfix(), info->pAccountTable->id); } #endif CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN, peer->GetHandle(), info); } // PLAYER_INDEX_CREATE_BUG_FIX void CClientManager::RESULT_PLAYER_INDEX_CREATE(CPeer * pkPeer, SQLMsg * msg) { CQueryInfo * qi = (CQueryInfo *) msg->pvUserData; ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData; char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), info->pAccountTable->id); CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info); } // END_PLAYER_INDEX_CREATE_BUG_FIX TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res) { char input_pwd[PASSWD_MAX_LEN + 1]; MYSQL_ROW row = NULL; DWORD col; row = mysql_fetch_row(res); col = 0; TAccountTable * pkTab = new TAccountTable; memset(pkTab, 0, sizeof(TAccountTable)); // ù¹øÂ° Ä÷³ °Í¸¸ Âü°í ÇÑ´Ù (JOIN QUERY¸¦ À§ÇÑ °Í ÀÓ) strlcpy(input_pwd, row[col++], sizeof(input_pwd)); str_to_number(pkTab->id, row[col++]); strlcpy(pkTab->login, row[col++], sizeof(pkTab->login)); strlcpy(pkTab->passwd, row[col++], sizeof(pkTab->passwd)); strlcpy(pkTab->social_id, row[col++], sizeof(pkTab->social_id)); str_to_number(pkTab->bEmpire, row[col++]); for (int j = 0; j < PLAYER_PER_ACCOUNT; ++j) str_to_number(pkTab->players[j].dwID, row[col++]); strlcpy(pkTab->status, row[col++], sizeof(pkTab->status)); if (strcmp(pkTab->passwd, input_pwd)) { delete pkTab; return NULL; } return pkTab; } void CreateAccountPlayerDataFromRes(MYSQL_RES * pRes, TAccountTable * pkTab) { if (!pRes) return; for (DWORD i = 0; i < mysql_num_rows(pRes); ++i) { MYSQL_ROW row = mysql_fetch_row(pRes); int col = 0; DWORD player_id = 0; !row[col++] ? 0 : str_to_number(player_id, row[col - 1]); if (!player_id) continue; int j; for (j = 0; j < PLAYER_PER_ACCOUNT; ++j) { if (pkTab->players[j].dwID == player_id) { CPlayerTableCache * pc = CClientManager::instance().GetPlayerCache(player_id); TPlayerTable * pt = pc ? pc->Get(false) : NULL; if (pt) { strlcpy(pkTab->players[j].szName, pt->name, sizeof(pkTab->players[j].szName)); pkTab->players[j].byJob = pt->job; pkTab->players[j].byLevel = pt->level; pkTab->players[j].dwPlayMinutes = pt->playtime; pkTab->players[j].byST = pt->st; pkTab->players[j].byHT = pt->ht; pkTab->players[j].byDX = pt->dx; pkTab->players[j].byIQ = pt->iq; pkTab->players[j].wMainPart = pt->parts[PART_MAIN]; pkTab->players[j].wHairPart = pt->parts[PART_HAIR]; pkTab->players[j].x = pt->x; pkTab->players[j].y = pt->y; pkTab->players[j].skill_group = pt->skill_group; pkTab->players[j].bChangeName = 0; } else { if (!row[col++]) *pkTab->players[j].szName = '\0'; else strlcpy(pkTab->players[j].szName, row[col - 1], sizeof(pkTab->players[j].szName)); pkTab->players[j].byJob = 0; pkTab->players[j].byLevel = 0; pkTab->players[j].dwPlayMinutes = 0; pkTab->players[j].byST = 0; pkTab->players[j].byHT = 0; pkTab->players[j].byDX = 0; pkTab->players[j].byIQ = 0; pkTab->players[j].wMainPart = 0; pkTab->players[j].wHairPart = 0; pkTab->players[j].x = 0; pkTab->players[j].y = 0; pkTab->players[j].skill_group = 0; pkTab->players[j].bChangeName = 0; str_to_number(pkTab->players[j].byJob, row[col++]); str_to_number(pkTab->players[j].byLevel, row[col++]); str_to_number(pkTab->players[j].dwPlayMinutes, row[col++]); str_to_number(pkTab->players[j].byST, row[col++]); str_to_number(pkTab->players[j].byHT, row[col++]); str_to_number(pkTab->players[j].byDX, row[col++]); str_to_number(pkTab->players[j].byIQ, row[col++]); str_to_number(pkTab->players[j].wMainPart, row[col++]); str_to_number(pkTab->players[j].wHairPart, row[col++]); str_to_number(pkTab->players[j].x, row[col++]); str_to_number(pkTab->players[j].y, row[col++]); str_to_number(pkTab->players[j].skill_group, row[col++]); str_to_number(pkTab->players[j].bChangeName, row[col++]); } sys_log(0, "%s %lu %lu hair %u", pkTab->players[j].szName, pkTab->players[j].x, pkTab->players[j].y, pkTab->players[j].wHairPart); break; } } /* if (j == PLAYER_PER_ACCOUNT) sys_err("cannot find player_id on this account (login: %s id %lu account %lu %lu %lu)", pkTab->login, player_id, pkTab->players[0].dwID, pkTab->players[1].dwID, pkTab->players[2].dwID); */ } } void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg) { CQueryInfo * qi = (CQueryInfo *) msg->pvUserData; ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData; if (info->account_index == 0) { // °èÁ¤ÀÌ ¾ø³×? if (msg->Get()->uiNumRows == 0) { sys_log(0, "RESULT_LOGIN: no account"); peer->EncodeHeader(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle, 0); delete info; return; } info->pAccountTable = CreateAccountTableFromRes(msg->Get()->pSQLResult); if (!info->pAccountTable) { sys_log(0, "RESULT_LOGIN: no account : WRONG_PASSWD"); peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle); delete info; } else { ++info->account_index; char queryStr[512]; extern std::string g_stLocale; if (g_stLocale == "gb2312") #ifdef ENABLE_TITLE_SYSTEM { snprintf(queryStr, sizeof(queryStr), "SELECT id, name, job, level, alignment, prestige, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u", GetTablePostfix(), info->pAccountTable->id); } else { snprintf(queryStr, sizeof(queryStr), "SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u", GetTablePostfix(), info->pAccountTable->id); } #endif CDBManager::instance().ReturnQuery(queryStr, QID_LOGIN, peer->GetHandle(), info); } return; } else { if (!info->pAccountTable) // ÀÌ·²¸®´Â ¾ø°ÚÁö¸¸;; { peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle); delete info; return; } // ´Ù¸¥ ÄÁ³Ø¼ÇÀÌ ÀÌ¹Ì ·Î±×ÀÎ ÇØ¹ö·È´Ù¸é.. ÀÌ¹Ì Á¢¼ÓÇß´Ù°í º¸³»¾ß ÇÑ´Ù. if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip)) { sys_log(0, "RESULT_LOGIN: already logon %s", info->pAccountTable->login); TPacketDGLoginAlready p; strlcpy(p.szLogin, info->pAccountTable->login, sizeof(p.szLogin)); peer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, info->dwHandle, sizeof(TPacketDGLoginAlready)); peer->Encode(&p, sizeof(p)); } else { sys_log(0, "RESULT_LOGIN: login success %s rows: %lu", info->pAccountTable->login, msg->Get()->uiNumRows); if (msg->Get()->uiNumRows > 0) CreateAccountPlayerDataFromRes(msg->Get()->pSQLResult, info->pAccountTable); //PREVENT_COPY_ITEM CLoginData * p = GetLoginDataByLogin(info->pAccountTable->login); memcpy(&p->GetAccountRef(), info->pAccountTable, sizeof(TAccountTable)); //END_PREVENT_COPY_ITEM peer->EncodeHeader(HEADER_DG_LOGIN_SUCCESS, info->dwHandle, sizeof(TAccountTable)); peer->Encode(info->pAccountTable, sizeof(TAccountTable)); } delete info->pAccountTable; info->pAccountTable = NULL; delete info; } } void CClientManager::QUERY_LOGOUT(CPeer * peer, DWORD dwHandle,const char * data) { TLogoutPacket* packet = (TLogoutPacket*)data; if (!*packet->login) return; CLoginData * pLoginData = GetLoginDataByLogin(packet->login); if (pLoginData == NULL) return; int pid[PLAYER_PER_ACCOUNT]; for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n) { if (pLoginData->GetAccountRef().players[n].dwID == 0) { if (g_test_server) sys_log(0, "LOGOUT %s %d", packet->login, pLoginData->GetAccountRef().players[n].dwID); continue; } pid[n] = pLoginData->GetAccountRef().players[n].dwID; if (g_log) sys_log(0, "LOGOUT InsertLogoutPlayer %s %d", packet->login, pid[n]); InsertLogoutPlayer(pid[n]); } if (DeleteLogonAccount(packet->login, peer->GetHandle())) { if (g_log) sys_log(0, "LOGOUT %s ", packet->login); } } void CClientManager::QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p) { char queryStr[QUERY_MAX_LEN]; if (g_stLocale == "sjis") snprintf(queryStr, sizeof(queryStr), "SELECT COUNT(*) as count FROM player%s WHERE name='%s' collate sjis_japanese_ci AND id <> %u", GetTablePostfix(), p->name, p->pid); else snprintf(queryStr, sizeof(queryStr), "SELECT COUNT(*) as count FROM player%s WHERE name='%s' AND id <> %u", GetTablePostfix(), p->name, p->pid); std::unique_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER)); if (pMsg->Get()->uiNumRows) { if (!pMsg->Get()->pSQLResult) { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult); if (*row[0] != '0') { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0); return; } } else { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } snprintf(queryStr, sizeof(queryStr), "UPDATE player%s SET name='%s',change_name=0 WHERE id=%u", GetTablePostfix(), p->name, p->pid); std::unique_ptr<SQLMsg> pMsg0(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER)); TPacketDGChangeName pdg; peer->EncodeHeader(HEADER_DG_CHANGE_NAME, dwHandle, sizeof(TPacketDGChangeName)); pdg.pid = p->pid; strlcpy(pdg.name, p->name, sizeof(pdg.name)); peer->Encode(&pdg, sizeof(TPacketDGChangeName)); }
-
You should add them with vnum. 1. Here is the item_proto.txt version and put them correctly. You already have the item_names. 55001 Licoare Premium Galbena ITEM_GIFTBOX 0 1 NONE 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 55002 Licoare Premium Roza ITEM_GIFTBOX 0 1 NONE 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 55003 Licoare Premium Alba ITEM_GIFTBOX 0 1 NONE 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 2. "use of undeclared identifier `pMsg` in Title.cpp. Search and change auto_ptr to unique_ptr in Title.cpp. You should find it x3. Hope its working.
-
Locale.lua & Translate.lua how it is working?
minigutza replied to CKaan's topic in Community Support - Questions & Answers
Hello, Those "gameforge.main_quest_lv1._10_sendLetter" are strings from translate.lua. Just add your new lines in translate.lua and everything will work just fine. If you add a new line in a quest with say, say_title and so on like "gameforge.main_quest_lv1._101_sendLetter" just be sure this new string is translated in translate.lua too. You can paste it wherever you want, it doesn't matter, or you can paste near the other translates for the same quest to keep an ordered translate.lua. Locale.lua is actually used for the ingame strings not quests lines, like system messages from the chat (e.g. "you dropped sword+0").- 1 reply
-
- 1
-
-
Hello, How can i set to not ride the mounts if you are moving/attacking? Horses and some mounts like the evolving ones can be ride even if you attack. That allows you to attack very fast if you mount and unmount every second (like spamming the riding). Those mounts have ITEM_QUEST flags. The other mounts like White Lion are "ITEM_UNIQUE UNIQUE_SPECIAL_RIDE". Those mounts can't be used when you move/attack and that's added in locale_string.txt too. "°¡¸¸È÷ ÀÖÀ» ¶§¸¸ Âø¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù."; "You have to stand still to equip the item."; I tried to add a condition in char_item.cpp but i couldn't do it. Can someonle help me? Please. Thanks...
