Forum du MMorpg Evol Online |
| | [Tuto] Allez plus loin dans le codage | |
| | Auteur | Message |
---|
Valkyrion
Nombre de messages : 143 Age : 30 Affectation : [Admin] Date d'inscription : 03/08/2009
| Sujet: [Tuto] Allez plus loin dans le codage Sam 8 Aoû - 18:06 | |
| Lien : http://www.eathena.ws/board/index.php?showtopic=203728&pid=1118072&st=0&#entry1118072
Introduction.
Pourquoi ce tutoriel ? Il en existe déjà des forts bons et très documentés... D'ailleurs, dans ce tuto, vous ne trouverez pas de "trucs" pour programmer vos NPC, pas (ou peu) d'explication sur le langage ou sur les fonctions. Rien de "technique". Les exemples seront datés, basiques, old school... Alors que va-t-on trouver dans ce tuto ? Et bien, j'ai constaté dans la communauté de scripteurs RO qu'il y avait 2 types de scripteurs. Les "techniques" et les "rolistes". Un scripteur "technique" prend son pied à "pisser du code", à coder des fonctions, des NPC d'un très haut niveau de complexité niveau code/effets produits ingame. Son niveau de connaissance du "langage" NPC, voire des sources eathena est très bon. Le scripteurs technique est généralement un "scientifique", un "ingénieur". Exemple de script "technique" : les antibot. Un scripteur "roliste" prend son pied à "fabriquer un histoire", à faire des quêtes, des events NPC. Pour lui le code n'est qu'un "moyen" et il s'en fiche s'il n'est pas super propre (tant qu'il n'y a pas d'abus possible ^^) ou super optimisé. Exemple de script "roliste" : les "quêtes à xp" de Gravity.
Il existe plein de tuto qui abordent l'aspect "technique" du script de NPC. Mais moi, je suis un scripteur "roliste" et mes joueurs jouent à un MMORPG. Je me dois de les immerger le plus possible dans mon monde. Alors, je vais essayer de vous lister les manières d'y arriver aussi.
Pour en finir avec : CODE if (countitem(666666) > 99){goto L_hat;} mes "[Hatmaker]"; mes "Rapporte moi 100 trukbidul et je te donnerais un hat Machintruk"; close;
L_hat: delitem 666666, 100; getitem 777777, 1; mes "[Hatmaker]"; mes "Tiens, ton hat"; close;
I- J'apprends, j'apprends.
Tout d'abord, un minimum de "bases" sont nécessaires. Référez-vous au tutoriel de Vince : http://www.roeathena.fr/index.php?showtopic=3780 Et y'en a un aussi sur eathena.ws Référez-vous au /doc/script_commands.txt Ayez un serveur local/de test et éclatez-vous à faire quelques scripts "bidons" ou des tutos, pour maîtriser la bête. Avant de poursuivre, voilà ce que vous devez connaître impérativement : - Déclarer un npc et le placer ingame - Connaître la syntaxe d'affichages des textes et menu* (mes "..."; , next;, menu "choix1",-,"choix2",L_choix2;) - Connaître le fonctionnement des label et goto* - Connaître les différents types de variables et leur "portée". - Connaître la syntaxe des boucles conditionnelles ( if{...}else{...} ) - Avoir de l'imagination - Avoir le script_commands.txt d'ouvert en permanence.
*: ouais, menu, goto, label. J'suis vieux jeu et y'a rien de mieux pour commencer. Les switch, l'aegis et le code "propre", c'est pour plus tard/si vous voulez.
II- Planification
Malheureux, que faîtes-vous avec le blocnote++ déjà ouvert !?! On se calme, on réfléchit avant de se lancer. Déjà, savoir où l'on va.
1°) Pour qui ? Pourquoi ?
On veut faire une quête. Oui, mais de quel type ? Si c'est une quête événementielle : elle ne restera pas. On note donc dans un coin : "Penser à nettoyer les variables à la fin". La quête aura-t-elle un impact sur le jeu ? Débloque-t-elle/débloquera-t-elle d'autres quêtes ou d'autre NPC ? Si oui, une variable joueur/account permanente sera nécessaire. La quête peut-elle être recommencée (exemple : quête de hat) ? Il faudra donc remettre une variable à 0. La quête concerne-t-elle un joueur ou un account ? Le type de variable changera en fonction. La quête sera-t-elle participative (exemple : dons pour ouvrir Rachel Sanctuary) ? Il faudra donc des variables serveurs.
2°)Sadisme lvl ? Maintenant, il faut réfléchir à la "difficulté" et aux récompenses. C'est assez difficile à évaluer et va dépendre de votre serveur (rates, % de nolife, de "prodeRO"). Les gens ont un certains masochisme et aime qu'on leur résiste. Mais attention de ne pas trop en faire ! Un quête où il faut ramener 10000 item MvP sur un lowrate sera trop frustrante. Il faut adapter en fonction de la "récompense" (xp ou objet). Il est évident qu'une quête offrant des Sunglasse[1] ou des Victory Wings devra être plus difficile qu'une quête permettant d'obtenir un White Ribbon. En gros, plus l'impact en jeu est grand (xp ou item "utile", surtout en PvP/WoE), plus la difficulté sera grande. Attention, certains hats/wings sont très beaux et très demandés par les joueurs même s'ils sont "inutiles". Il convient donc d'augmenter la difficulté en fonction de l'attente et de la "beauté" si ces items sont concernés.
3°) Scénario Le type de quête, sa récompense et sa difficulté (approximative) ont été défini. Maintenant, il convient d'imaginer le déroulement. En général on a une petite idée. La plupart du temps, une quête comprend les éléments suivant : - Accroche de la quête (exemple : le début de la Gaebolg, où l'on "bump" dans un gosse). - Exposé de la situation/quête. Où l'on expose le "problème", les difficultés (ex: liste d'item à ramener, énigme, ect). - Rassemblements des éléments pour résoudre le problème (rassemblement d'item, résolution d'énigmes, recherche de NPC, killage de mobs,...) - Résolution de problème (facultatif : - Trahison, nouveau(x) problème(s), rebondissement(s)) - Récompense.
Un des "erreurs" qui est souvent commise est de négliger l'accroche. Bien souvent, un NPC nous expose de but en blanc ce qu'il veut. C'est très artificiel et n'offre pas d'intérêt dans l'immersion. Il faut titiller la curiosité des joueurs et les amener à s'intéresser à l'histoire, même pour fabriquer un banal hat. Pourquoi ? Parce que c'est plus fun.
III- NPC
ça y est, on a une idée assez précise de ce qu'on veut faire, avec un scénario qui tient la route. On peut donc commencer à coder les NPC. C'est bon là, vous pouvez ouvrir le notepad++. On peut coder. Je vais par revenir sur "comment" (y'a les autres tuto pour ça). On va maintenant essayer de rendre un peu plus "vivants" et "réalistes" les NPC.
1°) Vous êtes qui, vous ?
Je ne sais pas vous, mais quand je m'adresse à quelqu'un croisé dans une rue, à part s'il s'agit d'un marchand, il ne me connait pas, ne me doit rien et n'a rien à fiche de ce que je veux. Et il va pas pleurer sur ses problèmes devant un inconnu. C'est pour ça que j'ai parlé "d'accroche" au début. Il faut que le NPC discute un peu avec le joueur, voir le "teste", avant de lui révéler la quête. Vous pouvez très bien engager une discussion politique,militaire, générale, etc sur un sujet qui amènera à un "test" que doit réussir le joueur pour progresser. Exemples : - Un jeune garde trouve la politique du palais trop "molle". Vous êtes d'accord => Ils vous en dit plus sur un parti de "mécontents" => quête. - Une vieille commère se plaint du temps tout détraqué à cause du nouveau mage installé non loin. Faudrait que quelqu'un aille voir, non ? => quête. - Un futur-Sage a égaré ses notes pour sa thèse. En l'aidant, on gagne sa confiance et il devient bavard au sujet de son projet top-secret => quête. - Une fillette faisant l'école buissonnière veut jouer avec vous. Si oui et que vous la battez, elle vous confie un secret => quête. J'pense que vous avez compris le truc : faire en sorte que le NPC apprécie et/ou oriente le joueur vers le vrai début de la quête.
Le fait de devoir gagner la confiance/prouver sa valeur aux NPC doit se poursuivre tout au long de la quête. Lors des aller-retour ou envoie vers d'autre NPC, n'hésitez pas à mettre des input @qui$; demandant "Et vous venez de la part de qui ?";
Lors des dialogues, utilisez strcharinfo(0) quand le NPC "accepte" le joueurs : cela montre plus d'intimité. De même, le ton peut changer une fois un "service" rendu.
2°) Tons et façons de "parler".
Tiens, parlons-en justement du ton. C'est ce qui rend le NPC original et vivant. Le ton dépend de la "proximité" du NPC avec le joueur (cf ci-dessus) et de son "statut socio-culturel". En effet, un gamin des rues de Morroc ne parle pas comme une Prêtresse de Freya ou comme une grand-mère acariâtre ou un vieux paysan méfiant. C'est le ton qui rend vraiment le personnage vivant, qui permet de faire penser au joueur "Ouais, là je discute avec un vrai Paladin" ou "Je le sens pas, ce Jaffar Coeurnoir de Vilfélon..."
Pour faire varier le ton, il faut d'abord définir le registre(niveau) de langue à employer. Généralement, on en discerne trois : - Le registre familier : c'est celui qu'on emploie entre 2 personne qui se connaissent bien et s'apprécie. Il n'est pas formel (pas de vouvoiement), les mots sont simples, le vocabulaire pauvre (répétitions), le langage est souvent imagé. Les phrases peuvent être "fausses" (ex : "J'ai pas fait ça !" au lieu de "Je n'ai pas fait ça !"). Idéal pour faire s'exprimer les gens du commun, de la rue, les pauvres... - Le registre standard : c'est le ton neutre, poli mais sans fioriture. Employez par 2 personnes venant de se rencontrer (et de même niveau social), par exemple. Cela donne un ton très neutre (et donc, potentiellement moins "implicatif" pour le joueurs). Parfait pour les gens "moyens", pour donner des informations (panneau, livres pour non-spécialiste/érudit), pour les "fonctionnaires" (Gardes, par exemple). - Le registre soutenu : c'est le plus haut "niveau" de langue. Les phrases sont complexes, avec un vocabulaire riche et de figures de style. Il est très précis. Le vouvoiement est généralement employé (mais pas forcement). La grammaire est rigoureuse. Idéal pour faire parler les gens "éduqués" (Sage, nobles, ...)
On peut "forcer le trait" dans les 2 sens pour ces registres de langue, pour plus d'effet (caricature, stéréotype, par exemple) : - Le registre argotique : permet de pousser la familiarité, de caricaturer. Vocabulaire vulgaire ou agressif, phrases courtes et incisives. Idéal pour les Rogues et pour caser de belles insultes ^^ - Le registre ampoulé : permet de pousser le soutenu à fond, donnant des phrases bien lourdes et pompeuses. Idéal si vous voulez caricaturez un bourgeois précieux ou un noble hautain.
Vouvoiement ou tutoiement ? La langue française permet de faire cette distinction, il serait bête de s'en priver ! Dans un registre familier, le tutoiement semble de rigueur (mais pas toujours). Pour les autres registres, c'est en fonction des "relations" entre le joueurs et le NPC. Généralement, le vouvoiement convient le mieux (oui, on devient rarement super-pote avec un NPC). Le vouvoiement peut être utilisé dans le registre familier, pour faire ressortir certains sentiments envers le joueur. Exemples : - "Si votre Grandeur veut bien s'donner la peine de bouger ses miches..." (mépris ironique) - "Houlà, z'êtes vraiment un bourrin vous !" (admiration... ou moquerie ^^). A l'inverse le tutoiement peut être utilisé en registre soutenu (ça fait très bobo): - "Tu vois là, c'est à la finesse du marbre d'Aldebaran qu'on reconnait le génie du sculpteur..." - strcharinfo(0)+" ! Je te fais la bise ! Que deviens-tu, mon choux ? Toujours à courir après la fortune et la gloire ?"
Il existe encore un autre ton possible : le registre "enfantin". Et oui, pour faire s'exprimer les gosses (c'est fou ce qu'on croise comme gosses dans RO). Ce ton est difficile à décrire et change selon le sexe/personnalité à donner au NPC. Le vocabulaire et la grammaire sont simples, avec des mots "enfantin".
2°)Apparence (aka le sprite)
Venons-en à l'apparence. Oui, le sprite a de l'importance et doit être coordonnée au ton choisi (ou pas, voir plus loin). C'est la première chose que voit un joueur, sa première impression du NPC et donc, c'est vital. Le joueur doit pouvoir identifier à qui il s'adresse: jeune, vieux, prêtre, voleur, riche, pauvre, ect. Il existe beaucoup de sprites différents pour les NPC (sans parler des sprites mob et des custom), aussi il faut en choisir un qui "cadre" avec le personnage et non un "qui claque". A noter qu'on peut jouer sur l'opposition apparence/style (c'est connu les apparences sont parfois trompeuses ^^). Vous pouvez par exemple faire un orc érudit, qui parle de manière normale, voire maniérée et se plaint d'être persécuté par les joueurs et par ses congénères. Bien sûr, ceci doit avoir un but (servir l'histoire, la quête).
3°)Emplacement
Cela peut sembler surprenant, mais l'emplacement d'un NPC peut être important. Honnis soient les "capitales" custom où l'on regroupe tous les NPC en ligne/cercle pour être à porté immédiate de clics des feignasses. C'est tout sauf "réaliste", donc immersif. Comme on peut aisément le constater, chaque ville de RO a une "ambiance". Chose qui est renforcée depuis peu par les quêtes "à histoire" et l'apparition de "factions" (République de Swarchzald, nation d'Azrunamachin, ...). Ajoutons à cela que les "skins" des NPC sont souvent présentés par "lots", typés selon la ville/factions. Donc si vous mettez un guerrier chinois/japonais hors de Louyang/Amatsu, une prêtresse de Freya en dehors de Rachel, il faut qu'il y ait une raison (autre que "le skin est joli").
Ne négligeons pas une autre importance de l'emplacement : la recherche du NPC. RO regorge d'endroits pittoresques/tordus/qu'ils faut faire visiter aux joueurs. La recherche d'un NPC est l'occasion, et apporte une touche de difficulté à la quête. Voire cela peut même devenir l'objet de la quête (npc-event cache-cache, etc).
4°) Comment tu m'causes, toi ! Quand on fait un menu pour "discuter" avec un NPC, la tentation est grande de mettre au moins une option "à la con", qui normalement fâcherait n'importe quelle personne... Or, le plus souvent, il suffit de fermer le dialogue et reparler au NPC pour qu'il oublie complètement vos insinuation sur sa mère... Pas très logique, non. Allez, un peu de code, pour changer. Mettons un NPC en colère : D'abord un petit menu qui renvoie vers une variable... CODE next; menu "Je suis poli...",L_suite,"Ta gueule",L_malpoli;
L_malpoli: set @malpoli, 5; mes "[NPC]"; mes "Et bien, quelle impolitesse !"; mes "^FF0000Dehors !^000000"; close2; percentheal -10,0; warp "payon",100,100; end;
Le NPC se met donc "en colère", frappe(percentheal) et jette (warp) le joueur. Maintenant, voyons comment le faire réagir s'il revient... Un peu de code après la déclaration du NPC : CODE if (@malpoli > 0){ mes "[NPC]"; mes "Encore vous le malpoli !"; next; menu "Pardon, pardon...",-,"Encore une fois, ta gueule!",L_malpoli; set @malpoli, @malpoli - 1; mes "[NPC]"; mes "Hummm... Des excuses...C'est déjà ça... Mais je ne sais pas si je peux vous pardonner..."; close; }
Simple : le joueur devra parler au NPC 5 fois avant de se faire pardonner. Et s'il choisit d'être encore impoli, la variable est remise à fond et il est rebalancé ailleurs. Ce n'est bien sûr qu'un exemple "basique". On peut imaginez des "miniquêtes" pour regagner les faveurs d'un NPC "fâché" (ramener un item, lui dire une phrase particulière, ect). Dans ce cas, mieux vaut employer une variable joueurs (sans le @). Le NPC restera alors "en colère" jusqu'à la résolution de la miniquête.
| |
| | | Valkyrion
Nombre de messages : 143 Age : 30 Affectation : [Admin] Date d'inscription : 03/08/2009
| Sujet: Re: [Tuto] Allez plus loin dans le codage Sam 8 Aoû - 18:08 | |
| IV - Items
Tiens, une section entière pour les items ? Mais, mais... Pourquoi ?
Ne nous leurrons pas, dans RO, la majorité des quêtes consistent à ramener entre beaucoup et énormément d'items (ou un peu moins, mais des rares). C'est assez basique/classique en MMORPG, voire en JdR. Ce n'est donc pas négligeable et on va donc s'y attarder un peu.
1°)Tenez, voici ma liste de courses... Toujours dans notre soucis "d'immersion", il faut que quand un NPC demande une liste d'item, ceux-ci soient "réalistes". Il doivent avoir un rapport avec la quête/l'item à obtenir. Quelques exemples seront plus parlant : Supposons que vous réalisiez une quête pour faire le Neko Mimi Hat. Cette quête est en 2 étapes : réparer la machine à coudre d'une couturière, puis lui apporter de quoi faire le hat.
Etape 1 : réparer la machine à coudre. Machine à coudre... Faut donc des items en rapport avec les machines ou la couture. On database/google et on peut ainsi trouver : Broken Needle, Needle Packet, Spool pour le coté couture, un peu de Steel pour réparer, voire de Solid Iron Piece. Puis on a décidé de faire une quête dure car le hat est mignon : Fragment , Cogwheel.
Etape 2 : fabriquer le hat. Le chapeau est vaguement orangé, mignon, représentant un chat, surement en fourrure. Soyons astucieux, de quoi aurait besoin une couturière pour fabriquer ça ? Imagination/Database : Orange Dyestuff, Cat's Eye, Kitty Band et de la Sea-Otter Fur.
Spécial vicieux : Rien ne vous oblige à demander un nombre explicite d'item. Ni en anglais (on est en francophonie, que diable !). Vous pouvez être vague (ex :"Une dizaine de pommes devraient suffire..."), voire obliger le joueur à chercher (par exemple : "Pour ma tarte aux pommes, il me faudrait des pommes et du miel". Et ailleurs, dans un NPC-livre ou objet-livre de cuisine (voir le tuto sur les books ^^) : "Recette tarte au pomme&miel : 10 pommes, 2 Miel"). Vous pouvez aussi parler par énigme (ex: "Un main d'épice rouge dans la main du Bouddha" => Apporter 5 Red Spice au NPC devant la statue...).
Et voilà, par la simple logique et par l'imagination, on a une liste d'items qui "collent" à la quête et à sa récompense.
Effet bonus : pensez à utiliser des items qui "font voyager" (monstres obscurs de donjons/fields peu fréquentés). Cela permet de faire découvrir des maps à vos joueurs et de les sortir de leur train-train mobtrain.
2°) Combien j'vous en mets ?
Bon, on a la liste d'item qui va bien pour faire la quête. Maintenant il faut doser la difficulté (voir II.2). C'est à qu'à l'inverse d'un Administrateur (voir le topic idoine ^^), un Scripteur doit avoir un perso joueur et bien connaître son serveur. Afin d'estimer la difficulté d'obtenir certains items. Doser le nombre d'item est difficile. Le "camping" n'est pas quelque-chose de rigolo, mais c'est un mur assez efficace. Evitez de trop en faire. Méfiez-vous de ce qui est achetable à quelque obscur marchand NPC. Vous devrez bien évidemment adapté ce qui est demandé aux rates/difficulté du serveurs. Une fois vos quantités choisies... rajoutez-en un peu ^^. On a toujours tendance à sous-estimer les no-life !
Attention : songez aux mage-class et autre lavettes avec str = 1 ! Méfiez-vous du poids de certains items ! Lors du test de la quête, effectuez-là en mage-classe no str. Si les items requis dépasse le poids max que peut porter un joueurs, faîtes-les rapporter en plusieurs fois.
3°) Controle Evidemment, il faut contrôler que le joueurs a rapporté les items. Y'a plusieurs méthodes : CODE if (countitem(502)<10)||(countitem(518)<2){ goto L_PasAssez; } else{ delitem 502,10; delitem 518,2 set tarte, 2; mes "Ah, vous avez tout ce qu'il faut pour faire une tarte au pomme !"; next; L_recompense: mes "Tenez, votre tarte au pomme..."; getitem 66666, 1; set tarte, 3; close; }
L_PasAssez: mes "Désolé, vous n'avez pas ce que j'ai demandé"; close;
On peut aussi faire comme ça : CODE if (countitem(502)>=10)&&(countitem(518)>=2){ delitem 502,10; delitem 518,2 set tarte, 2; mes "Ah, vous avez tout ce qu'il faut pour faire une tarte au pomme !"; next; L_recompense: mes "Tenez, votre tarte au pomme..."; getitem 66666, 1; set tarte, 3; close;
} else{ goto L_PasAssez; }
L_PasAssez: mes "Désolé, vous n'avez pas ce que j'ai demandé"; close;
Personnellement je préfère la première méthode, mais les deux fonctionnent. Pourquoi une variable set et un label "L_recompense:" après l'effacement des items ? Juste pour les malheureux qui déconnecte au mauvais moment (ça arrive, parfois volontairement). Cela permet de renvoyer à la récompense les gens ayant rapporté les item (variable à 2 ici), mais pas reçu l'item. Cela peut être utile si vous placer un NPC dans un endroit "qui craint" (joueur mourant durant les dialogues).
Jamais, jamais, par contre : CODE if (countitem(502)<10)||(countitem(518)<2){ goto L_PasAssez; } else{ set tarte, 2; mes "Ah, vous avez tout ce qu'il faut pour faire une tarte au pomme !"; next; delitem 502,10; delitem 518,2 L_recompense: mes "Tenez, votre tarte au pomme..."; getitem 66666, 1; set tarte, 3; close; }
Ne jamais set de variable avant un next. Dans cet exemple, si on déconnecte à la phrase "Ah, vous avez tout ce qu'il faut pour faire une tarte au pomme !", on aura la variable à 2, donc on sera renvoyer aux récompenses sans se faire deleter les items.
4°) Encore vous !?!
Il est toujours sympathique de prévoir un "rappel" des éléments à fournir (tout le monde n'as pas la mémoire pour se souvenir de douzaine de listes d'objets réclamés par les NPC). CODE L_ingredient: mes "Je pourrais te faire une tarte aux pommes et au miel, si tu me rapportes une dizaine de pommes et deux pots de miel..."; next; ... ... L_PasAssez: mes "Désolé, vous n'avez pas ce que j'ai demandé..."; next; goto L_ingredient;
Cependant,toujours pour plus de réalisme, les NPC pourraient se "fâcher" (voir III.4) si les joueurs reviennent sans cesse leur demander la liste des items.^^ Soyez cruel !
| |
| | | Valkyrion
Nombre de messages : 143 Age : 30 Affectation : [Admin] Date d'inscription : 03/08/2009
| Sujet: Re: [Tuto] Allez plus loin dans le codage Sam 8 Aoû - 18:08 | |
| V - Textes, énigmes et effets spéciaux.
Bon, j'ai déjà parlé du "ton" du NPC et tout ça. Là on va voir comment "décorer".
1°) Voir la vie en rose
Classique, efficace : la couleur. CODE mes "^FF0000Attention !^000000"; mes "Pour ceux qui aime cliquer comme un ^FF0000bourrin^000000 sur ^CCCCCCnext^000000, vous pouvez ^0000FFcolorer les informations essentielles^000000!"; next;
La couleur peut être utiliser pour différentes choses : - Faire ressortir les informations vitales (liste d'item, phrase à retenir, code...). L'exemple ci-dessus est mauvais : il y a trop de couleurs en même temps ^^. - Renforcer un ton ou montrer une manière de s'exprimer particulière (bleu = glacial, rouge = colère, rose = fillette, couleur passée/très claire = chuchotement, ect). - Marquer un dialogue entre différents interlocuteurs: CODE mes "[Boulet]"; mes "Eh ! Salut mon vieux !"; next; mes "^0000CC["+strcharinfo(0)+"]"; mes "* Oh Non !*"; mes "* Encore ce pot de colle... Comment l'éviter ?*^000000"; next; mes "^0000FF["+strcharinfo(0)+"]"; mes "Je...Je dois y aller. Y'a WoE, tout ça !^000000"; next;
Là, on colore les "pensées" du joueur (j'ajoute un caractère * devant les pensées. Chacun à son truc pour ça, y'en a qui mette rien, d'autre ~, etc), puis ses "paroles". Attention de ne pas abuser des couleurs, sinon ça fait "sapin de Noël".
2°) Typographie
Tiens, quel est la différence entre : CODE mes "Vous trouverez le Vieux Sage sur la Montagne au sommet du Pic de Moljnir. Attention aux araignées géantes et aux insectes piqueurs !";
et CODE mes "Vous trouverez le Vieux Sage sur la Montagne au sommet du Pic de Moljnir."; mes "Attention aux araignées géantes et aux insectes piqueurs !";
C'est simple : un second "mes" force un retour à la ligne. Normalement, il n'y en a pas besoin, le retour à la ligne se fait de manière automatique (méfiez des retour à la ligne impromptu d'éléments typographies isolés : !,?,: ect) Forcer un retour à la ligne peut être utile pour mettre en relief une phrase ou une partie de celle-ci. N'oubliez pas de bien "aérer" vos textes en découpant avec "next;".
3°) Regardez-moi dans les yeux. Il est toujours plus sympa de savoir à quoi ressemble celui à qui on s'adresse. On a déjà le sprite, mais on peut faire mieux : mettre un portrait en pied, un cutin ! Bon, y'a déjà un tuto là : http://www.roeathena.fr/index.php?showtopic=311 Je vais donc pas y revenir dessus. La chose à ne pas oublier : "fermer" le cutin avec : CODE ... close2; cutin "",255; end;
4°) Variables de personnalisations
Un titre barbare, hein ?
Ne vous affolez, pas, c'est juste une liste (non-exhaustive) des p'tits bouts de code qui peuvent être utile pour rendre les dialogue plus vivants, plus personnels. C'est parti !
Classique : afficher le nom du joueur : CODE mes "Vous voilà de retour, "+strcharinfo(0)+" ?";
Notez la syntaxe, avec les + et le fait de "sortir" des guillemets du mes. Notez également que ça fonctionne pour pas mal de chose : CODE mes "Quel est ton nom ?"; next; input @ton_nom$ if (@ton_nom$ != strcharinfo(0)){ announce "La honte, "+strcharinfo(0)+" ne connait même pas son propre nom !",bc_all,0xFFFF00; atcommand "@jail "+strcharinfo(0); }
Ses informations personnelles... CODE mes "Vous êtes "+strcharinfo(0)+", le ^FF0000"+jobname(Class)+"^000000."; mes "Actuellement, vous êtes de niveau ^FF0000"+BaseLevel+"/"+JobLevel+"^000000. Vous passerez de niveau dans "+NextBaseExp+" exp."; if (Hp < MaxHp){mes "Et vous oser vous présenter devant nous blessé !";}
Vous trouverez la liste des variables prédéfinis pour les joueurs dans doc/script_commands.txt et surtout dans db/const.txt Notez l'amusante fonction jobname() qui retourne le nom du job (en théorie : je ne m'en suis jamais servi ^^).
Ses amis... CODE set @id_character, getcharid(0); set @id_guilde, getcharid(2); set @id_groupe, getcharid(1); getpartymember(@id_groupe); set @partymembercount,$@partymembercount; copyarray @partymembername$[0],$@partymembername$[0],@partymembercount; if (@partymembercount > 1){ mes "Et voilà "+strcharinfo(0)+", membre de la célébre compagnie d'aventuriers connue sous le nom de "+getpartyname(@id_groupe); mes "Il partage ce privilège avec "+@partymembercount+" aventuriers :"; for( set @i,0; @i<=@partymembercount; set @i,@i+1 ){ switch(Sex){ case 0: mes "La vaillante ^FF66FF"+@partymembername$[@i]+"^000000."; break; case 1: mes "Le brave ^0000FF"+@partymembername$[@i]+"^000000."; break; } } if (getpartyleader(@id_groupe,2) == @id_character){ mes "Dont il est d'ailleurs actuellement le chef."; } if (@id_guilde != 0){ set @guildmaster$, getguildmaster(@id_guilde); if (@guildmaster$ == strcharinfo(0)){ mes strcharinfo(0)+" est d'ailleurs le Maître de la prestigieuse Guilde ^FF0000"+getguildname(@id_guilde)+"^000000."; } else{ mes strcharinfo(0)+" est d'ailleurs le membre de la prestigieuse Guilde ^FF0000"+getguildname(@id_guilde)+"^000000."; } }
} else{ mes "Pas trop solitaire ?"; }
Sympathique, non, l'oeil qui voit tout ? (Note : j'ai fait ce script "à main levée", pour l'exemple, à vérifier s'il marche vraiment...). Notez le @partymembercount > 1 (car on peut être seul dans un groupe...).
Je pense que vous avez piger le truc, je vous épargne "Sa famille" (facile, jetez un oeil aux fonctions getpartnerid(), getchildid(), getmotherid() et getfatherid() ).
5°) Enigmes.
Tiens, pourquoi énigmes dans ce paragraphe ? Et bien parce que c'est du texte, donc elles doivent être bien présentés. D'abord, le joueur est un feignasse inattentif qui clique sur next trop vite : mettez votre énigme en couleurs. Mettez là généralement seule dans un "bloc de texte" (entre deux next; quoi). Un petit exemple : CODE mes "[Père Fouras]"; mes "Voici maintenant mon énigme, qui vous permettra d'entrer par la porte de service qui amène directement en bas de Thanatos Tower..."; next; L_enigme: mes "[Père Fouras]"; mes "^0000CCJe suis toujours à l'abris et pourtant toujours mouillée.^000000"; mes "^0000CCQue suis-je ?^000000"; next; input @reponse$; if ((@reponse$ == "langue")||(@reponse$ == "Langue")||(@reponse$ == "la langue")||(@reponse$ == "La langue")||(@reponse$ == "LANGUE")||(@reponse$ == "LA LANGUE")){ mes "[Père Fouras]"; mes "Vous avez bien répondu..."; goto L_lasuite; } else{ mes "[Père Fouras]"; mes "Hélas, ce n'est pas cela..."; mes "Souhaitez-vous ré-écouter mon énigme ?"; next; menu "Oui.",L_enigme,"Non,-; } close;
Rien de bien compliqué et une énigme textuelle fait toujours plaisir. Notez le principal problème des énigmes textuelles : la multiplicité possible des "bonnes réponses". Dans l'exemple, j'ai mis avec et sans article, en majuscule ou non (pour les gens qui ont la manie de bloquer capslock). Notons qu'une réponse "La Langue" est considérée comme fausse, mais bon, faut pas pousser mémé dans les orties...
A noter également les 2 types d'input : ne vous trompez pas entre les input de texte (input @texte$ et de chiffres (input @chiffre;). Un seul $ d'oublié et vos tests ne marcheront pas...
6°) Son et Lumière !
Il est toujours amusant de pouvoir déclencher quelques "effets spéciaux" lors d'une quête, de pouvoir faire jouer un son ou "simuler" le lancement d'un skill. Voici quelques exemples de commandes permettant cela : CODE specialeffect 90;
Voilà un bel effet (visuel, on ne subit rien). Regardez dans les quêtes de Veins pour un exemple (un percentheal permet de blesser le joueur pour plus de réalisme ^^). Cet "effet" est centré sur le NPC. Pour en faire un centré sur le joueurs, il faut utiliser specialeffect2. Vous pouvez également utiliser misceffect, qui peut selon le cas être centré sur le NPC ou sur le joueur. La liste des effets est disponible dans /doc/effect_list.txt
Un autre truc sympa, c'est de faire lancer des skills. Un Prêtre de Freya pourrait vous bénir et vous soigner, par exemple. CODE skilleffect 28,2000; // Visuel de Heal, en montrant le 2000 vert flottant, comme un vrai heal 2000,0; // Effet de Heal skilleffect 34,0; // visuel de Bless sc_start 10,240000,10; // Effet de Bless level 10
Ouais, c'est la honte, c'est qu'un copier-coller de la doc ^^ On peut également centrer le visuel sur la map plutôt que sur le joueurs avec npcskilleffect. Pratique si vous voulez montrer des "scènes" (genre un Meteor Storm qui s'abat sur un pont, l'apparition d'un démon avec son&lumière...) La liste des différents skill est dans /db/skill_db.txt Attention avec skilleffect : ce n'est que le visuel du skill, pas son effet. Celui-ci peut être généralement "reproduit" avec sc_start (voir db/const.txt pour la liste des effets/status) ou d'autres commandes.
Pour les sons 2 possibilité : - Pour jouer un son pour le joueur uniquement : CODE soundeffect "nomduson",0;
Le fichier son doit être au format .wav et se place dans /data/wav/
Plus rigolo, un effet de zone pour que tout le monde profite du concert de métal : CODE soundeffectall "mon_concert",0,"prontera",100,100,120,120;
Voilà, ça jouera le son dans un carré de la map de prontera (coordonnée au pif pour l'exemple).
Et pour qu'un NPC utilise une emoticon (un smiley), on utilise: CODE mes "Bisou !"; emotion 3,0;
Le premier chiffre est le code de l'emoticon (voir dans /db/const.txt c'est les truc commençant par e_ ). Le second chiffre est la cible : 0 pour le NPC, 1 pour le joueur.
| |
| | | Valkyrion
Nombre de messages : 143 Age : 30 Affectation : [Admin] Date d'inscription : 03/08/2009
| Sujet: Re: [Tuto] Allez plus loin dans le codage Sam 8 Aoû - 18:09 | |
| VI-) Derrière le paravent du MJ...
1°) Tu me vois ? Tu me vois plus !
Voilà, vous avez créer votre quête/votre event/vos NPC. Vous pensez que tout va bien. Vous pensez avoir tout testé. Il est grand temps de passer en production, comme on dit dans l'milieu. Et comment allez-vous faire ça ? Update et relance du serveur, rien de plus facile me direz-vous (au pire, c'est l'Admin qui le fait ^^). Mais ne serez-t-il pas mieux de pouvoir contrôler à volonté l'activation/désactivation de votre quête/votre event/vos NPC. C'est particulièrement utile pour lancer un event à une date désirée et éviter trop de reboot serveur (1 maintenance par semaine pour charger les scripts et un activation ingame quand on en a besoin).
Voilà comment je procède. C'est du pur facultatif. Dans un de mes NPC (normalement actif), je balance un petit paragraphe OnInit qui désactive tous mes NPC si une variable serveur n'est pas à 1. CODE OnInit: if ($my_event17 == 0){ disablenpc "Mon_NPC01"; disablenpc "Mon_NPC02"; ... disablenpc "Mon_NPC35"; } end;
Donc, en cas de reboot serveur (pour update/maintenance), mon script est loadé puis pouf, mes NPC sont désactivés. Pour les activer, j'utilise un NPC "GM" qui contrôle les quêtes et les events custom du serveur. Il est donc placé sur une map GM et n'est utilisable que par les GM ayant un certain niveau. Voici un petit exemple : CODE L_choix: if (getgmlevel()>50){ mes "Maître, que souhaitez-vous faire ?"; next; menu "Controle de l'event n°1",L_e1,"Controle de la quête n°2",L_e2,"Controle de l'event n°17",Le17,"Rien",-; mes "Au revoir alors"; close;
L_e17: mes "Que voulez faire à propos de l'event n°17"; next; menu "Activer event n°17",L_e17a,"Désactiver event n°17",L_e17d,"Rien",-; goto L_choix;
L_e17a: set $my_event17, 1; enablenpc "Mon_NPC01"; enablenpc "Mon_NPC01"; ... enablenpc "Mon_NPC35"; mes "Event n°17 activé !"; next; goto L_choix;
L_e17d: set $my_event17, 0; disablenpc "Mon_NPC01"; disablenpc "Mon_NPC02"; ... disablenpc "Mon_NPC35"; mes "Event n°17 désactivé !"; next; goto L_choix; } else{ mes "Du balais, manant !"; close; }
Voilà, comme ça, on peut "lancer" un event ou un quête depuis le jeu (si bien évidemment ça a été chargé au préalable ^^). La variable permet de laisser la quête active même en cas de reboot.
Note : rien n'empêche de mettre le OnInit dans ce NPC "de contrôle". Mettez des commentaires pour vous y retrouver dans les event/quêtes/npc à désactiver/activer.
2°) Halte ! Contrôle !
Voilà, inspirer par ce guide et plein de fougue, vous avez réaliser une méga-quête, 500ko, 200 variables diverses, The Sign à coté c'est de la gnognotte. Et paf ! Lors du test sur le serveur-test, ça merdoie quelque-part... Mais où ? Le "chargement" (map_server) indique que tout va bien... Pour se mettre sur la piste, rien de tel qu'un petit NPC "contrôlateur de variables". Le but ? Afficher/Permettre de modifier toutes les variables de la quête. Cela permet de voir(enfin, peut être...) à quelle étape ça "coince". Et de s'éviter des requêtes SQL/fouiller les txt pour vérifier les variables. Bref, une petite aide sympathique et pour flemmards, mais qui ne fera pas de miracle.
Un petit exemple : CODE L_show: mes "Les variables de l'event 17:"; mes "Variable joueur event17 : ^FF0000"+event17+"^000000."; mes "Variable joueur event17_part2 : ^FF0000"+event17_part2+"^000000."; mes "Variable event17_pass$ : ^FF0000"+event17_pass$+"^000000."; mes "Variable server $event17_idwinner : ^FF0000"+$event17_idwinner+"^000000."; mes "Que souhaitez-vous faire ?"; next; menu "RAZ variables",L_raz,"Modifier les variables",L_modif,"Rien",-; mes "Ok, salut alors; close;
L_raz: set event17,0; set event17_part2,0; set event17_pass$, ""; set $event17_idwinner, 0; mes "Les variables ont été remise à zéro"; next; goto L_show;
L_modif: mes "Nouvelle valeur event17 ?"; input @nb; set event17, @nb; next; mes "Nouvelle valeur event17 ?"; input @nb; set event17_part2, @nb; next; mes "Nouvelle valeur event17_pass$ ?"; input @txt$; set event17_pass$, @txt$; next; mes "Nouvelle valeur $event17_idwinner ?"; input @nb; set $event17_idwinner, @nb; goto L_show;
Voilà de quoi tester un peu vos quêtes. ça peut paraître un peu bête ou superflu, mais l'air de rien, à l'usage c'est utile. Un autre truc : comme vous avez le contrôle, vous savez toujours où vous en êtes niveau variable. ça vous permet donc de faire des tests du style : "Il se passe quoi si je reparle au NPC 14 alors que j'en suis à l'étape 27 ?".
VII°) Être sympa avec les collégues
1°) Le "header". Vous l'avez surement remarqué, mais tous les fichiers de /npc/ (ou presque) commence par un "header" composé de commentaires (lignes commençant par // ) C'est pas pour rien. Voyons un peu ça (ce n'est qu'un exemple, mais il est assez standard) : CODE //===== eAthena Script ======================================= //= Script Machin (nom/titre du script) //===== By: ================================================== //= MageGaHell, Myllena (Votre pseudo et ceux des autres contributeurs) //===== Current Version: ===================================== //= 1.4 (La version du script. Perso : j'augmente de 0.1 à change modification mineure et de 1 à chaque modification majeure. J'ajoute un b si le script est en test, que j'enlève une fois le test effectué, avant de passer en prod') //===== Compatible With: ===================================== //= eAthena SVN (la version d'eAthena sur laquelle vous avez testé le script) //===== Description: ========================================= //= Script Machin //= Quête custom pour DoT. Permet d'obtenir un Machin Hat. //= Part 1 : activation multijoueur. Non répétable. //= Part 2 : hat making mono-joueur. Répétable. //= (une description plus ou moins poussé du script, vous l'aurez compris) //= //===== Additional Comments: ================================= //= 1.0 Première version, par MageGaHell //= 1.1 Correction orthographique, par Myllena //= 1.2 Correction faille possible, par MageGaHell //= 1.3 Complexification Part 1. //= 1.4 Dernière modification. Mise en ligne. //============================================================
J'espère que l'exemple est assez clair. Vous pouvez aussi rajouter les lists des variables utilisés (toujours pratique) et une description sommaire de leur rôle. J'ajoute parfois aussi dans mes quêtes, notamment de hat, la liste des items nécessaires. Le but de ce truc est de simplifier la vie de l'admin et des scripteurs qui pourraient être amener à bosser sur/avec vos scripts. Normalement, si vous utilisez une SVN dans votre team, vous aurez pas trop de soucis. Mais le header reste toujours utiles pour savoir qui a fait quoi et pour pallier à d'éventuelle erreurs humaines ("Bordel, mais t'as passé quoi comme version du script !" "La dernière...T'es sur d'avoir commit ?" "...Euh..").
2°) Clear code
Afin de faciliter le travail (éventuel) de correcteurs/scripteurs autres que vous, il est sympathique de rendre ses scripts le plus lisible possible. Pour cela, il est bienvenue de faire 2 choses :
- Commenter : comme vu dans le header, une ligne débutant par // n'est pas exécuté. Mettre des commentaires permet aux autres de savoir ce que fait le script et où. C'est aussi particulièrement utile pour vous si êtes amateurs de if/else et autre switch bien imbriqué... Ne tombez pas non plus dans l'accès à commenter chaque ligne : essayez de commenter des "bloc-logiques" ("ça c'est la partie 1 de la quête", "ça c'est les fonctions", "ici les tests sur les items/variables...") N'en écrivez pas non plus des tartines, ça doit être informatif et bref.
- Organiser. Cela veut dire regrouper les npc/fonction d'un fichier en "bloc-logiques" là aussi (NPC pour la partie 1 de la quête, NPC pour la partie 2, fonctions...). Mais pas seulement : il est aussi bien de produire un code clair et indenté. C'est certes une perte de temps à taper, mais c'est plus facile à lire (pour vous aussi). Exemple : CODE if ((machin01 > 17)||(truc04 < 4)){ switch(machin01){ case 23: if ((truc04 == 1)||(truc04 == 2)){ mes "Et bien, vous êtes bien confus..."; set truc04, truc04 + 1; close; } else{ mes "Pas encore assez ?"; close; } case 25: if ((truc04 == 2)||(truc04 == 3)){ mes "Mais où en sommes-nous ?"; set truc04, truc04 + 1; close; } else{ mes "Est bien clair ?"; close; } default: if ((truc04 == 1)||(truc04 == 2)){ mes "Seriez vous un peu perdu ?"; set truc04, truc04 + 1; if (machin01 > 25){ set machin01, machin01 - 1; } close; } else{ mes "Pas encore assez ?"; close; } } } else{ if (truc04 == 5){ mes "Mouaip, là ça va ?"; close; } }
Vous préférez pas ça ? CODE if ((machin01 > 17)||(truc04 < 4)){ switch(machin01){ case 23: if ((truc04 == 1)||(truc04 == 2)){ mes "Et bien, vous êtes bien confus..."; set truc04, truc04 + 1; close; } else{ mes "Pas encore assez ?"; close; } case 25: if ((truc04 == 2)||(truc04 == 3)){ mes "Mais où en sommes-nous ?"; set truc04, truc04 + 1; close; } else{ mes "Est bien clair ?"; close; } default: if ((truc04 == 1)||(truc04 == 2)){ mes "Seriez vous un peu perdu ?"; set truc04, truc04 + 1; if (machin01 > 25){ set machin01, machin01 - 1; } close; } else{ mes "Pas encore assez ?"; close; } } } else{ if (truc04 == 5){ mes "Mouaip, là ça va ?"; close; } }
ça fait plus "pro", non ? Jeu interactif : dans mon premier exemple, me suis-je merdé dans l'ouverture/fermeture de parenthèse/accolades. Jeu interactif 2 : si machin01 vaut 22 et truc04 vaut 3, que m'affichera le script ? Et quelles seront les valeurs de machin01 et truc04 au final dans ce cas ?
VIII-) Conclusion
Voilà, vous pouvez scripter les npc et votre quête, une vraie, une originale et intéressante. Vous avez du piger le principe : cohérence, réalisme, suprise, envoutement du joueur !^^ Vous trouverez les trucs "utiles", plus mécanique dans /doc/script_commands.txt et /doc/pccommand_list.txt Méfiez-vous en tout de même ! C'est pas graver dans le marbre et tout peu changer. Donc tester, tester, tester. Mettez-vous dans la peau d'un joueurs vicieux. Testez votre quête avec des classes "à la con" qui ont des limitations (Wizard sans force, TK sans arme, ect) et testez sans item/commandes GM (bon, je vous autorise @item). Connaissez votre serveur et vos joueurs.
Enfin, venez pas ouinouiner si un des exemples que je cite plante. Je ne les ai pas tous tester, et ce n'est que des exemples. On est dans un tuto pour vous faire comprendre l'importance des lettres RPG de MMORPG, pas dans un tuto "technique".
En espérant que cela vous soit utile. | |
| | | Contenu sponsorisé
| Sujet: Re: [Tuto] Allez plus loin dans le codage | |
| |
| | | | [Tuto] Allez plus loin dans le codage | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |
|