Jump to content

Mário.

Member
  • Content count

    77
  • Joined

  • Last visited

  • Days Won

    17

Mário. last won the day on April 10

Mário. had the most liked content!

Community Reputation

88 Neutral

3 Followers

About Mário.

  • Rank
    Member

Recent Profile Visitors

669 profile views
  1. Mário.

    Erro tables crachad Mysql

    Utilize uma das três: mob_proto.sql <- Estrutura oficial datada a 03/02/2018 | Não contêm nenhuma informação [5 kb] mob_proto_.sql <- Estrutura oficial datada a 03/02/2018 | Contém todo o mob_proto oficial [751 kb] mob_proto.txt <- Estrutura oficial em txt datada a 03/02/2018 [352 kb]
  2. Mário.

    File Index / Patchs .epk

    Procura por: PACK * Adiciona depois: metin2_patch_6th_armor pack/ metin2_patch_monster_card pack/ Em primeiro lugar é o nome do ficheiro seguidamente pelo diretório da pasta.
  3. Mário.

    System Team (Source)

    messenger_manager.cpp: void MessengerManager::Login(MessengerManager::keyA account) { if (m_set_loginAccount.find(account) != m_set_loginAccount.end()) return; DBManager::instance().FuncQuery(std::bind1st(std::mem_fun(&MessengerManager::LoadList), this), "SELECT account, companion FROM messenger_list%s WHERE account='%s'", get_table_postfix(), __account); #ifdef ENABLE_MESSENGER_TEAM DBManager::instance().FuncQuery(std::bind1st(std::mem_fun(&MessengerManager::LoadTeamList), this), "SELECT '%s' as account, mName as companion FROM common.gmlist", account.c_str()); #endif m_set_loginAccount.insert(account); } #ifdef ENABLE_MESSENGER_TEAM void MessengerManager::LoadTeamList(SQLMsg * msg) { if (NULL == msg or NULL == msg->Get() or msg->Get()->uiNumRows == 0) return; std::string account; for (uint i = 0; i < msg->Get()->uiNumRows; ++i) { MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult); if (row[0] && row[1]) { if (account.length() == 0) account = row[0]; m_TeamRelation[row[0]].insert(row[1]); m_InverseTeamRelation[row[1]].insert(row[0]); } } SendTeamList(account); std::set<MessengerManager::keyT>::iterator it; for (it = m_InverseTeamRelation[account].begin(); it != m_InverseTeamRelation[account].end(); ++it) SendTeamLogin(*it, account); } void MessengerManager::SendTeamList(MessengerManager::keyA account) { LPCHARACTER ch = CHARACTER_MANAGER::instance().FindPC(account.c_str()); if (!ch) return; LPDESC d = ch->GetDesc(); if (!d) return; TPacketGCMessenger pack; pack.header = HEADER_GC_MESSENGER; pack.subheader = MESSENGER_SUBHEADER_GC_TEAM_LIST; pack.size = sizeof(TPacketGCMessenger); TPacketGCMessengerTeamListOffline pack_offline; TPacketGCMessengerTeamListOnline pack_online; TEMP_BUFFER buf(128 * 1024); itertype(m_TeamRelation[account]) it = m_TeamRelation[account].begin(), eit = m_TeamRelation[account].end(); while (it != eit) { if (m_set_loginAccount.find(*it) != m_set_loginAccount.end()) { pack_online.connected = 1; pack_online.length = it->size(); buf.write(&pack_online, sizeof(TPacketGCMessengerTeamListOnline)); buf.write(it->c_str(), it->size()); } else { pack_offline.connected = 0; pack_offline.length = it->size(); buf.write(&pack_offline, sizeof(TPacketGCMessengerTeamListOffline)); buf.write(it->c_str(), it->size()); } ++it; } pack.size += buf.size(); d->BufferedPacket(&pack, sizeof(TPacketGCMessenger)); d->Packet(buf.read_peek(), buf.size()); } void MessengerManager::SendTeamLogin(MessengerManager::keyA account, MessengerManager::keyA companion) { LPCHARACTER ch = CHARACTER_MANAGER::instance().FindPC(account.c_str()); LPDESC d = ch ? ch->GetDesc() : NULL; if (!d) return; if (!d->GetCharacter()) return; BYTE bLen = companion.size(); TPacketGCMessenger pack; pack.header = HEADER_GC_MESSENGER; pack.subheader = MESSENGER_SUBHEADER_GC_TEAM_LOGIN; pack.size = sizeof(TPacketGCMessenger) + sizeof(BYTE) + bLen; d->BufferedPacket(&pack, sizeof(TPacketGCMessenger)); d->BufferedPacket(&bLen, sizeof(BYTE)); d->Packet(companion.c_str(), companion.size()); } void MessengerManager::SendTeamLogout(MessengerManager::keyA account, MessengerManager::keyA companion) { if (!companion.size()) return; LPCHARACTER ch = CHARACTER_MANAGER::instance().FindPC(account.c_str()); LPDESC d = ch ? ch->GetDesc() : NULL; if (!d) return; BYTE bLen = companion.size(); TPacketGCMessenger pack; pack.header = HEADER_GC_MESSENGER; pack.subheader = MESSENGER_SUBHEADER_GC_TEAM_LOGOUT; pack.size = sizeof(TPacketGCMessenger) + sizeof(BYTE) + bLen; d->BufferedPacket(&pack, sizeof(TPacketGCMessenger)); d->BufferedPacket(&bLen, sizeof(BYTE)); d->Packet(companion.c_str(), companion.size()); } #endif void MessengerManager::Logout(MessengerManager::keyA account) { if (m_set_loginAccount.find(account) == m_set_loginAccount.end()) return; m_set_loginAccount.erase(account); std::set<MessengerManager::keyT>::iterator it; for (it = m_InverseRelation[account].begin(); it != m_InverseRelation[account].end(); ++it) { SendLogout(*it, account); } std::map<keyT, std::set<keyT> >::iterator it2 = m_Relation.begin(); while (it2 != m_Relation.end()) { it2->second.erase(account); ++it2; } #ifdef ENABLE_MESSENGER_TEAM std::set<MessengerManager::keyT>::iterator it5; for (it5 = m_InverseTeamRelation[account].begin(); it5 != m_InverseTeamRelation[account].end(); ++it5) { SendTeamLogout(*it5, account); } std::map<keyT, std::set<keyT> >::iterator it6 = m_TeamRelation.begin(); while (it6 != m_TeamRelation.end()) { it6->second.erase(account); ++it6; } m_TeamRelation.erase(account); #endif m_Relation.erase(account); //m_map_stMobile.erase(account); }
  4. Mário.

    Resolver Problemas Em Missões Biologo Dos Jogadores

    Quem puder testar que dê feedback pls: questlua_global.cpp: int _set_quest_state_other (lua_State* L) { if (!lua_isstring(L, 1) || !lua_isstring(L, 2) || !lua_isstring(L, 3)) return 0; CQuestManager& q = CQuestManager::instance(); PC* pPC = q.GetCurrentNPC(); QuestState * pqs = q.GetCurrentState(); const string stPlayerName(lua_tostring(L, 1)); if (L!=pqs->co) { luaL_error(L, "running thread != current thread???"); sys_log(0,"running thread != current thread???"); return -1; } if (pPC) { const string stQuestName(lua_tostring(L, 2)); const string stStateName(lua_tostring(L, 3)); if (pPC->GetPlayerName(stPlayerName)) { if ( test_server ) sys_log(0,"set_state %s %s ", stQuestName.c_str(), stStateName.c_str() ); if (pPC->GetCurrentQuestName() == stQuestName) { pqs->st = q.GetQuestStateIndex(pPC->GetCurrentQuestName(), lua_tostring(L, -1)); pPC->SetCurrentQuestStateName(lua_tostring(L,-1)); } else { pPC->SetQuestState(stQuestName, stStateName); } } } return 0; } { "set_quest_state_other", _set_quest_state_other }, questpc.h: // Procurar por: const string & GetCurrentQuestName() const; // Adicionar abaixo: const string & GetPlayerName() const; questluapc.cpp: const string & PC::GetPlayerName() const char * name { LPCHARACTER npc = CHARACTER_MANAGER::instance().FindPC(name); return npc->GetName(); } questmanager.h: // Procurar por: LPCHARACTER m_pCurrentNPCCharacter; // Substituir por: PC* m_pCurrentNPCCharacter; // Procurar por: PC * GetCurrentPC() { return m_pCurrentPC; } // Adicionar abaixo: PC * GetCurrentNPC() { return m_pCurrentNPCCharacter; } A utilização dele é como o @Tierri Lopes disse: set_quest_state_other("Tierri", "quest_test", "run") -- Nome do jogador | quest | state
  5. Mário.

    [Quest][Pedido]Biologo

    https://metin2dev.org/board/index.php?/topic/11941-small-release-blocking-ip-address-to-killings/
  6. Mário.

    Admin Whisper

    Obrigado, fiz a quest à pressa e nem reparei nisso E sim, tens razão, será melhor utilizar um ficheiro externo: when login begin a = io.open(get_locale_base_path().."/admin_whisper.txt", "r") this = a:read() cmdchat(string.format("admin_whisper %s %s",this,this)) end Desta forma ficaria o ficheiro ficaria: mário paci Resultado: O @Marco e o Daryl (GalaxyMT2) deram a ideia da mensagem ser enviada de X a X tempos de acordo com a hora que eles queriam, então para isso é só utilizar esta quest: quest admin_whisper begin state start begin when login begin -- Desta forma, todas as segundas e terças às 15:30, será enviado um PM a cada jogador online durante esse tempo local data = {"Monday 15:30","Tuesday 15:30"} for index, datetime in ipairs(data) do if datetime == os.date("%A %H:%M") then if game.get_event_flag("admin_whisper") == 1 then cmdchat(string.format("admin_whisper %s %s",whisper.admin,whisper.text)) end end end end end end
  7. Mário.

    [Quest][Pedido]Biologo

    Em baixo estão cerca 9 quests totalmente otimizados para droparem itens do biólogo em jogador. Alguns extras: Tem verificação vs IP (Jogadores com o mesmo IP não irão dropar itens); Com um pet, terão mais possibilidade de droparem ou não o item; As quests estão interligadas uma com a outra, ou seja, assim que acabam uma missão a outra é logo ativada (se tiverem o nível requerido); Possibilidade de saberem vários detalhes de cada morte (logs): O jogador, o adversário, em que canal, em qual missão e a hora; Se o jogador matar a mesma pessoa 5x, a mesma é posta a parte para ser analisado pela equipa. Estes dois últimos têm como o nome biólogo e biólogo_farm Se algum jogador aparecer no biólogo_farm é porque o mesmo matou mais que 5x a mesma pessoa. Com o biólogo, analisas se é farm ou não (pelas horas/minutos/segundos) e depois apagas o nome da pessoa nessa tabela, foi desta forma que eu fiz no pvp e correu-me bastante bem. Está tudo identificado de forma a conseguires entender o que cada coisa significa: sistema.biologo.lv75_inicial = 75 -- Nível inicial para começarem a missão sistema.biologo.lv75_item = 30006 -- item que será dropado assim que matarem os jogadores [a base de probabilidade, linha 67] sistema.biologo.lv75_quantidade = 1 -- quantidade do item a ser dado. sistema.biologo.lv75_minquantidade = 1 -- mínimo de quantidade para poderem entregar o item [recomendado 1, visto que poderão entregar sempre, desde que o tenham] sistema.biologo.lv75_maxquantidade = 15 -- quantidade máxima que precisam de ter para aparecer o aviso de onde terão que voltar para o biólogo sistema.biologo.lv75_pet = 34001 -- ID do pet que dará mais % no biólogo sistema.biologo.lv75_percentagem = 20 -- percentagem sem pet sistema.biologo.lv75_percentagempet = 50 -- percentagem se possuirem determinado pet Alguns avisos: É necessário ter pc.get_ip e npc.get_ip implementados; É necessário adicionar dofile(get_locale_base_path().."/quest/sistema.lua") no questlib.lua; É necessário colocar o sistema.lua na pasta /quest. Recomendo apenas a mexeres nas quests principais somente para alterar os bónus sistema biologo.rar
  8. Mário.

    Admin Whisper

    Antes de começar com o tópico, se esperam algo complexo deste sistema, então poderão voltar para trás porque isto foi em apenas 1 hora de trabalho. Têm todo o direito de melhorar isto à vontade. Bem, eu ando a fazer alguns testes no que toca a performance entre quest-client e game-client e sendo sincero, quase ou pouco noto a diferença (já deu para entender que sou fanboy de lua certo?), apenas há 1 ~ 3 comandos extras a serem feitos. O que é este sistema? Isto dá-se como o nome de Admin Whisper (Mensagens de Equipa em português) e tem como objetivo enviar uma mensagem a todos os jogadores assim que entram pela primeira vez no jogo. Para que serve? Tal como disse acima, todos os jogadores (independentemente do canal - ou seja, poderão estar no CH1 como no CH2 -) irão receber sem qualquer tipo de problema ou latência. (Mensagem a ser enviada - No print não tem como ser visível mas ela pisca) (Conteúdo da mensagem) Requisitos: Python LUA Client Procurem (game.py) por: "PlayMusic" : self.__PlayMusic, Em baixo, adicionem: "admin_whisper" : self.AdminWhisper, Procurem por: def __PlayMusic(self, flag, filename): flag = int(flag) if flag: snd.FadeOutAllMusic() musicInfo.SaveLastPlayFieldMusic() snd.FadeInMusic("BGM/" + filename) else: snd.FadeOutAllMusic() musicInfo.LoadLastPlayFieldMusic() snd.FadeInMusic("BGM/" + musicInfo.fieldMusic) Adicionem isto no questlib.lua: dofile(get_locale_base_path().."/admin_whisper.lua") Por baixo adicionem: def AdminWhisper(self, admin, text): # Nome a ser chamado txt = str(text) # A mensagem em si show = txt.replace("_", " ") # Os _ são substituidos por espaço name = "|cFFFF8C00|H|h[%s]|h|r" % (admin) # Cor semelhante a de um Game Master + o nome proveniente do servidor chat.AppendWhisper(chat.WHISPER_TYPE_GM, name, show) # É enviado a mensagem com carácter GM self.interface.RecvWhisper(name) # É anúnciado da mesma forma que uma mensagem normal SERVER Criem no diretório do locale um ficheiro chamado admin_whisper.lua com isto lá dentro: --[[ De forma a que as mensagens tenham espaço uma da outra, é necessário utilizarem o uso da _ de forma a que o client consiga substituir. O motivo deve-se ao facto do comando cmdchat - ou CHAT_TYPE_COMMAND - ignorar tudo o que venha depois de um espaço (corrigem-me se estiver mal), por isso decidi que isto poderia ser a melhor forma disponível para que os espaços sejam visto visualmente. OBS: Repito, se queres algo complexo, podes usar isto como base ou simplesmente não usar, não obrigo ninguém a utiliza-lo. PS: Também poderão mandar mensagem a cada um dos jogadores de acordo com a sua linguagem (se tiverem multilinguagens instalado). ]] whisper = {} -- Abre a clásula para a palavra whisper whisper.admin = "MÁRIO" -- Nome do sistema a aparecer -- Mensagem a ser exibida | Se quiserem enviar mais que uma, poderão faze-lo perfeitamente dando alguns retoques no código whisper.text = "Olá_a_todos,_só_queria_dizer_que_este_´tutorial´_foi_criado_pelo_Mário_por_isso_se_quiserem_meter_os_créditos_quando_forem_meter_em_um_outro_sítio,_metam_os_meus_e_não_os_vossos_^^ " Utilizem a seguinte quest como um teste: quest admin_whisper begin state start begin when login begin if game.get_event_flag("admin_whisper) == 0 then return else cmdchat(string.format("admin_whisper %s %s",whisper.admin,whisper.text)) end end end end /e admin_whisper 1 - O sistema estará ativo e todos irão receber as mensagens /e admin_whisper 0 - O sistema estará desativo e ninguém irá receber as mensagens
  9. Mário.

    [QNA] Proteção anti-hack

    Apoio totalmente a nova filosofia e já tive oportunidade de ver e analisar a mesma em ação. Considero que é mais prático e eficiente tornar o cliente disponível para todos e mudar a estrutura interna de forma a que ir no sentido contrário de módulos pré-definidos pela source (headers, modules, imports, etc.). Um exemplo disso é a forma como o lalaker funciona. Se analisares como ela se comporta e que tipos de headers ela usa (graças a um packet reader) consegue-se descobrir que utiliza o header que se encontra disponível para o ataque (SPACE) = 3. Ora mudando o número, com a opção ProDamage ligado, a personagem acabaria por levar dc pois o objetivo do mesmo é utilização do default. O m2bob funciona de outra forma, excluindo a utilização de headers. De certa forma, concordo e apoio.
  10. Mário.

    Bonus Pvm/Pvp e Faixas

    1. Procura por (game.py): onPressKeyDict[app.DIK_X] = lambda : 2. Comenta/Apaga: #onPressKeyDict[app.DIK_X] = lambda : self.__OpenBonus() <- Isto é um exemplo, não é igual ao que tens 3. Procura por: (uitooltip.py): if isCostumeSash: 4. Substitui por: if itemVnum >= 85001 and itemVnum <= 85024: # São os IDs das faixas, se tens de outra forma, substitui
  11. Mário.

    System MultiLanguage

    O default encontra-se em inglês de momento. De momento utilizo a opção de reiniciar o cliente por motivos de estética até conseguir ter um código perfeitamente aceitável. - Utilizo somente alguns ficheiros para a parte /locale/country sendo que o resto fica no default que é o pt. A ideia do item_names e de meter nas opções é muito bem vinda mesmo, é algo que irei adaptar para o sistema. O locale_string foi totalmente complicado para mim mas deixo já um obrigado ao @Sil3nce por me ter salvado. Tens razão, a parte da quest não causa problemas nenhuns e torna-se super acessível para futuros usos.
  12. Mário.

    System MultiLanguage

    Estou a pensar em publicar mas não posso garantir.
  13. Mário.

    System MultiLanguage

    Mário* Na verdade não há nenhum problema que tenha a ver com traduções de quest, pela forma que fiz (ou mesmo fazendo do_file pela questlib) não teria qualquer problema no que toca a isso, a aba que te referes é do common.locale mas não é necessário mudar de forma alguma porque poderás meter todas dentro da pasta /portugal (ou o nome qualquer que tenhas) e meteres de forma a que o jogador vá buscar certo .txt, tal como fiz com o mob_names: Português: Inglês:
  14. Mário.

    System MultiLanguage

    O problema é que o VegaS é "internacionalmente" conhecido e interpretam-no como o único capaz de fazer estes tipos de sistemas. Vejo mesmo pessoas que chegam a dizer "nada é igual se fosse o vegas a fazer" o que respeito mas há que ter bom senso para saber que ele não é o único com competências. Longe de mim comparar-me com ele, até porque há sistemas que ele criou e que eu implementei, mas chega de dar dickriding nele. Continuando com o tópico, utilizei um pouco de tudo o que disseram: Criei uma aba na tabela account onde estará a linguagem definida (ideia dada pelo @trample): Por default, todas as contas virão em inglês, sendo que assim que entrarem poderão escolher a linguagem. As quests poderão ser facilmente modificadas pelo translate.lua (ideia dada pelo @AprendizM2): snprintf(translateFileName, sizeof(translateFileName), "%s/translate_%s.lua", LocaleService_GetBasePath().c_str(), Language_GetBasePath().c_str()); Invés de fazer do_file na questlib, preferi fazer pela source criando um diretório para as linguagens: Language_GetBasePath Com novas funções como pc.get_lang() que busca qual é a linguagem que temos inserido na base de dados, poderemos utilizar algo como isto: quest language begin state start begin when login begin syschat(system[pc.get_lang].testing) end end end system = {} system["pt"].testing = "Olá" system["en"].testing = "Hi" Esta forma de fazer é bastante simples e penso que deva de estar público em algum lugar. Estou a trabalhar para deteção de IP utilizando o GeoLite2++ (ideia dada pelo @Tierri Lopes) void CInputLogin::LoginByKey(LPDESC d, const char * data) { TPacketCGLogin2 * pinfo = (TPacketCGLogin2 *) data; char login[LOGIN_MAX_LEN + 1]; trim_and_lower(pinfo->login, login, sizeof(login)); GeoLite2PP:DB db("/opt/stuff/GeoLite2-City.mmdb") std:string ip = db.get_field(d->GetHostName(), GeoLite2PP::VCStr {"country", "names", "geral"}); sys_log(0, "Country: %s", ip); // Just a test to see the output const char * country = { "Portugal", "England", "Romenia", "Spanish", "Turkey", "Germany" }; ... } Ainda não está concluído, é apenas para terem uma ideia de como será feito a deteção (podem utilizar que não me importo). Estou a pensar em como devo de fazer a identificação para o locale_string.txt, penso que serei capaz de remodelar por completo a forma como ela é estruturada e ser chamada como um ficheiro de lua (exemplo): %s ±ºÁÖ Èĺ¸¿¡¼­ »èÁ¦ÇÏ¿´½À´Ï´Ù = "%s foi excluido como Candidato da Monarquia."
  15. (O título está inglês para chamar mais atenção) Ontem vi-me a falar sozinho na shoutbox e hoje cheguei a seguinte conclusão. Ultimamente tenho andado um pouco viciado em PHP & HTML e graças a isso, decidi meter na cabeça criar um sistema completo de multilinguagens em: Site; Client; Serverside. No site está otimizado e bem estruturado mas no client e no serverside não estão bem exatamente da forma como eu quero e daí pedir-vos sugestões. Esta é a forma como eu tenho feito: PHP: $details = ip_details($real_ip); $country = $details->country; $current_country = array( 'PT' => 'pt', 'BR' => 'pt', 'ES' => 'es', 'DE' => 'ge', 'GB' => 'en', 'US' => 'en', 'RO' => 'ro', 'TR' => 'tr', // Ficará para depois ); Python: # Add after: if app.ENABLE_LSM2_MULTI_LANGUAGE: self.text = ConnectingDialog() self.text.SetText(localeInfo.CLIENT_RESTART) self.text.Close() # This was made in order to make some changes/upgrades in the system. You can simple edit if you want. self.flag = { 'LANG' : ( "pt", "en", "ro", "es", "de", "tr", ) } # This means: # pt: 0 # en: 1 # ... self.exe = "metin2client.exe" # Change the name for your metin2client.exe # If you use .bin, just change it to the directory of the patcher (ex: patcher.exe) # Search for: def __ExitGame(self): app.Exit() # Add after: if app.ENABLE_LSM2_MULTI_LANGUAGE: # I made this way because of the timer (It's kinda of stupid but I will change it on the next update) # Probably this is not the best code, but it works - not really an expert in python Tenho feito de forma a ser por tutorial pois estou a pensar em lançar o mesmo quando acabar. Um print de como está no login: O pedido agora é: Como devo de fazer o sistema? Por identificação de IP ou por algo como mudança de linguagem presente por quest (sou bastante fã de LUA rs)? Pedi já opiniões externas e debateram-se dizendo que se for IP acabará por a desvantagem de (por exemplo) ser impossível um português morar no estrangeiro e querer jogar na língua materna e é por essa razão que estou mais inclinado para fazer por quest (a minha ideia seria criar uma função como ch->GetLang que pudesse indicar a que linguagem ele tem de forma a poder ser mudado o locale_string/translate.lua/oxquiz.lua/. Obrigado desde já pela atenção
×

Important Information

By using this site, you agree to our Terms of Use.