Aide et informations diverses sur Neverwinter Nights ainsi que D&D3.
S'enregistrer Se connecter pour vérifier ses messages privés Connexion
Voir le sujet précédent ¤ Voir le sujet suivant | |
---|---|
Auteur | Message |
Baldurien L'homme qui chutait sur le macadam Messages: 14066 Localisation: Quadran Alpha |
Suite à un message que j'ai écris (tant bien que mal) sur les forums Bioware - après l'avoir perdu suite à une mauvaise manip, et après avoir été copieusement *emmerdé* par les BioBoard pour des URL trop longues (...)), je m'interroge sur les évolutions du NWScript que vous - scripteurs - aimeriez voir? Parmi ces évolutions (que j'aimerai voir), on peut trouver les tableaux, une réelle classification des objets, une syntaxe objet, de la javadoc, des itérateurs, une fonction de debug (print), et des événements ne faisant pas nécessairement appel à une fonction main situé dans un script. Pour ce qui est d'ajouter votre missing list (liste des trucs qui manquent) je vous renvoie aux commentaires de nouvelle, où en vous trouverez les descriptions de ma missing list. _________________ #nwnights-fr @ irc.darkmyst.org TitanQuest-FR |
Revenir en haut | |
Baldurien L'homme qui chutait sur le macadam Messages: 14066 Localisation: Quadran Alpha |
Commençons par la classification des objets :
Dans NWN, on a plusieurs types d'objets, à savoir (liste non exhaustive) : Module Area (zone) Creature Placeable Waypoint Camera Player On peut classer ces objets tels que : Module - Contient des Area - Contient des PlaceableObject : Creature, Placeable, Waypoint Area - Contient des PlaceableObject (le nom n'est pas très bon étant donné les objets Placeable) Waypoint Placeable Dans NWN, on n'a affaire qu'à un seul type d'objet pour désigner plein de choses différentes. Pourquoi ne pas justement créer des types spécifiques permettant de rendre moins ambiguüe les choses? Puis la syntaxe objets : Vous manipulez les structures (struct {}) du jeu par l'opérateur '.'. La syntaxe objet, c'est pareil ! Donc, par exemple, on aurait area.addCreature(Creature c) qui nous permettrait d'ajouter une créature dans une zone. Simple non? Avec cette syntaxe, ce qu'il faut c'est des setters et getters. Il y a près de 1000 fonctions de base qui font tout et n'importe quoi. Y a une fonction pour chopper une carac, et y a 6 caracs : donc *pouf* on a 6 constantes, et une fonction, que l'on applique sur un objet qui doit être une créature. Mais attendez là ??? Qu'est ce qui m'affirme qu'un objet est une créature? Moi? ah oui... Mais c'est pas à moi de gérer ça : c'est au compilateur de me dire tu t'es trompé! Rien que la syntaxe objet permettrait de réduire de beaucoup les écritures et rendrait beaucoup plus clair le code. Un exemple? Prenez un script actuel et transformez le avec la syntaxe objet. -> en sus, il faut des setter (définisseurs) et des getters (accesseurs). Ex tout bête: Code : Creature c = getCreature(1);
c.charisma = 3; print c.charisma; Ce qui est beau ici, c'est que derrière le compilateur va réécrire le code tel que : Code : setCharisma(c, 3);
print getCharisma(c); Mais au final pas besoin d'appeler une fonction, le compilateur se démerdra tout seul (c'est un peu le but : on jette toutes les lourdeurs sur le compilateur) Bien sûr, pour déplacer un objet d'un point de là où il est vers un autre point, ça fonctionnerait comme ça : c.moveTo(waypointQuelconque); (noter que je ne met pas wp, ou un quelconque préfixe aux noms de variable, c'est lourd.) Tableaux Trop utile pour être oublié! Un tableau c'est quoi? C'est un ensemble contigu et fini d'éléments de même type. Un exemple tout bête : Code : Waypoint[][] chess = new Waypoint[10][10];
Crée une matrice de Waypoint de 10x10 permettant par exemple de représenter un jeu d'échec. C'est un exemple mal fait, mais c'est l'idée. Ce qui est merveilleux? Hé bien : vous pouvez itérer là dessus ! Et pouf : Code : for ( i = 0; i < chess.length; i++ )
for ( j = 0; j < chess[i].length; j++ ) print chess[i][j]; Si vous ne voyez pas d'applications, je suis sûr que d'autres vous en trouveront. Et maintenant, le fin du fin : pourquoi pas des Map? Les Map c'est un objet de base des langages orientés objets. Ils permettent d'associer à une clef une valeur. Exemple tout bête : vous voulez associer à une liste de créatures, une série de Waypoint. Code : Map<Creature, Waypoint> m = new Map<Creature, Waypoint>();
m.put(c1, w1); ... m.put(cN, wN); Et si vous voulez trouver le waypoint de destination associé à la créature, il vous suffit de faire un simple : Code : m.get(c1)
Et inclure les Map étant lourd, je propose de faire ça : Waypoint[Creature] Signifiant que les Waypoint sont indexés par des Creature plutôt que par des entiers. Et mieux encore : ce tableau est extensible. Quand y a plus de place, y a de la place! (ie: si jamais on ajoute un élément et que le tableau est pas assez grand, on le ragrandit). Ce qui implique les itérateurs Etant donné ces maps, comment bien parcourir ces tableaux spéciaux dont on peut pas deviner les clefs? Réponse : avec foreach. Ex: Code : /**
* parcours d'un tableau de créature indexé par des entiers * mieux: si jamais c'est une liste d'élément (un objet * interne au jeu par exemple), on peut la parcourir ainsi * de manière [b]transparente[/b] */ foreach ( Creature c in tableauDeCreature ) ; /** * Idem, en déclarant implicitement deux variables c et p */ foreach ( tableauDeCreature as c => p ) ; c contient ici la créature (qui joue le rôle de clef), et p la position (qui joue le rôle de valeur). Y a cependant un autre truc chiant dans NWN : Code : object o = getFirstObjectInArea();
while ( getIsValidObject(o) ) { destroyObject(o); o = getNextObjectInArea(); } Ce code parcourt tous les objets de la zone (et on connaît pas leur type, yahoo) et les détruit. Ca ça marche, c'est génial hein. Mais ajoutez donc des objets et vous obtiendrez une boucle infinie. C'est normal : NWN utilise une liste d'objets, et ajoute les objets en fin de la liste. Une solution consisterai à ajouter les objets en début de liste, mais hélas : cela implique d'utiliser une liste chaînée (ajout au début de liste en temps constant) tandis qu'ajouter en fin permet d'avoir une liste d'objets utilisant un tableau de références. Bien optimisé, ça peut être mieux que la liste d'objet, mais l'ajout au début est plus long car il faut décaler tous les autres objets. Donc on ajoute en fin. Donc on ne finit jamais la boucle puisque getNextObjectInArea renvoie toujours un objet. La boucle s'arrête que quand le jeu a bien planté. A ça, je propose les itérateurs comme en Java (ceci dit c'est un design pattern de base). Code : for ( Iterator it = area.iterator(); it.hasNext(); ) {
PlaceableObject o = it.next(); if ( o isa Placeable ) o.remove(); } Ce que ça fait? Ca crée un objet Iterator en demandant à area de le créer, puis ça parcourt les éléments de la zone en nous assurant que la boucle soit fini (eg: une copie locale avec un champ indiquant le dernier élément de la liste d'objet de la zone). Comme un zone contient différents types d'objets, on doit d'abord vérifier si l'objet n'est pas un Placeable pour le supprimer (c'est mon exemple). Ici : it.hasNext() renvoie vrai ou faux si on a fini d'itérer it.next() renvoie l'objet courant et avance le pointeur interne (équivalent du getNext de tantôt) it.remove() détruit l'objet courant avant l'appel de next() C'est puissant, c'est magnifique! Et mieux, puisqu'à priori on ne voudra pas tout le temps supprimer un objet, on peut même oser ça : Code : foreach ( PlaceableObject o in area )
; Ca permet d'éviter d'écrire des choses trop longues, etc. Mais un autre truc qui manque, c'est de quoi afficher facilement du texte dans la console, et puis faire des IntToStr(i) ça reste agaçant quant on sait que "a" + 6 en Java ne nécessite pas de faire "a" + IntToStr(6). Je propose une nouvelle instruction : print. Elle peut être désactivé si le mode debug est désactivé, et elle ne fait qu'afficher du texte dans la console. ex: Code : Creature c = getCreature();
print 3, "3", c; // affiche le nombre 3, la chaîne 3, et la créature (oui!) On peut transformer en chaîne un objet, c'est à dire obtenir quelque chose de plus lisible qu'un tag. Le print a pour seul avantage d'afficher dans la console le texte. Pas besoin de faire un AssignAction(talkTo(...)). Et puis tiens, OBJECT_SELF, OBJECT_INVALID, TRUE et FALSE sont pas terribles... Je propose de renommer OBJECT_SELF en self, qui est de type Object (ça dépend le contexte). Faire Creature c = self devrait provoquer une erreur si c n'est pas une créature. Une erreur sévère finissant directement le script et affichant dans la console la fonction qui a provoqué l'erreur. OBJECT_SELF est par contre moche : on vous a dit que les constantes devait être en majuscules... oui mais OBJECT_SELF c'est pas une constante. OBJECT_INVALID est une constante, mais null serait plus approprié. null pour dire "y pas d'objets ici, il existe pas". Et enfin TRUE et FALSE sont mis en vert dans l'éditeur de script. Pourquoi? Parce qu'ils sont pris en compte comme des mots clefs, pas des constantes. Ils méritent donc d'être écrit en minuscule : true et false. Pour presque finir, les événements Les événements c'est bien, mais c'est un fichier par événement. Vous trouvez pas ça lourd vous? Ce que je veux c'est pouvoir choisir la fonction qui va gérer l'événement et ne pas avoir 10 fichiers pour une créature alors que c'est une créature unique, et que que j'aimerai bien avoir tout ce qui la concerne au même endroit sans m'amuser à nommer les scripts de manière farfelues. Et puis ça serait bien de jarter toutes les méthodes associées aux événements pour utiliser ce que le NWScript connaît : une structure (ou des paramètres) donnant par défaut les objets ayant provoqués l'événements. Genre : areaOnEnter(Creature c); c est entré dans la zone, rien de bien compliqué, non? Et derrière pas de getEnteringObject. Et finalement, les commentaires de fonction/variables Un truc qui est moche dans le NWScript c'est les commentaires de base et surtout la façon dont ils sont écrits : ça utilise les commentaires sur une ligne (//) comme si les commentaires multilignes (/*..*/) n'existaient pas, et pire : les gens font souvent de l'ASCII Art pensant qu'un script doit avoir des images. Ce que je veux, c'est qu'il y ait une vraie syntaxe pour documenter les éléments. Cette syntaxe éxiste déjà : c'est la Javadoc. Comme ça : Code : /**
* Crée X objets * @param x le nombre d'objets à créer * @return retourne false en cas d'erreur (si x < 1, ou x > 5) */ bool creerXObjets(int x); Et pas les commentaires imbiffables : Code : // Crée X objets
// false en cas d'erreur (si x < 1, ou x > 5) bool creerXObjets(int x); Voilà. Bien sûr, c'est normal que je sois chiant sur ce point : j'ai connu d'autres langages que le NWScript, et je sais que ce que je propose va en partie apporter un mieux. (mais encore faut il que les devs répondent autrement que "on n'en a pas besoin" et qu'ils y réfléchissent) _________________ #nwnights-fr @ irc.darkmyst.org TitanQuest-FR |
Revenir en haut | |
Athanor salamander Légende vivante Messages: 306 Localisation: Ecole du Script |
Ce qu'il manque dans le NWscript c'est surtout l'ouverture du controle vers les objects utilisés :
Pour expliquer ce que je veux dire par là on va y aller tout doux : Aujourd'hui dans NWScript pour récupérer une valeur ou en assigner une à un object, le langage t'ouvre des méthodes, du genre Get qqchose et Set machin chose. Elles permettent la manipulation de certaines propriétés, mais ça reste hyper protégé et hyper privé. En fait ça revient un peu au même que ce que tu décris dans ton post Baldurien au niveau technique, mais ce qui serait bien c'est d'avoir un accès aux objects bien plus vaste, à savoir une grosse modification de ceux ci : Monstres : modifier les caracs, les dons, les sorts en direct, modifier leur apparence, leur nom etc... Avoir accès à l'animation en cours également, à son attaque, etc... PC : idem, mais y avoir aussi des événements, pouvoir ajouter des events précis à un joueur. Zones : Avoir accès à sa ResRef. Il faudrait aussi qu'une zone puisse écouter. (Event OnConversation, OnPerceived etc...) Rencontre : Ajouter et supprimer des créatures à l'object rencontre, pouvoir positionner des points de rencontre, et avoir un événement d'avant déclenchement. Plaçable : Leur donner une propriété de déplacement similaire aux créatures, afin de donner des effets aux décors. Aujourd'hui un plaçable est déplaçable mais cette gestion est différence que celle des créatures parce que gérables avec l'axe des Z. Il faudrait également qu'ils puissent être déplaçables de la même façon. Exemple, une maison qui s'enfonce, des éboulis de pierre etc... Qu'ils puissent écouter (pour des mots de passe par exemple) Effects : Gérer les effets intégralement (mis à part les visus) par script. Ainsi au lieu d'un effet directement géré en interne, qu'on puisse avoir directement une librairie de fonction permettant réellement de gérer et d'utiliser l'object Effect. Par ailleurs donner à chaque effet une signature (à savoir, l'effet en cours, qui l'a lancé, depuis quand il est sur cet object, est il néfaste, est il redondant avec un autre effet etc...) : NWScript :Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.
Aujourd'hui la fonction effect existe mais ne sert à rien, sinon à linker linker et linker. En fait, pour finir, mis à part certaines choses qu'il manque énormément au NWScript, très bien expliqués par Baldurien, ce qui handicape le plus ce langage qui est mine de rien assez convivale, c'est la trop haute protection des object qu'il gère, et la simplicité trop gênante de ces mêmes objects. Un plaçable est trop plaçable donc inerte, un effect est trop rigide, un monstre n'est pas assez modellable etc... _________________ Atha, Artisan Scripteur. meet the most beautiful woman in the world |
Revenir en haut | |
Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum