Search the Community

Showing results for tags 'tutoriel / partage'.



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 778 results

  1. Bonjour, New tuto: comment changer l'icône des skills en jeu ! Go !! 1. Ouvrez EterNexus Vous depackez ensuite le pack etc.eix 2.On va où il faut : Rendez-vous ici : etc\ymir work\ui Vous ouvrez ensuite : skillsura.dds ou skillshaman.dds ou skillwarrior.dds ou bien skillninja.dds Vous devriez avoir ça : On modifie.... hum comme ça : On repack ensuite le tout ! Et voilà le rendu IG : J’espère que ça vous aura plu ! Bon jeu ! Cordialement.
  2. Bonjour, Nouveau petit tutoriel encore une fois très simple : Comment changer la couleur des bulles d'exp en bas de l'écran, ou même mettre des formes dedans ? On va voir tout ça aujourd'hui ! 1.On reprend notre bon vieux EterNexus Vous allez donc depacker : Etc.eix et Etc.epk avec. 2.On va chercher les dossiers Rendez-vous ensuite dans votre pack Etc ensuite ymir work et enfin dans ui. Vous allez ensuite ouvrir le fichier : taskbar.tga Vous devriez avoir ceci : Vous allez donc zoomer sur la bulle d'exp (elle est en haut à droite) : Vous allez donc pouvoir modifier la bulle selon vos envies par exemple : (J'ai fais ça en 10 sec, c'est un exemple ! Je crois que le rendu IG va être horrible ). On repack donc tout ça, et on remet ça dans notre client ! Voilà le rendue IG : Voilà, c'est la fin de ce petit tutoriel très simple Bon jeu ! Cordialement.
  3. -------------------------------------------------------------------- 1 Dans le dossier germany pack, vous trouverez 2 fichiers .eix et .epk 2 Placez ces deux fichiers dans le dossier pack de votre client. 3 Ouvrez avec notepad++ votre fichier index ( toujours dans pack, puis rajoutez tout en bas de la ligne, ceci : kfworsgermanypython/ kfworsgermanypython [laissez un espace vide] 4 Mettez les fichiers du dossier lib, dans le dossier lib de votre client. 5 Mettez le dossier settings a la racine de votre client. /!\ Si ca ne fonctionne pas, mettez les fichiers dans le dossier pack. /!\ 6 Depackez locale_fr de votre client, et remplacez les fichiers dans /ui 7 Depackez root de votre client, et remplacez le intrologin.py dans /root 8 --- Modifiez dans le intrologin.py aux lignes 1638 à 1665, le nom du serveur uniquement, ne pas toucher a SERVERIP --- net.SetServerInfo("Serveur - CH1") net.SetMarkServer(SERVERIP, CH1PORT) self.serverInfo.SetText("Serveur Ch1") app.SetGuildMarkPath("10.tga") app.SetGuildSymbolPath("10") 9 Dirigez vous vers les lignes 29 à 36 dans intrologin.py et regardez ces lignes : SERVERIP = "192.168.0.63" KANAL = 4 CH1PORT = 13000 CH2PORT = 13001 CH3PORT = 13002 CH4PORT = 13003 AUTHPORT = 11002 SERVERADI = "KF-Works" FRAGEN = 1 SERVERIP : Mettez votre IP KANAL = 4 : Laissez 4 c'est par défaut . CH1/2/3/4/PORT : Je vous ai déja réglé les ports par défaut des Ch. AUTHPORT : Déja réglé également. SERVERADI : Nom du serveur ---------- 10 Dans le dossier que vous avez téléchargé, il y a un dossier " kfworsturkeypython " . A l'intérieur de celui ci, se trouve un dossier se nommant " kf works " , copiez le dossier " kf works " dans locale/fr/ui. ------------------------ Bonne utilisation. #fichiers traduits et adaptés Lien avec tuto mis a jour : [Hidden Content]
  4. Bonsoir, Je viens vous présentez une minimap que vous devez connaitre, les nouveautés? aucun sauf la rectification du beug de "+" "-" "m", et un autre design partager. Vous avez juste à télécharger et à remplacer les fichiers. De plus vous aurez un .txt "A lire!" qui vous informera d'un petit plus que j'ai mis. Minimap.rar (65 Ko) [Hidden Content] Autre skin possible; minimapskin1.rar (21 Ko) [Hidden Content] Source de l'image: [Hidden Content] Source: epvp et moi. Ps: éditer le xml pour rajouter les fichiers du pattern ajouté et ce du ymirk work/ui . Cordialement, Wiki.
  5. Bonjour à tous, Aujourd'hui je vais vous expliquer rapidement comment compiler les sources enhanceMT pour la partie serveur sous Windows. Lisez bien tranquillement et tout se passera bien ! 1. Logiciels requis 2. Récupérer les sources 3. Configurer la solution avec CMake 4. Compiler ! Dans le menu, définissez le mode de compilation en "Release" et cliquez sur "Générer -> Générer la solution" (ou pressez F7). Une fois la compilation terminée vous trouverez les exécutables "db.exe" et "game.exe" dans le dossier "Server/build/bin/Release". Et voilà, c'était pas si difficile que ça au final non ? Je vous rappelle que le projet enhanceMT est un projet open source et communautaire, tout le monde peut y participer, alors n'hésitez pas à nous faire part de vos suggestions, remarques, bugs, etc. (Si possible directement sur GitHub, ici : [Hidden Content]). Sgt Fatality
  6. Bonjour, Bonsoir Voilà donc ayant eu pas mal de soucis pour compiler ces derniers jours et avec l'aide de l'équipe enhanceMT j'ai pu finalement compiler sous freebsd 10, c'est pourquoi je viens faire un tutoriel sur comment compiler sous freebsd 10. "Tout au long du tutoriel nous partirons du fait que votre machine est déjà installé." Sommaire: I- Installation des utilitaires II- Installation des sources III- Les utiles I- Installation des utilitaires: Alors commençons, dans votre machine vous tapez ceci: pkg install git Une fois fait vous tapez la commande suivante toujours sur votre machine: pkg install cmake-3.0.2 Attention il faut mettre en fonction de votre machine pour savoir votre version cmake vous tapez la commande: pkg search cmake Pour faire un peu d'explication merci à SGT de m'avoir expliqué: pkg c'est le système de gestion de paquet de freebsd, donc s'il vous manque une lib ou si vous recherchez un paquet vous faites : pkg search nom_paquet et pour installer : pkg install nom_paquet On reprend donc une fois le cmake d'installé, vous tapez la commande suivante: pkg install boost-all-1.55.0 "Toujours pareils en fonction de votre machine donc faites une recherche" On continue avec cette commande: pkg install cryptopp-5.6.2_2 Ensuite on tape la commande: pkg install mysql55-server-5.5.41 mysql55-client-5.5.41 Et pour finir en beauté voici la dernière commande: pkg install devil Donc nous avons finis la première partie du tutoriel, on va installer les sources. II- Installation des sources: Sur votre machine vous entrez la commande suivante: Nouveau: Vous devez vous enregistrer ici : [Hidden Content] avant de pouvoir faire la commande ci-dessous : git clone [Hidden Content] Une fois l'installation terminé tapez la commande suivante et retrouvons-nous dans le dossier source: cd /root/Server/ Dans root car par défaut les sources s'installeront dedans. Voilà vous avez les sources sur votre serveur. III- Les utiles Pour compiler votre db et game vous tapez ceci: cd /root/Server/build Une fois fait vous enchainez avec: cmake ../ Si vous n'avez aucune erreur ce qui devrait être logique si vous avez bien suivis le tutoriel vous tapez: make Et vous voilà avec votre game et db de compilé. J'espère que sa vous aideras pour tous soucis on se retrouve dans A/Q/S. Bonne journée/ Bonne soirée Kuzuri
  7. Bonjours à toutes et à tous ! Il ne me semble pas avoir vu ce tuto sur ce forum donc je vais partager la façon d'installer un nouveau bouton sur l'interface IG. Pour l'exemple, je vais utiliser la Bonus Gui en la mettant sur un nouveau bouton à côté de celui de l'inventaire. Bien évidemment on peut adapter ce tuto pour mettre sur le bouton tout autre chose que la bonus gui ! Dans ce tuto nous allons utiliser la Bonus Gui partagée par Cube: [Hidden Content] Commencez par télécharger le script python de la GUI: [Hidden Content] Mettez ce fichier dans votre root. Pour commencer, nous allons ajouter le bouton à l'interface. Dépackez locale_fr puis ouvrez le fichier "taskbar.py" se trouvant dans: depack\locale\fr\ui Dans ce fichier, cherchez ceci: { "name" : "InventoryButton", "type" : "button", "x" : SCREEN_WIDTH - 110, "y" : 3 + Y_ADD_POSITION, "tooltip_text" : uiScriptLocale.TASKBAR_INVENTORY, "default_image" : ROOT + "TaskBar/Inventory_Button_01.sub", "over_image" : ROOT + "TaskBar/Inventory_Button_02.sub", "down_image" : ROOT + "TaskBar/Inventory_Button_03.sub", }, Une fois trouvé, faites un copier/coller de ceci juste en dessous: { "name" : "BonusGui", "type" : "button", "x" : SCREEN_WIDTH - 178, "y" : 3 + Y_ADD_POSITION, "tooltip_text" : "Bonus", "default_image" : ROOT + "TaskBar/Inventory_Button_01.sub", "over_image" : ROOT + "TaskBar/Inventory_Button_02.sub", "down_image" : ROOT + "TaskBar/Inventory_Button_03.sub", }, "tooltip_text" : "Bonus", Ceci veut dire que lorsque vous passez votre curseur sur la case, le texte "Bonus" s'affiche, vous pouvez donc le modifier comme vous le souhaitez "default_image" : ROOT + "TaskBar/Inventory_Button_01.sub", "over_image" : ROOT + "TaskBar/Inventory_Button_02.sub", "down_image" : ROOT + "TaskBar/Inventory_Button_03.sub", Cette partie gère les 3 images composant l'icône, il y a l'image lorsque l'icône est normal, lorsqu'on passe notre curseur sur l'icône est lorsqu'on clic dessus. Pour ce tuto, c'est donc l'icône de l'inventaire, à vous de mettre ce que vous voulez ! "name" : "BonusGui", Ici, mettez le nom de ce que vous ajoutez, vous pouvez entrer ce que vous voulez mais il me paraît logique de mettre le nom de ce qu'on ajoute pour se repérer plus facilement (et que ce soit plus facile pour la suite du tuto). Suivant ce que vous ajoutez, modifiez cette ligne comme bon vous semble mais on en aura besoin pour la suite du tuto. Lorsque vous avez ajouté et modifié comme vous le souhaitez, on va tester si l'icône s'affiche bien. Repackez puis connectez-vous, si vous avez gardé les mêmes coordonnées que dans le tuto, vous aurez un nouvel icône ayant le skin de celui de l'inventaire en bas à droite de votre écran. Lorsque vous cliquez dessus rien ne se passe ? c'est normal, ça se passe dans la suite du tuto ! On passe maintenant au plus "compliqué". Dépackez root et ouvrez le fichier "uitaskbar.py" (attention, ce n'est pas celui qui se trouve dans locale_fr !) Cherchez maintenant la ligne: toggleButtonDict[TaskBar.BUTTON_CHARACTER]=self.GetChild("CharacterButton") Puis collez en dessous ceci: toggleButtonDict[TaskBar.BUTTON_BONUSGUI]=self.GetChild("BonusGui") self.GetChild("BonusGui") Dans ces crochets, veillez à écrire le "name" précédemment ajouté dans le fichier uitaskbar.py du locale_fr. Dans notre cas c'est donc "BonusGui" toggleButtonDict[TaskBar.BUTTON_BONUSGUI] Cette partie est importante ! vous pouvez écrire ce que vous souhaitez, ce sera le nom de la fonction qu'on utilisera plus tard, il faut que ce qu'il y a après "TaskBar." soit écrit EN MAJUSCULE comme dans l'exemple ! Cherchez maintenant: BUTTON_CHAT = 4 On va donner un numéro à cette fonction, ajoutez donc en dessus: BUTTON_BONUSGUI = 5 "BUTTON_BONUSGUI" est le nom de la fonction précédemment ajoutée, celle qu'on a dû écrire en majuscule, veillez à écrire le même nom ! Vous pouvez bien évidemment écrire ce que vous voulez, mais il faut que ce soit le même nom que la fonction qu'on a écrit ici: toggleButtonDict[TaskBar.BUTTON_BONUSGUI]=self.GetChild("BonusGui") Dans root, ouvrez le fichier "interfacemodule.py" puis cherchez: self.wndTaskBar.SetToggleButtonEvent(uiTaskBar.TaskBar.BUTTON_CHAT, ui.__mem_func__(self.ToggleChat)) Et ajoutez en dessous: self.wndTaskBar.SetToggleButtonEvent(uiTaskBar.TaskBar.BUTTON_BONUSGUI, ui.__mem_func__(self.BonusGui)) TaskBar.BUTTON_BONUSGUI À cette ligne vous devez écrire le nom de la fonction (donc "BUTTON_BONUSGUI" si on suit ce tuto à la lettre) (self.BonusGui) Ici c'est "name" se trouvant dans uitaskbar.py dans locale_fr. Veillez à ce qu'il y ai écrit exactement la même chose que dans "name". Maintenant il vous suffit d'ajouter le code que vous souhaitez exécuter lorsqu'on clic sur ce bouton. Je vais donc utiliser le code pour la Bonus Gui. Mettez où vous le souhaitez, pour ma part je l'ai mis au dessus de " def __MakeParty(self): Pour les personnes implantant la bonus gui, ajoutez ceci: def BonusGui(self): import uiBonusPage global BPisLoaded try: if BPisLoaded != 1: exec 'uiBonusPage.BonusBoardDialog().Show()' else: pass except ImportError: import dbg,app dbg.Trace('uiBonusPage.py Importing error') app.Abort() Pour les autres ajoutez VOTRE code. Vous l'aurez sans doute compris, après "def" vous devez écrire le nom inscrit dans "name" dans uitaskbar.py du locale_fr. Pour les personnes implantant quelque chose d'autre que la BonusGui, ce tuto est fini, vous pouvez repack root et tester votre icône ! pour ceux qui implantent la bonus gui du topic de Cube vous avez encore 2-3 choses à faire ! Toujours dans interfacemodule.py, cherchez: IsQBHide = 0 Puis ajoutez en dessous: BPisLoaded = 0 Toujours pour ceux implantant la Bonus Gui, on reprend simplement le topic de Cube, allez dans ui.py puis cherchez ceci: def SetOverVisual(self, filename): Ajoutez ensuite en dessous: ##Bonus def GetText(self): if not self.ButtonText: return# "" return self.ButtonText.GetText() def SetDownVisual(self, filename): wndMgr.SetDownVisual(self.hWnd, filename) N'oubliez pas que le python n'aime pas les espaces ! remplacez donc les espaces par des tabulations et mettez les tabulations aux bons endroits. Ce tuto est maintenant terminé, vous pouvez repack root ! si vous avez des questions n'hésitez pas à les poser dans la section "Aide / Questions / Support" ! Bonne soirée/journée à toutes et à tous !
  8. Bonjour à tous et à toutes, Voici mon tout premier tutoriel qui va vous permettre d'afficher l'orbe de bénédiction/cuivre magique en magasin mais aussi de supprimer la multiplication x3 du prix des items pouir la vente aux autres empires sous files 2014. --- 1. Pour commencer il faut décompiler le game, voir ici: [Hidden Content] (Merci infiniment à Calypso). 2. Nous allons aller chercher le fichier shop.cpp à cet emplacement: /usr/src/mainline/Srcs/Server/game/src et l'ouvrir 3. Pour les rendre visibles en magasin, il vous faut chercher le code ci-dessous à l'aide de "CTRL+F" : if (item->GetVnum() == 70024 || item->GetVnum() == 70035) --- 70024 est le code de l'orbe 70035 celui du cuivre --- Pour afficher l'orbe et non le cuivre vous faites comme ceci : if (item->GetVnum() == 70035) Et pour afficher le cuivre et non l'orbe vous faites comme ceci : if (item->GetVnum() == 70024) cherchez le code ci-dessous et faites de même : if (item.vnum == 70024 || item.vnum == 70035) Pour afficher les deux, vous retirez le petit bout de code ou commentez la ligne. --- 4. Le prix multiplié x3 dans un autre empire que le sien. Toujours dans le fichier shop.cpp, cherchez le code ci-dessous à l'aide de "CTRL+F" : pack2.items[i].price = item.price * 3; *3 est le chiffre par lequel on multiplie le prix des item's dans un autre empire Vous pouvez le multiplier par *1, *2, *3, *4, *5, etc... Pour ne pas multiplier le prix d'un item il vous suffit de mettre *1 Vous devez faire la même ici : if (it->second) // if other empire, price is triple dwPrice *= 3; --- 5. Vous avez fini, il ne vous reste plus qu'a compiler le game. Source : moi
  9. Bonjour all, Aujourd'hui je vous propose un tutoriel pour rajouter un top classement sur votre MT2-CMS. Ce tutoriel est très simple si vous suivez bien toutes les étapes que je vous indique. Première partie : Top joueurs I - Les fichiers à modifier Comme vous vous en doutez, il y a des fichiers à modifier. Commencez par ouvrir index.php et rajoutez ce script : // Classement // $i = 0; $requette = ("SELECT name,level FROM player.player WHERE name NOT IN(SELECT mName FROM common.gmlist) ORDER BY level DESC, exp DESC LIMIT 0,10"); $sql = mysql_query($requette) or die(mysql_error()); while(($data = mysql_fetch_array($sql))) { $i++; $tpl->assign_array('top5', array( 'name' => $data['name'], 'lvl' => $data['level'], 'i' => $i )); } Ce bout de code sert à choisir le nombre de joueurs à afficher : exp DESC LIMIT 0,10"); Vous remplacez 0,10 par 0,5 si vous voulez qu'il y ait 5 joueurs d'affiché. Maintenant il faut aller dans templates/default/fr/includes/ et vous ouvrez sidebar.tpl Si vous avez toujours la publicité, vous rajoutez ce bout de code en dessous. Si vous ne l'avez plus, il suffit de rajouter le script en bas : Top classement #Joueurlvl{top[i]}{top[name]}{top[lvl]} Deuxième partie : Top guilde Vous devez suivre le même tutoriel, mais avec ces script la : Dans l'index.php : // Classement ( GUILDE) // $i = 0; $requette = ("SELECT name,level,sp FROM player.guild WHERE name NOT IN(SELECT mName FROM common.gmlist) ORDER BY level DESC, exp DESC LIMIT 0,10"); $sql = mysql_query($requette) or die(mysql_error()); while(($data = mysql_fetch_array($sql))) { $i++; $tpl->assign_array('top5g', array( 'name' => $data['name'], 'lvl' => $data['level'], 'pts' => $data['sp'], 'i' => $i )); } et dans templates/default/fr/sidebar.tpl : Top classement guilde #GuildelvlPoints{top[i]}{top[name]}{top[lvl]}{top[pts]} Cordialement, Awesome PS : Contactez-moi sur skype si vous avez des problèmes pour l'installer : awesome.fr Source : Cms de roxas
  10. Cadeau 2016 ! Émulateur : Source + Exécutable + Bdd (V1) : Télécharger Changelogs : --- Download
  11. 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
  12. Bonjour à tous! Je viens vous partager un kit de développement complet pour RaiderZ dont je me servirai dans mes tutoriels / partages dans la section. Le kit est séparé en deux parties: Une partie contenant le serveur, le client, la base de donnée et les redistribuables: Client Serveur Redist /!\ Pour la partie serveur, des membres m'ont signalé des problèmes, si le message suivant apparait: /!\ Téléchargez ces redistribuables et installez les: [Hidden Content] Et une autre partie contenant les sources et les SDK du jeu: Sources + SDK Le client est le dernier client américain en date (2015), et le serveur possède la majeure partie des tous derniers contenus du jeu, lors de sa fermeture. Dans la première archive sont inclus les redistribuables, dans le dossier Redist. Pour être sûr de pouvoir jouer sans soucis, installez les avant de lancer le client ! Les sources ont été légèrement retravaillées pour être compatibles avec Visual Studio 2017, et sont issues d'un Github public : (Lien ici) Mot de passe pour les archives: Funky-emu.net --------------------------------------------------------------- Changelog : Lien des mises à jour pour la version actuelle : Si le dossier est vide, c'est qu'il n'y a pas de mises à jour pour ma version actuelle, et que tout est déjà inclus dans le pack principal. [Hidden Content] --- Download
  13. Bonjour, Un utilitaire qui permet de créer des ITEMS. Outil développé par NIXODAS. Logiciel en Allemand traduit (tant bien que mal) en Français par mes soins. [Hidden Content] A+ --- Download
  14. Salut tout le monde ! Aujourd'hui je vais vous apprendre à créer un serveur Habbo avec l'émulateur PlusEMU en dernière version. L'émulateur est assez stable et ne comporte quasiment aucun bug. --- Download
  15. 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
  16. Ce tutoriel a pour but de vous expliquer comment mettre un effet visuel sur berserk. Tous les buffs en ont un, par exemple bénédiction entoure le joueur d'une aura bleutée, berserk est l'exception. 1 -- Pour commencer dépacker le pack root puis ouvrez le fichier playersettingmodule.py vers la ligne 300 vous aurez : chrmgr.RegisterEffect(chrmgr.EFFECT_AFFECT+16, "", "d:/ymir work/pc/warrior/effect/gyeokgongjang_loop.mse") ajoutez cette ligne là avant : chrmgr.RegisterEffect(chrmgr.EFFECT_AFFECT+14, "Bip01", "d:/ymir work/pc/warrior/effect/berserk.mse") 2 -- Enregistrez, puis dépackez le pack pc. Il faut rajouter le fichier berserk.mse dans le dossier ymir work/pc/warrior/effect/ si vous n'en avez pas, voici le mien : 3 -- Repackez root et pc puis lancez berserk, vous devriez avoir ça: En espérant vous avoir aidé. Pour toutes questions, rendez-vous dans la catégorie Aide/Questions/Support
  17. Gestion des yangs : Aujourd'hui je vais vous partager une quête qui permet d'échanger ces yangs contre un lingot n'importe ou dans la map. quest yangs begin state start begin when 80001.use begin--Ajuster en fonction de l'item a utiliser say_title("Gestion des yangs") say("") say("Bonjour.") say("Ici, vous pouvez transformer vos yangs en lingots.") say("Combien de yangs voulez vous transformer ?") say("Vous avez un total de "..pc.gold.." yang(s).") local sy = select("50M","100M","250M","500M","1MM","Aucun")--Ajuster en fonction des yangs du lingots if sy==6 then return elseif sy==1 then if pc.gold > 50000000 then --Ajuster en fonction des yangs du lingots pc.change_gold(-50000000)--Ajuster en fonction des yangs du lingots pc.give_item2(80003, 1) else syschat("Vous n'avez pas assez de yangs !") end elseif sy==2 then if pc.gold > 100000000 then--Ajuster en fonction des yangs du lingots pc.change_gold(-100000000)--Ajuster en fonction des yangs du lingots pc.give_item2(80004, 1) else syschat("Vous n'avez pas assez de yangs !") end elseif sy==3 then if pc.gold > 250000000 then--Ajuster en fonction des yangs du lingots pc.change_gold(-2500000000)--Ajuster en fonction des yangs du lingots pc.give_item2(80005, 1) else syschat("Vous n'avez pas assez de yangs !") end elseif sy==4 then if pc.gold > 500000000 then--Ajuster en fonction des yangs du lingots pc.change_gold(-500000000)--Ajuster en fonction des yangs du lingots pc.give_item2(80006, 1) else syschat("Vous n'avez pas assez de yangs !") end elseif sy==5 then if pc.gold > 1000000000 then--Ajuster en fonction des yangs du lingots pc.change_gold(-1000000000)--Ajuster en fonction des yangs du lingots pc.give_item2(80006, 1) else syschat("Vous n'avez pas assez de yangs !") end end end end end Si vous ne savez pas implanter une quête, suivez ce tutoriel : ICI
  18. Bonjour, Bonsoir Je vous présente aujourd'hui, un petit partage, qui vous permettra d'ajouter des emplacements pour vos personnages. Ceci est mon premier partage, donc toutes critiques ou autres seront une source d'améliorations. Le tutoriel se base sur l'ordre suivant : Serveur/Client/MySQL Fini de parler, passons au tutoriel : /!\ Serveur /!\ Rendez-vous dans Common/length.h Cherchez : PLAYER_PER_ACCOUNT = 4, Remplacez par : PLAYER_PER_ACCOUNT = 8, Rendez-vous maintenant dans Game/src/locale_service.cpp Cherchez : static void __CheckPlayerSlot(const std::string& service_name) { if (PLAYER_PER_ACCOUNT != 4) { printf(" PLAYER_PER_ACCOUNT = %d\n", PLAYER_PER_ACCOUNT); exit(0); } } Remplacez par : static void __CheckPlayerSlot(const std::string& service_name) { if (PLAYER_PER_ACCOUNT != 8) { printf(" PLAYER_PER_ACCOUNT = %d\n", PLAYER_PER_ACCOUNT); exit(0); } } Maintenant, allez dans Game/src/char_change_empire.cpp Cherchez : snprintf(szQuery, sizeof(szQuery), "SELECT id, pid1, pid2, pid3, pid4 FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); std::auto_ptr msg(DBManager::instance().DirectQuery(szQuery)); Remplacez par : snprintf(szQuery, sizeof(szQuery), "SELECT id, pid1, pid2, pid3, pid4, pid5, pid6, pid7, pid8 FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u OR pid5=%u OR pid6=%u OR pid7=%u OR pid8=%u AND empire=%u", get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); std::auto_ptr msg(DBManager::instance().DirectQuery(szQuery)); Toujours dans char_change_empire.cpp Cherchez : MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult); str_to_number(dwAID, row[0]); str_to_number(dwPID[0], row[1]); str_to_number(dwPID[1], row[2]); str_to_number(dwPID[2], row[3]); str_to_number(dwPID[3], row[4]); Remplacez par : MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult); str_to_number(dwAID, row[0]); str_to_number(dwPID[0], row[1]); str_to_number(dwPID[1], row[2]); str_to_number(dwPID[2], row[3]); str_to_number(dwPID[3], row[4]); str_to_number(dwPID[4], row[5]); str_to_number(dwPID[5], row[6]); str_to_number(dwPID[6], row[7]); str_to_number(dwPID[7], row[8]); cherchez ensuite : snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); std::auto_ptr msg(DBManager::instance().DirectQuery(szQuery)); Remplacez par : snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u OR pid5=%u OR pid6=%u OR pid7=%u OR pid8=%u AND empire=%u", get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); std::auto_ptr msg(DBManager::instance().DirectQuery(szQuery)); Cherchez : DWORD CHARACTER::GetAID() const { char szQuery[1024+1]; DWORD dwAID = 0; snprintf(szQuery, sizeof(szQuery), "SELECT id FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); SQLMsg* pMsg = DBManager::instance().DirectQuery(szQuery); Remplacez par : DWORD CHARACTER::GetAID() const { char szQuery[1024+1]; DWORD dwAID = 0; snprintf(szQuery, sizeof(szQuery), "SELECT id FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u OR pid5=%u OR pid6=%u OR pid7=%u OR pid8=%u AND empire=%u", get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); SQLMsg* pMsg = DBManager::instance().DirectQuery(szQuery); Maintenant, rendez-vous dans db/src/clientmanager.cpp Cherchez : void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpireSelectPacket * p) { char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE id=%u", GetTablePostfix(), p->bEmpire, p->dwAccountID); delete CDBManager::instance().DirectQuery(szQuery); sys_log(0, "EmpireSelect: %s", szQuery); { snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4 FROM player_index%s WHERE id=%u", GetTablePostfix(), p->dwAccountID); std::auto_ptr pmsg(CDBManager::instance().DirectQuery(szQuery)); SQLResult * pRes = pmsg->Get(); Remplacez par : void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpireSelectPacket * p) { char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE id=%u", GetTablePostfix(), p->bEmpire, p->dwAccountID); delete CDBManager::instance().DirectQuery(szQuery); sys_log(0, "EmpireSelect: %s", szQuery); { snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, pid6, pid7, pid8 FROM player_index%s WHERE id=%u", GetTablePostfix(), p->dwAccountID); std::auto_ptr pmsg(CDBManager::instance().DirectQuery(szQuery)); SQLResult * pRes = pmsg->Get(); Cherchez : void CClientManager::ChangeMonarchLord(CPeer * peer, DWORD dwHandle, TPacketChangeMonarchLord* info) { char szQuery[1024]; snprintf(szQuery, sizeof(szQuery), "SELECT a.name, NOW() FROM player%s AS a, player_index%s AS b WHERE (a.account_id=b.id AND a.id=%u AND b.empire=%u) AND " "(b.pid1=%u OR b.pid2=%u OR b.pid3=%u OR b.pid4=%u)", GetTablePostfix(), GetTablePostfix(), info->dwPID, info->bEmpire, info->dwPID, info->dwPID, info->dwPID, info->dwPID); SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER); Remplacez par : void CClientManager::ChangeMonarchLord(CPeer * peer, DWORD dwHandle, TPacketChangeMonarchLord* info) { char szQuery[1024]; snprintf(szQuery, sizeof(szQuery), "SELECT a.name, NOW() FROM player%s AS a, player_index%s AS b WHERE (a.account_id=b.id AND a.id=%u AND b.empire=%u) AND " "(b.pid1=%u OR b.pid2=%u OR b.pid3=%u OR b.pid4=%u OR b.pid5=%u OR b.pid6=%u OR b.pid7=%u OR b.pid8=%u)", GetTablePostfix(), GetTablePostfix(), info->dwPID, info->bEmpire, info->dwPID, info->dwPID, info->dwPID, info->dwPID, info->dwPID, info->dwPID, info->dwPID, info->dwPID); SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER); Rendez-vous ensuite dans db/src/clientmanagerlogin.cpp Cherchez : void CClientManager::QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p) Ensuite, trouvez les lignes : sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip); char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id); CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info); Remplacez par : sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip); char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, pid6, pid7, pid8, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id); CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info); Cherchez ensuite : void CClientManager::RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg) Trouvez les lignes : if (msg->Get()->uiNumRows == 0) { DWORD account_id = info->pAccountTable->id; char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id); std::auto_ptr pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER)); Et remplacez par : if (msg->Get()->uiNumRows == 0) { DWORD account_id = info->pAccountTable->id; char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, pid6, pid7, pid8, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id); std::auto_ptr pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER)); Maintenant, cherchez : void CClientManager::RESULT_PLAYER_INDEX_CREATE(CPeer * pkPeer, SQLMsg * msg) Trouvez les lignes : char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), info->pAccountTable->id); CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info); Remplacez par : char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, pid6, pid7, pid8, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), info->pAccountTable->id); CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info); /!\ Client /!\ Rendez-vous dans Client/UserInterface/Packet.h Cherchez : PLAYER_PER_ACCOUNT3 = 3, PLAYER_PER_ACCOUNT4 = 4, Remplacez par : PLAYER_PER_ACCOUNT3 = 7, PLAYER_PER_ACCOUNT4 = 8, Rendez-vous maintenant dans Pack/root/introselect.py Cherchez : SLOT_COUNT = 4 Remplacez par : SLOT_COUNT = 8 Cherchez : SLOT_ROTATION = [135.0, 225.0, 315.0, 45.0] Remplacez par : SLOT_ROTATION = [135.0, 180.0, 225.0, 270.0, 315.0, 360.0, 45.0, 90.0] Cherchez : chr.DeleteInstance(0) chr.DeleteInstance(1) chr.DeleteInstance(2) chr.DeleteInstance(3) Remplacez par : chr.DeleteInstance(0) chr.DeleteInstance(1) chr.DeleteInstance(2) chr.DeleteInstance(3) chr.DeleteInstance(4) chr.DeleteInstance(5) chr.DeleteInstance(6) chr.DeleteInstance(7) Cherchez : indexArray = (3, 2, 1, 0) Remplacez par : indexArray = (8, 7, 6, 5, 4, 3, 2, 1, 0) Cherchez : def OnKeyDown(self, key): if 1 == key: self.ExitSelect() if 2 == key: self.SelectSlot(0) if 3 == key: self.SelectSlot(1) if 4 == key: self.SelectSlot(2) if 5 == key: self.SelectSlot(3) Remplacez par : def OnKeyDown(self, key): if 1 == key: self.ExitSelect() if 2 == key: self.SelectSlot(0) if 3 == key: self.SelectSlot(1) if 4 == key: self.SelectSlot(2) if 5 == key: self.SelectSlot(3) if 6 == key: self.SelectSlot(4) if 7 == key: self.SelectSlot(5) if 8 == key: self.SelectSlot(6) if 9 == key: self.SelectSlot(7) /!\ MySQL /!\ Rendez-vous dans Player/Player_index Modifiez : `id` int(11) NOT NULL DEFAULT '0', `pid1` int(11) NOT NULL DEFAULT '0', `pid2` int(11) NOT NULL DEFAULT '0', `pid3` int(11) NOT NULL DEFAULT '0', `pid4` int(11) NOT NULL DEFAULT '0', `empire` tinyint(4) NOT NULL DEFAULT '0', Par : `id` int(11) NOT NULL DEFAULT '0', `pid1` int(11) NOT NULL DEFAULT '0', `pid2` int(11) NOT NULL DEFAULT '0', `pid3` int(11) NOT NULL DEFAULT '0', `pid4` int(11) NOT NULL DEFAULT '0', `pid5` int(11) NOT NULL DEFAULT '0', `pid6` int(11) NOT NULL DEFAULT '0', `pid7` int(11) NOT NULL DEFAULT '0', `pid8` int(11) NOT NULL DEFAULT '0', `empire` tinyint(4) NOT NULL DEFAULT '0', Voilà, vous venez d'ajouter des emplacements supplémentaire sur vos comptes. Aperçu ? Le screen du système comporte les 8 emplacements. Je vous conseil de mettre 6 emplacements pour éviter une "surcharge" des personnages. Bien entendu, si quelqu'un souhaite modifier/corriger les codes, je suis d'accord car je ne suis pas trop calé niveau sources. Source : Turkmmo
  19. Bonjours, Je vous partage une partie d'un système pvp que j'utilise : Coté navicat : Player.player <== editer cette table en cliquand dessus avec le bouton droit et cliquer sur design table ou editer table Puis ajouter comme ici : Maintenant , niveau winscp/filezilla: Aller dans le dossier quest (metin2/share/locale/france/quest) puis crée un fichier pvpadd.quest et remplissez comme sa : quest killadd begin state start begin when kill with npc.is_pc() begin mysql_query("UPDATE player.player SET kills = kills+1 WHERE account_id ='"..pc.get_account_id()"';") end end end enregistrer la quête et maintenant allez éditer le local_list puis ajouter a la fin pvpadd.quest en ajoutant une entrée après votre deniere quête. Ensuite , allez sur putty/virtual box et faite un remake des quest : sh quest.sh ensuite allez ig et reload q Et voila votre système pvp coté server est fait ! Desolé pour les fautes d'orthographe!
  20. Niveau requis : Intermédiaire Temps estimé : 10 minutes Ré-écrit par @Gurgarath Bonjour, Grâce à ce tutoriel, vous pourrez, voir les PV et les PM de votre adversaire lors d'un duel. En contrepartie, il pourra voir les vôtres ! Plus de tricherie possible lors d'un duel grâce à ça Pré-Requis : L'accès au fichier root dépacké Un accès aux files serveur (quêtes) I. Installation (Partie client) II. Installation (Partie serveur -> quêtes) III. Potentielles remarques Source : ElitePvPers Cordialement,
  21. Bonjour, Ce tutoriel-partage va vous aidez à fix le bug de pouvoir switch les bonus d'un équipement déjà équiper et du coup fix l'accumulation des bonus. Rendez vous dans dans le fichier char_item.cpp Cherchez : if (ITEM_COSTUME == item2->GetType()) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ĽÓĽşŔ» şŻ°ćÇŇ Ľö ľř´Â ľĆŔĚĹŰŔÔ´Ď´Ů.")); return false; } if (item2->IsExchanging()) return false; Ajoutez en dessous : if (item2->IsEquipped()) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("no.switch")); return false; } /!\ Attention à bien mettre les tabulations /!\ Dans le même fichier cherchez : case 71052 : // ÁøÀç°æ { // À¯·´, ½Ì°¡Æú, º£Æ®³² ÁøÀç°¡ »ç¿ë±ÝÁö //if (LC_IsEurope() || LC_IsSingapore() || LC_IsVietnam()) //return false; LPITEM item2; if (!IsValidItemPosition(DestCell) || !(item2 = GetItem(DestCell))) return false; if (item2->IsExchanging() == true) return false; if (item2->GetAttributeSetIndex() == -1) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼Ó¼ºÀ» º¯°æÇÒ ¼ö ¾ø´Â ¾ÆÀÌÅÛÀÔ´Ï´Ù.")); return false; } if (item2->ChangeRareAttribute() == true) { char buf[21]; snprintf(buf, sizeof(buf), "%u", item2->GetID()); LogManager::instance().ItemLog(this, item, "CHANGE_RARE_ATTR", buf); item->SetCount(item->GetCount() - 1); } else { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("º¯°æ ½Ãų ¼Ó¼ºÀÌ ¾ø½À´Ï´Ù")); } } Entre "if (item2->GetAttributeSetIndex() == -1)" et "if (item2->ChangeRareAttribute() == true)" Ajoutez ceci : if (item2->IsEquipped()) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("no.switch")); return false; } /!\ Attention à bien mettre les tabulations /!\ Partie source c'est fini ! Ensuite rendez vous ici => /usr/metin2/share/locale/france/locale_string.txt/ Et ajoutez à la fin du fichier : "no.switch"; "Vous ne pouvez pas switch les bonus d'un équipement équiper"; /!\ Attention à bien laisser une ligne vide à la fin du fichier /!\ Source : Just4Metin et moi
  22. Ouvrir Userinterface/instancebase.cpp : if (12010 <= vnum && vnum <= 12049) Ajouté : if (vnum >= 20760 && vnum <= 20959) { __AttachEffect(EFFECT_REFINED+YENI_YILDIRIM_EFEKTI _BLACK); } Ouvrir instancebase.h : EFFECT_BODYARMOR_SPECIAL2, Ajouté : YENI_YILDIRIM_EFEKTI_BLACK, Ouvrir root / playersettingsmodule.py : chrmgr.RegisterEffect(chrmgr.EFFECT_REFINED+20, "Bip01", "D:/ymir work/pc/common/effect/armor/armor-4-2-2.mse") Ajouté : chrmgr.RegisterEffect(chrmgr.EFFECT_REFINED+22, "Bip01", "D:/ymir work/pc/common/effect/armor/armor-5-1.mse") Lien téléchargement : TELECHARGEMENT Ajouter à l' index : *black_new_armor_effects * Source : Turkmmo
  23. Salut tout le monde La quête d'aujourd'hui sert à : -Bloquer l'expérience -Débloquer l'expérience -Vider l'expérience Bloquer l'exp sert à quoi ? Simplement à ne pas gagner d'exp pour pouvoir drop Voilà la quête : quest gestion_exp begin state start begin when 20041.chat."Mon experience ..." begin say_title("Mon experience ...") say("") local z=select("Bloquer mon experience","Débloquer mon experience","Vider mon experience","Fermer") if z==4 then return end if z==1 then say_title("Bloquer mon experience :") if pc.getqf("lock_exp") == 1 then say_reward("Votre experience est déjà bloqué.") else say("Salut ! Si tu veux, je peux bloquer") say("ton experience, pour pouvoir dropper") say("tranquillement.") say("") local lock=select("Bloquer","Ne pas bloquer") say_title("Bloquer mon experience :") if lock==2 then say("Reviens plus tard si tu change d'avis.") end if lock==1 then say("Voilà, votre experience est bloquée !") wait() pc.setqf("lock_exp", 1) pc.setqf("exp_lock", pc.get_exp()) end end end if z==2 then say_title("Débloquer mon experience :") if pc.getqf("lock_exp") == 0 then say_reward("Votre experience n'est pas bloqué.") else say("Alors, tu veux que je débloque") say("ton experience ?") say("") local unlock=select("Oui","Non") if unlock==2 then return end if unlock==1 then say("Voilà, votre experience est débloquée.") wait() pc.setqf("lock_exp", 0) pc.setqf("exp_lock", 0) end end if z==3 then say_title("Vider mon experience :") say("") say("Est tu sûr de vouloir vider ton experience ?") say("Il n'y aura aucun retour possible !") local vider=select("Vider","Fermer") if vider==2 then return end if vider==1 then pc.give_exp2(-pc.get_exp()) end end end when kill begin if pc.getqf("lock_exp") == 1 then if pc.get_exp() > pc.getqf("exp_lock") then pc.give_exp2(-pc.get_exp()) pc.give_exp2(pc.getqf("exp_lock")) else pc.setqf("exp_lock", 0) end end end end end end Note : La quête est sur le passant ivre mais vous pouvez modifier Si vous ne savez pas implanter une quête, suivez ce tutoriel : ici Vous pouvez la partager sur d'autres forums en mettant la source!
  24. ATTENTION Trojan détécté par Microsoft Security sur Windows 10 ! Bonjour, En effectuant des traveaux d'organisation et d'optimisations sur les sources metin2, je suis tombé sur ce travail déjà tout fait en ce qui concerne le lanceur du client. Reboot, l'auteur de ce travail admiratif m'a autorisé de vous le partager et en voici la preuve: Explications: Binary => Endroit où sont placé les exe après la compilation extern => Vous vous en rendrez compte seulement... source => Contient les sources (.cpp et .h) vs_files => Nécessaires à Visual Studio client.sln => Projet Visual Studio (pour compiler) Version Python: 2.2 ENABLE_COSTUME_SYSTEM ENABLE_ENERGY_SYSTEM ENABLE_DRAGON_SOUL_SYSTEM ENABLE_BELT_SYSTEM Cryptopp 5.6.2 boost 1.55 *Normalement, aucune erreur à la génération de la solution. Version de Visual Studio: 2012 ou 2013 Lien (original): sur Zippyshare Source: Metin2Dev Cordialement, Ioio --- Download
  25. Bonjour, aujourd'hui je vous partage une API dont j'en suis l'auteur. Cette API sert pour tout ce qui est sur le client de jeu Dofus 1.29, c'est-à-dire : Les news RSS Inscription via le client de jeu Affichage du captcha qui peut-être regénéré Affichage des réponses de "Comment avez-vous connu Dofus ?" Les cadeaux (les Dofus sur la connexion sont des cadeaux d'abonnement à la base) Le statut des serveurs L'API gère aussi les différentes communautés du jeu, j'entends par la la gestion des langues (FR, EN, DE, ES, IT, PT, NL) qui sont présentes dans le client. Les news RSS Inscription via le client de jeu Les cadeaux Le statut des serveurs Pour utiliser cette API il vous faut avoir composer, composer est un gestionnaire de dépendances qui vous servira pour importer les bibliothèques nécessaire au fonctionnement de l'API. Il vous aussi posséder une base de données MySQL ou MariaBD, ces deux systèmes de base de données sont "identiques". Il vous faut activer la ré-écriture d'url sur votre serveur web. Une documentation est disponible sur le dépôt de l'API. L'API ainsi que les sources sont disponibles sur le dépôt github.com. --- Download