Search the Community

Showing results for tags 'a corriger'.



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
    • Discussions Générales
    • Bureau de la Communauté
    • Espace Gaming
    • 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 - M2SF / M2CF's M2SF
  • M2Project - M2SF / M2CF's Aide / Questions / Support
  • M2Project - M2SF / M2CF's Tutoriels & Partages
  • M2Project - M2SF / M2CF's Suggestions
  • M2Project - M2SF / M2CF'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 617 results

  1. Bonjour, Module Loader est un projet similaire à Adhons les principales différence sont les fonctions et les modules (qui sont plus difficile a trouvé que les addons). Module Loader entièrement gratuit et si vous voulez les sources je peut vous les envoyé Lien : [Hidden Content] Contenu de l'archive : Le dossier "dev" avec quelques fichiers expliquant les fonctions disponibles. Le dossier module avec un fichier loader.swf et un fichier de configuration modules.txt (les modules à charger sont dans ce fichier). Le fichier dofus.dll (pour le menu au clic droit). Le fichier Dofus.exe (j'ai juste oublié de le viré de l'archive). Le fichier loader.swf qui permet de charger modules/loader.swf. Merci, --- Download
  2. Bonsoir, Voici le fameux plugin Essentials ! Ce plugin permet d'instaurer les commandes essentielles a votre serveur. Comme remettre le jour, mettre le beau temps lorsque la pluie tombe et d'autre choses comme ceci. C'est LA BASE des plugins, sans lui, hum votre serveur sera bancale,j'estime que plus de 60% des commandes qu'on écrit sur un serveur provienne de Essentials. Sommaire : I- Installation II- Commandes de Essentials 1- Liste des commandes de triches 2- Liste des commandes d'économie 3- Liste des commandes générales 4- Liste des commandes de modération 5- Liste des commandes de spawn et téléportation Lors de la 2éme partie, les commandes seront triés par ordre alphabétique pour chaque Liste. En dessous de chaque commande et de sa description. J'ai mis la permission concernant la commande a mettre dans votre plugin Permission. I-Installation Télécharger Essentials ici en choisissant la version que vous voulez : Essentials Spigot / Bukkit Vous avez maintenant 4 fichiers jar : - EssentialsChat.jar - EssentialsAntiBuild.jar - EssentialsSpawn.jar - EssentialsProtect.jar - Essentials.jar Mettez ces 4 fichiers dans votre dossier "plugins" de vos FTP de votre serveur. (Vous pouvez ne pas mettre les 4 fichiers, aujourd'hui on va s'interessé seulement a Essentials.jar) Après ceci, redémarrer votre serveur. Normalement c'est bon ! II- Commandes 1- Liste des commandes de triches : /bigtree : Fait apparaître un énorme arbre. essentials.bigtree /break : Casse le bloc que vous regardez. essentials.break /enchant : Enchante l'item que vous tenez en main essentials.enchant /exp : Permet de se donner un certain niveau ou de se rajouter des niveaux. essentials.exp essentials.exp.set (Permet de se donner un niveau précis) essentials.exp.set.others (Donner un niveau précis à d'autres joueurs) essentials.exp.give (Se rajouter le nombre de niveau choisi) essentials.exp.give.others ( Faire de même mais sur d'autre joueurs) essentials.exp.others (Voir le nombre d'exp de d'autres joueurs) /feed : Rempli la barre de faim a 100% essentials.feed essentials.feed.others (Permet de nourrir d'autre joueur) /firework : Créer des feu d'artifices précis. Syntaxe entiére : color: fade:] shape: effect:[,] Exemples: /firework color:red /firework color:red shape:star effect:trail (Feu d'artifice rouge, forme d'étoile avec l'effet trainée) /firework color:red,blue,green fade:yellow (Rouge,bleu,vert, jaune en couleur "inférieur") essentials.firework essentials.firework.fire (Faire une copie des fusées de feu d'artifice dans a main) /fly : Autorise le joueur choisi à voler. essentials.fly essentials.fly.others (Permet de mettre le /fly à d'autre joueurs) /gamemode : Change le type de jeu du joueur choisie essentials.gamemode essentials.gamemode.others (Permet de changer le type du jeu à un autre joueur. /give : Permet de donner des objets à un joueur. essentials.give /god : Permet de se rendre invincible/immortel. essentials.god essentials.god.others (Permet de mettre le /god à d'autre joueurs.) /hat : Permet d'avoir un bloc comme chapeau. essentials.hat /heal : Permet de remettre son état de santé à 100%. essentials.heal essentials.heal.others (Permet de /heal les autres joueurs.) /i : Premet de se donner des objets à soi-même. essentials.item /kit : Fait apparaître un kit d'objet prédéfinit sur le sol. essentials.kit essentials.kit.* (Permet d'accéder a tout les kit) essentials.kit.others (Permet de mettre un kit à un autre joueur.) /more : Rempli au maximum l'item tenu en main. essentials.more /ptime : Change le temps du jeu pour un joueur. essentials.ptime essentials.ptime.others (Changer le temps de jeu pour d'autres joueurs) /repair : Répare l'objet en main, ou de tout les objets possédés. essentials.repair essentials.repair.armor (Permet de réparer les armures) essentials.repair.enchanted (Permet de réparer les objets enchantés) /speed : Augmenter sa vitesse de déplacement. essentials.speed essentials.speed.others (Changer la vitesse à d'autres joueurs) essentials.speed.bypass ( Dépasser la limite de vitesse marqué dans le config.yml) /time : Change le temps du serveurs pour tout les joueurs pour un monde ou tous. essentials.time essentials.time.set (Permet de changer le temps du monde) /tree : Permet de faire apparaître un arbre. essentials.tree /ul : Permet de placer un objet en illimité. essentials.unlimited essentials.unlimited.others (Permet de placer un objet en illimité à un autre personne.) /wb : Permet d'ouvrir la fenêtre d'un établi. (sans établi à proximité) essentials.workbench 2- Liste des commandes d'économie : /balance : Affiche l'argent actuellement possédé par un joueur. essentials.balance essentials.balance.others (Permet de voir l'argent possédé par les autres joueurs. /balancetop : Affiches les comptes possédant le plus d'argent. essentials.balancetop /eco : Modifie le montant total du compte d'un joueur. essentials.eco essentials.eco.loan (Donner de l'argent illimité à un joueur) /pay : Paye un joueur du montant souhaité. essentials.pay /sell : Vend un nombre d'objet souhaité. essentials.sell /setworth : Assigne un prix à un objet. essentials.setworth /worth : Affich le prix d'un objet. essentials.worth 3- Liste des commandes générale : /afk : Vous mets en statut "Away From Keyboard" (Pas devant son clavier) essentials.afk essentials.afk.kickexempt (Exempter de l'auto-Kick après le AFK) essentials.afk.others (Mettre les autres joueurs AFK) /book : Permet de changer le contenu d'un livre déjà signé. essentials.book essentials.book.author (Permet de changer l'auteur du livre) essentials.book.title (Permet de changer le titre du livre) /compass : Affiche la direction dans laquelle vous regardez en degrés et avec les points cardinaux. essentials.compass /depth : Affiche la hauteur du personnage par rapport au niveau de la mer. essentials.depth /getpos : Affiche les coordonnés X, Y, Z, Y, Yaw et Pitch. essentials.getpos essentials.getpos.others (Connaitre la position d'un autre joueur) /help : Affiche la liste des commandes disponibles essentials.help /helpop : Envoie une demande privée à tous les Opérateurs (op) essentials.helpop essentials.helpop.receive (Voir les message Helpop) /ignore : Ignore certains joueurs essentials.ignore /info : Attribue la fonction "info" à l'objet en main ; permet d'avoir des informations sur le bloc sélectionné. essentials.info /list : Permet d'avoir la liste des joueur(s) connecté(s) essentials.list /mail : Envoie un mail intra-joueurs , intra-serveur , même quand ceux-ci sont déconnectés essentials.mail essentials.mail.send (Envoyer un mail) /me : Décrit une action dans le contexte du joueur. (Exemple : /me veut du pain. Pseudo veut du pain.) essentials.me /motd : Affiche le Message Of The Day : message de connexion des joueurs. essentials.motd /msg : Permet d'écrire un message privé exemple : /msg [le nom de la personne] [votre message] essentials.msg /nick : Donne un pseudonyme à un joueur. essentials.nick essentials.nick.others (Permet de mettre un surnom à un autre joueur) /powertool : Assigne une commande à l'objet tenu dans la main. essentials.powertool /r : Permet de répondre à un mail. essentials.msg /realname : Permet de voir le nom original du joueur (sans le /nick). essentials.realname /recipe : Voir la recette pour fabriquer un objet. essentials.recipe /rules : Voir les régles du serveur. essentials.rules /seen : Voir des informations de connection d'un joueur. essentials.seen essentials.seen.banreason (Voir la raison du bannissement de ce joueur) essentials.seen.extra (Voir l'IP du joueur et le lieu de sa derniére connection) /spawner : Changer le type de monstre d'un générateur de monstre. essentials.spawner essentials.spawner.[mob] (Accés aux changements à certains monstres) essentials.spawner.* (Tout type de générateur de monstre autorisé) /suicide : Permet de ce "suicider". essentials.suicide /whois : Donne des informations sur le joueur (adresse IP, etc). essentials.whois 4- Liste des commandes de modération : /antioch : Place un bloc de TNT près de vous. essentials.antioch /backup : Met en route la fonction backup comme elle est défini dans le config.yml. essentials.backup /ban : Bannir un joueur. essentials.ban essentials.ban.notify (Permet de voir lorsque un joueur est banni) /banip : Bannir l'IP d'un joueur. essentials.banip /broadcast : Affiche le message spécifié a l'ensemble des joueurs. essentials.broadcast /burn : Met en feu le joueur spécifié. essentials.burn /ci : Vide l'inventaire d'un joueur. essentials.clearinventory essentials.clearinventory.others (Vider l'inventaire des autres) /deljail : Permet de libérer un joueur d'une prison. essentials.deljail /enderchest : Permet de voir le contenu d'un coffre de l'Ender. essentials.enderchest essentials.enderchest.others (Voir le contenu d'un coffre de l'Ender à un autre joueur) essentials.enderchest.modify (Modifier le coffre de l'Ender d'un autre joueur) /essentials : Permet de recharger Essentials. essentials.essentials /ext : Eteint le feu. essentials.ext /fireball : Lance une boule de feu mélangée avec de la neige. essentials.fireball /jail : Permet de mettre un joueur en prison. essentials.jail /kick : Permet d'expulser un joueur. essentials.kick essentials.kick.notify (Permet de voir lorsqu'un joueur est kické) /kickall : Permet d'expulser tout les joueurs du serveur sauf vous. essentials.kickall /kill : Permet de vous tuer ou de tuer un autre joueur. essentials.kill /butcher : Permet de tuer tout les monstres essentials.killall /lightning : Permet de lancer un éclair. essentials.lightning essentials.lightning.others (Permet de lancer un éclair sur un joueur) /mute : Permet de couper la parole à un joueur. essentials.mute /nuke : Fait apparaître de la TNT. Beaucoup. essentials.nuke /ping : Permet de savoir si Essentials fonctionne correctement en affichant "Pong !". essentials.ping /remove : Supprime les entités dans le rayon choisi. Exemple : /remove items|flèches|bateaux|minecarts|xp|tableaux rayon (Les | vous montrent juste les différentes options que vous pouvez prendre) essentials.remove /setjail : Positionner une prison à l'endroit où vous êtes. essentials.setjail /socialspy : Permet de voir les messages privés des joueurs (entre eux) et les mails. Voir toutes les discussions de tout le monde. essentials.socialspy /spawnmob [monstre] [nombre] : Fait apparaître des monstres. essentials.spawnmob essentials.spawnmob.mob (Autoriser le spawn d'un monstre spécifique) essentials.spawnmob.* (Autoriser le spawn de tout les monstres) /sudo : Forcer un joueur à faire une certaine commande. Exemple : /sudo Kraken pay Jean-Kevin 1000 ( Kraken enverra directement 1000 sous à Jean-Kevin) essentials.sudo essentials.sudo.exempt (Empêcher d'être sudo par certains joueurs) /tempban : Permet de bannir un joueur temporairement. essentials.tempban /unban : Permet de débannir un joueur. essentials.unban /unbanip : Permet de débannir une IP. essentials.unbanip /vanish : Vous rends totalement invisible. essentials.vanish essentials.vanish.see (Voir un joueur qui est invisible) essentials.list.hidden (Voir les joueurs dans les commandes genre /list, /whois) essentials.teleport.hidden (Vous permet la téléportation avec un joueur invisible) essentials.vanish.effect (Avoir le même effet que la potion d'invisibilité) /weather : Permet de mettre la pluie ou le beau temps (sun ou storm). essentials.weather 5- Liste des commandes de spawn et téléportation : /spawn : Vous téléporte au point de spawn. essentials.spawn /setspawn : Permet de définir un nouveau spawn. essentials.setspawn /back : Permet de se téléporter à l'endroit de sa mort. essentials.back essentials.back.ondeath (Pour revenir au lieu de sa mort) /delhome : Supprime sa maison. essentials.delhome essentials.delhome.others (Supprimer les home des autres joueurs.) /delwarp : Supprime un warp. essentials.delwarp /home : Permet de se téléporter a sa maison. essentials.home essentials.home.others (Se téléporter aux homes des autres joueurs) /j : Permet d'atteindre le plus haut bloc au dessus de vous. essentials.jump /sethome : Définir votre maison. essentials.sethome essentials.sethome.others (Changer les maisons des autres) essentials.sethome.multiple (Autoriser plusieurs maisons aux joueurs) essentials.sethome.multiple.unlimited (Autoriser une infinité de maison à chaque joueur) essentials.sethome.multiple.[set] (Mettre un nombre définie de home a chaque joueur) /setwarp : Permet de créer un point de téléportation. essentials.setwarp /tp [pseudo] : Permet de se téléporter à un joueur. essentials.tp essentials.tp.others (Téléporter un joueur à un autre joueur) /tphere [pseudo] : Permet de téléporter quelqu'un sur soi. essentials.tphere /tppos : Se téléporter a certaines coordonnées. essentials.tppos /warp : Permet de se téléporter à un warp. essentials.warp essentials.warp.list (Voir la liste des warp) essentials.warp.* (Pouvoir utiliser tout les warps) Voila, j'ai enfin fini après 1h30 pour écrire ceci. (Pleins de tableaux permette de voir toutes les commandes, mais jamais par une liste comme ici.) :tounge: Je vous souhaite une excellente journée/soirée a vous.
  3. 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
  4. Salut à tous, voici une petite API pour les votes sur RPG paradize. En gros elle fait : Récupère le captcha de la page de vote. Envoi le formulaire de vote. Regarde si le vote a été accepté et retourne true ou false. Donc au final plus besoin de faire une redirection vers RPG Paradize, et seul les bon votes seront comptés, et tout ça, très simplement ! RpgApi.php : ICI Exemple : ICI L'utilisation d'un tel système est relativement lourd, il est donc préférable de ne pas trop charger la page de vote. --- Download
  5. 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
  6. 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
  7. 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!
  8. 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,
  9. 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
  10. 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!
  11. 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
  12. Salut, Voici un Tuto pour changer les News ( Voir Pièce Jointe ).Dans un Premiers Temps, Télécharger ceci : News RSSEnsuite,Ouvrez le Dossier News RssOuvrez Ensuite Le Dossier RSSEnsuite Ouvrez config.phpFaites comme ceci : <?php define("DB_HOST","IP DE LA DB (PAR DÉFAUT 127.0.0.1)"); define("DB_LOGIN","root"); define("DB_PASS","MOT DE PASSE SI VOUS EN AVEZ UN"); define("DB_BDD","news");?> Enregistrez Puis fermezMaintenant Ouvrez RSS.PHPEt Remplissez Comme Ceci : <?php echo '<?xml version="1.0" encoding="utf-8"?>' ?>NOM DE VORE SERVEURURL DE VORE SERVEUR DESCRIPTION DE VORE SERVEUR<?php require "config.php"; mysql_connect(DB_HOST,DB_LOGIN,DB_PASS); mysql_select_db(DB_BDD); mysql_query("SET NAMES UTF8"); $sql="SELECT * FROM rss ORDER BY id DESC LIMIT 0, 6"; $req = mysql_query($sql) or die('Erreur SQL ! '.$sql.' '.mysql_error()); while($data=mysql_fetch_assoc($req)){ echo "\n"; echo "{$data["id"]}"; echo "{$data["title"]}\n"; echo "URL DE VORE SERVEUR\n"; echo "{$data["icon"]}\n"; echo "".date("D, d M Y H:i:s",strtotime($data["date"]))." +0200\n"; echo "\n"; }?> Enregistrez Puis FermezCopiez Rss.php et config.phpCollez-les dans votre dossier lang !- Ensuite, Ouvrez Sothink SWF QuickerAllez dans votre Dossier SWF et choisissez lang_fr_786Faites CTRL+F et dans la recherche tappez RSS_LINKVous devriez avoir une ligne ressemblant à ceci : Donc Replacez Comme Cela : Ensuite, Faites Export Et Fermer votre Sohtink SWF QuickerMaintenant, Retournez dans votre dossier de News RSS et ouvrez cette fois-ci le dossier News RSS ScriptOuvrez config.phpPuis Remplissez :<?php define("DB_HOST","IP DE LA DB (PAR DÉFAUT 127.0.0.1)"); define("DB_LOGIN","root"); define("DB_PASS","MOT DE PASSE SI VOUS EN AVEZ UN"); define("DB_BDD","news");?> Enregistrez Puis FermezEnsuite Copiez le dossier News RSS Script et collez-le dans votre dossier “www” De WampMaintenant Lancez Navicat, Créez une New Database Que vous appellerez "news"Une fois fait, executez le fichier sql "rss.sql" Qui se trouve dans le Dossier "RSS"Ajouter Une News :Ouvrez Navicat puis Double-clique sur NewsOuvrez la Table rsset Remplissez Comme ceci : Voici la liste des Icons : à écrire dans la colone Icon => Icon afficher Tuto By Icer Un Petit Merci ferai plaisir.
  13. Salut. Ce bouton, vous a jamais soûlé car il marche pas ? : Moi si. Je partage donc vite fait le debug que je fais je ne sais quand. Dans votre intrologin.py: Dans : class LoginWindow(ui.ScriptWindow): Trouvez : def __init__(self, stream): Ajoutez dans la fonction : self.HakConnexionStop = False Allez dans la fonction Close qui se trouve un petit peu plus bas et ajoutez : self.HakConnexionStop = None Cherchez ensuite : def OnConnectFailure(self): Vous aurez dans la fonction : if self.isNowCountDown: return Ajoutez en dessous : if self.HakConnexionStop: self.HakConnexionStop = False return Cherchez : def Connect(self, id, pwd): Vous trouverez : self.stream.popupWindow.Open(localeInfo.LOGIN_CONNETING, localeInfo.UI_CANCEL) Changez cette ligne en : self.stream.popupWindow.Open(localeInfo.LOGIN_CONNETING, self.HakOnConnexionSTOP, localeInfo.UI_CANCEL) Après la fonction, ajoutez : def HakOnConnexionSTOP(self): self.HakConnexionStop = True self.stream.popupWindow.Close() Vous n'avez plus qu'à repack et le bouton marchera. Quand on clique sur le bouton, je n'efface pas les inputs comme pouvait le faire l'erreur de connexion etc. Si c'est nécessaire je peux vous dire comment faire. Code original = Frozen, forum étrangé.
  14. SharkEmu est un émulateur codé en C# par Bouh2. Il à été repris par la Sharkteam, mais est actuellement stoppé. Il utilise peux de ram (moins de 900mo). Un tutoriel complet est inclu, ainsi qu'un CMS. Télécharger SharkEmu v0.8.2.2.rar et Database RC3.rar. Téléchargement : ICI 2 - Avancement : POST ORIGINALE Bonjour à tous, Aujourd'hui je vous présente mon projet longuement développé et qui est déjà publique. SharkEmu développé en C# est un émulateur Dofus stable et déjà très complet. Je le développe depuis maintenant 6 mois à peu près et il avance pourtant assez vite. SharkEmu a le privilège d'être entièrement Opensource sous license GNU. Cela signifie que les sources sont disponibles et publiques pour tout le monde et que c'est totalement gratuit ! SharkEmu est axé sur la personnalisation et la simplicité. Cela signifie que l'emulateur est prêt en main et permet en 10 minutes de créer son serveur, mais aussi que il est prévu pour être entièrement modifiable et modeler le serveur à votre guise. Ce qui permet de créer un gameplay tout à fait inédit et d'ajouter du contenu complétement personnaliser. L'avancé de SharkEmu (5.02.10) A l'heure où j'écris ces lignes, l'émulateur est en version 0.6.3.0 car je n'est peut être pas modifier ce post. Voici les fonctions majeurs disponibles : -Gestion de connexion -Gestion des comptes/ et joueurs -Gestion du monde et des maps -Gestion de transfert des données entre joueurs (affichage, déplacement, chat ...) -Gestion des inventaires -Gestion des items -Gestion des 90% effets des items -Gestion des drops d'items -Gestion des combats inter-joueurs (PvP) -Gestion des abandons -Gestion des sorts principaux (voir liste ci-dessous) -Gestion des buffs -Gestion des scores de fin de combat (Kamas & Experience) -Gestion des niveaux -Gestion de l'expérience -Gestion des statistiques -Gestion de commandes (voir ci-dessous) -Gestion des Pnjs -Gestion des Pnj-vendeur -Gestion d'achat/vente d'objet -Gestion d'actions Pnj Spéciales (téléportation, dons de kamas...) Effet sorts implantés (Tiré des SpellActions -> Game/SpellAction.cs) : InflictDamage RestoreHealth StolenLife Push ChangeCase Buff Les fonctions majeurs qui seront implantés : -Créatures & Intelligence artificiel -Quêtes -Métiers La base de donnée est elle aussi bien remplie (merci à Ancestra) -Maps : 4000 -Items : 100% -Monstres : 1200 -Pnj : 600 -Spell : 100% L'emulateur comprend quelques commandes de base, il se va de soit que l'on peut en ajouter à sa guise info Information sur l'état du serveur pos Position actuelle du personnage go Se téléporte sur la map et case choisi gopos Se téléporte selon les coordonnés choisis avec option de map intérieur ou non help Affiche l'aide d'une commande command Affiche la liste des commandes world Envois un message à tout le monde start Vous téléporte au point de départ goname Vous téléporte sur le joueur namego Téléporte le joueur à vous save Sauvegarde les informations du personnages saveworld Sauvegarde chaque joueur shutdown Arrête le serveur après le temps donné; "shutdown stop" pour annuler morph Change le skin du joueur additem Ajoute un objet à la cible; cible : %target%, %me% ou le nom d'un joueur fillmap Rempli une map avec un item target Active le mode target settarget Défini la cible; cible : %target%, %me% ou le nom d'un joueur Dofus 2.0 Le noyau de l'emulateur sera repris pour faire une version approprié pour Dofus 2.0. Cette version ne verra pas le jour avant la release 1.0 Anecdote La première fois que j'ai entendu d'émulateur c'était sur britania 3 avec DofusEmu de Elxior dont j'ai participer à la bêta. J'ai commencer à programmer en C# cela fait tout juste 1 an. J'ai développé sur le cheat WoW, créer 2 programmes tiers pour le même jeu et beaucoup contribuer au cheat wow français (notamment en developpement de cheat). Avant les vacances d'été 2009, on m'a proposé de reprendre les sources d'Elxior en Team et de faire un premier émulateur dofus. Mi Juillet / Aout j'ai commencer SharkEmu, car je voyais que le projet n'avancer pas et que les sources était irrécupérable, tout d'abords en Team de 4 (je peux citer Air5 et Antique) puis fin été j'ai continuer le développement seul. Je décide alors de faire un émulateur Opensource. Projet : ICI Je cherche des codeurs qui serais prêt à m'aider pour commenter le code et le documenter ainsi que coder d'autres commandes et sorts. De plus chaque bug reporté contribue au développement de SharkEmu et m'aide énormément alors n'hésitez pas. Pensez à faire un don car c'est ma seule source de contribution de cet énorme projet. J'espère que vous soutiendrez mon projet. Merci de votre lecture, et merci d'utiliser SharkEmu. --- Download
  15. Salut à tous , je vais vous expliquer comment mettre 4 pages d'inventaire. Tout d'abord, allez ici : mainline_released/mainline_sg/Srcs/Server/common puis ouvrez length.h Ensuite chercher : INVENTORY_MAX_NUM = 90, et remplacez par INVENTORY_MAX_NUM = 180, Ensuite, toujours dans le répertoire : mainline_released/mainline_sg/Srcs/Server/common 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 completez comme ici : static CGrid s_grid1(5, INVENTORY_MAX_NUM/5 / 2); // inven page 1 static CGrid s_grid2(5, INVENTORY_MAX_NUM/5 / 2); // inven page 2 static CGrid s_grid3(5, INVENTORY_MAX_NUM/5 / 2); // inven page 3 static CGrid s_grid4(5, INVENTORY_MAX_NUM/5 / 2); // inven page 4 s_grid1.Clear(); s_grid2.Clear(); s_grid3.Clear(); s_grid4.Clear(); Et pour finir la partie serveur , remplacez les lignes ci-dessous for (i = 0; i < INVENTORY_MAX_NUM / 4; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid1.Put(i, 1, item->GetSize()); } for (i = INVENTORY_MAX_NUM / 4; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid2.Put(i - INVENTORY_MAX_NUM / 4, 1, item->GetSize()); } for (i = INVENTORY_MAX_NUM / 4; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid3.Put(i - INVENTORY_MAX_NUM / 4, 1, item->GetSize()); } for (i = INVENTORY_MAX_NUM / 4; i < INVENTORY_MAX_NUM; ++i) { if (!(item = victim->GetInventoryItem(i))) continue; s_grid4.Put(i - INVENTORY_MAX_NUM / 4, 1, item->GetSize()); } PARTIE SERVEUR TERMINÉ Passons maintenant Partie client. Pour commencer , allez ici : mainline_released/mainline_sg/Srcs/Client/Userinterface et ouvrez GameType.h Cherchez const DWORD c_Inventory_Page_Count = 2; et remplacez par const DWORD c_Inventory_Page_Count = 4; Ouvrez ensuite inventorywindow.py et chercher EQUIPMENT_START_INDEX = 90 que vous remplacez par EQUIPMENT_START_INDEX = 180 Ensuite, hé oui c'est toujours pas terminé ouvrez uiinventory.py et chercher 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)) 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É Vous pouvez tout recompiler et la partie source est terminé Je vous partage mon inventorywindow.py qui se trouve dans locale 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 terminer 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 Voilà, tout est terminé , vous pouvez tout recompiler, repacker et regarder le résultat. Voila, tutoriel terminé, desolé pour les quelques fautes d'orthographes, bonne chance pour tout faire Source : M2Dev DEBUG ---
  16. 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
  17. Bonjour, Granny 2.9.12 Granny 2.11.8 Granny 2.8.41 Cordialement, History. --- Download
  18. 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
  19. 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
  20. 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 !
  21. 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
  22. 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
  23. 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.
  24. 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.
  25. -------------------------------------------------------------------- 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]