Search the Community

Showing results for tags 'mt2 fr systeme'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Register & Login
    • Register
    • Login
  • Espace Communautaire
    • Funky Emulation
    • Présentations
    • Services
    • Discussions Générales
    • Bureau de la Communauté
    • Espace Premium
  • Emulation & Co
    • Rewrite a Release / Tutorial
    • Suggest a Release / Tutorial
    • The Ideas Box
  • Emulation de jeux
    • RaiderZ
    • Aura Kingdom
    • Metin2
    • Dofus
    • World of Warcraft
    • Minecraft
    • Aion
    • Habbo
    • Voir plus...
  • Espace Divers
  • Internationnal Forum
  • PassionDev's Forum
  • M2Project - Metin2's M2SF
  • M2Project - Metin2's Aide / Questions / Support
  • M2Project - Metin2's Tutoriels & Partages
  • M2Project - Metin2's Suggestions
  • M2Project - Metin2's Report de Bugs

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Nationality


Sexe


Discord


Skype


Biographie


Site


Nombre

 
or  

Found 33 results

  1. Verrouillage/Déverrouillage d'inventaire système de l'officiel. 1) Qu'est ce que c'est ? 2) Les Prérequis 3) Les téléchargements 1) Qu'est ce que c'est ? Le Système de Verrouillage/Déverrouillage d'inventaire est un verrou poser sur certains espaces de vos inventaire ( jusqu'à 4 inventaires ) Pour les déverrouiller il vous faut un item appeler Clé d'inventaire . Vidéos Screens Des images et vidéos valent mieux qu'un tas de mots sur une page blanche. 2) Les Prérequis Avoir des files et un client Disposez des 4 inventaires ( L'inventaires 3 et 4 doit être vide autrement cela vous empêchera de connecter le personnages en question.) Sources Client / Game / DB Les fichiers à télécharger et votre tête! 3) Les téléchargements Comme à mon habitude le tutoriel ce trouve à l'intérieur du .rar. Changelog : Sachez encore une fois que ce partage n'est pas de moi mais qu'il provient de TurkMmo. La traduction/réorganisation du tutoriel est cependant de moi. Lien mis à jour avec la correction : Cliquez ici FEV1 FEV2 GitHubV2 Cordialement, History.
  2. Bonjour à tous, je vous partage donc un partage d'epvps pour ne plus avoir besoin de txt et reprendre donc l'ancien systeme via mysql. Pour ce faire on se rend donc dans ClientManagerBoot.cpp qui se trouve donc dans mainline/srcs/server/db/src. Ensuite il vous faudra remplacer bool CClientManager::InitializeItemTable() { //================== ÇÔ¼ö ¼³¸à ==================// //1. ¿ä¾à : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' ÆÄÀÃÀ» ÀðÃ, // (TItemTable), ¿ÀºêçƮ¸¦ »ý¼ºÇÑ´Ù. //2. ¼ø¼ // 1) 'item_names.txt' ÆÄÀÃÀ» ÀÃ¾î¼ (a)[localMap](vnum:name) ¸ÊÀ» ¸¸µç´Ù. // 2) 'item_proto_text.txt'ÆÄÀðú (a)[localMap] ¸ÊÀ¸·Î // (b)[test_map_itemTableByVnum](vnum:TItemTable) ¸ÊÀ» »ý¼ºÇÑ´Ù. // 3) 'item_proto.txt' ÆÄÀðú (a)[localMap] ¸ÊÀ¸·Î // (!)[item_table], À» ¸¸µç´Ù. // <Âü°Ã> // °¢ row µé Ãß, // (b)[test_map_itemTableByVnum],(!)[mob_table] ¸ðµÎ¿¡ ÀÖ´Â row´Â // (b)[test_map_itemTableByVnum]ÀÇ °ÃÀ» »ç¿ëÇÑ´Ù. // 4) (b)[test_map_itemTableByVnum]ÀÇ rowÃß, (!)[item_table]¿¡ ¾ø´Â °ÃÀ» Ãß°¡ÇÑ´Ù. //3. Å×½ºÆ® // 1)'item_proto.txt' 亸°¡ item_table¿¡ Àß µé¾î°¬´ÂÃö. -> ¿Ã·á // 2)'item_names.txt' 亸°¡ item_table¿¡ Àß µé¾î°¬´ÂÃö. // 3)'item_proto_test.txt' ¿¡¼ [°ãÄ¡´Â] 亸°¡ item_table ¿¡ Àß µé¾î°¬´ÂÃö. // 4)'item_proto_test.txt' ¿¡¼ [»õ·Î¿î] 亸°¡ item_table ¿¡ Àß µé¾î°¬´ÂÃö. // 5) (ÃÖþ) °ÔÀÓ Ŭ¶óÀ̾ðÆ®¿¡¼ æ´ë·Î ÀÛµ¿ ÇôÂÃö. //_______________________________________________// //=================================================================================// // 1) 'item_names.txt' ÆÄÀÃÀ» ÀÃ¾î¼ (a)[localMap](vnum:name) ¸ÊÀ» ¸¸µç´Ù. //=================================================================================// bool isNameFile = true; map localMap; cCsvTable nameData; if(!nameData.Load("item_names.txt",'\t')) { fprintf(stderr, "item_names.txt was loaded successfully.\n"); isNameFile = false; } else { nameData.Next(); while(nameData.Next()) { localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1); } } //_________________________________________________________________// //=================================================================// // 2) 'item_proto_text.txt'ÆÄÀðú (a)[localMap] ¸ÊÀ¸·Î // (b)[test_map_itemTableByVnum](vnum:TItemTable) ¸ÊÀ» »ý¼ºÇÑ´Ù. //=================================================================// map test_map_itemTableByVnum; //1. ÆÄÀà Àþî¿À±â. cCsvTable test_data; if(!test_data.Load("item_proto_test.txt",'\t')) { fprintf(stderr, "item_proto_test.txt was loaded successfully.\n"); //return false; } else { test_data.Next(); //¼³¸à ·Î¿ì ³Ñ¾î°¡±â. //2. Å×½ºÆ® ¾ÆÀÌÅÛ Å×ÀÌºà »ý¼º. TItemTable * test_item_table = NULL; int test_itemTableSize = test_data.m_File.GetRowCount()-1; test_item_table = new TItemTable[test_itemTableSize]; memset(test_item_table, 0, sizeof(TItemTable) * test_itemTableSize); //3. Å×½ºÆ® ¾ÆÀÌÅÛ Å×À̺ÿ¡ °ªÀ» ³Ö°Ã, ¸Ê¿¡±îÃö ³Ö±â. while(test_data.Next()) { if (!Set_Proto_Item_Table(test_item_table, test_data, localMap)) { fprintf(stderr, "¾ÆÀÌÅÛ Ç÷ÎÅä Å×ÀÌºà ¼ÂÆà ½ÇÆÃ.\n"); } test_map_itemTableByVnum.insert(std::map::value_type(test_item_table->dwVnum, test_item_table)); test_item_table++; } } //______________________________________________________________________// //========================================================================// // 3) 'item_proto.txt' ÆÄÀðú (a)[localMap] ¸ÊÀ¸·Î // (!)[item_table], À» ¸¸µç´Ù. // <Âü°Ã> // °¢ row µé Ãß, // (b)[test_map_itemTableByVnum],(!)[mob_table] ¸ðµÎ¿¡ ÀÖ´Â row´Â // (b)[test_map_itemTableByVnum]ÀÇ °ÃÀ» »ç¿ëÇÑ´Ù. //========================================================================// //vnumµéÀ» ÀúÀåÇÒ ¼Â. »õ·Î¿î Å×½ºÆ® ¾ÆÀÌÅÛÀ» ÆǺ°ÇÒ¶§ »ç¿ëµÈ´Ù. set vnumSet; //ÆÄÀà Àþî¿À±â. cCsvTable data; if(!data.Load("item_proto.txt",'\t')) { fprintf(stderr, "item_proto.txt was loaded successfully.\n"); return false; } data.Next(); //¸Ç ÀÃ٠æ¿Ü (¾ÆÀÌÅÛ Ä®·³À» ¼³¸ÃÇô ºÎºÃ) if (!m_vec_itemTable.empty()) { sys_log(0, "RELOAD: item_proto"); m_vec_itemTable.clear(); m_map_itemTableByVnum.clear(); } //===== ¾ÆÀÌÅÛ Å×ÀÌºà »ý¼º =====// //»õ·Î Ãß°¡µÇ´Â °¹¼ö¸¦ ÆľÇÇÑ´Ù. int addNumber = 0; while(data.Next()) { int vnum = atoi(data.AsStringByIndex(0)); std::map::iterator it_map_itemTable; it_map_itemTable = test_map_itemTableByVnum.find(vnum); if(it_map_itemTable != test_map_itemTableByVnum.end()) { addNumber++; } } //data¸¦ ´Ù½Ã ùÃÙ·Î ¿Å±ä´Ù.(´Ù½Ã Àþî¿Â´Ù; data.Destroy(); if(!data.Load("item_proto.txt",'\t')) { fprintf(stderr, "item_proto.txt was loaded successfully.\n"); return false; } data.Next(); //¸Ç ÀÃ٠æ¿Ü (¾ÆÀÌÅÛ Ä®·³À» ¼³¸ÃÇô ºÎºÃ) m_vec_itemTable.resize(data.m_File.GetRowCount() - 1 + addNumber); memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size()); int testValue = m_vec_itemTable.size(); TItemTable * item_table = &m_vec_itemTable[0]; while (data.Next()) { int col = 0; std::map::iterator it_map_itemTable; it_map_itemTable = test_map_itemTableByVnum.find(atoi(data.AsStringByIndex(col))); if(it_map_itemTable == test_map_itemTableByVnum.end()) { //°¢ Ä®·³ µ¥ÀÌÅà ÀúÀå if (!Set_Proto_Item_Table(item_table, data, localMap)) { fprintf(stderr, "¾ÆÀÌÅÛ Ç÷ÎÅä Å×ÀÌºà ¼ÂÆà ½ÇÆÃ.\n"); } } else { //$$$$$$$$$$$$$$$$$$$$$$$ Å×½ºÆ® ¾ÆÀÌÅÛ Ã¤º¸°¡ ÀÖ´Ù! TItemTable *tempTable = it_map_itemTable->second; item_table->dwVnum = tempTable->dwVnum; strlcpy(item_table->szName, tempTable->szName, sizeof(item_table->szName)); strlcpy(item_table->szLocaleName, tempTable->szLocaleName, sizeof(item_table->szLocaleName)); item_table->bType = tempTable->bType; item_table->bSubType = tempTable->bSubType; item_table->bSize = tempTable->bSize; item_table->dwAntiFlags = tempTable->dwAntiFlags; item_table->dwFlags = tempTable->dwFlags; item_table->dwWearFlags = tempTable->dwWearFlags; item_table->dwImmuneFlag = tempTable->dwImmuneFlag; item_table->dwGold = tempTable->dwGold; item_table->dwShopBuyPrice = tempTable->dwShopBuyPrice; item_table->dwRefinedVnum =tempTable->dwRefinedVnum; item_table->wRefineSet =tempTable->wRefineSet; item_table->bAlterToMagicItemPct = tempTable->bAlterToMagicItemPct; item_table->cLimitRealTimeFirstUseIndex = -1; item_table->cLimitTimerBasedOnWearIndex = -1; int i; for (i = 0; i < ITEM_LIMIT_MAX_NUM; ++i) { item_table->aLimits.bType = tempTable->aLimits.bType; item_table->aLimits.lValue = tempTable->aLimits.lValue; if (LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits.bType) item_table->cLimitRealTimeFirstUseIndex = (char)i; if (LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits.bType) item_table->cLimitTimerBasedOnWearIndex = (char)i; } for (i = 0; i < ITEM_APPLY_MAX_NUM; ++i) { item_table->aApplies.bType = tempTable->aApplies.bType; item_table->aApplies.lValue = tempTable->aApplies.lValue; } for (i = 0; i < ITEM_VALUES_MAX_NUM; ++i) item_table->alValues = tempTable->alValues; item_table->bGainSocketPct = tempTable->bGainSocketPct; item_table->sAddonType = tempTable->sAddonType; item_table->bWeight = tempTable->bWeight; } vnumSet.insert(item_table->dwVnum); m_map_itemTableByVnum.insert(std::map::value_type(item_table->dwVnum, item_table)); ++item_table; } //_______________________________________________________________________// //========================================================================// // 4) (b)[test_map_itemTableByVnum]ÀÇ rowÃß, (!)[item_table]¿¡ ¾ø´Â °ÃÀ» Ãß°¡ÇÑ´Ù. //========================================================================// test_data.Destroy(); if(!test_data.Load("item_proto_test.txt",'\t')) { fprintf(stderr, "item_proto_test.txt was loaded successfully.\n"); //return false; } else { test_data.Next(); //¼³¸à ·Î¿ì ³Ñ¾î°¡±â. while (test_data.Next()) //Å×½ºÆ® µ¥ÀÌÅà °¢°¢À» ÈȾ°¡¸ç,»õ·Î¿î °ÃÀ» Ãß°¡ÇÑ´Ù. { //Ãߺ¹µÇ´Â ºÎºÃÀ̸é ³Ñ¾î°£´Ù. set::iterator itVnum; itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0))); if (itVnum != vnumSet.end()) { continue; } if (!Set_Proto_Item_Table(item_table, test_data, localMap)) { fprintf(stderr, "¾ÆÀÌÅÛ Ç÷ÎÅä Å×ÀÌºà ¼ÂÆà ½ÇÆÃ.\n"); } m_map_itemTableByVnum.insert(std::map::value_type(item_table->dwVnum, item_table)); item_table++; } } // QUEST_ITEM_PROTO_DISABLE // InitializeQuestItemTable(); // END_OF_QUEST_ITEM_PROTO_DISABLE m_map_itemTableByVnum.clear(); itertype(m_vec_itemTable) it = m_vec_itemTable.begin(); while (it != m_vec_itemTable.end()) { TItemTable * item_table = &(*(it++)); sys_log(1, "ITEM: #%-5lu %-24s %-24s VAL: %ld %ld %ld %ld %ld %ld WEAR %lu ANTI %lu IMMUNE %lu REFINE %lu REFINE_SET %u MAGIC_PCT %u", item_table->dwVnum, item_table->szName, item_table->szLocaleName, item_table->alValues[0], item_table->alValues[1], item_table->alValues[2], item_table->alValues[3], item_table->alValues[4], item_table->alValues[5], item_table->dwWearFlags, item_table->dwAntiFlags, item_table->dwImmuneFlag, item_table->dwRefinedVnum, item_table->wRefineSet, item_table->bAlterToMagicItemPct); m_map_itemTableByVnum.insert(std::map::value_type(item_table->dwVnum, item_table)); } sort(m_vec_itemTable.begin(), m_vec_itemTable.end(), FCompareVnum()); return true; } par bool CClientManager::InitializeItemTable() { char query[2048]; fprintf(stderr,"Loading item_proto from MySQL"); snprintf(query, sizeof(query), "SELECT vnum,name,%s,type,subtype,weight,size,antiflag,flag,wearflag,immuneflag+0,gold,shop_buy_price,refined_vnum," "refine_set,magic_pct,limittype0,limitvalue0,limittype1,limitvalue1,applytype0,applyvalue0," "applytype1,applyvalue1,applytype2,applyvalue2,value0,value1,value2,value3,value4,value5,socket_pct,addon_type FROM item_proto%s ORDER BY vnum", g_stLocaleNameColumn.c_str(), GetTablePostfix()); std::auto_ptr pkMsg(CDBManager::instance().DirectQuery(query)); SQLResult * pRes = pkMsg->Get(); if (!pRes->uiNumRows) return false; int addNumber = pRes->uiNumRows; if (!m_vec_itemTable.empty()) { sys_log(0, "RELOAD: item_proto"); m_vec_itemTable.clear(); m_map_itemTableByVnum.clear(); } m_vec_itemTable.resize(addNumber-1); memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size()); TItemTable * item_table = &m_vec_itemTable[0]; MYSQL_ROW data; //return true; set vnumSet; while ((data = mysql_fetch_row(pRes->pSQLResult))) { str_to_number(item_table->dwVnum, data[0]); strlcpy(item_table->szName,data[1] , sizeof(item_table->szName)); strlcpy(item_table->szLocaleName, data[2], sizeof(item_table->szLocaleName)); str_to_number(item_table->bType, data[3]); str_to_number(item_table->bSubType, data[4]); str_to_number(item_table->bWeight, data[5]); str_to_number(item_table->bSize, data[6]); str_to_number(item_table->dwAntiFlags, data[7]); str_to_number(item_table->dwFlags, data[8]); str_to_number(item_table->dwWearFlags, data[9]); str_to_number(item_table->dwImmuneFlag, data[10]); str_to_number(item_table->dwGold, data[11]); str_to_number(item_table->dwShopBuyPrice, data[12]); str_to_number(item_table->dwRefinedVnum, data[13]); str_to_number(item_table->wRefineSet, data[14]); str_to_number(item_table->bAlterToMagicItemPct, data[15]); item_table->cLimitRealTimeFirstUseIndex = -1; item_table->cLimitTimerBasedOnWearIndex = -1; str_to_number(item_table->aLimits[0].bType, data[16]); str_to_number(item_table->aLimits[0].lValue, data[17]); if (LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[0].bType) item_table->cLimitRealTimeFirstUseIndex = (char)0; if (LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[0].bType) item_table->cLimitTimerBasedOnWearIndex = (char)0; str_to_number(item_table->aLimits[1].bType, data[18]); str_to_number(item_table->aLimits[1].lValue, data[19]); if (LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[1].bType) item_table->cLimitRealTimeFirstUseIndex = (char)1; if (LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[1].bType) item_table->cLimitTimerBasedOnWearIndex = (char)1; str_to_number(item_table->aApplies[0].bType, data[20]); str_to_number(item_table->aApplies[0].lValue, data[21]); str_to_number(item_table->aApplies[1].bType, data[22]); str_to_number(item_table->aApplies[1].lValue, data[23]); str_to_number(item_table->aApplies[2].bType, data[24]); str_to_number(item_table->aApplies[2].lValue, data[25]); str_to_number(item_table->alValues[0], data[26]); str_to_number(item_table->alValues[1], data[27]); str_to_number(item_table->alValues[2], data[28]); str_to_number(item_table->alValues[3], data[29]); str_to_number(item_table->alValues[4], data[30]); str_to_number(item_table->alValues[5], data[31]); str_to_number(item_table->bGainSocketPct, data[32]); str_to_number(item_table->sAddonType, data[33]); vnumSet.insert(item_table->dwVnum); m_map_itemTableByVnum.insert(std::map::value_type(item_table->dwVnum, item_table)); sys_log(0, "ITEM: #%-5lu %-24s %-24s VAL: %d %ld %d %d %d %d WEAR %d ANTI %d IMMUNE %d REFINE %lu REFINE_SET %u MAGIC_PCT %u", item_table->dwVnum, item_table->szName, item_table->szLocaleName, item_table->alValues[0], item_table->alValues[1], item_table->alValues[2], item_table->alValues[3], item_table->alValues[4], item_table->alValues[5], item_table->dwWearFlags, item_table->dwAntiFlags, item_table->dwImmuneFlag, item_table->dwRefinedVnum, item_table->wRefineSet, item_table->bAlterToMagicItemPct); item_table++; } fprintf(stderr," Complete! %d Items loaded.\r\n",addNumber); return true; } et bool CClientManager::InitializeMobTable() { //================== ÇÔ¼ö ¼³¸í ==================// //1. ¿ä¾à : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' ÆÄÀÏÀ» Àаí, // (!)[mob_table] Å×ÀÌºí ¿ÀºêÁ§Æ®¸¦ »ý¼ºÇÑ´Ù. (ŸÀÔ : TMobTable) //2. ¼ø¼­ // 1) 'mob_names.txt' ÆÄÀÏÀ» Àо (a)[localMap](vnum:name) ¸ÊÀ» ¸¸µç´Ù. // 2) 'mob_proto_test.txt'ÆÄÀÏ°ú (a)[localMap] ¸ÊÀ¸·Î // (b)[test_map_mobTableByVnum](vnum:TMobTable) ¸ÊÀ» »ý¼ºÇÑ´Ù. // 3) 'mob_proto.txt' ÆÄÀÏ°ú (a)[localMap] ¸ÊÀ¸·Î // (!)[mob_table] Å×À̺íÀ» ¸¸µç´Ù. // <Âü°í> // °¢ row µé Áß, // (b)[test_map_mobTableByVnum],(!)[mob_table] ¸ðµÎ¿¡ ÀÖ´Â row´Â // (b)[test_map_mobTableByVnum]ÀÇ °ÍÀ» »ç¿ëÇÑ´Ù. // 4) (b)[test_map_mobTableByVnum]ÀÇ rowÁß, (!)[mob_table]¿¡ ¾ø´Â °ÍÀ» Ãß°¡ÇÑ´Ù. //3. Å×½ºÆ® // 1)'mob_proto.txt' Á¤º¸°¡ mob_table¿¡ Àß µé¾î°¬´ÂÁö. -> ¿Ï·á // 2)'mob_names.txt' Á¤º¸°¡ mob_table¿¡ Àß µé¾î°¬´ÂÁö. // 3)'mob_proto_test.txt' ¿¡¼­ [°ãÄ¡´Â] Á¤º¸°¡ mob_table ¿¡ Àß µé¾î°¬´ÂÁö. // 4)'mob_proto_test.txt' ¿¡¼­ [»õ·Î¿î] Á¤º¸°¡ mob_table ¿¡ Àß µé¾î°¬´ÂÁö. // 5) (ÃÖÁ¾) °ÔÀÓ Å¬¶óÀ̾ðÆ®¿¡¼­ Á¦´ë·Î ÀÛµ¿ ÇÏ´ÂÁö. //_______________________________________________// //===============================================// // 1) 'mob_names.txt' ÆÄÀÏÀ» Àо (a)[localMap] ¸ÊÀ» ¸¸µç´Ù. //<(a)localMap ¸Ê »ý¼º> map localMap; bool isNameFile = true; //<ÆÄÀÏ Àбâ> cCsvTable nameData; if(!nameData.Load("mob_names.txt",'\t')) { fprintf(stderr, "mob_names.txt ÆÄÀÏÀ» Àоî¿ÀÁö ¸øÇß½À´Ï´Ù\n"); isNameFile = false; } else { nameData.Next(); //¼³¸írow »ý·«. while(nameData.Next()) { localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1); } } //________________________________________________// //===============================================// // 2) 'mob_proto_test.txt'ÆÄÀÏ°ú (a)localMap ¸ÊÀ¸·Î // (b)[test_map_mobTableByVnum](vnum:TMobTable) ¸ÊÀ» »ý¼ºÇÑ´Ù. //0. set vnumSet; //Å×½ºÆ®¿ë ÆÄÀÏ µ¥ÀÌÅÍÁß, ½Å±Ô¿©ºÎ È®Àο¡ »ç¿ë. //1. ÆÄÀÏ Àоî¿À±â bool isTestFile = true; cCsvTable test_data; if(!test_data.Load("mob_proto_test.txt",'\t')) { fprintf(stderr, "Å×½ºÆ® ÆÄÀÏÀÌ ¾ø½À´Ï´Ù. ±×´ë·Î ÁøÇàÇÕ´Ï´Ù.\n"); isTestFile = false; } //2. (c)[test_map_mobTableByVnum](vnum:TMobTable) ¸Ê »ý¼º. map test_map_mobTableByVnum; if (isTestFile) { test_data.Next(); //¼³¸í ·Î¿ì ³Ñ¾î°¡±â. //¤¡. Å×½ºÆ® ¸ó½ºÅÍ Å×ÀÌºí »ý¼º. TMobTable * test_mob_table = NULL; int test_MobTableSize = test_data.m_File.GetRowCount()-1; test_mob_table = new TMobTable[test_MobTableSize]; memset(test_mob_table, 0, sizeof(TMobTable) * test_MobTableSize); //¤¤. Å×½ºÆ® ¸ó½ºÅÍ Å×ÀÌºí¿¡ °ªÀ» ³Ö°í, ¸Ê¿¡±îÁö ³Ö±â. while(test_data.Next()) { if (!Set_Proto_Mob_Table(test_mob_table, test_data, localMap)) { fprintf(stderr, "¸÷ ÇÁ·ÎÅä Å×ÀÌºí ¼ÂÆà ½ÇÆÐ.\n"); } test_map_mobTableByVnum.insert(std::map::value_type(test_mob_table->dwVnum, test_mob_table)); ++test_mob_table; } } // 3) 'mob_proto.txt' ÆÄÀÏ°ú (a)[localMap] ¸ÊÀ¸·Î // (!)[mob_table] Å×À̺íÀ» ¸¸µç´Ù. // <Âü°í> // °¢ row µé Áß, // (b)[test_map_mobTableByVnum],(!)[mob_table] ¸ðµÎ¿¡ ÀÖ´Â row´Â // (b)[test_map_mobTableByVnum]ÀÇ °ÍÀ» »ç¿ëÇÑ´Ù. //1. ÆÄÀÏ Àбâ. cCsvTable data; if(!data.Load("mob_proto.txt",'\t')) { fprintf(stderr, "mob_proto.txt ÆÄÀÏÀ» Àоî¿ÀÁö ¸øÇß½À´Ï´Ù\n"); return false; } data.Next(); //¼³¸í row ³Ñ¾î°¡±â //2. (!)[mob_table] »ý¼ºÇϱâ //2.1 »õ·Î Ãß°¡µÇ´Â °¹¼ö¸¦ ÆÄ¾Ç int addNumber = 0; while(data.Next()) { int vnum = atoi(data.AsStringByIndex(0)); std::map::iterator it_map_mobTable; it_map_mobTable = test_map_mobTableByVnum.find(vnum); if(it_map_mobTable != test_map_mobTableByVnum.end()) { addNumber++; } } //data¸¦ ´Ù½Ã ùÁÙ·Î ¿Å±ä´Ù.(´Ù½Ã Àоî¿Â´Ù; data.Destroy(); if(!data.Load("mob_proto.txt",'\t')) { fprintf(stderr, "mob_proto.txt ÆÄÀÏÀ» Àоî¿ÀÁö ¸øÇß½À´Ï´Ù\n"); return false; } data.Next(); //¸Ç À­ÁÙ Á¦¿Ü (¾ÆÀÌÅÛ Ä®·³À» ¼³¸íÇÏ´Â ºÎºÐ) //2.2 Å©±â¿¡ ¸Â°Ô mob_table »ý¼º if (!m_vec_mobTable.empty()) { sys_log(0, "RELOAD: mob_proto"); m_vec_mobTable.clear(); } m_vec_mobTable.resize(data.m_File.GetRowCount()-1 + addNumber); memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size()); TMobTable * mob_table = &m_vec_mobTable[0]; //2.3 µ¥ÀÌÅÍ Ã¤¿ì±â while (data.Next()) { int col = 0; //(b)[test_map_mobTableByVnum]¿¡ °°Àº row°¡ ÀÖ´ÂÁö Á¶»ç. bool isSameRow = true; std::map::iterator it_map_mobTable; it_map_mobTable = test_map_mobTableByVnum.find(atoi(data.AsStringByIndex(col))); if(it_map_mobTable == test_map_mobTableByVnum.end()) { isSameRow = false; } //°°Àº row °¡ ÀÖÀ¸¸é (b)¿¡¼­ Àоî¿Â´Ù. if(isSameRow) { TMobTable *tempTable = it_map_mobTable->second; mob_table->dwVnum = tempTable->dwVnum; strlcpy(mob_table->szName, tempTable->szName, sizeof(tempTable->szName)); strlcpy(mob_table->szLocaleName, tempTable->szLocaleName, sizeof(tempTable->szName)); mob_table->bRank = tempTable->bRank; mob_table->bType = tempTable->bType; mob_table->bBattleType = tempTable->bBattleType; mob_table->bLevel = tempTable->bLevel; mob_table->bSize = tempTable->bSize; mob_table->dwAIFlag = tempTable->dwAIFlag; mob_table->dwRaceFlag = tempTable->dwRaceFlag; mob_table->dwImmuneFlag = tempTable->dwImmuneFlag; mob_table->bEmpire = tempTable->bEmpire; strlcpy(mob_table->szFolder, tempTable->szFolder, sizeof(tempTable->szName)); mob_table->bOnClickType = tempTable->bOnClickType; mob_table->bStr = tempTable->bStr; mob_table->bDex = tempTable->bDex; mob_table->bCon = tempTable->bCon; mob_table->bInt = tempTable->bInt; mob_table->dwDamageRange[0] = tempTable->dwDamageRange[0]; mob_table->dwDamageRange[1] = tempTable->dwDamageRange[1]; mob_table->dwMaxHP = tempTable->dwMaxHP; mob_table->bRegenCycle = tempTable->bRegenCycle; mob_table->bRegenPercent = tempTable->bRegenPercent; mob_table->dwGoldMin = tempTable->dwGoldMin; mob_table->dwGoldMax = tempTable->dwGoldMax; mob_table->dwExp = tempTable->dwExp; mob_table->wDef = tempTable->wDef; mob_table->sAttackSpeed = tempTable->sAttackSpeed; mob_table->sMovingSpeed = tempTable->sMovingSpeed; mob_table->bAggresiveHPPct = tempTable->bAggresiveHPPct; mob_table->wAggressiveSight = tempTable->wAggressiveSight; mob_table->wAttackRange = tempTable->wAttackRange; mob_table->dwDropItemVnum = tempTable->dwDropItemVnum; mob_table->dwResurrectionVnum = tempTable->dwResurrectionVnum; for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i) mob_table->cEnchants[i] = tempTable->cEnchants[i]; for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i) mob_table->cResists[i] = tempTable->cResists[i]; mob_table->fDamMultiply = tempTable->fDamMultiply; mob_table->dwSummonVnum = tempTable->dwSummonVnum; mob_table->dwDrainSP = tempTable->dwDrainSP; mob_table->dwPolymorphItemVnum = tempTable->dwPolymorphItemVnum; mob_table->Skills[0].bLevel = tempTable->Skills[0].bLevel; mob_table->Skills[0].dwVnum = tempTable->Skills[0].dwVnum; mob_table->Skills[1].bLevel = tempTable->Skills[1].bLevel; mob_table->Skills[1].dwVnum = tempTable->Skills[1].dwVnum; mob_table->Skills[2].bLevel = tempTable->Skills[2].bLevel; mob_table->Skills[2].dwVnum = tempTable->Skills[2].dwVnum; mob_table->Skills[3].bLevel = tempTable->Skills[3].bLevel; mob_table->Skills[3].dwVnum = tempTable->Skills[3].dwVnum; mob_table->Skills[4].bLevel = tempTable->Skills[4].bLevel; mob_table->Skills[4].dwVnum = tempTable->Skills[4].dwVnum; mob_table->bBerserkPoint = tempTable->bBerserkPoint; mob_table->bStoneSkinPoint = tempTable->bStoneSkinPoint; mob_table->bGodSpeedPoint = tempTable->bGodSpeedPoint; mob_table->bDeathBlowPoint = tempTable->bDeathBlowPoint; mob_table->bRevivePoint = tempTable->bRevivePoint; } else { if (!Set_Proto_Mob_Table(mob_table, data, localMap)) { fprintf(stderr, "¸÷ ÇÁ·ÎÅä Å×ÀÌºí ¼ÂÆà ½ÇÆÐ.\n"); } } //¼Â¿¡ vnum Ãß°¡ vnumSet.insert(mob_table->dwVnum); sys_log(1, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire); ++mob_table; } //_____________________________________________________// // 4) (b)[test_map_mobTableByVnum]ÀÇ rowÁß, (!)[mob_table]¿¡ ¾ø´Â °ÍÀ» Ãß°¡ÇÑ´Ù. //ÆÄÀÏ ´Ù½Ã Àоî¿À±â. test_data.Destroy(); isTestFile = true; test_data; if(!test_data.Load("mob_proto_test.txt",'\t')) { fprintf(stderr, "Å×½ºÆ® ÆÄÀÏÀÌ ¾ø½À´Ï´Ù. ±×´ë·Î ÁøÇàÇÕ´Ï´Ù.\n"); isTestFile = false; } if(isTestFile) { test_data.Next(); //¼³¸í ·Î¿ì ³Ñ¾î°¡±â. while (test_data.Next()) //Å×½ºÆ® µ¥ÀÌÅÍ °¢°¢À» ÈȾ°¡¸ç,»õ·Î¿î °ÍÀ» Ãß°¡ÇÑ´Ù. { //Áߺ¹µÇ´Â ºÎºÐÀÌ¸é ³Ñ¾î°£´Ù. set::iterator itVnum; itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0))); if (itVnum != vnumSet.end()) { continue; } if (!Set_Proto_Mob_Table(mob_table, test_data, localMap)) { fprintf(stderr, "¸÷ ÇÁ·ÎÅä Å×ÀÌºí ¼ÂÆà ½ÇÆÐ.\n"); } sys_log(0, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire); ++mob_table; } } sort(m_vec_mobTable.begin(), m_vec_mobTable.end(), FCompareVnum()); return true; } par bool CClientManager::InitializeMobTable() { char query[2048]; fprintf(stderr,"Loading mob_proto from MySQL "); snprintf(query, sizeof(query), "SELECT vnum,name,%s,rank,type,battle_type,level,size,ai_flag,mount_capacity,setRaceFlag,setImmuneFlag," "empire,folder,on_click,st,dx,ht,iq,damage_min,damage_max,max_hp,regen_cycle,regen_percent,gold_min," "gold_max,exp,def,attack_speed,move_speed,aggressive_hp_pct,aggressive_sight,attack_range,drop_item," "resurrection_vnum,enchant_curse,enchant_slow,enchant_poison,enchant_stun,enchant_critical,enchant_penetrate," "resist_sword,resist_twohand,resist_dagger,resist_bell,resist_fan,resist_bow,resist_fire,resist_elect," "resist_magic,resist_wind,resist_poison,dam_multiply,summon,drain_sp,mob_color,polymorph_item,skill_level0," "skill_vnum0,skill_level1,skill_vnum1,sp_berserk,sp_stoneskin,sp_godspeed,sp_deathblow,sp_revive,skill_level2," "skill_vnum2,skill_level3,skill_vnum3,skill_level4,skill_vnum4 FROM mob_proto%s" ,g_stLocaleNameColumn.c_str(), GetTablePostfix()); std::auto_ptr pkMsg(CDBManager::instance().DirectQuery(query)); SQLResult * pRes = pkMsg->Get(); if (!pRes->uiNumRows) return false; if (!m_vec_mobTable.empty()) { sys_log(0, "RELOAD: mob_proto"); m_vec_mobTable.clear(); } int size = pRes->uiNumRows; m_vec_mobTable.resize(size); memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size()); TMobTable * mob_table = &m_vec_mobTable[0]; MYSQL_ROW data; //return true; set vnumSet; while ((data = mysql_fetch_row(pRes->pSQLResult))) { /* "SELECT vnum,name,locale_name,rank,type,battle_type,level,size,ai_flag,mount_capacity,setRaceFlag,setImmuneFlag," "empire,folder,on_click,st,dx,ht,iq,damage_min,damage_max,max_hp,regen_cycle,regen_percent,gold_min," "gold_max,exp,def,attack_speed,move_speed,aggressive_hp_pct,aggressive_sight,attack_range,drop_item," "resurrection_vnum,enchant_curse,enchant_slow,enchant_poison,enchant_stun,enchant_critical,enchant_penetrate," "resist_sword,resist_twohand,resist_dagger,resist_bell,resist_fan,resist_bow,resist_fire,resist_elect," "resist_magic,resist_wind,resist_poison,dam_multiply,summon,drain_sp,mob_color,polymorph_item,skill_level0," "skill_vnum0,skill_level1,skill_vnum1,sp_berserk,sp_stoneskin,sp_godspeed,sp_deathblow,sp_revive,skill_level2," "skill_vnum2,skill_level3,skill_vnum3,skill_level4,skill_vnum4 FROM mob_proto%s */ int col = 0; str_to_number(mob_table->dwVnum, data[col++]); if(mob_table->dwVnum ==0) continue; strlcpy(mob_table->szName,data[col++] , sizeof(mob_table->szName)); strlcpy(mob_table->szLocaleName, data[col++], sizeof(mob_table->szLocaleName)); str_to_number(mob_table->bRank,data[col++]); str_to_number(mob_table->bType,data[col++]); str_to_number(mob_table->bBattleType,data[col++]); str_to_number(mob_table->bLevel,data[col++]); str_to_number(mob_table->bSize,data[col++]); //AI_FLAG mob_table->dwAIFlag = get_Mob_AIFlag_Value(data[col++]); //mount_capacity; col++; //RACE_FLAG mob_table->dwRaceFlag = get_Mob_RaceFlag_Value(data[col++]); //IMMUNE_FLAG mob_table->dwImmuneFlag = get_Mob_ImmuneFlag_Value(data[col++]); mob_table->bEmpire = atoi(data[col++]); strlcpy(mob_table->szFolder, data[col++], sizeof(mob_table->szFolder)); mob_table->bOnClickType = atoi(data[col++]); mob_table->bStr = atoi(data[col++]); mob_table->bDex = atoi(data[col++]); mob_table->bCon = atoi(data[col++]); mob_table->bInt = atoi(data[col++]); mob_table->dwDamageRange[0] = atoi(data[col++]); mob_table->dwDamageRange[1] = atoi(data[col++]); mob_table->dwMaxHP = atoi(data[col++]); mob_table->bRegenCycle = atoi(data[col++]); mob_table->bRegenPercent = atoi(data[col++]); mob_table->dwGoldMin = atoi(data[col++]); mob_table->dwGoldMax = atoi(data[col++]); mob_table->dwExp = atoi(data[col++]); mob_table->wDef = atoi(data[col++]); mob_table->sAttackSpeed = atoi(data[col++]); mob_table->sMovingSpeed = atoi(data[col++]); mob_table->bAggresiveHPPct = atoi(data[col++]); mob_table->wAggressiveSight = atoi(data[col++]); mob_table->wAttackRange = atoi(data[col++]); str_to_number(mob_table->dwDropItemVnum, data[col++]); //32 str_to_number(mob_table->dwResurrectionVnum, data[col++]); for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i) str_to_number(mob_table->cEnchants[i], data[col++]); for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i) str_to_number(mob_table->cResists[i], data[col++]); str_to_number(mob_table->fDamMultiply, data[col++]); str_to_number(mob_table->dwSummonVnum, data[col++]); str_to_number(mob_table->dwDrainSP, data[col++]); //Mob_Color ++col; str_to_number(mob_table->dwPolymorphItemVnum, data[col++]); str_to_number(mob_table->Skills[0].bLevel, data[col++]); str_to_number(mob_table->Skills[0].dwVnum, data[col++]); str_to_number(mob_table->Skills[1].bLevel, data[col++]); str_to_number(mob_table->Skills[1].dwVnum, data[col++]); str_to_number(mob_table->Skills[2].bLevel, data[col++]); str_to_number(mob_table->Skills[2].dwVnum, data[col++]); str_to_number(mob_table->Skills[3].bLevel, data[col++]); str_to_number(mob_table->Skills[3].dwVnum, data[col++]); str_to_number(mob_table->Skills[4].bLevel, data[col++]); str_to_number(mob_table->Skills[4].dwVnum, data[col++]); str_to_number(mob_table->bBerserkPoint, data[col++]); str_to_number(mob_table->bStoneSkinPoint, data[col++]); str_to_number(mob_table->bGodSpeedPoint, data[col++]); str_to_number(mob_table->bDeathBlowPoint, data[col++]); str_to_number(mob_table->bRevivePoint, data[col++]); //ĽÂżˇ vnum Ăß°ˇ vnumSet.insert(mob_table->dwVnum); //fprintf(stderr, "MOB #%d %s %s level: %u rank: %u empire: %d\n", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire); sys_log(0, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire); ++mob_table; } fprintf(stderr," Complete! %d/%d Mobs loaded.\r\n",size,vnumSet.size()); sort(m_vec_mobTable.begin(), m_vec_mobTable.end(), FCompareVnum()); return true; } Attention dans bool CClientManager::InitializeTables() vous devrez supprimez donc MirrorMobTableIntoDB() and MirrorItemTableIntoDB() Source : EPvP
  3. Salut à tous , je vais vous expliquer comment mettre 4 pages d'inventaire. Tout d'abord, allez ici : Server/common/ puis ouvrez length.h Ensuite cherchez : INVENTORY_MAX_NUM = 90, et remplacez par : INVENTORY_MAX_NUM = 180, Ensuite, dans le répertoire : game/src ouvrez char_item.cpp et cherchez : BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2); et remplacez cette ligne par : BYTE bPage = bCell / (INVENTORY_MAX_NUM / 4); Cherchez ensuite(toujours dans le char_item.cpp) : if (p / (INVENTORY_MAX_NUM / 2) != bPage) puis remplacez par : if (p / (INVENTORY_MAX_NUM / 4) != bPage) Ensuite ouvrez exchange.cpp et cherchez : static CGrid s_grid1(5, INVENTORY_MAX_NUM/5 / 2); // inven page 1 puis complétez comme ici : static CGrid s_grid1(5, INVENTORY_MAX_NUM/5 / 4); // inven page 1 static CGrid s_grid2(5, INVENTORY_MAX_NUM/5 / 4); // inven page 2 static CGrid s_grid3(5, INVENTORY_MAX_NUM/5 / 4); // inven page 3 static CGrid s_grid4(5, INVENTORY_MAX_NUM/5 / 4); // inven page 4 s_grid1.Clear(); s_grid2.Clear(); s_grid3.Clear(); s_grid4.Clear(); Ensuite, rajoutez en début de fichier ces lignes (en dessous des #include) : /* 4 INVENTORY DEFINES */ #define INVEN_PAGES 4 #define INVEN_PAGE_SIZE (INVENTORY_MAX_NUM / INVEN_PAGES) Ensuite dans la fonction , remplacez les lignes ci-dessous : for (i = 0; i < INVEN_PAGE_SIZE; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid1.Put(i, 1, item->GetSize()); } for (i = INVEN_PAGE_SIZE; i < INVEN_PAGE_SIZE*2; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid2.Put(i - INVEN_PAGE_SIZE, 1, item->GetSize()); } for (i = INVEN_PAGE_SIZE*2; i < INVEN_PAGE_SIZE*3; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid3.Put(i - INVEN_PAGE_SIZE*2, 1, item->GetSize()); } for (i = INVEN_PAGE_SIZE*3; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid4.Put(i - INVEN_PAGE_SIZE*3, 1, item->GetSize()); } PARTIE SERVEUR TERMINÉE Passons maintenant Partie client. Pour commencer , allez ici : Client/Userinterface et ouvrez GameType.h et cherchez : const DWORD c_Inventory_Page_Count = 2; et remplacez par : const DWORD c_Inventory_Page_Count = 4; Ouvrez ensuite inventorywindow.py et cherchez : EQUIPMENT_START_INDEX = 90 que vous remplacez par : EQUIPMENT_START_INDEX = 180 Ensuite, (eh oui, c'est toujours pas terminé !) ouvrez uiinventory.py et cherchez : self.inventoryTab.append(self.GetChild("Inventory_Tab_02")) que vous ajoutez en dessous : self.inventoryTab.append(self.GetChild("Inventory_Tab_03")) self.inventoryTab.append(self.GetChild("Inventory_Tab_04")) ensuite cherchez : self.inventoryTab[1].SetEvent(lambda arg=1: self.SetInventoryPage(arg)) et ajoutez en dessous : self.inventoryTab[2].SetEvent(lambda arg=2: self.SetInventoryPage(arg)) self.inventoryTab[3].SetEvent(lambda arg=3: self.SetInventoryPage(arg)) cherchez ensuite : self.inventoryTab[0].Down() rajoutez en dessous : self.inventoryPageIndex = 0 Ensuite cherchez la fonction SetInventoryPage et remplacez par ça : def SetInventoryPage(self, page): self.inventoryTab[self.inventoryPageIndex].SetUp() self.inventoryPageIndex = page self.inventoryTab[self.inventoryPageIndex].Down() self.RefreshBagSlotWindow() PARTIE CLIENT TERMINÉE Vous pouvez tout recompiler et la partie source est terminée. Je vous partage mon inventorywindow.py qui se trouve dans locale_fr/ui : import uiScriptLocale import item EQUIPMENT_START_INDEX = 180 window = { "name" : "InventoryWindow", ## 600 - (width + i?¢´e¡Í¢¬i¨£¨öi©«¨ùe¢®©« e¢Ò¢æi?¡Æ e?i?¡Æe¢¬¡Æ 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}, ## i?? e¡Æ?i¡×¢æ1 ##{"index":item.EQUIPMENT_RING1, "x":2, "y":106, "width":32, "height":32}, ## i?? e¡Æ?i¡×¢æ2 ##{"index":item.EQUIPMENT_RING2, "x":75, "y":106, "width":32, "height":32}, ## i?? e©÷¡§i?¢¬ {"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_3, "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_4, "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", }, ), }, ), }, ), } Pour clore le tutoriel , allez dans locale_interface.txt et cherchez : INVENTORY_PAGE_BUTTON_TOOLTIP_2 2e inventaire et ajoutez en dessous : INVENTORY_PAGE_BUTTON_TOOLTIP_3 3e inventaire INVENTORY_PAGE_BUTTON_TOOLTIP_4 4e inventaire Vous pouvez tout recompiler, repacker et regarder le résultat. Voila, tutoriel terminé, bonne chance ! Source : M2Dev, Corrigé par Kameyu, et merci à History, Galet et Calypso pour leur participation au débug.
  4. Bonjour ! Je vous propose un tutoriel pour installer le système de ticket partagé par Shang, que j'ai corrigé car il contenait d'assez gros problèmes côté python, permettant des injections SQL. I - Source client : Dans le fichier Packet.h : Chercher : QUEST_INPUT_STRING_MAX_NUM = 64, Ajouter juste après : #ifdef ENABLE_TICKET_SYSTEM QUEST_INPUT_STRING_LONG_MAX_NUM = 512, #endif Chercher ensuite : typedef struct command_quest_input_string { BYTE bHeader; char szString[QUEST_INPUT_STRING_MAX_NUM+1]; } TPacketCGQuestInputString; Ajouter : #ifdef ENABLE_TICKET_SYSTEM typedef struct command_quest_input_long_string { BYTE bHeader; char szString[QUEST_INPUT_STRING_LONG_MAX_NUM]; } TPacketCGQuestInputLongString; #endif Pour en finir avec ce fichier, chercher : #ifdef __AUCTION__ HEADER_CG_AUCTION_CMD = 205, #endif Puis ajouter : #ifdef ENABLE_TICKET_SYSTEM HEADER_CG_QUEST_INPUT_LONG_STRING = 214, #endif Vérifiez qu'aucun de vos packets n'utilise le 214, sinon changez en conséquence, et vous ferez de même dans les sources serveur. Dans le fichier PythonNetworkStream.h : Chercher : bool SendQuestInputStringPacket(const char * c_szString); Ajouter : #ifdef ENABLE_TICKET_SYSTEM bool SendQuestInputStringLongPacket(const char * c_pszString); #endif Dans le fichier PythonNetworkStreamModule.cpp : Chercher : PyObject* netSendQuestInputStringPacket(PyObject* poSelf, PyObject* poArgs) { char * szString; if (!PyTuple_GetString(poArgs, 0, &szString)) return Py_BuildException(); CPythonNetworkStream& rns=CPythonNetworkStream::Instance(); rns.SendQuestInputStringPacket(szString); return Py_BuildNone(); } Ajouter : #ifdef ENABLE_TICKET_SYSTEM PyObject * netSendQuestInputLongStringPacket(PyObject * poSelf, PyObject * poArgs) { char * szString; if (!PyTuple_GetString(poArgs, 0, &szString)) return Py_BuildException(); CPythonNetworkStream & rns = CPythonNetworkStream::Instance(); rns.SendQuestInputStringLongPacket(szString); return Py_BuildNone(); } #endif Chercher ensuite : { "SendQuestInputStringPacket", netSendQuestInputStringPacket, METH_VARARGS }, Ajouter : #ifdef ENABLE_TICKET_SYSTEM { "SendQuestInputLongStringPacket", netSendQuestInputLongStringPacket, METH_VARARGS }, #endif Dans le fichier PythonNetworkSteamPhaseGame.cpp : Chercher : bool CPythonNetworkStream::SendQuestInputStringPacket(const char * c_szString) { TPacketCGQuestInputString Packet; Packet.bHeader = HEADER_CG_QUEST_INPUT_STRING; strncpy(Packet.szString, c_szString, QUEST_INPUT_STRING_MAX_NUM); if (!Send(sizeof(Packet), &Packet)) { Tracen("SendQuestInputStringPacket Error"); return false; } return SendSequence(); } Ajouter : #ifdef ENABLE_TICKET_SYSTEM bool CPythonNetworkStream::SendQuestInputStringLongPacket(const char * c_pszString) { TPacketCGQuestInputLongString Packet; Packet.bHeader = HEADER_CG_QUEST_INPUT_LONG_STRING; strncpy(Packet.szString, c_pszString, QUEST_INPUT_STRING_LONG_MAX_NUM); if (!Send(sizeof(Packet), &Packet)) { Tracen("SendQuestInputStringLongPacket Error"); return false; } return SendSequence(); } #endif Dans le fichier PythonApplicationModule.cpp : Chercher : #ifdef ENABLE_COSTUME_SYSTEM PyModule_AddIntConstant(poModule, "ENABLE_COSTUME_SYSTEM", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_COSTUME_SYSTEM", 0); #endif Ajouter : #ifdef ENABLE_TICKET_SYSTEM PyModule_AddIntConstant(poModule, "ENABLE_TICKET_SYSTEM", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_TICKET_SYSTEM", 0); #endif Dans le fichier Locale_inc.h : Ajouter : #define ENABLE_TICKET_SYSTEM Vous pouvez maintenant lancer la compilation de vos sources client le temps qu'on s'occupe des sources serveur ! II - Source serveur : Dans le fichier service.h : Ajouter : #define ENABLE_TICKET_SYSTEM Dans le fichier input.h : Chercher : void QuestInputString(LPCHARACTER ch, const void * pvData); Ajouter : #ifdef ENABLE_TICKET_SYSTEM void QuestInputLongString(LPCHARACTER ch, const void * c_pvData); #endif Dans le fichier input_main.cpp : Chercher : void CInputMain::QuestInputString(LPCHARACTER ch, const void* c_pData) { TPacketCGQuestInputString * p = (TPacketCGQuestInputString*) c_pData; char msg[65]; strlcpy(msg, p->msg, sizeof(msg)); sys_log(0, "QUEST InputString pid %u msg %s", ch->GetPlayerID(), msg); quest::CQuestManager::Instance().Input(ch->GetPlayerID(), msg); } Ajouter : #ifdef ENABLE_TICKET_SYSTEM void CInputMain::QuestInputLongString(LPCHARACTER ch, const void * c_pvData) { const TPacketCGQuestInputLongString * p = reinterpret_cast<const TPacketCGQuestInputLongString*>(c_pvData); sys_log(0, "QUEST InputLongString pid %u msg %s", ch->GetPlayerID(), p->szMsg); quest::CQuestManager::Instance().Input(ch->GetPlayerID(), p->szMsg); } #endif Chercher : case HEADER_CG_QUEST_INPUT_STRING: QuestInputString(ch, c_pData); break; Ajouter : #ifdef ENABLE_TICKET_SYSTEM case HEADER_CG_QUEST_INPUT_LONG_STRING: QuestInputLongString(ch, c_pData); break; #endif Dans le fichier packet.h : Chercher : typedef struct command_quest_input_string { BYTE header; char msg[64+1]; } TPacketCGQuestInputString; Ajouter : #ifdef ENABLE_TICKET_SYSTEM typedef struct command_quest_input_long_string { BYTE header; char szMsg[512]; } TPacketCGQuestInputLongString; #endif Chercher : HEADER_CG_XTRAP_ACK = 204, Ajouter : #ifdef ENABLE_TICKET_SYSTEM HEADER_CG_QUEST_INPUT_LONG_STRING = 214, #endif -->Penser à modifier le packet si vous l'avez fait dans les sources client. Dans le fichier packet_info.cpp : Chercher : Set(HEADER_CG_STATE_CHECKER, sizeof(BYTE), "ServerStateCheck", false); Ajouter : #ifdef ENABLE_TICKET_SYSTEM Set(HEADER_CG_QUEST_INPUT_LONG_STRING, sizeof(TPacketCGQuestInputLongString), "QuestInputLongString", true); #endif Dans le fichier questlua_global.cpp : Si, et seulement si vous n'avez pas mysql_direct_query, vous suivez cette étape, sinon, vous pouvez dores et déjà compiler vos sources. Chercher : void RegisterGlobalFunctionTable(lua_State* L) Ajouter au dessus : #ifdef _MSC_VER #define INFINITY (DBL_MAX+DBL_MAX) #define NAN (INFINITY-INFINITY) #endif int _mysql_direct_query(lua_State* L) { // char szQuery[1024]; if (!lua_isstring(L, 1)) return 0; // strncpy(szQuery, lua_tostring(L, 1), sizeof(szQuery)); int i=0, m=1; MYSQL_ROW row; MYSQL_FIELD * field; MYSQL_RES * result; // SQLMsg * pMsg = DBManager::instance().DirectQuery(szQuery); std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery(lua_tostring(L, 1))); if (pMsg.get()) { // ret1 (number of affected rows) lua_pushnumber(L, pMsg->Get()->uiAffectedRows); //-1 if error such as duplicate occurs (-2147483648 via lua) // if wrong syntax error occurs (4294967295 via lua) // ret2 (table of affected rows) lua_newtable(L); if ((result = pMsg->Get()->pSQLResult) && !(pMsg->Get()->uiAffectedRows == 0 || pMsg->Get()->uiAffectedRows == (uint32_t)-1)) { // LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); // ch->ChatPacket(CHAT_TYPE_INFO, "<%s> Retrieved %u fields\n", __FUNCTION__, mysql_num_fields(result)); // ch->ChatPacket(CHAT_TYPE_INFO, "<%s> Retrieved %u rows\n", __FUNCTION__, mysql_num_rows(result)); // ch->ChatPacket(CHAT_TYPE_INFO, "<%s> Affected %u rows\n", __FUNCTION__, pMsg->Get()->uiAffectedRows); // ch->ChatPacket(CHAT_TYPE_INFO, "<%s> Num %u rows\n", __FUNCTION__, pMsg->Get()->uiNumRows); while((row = mysql_fetch_row(result))) { lua_pushnumber(L, m); lua_newtable(L); while((field = mysql_fetch_field(result))) { lua_pushstring(L, field->name); if (!(field->flags & NOT_NULL_FLAG) && (row[i]==NULL)) { // lua_pushstring(L, "NULL"); lua_pushnil(L); } else if (IS_NUM(field->type)) { double val = NAN; lua_pushnumber(L, (sscanf(row[i],"%lf",&val)==1)?val:NAN); } else if (field->type == MYSQL_TYPE_BLOB) { lua_newtable(L); for (DWORD iBlob=0; iBlob < field->max_length; iBlob++) { lua_pushnumber(L, row[i][iBlob]); lua_rawseti(L, -2, iBlob+1); } } else lua_pushstring(L, row[i]); // LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); // ch->ChatPacket(CHAT_TYPE_INFO, "<%s> Retrieved %d flag %s for %s\n", __FUNCTION__, field->type, field->name, row[i]?row[i]:"NULL"); lua_rawset(L, -3); i++; } mysql_field_seek(result, 0); i=0; lua_rawset(L, -3); m++; } } } else {lua_pushnumber(L, 0); lua_newtable(L);} // delete pMsg; return 2; } Chercher ensuite : { NULL, NULL } Ajouter au dessus : { "mysql_direct_query", _mysql_direct_query }, Vous pouvez maintenant lancer la compilation de vos sources serveur, le temps qu'on s'occupe des fichiers serveur ! III - Serveur : Vous allez dans cette partie, ajouter ceci dans votre quest_functions : ticket.answer_ticket ticket.create_ticket ticket.load_answers ticket.load_permisions ticket.load_tickets ticket.add_member ticket.update_permisions ticket.delete_member ticket.has_permision ticket.add_viewer ticket.delete_viewer Ajouter dans questlib : dofile(get_locale_base_path().."/quest/ticket_lib.so") Ajouter ensuite la lib disponible en pièce jointe, la quête et le dossiers "tickets" (Pièce jointe : QUEST.rar). IV - MySQL : je vous invite pour cette partie à lancer ces queries : SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for tickets -- ---------------------------- DROP TABLE IF EXISTS `tickets`; CREATE TABLE `tickets` ( `order_id` int(11) NOT NULL AUTO_INCREMENT, `id` varchar(8) NOT NULL, `title` varchar(60) NOT NULL, `priority` varchar(150) NOT NULL, `date` datetime NOT NULL, `status` tinyint(1) NOT NULL, `creator` varchar(16) NOT NULL, `msg` varchar(500) NOT NULL, `category` int(2) NOT NULL, PRIMARY KEY (`order_id`) ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for tickets_answers -- ---------------------------- DROP TABLE IF EXISTS `tickets_answers`; CREATE TABLE `tickets_answers` ( `order_id` int(11) NOT NULL AUTO_INCREMENT, `id` varchar(8) NOT NULL, `creator` varchar(16) NOT NULL, `date` datetime NOT NULL, `msg` varchar(500) NOT NULL, PRIMARY KEY (`order_id`) ) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1; SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for tickets_permisions -- ---------------------------- DROP TABLE IF EXISTS `tickets_permisions`; CREATE TABLE `tickets_permisions` ( `pid` int(50) NOT NULL, `answer_permision` tinyint(1) NOT NULL, `delete_permision` tinyint(1) NOT NULL, `add_permision` tinyint(1) NOT NULL, PRIMARY KEY (`pid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; V - Client : Dans votre locale_game.txt, ajouter : TICKET_PRIORITY_HIGH Élevée TICKET_PRIORITY_MEDIUM Normale TICKET_PRIORITY_LOW Faible TICKET_STATE_ON_HOLD En cours TICKET_STATE_CLOSED Fermé TICKET_STATE_SOLVED Résolu TICKET_ADD_NAME Nom: TICKET_ADD_TITLE Ajouter un membre TICKET_ADD_ACCEPT Accepter TICKET_SEND Envoyer TICKET_TITLE Asylum : Tickets TICKET_MY_TICKETS Mes Tickets TICKET_ADMINISTRATION Administration TICKET_SORT_BY Ordre : TICKET_ID ID TICKET_TITLE_T Titre TICKET_PRIORITY Priorité TICKET_DATE Date TICKET_STATE Etat TICKET_CREATE_NEW Créer un nouveau ticket TICKET_SEARCH Rechercher par ID: TICKET_SEARCH_BUTTON Rechercher TICKET_NAME Nom TICKET_ANSWER Répondre TICKET_DELETE Supprimer TICKET_CHANGE_PERMISIONS Modifier les permissions TICKET_ADD_MEMBER Ajouter un membre TICKET_REFRESH Actualiser TICKET_CATEGORY Categorie TICKET_CATEGORY_0 Tous Dans votre uiquest.py : Chercher : def Destroy(self): self.ClearDictionary() if self.OnCloseEvent: self.OnCloseEvent() self.OnCloseEvent = None # QUEST_INPUT if self.needInputString: if self.editLine: text = self.editLine.GetText() net.SendQuestInputStringPacket(text) # END_OF_QUEST_INPUT self.imgTitle = None self.images = None self.eventCurtain = None self.board = None Remplacer par : def Destroy(self): self.ClearDictionary() if self.OnCloseEvent: self.OnCloseEvent() self.OnCloseEvent = None # QUEST_INPUT if self.needInputString: if self.editLine: text = self.editLine.GetText() if app.ENABLE_TICKET_SYSTEM: if (len(text) > 64): net.SendQuestInputLongStringPacket(text) else: net.SendQuestInputStringPacket(text) else: net.SendQuestInputStringPacket(text) # END_OF_QUEST_INPUT self.imgTitle = None self.images = None self.eventCurtain = None self.board = None Dans le fichier interfaceModule.py : Ajouter : if app.ENABLE_TICKET_SYSTEM: import uiTicket Chercher : self.dlgShop = uiShop.ShopDialog() self.dlgShop.LoadDialog() self.dlgShop.Hide() Ajouter : if app.ENABLE_TICKET_SYSTEM: self.wndTicket = uiTicket.TicketWindow() self.wndTicket.Hide() Chercher : if self.dlgShop: self.dlgShop.Destroy() Ajouter : if app.ENABLE_TICKET_SYSTEM: if self.wndTicket: self.wndTicket.Destroy() Chercher : del self.wndItemSelect Ajouter : if app.ENABLE_TICKET_SYSTEM: del self.wndTicket Dans le fichier costinfo.py : Ajouter : if app.ENABLE_TICKET_SYSTEM: Tickets = { 'QID' : 0, 'QCMD' : '', 'MY_TICKETS' : [], 'GLOBAL_TICKETS' : [], 'ANSWERS' : {}, 'PERMISIONS' : [] } CApiSetHide = 0 Dans le fichier game.py : Chercher : "mall" : self.__InGameShop_Show, Ajouter : if app.ENABLE_TICKET_SYSTEM: "TICKETS" : self.ManagerTickets, Chercher : def OpenQuestWindow(self, skin, idx): Ajouter : if app.ENABLE_TICKET_SYSTEM: if constInfo.CApiSetHide == 1: net.SendQuestInputStringPacket(str(constInfo.SendString)) constInfo.CApiSetHide = 0 return Chercher : def __InGameShop_Show(self, url): if constInfo.IN_GAME_SHOP_ENABLE: self.interface.OpenWebWindow(url) Ajouter : if app.ENABLE_TICKET_SYSTEM: def ManagerTickets(self, cmd): cmd = cmd.split('#') if cmd[0] == 'QID': constInfo.Tickets['QID'] = int(cmd[1]) elif cmd[0] == 'INPUT': constInfo.INPUT_IGNORE = int(cmd[1]) elif cmd[0] == 'SEND': net.SendQuestInputLongStringPacket(str(constInfo.Tickets['QCMD'])) constInfo.Tickets['QCMD'] = '' elif cmd[0] == 'CLEAR_CONTENT': constInfo.Tickets['MY_TICKETS'] = [] constInfo.Tickets['GLOBAL_TICKETS'] = [] elif cmd[0] == 'CLEAR_PERMISIONS': constInfo.Tickets['PERMISIONS'] = [] elif cmd[0] == 'SET_TICKET': date = cmd[4].split('[_]') constInfo.Tickets['GLOBAL_TICKETS'].append([cmd[1], cmd[2].replace('[_]', ' '), int(cmd[3]), date[0], date[1], int(cmd[5]), cmd[6], cmd[7].replace('[_]', ' '), int(cmd[8])]) if cmd[6] == player.GetName(): constInfo.Tickets['MY_TICKETS'].append([cmd[1], cmd[2].replace('[_]', ' '), int(cmd[3]), date[0], date[1], int(cmd[5]), cmd[6], cmd[7].replace('[_]', ' '), int(cmd[8])]) elif cmd[0] == 'CREATE_ANSWER': constInfo.Tickets['ANSWERS'][cmd[1]] = [] elif cmd[0] == 'SET_ANSWER': date = cmd[3].split('[_]') constInfo.Tickets['ANSWERS'][cmd[1]].append([cmd[2], date[0], date[1], cmd[4].replace('[_]', ' ')]) elif cmd[0] == 'SET_PERMISION': constInfo.Tickets['PERMISIONS'].append([cmd[1], int(cmd[2]), int(cmd[3]), int(cmd[4])]) elif cmd[0] == 'OPEN': self.interface.wndTicket.Open(int(cmd[1])) elif cmd[0] == 'REFRESH_CONTENT': self.interface.wndTicket.RefreshPage() Dans le fichier ui.py : Ajouter la class : if app.ENABLE_TICKET_SYSTEM: class CoolButton(Window): BACKGROUND_COLOR = grp.GenerateColor(0.0, 0.0, 0.0, 1.0) DARK_COLOR = grp.GenerateColor(0.4, 0.4, 0.4, 1.0) WHITE_COLOR = grp.GenerateColor(1.0, 1.0, 1.0, 0.3) HALF_WHITE_COLOR = grp.GenerateColor(1.0, 1.0, 1.0, 0.2) def __init__(self, layer = "UI"): Window.__init__(self, layer) self.eventFunc = None self.eventArgs = None self.ButtonText = None self.ToolTipText = None self.EdgeColor = None self.isOver = FALSE self.isSelected = FALSE self.width = 0 self.height = 0 def __del__(self): Window.__del__(self) self.eventFunc = None self.eventArgs = None def SetSize(self, width, height): Window.SetSize(self, width, height) self.width = width self.height = height def SetEvent(self, func, *args): self.eventFunc = func self.eventArgs = args def SetTextColor(self, color): if not self.ButtonText: return self.ButtonText.SetPackedFontColor(color) def SetEdgeColor(self, color): self.EdgeColor = color def SetText(self, text): if not self.ButtonText: textLine = TextLine() textLine.SetParent(self) textLine.SetPosition(self.GetWidth()/2, self.GetHeight()/2) textLine.SetVerticalAlignCenter() textLine.SetHorizontalAlignCenter() textLine.SetOutline() textLine.Show() self.ButtonText = textLine self.ButtonText.SetText(text) def SetToolTipText(self, text, x=0, y = -19): if not self.ToolTipText: toolTip=createToolTipWindowDict["TEXT"]() toolTip.SetParent(self) toolTip.SetSize(0, 0) toolTip.SetHorizontalAlignCenter() toolTip.SetOutline() toolTip.Hide() toolTip.SetPosition(x + self.GetWidth()/2, y) self.ToolTipText=toolTip self.ToolTipText.SetText(text) def ShowToolTip(self): if self.ToolTipText: self.ToolTipText.Show() def HideToolTip(self): if self.ToolTipText: self.ToolTipText.Hide() def SetTextPosition(self, width): self.ButtonText.SetPosition(width, self.GetHeight()/2) self.ButtonText.SetHorizontalAlignLeft() def Enable(self): wndMgr.Enable(self.hWnd) def Disable(self): wndMgr.Disable(self.hWnd) def OnMouseLeftButtonDown(self): self.isSelected = TRUE def OnMouseLeftButtonUp(self): self.isSelected = FALSE if self.eventFunc: apply(self.eventFunc, self.eventArgs) def OnUpdate(self): if self.IsIn(): self.isOver = TRUE self.ShowToolTip() else: self.isOver = FALSE self.HideToolTip() def OnRender(self): xRender, yRender = self.GetGlobalPosition() widthRender = self.width heightRender = self.height grp.SetColor(self.BACKGROUND_COLOR) grp.RenderBar(xRender, yRender, widthRender, heightRender) if self.EdgeColor: grp.SetColor(self.EdgeColor) else: grp.SetColor(self.DARK_COLOR) grp.RenderLine(xRender, yRender, widthRender, 0) grp.RenderLine(xRender, yRender, 0, heightRender) grp.RenderLine(xRender, yRender+heightRender, widthRender, 0) grp.RenderLine(xRender+widthRender, yRender, 0, heightRender) if self.isOver: grp.SetColor(self.HALF_WHITE_COLOR) grp.RenderBar(xRender + 2, yRender + 2, self.width - 3, heightRender - 3) if self.isSelected: grp.SetColor(self.WHITE_COLOR) grp.RenderBar(xRender + 2, yRender + 2, self.width - 3, heightRender - 3) Chercher (EditLine): self.eventKillFocus = None Ajouter : if app.ENABLE_TICKET_SYSTEM: self.CanClick = None Chercher : def SetTabEvent(self, event): self.eventTab = event Ajouter : if app.ENABLE_TICKET_SYSTEM: def CanEdit(self, flag): self.CanClick = flag Chercher : def OnMouseLeftButtonDown(self): En dessous de : if FALSE == self.IsIn(): return FALSE Ajouter : if app.ENABLE_TICKET_SYSTEM: if FALSE == self.CanClick: return Déplacer ensuite les fichiers fournis dans l'archive PACK.rar où il faut, et voilà ! C'est terminé. Vous pouvez maintenant ouvrir la fenêtre en utilisant la fonction : if app.ENABLE_TICKET_SYSTEM: def OpenTicketWindow(self): import event constInfo.Tickets['QCMD'] = 'OPEN#' event.QuestButtonClick(constInfo.Tickets['QID']) return Rendu (je vous renvoie sur la chaine de l'auteur) : A ploush ! TÉLÉCHARGE MOI EN CLIQUANT ICI
  5. Plop, Je vous partage l'item shop in game de shang dans sa dernière version v1.3.1 fonctionne parfaitement avec quelques petites retouches sur les files FE 2016 Dl : ICI FE Pour les problèmes et les bugs c'est dans l'A/Q/S Source : Shang
  6. Bonjour à toutes et à tous ! Voilà un nouveau tuto mais cette fois sur une board qui s'affiche en jeu en utilisant par exemple la touche "F6" de votre clavier puis vous verrez apparaître cette fameuse fenêtre vous tout ce que la personne ayant accès au FTP a à dire aux joueurs. La particularité ? ce n'est qu'un fichier texte à modifier sur le FTP et la modification se fait en jeu sans le moindre reboot du serveur ni la moindre ferme/réouverture du client, il suffit de fermer/ouvrir la board et c'est bon ! Je tiens à préciser que ce partage ne fonctionne pas avec le "Hack detector" . Let's go ! Commencez par dépack votre root ainsi que "etc" Téléchargez ça: [Hidden Content] Allez dans votre dépacker puis ouvrez votre game.py. Allez à la fin du fichier, pour ma part je l'ai collé entre la kill-gui et cette ligne: def __ProcessPreservedServerCommand(self): (je vous conseille de faire une recherche de cette ligne et de coller ce qui suit juste au dessus): collez ceci: def __newsboard(self): import epvpgui try: if constInfo.epvpgui != 1: exec 'epvpgui.EpvpGuiDialog().Show()' else: chat.AppendChat(chat.CHAT_TYPE_INFO, " Ist bereits offnen") except ImportError: import dbg,app dbg.Trace('epvpgui.py Importing error :(') app.Abort() Cherchez maintenant cette ligne: onPressKeyDict[app.DIK_F4] = lambda : self.__PressQuickSlot(7) Puis collez ceci en dessous: onPressKeyDict[app.DIK_F6] = lambda : self.__newsboard() Note: Remplacez "F6" par "F5" par exemple si vous souhaitez que le raccourcis pour ouvrir la board soit F5 et non F6 /!\Attention à ne pas prendre un raccourcis déjà existant, une liste d'autres raccourcis non utilisés est dispo en bas du topic/!\ Maintenant allez dans "constinfo.py" puis en dessous de la ligne "PVPMODE_PROTECTED_LEVEL = 30" ou tout dépend si vous avez déjà rajouté quelque chose ou non, ajoutez cette ligne: epvpgui = 0 Maintenant, mettez le fichier "epvpgui.py" avec les autres fichiers de votre root, chemin d'accès: Metin2 Repacker\depack Allez dans ymir work>>ui puis mettez y l'interface sous le nom "weirdwar.tga" Chemin d'accès: Metin2 Repacker\depack\ymir work\ui Allons maintenant sur le FTP ! Allez dans usr, puis www, placez-y ce fichier: [Hidden Content] Bien sûr, vous pouvez modifier le texte comme vous le souhaitez ! /!\Pour éviter un message d'erreur il y a en tout 9 lignes dispo, si vous voulez écrire par exemple 5 lignes écrivez ces 5 lignes puis sur les 4 dernières du fichier "tryhard.txt" mettez des espaces " "/!\ Il y a également une alternative à ce problème en bas du topic. Maintenant, votre serveur sait ce qu'il doit écrire dans la board, il ne reste plus qu'à dire à la board où trouver ce fichier ! Retournez dans votre root puis ouvrez le fichier "epvpgui.py" Vous verrez alors cette ligne: news_url = '[Hidden Content]' #Eure Url ihr dumpfbacken C'est donc l'endroit où la board télécharge le texte. Modifiez "[Hidden Content]" par l'endroit où est le fichier texte sur votre ftp, par exemple pour moi ça devient: news_url = '[Hidden Content]' #Eure Url ihr dumpfbacken Pour connaître le lien de votre serveur, cherchez le lien de téléchargement de votre client qui est normalement upload sur "www" puis remplacez la fin de l'adresse par "tryhard.txt" Exemple, le lien: [Hidden Content] Devient: [Hidden Content] Lorsque vous avez fait tout ça, vous pouvez repack votre root et etc. /!\N'oubliez pas d'ajouter les nouveau fichiers à votre root et a etc/!\ En cas de besoin voilà la ligne à placer dans etc_repack: depack\ymir work\ui\weirdwar.tga Puis dans root_repack: depack\epvpgui.py Allez en jeu, appuyez sur la touche que vous avez mis en raccourcis et admirez ! vous devriez avoir à peu près ceci: (je dois avouer que j'ai la flemme de remettre l'ancienne interface juste pour cette screen puisque j'utilise celle en haut de ce topic !) Maintenant, à vous de la modifier ! si vous avez besoin d'aide ou de conseille vous pouvez me demander (soit dit en passant, je suis vraiment nul en python, je ne peux pas faire de miracles !) Votre interface ne s'ouvre pas ? C'est simple, le problème est juste que vos lib ne sont pas à jour pour gérer cette GUI, voilà un lien de téléchargement: [Hidden Content] Placez les fichiers présent dans le dossier "lib" de ce que vous venez de télécharger vers le dossier "lib" dans votre client. Peut-être que vous ne verrez aucun fichier se rajouter parmi la liste déjà présente (c'est le cas pour moi) mais les changements ont bien été fait ! lancez à nouveau votre client et admirez ! Note: J'ai cru remarquer que si on ne remplissait pas toutes les cases de la board, un message d'erreur s'affiche à chaque ouverture de cette board, vous conseille donc de modifier le texte de l'erreur en quelque chose qui fait moins peur aux joueurs, allez dans le fichier "epvpgui.py" puis modifier les deux lignes qui se trouvent en dessous de " except IndexError:" Les raccourcis dispo Il y a beaucoup de touches non utilisées ! voilà les raccourcis non utilisés pour les client qui n'ont pas touché aux raccourcis: onPressKeyDict[app.DIK_P] = lambda : self.__newsboard() (Sur la touche P) onPressKeyDict[app.DIK_Y] = lambda : self.__newsboard() (Sur la touche Y) onPressKeyDict[app.DIK_U] = lambda : self.__newsboard() (Sur la touche U) onPressKeyDict[app.DIK_O] = lambda : self.__newsboard() (Sur la touche O) onPressKeyDict[app.DIK_K] = lambda : self.__newsboard() (plus besoin de préciser le touche, je penses que vous avez compris) onPressKeyDict[app.DIK_M] = lambda : self.__newsboard() onPressKeyDict[app.DIK_X] = lambda : self.__newsboard() Je peux encore continuer, il y en a d'autres mais je ne penses pas que ça serve à grand chose, il y a largement le choix. Pour remplacer le raccourcis, allez à la ligne: onPressKeyDict[app.DIK_F6] = lambda : self.__newsboard() Puis remplacez soit toute la ligne par la ligne de votre choix juste au dessus, soit vous remplacez "F6" par la lettre de votre choix /!\Ecrivez cette lettre en majuscule/!\ Fix de l'erreur dans le fichier .txt par .CrøKø 1.Allez dans le fichier game.py puis Modifiez ceci: def __newsboard(self): import epvpgui try: if constInfo.epvpgui != 1: exec 'epvpgui.EpvpGuiDialog().Show()' else: chat.AppendChat(chat.CHAT_TYPE_INFO, " Ist bereits offnen") except ImportError: import dbg,app dbg.Trace('epvpgui.py Importing error :(') app.Abort() Par ceci: def __newsboard(self): import epvpgui if constInfo.epvpgui != 1: exec 'epvpgui.EpvpGuiDialog().Show()' else: chat.AppendChat(chat.CHAT_TYPE_INFO, " est déjà ouvert" Allez ensuite dans le fichier epvpgui.py puis à la fin du fichier supprimez ces lignes: except IndexError: dbg.LogBox("ShuzZzles Error Blocking executed!!!!") chat.AppendChat(chat.CHAT_TYPE_INFO, ": (IndexError) List is out of range!") Ce qui devrait vous donner ceci: import ui import chat import app import player import snd import game import item import dbg import net import constInfo import urllib ######################################### # Author: ShuzZzle # # Idee: [sA]Horny # # Babo: .Analyze # # Hackfresse: .Panasonic # ######################################### class EpvpGuiDialog(ui.ScriptWindow): UI = [] Fields_slot = [] def __init__(self): ui.ScriptWindow.__init__(self) self.LoadUI() constInfo.epvpgui = 1 def __del__(self): ui.ScriptWindow.__del__(self) self.Board.Hide() constInfo.epvpgui = 0 def LoadUI(self): news_url = 'votre adresse' #Eure Url ihr dumpfbacken auslese = urllib.urlopen(news_url) btext = auslese.readlines() ###Haupt-Board### self.Board = ui.BoardWithTitleBar() self.Board.SetSize(700, 350) self.Board.SetCenterPosition() self.Board.AddFlag("movable") self.Board.AddFlag("float") self.Board.SetTitleName("Info Board :)") self.Board.SetCloseEvent(self.__del__) self.Board.Show() Button1 = ui.Button() Button1.SetParent(self.Board) Button1.SetUpVisual("d:/ymir work/ui/public/large_button_01.sub") Button1.SetOverVisual("d:/ymir work/ui/public/large_button_02.sub") Button1.SetDownVisual("d:/ymir work/ui/public/large_button_03.sub") Button1.SetText("Fermer!") Button1.SetEvent(self.__buttonfunc) Button1.SetPosition(350, 50) Button1.Show() self.UI.append(Button1) Bild = ui.AniImageBox() Bild.SetParent(self.Board) Bild.AppendImage("d:/ymir work/ui/Omega.tga") # Bild Pfad Bild.SetPosition(100, 200) Bild.Show() self.UI.append(Bild) Bild_war = ui.AniImageBox() Bild_war.SetParent(self.Board) Bild_war.AppendImage("d:/ymir work/ui/background test.jpg") # Pfad des Bildes Bild_war.SetPosition(5, 30) Bild_war.Show() self.UI.append(Bild_war) y = 40 for i in xrange(9): Slot1 = ui.SlotBar() Slot1.SetParent(self.Board) Slot1.SetSize(400, 25) Slot1.SetPosition(20, y) Slot1.Show() y += 25 self.Fields_slot.append(Slot1) try: y = 40 for i in xrange(9): Update1 = ui.TextLine() Update1.SetParent(self.Board) Update1.SetDefaultFontName() Update1.SetFontName("Arial:18") Update1.SetText(btext[i]) Update1.SetPosition(20, y) y += 25 Update1.SetFontColor(0.42, 0.54, 0.25) Update1.Show() self.UI.append(Update1) def __buttonfunc(self): self.Board.Hide() constInfo.epvpgui = 0 Pour les personnes n'y arrivant pas ou ayant la flemme de modifier manuellement le fichier epvpgui.py, vous pouvez avoir le fichier modifié par .CrøKø en cliquant ici. Enregistrez puis repackez votre root, vous ne devriez plus avoir de problème. Je n'ai pas testé cette solution. Merci à .CrøKø pour cette solution ! Pour les personnes voulant voir à quoi ça ressemble en jeu mais en vidéo, allez sur cette vidéo à 3m59: N'oublions pas ceci ! Voilà que ce tuto est fini ! j'espère que ça vous aura aidé, maintenant vous n'avez plus qu'à changer le texte dans le fichier "tryhard.txt" sur votre FTP, l'enregistrer puis le reupload et lorsque vous ouvrirait à nouveau votre board, le texte aura changé sans reboot ni même la fermeture de votre client ! Bon jeu à tous et bonne chance Sources: Board par ShuzZzle sur epvp. Lib par RealFreak sur epvp. Fix du message d'erreur par .CrøKø. Tuto entièrement par moi.
  7. Niveau requis : Débutant Temps estimé : Entre 10 et 15 minutes Réécriture by Xayah Bonjour, voici un système qui vous permettra d'équiper des stuffs pré-enregistrés dans une fenêtre ! Pré-requis: Cette archive : Téléchargement ou FE Votre client Eternexus I. Tutoriel II. Placer les fichiers Succès ! Vous pouvez désormais profiter pleinement de ce système, Enjoy ! A savoir : Si vous ne savez pas comment utiliser Eternexus, je vous invite à bien lire ce tutoriel : Depack & Repack avec Eternexus Si vous avez un problème, n'hésitez pas à rédiger un sujet dans la section A/Q/S
  8. Skill Sage Grand Maître. 1) Qu'est ce que cela? 2) Les Prérequis. 3) Le téléchargement. 1) Qu'est ce que cela? Alors, les skill Sage Grand Maître sont des skills au-dessus de P ( Oui vous l'avez compris, vous pourrez up vos skills plus de P) Les skills s'upent de la même manière que pour up en P (de G1 à P ) Ils s'up de P1 à S Pour up vos skills vous aurez besoin de lire des Sage Pierre d'âme (Oh non pas encore des PA !!!!!!!!!!!!!!!!) Vidéos Une vidéo est toujours explicite que quelques mots sur une page blanche. 2) Les Prérequis. Des Files et un client Sources Client/Game/Db De l'archive en téléchargement et votre tête. Sachez encore une fois que ce partage n'est pas de moi et provient de Board Legend, ce système à été créé par Lennt. La traduction est cependant de moi. (Si quelqu'un pourrais traduire le skilldesc.txt je suis preneur.) 3) Le téléchargement. Cliquez ici FE Cordialement, History.
  9. Salut à tous, J'ai eu plusieurs requête par rapport à mes systèmes dont celui qui permet de cacher n'importe quel gr2 à cause des lags. J'ai appris que celui-ci avait fuité, donc j'ai décidé de faire une nouvelle version. C'est la raison pour la qu'elle je viens vous partager celle-ci. Pour ceux qui me l'ont acheté directement, veuillez me contacter en MP, je vous ferai une v2. Elle inclura le hide des étoles & costumes. Quelques informations avant tout : AFFECT_INVISIBILITY est bugé de base (essayez de vous inv avec un logo GM, une fois réapparu vous ne le verrez plus) J'avais trouvé un fix par hasard sur metin2dev il y a quelques mois, je vous le partagerais dans les commentaires si je le retrouve. Ce système est dynamique et le code est léger. Il possède également des define côté C++ mais j'ai pas pensé à le faire côté python. Merci de ne pas vendre ce système. Le tutoriel se trouve dans le .rar Une petite vidéo concernant le fonctionnement : Lien de téléchargement : Cliquez-ici ! FE
  10. Bonjour ! Je vien aujourd'hui vous partager un système d'effet qui vous permettra d'ajouter des effets à n'importe quel armures ou costumes par un fichier .py Téléchargement : ICIV2 - FEV1 - FEV2 Source : Freakgamer Edit : Ajout du code pour les effets sur les costumes dans le fichier InstanceBase.cpp Si vous avez des soucis avec ce système, je vous demande de poster votre problèmes dans la section Aide / Questions / Support.
  11. Hellow, Je vous partage un petit "systeme ?" pour choisir le skin de son magasin ==> ICI FE Le tuto est dans le dossier , petit screen de ce petit système a l'ouverture d'un magasin : source : turkmmo feat. iRyZz ^_-
  12. Bonjour la communauté! Après avoir été sur Epvp j'ai trouvé un joli système en python. Je vous glisse une aperçu. Pour commencer ouvrez: game.py Recherchez: import ime Ajoutez en dessous: import uisidebar Recherchez: self.__ServerCommand_Build() self.__ProcessPreservedServerCommand() Passer une ligne et ajoutez: self.sideBar = uisidebar.SideBar() self.sideBar.Show() Recherchez: self.KillFocus() app.HideCursor() Passer une ligne et ajoutez: self.sideBar.Destroy() self.sideBar = None Téléchargez-ici FE Bonne journée!
  13. Bonjour, Je vous partage un petit tutoriel rédigé par mes soins afin d'installer le système de bonus dans l'inventaire sur les files 2014 (et 2016 by FE). PS : Sur l'image le système est en espagnol mais dans ce tutoriel le système est traduit en français par Eristoff. Point positif : Système fonctionnel une fois adapté. Point négatif : Le bouton "Minimiser" ne fonctionne plus (Ce qui n'est pas très grave). Edit : Le bouton fonctionne ! Voir plus bas dans le tutoriel. Dans un premier temps vous devez vous munir d'un éditeur de texte et de vos fichiers "root" et "local_fr". Dans root : Trouvez et ouvrez le fichier "uiinventory.py" Trouvez ce bout de code : ## Refresh self.SetInventoryPage(0) self.SetEquipmentPage(0) self.RefreshItemSlot() self.RefreshStatus() Le remplacer par : ## Refresh self.SetInventoryPage(0) self.SetEquipmentPage(0) self.RefreshItemSlot() self.RefreshStatus() self.ActualizarBonus() def MinimizarBonus(self): if self.ESTADO_PAGINA_INVENTORY == False: #####Esta parte pertence en volver al estado original al inventory self.GetChild("board").SetSize(176,585) self.GetChild("TitleBar").SetWidth(161) self.GetChild("TitleName").SetPosition(77, 3) self.GetChild("OcultarTabla").SetPosition(161 - 30, 10) self.SetSize(176, 585) self.SetPosition(wndMgr.GetScreenWidth() - 176, wndMgr.GetScreenHeight() - 37 - 585) self.GetChild("Money_Slot").SetPosition(8, 28) #Tabla self.GetChild("txt_info_defenza").Hide() self.ESTADO_PAGINA_INVENTORY = True else: #####Esta parte pertence en volver al estado editado al inventory self.GetChild("board").SetSize(306,585) self.GetChild("TitleBar").SetWidth(161 + 130) self.GetChild("TitleName").SetPosition((161 + 130) / 2, 3) self.GetChild("OcultarTabla").SetPosition(161 + 130 - 30, 10) self.SetSize(306, 585) self.SetPosition(wndMgr.GetScreenWidth() - 176 - 130, wndMgr.GetScreenHeight() - 37 - 585) self.GetChild("Money_Slot").SetPosition(-55, 28) #Tabla self.GetChild("txt_info_defenza").Show() self.ESTADO_PAGINA_INVENTORY = False self.OcultarInfoTable(self.ESTADO_PAGINA_INVENTORY) if self.wndBelt: self.wndBelt.AdjustPositionAndSize() def OcultarInfoTable(self, arg): if arg == True: self.GetChild("txt_info_defenza").Hide() self.GetChild("txt_info_defenza_espada").Hide() self.GetChild("Thin_info_defenza_espada").Hide() self.GetChild("txt_info_defenza_2manos").Hide() self.GetChild("Thin_info_defenza_2manos").Hide() self.GetChild("txt_info_defenza_daga").Hide() self.GetChild("Thin_info_defenza_daga").Hide() self.GetChild("txt_info_defenza_Felcha").Hide() self.GetChild("Thin_info_defenza_Felcha").Hide() self.GetChild("txt_info_defenza_campana").Hide() self.GetChild("Thin_info_defenza_campana").Hide() self.GetChild("txt_info_defenza_fan").Hide() self.GetChild("Thin_info_defenza_fan").Hide() self.GetChild("txt_info_resist_Magia").Hide() self.GetChild("Thin_info_resist_Magia").Hide() self.GetChild("txt_info_resist_veneno").Hide() self.GetChild("Thin_info_resist_veneno").Hide() self.GetChild("txt_info_resist_guerrero").Hide() self.GetChild("Thin_info_resist_guerrero").Hide() self.GetChild("txt_info_resist_ninja").Hide() self.GetChild("Thin_info_resist_ninja").Hide() self.GetChild("txt_info_resist_sura").Hide() self.GetChild("Thin_info_resist_sura").Hide() self.GetChild("txt_info_resist_chaman").Hide() self.GetChild("Thin_info_resist_chaman_").Hide() self.GetChild("txt_info_onfensivo").Hide() self.GetChild("txt_info_criticos").Hide() self.GetChild("Thin_info_criticos").Hide() self.GetChild("txt_info_penetracion").Hide() self.GetChild("Thin_info_penetracion").Hide() self.GetChild("txt_info_danomedia").Hide() self.GetChild("Thin_info_danomedia").Hide() self.GetChild("txt_info_danohabilidad").Hide() self.GetChild("Thin_info_danohabilidad").Hide() self.GetChild("txt_info_fmediohumano").Hide() self.GetChild("Thin_info_fmediohumano").Hide() self.GetChild("txt_info_fnomuerto").Hide() self.GetChild("Thin_info_fnomuerto").Hide() self.GetChild("txt_info_fdemonio").Hide() self.GetChild("Thin_info_fdemonio").Hide() self.GetChild("txt_info_fguerrero").Hide() self.GetChild("Thin_info_fguerrero").Hide() self.GetChild("txt_info_fninja").Hide() self.GetChild("Thin_info_fninja").Hide() self.GetChild("txt_info_fsura").Hide() self.GetChild("Thin_info_fsura").Hide() self.GetChild("txt_info_fcham").Hide() self.GetChild("Thin_info_fcham").Hide() else: self.GetChild("txt_info_defenza").Show() self.GetChild("txt_info_defenza_espada").Show() self.GetChild("Thin_info_defenza_espada").Show() self.GetChild("txt_info_defenza_2manos").Show() self.GetChild("Thin_info_defenza_2manos").Show() self.GetChild("txt_info_defenza_daga").Show() self.GetChild("Thin_info_defenza_daga").Show() self.GetChild("txt_info_defenza_Felcha").Show() self.GetChild("Thin_info_defenza_Felcha").Show() self.GetChild("txt_info_defenza_campana").Show() self.GetChild("Thin_info_defenza_campana").Show() self.GetChild("txt_info_defenza_fan").Show() self.GetChild("Thin_info_defenza_fan").Show() self.GetChild("txt_info_resist_Magia").Show() self.GetChild("Thin_info_resist_Magia").Show() self.GetChild("txt_info_resist_veneno").Show() self.GetChild("Thin_info_resist_veneno").Show() self.GetChild("txt_info_resist_guerrero").Show() self.GetChild("Thin_info_resist_guerrero").Show() self.GetChild("txt_info_resist_ninja").Show() self.GetChild("Thin_info_resist_ninja").Show() self.GetChild("txt_info_resist_sura").Show() self.GetChild("Thin_info_resist_sura").Show() self.GetChild("txt_info_resist_chaman").Show() self.GetChild("Thin_info_resist_chaman_").Show() self.GetChild("txt_info_onfensivo").Show() self.GetChild("txt_info_criticos").Show() self.GetChild("Thin_info_criticos").Show() self.GetChild("txt_info_penetracion").Show() self.GetChild("Thin_info_penetracion").Show() self.GetChild("txt_info_danomedia").Show() self.GetChild("Thin_info_danomedia").Show() self.GetChild("txt_info_danohabilidad").Show() self.GetChild("Thin_info_danohabilidad").Show() self.GetChild("txt_info_fmediohumano").Show() self.GetChild("Thin_info_fmediohumano").Show() self.GetChild("txt_info_fnomuerto").Show() self.GetChild("Thin_info_fnomuerto").Show() self.GetChild("txt_info_fdemonio").Show() self.GetChild("Thin_info_fdemonio").Show() self.GetChild("txt_info_fguerrero").Show() self.GetChild("Thin_info_fguerrero").Show() self.GetChild("txt_info_fninja").Show() self.GetChild("Thin_info_fninja").Show() self.GetChild("txt_info_fsura").Show() self.GetChild("Thin_info_fsura").Show() self.GetChild("txt_info_fcham").Show() self.GetChild("Thin_info_fcham").Show() def ActualizarBonus(self): self.GetChild("bonus_1").SetText(str(player.GetStatus(69))) self.GetChild("bonus_2").SetText(str(player.GetStatus(70))) self.GetChild("bonus_3").SetText(str(player.GetStatus(71))) self.GetChild("bonus_4").SetText(str(player.GetStatus(74))) self.GetChild("bonus_5").SetText(str(player.GetStatus(72))) self.GetChild("bonus_6").SetText(str(player.GetStatus(73))) self.GetChild("bonus_7").SetText(str(player.GetStatus(77))) self.GetChild("bonus_8").SetText(str(player.GetStatus(81))) self.GetChild("bonus_9").SetText(str(player.GetStatus(59))) self.GetChild("bonus_10").SetText(str(player.GetStatus(60))) self.GetChild("bonus_11").SetText(str(player.GetStatus(61))) self.GetChild("bonus_12").SetText(str(player.GetStatus(62))) self.GetChild("bonus_13").SetText(str(player.GetStatus(40))) self.GetChild("bonus_14").SetText(str(player.GetStatus(41))) self.GetChild("bonus_15").SetText(str(player.GetStatus(122))) self.GetChild("bonus_16").SetText(str(player.GetStatus(121))) self.GetChild("bonus_17").SetText(str(player.GetStatus(43))) self.GetChild("bonus_18").SetText(str(player.GetStatus(47))) self.GetChild("bonus_19").SetText(str(player.GetStatus(48))) self.GetChild("bonus_20").SetText(str(player.GetStatus(54))) self.GetChild("bonus_21").SetText(str(player.GetStatus(55))) self.GetChild("bonus_22").SetText(str(player.GetStatus(56))) self.GetChild("bonus_23").SetText(str(player.GetStatus(57))) En suite rendez vous tout tout à la fin et ajoutez : def OnUpdate(self): self.ActualizarBonus() Pour faire fonctionner le bouton "Minimiser" il faut (toujours dans le même fichier) trouver : wndItem = self.GetChild("ItemSlot") wndEquip = self.GetChild("EquipmentSlot") Et ajouter juste en dessous : self.ButonMinimize = self.GetChild2("OcultarTabla") self.ButonMinimize.SetEvent(ui.__mem_func__(self.MinimizarBonus)) Dans locale_fr : Trouvez et ouvrez le fichier "inventorywindow.py" Sélectionnez tout le début jusqu'à la ligne : (Arrêtez votre sélection juste avant cette ligne) ## Equipment Slot Et remplacez par : import uiScriptLocale import item EQUIPMENT_START_INDEX = 180 SPACE_BONUS_INVENTORY = 130 IMAGE_CHELO = "d:/ymir work/ui/public/Parameter_Slot_01.sub" window = { "name" : "InventoryWindow", ## 600 - (width + 오른쪽으로 부터 띄우기 24 px) "x" : SCREEN_WIDTH - 176 - SPACE_BONUS_INVENTORY, "y" : SCREEN_HEIGHT - 37 - 585, "style" : ("movable", "float",), "width" : 176 + SPACE_BONUS_INVENTORY, "height" : 585, "children" : ( ## Inventory, Equipment Slots { "name" : "board", "type" : "board", "style" : ("attach",), "x" : 0, "y" : 0, "width" : 176 + SPACE_BONUS_INVENTORY, "height" : 585, "children" : ( ## Title { "name" : "TitleBar", "type" : "titlebar", "style" : ("attach",), "x" : 8, "y" : 7, "width" : 161 + SPACE_BONUS_INVENTORY, "color" : "yellow", "children" : ( { "name":"TitleName", "type":"text", "x": (161 + SPACE_BONUS_INVENTORY) / 2, "y":3, "text":uiScriptLocale.INVENTORY_TITLE, "text_horizontal_align":"center" }, ), }, ##Ocultar table de bonus { "name" : "OcultarTabla", "type" : "button", "x" : 161 + SPACE_BONUS_INVENTORY - 30, "y" : 10, "default_image" : "d:/ymir work/ui/public/minimize_button_01.sub", "over_image" : "d:/ymir work/ui/public/minimize_button_02.sub", "down_image" : "d:/ymir work/ui/public/minimize_button_03.sub", "tooltip_text" : "Bonus", }, ################################################### ################################################### ################################################### #############Tabla de Bonus @Chelo############ #Bonus de Defenza.......................... { "name" : "txt_info_defenza", "type" : "horizontalbar", "x" : 176 - 7, "y" : 33, "width" : 125, "children" : ( { "name" : "bonus_text_1", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "Defensif", }, ), }, ######################################## { "name" : "txt_info_defenza_espada", "type" : "text", "x" : 176 - 5, "y" : 55, "text" : "Epee:" }, { "name" : "Thin_info_defenza_espada", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 55 - 2, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_1", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_defenza_2manos", "type" : "text", "x" : 176 - 5, "y" : 75, "text" : "Lance:" }, { "name" : "Thin_info_defenza_2manos", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 - 2, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_2", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_defenza_daga", "type" : "text", "x" : 176 - 5, "y" : 75 + 20, "text" : "Dague:" }, { "name" : "Thin_info_defenza_daga", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_3", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_defenza_Felcha", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20, "text" : "Fleche:" }, { "name" : "Thin_info_defenza_Felcha", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_4", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_defenza_campana", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20, "text" : "Gong:" }, { "name" : "Thin_info_defenza_campana", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_5", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_defenza_fan", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20, "text" : "Eventail:" }, { "name" : "Thin_info_defenza_fan", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_6", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_resist_Magia", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20, "text" : "Magie:" }, { "name" : "Thin_info_resist_Magia", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_7", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## ######################################## { "name" : "txt_info_resist_veneno", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Poison:" }, { "name" : "Thin_info_resist_veneno", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_8", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_resist_guerrero", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Guerrier:" }, { "name" : "Thin_info_resist_guerrero", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_9", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_resist_ninja", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Ninja:" }, { "name" : "Thin_info_resist_ninja", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_10", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_resist_sura", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Sura:" }, { "name" : "Thin_info_resist_sura", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_11", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ######################################## { "name" : "txt_info_resist_chaman", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Shaman:" }, { "name" : "Thin_info_resist_chaman_", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_12", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### #Bonus de onfensivo.......................... { "name" : "txt_info_onfensivo", "type" : "horizontalbar", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "width" : 125, "children" : ( { "name" : "bonus_text_2", "type" : "text", "x" : 0, "y" : 0, "all_align" : "center", "text" : "Offensif", }, ), }, ######################################## { "name" : "txt_info_criticos", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Critique:" }, { "name" : "Thin_info_criticos", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_13", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_penetracion", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Percant:" }, { "name" : "Thin_info_penetracion", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_14", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_danomedia", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Degats moyen:" }, { "name" : "Thin_info_danomedia", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_15", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_danohabilidad", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Degats comp.:" }, { "name" : "Thin_info_danohabilidad", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_16", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fmediohumano", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Demi humains:" }, { "name" : "Thin_info_fmediohumano", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_17", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fnomuerto", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Mort vivant:" }, { "name" : "Thin_info_fnomuerto", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_18", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fdemonio", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Mal:" }, { "name" : "Thin_info_fdemonio", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_19", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fguerrero", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Guerrier:" }, { "name" : "Thin_info_fguerrero", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_20", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fninja", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Ninja:" }, { "name" : "Thin_info_fninja", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_21", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fsura", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Sura:" }, { "name" : "Thin_info_fsura", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_22", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### { "name" : "txt_info_fcham", "type" : "text", "x" : 176 - 5, "y" : 75 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "text" : "Shaman:" }, { "name" : "Thin_info_fcham", "type" : "image", "x" : 176 + SPACE_BONUS_INVENTORY - 65, "y" : 75 + 20 - 2 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20 + 20, "image" : IMAGE_CHELO, "children" : ( { "name" : "bonus_23", "type" : "text", "x" : 26, "y" : 3, "text" : "999", "r" : 1.0, "g" : 1.0, "b" : 1.0, "a" : 1.0, "text_horizontal_align":"center" }, ), }, ################################################### Et le tour est joué Petite astuce dans Notepad++ si en copiant/collant il vous remplace les tabulations par des espaces : Placez votre curseur là ou devraient être les tabulations, appuyez sur la touche de tabulation et appuyez sur la touche précédent. En faisant cette manip Notepad++ remplacera les espaces par le nombre de tabulation qu'il faut. Ce tutoriel est à présent terminé. Merci d'avoir lu en espérant en aider certains. Source : FreakGamers, et un peu moi ^^
  14. Salut à tous, aujourd'hui, je vais vous faire un petit tutoriel sur comment implanter le BonusPage, alors commençons d'abord, téléchargez le fichier suivant : ICI FE Ouvrez votre game.py Cherchez la ligne import chat Ajoutez en dessous import uibonuspage Cherchez la ligne onPressKeyDict[app.DIK_F4] = lambda : self.__PressQuickSlot(7) Ajoutez en dessous onPressKeyDict[app.DIK_U] = lambda : self.__BonusPage() Allez à la fin de votre game.py et ajoutez # Page de bonus def __showbonus(self): import uiBonusPage global bonuspp try: if bonuspp != 1: exec 'uiBonusPage.BonusBoardDialog().Show()' else: pass except ImportError: import dbg,app dbg.Trace('uiBonusPage.py Importing error') app.Abort() def __BonusPage(self): import uibonuspage self.wndBonus = uibonuspage.BonusBoardDialog() self.wndBonus.Show() Enregistrez votre game.py, fermez le et ouvrez ui.py Cherchez la ligne def SetOverVisual(self, filename): wndMgr.SetOverVisual(self.hWnd, filename) Ajoutez en dessous en sautant une ligne # Page de bonus def GetText(self): if not self.ButtonText: return return self.ButtonText.GetText() Voilà, le tutoriel est fini, le BonusPage apparaîtra quand vous appuierez sur la touche U Le BonusPage est totalement traduit en français, il n'y aura donc pas besoin de le traduire Sources : J'ai copié ce système sur le client de Metin2 World Bonne journée !
  15. Bonjour à tous, je partage donc aujourd'hui le système de costume weapon. Je tiens à signialer que celui si bug au niveau des arc et des dagues, en effet, le personnage porte l'arc du mauvais coter, et la dague une seul partie est apparente l'autre c'est la dague normal. Je vous met tout de même deux screen vous montrant les bug Le liens de téléchargement : ICI FE
  16. Plop, je vous partage un système que j'ai trouvé avec l'aide de Franch Chaque grade comporte un grade IMPLEMENTOR = GA HIGH_WIZARD = SGM GOD = GM LOW_WIZARD = MOD Il faudra modifier la partie Source serveur ( tutoriel dans le fichier rar ) Il faudra modifier la partie source client ( tutoriel dans le fichier rar ) Il faudra modifier la partie root.eix Il faudra modifier la partie locale_fr.eix Toute les informations ce trouve dans le fichiers rar, Le partage vient du forum turkmmo l'auteur c'est Suky Voici les screens qui vont avec : Virus Total : ICI Download : ICI FE Mirroir : Yeni Yetkili Tagları.rar J’espère que sa pourra vous intéressé
  17. Carquois de flèche. 1) Qu'est-ce que c'est? 2) Les prérequis. 3) Les téléchargements. 1) Qu'est-ce que c'est? Il existe 4 type de carquois qui ont chacun un temps différent. Durée de 24 Heures. Durée de 7 Jours. Durée de 15 Jours. Durée de 30 Jours. Une carquois c'est un stock de flèche illimité sauf en temps comme indiqué ci-dessus, Les dégâts infligés ne sont pas réduit par la distances. 2) Les prérequis. Sources Client / Server. Un Client. Files. Les fichiers en téléchargement. Votre tête qui encore une fois vous sera utile. 3) Les téléchargements. Cliquez ici FE Sources : Board-Legend LeNn't. Traduction : Moi. Bonne installation. Cordialement, History.
  18. Shop Hors-Ligne. 1) Qu'est-ce que c'est? 2) Les prérequis. 3) Le téléchargement. 1) Qu'est-ce que c'est? Les shop hors-ligne sont des shop ou sont propriétaire est soit déconnecter ou soit en train de jouer les shops sont séparer de sont propriétaire! Finit de ce déshabiller pour ce mettre en shop! Maintenant vous être libre de jouer tout en ayant un shop ouvert! 2) Les prérequis. Sources Client/Serveur. Un Client. Des files. Les fichiers en téléchargement. Votre tête qui est encore une fois utile. 3) Le téléchargement. Cliquez ici FE Autres fonctions: Support multi-prix. Montre l'emplacement de l'item vendu. Possibilité d'ouvrir jusqu'à 2 shop par joueurs. Source: BoardLegend/Koray. Traduction: Moi. ( Temps de traduction environ 2 à 3h.) Cordialement, History.
  19. Bon nombre d'entre nous sont fatigué sur metin. Alors pourquoi pas faire une pause? 1) Comment ? Qu'est ce que c'est ? 2) Les pré requis. 3) Les fichiers. 1) Comment ? Qu'est ce que c'est ? Depuis peu, j'ai remarqué que beaucoup de joueurs étaient fatigué après avoir exp etc ... Alors je me suis dit pourquoi pas installer cela qui pourrais vraiment être sympa ! Vous-vous dites mais il est fous, il va nous mettre des système de malade et tout ! Et bien oui, je suis fous °-°. Comme vous l'avez vu sur le screen et bien on peux désormais s'asseoir sur metin. Ce système vous permet de vous asseoir le temps d'une pause. Utilisation: /stand /sit Bon repos les amis 2) Les prérequis. Sources Client Sources game/db Des Files Un Client Être en Granny 2.9 3) Les fichiers. Cliquez ici :) Lien mis à jours le 15/01/2018 Nouvelles Animation Sitting FE (contient les 2) #Ajout 25/11/17: Nouvelles animations pour s’asseoir avec en bonus une animation pour ce lever ! Ces animations sont pour toutes classes et viennent de Ymir. Edit: Merci à Keito pour avoir implanté le système et avoir refait tout les screens de l'archive. (Screens présent dans l'archive directement.) Sources: Board Legend Traduction par moi même. Cordialement, History.
  20. Bonjour à tous. J'ai remarqué grâce à un screen de l'officiel posté par @ASIKOO sur le Discord que l'officiel avait implanté de nouvelles potions lors de la nouvelle mise à jour 18.0. Ces potions sont des Potions Bleues et Rouges de taille XXL qui restaurent respectivement 2400 PV et 800 PM. Donc après un peu de fouille dans le client de l'officiel ainsi qu'à une extraction de protos et à une rapide création de query, voici les potions XXL. Le pack contient la partie client & serveur ainsi que la partie base de donnée. Cependant, vous devrez packer vous même votre "item_proto". Vidéo de présentation : Rapide tutoriel d'implantation : Dépackez votre pack "icon" et glissez y le dossier "icon" présent dans "ymir work/icon" de ce pack. Il faut que Windows vous demande si vous souhaitez fusionner les dossiers. Faites oui et repackez icon. Rendez-vous côté serveur, ouvrez votre "item_names.txt" et votre "item_proto.txt " et rajoutez le contenu des fichiers"item_names.txt" et "item_proto.txt" présent dans le dossier "files_db" du pack. Dépackez "locale_fr", ouvrez le fichier "locale" présent dans ce pack et rajoutez le contenu du fichier "item_list.txt" dans le fichier "item_list.txt" du pack "locale_fr" que vous venez de dépacker. La même manipulation est requise pour le fichier "itemdesc.txt". Une fois ceci fait, packez les protos serveur avec les potions rajoutées. Placez le nouvel "item_proto" dans votre pack "locale". Vous pouvez repacker "locale_fr" une fois ces trois fichiers à jour. Ouvrez Navicat, ouvrez la base de donnée "player", puis copiez le contenu de "shop_item.sql" présent dans le dossier "sql_db_player" du pack. Puis, dans Navicat, appuyez sur F6 en ayant la base de donnée "player" sélectionnée et collez le contenu du fichier "shop_item.sql" précédement copié. Appuyez sur votre touche "Entrée" pour valider la query. Une fois les étapes-ci dessus effectuées, lancez votre serveur. Les potions seront disponibles à l'achat à la marchande. Lien du pack : ICI FE (Futures ?) Mises à jours : La version actuelle est la version 0.1, elle contient les potions identiques à l'officiel (22/04/2018) ainsi que leur présence à la Marchande. Je mettrai le pack à jour si l'officiel fait une mise à jour (je pense notamment au modèle 3D lorsque dropées au sol qui n'existe pas pour ces potions (vous pouvez utiliser celui des autres potions, l'officiel n'en n'utilise pas)). Je peux aussi mettre ce pack à jour si quelqu'un me fait part de plus d'info : Est-ce que ces potions se droppent et si oui, où, à partir de quel level etc. Le pack sera à jour au fil des informations que vous me donnerez. Libre à vous de vous même effectuer ces modifications et de les partager (ou pas, selon vous) ici. PS : Selon le patchnote, la Potion Rouge (XL) existe, cependant je n'ai pas regardé les shops, mais il me semble que cette dernière n'est pas répertoriée. Si jamais vous avez des infos, n'hésitez pas ! Bonne implantation et journée
  21. Bonjour à tous , j'ai décidé de partagé et d'expliquer comment implanter les systèmes que j'ai sur mon DD. (Tous fonctionnel) Aujourd'hui , ce sera un système qui vous permet de voir ce que drop le mob que vous pointez. !!!!! ATTENTION AUX TABULATIONS!!!!! 1) Pré-requis: -Source Server/Client -Un client On va commencer par les sources Serveur: Ouvre le fichier service.h qui ce trouve dans le dossier common : Ajouter: #define __SEND_TARGET_INFO__ Maintenant aller dans game/src puis ouvrez le fichier char.h: Cherchez: ////////////////////////////////////////////////////////////////////////////////// // Basic Points Ajoutez en dessous : #ifdef __SEND_TARGET_INFO__ private: DWORD dwLastTargetInfoPulse; public: DWORD GetLastTargetInfoPulse() const { return dwLastTargetInfoPulse; } void SetLastTargetInfoPulse(DWORD pulse) { dwLastTargetInfoPulse = pulse; } #endif Ouvrez le dossier char.cpp: Cherchez: #include "DragonSoul.h" Puis ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ #include #include using namespace std; #endif Cherchez: m_dwKillerPID = 0; Puis ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ dwLastTargetInfoPulse = 0; #endif Maintenant , ouvrez le fichier input.h Cherchez: void Roulette(LPCHARACTER ch, const char* c_pData); Ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ void TargetInfoLoad(LPCHARACTER ch, const char* c_pData); #endif Ouvrez le dossier input_main.cpp: Cherchez: static int __deposit_limit() { return (1000*10000); // 1õ¸¸ } Ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ void CInputMain::TargetInfoLoad(LPCHARACTER ch, const char* c_pData) { TPacketCGTargetInfoLoad* p = (TPacketCGTargetInfoLoad*)c_pData; TPacketGCTargetInfo pInfo; pInfo.header = HEADER_GC_TARGET_INFO; static std::vector s_vec_item; s_vec_item.clear(); LPITEM pkInfoItem; LPCHARACTER m_pkChrTarget = CHARACTER_MANAGER::instance().Find(p->dwVID); // if (m_pkChrTarget && (m_pkChrTarget->IsMonster() || m_pkChrTarget->IsStone())) // { // if (thecore_heart->pulse - (int) ch->GetLastTargetInfoPulse() < passes_per_sec * 3) // return; // ch->SetLastTargetInfoPulse(thecore_heart->pulse); if (ITEM_MANAGER::instance().CreateDropItemVector(m_pkChrTarget, ch, s_vec_item) && (m_pkChrTarget->IsMonster() || m_pkChrTarget->IsStone())) { if (s_vec_item.size() == 0); else if (s_vec_item.size() == 1) { pkInfoItem = s_vec_item[0]; pInfo.dwVID = m_pkChrTarget->GetVID(); pInfo.race = m_pkChrTarget->GetRaceNum(); pInfo.dwVnum = pkInfoItem->GetVnum(); pInfo.count = pkInfoItem->GetCount(); ch->GetDesc()->Packet(&pInfo, sizeof(TPacketGCTargetInfo)); } else { int iItemIdx = s_vec_item.size() - 1; while (iItemIdx >= 0) { pkInfoItem = s_vec_item[iItemIdx--]; if (!pkInfoItem) { sys_err("pkInfoItem null in vector idx %d", iItemIdx + 1); continue; } pInfo.dwVID = m_pkChrTarget->GetVID(); pInfo.race = m_pkChrTarget->GetRaceNum(); pInfo.dwVnum = pkInfoItem->GetVnum(); pInfo.count = pkInfoItem->GetCount(); ch->GetDesc()->Packet(&pInfo, sizeof(TPacketGCTargetInfo)); } } } // } } #endif Cherchez: case HEADER_CG_XTRAP_ACK: { TPacketXTrapCSVerify* p = reinterpret_cast((void*)c_pData); CXTrapManager::instance().Verify_CSStep3(d->GetCharacter(), p->bPacketData); } break; Mettez en dessous : #ifdef __SEND_TARGET_INFO__ case HEADER_CG_TARGET_INFO_LOAD: { TargetInfoLoad(ch, c_pData); } break; #endif Ouvre le fichier item_manager.cpp: Cherchez: bool ITEM_MANAGER::GetDropPct(LPCHARACTER pkChr, LPCHARACTER pkKiller, OUT int& iDeltaPercent, OUT int& iRandRange) Ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ bool ITEM_MANAGER::CreateDropItemVector(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector & vec_item) { if (pkChr->IsPolymorphed() || pkChr->IsPC()) { return false; } int iLevel = pkKiller->GetLevel(); BYTE bRank = pkChr->GetMobRank(); LPITEM item = NULL; std::vector::iterator it = g_vec_pkCommonDropItem[bRank].begin(); while (it != g_vec_pkCommonDropItem[bRank].end()) { const CItemDropInfo & c_rInfo = *(it++); if (iLevel < c_rInfo.m_iLevelStart || iLevel > c_rInfo.m_iLevelEnd) continue; TItemTable * table = GetTable(c_rInfo.m_dwVnum); if (!table) continue; item = NULL; if (table->bType == ITEM_POLYMORPH) { if (c_rInfo.m_dwVnum == pkChr->GetPolymorphItemVnum()) { item = CreateItem(c_rInfo.m_dwVnum, 1, 0, true); if (item) item->SetSocket(0, pkChr->GetRaceNum()); } } else item = CreateItem(c_rInfo.m_dwVnum, 1, 0, true); if (item) vec_item.push_back(item); } // Drop Item Group { itertype(m_map_pkDropItemGroup) it; it = m_map_pkDropItemGroup.find(pkChr->GetRaceNum()); if (it != m_map_pkDropItemGroup.end()) { typeof(it->second->GetVector()) v = it->second->GetVector(); for (DWORD i = 0; i < v.size(); ++i) { item = CreateItem(v[i].dwVnum, v[i].iCount, 0, true); if (item) { if (item->GetType() == ITEM_POLYMORPH) { if (item->GetVnum() == pkChr->GetPolymorphItemVnum()) { item->SetSocket(0, pkChr->GetRaceNum()); } } vec_item.push_back(item); } } } } // MobDropItem Group { itertype(m_map_pkMobItemGroup) it; it = m_map_pkMobItemGroup.find(pkChr->GetRaceNum()); if ( it != m_map_pkMobItemGroup.end() ) { CMobItemGroup* pGroup = it->second; // MOB_DROP_ITEM_BUG_FIX // 20050805.myevan.MobDropItem ? ???? ?? ?? CMobItemGroup::GetOne() ??? ?? ?? ?? if (pGroup && !pGroup->IsEmpty()) { const CMobItemGroup::SMobItemGroupInfo& info = pGroup->GetOne(); item = CreateItem(info.dwItemVnum, info.iCount, 0, true, info.iRarePct); if (item) vec_item.push_back(item); } // END_OF_MOB_DROP_ITEM_BUG_FIX } } // Level Item Group { itertype(m_map_pkLevelItemGroup) it; it = m_map_pkLevelItemGroup.find(pkChr->GetRaceNum()); if ( it != m_map_pkLevelItemGroup.end() ) { if ( it->second->GetLevelLimit() <= (DWORD)iLevel ) { typeof(it->second->GetVector()) v = it->second->GetVector(); for ( DWORD i=0; i < v.size(); i++ ) { DWORD dwVnum = v[i].dwVNum; item = CreateItem(dwVnum, v[i].iCount, 0, true); if ( item ) vec_item.push_back(item); } } } } // BuyerTheitGloves Item Group { // by mhh ?? ??? ??? ?? drop ? ???? ?? if (pkKiller->GetPremiumRemainSeconds(PREMIUM_ITEM) > 0 || pkKiller->IsEquipUniqueGroup(UNIQUE_GROUP_DOUBLE_ITEM)) { itertype(m_map_pkGloveItemGroup) it; it = m_map_pkGloveItemGroup.find(pkChr->GetRaceNum()); if (it != m_map_pkGloveItemGroup.end()) { typeof(it->second->GetVector()) v = it->second->GetVector(); for (DWORD i = 0; i < v.size(); ++i) { DWORD dwVnum = v[i].dwVnum; item = CreateItem(dwVnum, v[i].iCount, 0, true); if (item) vec_item.push_back(item); } } } } // ?? if (pkChr->GetMobDropItemVnum()) { itertype(m_map_dwEtcItemDropProb) it = m_map_dwEtcItemDropProb.find(pkChr->GetMobDropItemVnum()); if (it != m_map_dwEtcItemDropProb.end()) { item = CreateItem(pkChr->GetMobDropItemVnum(), 1, 0, true); if (item) vec_item.push_back(item); } } if (pkChr->IsStone()) { if (pkChr->GetDropMetinStoneVnum()) { item = CreateItem(pkChr->GetDropMetinStoneVnum(), 1, 0, true); if (item) vec_item.push_back(item); } } return vec_item.size(); } #endif Ouvrez le fichier item_manager.h Cherchez: bool CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector & vec_item); Ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ bool CreateDropItemVector(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector & vec_item); #endif Ouvrez le fichier packet.h Cherchez: HEADER_GC_TARGET = 63, Mettez en dessous: #ifdef __SEND_TARGET_INFO__ HEADER_GC_TARGET_INFO = 58, HEADER_CG_TARGET_INFO_LOAD = 59, #endif Cherchez: typedef struct packet_target Ajoutez apres la fonction: #ifdef __SEND_TARGET_INFO__ typedef struct packet_target_info { BYTE header; DWORD dwVID; DWORD race; DWORD dwVnum; BYTE count; } TPacketGCTargetInfo; typedef struct packet_target_info_load { BYTE header; DWORD dwVID; } TPacketCGTargetInfoLoad; #endif Ouvre le fichiez packet_info.cpp Cherchez: Set(HEADER_CG_STATE_CHECKER, sizeof(BYTE), "ServerStateCheck", false); Ajoutez en dessous: #ifdef __SEND_TARGET_INFO__ Set(HEADER_CG_TARGET_INFO_LOAD, sizeof(TPacketCGTargetInfoLoad), "TargetInfoLoad", true); #endif Voilà on en a fini avec la partie "Source Server" , maintenant attaquons la partie "Source client": Aller dans le dossier UserInterface: Cherchez le fichier Locale_inc.h Ajoutez: #define ENABLE_SEND_TARGET_INFO Ouvrez le fichier Packet.h Cherchez: HEADER_GC_TARGET = 63, Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO HEADER_GC_TARGET_INFO = 58, HEADER_CG_TARGET_INFO_LOAD = 59, #endif Cherchez: typedef struct packet_target Ajoutez après la fonction: #ifdef ENABLE_SEND_TARGET_INFO typedef struct packet_target_info { BYTE header; DWORD dwVID; DWORD race; DWORD dwVnum; BYTE count; } TPacketGCTargetInfo; typedef struct packet_target_info_load { BYTE header; DWORD dwVID; } TPacketCGTargetInfoLoad; #endif Ouvrez le fichier PythonApplicationModule.cpp Cherchez: #ifdef ENABLE_COSTUME_SYSTEM Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO PyModule_AddIntConstant(poModule, "ENABLE_SEND_TARGET_INFO", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_SEND_TARGET_INFO", 0); #endif Ouvrez le fichier PythonNetworkStream.cpp Cherchez: Set(HEADER_GC_TARGET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCTarget), STATIC_SIZE_PACKET)); Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO Set(HEADER_GC_TARGET_INFO, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCTargetInfo), STATIC_SIZE_PACKET)); #endif Ouvrez le fichier PythonNetworkStream.h Cherchez: bool RecvDamageInfoPacket(); Inserez en dessous : #ifdef ENABLE_SEND_TARGET_INFO bool RecvTargetInfoPacket(); public: bool SendTargetInfoLoadPacket(DWORD dwVID); protected: #endif Ouvre le fichier PythonNetworkStreamModule.cpp Cherchez: PyObject* netConnectToAccountServer(PyObject* poSelf, PyObject* poArgs) Ajoutez après la fonction : #ifdef ENABLE_SEND_TARGET_INFO PyObject* netTargetInfoLoad(PyObject* poSelf, PyObject* poArgs) { DWORD dwVID; if (!PyArg_ParseTuple(poArgs, "i", &dwVID)) { return Py_BuildException(); } if (dwVID < 0) { return Py_BuildNone(); } CPythonNetworkStream& rns = CPythonNetworkStream::Instance(); rns.SendTargetInfoLoadPacket(dwVID); return Py_BuildNone(); } #endif Cherchez: { "ConnectToAccountServer", netConnectToAccountServer, METH_VARARGS }, Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO { "SendTargetInfoLoad", netTargetInfoLoad, METH_VARARGS }, #endif Ouvrez le fichier PythonNetworkStreamPhaseGame.cpp Cherchez: case HEADER_GC_TARGET: Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO case HEADER_GC_TARGET_INFO: ret = RecvTargetInfoPacket(); break; #endif Cherchez : bool CPythonNetworkStream::RecvTargetPacket() Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO bool CPythonNetworkStream::RecvTargetInfoPacket() { TPacketGCTargetInfo pInfoTargetPacket; if (!Recv(sizeof(TPacketGCTargetInfo), &pInfoTargetPacket)) { Tracen("Recv Info Target Packet Error"); return false; } CInstanceBase * pInstPlayer = CPythonCharacterManager::Instance().GetMainInstancePtr(); CInstanceBase * pInstTarget = CPythonCharacterManager::Instance().GetInstancePtr(pInfoTargetPacket.dwVID); if (pInstPlayer && pInstTarget) { if (!pInstTarget->IsDead()) { if (pInstTarget->IsEnemy() || pInstTarget->IsStone()) { PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_AddTargetMonsterDropInfo", Py_BuildValue("(iii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count)); PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_RefreshTargetMonsterDropInfo", Py_BuildValue("(i)", pInfoTargetPacket.race)); } else PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "CloseTargetBoard", Py_BuildValue("()")); // m_pInstTarget = pInstTarget; } } else { PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "CloseTargetBoard", Py_BuildValue("()")); } return true; } #endif Cherchez : bool CPythonNetworkStream::RecvObserverAddPacket() Ajoutez après la fonction: #ifdef ENABLE_SEND_TARGET_INFO bool CPythonNetworkStream::SendTargetInfoLoadPacket(DWORD dwVID) { TPacketCGTargetInfoLoad TargetInfoLoadPacket; TargetInfoLoadPacket.header = HEADER_CG_TARGET_INFO_LOAD; TargetInfoLoadPacket.dwVID = dwVID; if (!Send(sizeof(TargetInfoLoadPacket), &TargetInfoLoadPacket)) return false; return SendSequence(); } #endif Ouvrez le fichier PythonNonPlayer.cpp Cherchez: void CPythonNonPlayer::GetMatchableMobList(int iLevel, int iInterval, TMobTableList * pMobTableList) Ajoutez après la fonction: #ifdef ENABLE_SEND_TARGET_INFO DWORD CPythonNonPlayer::GetMonsterMaxHP(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD dwMaxHP = 0; return dwMaxHP; } return c_pTable->dwMaxHP; } DWORD CPythonNonPlayer::GetMonsterRaceFlag(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD dwRaceFlag = 0; return dwRaceFlag; } return c_pTable->dwRaceFlag; } DWORD CPythonNonPlayer::GetMonsterLevel(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD level = 0; return level; } return c_pTable->bLevel; } DWORD CPythonNonPlayer::GetMonsterDamage1(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD range = 0; return range; } return c_pTable->dwDamageRange[0]; } DWORD CPythonNonPlayer::GetMonsterDamage2(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD range = 0; return range; } return c_pTable->dwDamageRange[1]; } DWORD CPythonNonPlayer::GetMonsterExp(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD dwExp = 0; return dwExp; } return c_pTable->dwExp; } float CPythonNonPlayer::GetMonsterDamageMultiply(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD fDamMultiply = 0; return fDamMultiply; } return c_pTable->fDamMultiply; } DWORD CPythonNonPlayer::GetMonsterST(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD bStr = 0; return bStr; } return c_pTable->bStr; } DWORD CPythonNonPlayer::GetMonsterDX(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD bDex = 0; return bDex; } return c_pTable->bDex; } bool CPythonNonPlayer::IsMonsterStone(DWORD dwVnum) { const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); if (!c_pTable) { DWORD bType = 0; return bType; } return c_pTable->bType == 2; } #endif Ouvrez le fichier PythonNonPlayer.h Cherchez: const char* GetMonsterName(DWORD dwVnum); Ajoutez en dessous : #ifdef ENABLE_SEND_TARGET_INFO // TARGET_INFO DWORD GetMonsterMaxHP(DWORD dwVnum); DWORD GetMonsterRaceFlag(DWORD dwVnum); DWORD GetMonsterLevel(DWORD dwVnum); DWORD GetMonsterDamage1(DWORD dwVnum); DWORD GetMonsterDamage2(DWORD dwVnum); DWORD GetMonsterExp(DWORD dwVnum); float GetMonsterDamageMultiply(DWORD dwVnum); DWORD GetMonsterST(DWORD dwVnum); DWORD GetMonsterDX(DWORD dwVnum); bool IsMonsterStone(DWORD dwVnum); #endif Enfin , ouvrez le fichier PythonNonPlayerModule.cpp Cherchez: PyObject * nonplayerLoadNonPlayerData(PyObject * poSelf, PyObject * poArgs) Ajoutez après la fonction: #ifdef ENABLE_SEND_TARGET_INFO PyObject * nonplayerGetMonsterMaxHP(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.GetMonsterMaxHP(race)); } PyObject * nonplayerGetRaceNumByVID(PyObject * poSelf, PyObject * poArgs) { int iVirtualID; if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID)) return Py_BuildException(); CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(iVirtualID); if (!pInstance) return Py_BuildValue("i", -1); const CPythonNonPlayer::TMobTable * pMobTable = CPythonNonPlayer::Instance().GetTable(pInstance->GetVirtualNumber()); if (!pMobTable) return Py_BuildValue("i", -1); return Py_BuildValue("i", pMobTable->dwVnum); } PyObject * nonplayerGetMonsterRaceFlag(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.GetMonsterRaceFlag(race)); } PyObject * nonplayerGetMonsterLevel(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.GetMonsterLevel(race)); } PyObject * nonplayerGetMonsterDamage(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); DWORD dmg1 = rkNonPlayer.GetMonsterDamage1(race); DWORD dmg2 = rkNonPlayer.GetMonsterDamage2(race); return Py_BuildValue("ii", dmg1,dmg2); } PyObject * nonplayerGetMonsterExp(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.GetMonsterExp(race)); } PyObject * nonplayerGetMonsterDamageMultiply(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("f", rkNonPlayer.GetMonsterDamageMultiply(race)); } PyObject * nonplayerGetMonsterST(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.GetMonsterST(race)); } PyObject * nonplayerGetMonsterDX(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.GetMonsterDX(race)); } PyObject * nonplayerIsMonsterStone(PyObject * poSelf, PyObject * poArgs) { int race; if (!PyTuple_GetInteger(poArgs, 0, &race)) return Py_BuildException(); CPythonNonPlayer& rkNonPlayer = CPythonNonPlayer::Instance(); return Py_BuildValue("i", rkNonPlayer.IsMonsterStone(race) ? 1 : 0); } #endif Cherchez: { "GetMonsterName", nonplayerGetMonsterName, METH_VARARGS }, Ajoutez en dessous: #ifdef ENABLE_SEND_TARGET_INFO // TARGET_INFO { "GetRaceNumByVID", nonplayerGetRaceNumByVID, METH_VARARGS }, { "GetMonsterMaxHP", nonplayerGetMonsterMaxHP, METH_VARARGS }, { "GetMonsterRaceFlag", nonplayerGetMonsterRaceFlag, METH_VARARGS }, { "GetMonsterLevel", nonplayerGetMonsterLevel, METH_VARARGS }, { "GetMonsterDamage", nonplayerGetMonsterDamage, METH_VARARGS }, { "GetMonsterExp", nonplayerGetMonsterExp, METH_VARARGS }, { "GetMonsterDamageMultiply", nonplayerGetMonsterDamageMultiply, METH_VARARGS }, { "GetMonsterST", nonplayerGetMonsterST, METH_VARARGS }, { "GetMonsterDX", nonplayerGetMonsterDX, METH_VARARGS }, { "IsMonsterStone", nonplayerIsMonsterStone, METH_VARARGS }, #endif Voilà , nous avons enfin terminez la partie Source , pour le coté Client , vous devez depacker locale et root , les choses à modifier sont dans l'archive à télécharger : [Hidden Content] EDIT: Screen: Source: FreaksGamers
  22. Bonjour à toutes et à tous ! J'ai fais quelques recherches sur ce forum mais je n'ai rien trouvé à ce sujet donc je vais vous expliquer comment mettre en place une GUI (Graphical User Interface) montrant les statistiques sans passer par une quête. Bien sûr, il y a possibilité de désactiver ou réactiver l'affichage de cette interface à tout moment à l'aide d'une petite quête. Bref, au travail ! Pour commencer vous aurez besoin de dépack le fichier "root" afin d'avoir accès au fichier "game.py" puis ouvrez le. Petite précision: le copier-coller c'est pas terrible vu que le python n'aime pas les espaces. Donc si vous avez des problèmes à la fin du tuto, remplacez les espaces par des tabulations. /!\La quête est nécessaire pour afficher l'interface/!\ Cherchez la ligne: self.SetSize(wndMgr.GetScreenWidth(), wndMgr.GetScreenHeight()) Puis faites un copier/coller de ceci: #START_KILLGUI KillGuiBg = ui.AniImageBox() KillGuiBg.AppendImage("d:/ymir work/ui/blue_killgui_interface.tga") self.KillGuiBg = KillGuiBg self.KillGuiBg.SetPosition(wndMgr.GetScreenWidth()-235,185) self.KillBlauReich = ui.TextLine() self.KillBlauReich.SetDefaultFontName() self.KillBlauReich.SetPosition((wndMgr.GetScreenWidth()-285)+120, 412) self.KillBlauReich.SetText("Royaume bleu: NaN") self.KillBlauReich.SetOutline() self.KillGelbReich = ui.TextLine() self.KillGelbReich.SetDefaultFontName() self.KillGelbReich.SetPosition((wndMgr.GetScreenWidth()-289)+120, 332) self.KillGelbReich.SetText("Royaume jaune: NaN") self.KillGelbReich.SetOutline() self.KillRotReich = ui.TextLine() self.KillRotReich.SetDefaultFontName() self.KillRotReich.SetPosition((wndMgr.GetScreenWidth()-289)+120, 255) self.KillRotReich.SetText("Royaume Rouge: NaN") self.KillRotReich.SetOutline() self.KillMob = ui.TextLine() self.KillMob.SetDefaultFontName() self.KillMob.SetPosition((wndMgr.GetScreenWidth()-268)+120, 490) self.KillMob.SetText("Monstre: NaN") self.KillMob.SetOutline() ##END_KILLGUI Cherchez maintenant la ligne: serverCommandList={ Puis faites un copier/coller de ceci: ##KILLGUI "ShowKillGui" : self.__showkillgui, "HideKillGui" : self.__hidekillgui, "KillBlauReich" : self.__KillBlauReich, "KillGelbReich" : self.__KillGelbReich, "KillRotReich" : self.__KillRotReich, "KillMob" : self.__KillMob, ##END_KILLGUI Maintenant, allez à la fin de votre fichier game.py, personnellement je l'ai mis au dessus de cette ligne: def __ProcessPreservedServerCommand(self): Lorsque vous avez repéré cette ligne, faites un copier/coller de ceci: def __hidekillgui(self): self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() def __showkillgui(self): self.KillGuiBg.Show() self.KillBlauReich.Show() self.KillGelbReich.Show() self.KillRotReich.Show() self.KillMob.Show() def __KillBlauReich(self, KillBlauReich): self.KillBlauReich.SetText("Royaume bleu " + KillBlauReich) def __KillGelbReich(self, KillGelbReich): self.KillGelbReich.SetText("Royaume jaune " + KillGelbReich) def __KillRotReich(self, KillRotReich): self.KillRotReich.SetText("Royaume rouge " + KillRotReich) def __KillMob(self, KillMob): self.KillMob.SetText("Monstre " + KillMob) Repackez votre fichier root. Vous devez maintenant extraire "etc" pour avoir accès à votre dossier "ui" Téléchargez ce fichier: [Hidden Content] Placez le dans le dossier "ui" d:/ymir work/ui/blue_killgui_interface.tga Ouvrez le fichier "etc_repack.xml" et ajoutez cette ligne: depack\ymir work\ui\blue_killgui_interface.tga Sauvegardez et repackez "etc" Le côté client est terminé ! maintenant il faut implanter la quête permettant de cacher ou afficher l'interface. Allez dans le dossier "quest" via winscp ou filezilla. Créez un fichier nommé: kill_gui.quest Puis ajoutez la quête au fichier: quest killgui begin state start begin when kill begin if npc.is_pc() then local new_point = pc.getqf("empire"..npc.get_empire())+1 pc.setqf("empire"..npc.get_empire(), new_point) cmdchat("KillRotReich "..pc.getqf("empire1")) cmdchat("KillGelbReich "..pc.getqf("empire2")) cmdchat("KillBlauReich "..pc.getqf("empire3")) else local new_point = pc.getqf("mob")+1 pc.setqf("mob", new_point) cmdchat("KillMob "..pc.getqf("mob")) end end when login begin if pc.getqf("showkillgui") == 1 then cmdchat("ShowKillGui") cmdchat("KillRotReich "..pc.getqf("empire1")) cmdchat("KillGelbReich "..pc.getqf("empire2")) cmdchat("KillBlauReich "..pc.getqf("empire3")) cmdchat("KillMob "..pc.getqf("mob")) else cmdchat("HideKillGui") end end when letter begin send_letter("Statistiques") end when info or button begin say_title("Statistiques") say("Voulez-vous désactiver l'affichage de vos") say("statistiques ?") say("Les personnes ou mobs tués seront tout de même") say("comptabilisés. Vous pourrez réactiver à tout moment") say("l'affichage des statistiques.") local janein = select("Afficher", "Cacher") if janein == 2 then pc.setqf("showkillgui", 0) cmdchat("HideKillGui") else pc.setqf("showkillgui", 1) cmdchat("ShowKillGui") cmdchat("KillRotReich "..pc.getqf("empire1")) cmdchat("KillGelbReich "..pc.getqf("empire2")) cmdchat("KillBlauReich "..pc.getqf("empire3")) cmdchat("KillMob "..pc.getqf("mob")) end end end end Ajoutez le fichier à filezilla ou winscp puis ouvrez le fichier: locale_list et ajoutez cette ligne: kill_gui.quest (N'oubliez pas de laisser une ligne vide en dessous de la dernière ligne ajoutée) Sauvegardez puis recompilez la quête. Dans la liste des quêtes vous verrez la quête "Statistiques" cliquez dessus puis activez l'affichage de la GUI, le tour est joué ! Petit plus ! Il y a en tout 5 interfaces (en comptant celle-ci) j'ai choisis de vous partager cette interface car je trouve que c'est la plus belle, mais après chacun ses goûts. Téléchargement: [Hidden Content] Téléchargement: [Hidden Content] Pour changer d'interface, renommez le fichier téléchargé en "blue_killgui_interface.tga" puis déplacez le ici en remplaçant l'ancienne interface si besoin est: d:/ymir work/ui/blue_killgui_interface.tga Changer l'emplacement de l'écriture Si vous changez d'interface, vous aurez sans doute besoin de régler la position du texte. Ouvrez le fichier "game.py" puis cherchez la ligne: self.SetSize(wndMgr.GetScreenWidth(), wndMgr.GetScreenHeight()) Vous verrez donc les coordonnées de chaque ligne: Si vous souhaitez changer le texte, c'est simple. Cherchez la ligne: def __hidekillgui(self): Laisser la GUI affichée après chaque téléportation: Merci à Spark pour la modification du python et de la quête ! Pour commencer, remplacez la quête implantée précédemment par celle-ci: quest killgui begin state start begin when kill begin if npc.is_pc() then local new_point = pc.getqf("empire"..npc.get_empire())+1 local tab = {"KillRotReich", "KillGelbReich", "KillBlauReich"} pc.setqf("empire"..npc.get_empire(), new_point) cmdchat(tab[npc.get_empire()].." "..new_point) else local new_point = pc.getqf("mob")+1 pc.setqf("mob", new_point) cmdchat("KillMob "..new_point) end end when login begin cmdchat("ShowKillGui") cmdchat("KillRotReich "..pc.getqf("empire1")) cmdchat("KillGelbReich "..pc.getqf("empire2")) cmdchat("KillBlauReich "..pc.getqf("empire3")) cmdchat("KillMob "..pc.getqf("mob")) end end end Allez dans vitre game.py puis remplacez: "ShowKillGui" : self.__showkillgui, Par: "ShowKillGui" : self.__showkillgui2, Remplacez ensuite: def __hidekillgui(self): self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() Par: def __showkillgui2(self): constInfo.killgui = 1 self.KillGuiBg.Show() self.KillBlauReich.Show() self.KillGelbReich.Show() self.KillRotReich.Show() self.KillMob.Show() Repackez votre root puis testez ! Merci à Spark ! Afficher/cacher l'interface à l'aide d'un raccourcis (F5)Passer par une quête à chaque fois pour afficher ou cacher l'interface peut être assez chiant, voilà la solution: un raccourcis sur la touche F5 ! Ouvrez le fichier game.py de votre root puis allez à la fin de votre fichier pour trouver ces lignes: Remplacez donc: def __hidekillgui(self): self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() def __showkillgui(self): self.KillGuiBg.Show() self.KillBlauReich.Show() self.KillGelbReich.Show() self.KillRotReich.Show() self.KillMob.Show() Par ceci: def __hidekillgui(self): self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() def __showkillgui(self): if constInfo.killgui == 0: constInfo.killgui = 1 self.KillGuiBg.Show() self.KillBlauReich.Show() self.KillGelbReich.Show() self.KillRotReich.Show() self.KillMob.Show() elif constInfo.killgui == 1: constInfo.killgui = 0 self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() Cherchez la ligne: onPressKeyDict[app.DIK_F4] = lambda : self.__PressQuickSlot(7) Puis ajoutez en dessous: onPressKeyDict[app.DIK_F5] = lambda : self.__showkillgui() (ne rien ajouter dans la parenthèse en fin de ligne) Sauvegardez puis quittez le fichier game.py. Toujours dans root ouvre le fichier "constinfo.py" Cherchez la ligne: PVPMODE_PROTECTED_LEVEL = 30 (la valeur à la fin de cette ligne peut changer) Puis en dessous ajoutez cette ligne: killgui = 0 Sauvegardez, repackez et en jeu, appuyez sur F5 ! Après ça on a toujours besoin de la quête, donc ne la supprimez pas ! Optimisé pour l'interface V4 (avec raccourcis) Je me suis intéressé à la version 4 de l'interface, voilà donc les emplacements que je trouve optimaux pour cet interface: /!\Vous devez avoir installé le raccourcis de la partie juste au dessus/!\ En dessous de la ligne: self.SetSize(wndMgr.GetScreenWidth(), wndMgr.GetScreenHeight()) Mettre ceci: ##START_KILLGUI KillGuiBg = ui.AniImageBox() KillGuiBg.AppendImage("d:/ymir work/ui/blue_killgui_interface.tga") self.KillGuiBg = KillGuiBg self.KillGuiBg.SetPosition(wndMgr.GetScreenWidth()-245,171) self.KillBlauReich = ui.TextLine() self.KillBlauReich.SetDefaultFontName() self.KillBlauReich.SetPosition((wndMgr.GetScreenWidth()-285)+120, 445) self.KillBlauReich.SetText("Royaume bleu: NaN") self.KillBlauReich.SetOutline() self.KillGelbReich = ui.TextLine() self.KillGelbReich.SetDefaultFontName() self.KillGelbReich.SetPosition((wndMgr.GetScreenWidth()-289)+120, 340) self.KillGelbReich.SetText("Royaume jaune: NaN") self.KillGelbReich.SetOutline() self.KillRotReich = ui.TextLine() self.KillRotReich.SetDefaultFontName() self.KillRotReich.SetPosition((wndMgr.GetScreenWidth()-289)+120, 231) self.KillRotReich.SetText("Royaume Rouge: NaN") self.KillRotReich.SetOutline() self.KillMob = ui.TextLine() self.KillMob.SetDefaultFontName() self.KillMob.SetPosition((wndMgr.GetScreenWidth()-268)+120, 557) self.KillMob.SetText("Monstre: NaN") self.KillMob.SetOutline() ##END_KILLGUI Puis au dessus de la ligne: def __ProcessPreservedServerCommand(self): Ceci: def __hidekillgui(self): self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() def __showkillgui(self): if constInfo.killgui == 0: constInfo.killgui = 1 self.KillGuiBg.Show() self.KillBlauReich.Show() self.KillGelbReich.Show() self.KillRotReich.Show() self.KillMob.Show() elif constInfo.killgui == 1: constInfo.killgui = 0 self.KillGuiBg.Hide() self.KillBlauReich.Hide() self.KillGelbReich.Hide() self.KillRotReich.Hide() self.KillMob.Hide() def __KillBlauReich(self, KillBlauReich): self.KillBlauReich.SetText(" " + KillBlauReich) def __KillGelbReich(self, KillGelbReich): self.KillGelbReich.SetText(" " + KillGelbReich) def __KillRotReich(self, KillRotReich): self.KillRotReich.SetText(" " + KillRotReich) def __KillMob(self, KillMob): self.KillMob.SetText(" " + KillMob) Repackez votre fichier root et c'est bon. Optimisé pour l'interface V5 (avec raccourcis) Par LordGune Nul besoin de faire tout un pitch pour expliquer comment mettre ce changement: #START_KILLGUI KillGuiBg = ui.AniImageBox() KillGuiBg.AppendImage("d:/ymir work/ui/blue_killgui_interface.tga") self.KillGuiBg = KillGuiBg self.KillGuiBg.SetPosition(wndMgr.GetScreenWidth()-235,185) self.KillBlauReich = ui.TextLine() self.KillBlauReich.SetDefaultFontName() self.KillBlauReich.SetPosition((wndMgr.GetScreenWidth()-207)+120, 458) self.KillBlauReich.SetText("Bleue Tuer: NaN") self.KillBlauReich.SetOutline() self.KillGelbReich = ui.TextLine() self.KillGelbReich.SetDefaultFontName() self.KillGelbReich.SetPosition((wndMgr.GetScreenWidth()-209)+120, 354) self.KillGelbReich.SetText("Jaune Tuer: NaN") self.KillGelbReich.SetOutline() self.KillRotReich = ui.TextLine() self.KillRotReich.SetDefaultFontName() self.KillRotReich.SetPosition((wndMgr.GetScreenWidth()-209)+120, 246) self.KillRotReich.SetText("Rouge Tuer: NaN") self.KillRotReich.SetOutline() self.KillMob = ui.TextLine() self.KillMob.SetDefaultFontName() self.KillMob.SetPosition((wndMgr.GetScreenWidth()-215)+120, 572) self.KillMob.SetText("Monstre: NaN") self.KillMob.SetOutline() ##END_KILLGUI Merci à LordGune pour avoir partagé cette version optimisée ! Sources: Tuto, screens, adaptation de l'interface/écriture, (petite) traduction de la quête entièrement par moi. Le reste est de ©ChaoSS sur epvp. L'option "raccourcis" provient de "ToBii™" sur epvp. GUI v5 par .ωєιя∂ sur epvp. J'espère ne rien avoir oublié. Bon jeu à tous et bonne chance ! Source : Craven LIEN DE DL GENERAL
  23. Les 7 et 8 ième skills. 1) Qu'est ce que c'est , comment ça fonctionne? 2) Les prérequis. 3) Les fichiers. 1) Qu'est ce que c'est , comment ça fonctionne? La 7ème compétence. La 7ième compétence offre un bonus de résistance contre une compétence choisie par le joueur parmi 9 compétences. Pour apprendre la 7ème compétence il vous faut un Livre de parade, un message s'ouvre alors pour choisir la compétences de parade. Listes des compétences : La 8ème compétence. La 8ème compétence offre un Bonus d'attaque à l'une de vos compétences, déterminée par votre classe. Pour apprendre ces compétences, deux conditions doivent-être réunies: La 7ième compétences doit être en Maître Parfait La compétences que vous voulez booster doit avoir au minimum 2 points de compétences dessus. Une fois les conditions réunies, il vous faut un Livre de bonus . Ce qui aura pour effet de débloquer la 8ième compétence. Voici les 9 compétences qui peuvent-être booster: Améliorations des compétences 7 et 8 L'amélioration de ces 2 compétences sont similaires à celle des compétences de classes. Elles comportent également 4 stades ( 1 / M / G / P ) Pour les améliorer vous devez: Soit Attribuer des points de compétences à cet compétence. Soit en réussissant la lecture ( Manuel Parade pour le parade ou Bonus pour le bonus ) 1 niveau augmenté pour un manuel utiliser. Niveau 0 à 19: La compétences passe niveau M1 Soit à 17 points soit 18 soit 19 soit 20. ( Les points sont différents de celle de vos personnages et ne dérange absolument en rien la progression de votre personnage.) La lecture d'un manuel de parade ou bonus Consomme toujours 20.000 points d'expérience et il faut attendre entre 18 et 30 heures entre 2 lectures. Niveau M1 à M10: Le système est le même que les compétences classes et il vous faut 55 Manuels pour la passer en G1. Niveau G1 à G10: Le système est le même que les compétences classes il vous faut réussir au total 10 Pierres d'âme ( Rose / Rouge ) Pour que la compétence passe au Stade P. Si le choix de l'une de vos 2 compétences ne vous conviens plus ou pas vous pouvez les réinitialiser via le Parchemin de modification d'entraînement. Sources des explications sur le système ( Wikipedia ) Screens ingame 2) Les prérequis. Pour les prérequis voici ce dont vous aurez besoin de: Sources client Sources DB Sources Game Un Client Des Files Pour le bon fonctionnement du système veuillez suivre le tutoriel (qui se trouve dans l'archive) à la lettre et faites attentions aux tabulations ! 3) Les fichiers. Cliquez ici FE Ces fichiers ne sont en aucun cas les miens , la traduction est de moi même ( Si toutes fois il as une erreur de traduction ou un manque merci de me l'indiquer je le corrigerai a la suite.) Cordialement, History.
  24. Ban ordinateur. 1) Qu'est-ce que c'est? 2) Les prérequis. 3) Le téléchargement. 1) Qu'est-ce que c'est? Je sais que bon nombre d'entre nous ont été embêté par des joueurs sans respect et qui en soit utilise un vpn pour contrer vos bans defs ! Et bien cet fois vous pouvez les bannir à partir de leurs ordinateur et non via l'ip ! Je sent déjà des joueurs qui vont me haïr, mais je vous aimes moi ! 2) Les prérequis. Des sources Client/Serveur. Un Client. Des Files. Une connexion Mysql. Votre tête. 3) Le téléchargement. Cliquez ici Coucou Calypso, je suis un lien FE Le partage n'est pas de moi ni même de la Team-Emu. Ce partage proviens de Koray. La traduction est de moi même. Bon bans à tout les joueurs qui vont pas aimer . Cordialement, History.